merge.
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
* Drop support of Python 2.5
|
||||
* Remove support of Many2Many field in record XML
|
||||
* Change Pool into a Singleton
|
||||
* Remove support of zipped modules
|
||||
|
||||
Version 2.0.0 - 2011-04-26
|
||||
|
||||
@@ -37,6 +37,8 @@ def parse_commandline():
|
||||
help="file where the server pid will be stored")
|
||||
parser.add_option("--logfile", dest="logfile",
|
||||
help="file where the server log will be stored")
|
||||
parser.add_option("--disable-cron", dest="cron",
|
||||
action="store_false", help="disable cron")
|
||||
|
||||
(opt, _) = parser.parse_args()
|
||||
|
||||
@@ -51,6 +53,7 @@ def parse_commandline():
|
||||
'debug_mode',
|
||||
'pidfile',
|
||||
'logfile',
|
||||
'cron',
|
||||
):
|
||||
if getattr(opt, arg) is not None:
|
||||
options[arg] = getattr(opt, arg)
|
||||
|
||||
@@ -508,7 +508,7 @@ A many-to-many relation field.
|
||||
|
||||
Instance methods:
|
||||
|
||||
.. method:: Many2Many.get_target(pool)
|
||||
.. method:: Many2Many.get_target()
|
||||
|
||||
Return the target :class:`~trytond.model.Model`.
|
||||
|
||||
@@ -530,7 +530,7 @@ A one-to-one relation field.
|
||||
|
||||
Instance methods:
|
||||
|
||||
.. method:: One2One.get_target(pool)
|
||||
.. method:: One2One.get_target()
|
||||
|
||||
Return the target :class:`~trytond.model.Model`.
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ How to install Tryton
|
||||
Prerequisites
|
||||
=============
|
||||
|
||||
* Python 2.5 or later (http://www.python.org/)
|
||||
* Python 2.6 or later (http://www.python.org/)
|
||||
* lxml 2.0 or later (http://codespeak.net/lxml/)
|
||||
* relatorio 0.2.0 or later (http://relatorio.openhex.org/)
|
||||
* python-dateutil (http://labix.org/python-dateutil)
|
||||
|
||||
@@ -61,7 +61,7 @@ When defining an `ir.action.report` the following attributes are available:
|
||||
* ``name``: The name of the report.
|
||||
|
||||
* ``report_name``: The name of the report model, for example
|
||||
my_module.my_report. This is the name you would use with `pool.get`
|
||||
my_module.my_report. This is the name you would use with `Pool().get`
|
||||
|
||||
* ``module_name``: If this report is of an existing model this is its name.
|
||||
For example my_module.my_model. Custom reports that aren't of a specific
|
||||
@@ -228,7 +228,7 @@ context. Now the invoice report will be able to access the employee object.
|
||||
class InvoiceReport(Report):
|
||||
_name = 'account.invoice'
|
||||
def parse(self, report, objects, datas, localcontext):
|
||||
employee_obj = self.pool.get('company.employee')
|
||||
employee_obj = Pool().get('company.employee')
|
||||
employee = False
|
||||
if Transaction().context.get('employee'):
|
||||
employee = employee_obj.browse(Transaction().context['employee'])
|
||||
|
||||
@@ -90,3 +90,6 @@
|
||||
|
||||
# Prevent database listing
|
||||
#prevent_dblist = False
|
||||
|
||||
# Enable cron
|
||||
# cron = True
|
||||
|
||||
@@ -8,10 +8,6 @@ import sys
|
||||
|
||||
execfile(os.path.join('trytond', 'version.py'))
|
||||
|
||||
SIMPLEJSON = []
|
||||
if sys.version_info < (2, 6):
|
||||
SIMPLEJSON = ['simplejson']
|
||||
|
||||
def read(fname):
|
||||
return open(os.path.join(os.path.dirname(__file__), fname)).read()
|
||||
|
||||
@@ -52,7 +48,6 @@ setup(name=PACKAGE,
|
||||
'Natural Language :: Russian',
|
||||
'Natural Language :: Spanish',
|
||||
'Operating System :: OS Independent',
|
||||
'Programming Language :: Python :: 2.5',
|
||||
'Programming Language :: Python :: 2.6',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
'Topic :: Software Development :: Libraries :: Application Frameworks',
|
||||
@@ -63,7 +58,7 @@ setup(name=PACKAGE,
|
||||
'relatorio >= 0.2.0',
|
||||
'Genshi',
|
||||
'python-dateutil',
|
||||
] + SIMPLEJSON,
|
||||
],
|
||||
extras_require={
|
||||
'PostgreSQL': ['psycopg2 >= 2.0'],
|
||||
'MySQL': ['MySQL-python'],
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from trytond.const import CONTEXT_CACHE_SIZE, MODEL_CACHE_SIZE
|
||||
|
||||
DatabaseIntegrityError = None
|
||||
DatabaseOperationalError = None
|
||||
@@ -103,7 +104,8 @@ class CursorInterface(object):
|
||||
IN_MAX = 1000
|
||||
|
||||
def __init__(self):
|
||||
self.cache = {}
|
||||
from trytond.cache import LRUDict
|
||||
self.cache = LRUDict(CONTEXT_CACHE_SIZE)
|
||||
|
||||
def get_cache(self, context=None):
|
||||
'''
|
||||
@@ -112,6 +114,7 @@ class CursorInterface(object):
|
||||
:param context: the context
|
||||
:return: the cache dictionary
|
||||
'''
|
||||
from trytond.cache import LRUDict
|
||||
if context is None:
|
||||
context = {}
|
||||
cache_ctx = context.copy()
|
||||
@@ -119,7 +122,8 @@ class CursorInterface(object):
|
||||
'_delete_records'):
|
||||
if i in cache_ctx:
|
||||
del cache_ctx[i]
|
||||
return self.cache.setdefault(repr(cache_ctx), {})
|
||||
return self.cache.setdefault(repr(cache_ctx),
|
||||
LRUDict(MODEL_CACHE_SIZE))
|
||||
|
||||
def execute(self, sql, params=None):
|
||||
'''
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
from trytond.backend.database import DatabaseInterface, CursorInterface
|
||||
from trytond.config import CONFIG
|
||||
import MySQLdb
|
||||
|
||||
@@ -84,10 +84,10 @@ CREATE TABLE res_group (
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE TABLE `res_user-res_group` (
|
||||
uid BIGINT NOT NULL,
|
||||
gid BIGINT NOT NULL,
|
||||
CONSTRAINT `res_user-res_group_uid_fkey` FOREIGN KEY (uid) REFERENCES res_user (id) ON DELETE CASCADE,
|
||||
CONSTRAINT `res_user-res_group_gid_fkey` FOREIGN KEY (gid) REFERENCES res_group (id) ON DELETE CASCADE
|
||||
`user` BIGINT NOT NULL,
|
||||
`group` BIGINT NOT NULL,
|
||||
CONSTRAINT `res_user-res_group_user_fkey` FOREIGN KEY (`user`) REFERENCES res_user (id) ON DELETE CASCADE,
|
||||
CONSTRAINT `res_user-res_group_group_fkey` FOREIGN KEY (`group`) REFERENCES res_group (id) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE TABLE wkf (
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
from trytond.backend.database import DatabaseInterface, CursorInterface
|
||||
from trytond.config import CONFIG
|
||||
from trytond.session import Session
|
||||
|
||||
@@ -102,10 +102,10 @@ CREATE SEQUENCE "res_user-res_group_id_seq";
|
||||
|
||||
CREATE TABLE "res_user-res_group" (
|
||||
id INTEGER DEFAULT NEXTVAL('res_user-res_group_id_seq') NOT NULL,
|
||||
uid INTEGER NOT NULL,
|
||||
gid INTEGER NOT NULL,
|
||||
FOREIGN KEY (uid) REFERENCES res_user (id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (gid) REFERENCES res_group (id) ON DELETE CASCADE,
|
||||
"user" INTEGER NOT NULL,
|
||||
"group" INTEGER NOT NULL,
|
||||
FOREIGN KEY ("user") REFERENCES res_user (id) ON DELETE CASCADE,
|
||||
FOREIGN KEY ("group") REFERENCES res_group (id) ON DELETE CASCADE,
|
||||
PRIMARY KEY(id)
|
||||
);
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
from trytond.backend.database import DatabaseInterface, CursorInterface
|
||||
from trytond.config import CONFIG
|
||||
from trytond.session import Session
|
||||
@@ -9,6 +8,7 @@ import re
|
||||
from decimal import Decimal
|
||||
import datetime
|
||||
import time
|
||||
import sys
|
||||
|
||||
_FIX_ROWCOUNT = False
|
||||
try:
|
||||
@@ -144,10 +144,9 @@ class Database(DatabaseInterface):
|
||||
return
|
||||
path = os.path.join(CONFIG['data_path'],
|
||||
database_name + '.sqlite')
|
||||
conn = sqlite.connect(path)
|
||||
cursor = conn.cursor()
|
||||
cursor.close()
|
||||
conn.close()
|
||||
with sqlite.connect(path) as conn:
|
||||
cursor = conn.cursor()
|
||||
cursor.close()
|
||||
|
||||
def drop(self, cursor, database_name):
|
||||
if database_name == ':memory:':
|
||||
@@ -358,7 +357,10 @@ class Cursor(CursorInterface):
|
||||
return select
|
||||
|
||||
sqlite.register_converter('NUMERIC', lambda val: Decimal(val))
|
||||
sqlite.register_adapter(Decimal, lambda val: buffer(str(val)))
|
||||
if sys.version_info[0] == 2:
|
||||
sqlite.register_adapter(Decimal, lambda val: buffer(str(val)))
|
||||
else:
|
||||
sqlite.register_adapter(Decimal, lambda val: bytes(str(val)))
|
||||
sqlite.register_adapter(Session, int)
|
||||
def adapt_datetime(val):
|
||||
return val.replace(tzinfo=None).isoformat(" ")
|
||||
|
||||
@@ -73,8 +73,8 @@ CREATE TABLE res_group (
|
||||
|
||||
CREATE TABLE "res_user-res_group" (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
uid INTEGER,
|
||||
gid INTEGER
|
||||
"user" INTEGER,
|
||||
"group" INTEGER
|
||||
);
|
||||
|
||||
CREATE TABLE wkf (
|
||||
|
||||
@@ -127,7 +127,7 @@ class TableHandler(TableHandlerInterface):
|
||||
match = re.match(r'(\w+)(\((.*?)\))?', type_)
|
||||
if match:
|
||||
typname = match.group(1).upper()
|
||||
size = match.group(3) and int(match.group(3)) or None
|
||||
size = match.group(3) and int(match.group(3)) or 0
|
||||
else:
|
||||
typname = type_.upper()
|
||||
size = -1
|
||||
|
||||
@@ -7,6 +7,7 @@ from threading import Lock
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.config import CONFIG
|
||||
from trytond.backend import Database
|
||||
from trytond.tools import OrderedDict
|
||||
|
||||
|
||||
class Cache(object):
|
||||
@@ -167,3 +168,32 @@ class Cache(object):
|
||||
cursor.commit()
|
||||
cursor.close()
|
||||
Cache._resets_lock.release()
|
||||
|
||||
|
||||
class LRUDict(OrderedDict):
|
||||
"""
|
||||
Dictionary with a size limit.
|
||||
If size limit is reached, it will remove the first added items.
|
||||
"""
|
||||
def __init__(self, size_limit, *args, **kwargs):
|
||||
assert size_limit > 0
|
||||
self.size_limit = size_limit
|
||||
super(LRUDict, self).__init__(*args, **kwargs)
|
||||
self._check_size_limit()
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
super(LRUDict, self).__setitem__(key, value)
|
||||
self._check_size_limit()
|
||||
|
||||
def update(self, *args, **kwargs):
|
||||
super(LRUDict, self).update(*args, **kwargs)
|
||||
self._check_size_limit()
|
||||
|
||||
def setdefault(self, key, default=None):
|
||||
default = super(LRUDict, self).setdefault(key, default=default)
|
||||
self._check_size_limit()
|
||||
return default
|
||||
|
||||
def _check_size_limit(self):
|
||||
while len(self) > self.size_limit:
|
||||
self.popitem(last=False)
|
||||
|
||||
+2
-4
@@ -51,6 +51,7 @@ class ConfigManager(object):
|
||||
'prevent_dblist': False,
|
||||
'init': {},
|
||||
'update': {},
|
||||
'cron': True,
|
||||
}
|
||||
self.configfile = None
|
||||
|
||||
@@ -82,12 +83,9 @@ class ConfigManager(object):
|
||||
if not self.configfile:
|
||||
return
|
||||
|
||||
fp = open(self.configfile)
|
||||
parser = ConfigParser.ConfigParser()
|
||||
try:
|
||||
with open(self.configfile) as fp:
|
||||
parser.readfp(fp)
|
||||
finally:
|
||||
fp.close()
|
||||
for (name, value) in parser.items('options'):
|
||||
if value == 'True' or value == 'true':
|
||||
value = True
|
||||
|
||||
@@ -18,4 +18,7 @@ OPERATORS = (
|
||||
'>',
|
||||
)
|
||||
|
||||
CONTEXT_CACHE_SIZE = 10
|
||||
MODEL_CACHE_SIZE = 200
|
||||
RECORD_CACHE_SIZE = 2000
|
||||
BROWSE_FIELD_TRESHOLD = 100
|
||||
|
||||
+7
-40
@@ -1,6 +1,5 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
import time
|
||||
from xml import sax
|
||||
from decimal import Decimal
|
||||
@@ -110,16 +109,7 @@ class MenuitemTagHandler:
|
||||
values['icon'] = 'tryton-new'
|
||||
|
||||
if values.get('groups'):
|
||||
g_names = values['groups'].split(',')
|
||||
groups_value = []
|
||||
for group in g_names:
|
||||
if group.startswith('-'):
|
||||
group_id = self.mh.get_id(group[1:])
|
||||
groups_value.append(('remove', group_id))
|
||||
else:
|
||||
group_id = self.mh.get_id(group)
|
||||
groups_value.append(('add', group_id))
|
||||
values['groups'] = groups_value
|
||||
raise Exception("Please use separate records for groups")
|
||||
|
||||
if not values.get('name'):
|
||||
if not action_name:
|
||||
@@ -205,17 +195,8 @@ class RecordTagHandler:
|
||||
search_model = self.model._columns[field_name].model_name
|
||||
f_obj = self.mh.pool.get(search_model)
|
||||
with Transaction().set_context(active_test=False):
|
||||
answer = f_obj.browse(f_obj.search(safe_eval(search_attr)))
|
||||
|
||||
if not answer: return
|
||||
|
||||
if self.model._columns[field_name]._type == 'many2many':
|
||||
self.values[field_name] = [
|
||||
('set', [x['id'] for x in answer]),
|
||||
]
|
||||
|
||||
elif self.model._columns[field_name]._type == 'many2one':
|
||||
self.values[field_name] = answer[0]['id']
|
||||
self.values[field_name], = \
|
||||
f_obj.search(safe_eval(search_attr))
|
||||
|
||||
elif ref_attr:
|
||||
self.values[field_name] = self.mh.get_id(ref_attr)
|
||||
@@ -527,7 +508,7 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
|
||||
ref_id = ref_id[0]
|
||||
return ref_mode + ',' + str(ref_id)
|
||||
elif field_type in ['one2many', 'many2many']:
|
||||
raise Unhandled_field()
|
||||
raise Unhandled_field("Unhandled field %s" % key)
|
||||
else:
|
||||
return browse_record[key]
|
||||
|
||||
@@ -695,13 +676,7 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
|
||||
to_update = {}
|
||||
for key in values:
|
||||
|
||||
try:
|
||||
db_field = self._clean_value(key, db_val, object_ref)
|
||||
except Unhandled_field:
|
||||
logging.getLogger("convert").info(
|
||||
'Field %s on %s : integrity not tested.'%(key, model))
|
||||
to_update[key] = values[key]
|
||||
continue
|
||||
db_field = self._clean_value(key, db_val, object_ref)
|
||||
|
||||
# if the fs value is the same has in the db, whe ignore it
|
||||
val = values[key]
|
||||
@@ -813,11 +788,7 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
|
||||
if not db_val:
|
||||
db_val = object_ref.browse(db_id)
|
||||
for key in to_update:
|
||||
try:
|
||||
values[key] = self._clean_value(
|
||||
key, db_val, object_ref)
|
||||
except Unhandled_field:
|
||||
continue
|
||||
values[key] = self._clean_value( key, db_val, object_ref)
|
||||
|
||||
if module != self.module:
|
||||
temp_values = old_values.copy()
|
||||
@@ -904,11 +875,7 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
|
||||
# in the model_data table:
|
||||
db_val = object_ref.browse(db_id)
|
||||
for key in values:
|
||||
try:
|
||||
values[key] = self._clean_value(key, db_val,
|
||||
object_ref)
|
||||
except Unhandled_field:
|
||||
continue
|
||||
values[key] = self._clean_value(key, db_val, object_ref)
|
||||
|
||||
for table in inherit_db_ids.keys():
|
||||
self.modeldata_obj.create({
|
||||
|
||||
+3
-2
@@ -1,6 +1,7 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.pool import Pool
|
||||
|
||||
|
||||
class WarningErrorMixin(object):
|
||||
@@ -24,7 +25,7 @@ class WarningErrorMixin(object):
|
||||
(or tuple if error_description is not empty) instead of raising an
|
||||
exception.
|
||||
'''
|
||||
translation_obj = self.pool.get('ir.translation')
|
||||
translation_obj = Pool().get('ir.translation')
|
||||
|
||||
error = self._error_messages.get(error, error)
|
||||
|
||||
@@ -92,7 +93,7 @@ class WarningErrorMixin(object):
|
||||
:param warning_description_args: the arguments that will be used
|
||||
for "%"-based substitution
|
||||
'''
|
||||
warning_obj = self.pool.get('res.user.warning')
|
||||
warning_obj = Pool().get('res.user.warning')
|
||||
if warning_obj.check(warning_name):
|
||||
if warning_description:
|
||||
warning, warning_description = self.raise_user_error(warning,
|
||||
|
||||
+27
-15
@@ -1,6 +1,5 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
import base64
|
||||
import os
|
||||
from trytond.model import ModelView, ModelSQL, ModelStorage, fields
|
||||
@@ -9,6 +8,7 @@ from trytond.backend import TableHandler
|
||||
from trytond.pyson import PYSONEncoder, CONTEXT, PYSON
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.cache import Cache
|
||||
from trytond.pool import Pool
|
||||
|
||||
|
||||
class Action(ModelSQL, ModelView):
|
||||
@@ -20,7 +20,7 @@ class Action(ModelSQL, ModelView):
|
||||
usage = fields.Char('Usage')
|
||||
keywords = fields.One2Many('ir.action.keyword', 'action',
|
||||
'Keywords')
|
||||
groups = fields.Many2Many('ir.action-res.group', 'action_id', 'gid',
|
||||
groups = fields.Many2Many('ir.action-res.group', 'action', 'group',
|
||||
'Groups')
|
||||
icon = fields.Many2One('ir.ui.icon', 'Icon')
|
||||
active = fields.Boolean('Active', select=2)
|
||||
@@ -38,6 +38,7 @@ class Action(ModelSQL, ModelView):
|
||||
return True
|
||||
|
||||
def get_action_id(self, action_id):
|
||||
pool = Pool()
|
||||
with Transaction().set_context(active_test=False):
|
||||
if self.search([
|
||||
('id', '=', action_id),
|
||||
@@ -49,7 +50,7 @@ class Action(ModelSQL, ModelView):
|
||||
'ir.action.wizard',
|
||||
'ir.action.url',
|
||||
):
|
||||
action_obj = self.pool.get(action_type)
|
||||
action_obj = pool.get(action_type)
|
||||
action_id2 = action_obj.search([
|
||||
('id', '=', action_id),
|
||||
])
|
||||
@@ -88,7 +89,8 @@ class ActionKeyword(ModelSQL, ModelView):
|
||||
})
|
||||
|
||||
def check_wizard_model(self, ids):
|
||||
action_wizard_obj = self.pool.get('ir.action.wizard')
|
||||
pool = Pool()
|
||||
action_wizard_obj = pool.get('ir.action.wizard')
|
||||
for action_keyword in self.browse(ids):
|
||||
if action_keyword.action.type == 'ir.action.wizard':
|
||||
action_wizard_id = action_wizard_obj.search([
|
||||
@@ -103,13 +105,15 @@ class ActionKeyword(ModelSQL, ModelView):
|
||||
|
||||
def _convert_vals(self, vals):
|
||||
vals = vals.copy()
|
||||
action_obj = self.pool.get('ir.action')
|
||||
pool = Pool()
|
||||
action_obj = pool.get('ir.action')
|
||||
if 'action' in vals:
|
||||
vals['action'] = action_obj.get_action_id(vals['action'])
|
||||
return vals
|
||||
|
||||
def models_get(self):
|
||||
model_obj = self.pool.get('ir.model')
|
||||
pool = Pool()
|
||||
model_obj = pool.get('ir.model')
|
||||
model_ids = model_obj.search([])
|
||||
res = []
|
||||
for model in model_obj.browse(model_ids):
|
||||
@@ -117,36 +121,39 @@ class ActionKeyword(ModelSQL, ModelView):
|
||||
return res
|
||||
|
||||
def delete(self, ids):
|
||||
pool = Pool()
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
for keyword in self.browse(ids):
|
||||
# Restart the cache view
|
||||
try:
|
||||
self.pool.get(keyword.model.split(',')[0]
|
||||
pool.get(keyword.model.split(',')[0]
|
||||
).fields_view_get.reset()
|
||||
except Exception:
|
||||
pass
|
||||
return super(ActionKeyword, self).delete(ids)
|
||||
|
||||
def create(self, vals):
|
||||
pool = Pool()
|
||||
vals = self._convert_vals(vals)
|
||||
if 'model' in vals:
|
||||
# Restart the cache view
|
||||
try:
|
||||
self.pool.get(vals['model'].split(',')[0]
|
||||
pool.get(vals['model'].split(',')[0]
|
||||
).fields_view_get.reset()
|
||||
except Exception:
|
||||
pass
|
||||
return super(ActionKeyword, self).create(vals)
|
||||
|
||||
def write(self, ids, vals):
|
||||
pool = Pool()
|
||||
vals = self._convert_vals(vals)
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
for keyword in self.browse(ids):
|
||||
# Restart the cache view
|
||||
try:
|
||||
self.pool.get(keyword.model.split(',')[0]
|
||||
pool.get(keyword.model.split(',')[0]
|
||||
).fields_view_get.reset()
|
||||
except Exception:
|
||||
pass
|
||||
@@ -154,13 +161,14 @@ class ActionKeyword(ModelSQL, ModelView):
|
||||
for keyword in self.browse(ids):
|
||||
# Restart the cache view
|
||||
try:
|
||||
self.pool.get(keyword.model.split(',')[0]
|
||||
pool.get(keyword.model.split(',')[0]
|
||||
).fields_view_get.reset()
|
||||
except Exception:
|
||||
pass
|
||||
return res
|
||||
|
||||
def get_keyword(self, keyword, value):
|
||||
pool = Pool()
|
||||
res = []
|
||||
model, model_id = value
|
||||
|
||||
@@ -176,7 +184,7 @@ class ActionKeyword(ModelSQL, ModelView):
|
||||
]))
|
||||
for action_keyword in self.browse(action_keyword_ids):
|
||||
try:
|
||||
action_obj = self.pool.get(action_keyword.action.type)
|
||||
action_obj = pool.get(action_keyword.action.type)
|
||||
except Exception:
|
||||
continue
|
||||
action_id = action_obj.search([
|
||||
@@ -369,7 +377,8 @@ class ActionReport(ModelSQL, ModelView):
|
||||
return super(ActionReport, self).write(ids, vals)
|
||||
|
||||
def delete(self, ids):
|
||||
action_obj = self.pool.get('ir.action')
|
||||
pool = Pool()
|
||||
action_obj = pool.get('ir.action')
|
||||
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
@@ -563,7 +572,8 @@ class ActionActWindow(ModelSQL, ModelView):
|
||||
return new_id
|
||||
|
||||
def delete(self, ids):
|
||||
action_obj = self.pool.get('ir.action')
|
||||
pool = Pool()
|
||||
action_obj = pool.get('ir.action')
|
||||
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
@@ -639,7 +649,8 @@ class ActionWizard(ModelSQL, ModelView):
|
||||
return new_id
|
||||
|
||||
def delete(self, ids):
|
||||
action_obj = self.pool.get('ir.action')
|
||||
pool = Pool()
|
||||
action_obj = pool.get('ir.action')
|
||||
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
@@ -773,7 +784,8 @@ class ActionURL(ModelSQL, ModelView):
|
||||
return new_id
|
||||
|
||||
def delete(self, ids):
|
||||
action_obj = self.pool.get('ir.action')
|
||||
pool = Pool()
|
||||
action_obj = pool.get('ir.action')
|
||||
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
|
||||
@@ -33,7 +33,6 @@ this repository contains the full copyright notices and license terms. -->
|
||||
</field>
|
||||
</page>
|
||||
<page name="groups">
|
||||
<separator name="groups" colspan="4"/>
|
||||
<field name="groups" colspan="4"/>
|
||||
</page>
|
||||
</notebook>
|
||||
@@ -119,7 +118,6 @@ this repository contains the full copyright notices and license terms. -->
|
||||
</field>
|
||||
</page>
|
||||
<page name="groups">
|
||||
<separator name="groups" colspan="4"/>
|
||||
<field name="groups" colspan="4"/>
|
||||
</page>
|
||||
</notebook>
|
||||
@@ -218,7 +216,6 @@ this repository contains the full copyright notices and license terms. -->
|
||||
</field>
|
||||
</page>
|
||||
<page name="groups">
|
||||
<separator name="groups" colspan="4"/>
|
||||
<field name="groups" colspan="4"/>
|
||||
</page>
|
||||
</notebook>
|
||||
@@ -294,7 +291,6 @@ this repository contains the full copyright notices and license terms. -->
|
||||
</field>
|
||||
</page>
|
||||
<page name="groups">
|
||||
<separator name="groups" colspan="4"/>
|
||||
<field name="groups" colspan="4"/>
|
||||
</page>
|
||||
</notebook>
|
||||
@@ -423,7 +419,6 @@ this repository contains the full copyright notices and license terms. -->
|
||||
</field>
|
||||
</page>
|
||||
<page name="groups">
|
||||
<separator name="groups" colspan="4"/>
|
||||
<field name="groups" colspan="4"/>
|
||||
</page>
|
||||
</notebook>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
import os
|
||||
try:
|
||||
import hashlib
|
||||
@@ -13,6 +12,7 @@ from trytond.config import CONFIG
|
||||
from trytond.backend import TableHandler
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.pyson import Not, Equal, Eval
|
||||
from trytond.pool import Pool
|
||||
|
||||
def firstline(description):
|
||||
try:
|
||||
@@ -84,7 +84,8 @@ class Attachment(ModelSQL, ModelView):
|
||||
return 0
|
||||
|
||||
def models_get(self):
|
||||
model_obj = self.pool.get('ir.model')
|
||||
pool = Pool()
|
||||
model_obj = pool.get('ir.model')
|
||||
model_ids = model_obj.search([])
|
||||
res = []
|
||||
for model in model_obj.browse(model_ids):
|
||||
@@ -189,7 +190,8 @@ class Attachment(ModelSQL, ModelView):
|
||||
|
||||
|
||||
def check_access(self, ids, mode='read'):
|
||||
model_access_obj = self.pool.get('ir.model.access')
|
||||
pool = Pool()
|
||||
model_access_obj = pool.get('ir.model.access')
|
||||
if Transaction().user == 0:
|
||||
return
|
||||
if not ids:
|
||||
@@ -224,7 +226,8 @@ class Attachment(ModelSQL, ModelView):
|
||||
return res
|
||||
|
||||
def view_header_get(self, value, view_type='form'):
|
||||
ir_model_obj = self.pool.get('ir.model')
|
||||
pool = Pool()
|
||||
ir_model_obj = pool.get('ir.model')
|
||||
value = super(Attachment, self).view_header_get(value,
|
||||
view_type=view_type)
|
||||
resource = Transaction().context.get('resource')
|
||||
@@ -232,7 +235,7 @@ class Attachment(ModelSQL, ModelView):
|
||||
model_name, record_id = resource.split(',', 1)
|
||||
ir_model_id, = ir_model_obj.search([('model', '=', model_name)])
|
||||
ir_model = ir_model_obj.browse(ir_model_id)
|
||||
model_obj = self.pool.get(model_name)
|
||||
model_obj = pool.get(model_name)
|
||||
record = model_obj.browse(int(record_id))
|
||||
value = '%s - %s - %s' % (ir_model.name, record.rec_name, value)
|
||||
return value
|
||||
|
||||
+109
-114
@@ -1,18 +1,19 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
import contextlib
|
||||
import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
import traceback
|
||||
import sys
|
||||
import logging
|
||||
from trytond.backend import Database
|
||||
from trytond.model import ModelView, ModelSQL, fields
|
||||
from trytond.tools import safe_eval
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.pool import Pool
|
||||
from trytond.backend import TableHandler
|
||||
|
||||
_INTERVALTYPES = {
|
||||
'work_days': lambda interval: relativedelta(days=interval),
|
||||
'days': lambda interval: relativedelta(days=interval),
|
||||
'hours': lambda interval: relativedelta(hours=interval),
|
||||
'weeks': lambda interval: relativedelta(weeks=interval),
|
||||
@@ -26,7 +27,8 @@ class Cron(ModelSQL, ModelView):
|
||||
_description = __doc__
|
||||
name = fields.Char('Name', required=True, translate=True)
|
||||
user = fields.Many2One('res.user', 'Execution User', required=True,
|
||||
help="The user used to execute this action")
|
||||
domain=[('active', '=', False)],
|
||||
help="The user used to execute this action")
|
||||
request_user = fields.Many2One(
|
||||
'res.user', 'Request User', required=True,
|
||||
help="The user who will receive requests in case of failure")
|
||||
@@ -35,24 +37,20 @@ class Cron(ModelSQL, ModelView):
|
||||
interval_type = fields.Selection( [
|
||||
('minutes', 'Minutes'),
|
||||
('hours', 'Hours'),
|
||||
('work_days', 'Work Days'),
|
||||
('days', 'Days'),
|
||||
('weeks', 'Weeks'),
|
||||
('months', 'Months'),
|
||||
], 'Interval Unit')
|
||||
numbercall = fields.Integer('Number of calls', select=1,
|
||||
help='Number of times the function is called,\n' \
|
||||
'a negative number indicates that the function ' \
|
||||
'will always be called')
|
||||
doall = fields.Boolean('Repeat missed')
|
||||
nextcall = fields.DateTime('Next call date', required=True,
|
||||
number_calls = fields.Integer('Number of Calls', select=1,
|
||||
help=('Number of times the function is called, a negative '
|
||||
'number indicates that the function will always be '
|
||||
'called'))
|
||||
repeat_missed = fields.Boolean('Repeat Missed')
|
||||
next_call = fields.DateTime('Next Call', required=True,
|
||||
select=1)
|
||||
model = fields.Char('Model')
|
||||
function = fields.Char('Function')
|
||||
args = fields.Text('Arguments')
|
||||
priority = fields.Integer('Priority',
|
||||
help='0=Very Urgent\n10=Not urgent')
|
||||
running = fields.Boolean('Running', readonly=True, select=1)
|
||||
|
||||
def __init__(self):
|
||||
super(Cron, self).__init__()
|
||||
@@ -62,135 +60,132 @@ class Cron(ModelSQL, ModelView):
|
||||
"properly: \"%s\"\n Traceback: \n\n%s\n"
|
||||
})
|
||||
|
||||
def default_nextcall(self):
|
||||
def init(self, module_name):
|
||||
cursor = Transaction().cursor
|
||||
|
||||
# Migration from 2.0: rename numbercall, doall and nextcall
|
||||
table = TableHandler(cursor, self, module_name)
|
||||
table.column_rename('numbercall', 'number_calls')
|
||||
table.column_rename('doall', 'repeat_missed')
|
||||
table.column_rename('nextcall', 'next_call')
|
||||
|
||||
super(Cron, self).init(module_name)
|
||||
|
||||
# Migration from 2.0: work_days removed
|
||||
cursor.execute('UPDATE "%s" '
|
||||
'SET interval_type = %%s '
|
||||
'WHERE interval_type = %%s' % self._table,
|
||||
('days', 'work_days'))
|
||||
|
||||
def default_next_call(self):
|
||||
return datetime.datetime.now()
|
||||
|
||||
def default_priority(self):
|
||||
return 5
|
||||
|
||||
def default_user(self):
|
||||
return int(Transaction().user)
|
||||
|
||||
def default_interval_number(self):
|
||||
return 1
|
||||
|
||||
def default_interval_type(self):
|
||||
return 'months'
|
||||
|
||||
def default_numbercall(self):
|
||||
return 1
|
||||
def default_number_calls(self):
|
||||
return -1
|
||||
|
||||
def default_active(self):
|
||||
return True
|
||||
|
||||
def default_doall(self):
|
||||
def default_repeat_missed(self):
|
||||
return True
|
||||
|
||||
def default_running(self):
|
||||
return False
|
||||
|
||||
def check_xml_record(self, ids, values):
|
||||
return True
|
||||
|
||||
def get_delta(self, cron):
|
||||
'''
|
||||
Return the relativedelta for the next call
|
||||
'''
|
||||
return _INTERVALTYPES[cron.interval_type](cron.interval_number)
|
||||
|
||||
def _get_request_values(self, cron):
|
||||
tb_s = reduce(lambda x, y: x + y,
|
||||
traceback.format_exception(*sys.exc_info()))
|
||||
tb_s = tb_s.decode('utf-8', 'ignore')
|
||||
name = self.raise_user_error('request_title',
|
||||
raise_exception=False)
|
||||
body = self.raise_user_error('request_body', (cron.name, tb_s),
|
||||
raise_exception=False)
|
||||
values = {
|
||||
'name': name,
|
||||
'priority': '2',
|
||||
'act_from': cron.user.id,
|
||||
'act_to': cron.request_user.id,
|
||||
'body': body,
|
||||
'date_sent': datetime.datetime.now(),
|
||||
'references': [
|
||||
('create', {
|
||||
'reference': '%s,%s' % (self._name, cron.id),
|
||||
}),
|
||||
],
|
||||
'state': 'waiting',
|
||||
'trigger_date': datetime.datetime.now(),
|
||||
}
|
||||
return values
|
||||
|
||||
def _callback(self, cron):
|
||||
pool = Pool()
|
||||
try:
|
||||
args = (cron['args'] or []) and safe_eval(cron['args'])
|
||||
obj = self.pool.get(cron['model'])
|
||||
if not obj and hasattr(obj, cron['function']):
|
||||
return False
|
||||
fct = getattr(obj, cron['function'])
|
||||
with Transaction().set_user(cron['user']):
|
||||
fct(*args)
|
||||
args = (cron.args or []) and safe_eval(cron.args)
|
||||
model_obj = pool.get(cron.model)
|
||||
with Transaction().set_user(cron.user.id):
|
||||
getattr(model_obj, cron.function)(*args)
|
||||
except Exception, error:
|
||||
Transaction().cursor.rollback()
|
||||
|
||||
tb_s = ''
|
||||
for line in traceback.format_exception(*sys.exc_info()):
|
||||
try:
|
||||
line = line.encode('utf-8', 'ignore')
|
||||
except Exception:
|
||||
continue
|
||||
tb_s += line
|
||||
try:
|
||||
tb_s += str(error).decode('utf-8', 'ignore')
|
||||
except Exception:
|
||||
pass
|
||||
request_obj = pool.get('res.request')
|
||||
req_user = cron.request_user
|
||||
language = (req_user.language.code if req_user.language
|
||||
else 'en_US')
|
||||
with contextlib.nested(Transaction().set_user(cron.user.id),
|
||||
Transaction().set_context(language=language)):
|
||||
values = self._get_request_values(cron)
|
||||
rid = request_obj.create(values)
|
||||
Transaction().cursor.commit()
|
||||
|
||||
request_obj = self.pool.get('res.request')
|
||||
try:
|
||||
user_obj = self.pool.get('res.user')
|
||||
req_user = user_obj.browse(cron['request_user'])
|
||||
language = (req_user.language.code if req_user.language
|
||||
else 'en_US')
|
||||
with contextlib.nested(Transaction().set_user(cron['user']),
|
||||
Transaction().set_context(language=language)):
|
||||
rid = request_obj.create({
|
||||
'name': self.raise_user_error('request_title',
|
||||
raise_exception=False),
|
||||
'priority': '2',
|
||||
'act_from': cron['user'],
|
||||
'act_to': cron['request_user'],
|
||||
'body': self.raise_user_error('request_body',
|
||||
(cron['name'], tb_s), raise_exception=False),
|
||||
'date_sent': datetime.datetime.now(),
|
||||
'references': [
|
||||
('create', {
|
||||
'reference': "ir.cron,%s" % cron['id'],
|
||||
}),
|
||||
],
|
||||
'state': 'waiting',
|
||||
'trigger_date': datetime.datetime.now(),
|
||||
})
|
||||
Transaction().cursor.commit()
|
||||
except Exception:
|
||||
Transaction().cursor.rollback()
|
||||
|
||||
def pool_jobs(self, db_name):
|
||||
def run(self, db_name):
|
||||
now = datetime.datetime.now()
|
||||
with Transaction().start(db_name, 0) as transaction:
|
||||
try:
|
||||
transaction.cursor.lock(self._table)
|
||||
transaction.cursor.execute('SELECT * FROM ir_cron '
|
||||
'WHERE numbercall <> 0 '
|
||||
'AND active '
|
||||
'AND nextcall <= %s '
|
||||
'AND NOT running '
|
||||
'ORDER BY priority', (datetime.datetime.now(),))
|
||||
crons = transaction.cursor.dictfetchall()
|
||||
transaction.cursor.lock(self._table)
|
||||
cron_ids = self.search([
|
||||
('number_calls', '!=', 0),
|
||||
('next_call', '<=', datetime.datetime.now()),
|
||||
])
|
||||
crons = self.browse(cron_ids)
|
||||
|
||||
for cron in crons:
|
||||
transaction.cursor.execute('UPDATE ir_cron '
|
||||
'SET running = %s '
|
||||
'WHERE id = %s', (True, cron['id']))
|
||||
nextcall = cron['nextcall']
|
||||
numbercall = cron['numbercall']
|
||||
done = False
|
||||
|
||||
while nextcall < now and numbercall:
|
||||
if numbercall > 0:
|
||||
numbercall -= 1
|
||||
if not done or cron['doall']:
|
||||
for cron in crons:
|
||||
try:
|
||||
next_call = cron.next_call
|
||||
number_calls = cron.number_calls
|
||||
first = True
|
||||
while next_call < now and number_calls != 0:
|
||||
if first or cron.repeat_missed:
|
||||
self._callback(cron)
|
||||
if numbercall:
|
||||
nextcall += _INTERVALTYPES[cron['interval_type']](
|
||||
cron['interval_number'])
|
||||
done = True
|
||||
next_call += self.get_delta(cron)
|
||||
if number_calls > 0:
|
||||
number_calls -= 1
|
||||
first = False
|
||||
|
||||
addsql = ''
|
||||
addsql_param = []
|
||||
if not numbercall:
|
||||
addsql = ', active = %s'
|
||||
addsql_param = [False]
|
||||
transaction.cursor.execute("UPDATE ir_cron "
|
||||
"SET nextcall = %s, "
|
||||
"running = %s, "
|
||||
"numbercall = %s" + addsql + " "
|
||||
"WHERE id = %s",
|
||||
[nextcall, False, numbercall] + addsql_param +
|
||||
[cron['id']])
|
||||
values = {
|
||||
'next_call': next_call,
|
||||
'number_calls': number_calls,
|
||||
}
|
||||
if not number_calls:
|
||||
values['active'] = False
|
||||
self.write(cron.id, values)
|
||||
transaction.cursor.commit()
|
||||
except Exception:
|
||||
transaction.cursor.rollback()
|
||||
raise
|
||||
except Exception:
|
||||
transaction.cursor.rollback()
|
||||
tb_s = reduce(lambda x, y: x + y,
|
||||
traceback.format_exception(*sys.exc_info()))
|
||||
tb_s = tb_s.decode('utf-8', 'ignore')
|
||||
logger = logging.getLogger('cron')
|
||||
logger.error('Exception:\n%s' % tb_s)
|
||||
|
||||
Cron()
|
||||
|
||||
+17
-23
@@ -12,16 +12,14 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="arch" type="xml">
|
||||
<![CDATA[
|
||||
<tree string="Scheduled Actions">
|
||||
<field name="nextcall"/>
|
||||
<field name="next_call"/>
|
||||
<field name="name" select="1"/>
|
||||
<field name="user" select="1"/>
|
||||
<field name="request_user" select="2"/>
|
||||
<field name="priority" select="2"/>
|
||||
<field name="interval_number"/>
|
||||
<field name="interval_type"/>
|
||||
<field name="numbercall" select="2"/>
|
||||
<field name="number_calls" select="2"/>
|
||||
<field name="active" select="2"/>
|
||||
<field name="running" select="2"/>
|
||||
</tree>
|
||||
]]>
|
||||
</field>
|
||||
@@ -31,37 +29,33 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<![CDATA[
|
||||
<form string="Scheduled Action" col="6">
|
||||
<form string="Scheduled Action">
|
||||
<label name="name"/>
|
||||
<field name="name"/>
|
||||
<label name="active"/>
|
||||
<field name="active"/>
|
||||
<label name="user"/>
|
||||
<field name="user"/>
|
||||
<label name="request_user"/>
|
||||
<field name="request_user"/>
|
||||
<label name="numbercall"/>
|
||||
<field name="numbercall"/>
|
||||
<label name="priority"/>
|
||||
<field name="priority"/>
|
||||
<label name="active"/>
|
||||
<field name="active"/>
|
||||
<label name="interval_number"/>
|
||||
<field name="interval_number"/>
|
||||
<label name="interval_type"/>
|
||||
<field name="interval_type"/>
|
||||
<label name="nextcall"/>
|
||||
<field name="nextcall"/>
|
||||
<label name="doall"/>
|
||||
<field name="doall"/>
|
||||
<separator string="Action to trigger" colspan="6"
|
||||
<label name="number_calls"/>
|
||||
<field name="number_calls"/>
|
||||
<label name="next_call"/>
|
||||
<field name="next_call"/>
|
||||
<label name="repeat_missed"/>
|
||||
<field name="repeat_missed"/>
|
||||
<separator string="Action to trigger" colspan="4"
|
||||
id="action_trigger"/>
|
||||
<label name="model"/>
|
||||
<field name="model" readonly="1"/>
|
||||
<field name="model"/>
|
||||
<label name="function"/>
|
||||
<field name="function" readonly="1"/>
|
||||
<label name="running"/>
|
||||
<field name="running"/>
|
||||
<separator name="args" colspan="6"/>
|
||||
<field name="args" colspan="6" readonly="1"/>
|
||||
<field name="function"/>
|
||||
<label name="args"/>
|
||||
<field name="args" colspan="3" widget="char"/>
|
||||
</form>
|
||||
]]>
|
||||
</field>
|
||||
@@ -69,7 +63,7 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<record model="ir.action.act_window" id="act_cron_form">
|
||||
<field name="name">Scheduled Actions</field>
|
||||
<field name="res_model">ir.cron</field>
|
||||
<field name="context">{'active_test': False}</field>
|
||||
<field name="context"></field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view"
|
||||
id="act_cron_form_view1">
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
import time
|
||||
import locale
|
||||
import os
|
||||
|
||||
+3
-2
@@ -1,12 +1,12 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
import time
|
||||
import datetime
|
||||
from trytond.model import ModelView, ModelSQL, fields
|
||||
from trytond.model.cacheable import Cacheable
|
||||
from trytond.tools import safe_eval, datetime_strftime
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.pool import Pool
|
||||
from time_locale import TIME_LOCALE
|
||||
from locale import CHAR_MAX
|
||||
|
||||
@@ -57,7 +57,8 @@ class Lang(ModelSQL, ModelView, Cacheable):
|
||||
return [('name',) + clause[1:]]
|
||||
|
||||
def read(self, ids, fields_names=None):
|
||||
translation_obj = self.pool.get('ir.translation')
|
||||
pool = Pool()
|
||||
translation_obj = pool.get('ir.translation')
|
||||
res = super(Lang, self).read(ids, fields_names=fields_names)
|
||||
if (Transaction().context.get('translate_name')
|
||||
and (not fields_names or 'name' in fields_names)):
|
||||
|
||||
+37
-22
@@ -8,6 +8,7 @@ from trytond.report import Report
|
||||
from trytond.wizard import Wizard
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.cache import Cache
|
||||
from trytond.pool import Pool
|
||||
IDENTIFIER = re.compile(r'^[a-zA-z_][a-zA-Z0-9_]*$')
|
||||
|
||||
|
||||
@@ -47,21 +48,24 @@ class Model(ModelSQL, ModelView):
|
||||
return True
|
||||
|
||||
def create(self, vals):
|
||||
property_obj = self.pool.get('ir.property')
|
||||
pool = Pool()
|
||||
property_obj = pool.get('ir.property')
|
||||
res = super(Model, self).create(vals)
|
||||
# Restart the cache of models_get
|
||||
property_obj.models_get.reset()
|
||||
return res
|
||||
|
||||
def write(self, ids, vals):
|
||||
property_obj = self.pool.get('ir.property')
|
||||
pool = Pool()
|
||||
property_obj = pool.get('ir.property')
|
||||
res = super(Model, self).write(ids, vals)
|
||||
# Restart the cache of models_get
|
||||
property_obj.models_get.reset()
|
||||
return res
|
||||
|
||||
def delete(self, ids):
|
||||
property_obj = self.pool.get('ir.property')
|
||||
pool = Pool()
|
||||
property_obj = pool.get('ir.property')
|
||||
res = super(Model, self).delete(ids)
|
||||
# Restart the cache of models_get
|
||||
property_obj.models_get.reset()
|
||||
@@ -117,7 +121,8 @@ class ModelField(ModelSQL, ModelView):
|
||||
return True
|
||||
|
||||
def read(self, ids, fields_names=None):
|
||||
translation_obj = self.pool.get('ir.translation')
|
||||
pool = Pool()
|
||||
translation_obj = pool.get('ir.translation')
|
||||
|
||||
to_delete = []
|
||||
if Transaction().context.get('language'):
|
||||
@@ -249,8 +254,9 @@ class ModelAccess(ModelSQL, ModelView):
|
||||
if Transaction().user == 0:
|
||||
return True
|
||||
|
||||
ir_model_obj = self.pool.get('ir.model')
|
||||
user_group_obj = self.pool.get('res.user-res.group')
|
||||
pool = Pool()
|
||||
ir_model_obj = pool.get('ir.model')
|
||||
user_group_obj = pool.get('res.user-res.group')
|
||||
cursor = Transaction().cursor
|
||||
|
||||
cursor.execute('SELECT MAX(CASE WHEN a.perm_%s THEN 1 ELSE 0 END) '
|
||||
@@ -258,8 +264,8 @@ class ModelAccess(ModelSQL, ModelView):
|
||||
'JOIN "%s" AS m '
|
||||
'ON (a.model = m.id) '
|
||||
'LEFT JOIN "%s" AS gu '
|
||||
'ON (gu.gid = a."group") '
|
||||
'WHERE m.model = %%s AND (gu.uid = %%s OR a."group" IS NULL)'
|
||||
'ON (gu."group" = a."group") '
|
||||
'WHERE m.model = %%s AND (gu."user" = %%s OR a."group" IS NULL)'
|
||||
% (mode, self._table, ir_model_obj._table,
|
||||
user_group_obj._table),
|
||||
(model_name, Transaction().user))
|
||||
@@ -275,7 +281,8 @@ class ModelAccess(ModelSQL, ModelView):
|
||||
res = super(ModelAccess, self).write(ids, vals)
|
||||
# Restart the cache
|
||||
self.check.reset()
|
||||
for _, model in self.pool.iterobject():
|
||||
pool = Pool()
|
||||
for _, model in pool.iterobject():
|
||||
try:
|
||||
model.fields_view_get.reset()
|
||||
except Exception:
|
||||
@@ -286,7 +293,8 @@ class ModelAccess(ModelSQL, ModelView):
|
||||
res = super(ModelAccess, self).create(vals)
|
||||
# Restart the cache
|
||||
self.check.reset()
|
||||
for _, model in self.pool.iterobject():
|
||||
pool = Pool()
|
||||
for _, model in pool.iterobject():
|
||||
try:
|
||||
model.fields_view_get.reset()
|
||||
except Exception:
|
||||
@@ -297,7 +305,8 @@ class ModelAccess(ModelSQL, ModelView):
|
||||
res = super(ModelAccess, self).delete(ids)
|
||||
# Restart the cache
|
||||
self.check.reset()
|
||||
for _, model in self.pool.iterobject():
|
||||
pool = Pool()
|
||||
for _, model in pool.iterobject():
|
||||
try:
|
||||
model.fields_view_get.reset()
|
||||
except Exception:
|
||||
@@ -359,9 +368,10 @@ class ModelFieldAccess(ModelSQL, ModelView):
|
||||
return dict((x, True) for x in fields)
|
||||
return True
|
||||
|
||||
ir_model_obj = self.pool.get('ir.model')
|
||||
ir_model_field_obj = self.pool.get('ir.model.field')
|
||||
user_group_obj = self.pool.get('res.user-res.group')
|
||||
pool = Pool()
|
||||
ir_model_obj = pool.get('ir.model')
|
||||
ir_model_field_obj = pool.get('ir.model.field')
|
||||
user_group_obj = pool.get('res.user-res.group')
|
||||
|
||||
cursor = Transaction().cursor
|
||||
|
||||
@@ -373,8 +383,8 @@ class ModelFieldAccess(ModelSQL, ModelView):
|
||||
'JOIN "%s" AS m '
|
||||
'ON (f.model = m.id) '
|
||||
'LEFT JOIN "%s" AS gu '
|
||||
'ON (gu.gid = a."group") '
|
||||
'WHERE m.model = %%s AND (gu.uid = %%s OR a."group" IS NULL) '
|
||||
'ON (gu."group" = a."group") '
|
||||
'WHERE m.model = %%s AND (gu."user" = %%s OR a."group" IS NULL) '
|
||||
'GROUP BY f.name'
|
||||
% (mode, self._table, ir_model_field_obj._table,
|
||||
ir_model_obj._table, user_group_obj._table),
|
||||
@@ -394,7 +404,8 @@ class ModelFieldAccess(ModelSQL, ModelView):
|
||||
res = super(ModelFieldAccess, self).write(ids, vals)
|
||||
# Restart the cache
|
||||
self.check.reset()
|
||||
for _, model in self.pool.iterobject():
|
||||
pool = Pool()
|
||||
for _, model in pool.iterobject():
|
||||
try:
|
||||
model.fields_view_get.reset()
|
||||
except Exception:
|
||||
@@ -405,7 +416,8 @@ class ModelFieldAccess(ModelSQL, ModelView):
|
||||
res = super(ModelFieldAccess, self).create(vals)
|
||||
# Restart the cache
|
||||
self.check.reset()
|
||||
for _, model in self.pool.iterobject():
|
||||
pool = Pool()
|
||||
for _, model in pool.iterobject():
|
||||
try:
|
||||
model.fields_view_get.reset()
|
||||
except Exception:
|
||||
@@ -416,7 +428,8 @@ class ModelFieldAccess(ModelSQL, ModelView):
|
||||
res = super(ModelFieldAccess, self).delete(ids)
|
||||
# Restart the cache
|
||||
self.check.reset()
|
||||
for _, model in self.pool.iterobject():
|
||||
pool = Pool()
|
||||
for _, model in pool.iterobject():
|
||||
try:
|
||||
model.fields_view_get.reset()
|
||||
except Exception:
|
||||
@@ -525,8 +538,9 @@ class ModelGraph(Report):
|
||||
|
||||
def execute(self, ids, datas):
|
||||
import pydot
|
||||
model_obj = self.pool.get('ir.model')
|
||||
action_report_obj = self.pool.get('ir.action.report')
|
||||
pool = Pool()
|
||||
model_obj = pool.get('ir.model')
|
||||
action_report_obj = pool.get('ir.action.report')
|
||||
|
||||
if not datas['form']['filter']:
|
||||
filter = None
|
||||
@@ -560,7 +574,8 @@ class ModelGraph(Report):
|
||||
models
|
||||
'''
|
||||
import pydot
|
||||
model_obj = self.pool.get('ir.model')
|
||||
pool = Pool()
|
||||
model_obj = pool.get('ir.model')
|
||||
|
||||
sub_models = set()
|
||||
if level > 0:
|
||||
|
||||
+21
-15
@@ -1,6 +1,5 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
import os
|
||||
from trytond.model import ModelView, ModelSQL, fields
|
||||
import trytond.tools as tools
|
||||
@@ -216,7 +215,8 @@ class Module(ModelSQL, ModelView):
|
||||
|
||||
# update the list of available packages
|
||||
def update_list(self):
|
||||
lang_obj = self.pool.get('ir.lang')
|
||||
pool = Pool()
|
||||
lang_obj = pool.get('ir.lang')
|
||||
res = 0
|
||||
with Transaction().set_context(language=False):
|
||||
lang_ids = lang_obj.search([
|
||||
@@ -313,7 +313,8 @@ class Module(ModelSQL, ModelView):
|
||||
return res
|
||||
|
||||
def _update_dependencies(self, module, depends=None):
|
||||
dependency_obj = self.pool.get('ir.module.module.dependency')
|
||||
pool = Pool()
|
||||
dependency_obj = pool.get('ir.module.module.dependency')
|
||||
dependency_obj.delete([x.id for x in module.dependencies
|
||||
if x.name not in depends])
|
||||
if depends is None:
|
||||
@@ -354,7 +355,8 @@ class ModuleDependency(ModelSQL, ModelView):
|
||||
|
||||
def get_state(self, ids, name):
|
||||
result = {}
|
||||
module_obj = self.pool.get('ir.module.module')
|
||||
pool = Pool()
|
||||
module_obj = pool.get('ir.module.module')
|
||||
for dependency in self.browse(ids):
|
||||
ids = module_obj.search([
|
||||
('name', '=', dependency.name),
|
||||
@@ -442,7 +444,8 @@ class ModuleConfigWizard(Wizard):
|
||||
return res
|
||||
|
||||
def _action_wizard(self, data):
|
||||
item_obj = self.pool.get('ir.module.module.config_wizard.item')
|
||||
pool = Pool()
|
||||
item_obj = pool.get('ir.module.module.config_wizard.item')
|
||||
item_ids = item_obj.search([
|
||||
('state', '=', 'open'),
|
||||
], limit=1)
|
||||
@@ -458,7 +461,8 @@ class ModuleConfigWizard(Wizard):
|
||||
return {}
|
||||
|
||||
def _next(self, data):
|
||||
item_obj = self.pool.get('ir.module.module.config_wizard.item')
|
||||
pool = Pool()
|
||||
item_obj = pool.get('ir.module.module.config_wizard.item')
|
||||
item_ids = item_obj.search([
|
||||
('state', '=', 'open'),
|
||||
])
|
||||
@@ -491,7 +495,8 @@ class ModuleInstallUpgrade(Wizard):
|
||||
_name = 'ir.module.module.install_upgrade'
|
||||
|
||||
def _get_install(self, data):
|
||||
module_obj = self.pool.get('ir.module.module')
|
||||
pool = Pool()
|
||||
module_obj = pool.get('ir.module.module')
|
||||
module_ids = module_obj.search([
|
||||
('state', 'in', ['to upgrade', 'to remove', 'to install']),
|
||||
])
|
||||
@@ -502,9 +507,9 @@ class ModuleInstallUpgrade(Wizard):
|
||||
}
|
||||
|
||||
def _upgrade_module(self, data):
|
||||
module_obj = self.pool.get('ir.module.module')
|
||||
lang_obj = self.pool.get('ir.lang')
|
||||
dbname = Transaction().cursor.dbname
|
||||
pool = Pool()
|
||||
module_obj = pool.get('ir.module.module')
|
||||
lang_obj = pool.get('ir.lang')
|
||||
with Transaction().new_cursor() as transaction:
|
||||
module_ids = module_obj.search([
|
||||
('state', 'in', ['to upgrade', 'to remove', 'to install']),
|
||||
@@ -515,7 +520,6 @@ class ModuleInstallUpgrade(Wizard):
|
||||
lang = [x.code for x in lang_obj.browse(lang_ids)]
|
||||
transaction.cursor.commit()
|
||||
if module_ids:
|
||||
pool = Pool(dbname)
|
||||
pool.init(update=True, lang=lang)
|
||||
new_wizard = pool.get('ir.module.module.install_upgrade',
|
||||
type='wizard')
|
||||
@@ -563,8 +567,9 @@ class ModuleInstallUpgrade(Wizard):
|
||||
}
|
||||
|
||||
def _menu(self, data):
|
||||
model_data_obj = self.pool.get('ir.model.data')
|
||||
act_window_obj = self.pool.get('ir.action.act_window')
|
||||
pool = Pool()
|
||||
model_data_obj = pool.get('ir.model.data')
|
||||
act_window_obj = pool.get('ir.action.act_window')
|
||||
act_window_id = model_data_obj.get_id('ir', 'act_menu_tree')
|
||||
res = act_window_obj.read(act_window_id)
|
||||
return res
|
||||
@@ -592,8 +597,9 @@ class ModuleConfig(Wizard):
|
||||
}
|
||||
|
||||
def _action_open(self, datas):
|
||||
model_data_obj = self.pool.get('ir.model.data')
|
||||
act_window_obj = self.pool.get('ir.action.act_window')
|
||||
pool = Pool()
|
||||
model_data_obj = pool.get('ir.model.data')
|
||||
act_window_obj = pool.get('ir.action.act_window')
|
||||
act_window_id = model_data_obj.get_id('ir', 'act_module_form')
|
||||
res = act_window_obj.read(act_window_id)
|
||||
return res
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
from decimal import Decimal
|
||||
from trytond.model import ModelView, ModelSQL, fields
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.cache import Cache
|
||||
from trytond.pool import Pool
|
||||
|
||||
|
||||
class Property(ModelSQL, ModelView):
|
||||
@@ -32,7 +32,8 @@ class Property(ModelSQL, ModelView):
|
||||
:param res_ids: a list of record ids
|
||||
:return: a dictionary
|
||||
"""
|
||||
model_access_obj = self.pool.get('ir.model.access')
|
||||
pool = Pool()
|
||||
model_access_obj = pool.get('ir.model.access')
|
||||
res = {}
|
||||
|
||||
model_access_obj.check(model, 'read')
|
||||
@@ -44,7 +45,7 @@ class Property(ModelSQL, ModelView):
|
||||
if res_ids is None:
|
||||
res_ids = []
|
||||
|
||||
model_obj = self.pool.get(model)
|
||||
model_obj = pool.get(model)
|
||||
fields = dict((name, field)
|
||||
for name, field in model_obj._columns.iteritems()
|
||||
if name in names)
|
||||
@@ -126,8 +127,9 @@ class Property(ModelSQL, ModelView):
|
||||
:param val: the value
|
||||
:return: the id of the record created
|
||||
"""
|
||||
model_field_obj = self.pool.get('ir.model.field')
|
||||
model_access_obj = self.pool.get('ir.model.access')
|
||||
pool = Pool()
|
||||
model_field_obj = pool.get('ir.model.field')
|
||||
model_access_obj = pool.get('ir.model.access')
|
||||
|
||||
model_access_obj.check(model, 'write')
|
||||
|
||||
@@ -135,7 +137,7 @@ class Property(ModelSQL, ModelView):
|
||||
('name', '=', name),
|
||||
('model.model', '=', model),
|
||||
], order=[], limit=1)[0]
|
||||
model_obj = self.pool.get(model)
|
||||
model_obj = pool.get(model)
|
||||
field = model_obj._columns[name]
|
||||
|
||||
property_ids = self.search([
|
||||
|
||||
+25
-24
@@ -1,6 +1,5 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
import contextlib
|
||||
import time
|
||||
from trytond.model import ModelView, ModelSQL, fields
|
||||
@@ -9,6 +8,7 @@ from trytond.pyson import Eval, Get
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.cache import Cache
|
||||
from trytond.const import OPERATORS
|
||||
from trytond.pool import Pool
|
||||
|
||||
|
||||
class RuleGroup(ModelSQL, ModelView):
|
||||
@@ -26,9 +26,9 @@ class RuleGroup(ModelSQL, ModelView):
|
||||
rules = fields.One2Many('ir.rule', 'rule_group', 'Tests',
|
||||
help="The rule is satisfied if at least one test is True")
|
||||
groups = fields.Many2Many('ir.rule.group-res.group',
|
||||
'rule_group_id', 'group_id', 'Groups')
|
||||
'rule_group', 'group', 'Groups')
|
||||
users = fields.Many2Many('ir.rule.group-res.user',
|
||||
'rule_group_id', 'user_id', 'Users')
|
||||
'rule_group', 'user', 'Users')
|
||||
perm_read = fields.Boolean('Read Access')
|
||||
perm_write = fields.Boolean('Write Access')
|
||||
perm_create = fields.Boolean('Create Access')
|
||||
@@ -65,19 +65,19 @@ class RuleGroup(ModelSQL, ModelView):
|
||||
def delete(self, ids):
|
||||
res = super(RuleGroup, self).delete(ids)
|
||||
# Restart the cache on the domain_get method of ir.rule
|
||||
self.pool.get('ir.rule').domain_get.reset()
|
||||
Pool().get('ir.rule').domain_get.reset()
|
||||
return res
|
||||
|
||||
def create(self, vals):
|
||||
res = super(RuleGroup, self).create(vals)
|
||||
# Restart the cache on the domain_get method of ir.rule
|
||||
self.pool.get('ir.rule').domain_get.reset()
|
||||
Pool().get('ir.rule').domain_get.reset()
|
||||
return res
|
||||
|
||||
def write(self, ids, vals):
|
||||
res = super(RuleGroup, self).write(ids, vals)
|
||||
# Restart the cache on the domain_get method of ir.rule
|
||||
self.pool.get('ir.rule').domain_get.reset()
|
||||
Pool().get('ir.rule').domain_get.reset()
|
||||
return res
|
||||
|
||||
RuleGroup()
|
||||
@@ -115,7 +115,7 @@ class Rule(ModelSQL, ModelView):
|
||||
if not recur:
|
||||
recur = []
|
||||
with Transaction().set_context(language='en_US'):
|
||||
obj_fields = self.pool.get(obj_name).fields_get()
|
||||
obj_fields = Pool().get(obj_name).fields_get()
|
||||
key = obj_fields.keys()
|
||||
key.sort()
|
||||
for k in key:
|
||||
@@ -158,12 +158,13 @@ class Rule(ModelSQL, ModelView):
|
||||
with Transaction().set_user(Transaction().context['user']):
|
||||
return self.domain_get(model_name)
|
||||
|
||||
rule_group_obj = self.pool.get('ir.rule.group')
|
||||
model_obj = self.pool.get('ir.model')
|
||||
rule_group_user_obj = self.pool.get('ir.rule.group-res.user')
|
||||
rule_group_group_obj = self.pool.get('ir.rule.group-res.group')
|
||||
user_group_obj = self.pool.get('res.user-res.group')
|
||||
user_obj = self.pool.get('res.user')
|
||||
pool = Pool()
|
||||
rule_group_obj = pool.get('ir.rule.group')
|
||||
model_obj = pool.get('ir.model')
|
||||
rule_group_user_obj = pool.get('ir.rule.group-res.user')
|
||||
rule_group_group_obj = pool.get('ir.rule.group-res.group')
|
||||
user_group_obj = pool.get('res.user-res.group')
|
||||
user_obj = pool.get('res.user')
|
||||
|
||||
cursor = Transaction().cursor
|
||||
cursor.execute('SELECT r.id FROM "' + self._table + '" r ' \
|
||||
@@ -173,21 +174,21 @@ class Rule(ModelSQL, ModelView):
|
||||
"WHERE m.model = %s "
|
||||
"AND g.perm_" + mode + " "
|
||||
"AND (g.id IN (" \
|
||||
'SELECT rule_group_id ' \
|
||||
'SELECT rule_group ' \
|
||||
'FROM "' + rule_group_user_obj._table + '" ' \
|
||||
"WHERE user_id = %s " \
|
||||
"UNION SELECT rule_group_id " \
|
||||
'WHERE "user" = %s ' \
|
||||
"UNION SELECT rule_group " \
|
||||
'FROM "' + rule_group_group_obj._table + '" g_rel ' \
|
||||
'JOIN "' + user_group_obj._table + '" u_rel ' \
|
||||
"ON (g_rel.group_id = u_rel.gid) " \
|
||||
"WHERE u_rel.uid = %s) " \
|
||||
'ON (g_rel."group" = u_rel."group") ' \
|
||||
'WHERE u_rel."user" = %s) ' \
|
||||
"OR default_p " \
|
||||
"OR g.global_p)",
|
||||
(model_name, Transaction().user, Transaction().user))
|
||||
ids = [x[0] for x in cursor.fetchall()]
|
||||
if not ids:
|
||||
return '', []
|
||||
obj = self.pool.get(model_name)
|
||||
obj = pool.get(model_name)
|
||||
clause = {}
|
||||
clause_global = {}
|
||||
operand2query = self._operand_get('res.user', level=1,
|
||||
@@ -222,14 +223,14 @@ class Rule(ModelSQL, ModelView):
|
||||
'WHERE m.model = %s ' \
|
||||
'AND (g.id NOT IN (SELECT rule_group ' \
|
||||
'FROM "' + self._table + '")) ' \
|
||||
'AND (g.id IN (SELECT rule_group_id ' \
|
||||
'AND (g.id IN (SELECT rule_group ' \
|
||||
'FROM "' + rule_group_user_obj._table + '" ' \
|
||||
'WHERE user_id = %s ' \
|
||||
'UNION SELECT rule_group_id ' \
|
||||
'WHERE "user" = %s ' \
|
||||
'UNION SELECT rule_group ' \
|
||||
'FROM "' + rule_group_group_obj._table + '" g_rel ' \
|
||||
'JOIN "' + user_group_obj._table + '" u_rel ' \
|
||||
'ON g_rel.group_id = u_rel.gid ' \
|
||||
'WHERE u_rel.uid = %s))',
|
||||
'ON g_rel."group" = u_rel."group" ' \
|
||||
'WHERE u_rel."user" = %s))',
|
||||
(model_name, user_id, user_id))
|
||||
fetchone = cursor.fetchone()
|
||||
if fetchone:
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
from string import Template
|
||||
import datetime
|
||||
import time
|
||||
@@ -8,6 +7,7 @@ from trytond.model import ModelView, ModelSQL, fields
|
||||
from trytond.tools import datetime_strftime
|
||||
from trytond.pyson import In, Eval, Not
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.pool import Pool
|
||||
|
||||
|
||||
class SequenceType(ModelSQL, ModelView):
|
||||
@@ -49,7 +49,7 @@ class Sequence(ModelSQL, ModelView):
|
||||
states={
|
||||
'invisible': Not(In(Eval('type'), ['incremental'])),
|
||||
}, depends=['type'])
|
||||
timestamp_rounding = fields.Integer('Timestamp Rounding', required=True,
|
||||
timestamp_rounding = fields.Float('Timestamp Rounding', required=True,
|
||||
states={
|
||||
'invisible': Not(In(Eval('type'),
|
||||
['decimal timestamp', 'hexadecimal timestamp'])),
|
||||
@@ -105,7 +105,8 @@ class Sequence(ModelSQL, ModelView):
|
||||
return Transaction().context.get('code', False)
|
||||
|
||||
def code_get(self):
|
||||
sequence_type_obj = self.pool.get('ir.sequence.type')
|
||||
pool = Pool()
|
||||
sequence_type_obj = pool.get('ir.sequence.type')
|
||||
sequence_type_ids = sequence_type_obj.search([])
|
||||
sequence_types = sequence_type_obj.browse(sequence_type_ids)
|
||||
return [(x.code, x.name) for x in sequence_types]
|
||||
@@ -131,7 +132,8 @@ class Sequence(ModelSQL, ModelView):
|
||||
return True
|
||||
|
||||
def _process(self, string, date=None):
|
||||
date_obj = self.pool.get('ir.date')
|
||||
pool = Pool()
|
||||
date_obj = pool.get('ir.date')
|
||||
if not date:
|
||||
date = date_obj.today()
|
||||
year = datetime_strftime(date, '%Y')
|
||||
|
||||
+51
-36
@@ -1,6 +1,5 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
import contextlib
|
||||
import base64
|
||||
try:
|
||||
@@ -17,6 +16,7 @@ try:
|
||||
from hashlib import md5
|
||||
except ImportError:
|
||||
from md5 import md5
|
||||
from functools import reduce
|
||||
from trytond.model import ModelView, ModelSQL, fields
|
||||
from trytond.model.cacheable import Cacheable
|
||||
from trytond.wizard import Wizard
|
||||
@@ -25,6 +25,7 @@ from trytond.tools import file_open, reduce_ids
|
||||
from trytond.backend import TableHandler, FIELDS
|
||||
from trytond.pyson import PYSONEncoder
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.pool import Pool
|
||||
|
||||
TRANSLATION_TYPE = [
|
||||
('field', 'Field'),
|
||||
@@ -143,7 +144,8 @@ class Translation(ModelSQL, ModelView, Cacheable):
|
||||
return [('id', 'in', [x[0] for x in cursor.fetchall()])]
|
||||
|
||||
def get_language(self):
|
||||
lang_obj = self.pool.get('ir.lang')
|
||||
pool = Pool()
|
||||
lang_obj = pool.get('ir.lang')
|
||||
lang_ids = lang_obj.search([])
|
||||
langs = lang_obj.browse(lang_ids)
|
||||
res = [(lang.code, lang.name) for lang in langs]
|
||||
@@ -153,8 +155,9 @@ class Translation(ModelSQL, ModelView, Cacheable):
|
||||
return md5((src or '').encode('utf-8')).hexdigest()
|
||||
|
||||
def _get_ids(self, name, ttype, lang, ids):
|
||||
model_fields_obj = self.pool.get('ir.model.field')
|
||||
model_obj = self.pool.get('ir.model')
|
||||
pool = Pool()
|
||||
model_fields_obj = pool.get('ir.model.field')
|
||||
model_obj = pool.get('ir.model')
|
||||
|
||||
translations, to_fetch = {}, []
|
||||
name = unicode(name)
|
||||
@@ -220,8 +223,9 @@ class Translation(ModelSQL, ModelView, Cacheable):
|
||||
return translations
|
||||
|
||||
def _set_ids(self, name, ttype, lang, ids, value):
|
||||
model_fields_obj = self.pool.get('ir.model.field')
|
||||
model_obj = self.pool.get('ir.model')
|
||||
pool = Pool()
|
||||
model_fields_obj = pool.get('ir.model.field')
|
||||
model_obj = pool.get('ir.model')
|
||||
|
||||
if lang == 'en_US':
|
||||
return 0
|
||||
@@ -262,7 +266,7 @@ class Translation(ModelSQL, ModelView, Cacheable):
|
||||
'fuzzy': False,
|
||||
})
|
||||
return len(ids)
|
||||
model_obj = self.pool.get(model_name)
|
||||
model_obj = pool.get(model_name)
|
||||
for record in model_obj.browse(ids):
|
||||
ids2 = self.search([
|
||||
('lang', '=', lang),
|
||||
@@ -439,7 +443,8 @@ class Translation(ModelSQL, ModelView, Cacheable):
|
||||
return super(Translation, self).write(ids, vals)
|
||||
|
||||
def translation_import(self, lang, module, datas):
|
||||
model_data_obj = self.pool.get('ir.model.data')
|
||||
pool = Pool()
|
||||
model_data_obj = pool.get('ir.model.data')
|
||||
model_data_ids = model_data_obj.search([
|
||||
('module', '=', module),
|
||||
])
|
||||
@@ -537,7 +542,8 @@ class Translation(ModelSQL, ModelView, Cacheable):
|
||||
return len(translation_ids)
|
||||
|
||||
def translation_export(self, lang, module):
|
||||
model_data_obj = self.pool.get('ir.model.data')
|
||||
pool = Pool()
|
||||
model_data_obj = pool.get('ir.model.data')
|
||||
|
||||
model_data_ids = model_data_obj.search([
|
||||
('module', '=', module),
|
||||
@@ -651,7 +657,9 @@ class ReportTranslationSet(Wizard):
|
||||
return strings
|
||||
|
||||
def _set_report_translation(self, data):
|
||||
report_obj = self.pool.get('ir.action.report')
|
||||
pool = Pool()
|
||||
report_obj = pool.get('ir.action.report')
|
||||
translation_obj = pool.get('ir.translation')
|
||||
|
||||
with Transaction().set_context(active_test=False):
|
||||
report_ids = report_obj.search([])
|
||||
@@ -713,7 +721,7 @@ class ReportTranslationSet(Wizard):
|
||||
strings += self._translate_report(document.documentElement)
|
||||
|
||||
for string in {}.fromkeys(strings).keys():
|
||||
src_md5 = self.get_src_md5(string)
|
||||
src_md5 = translation_obj.get_src_md5(string)
|
||||
done = False
|
||||
if string in trans_reports:
|
||||
del trans_reports[string]
|
||||
@@ -807,9 +815,10 @@ class TranslationClean(Wizard):
|
||||
}
|
||||
|
||||
def _clean_translation(self, data):
|
||||
translation_obj = self.pool.get('ir.translation')
|
||||
model_data_obj = self.pool.get('ir.model.data')
|
||||
report_obj = self.pool.get('ir.action.report')
|
||||
pool = Pool()
|
||||
translation_obj = pool.get('ir.translation')
|
||||
model_data_obj = pool.get('ir.model.data')
|
||||
report_obj = pool.get('ir.action.report')
|
||||
|
||||
offset = 0
|
||||
cursor = Transaction().cursor
|
||||
@@ -828,10 +837,10 @@ class TranslationClean(Wizard):
|
||||
except ValueError:
|
||||
to_delete.append(translation.id)
|
||||
continue
|
||||
if model_name not in self.pool.object_name_list():
|
||||
if model_name not in pool.object_name_list():
|
||||
to_delete.append(translation.id)
|
||||
continue
|
||||
model_obj = self.pool.get(model_name)
|
||||
model_obj = pool.get(model_name)
|
||||
if field_name not in model_obj._columns:
|
||||
to_delete.append(translation.id)
|
||||
continue
|
||||
@@ -841,11 +850,11 @@ class TranslationClean(Wizard):
|
||||
except ValueError:
|
||||
to_delete.append(translation.id)
|
||||
continue
|
||||
if model_name not in self.pool.object_name_list():
|
||||
if model_name not in pool.object_name_list():
|
||||
to_delete.append(translation.id)
|
||||
continue
|
||||
if translation.res_id:
|
||||
model_obj = self.pool.get(model_name)
|
||||
model_obj = pool.get(model_name)
|
||||
if field_name not in model_obj._columns:
|
||||
to_delete.append(translation.id)
|
||||
continue
|
||||
@@ -870,10 +879,10 @@ class TranslationClean(Wizard):
|
||||
except ValueError:
|
||||
to_delete.append(translation.id)
|
||||
continue
|
||||
if model_name not in self.pool.object_name_list():
|
||||
if model_name not in pool.object_name_list():
|
||||
to_delete.append(translation.id)
|
||||
continue
|
||||
model_obj = self.pool.get(model_name)
|
||||
model_obj = pool.get(model_name)
|
||||
if field_name not in model_obj._columns:
|
||||
to_delete.append(translation.id)
|
||||
continue
|
||||
@@ -890,7 +899,7 @@ class TranslationClean(Wizard):
|
||||
continue
|
||||
elif translation.type == 'view':
|
||||
model_name = translation.name
|
||||
if model_name not in self.pool.object_name_list():
|
||||
if model_name not in pool.object_name_list():
|
||||
to_delete.append(translation.id)
|
||||
continue
|
||||
elif translation.type == 'wizard_button':
|
||||
@@ -901,10 +910,10 @@ class TranslationClean(Wizard):
|
||||
to_delete.append(translation.id)
|
||||
continue
|
||||
if wizard_name not in \
|
||||
self.pool.object_name_list(type='wizard'):
|
||||
pool.object_name_list(type='wizard'):
|
||||
to_delete.append(translation.id)
|
||||
continue
|
||||
wizard = self.pool.get(wizard_name, type='wizard')
|
||||
wizard = pool.get(wizard_name, type='wizard')
|
||||
if not wizard:
|
||||
to_delete.append(translation.id)
|
||||
continue
|
||||
@@ -925,10 +934,10 @@ class TranslationClean(Wizard):
|
||||
except ValueError:
|
||||
to_delete.append(translation.id)
|
||||
continue
|
||||
if model_name not in self.pool.object_name_list():
|
||||
if model_name not in pool.object_name_list():
|
||||
to_delete.append(translation.id)
|
||||
continue
|
||||
model_obj = self.pool.get(model_name)
|
||||
model_obj = pool.get(model_name)
|
||||
if field_name not in model_obj._columns:
|
||||
to_delete.append(translation.id)
|
||||
continue
|
||||
@@ -961,8 +970,8 @@ class TranslationClean(Wizard):
|
||||
'search_function_missing',
|
||||
):
|
||||
continue
|
||||
if model_name in self.pool.object_name_list():
|
||||
model_obj = self.pool.get(model_name)
|
||||
if model_name in pool.object_name_list():
|
||||
model_obj = pool.get(model_name)
|
||||
errors = model_obj._error_messages.values() + \
|
||||
model_obj._sql_error_messages.values()
|
||||
for _, _, error in model_obj._sql_constraints:
|
||||
@@ -970,8 +979,8 @@ class TranslationClean(Wizard):
|
||||
if translation.src not in errors:
|
||||
to_delete.append(translation.id)
|
||||
continue
|
||||
elif model_name in self.pool.object_name_list(type='wizard'):
|
||||
wizard_obj = self.pool.get(model_name, type='wizard')
|
||||
elif model_name in pool.object_name_list(type='wizard'):
|
||||
wizard_obj = pool.get(model_name, type='wizard')
|
||||
errors = wizard_obj._error_messages.values()
|
||||
if translation.src not in errors:
|
||||
to_delete.append(translation.id)
|
||||
@@ -1005,7 +1014,8 @@ class TranslationUpdateInit(ModelView):
|
||||
return Transaction().context.get('language', False)
|
||||
|
||||
def get_language(self):
|
||||
lang_obj = self.pool.get('ir.lang')
|
||||
pool = Pool()
|
||||
lang_obj = pool.get('ir.lang')
|
||||
lang_ids = lang_obj.search([('translatable', '=', True)])
|
||||
langs = lang_obj.browse(lang_ids)
|
||||
res = [(lang.code, lang.name) for lang in langs if lang.code != 'en_US']
|
||||
@@ -1019,7 +1029,8 @@ class TranslationUpdate(Wizard):
|
||||
_name = "ir.translation.update"
|
||||
|
||||
def _update_translation(self, data):
|
||||
translation_obj = self.pool.get('ir.translation')
|
||||
pool = Pool()
|
||||
translation_obj = pool.get('ir.translation')
|
||||
cursor = Transaction().cursor
|
||||
cursor.execute('SELECT name, res_id, type, src, module ' \
|
||||
'FROM ir_translation ' \
|
||||
@@ -1107,8 +1118,9 @@ class TranslationUpdate(Wizard):
|
||||
return {}
|
||||
|
||||
def _action_translation_open(self, data):
|
||||
model_data_obj = self.pool.get('ir.model.data')
|
||||
act_window_obj = self.pool.get('ir.action.act_window')
|
||||
pool = Pool()
|
||||
model_data_obj = pool.get('ir.model.data')
|
||||
act_window_obj = pool.get('ir.action.act_window')
|
||||
|
||||
model_data_ids = model_data_obj.search([
|
||||
('fs_id', '=', 'act_translation_form'),
|
||||
@@ -1161,7 +1173,8 @@ class TranslationExportInit(ModelView):
|
||||
return Transaction().context.get('language', False)
|
||||
|
||||
def get_language(self):
|
||||
lang_obj = self.pool.get('ir.lang')
|
||||
pool = Pool()
|
||||
lang_obj = pool.get('ir.lang')
|
||||
lang_ids = lang_obj.search([
|
||||
('translatable', '=', True),
|
||||
])
|
||||
@@ -1170,7 +1183,8 @@ class TranslationExportInit(ModelView):
|
||||
return res
|
||||
|
||||
def get_module(self):
|
||||
module_obj = self.pool.get('ir.module.module')
|
||||
pool = Pool()
|
||||
module_obj = pool.get('ir.module.module')
|
||||
module_ids = module_obj.search([
|
||||
('state', 'in', ['installed', 'to upgrade', 'to remove']),
|
||||
])
|
||||
@@ -1195,7 +1209,8 @@ class TranslationExport(Wizard):
|
||||
_name = "ir.translation.export"
|
||||
|
||||
def _export_translation(self, data):
|
||||
translation_obj = self.pool.get('ir.translation')
|
||||
pool = Pool()
|
||||
translation_obj = pool.get('ir.translation')
|
||||
file_data = translation_obj.translation_export(data['form']['lang'],
|
||||
data['form']['module'])
|
||||
return {
|
||||
|
||||
@@ -9,6 +9,7 @@ from trytond.backend import TableHandler
|
||||
from trytond.tools import reduce_ids
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.cache import Cache
|
||||
from trytond.pool import Pool
|
||||
|
||||
|
||||
class Trigger(ModelSQL, ModelView):
|
||||
@@ -135,7 +136,8 @@ class Trigger(ModelSQL, ModelView):
|
||||
:param record: a BrowseRecord of the tested model
|
||||
:return: a boolean
|
||||
"""
|
||||
model_obj = self.pool.get(trigger.model.model)
|
||||
pool = Pool()
|
||||
model_obj = pool.get(trigger.model.model)
|
||||
env = {}
|
||||
env['current_date'] = datetime.datetime.today()
|
||||
env['time'] = time
|
||||
@@ -150,9 +152,10 @@ class Trigger(ModelSQL, ModelView):
|
||||
:param ids: the list of record ids triggered
|
||||
:param trigger_id: the trigger id
|
||||
"""
|
||||
trigger_log_obj = self.pool.get('ir.trigger.log')
|
||||
pool = Pool()
|
||||
trigger_log_obj = pool.get('ir.trigger.log')
|
||||
trigger = self.browse(trigger_id)
|
||||
model_obj = self.pool.get(trigger.action_model.model)
|
||||
model_obj = pool.get(trigger.action_model.model)
|
||||
cursor = Transaction().cursor
|
||||
|
||||
# Filter on limit_number
|
||||
@@ -220,11 +223,12 @@ class Trigger(ModelSQL, ModelView):
|
||||
'''
|
||||
Trigger time actions
|
||||
'''
|
||||
pool = Pool()
|
||||
trigger_ids = self.search([
|
||||
('on_time', '=', True),
|
||||
])
|
||||
for trigger in self.browse(trigger_ids):
|
||||
model_obj = self.pool.get(trigger.model.model)
|
||||
model_obj = pool.get(trigger.model.model)
|
||||
triggered_ids = []
|
||||
# TODO add a domain
|
||||
record_ids = model_obj.search([])
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of this
|
||||
# repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
|
||||
import os
|
||||
|
||||
|
||||
+51
-19
@@ -1,8 +1,8 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
from trytond.model import ModelView, ModelSQL, fields
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.pool import Pool
|
||||
|
||||
def one_in(i, j):
|
||||
"""Check the presence of an element of setA in setB
|
||||
@@ -58,6 +58,7 @@ CLIENT_ICONS = [(x, x) for x in (
|
||||
'tryton-system',
|
||||
'tryton-undo',
|
||||
'tryton-web-browser')]
|
||||
SEPARATOR = ' / '
|
||||
|
||||
|
||||
class UIMenu(ModelSQL, ModelView):
|
||||
@@ -70,9 +71,9 @@ class UIMenu(ModelSQL, ModelView):
|
||||
parent = fields.Many2One('ir.ui.menu', 'Parent Menu', select=1,
|
||||
ondelete='CASCADE')
|
||||
groups = fields.Many2Many('ir.ui.menu-res.group',
|
||||
'menu_id', 'gid', 'Groups')
|
||||
'menu', 'group', 'Groups')
|
||||
complete_name = fields.Function(fields.Char('Complete Name',
|
||||
order_field='name'), 'get_full_name')
|
||||
order_field='name'), 'get_rec_name', searcher='search_rec_name')
|
||||
icon = fields.Selection('list_icons', 'Icon')
|
||||
action = fields.Function(fields.Reference('Action',
|
||||
selection=[
|
||||
@@ -86,6 +87,14 @@ class UIMenu(ModelSQL, ModelView):
|
||||
def __init__(self):
|
||||
super(UIMenu, self).__init__()
|
||||
self._order.insert(0, ('sequence', 'ASC'))
|
||||
self._constraints += [
|
||||
('check_recursion', 'recursive_menu'),
|
||||
('check_name', 'wrong_name'),
|
||||
]
|
||||
self._error_messages.update({
|
||||
'recursive_menu': 'You can not create recursive menu!',
|
||||
'wrong_name': 'You can not use "%s" in name field!' % SEPARATOR,
|
||||
})
|
||||
|
||||
def default_icon(self):
|
||||
return 'tryton-open'
|
||||
@@ -97,24 +106,45 @@ class UIMenu(ModelSQL, ModelView):
|
||||
return True
|
||||
|
||||
def list_icons(self):
|
||||
icon_obj = self.pool.get('ir.ui.icon')
|
||||
pool = Pool()
|
||||
icon_obj = pool.get('ir.ui.icon')
|
||||
return sorted(CLIENT_ICONS
|
||||
+ [(name, name) for _, name in icon_obj.list_icons()])
|
||||
|
||||
def get_full_name(self, ids, name):
|
||||
res = {}
|
||||
def check_name(self, ids):
|
||||
for menu in self.browse(ids):
|
||||
res[menu.id] = self._get_one_full_name(menu)
|
||||
if SEPARATOR in menu.name:
|
||||
return False
|
||||
return True
|
||||
|
||||
def get_rec_name(self, ids, name):
|
||||
if not ids:
|
||||
return {}
|
||||
res = {}
|
||||
def _name(menu):
|
||||
if menu.id in res:
|
||||
return res[menu.id]
|
||||
elif menu.parent:
|
||||
return _name(menu.parent) + SEPARATOR + menu.name
|
||||
else:
|
||||
return menu.name
|
||||
for menu in self.browse(ids):
|
||||
res[menu.id] = _name(menu)
|
||||
return res
|
||||
|
||||
def _get_one_full_name(self, menu, level=6):
|
||||
if level <= 0:
|
||||
return '...'
|
||||
if menu.parent:
|
||||
parent_path = self._get_one_full_name(menu.parent, level-1) + "/"
|
||||
else:
|
||||
parent_path = ''
|
||||
return parent_path + menu.name
|
||||
def search_rec_name(self, name, clause):
|
||||
if isinstance(clause[2], basestring):
|
||||
values = clause[2].split(SEPARATOR)
|
||||
values.reverse()
|
||||
domain = []
|
||||
field = 'name'
|
||||
for name in values:
|
||||
domain.append((field, clause[1], name))
|
||||
field = 'parent.' + field
|
||||
ids = self.search(domain, order=[])
|
||||
return [('id', 'in', ids)]
|
||||
#TODO Handle list
|
||||
return [('name',) + tuple(clause[1:])]
|
||||
|
||||
def search(self, domain, offset=0, limit=None, order=None, count=False,
|
||||
query_string=False):
|
||||
@@ -137,7 +167,8 @@ class UIMenu(ModelSQL, ModelView):
|
||||
return res
|
||||
|
||||
def get_action(self, ids, name):
|
||||
action_keyword_obj = self.pool.get('ir.action.keyword')
|
||||
pool = Pool()
|
||||
action_keyword_obj = pool.get('ir.action.keyword')
|
||||
res = {}
|
||||
for menu_id in ids:
|
||||
res[menu_id] = False
|
||||
@@ -149,7 +180,7 @@ class UIMenu(ModelSQL, ModelView):
|
||||
for action_keyword in action_keyword_obj.browse(action_keyword_ids):
|
||||
model_id = int(
|
||||
action_keyword.model.split(',')[1].split(',')[0].strip('('))
|
||||
action_obj = self.pool.get(action_keyword.action.type)
|
||||
action_obj = pool.get(action_keyword.action.type)
|
||||
with Transaction().set_context(active_test=False):
|
||||
action_id = action_obj.search([
|
||||
('action', '=', action_keyword.action.id),
|
||||
@@ -164,7 +195,8 @@ class UIMenu(ModelSQL, ModelView):
|
||||
def set_action(self, ids, name, value):
|
||||
if not value:
|
||||
return
|
||||
action_keyword_obj = self.pool.get('ir.action.keyword')
|
||||
pool = Pool()
|
||||
action_keyword_obj = pool.get('ir.action.keyword')
|
||||
action_keyword_ids = []
|
||||
cursor = Transaction().cursor
|
||||
for i in range(0, len(ids), cursor.IN_MAX):
|
||||
@@ -180,7 +212,7 @@ class UIMenu(ModelSQL, ModelView):
|
||||
action_type, action_id = value.split(',')
|
||||
if not int(action_id):
|
||||
return
|
||||
action_obj = self.pool.get(action_type)
|
||||
action_obj = pool.get(action_type)
|
||||
action = action_obj.browse(int(action_id))
|
||||
for menu_id in ids:
|
||||
with Transaction().set_context(_timestamp=False):
|
||||
|
||||
+16
-6
@@ -24,7 +24,7 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="arch" type="xml">
|
||||
<![CDATA[
|
||||
<tree string="Menu" fill="1">
|
||||
<field name="rec_name" icon="icon"/>
|
||||
<field name="complete_name" icon="icon" select="1"/>
|
||||
</tree>
|
||||
]]>
|
||||
</field>
|
||||
@@ -50,7 +50,6 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="sequence"/>
|
||||
<label name="complete_name"/>
|
||||
<field name="complete_name" colspan="3"/>
|
||||
<separator name="groups" colspan="4"/>
|
||||
<field name="groups" colspan="4"/>
|
||||
</form>
|
||||
]]>
|
||||
@@ -69,14 +68,25 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="view" ref="menu_view_tree_tree"/>
|
||||
<field name="act_window" ref="act_menu_tree"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_menu_list">
|
||||
<field name="name">Menu</field>
|
||||
<field name="res_model">ir.ui.menu</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view"
|
||||
id="act_menu_form_view2">
|
||||
<field name="sequence" eval="2"/>
|
||||
id="act_menu_list_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="menu_view_list"/>
|
||||
<field name="act_window" ref="act_menu_list"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view"
|
||||
id="act_menu_list_view2">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view" ref="menu_view_form"/>
|
||||
<field name="act_window" ref="act_menu_tree"/>
|
||||
<field name="act_window" ref="act_menu_list"/>
|
||||
</record>
|
||||
|
||||
<menuitem parent="menu_ui"
|
||||
action="act_menu_tree" id="menu_menu_tree"/>
|
||||
action="act_menu_list" id="menu_menu_list"/>
|
||||
</data>
|
||||
</tryton>
|
||||
|
||||
+23
-14
@@ -1,6 +1,5 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
import os
|
||||
import logging
|
||||
from lxml import etree
|
||||
@@ -11,6 +10,7 @@ from trytond.pyson import PYSONEncoder, CONTEXT, Eval, Not, Bool, Equal
|
||||
from trytond.tools import safe_eval
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.wizard import Wizard
|
||||
from trytond.pool import Pool
|
||||
|
||||
|
||||
class View(ModelSQL, ModelView):
|
||||
@@ -66,7 +66,8 @@ class View(ModelSQL, ModelView):
|
||||
|
||||
def check_xml(self, ids):
|
||||
"Check XML"
|
||||
translation_obj = self.pool.get('ir.translation')
|
||||
pool = Pool()
|
||||
translation_obj = pool.get('ir.translation')
|
||||
cursor = Transaction().cursor
|
||||
views = self.browse(ids)
|
||||
for view in views:
|
||||
@@ -188,7 +189,8 @@ class View(ModelSQL, ModelView):
|
||||
def delete(self, ids):
|
||||
res = super(View, self).delete(ids)
|
||||
# Restart the cache
|
||||
for _, model in self.pool.iterobject():
|
||||
pool = Pool()
|
||||
for _, model in pool.iterobject():
|
||||
try:
|
||||
model.fields_view_get.reset()
|
||||
except Exception:
|
||||
@@ -198,7 +200,8 @@ class View(ModelSQL, ModelView):
|
||||
def create(self, vals):
|
||||
res = super(View, self).create(vals)
|
||||
# Restart the cache
|
||||
for _, model in self.pool.iterobject():
|
||||
pool = Pool()
|
||||
for _, model in pool.iterobject():
|
||||
try:
|
||||
model.fields_view_get.reset()
|
||||
except Exception:
|
||||
@@ -208,7 +211,8 @@ class View(ModelSQL, ModelView):
|
||||
def write(self, ids, vals):
|
||||
res = super(View, self).write(ids, vals)
|
||||
# Restart the cache
|
||||
for _, model in self.pool.iterobject():
|
||||
pool = Pool()
|
||||
for _, model in pool.iterobject():
|
||||
try:
|
||||
model.fields_view_get.reset()
|
||||
except Exception:
|
||||
@@ -274,8 +278,9 @@ class AddShortcut(Wizard):
|
||||
}
|
||||
|
||||
def _add_shortcut(self, data):
|
||||
view_sc_obj = self.pool.get('ir.ui.view_sc')
|
||||
model_obj = self.pool.get(data['model'])
|
||||
pool = Pool()
|
||||
view_sc_obj = pool.get('ir.ui.view_sc')
|
||||
model_obj = pool.get(data['model'])
|
||||
|
||||
record = model_obj.browse(data['id'])
|
||||
view_sc_obj.create({
|
||||
@@ -304,8 +309,9 @@ class OpenShortcut(Wizard):
|
||||
}
|
||||
|
||||
def _open(self, data):
|
||||
view_sc_obj = self.pool.get('ir.ui.view_sc')
|
||||
action_keyword_obj = self.pool.get('ir.action.keyword')
|
||||
pool = Pool()
|
||||
view_sc_obj = pool.get('ir.ui.view_sc')
|
||||
action_keyword_obj = pool.get('ir.action.keyword')
|
||||
|
||||
view_sc = view_sc_obj.browse(data['id'])
|
||||
models = (
|
||||
@@ -323,7 +329,7 @@ class OpenShortcut(Wizard):
|
||||
if not action_keyword_ids:
|
||||
return {}
|
||||
action_keyword = action_keyword_obj.browse(action_keyword_ids[0])
|
||||
action_obj = self.pool.get(action_keyword.action.type)
|
||||
action_obj = pool.get(action_keyword.action.type)
|
||||
action_ids = action_obj.search([
|
||||
('action.id', '=', action_keyword.action.id),
|
||||
])
|
||||
@@ -352,37 +358,40 @@ class ViewTreeWidth(ModelSQL, ModelView):
|
||||
})
|
||||
|
||||
def delete(self, ids):
|
||||
pool = Pool()
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
views = self.browse(ids)
|
||||
for view in views:
|
||||
# Restart the cache
|
||||
try:
|
||||
self.pool.get(view.model).fields_view_get.reset()
|
||||
pool.get(view.model).fields_view_get.reset()
|
||||
except Exception:
|
||||
pass
|
||||
res = super(ViewTreeWidth, self).delete(ids)
|
||||
return res
|
||||
|
||||
def create(self, vals):
|
||||
pool = Pool()
|
||||
res = super(ViewTreeWidth, self).create(vals)
|
||||
if 'model' in vals:
|
||||
model = vals['model']
|
||||
# Restart the cache
|
||||
try:
|
||||
self.pool.get(model).fields_view_get.reset()
|
||||
pool.get(model).fields_view_get.reset()
|
||||
except Exception:
|
||||
pass
|
||||
return res
|
||||
|
||||
def write(self, ids, vals):
|
||||
pool = Pool()
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
views = self.browse(ids)
|
||||
for view in views:
|
||||
# Restart the cache
|
||||
try:
|
||||
self.pool.get(view.model).fields_view_get.reset()
|
||||
pool.get(view.model).fields_view_get.reset()
|
||||
except Exception:
|
||||
pass
|
||||
res = super(ViewTreeWidth, self).write(ids, vals)
|
||||
@@ -390,7 +399,7 @@ class ViewTreeWidth(ModelSQL, ModelView):
|
||||
for view in views:
|
||||
# Restart the cache
|
||||
try:
|
||||
self.pool.get(view.model).fields_view_get.reset()
|
||||
pool.get(view.model).fields_view_get.reset()
|
||||
except Exception:
|
||||
pass
|
||||
return res
|
||||
|
||||
+165
-147
@@ -1,11 +1,14 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
import contextlib
|
||||
from itertools import islice, ifilter, ifilterfalse
|
||||
from itertools import islice, ifilter, ifilterfalse, chain
|
||||
from trytond.model import fields
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.const import BROWSE_FIELD_TRESHOLD
|
||||
from trytond.pool import Pool
|
||||
from trytond.cache import LRUDict
|
||||
from trytond.const import MODEL_CACHE_SIZE, RECORD_CACHE_SIZE, \
|
||||
BROWSE_FIELD_TRESHOLD
|
||||
|
||||
|
||||
class BrowseRecordList(list):
|
||||
'''
|
||||
@@ -46,164 +49,177 @@ class BrowseRecord(object):
|
||||
An object that represents record defined by a ORM object.
|
||||
'''
|
||||
|
||||
def __init__(self, record_id, model, local_cache=None):
|
||||
def __init__(self, record_id, model, ids, local_cache):
|
||||
assert isinstance(ids, list)
|
||||
if ids:
|
||||
assert record_id in ids
|
||||
self._cursor = Transaction().cursor
|
||||
self._user = Transaction().user
|
||||
self._id = record_id
|
||||
self.id = record_id
|
||||
self._model = model
|
||||
self._model_name = self._model._name
|
||||
self._context = Transaction().context
|
||||
self._pool = Pool()
|
||||
self._ids = ids
|
||||
|
||||
cache = self._cursor.get_cache(self._context)
|
||||
cache.setdefault(model._name, {})
|
||||
cache.setdefault('_language_cache', {})
|
||||
if model._name not in cache:
|
||||
cache[model._name] = LRUDict(RECORD_CACHE_SIZE)
|
||||
self._data = cache[model._name]
|
||||
if not record_id in self._data:
|
||||
self._data[record_id] = {'id': record_id}
|
||||
self._cache = cache
|
||||
if local_cache is None:
|
||||
local_cache = {}
|
||||
self._local_cache = local_cache
|
||||
self._local_cache.setdefault(model._name, {})
|
||||
self._local_cache.setdefault('_language_cache', {})
|
||||
self._local_data = self._local_cache[model._name]
|
||||
if not record_id in self._local_data:
|
||||
self._local_data[record_id] = {}
|
||||
assert isinstance(local_cache, LRUDict)
|
||||
self._local_data = local_cache
|
||||
|
||||
def __getitem__(self, name):
|
||||
if name == 'id':
|
||||
return self._id
|
||||
if name == 'setLang':
|
||||
return self.setLang
|
||||
if not self._data[self._id].has_key(name) \
|
||||
and not self._local_data[self._id].has_key(name):
|
||||
# build the list of fields we will fetch
|
||||
# Access to LRUDict must be atomic
|
||||
result = self._local_data.get(self.id, {}).get(name)
|
||||
if (self.id in self._local_data
|
||||
and name in self._local_data[self.id]):
|
||||
return result
|
||||
result = self._data.get(self.id, {}).get(name)
|
||||
if self.id in self._data and name in self._data[self.id]:
|
||||
return result
|
||||
|
||||
# fetch the definition of the field which was asked for
|
||||
if name in self._model._columns:
|
||||
col = self._model._columns[name]
|
||||
elif name in self._model._inherit_fields:
|
||||
col = self._model._inherit_fields[name][2]
|
||||
elif hasattr(self._model, name):
|
||||
return getattr(self._model, name)
|
||||
else:
|
||||
raise Exception('Error', 'Programming error: field "%s" ' \
|
||||
'does not exist in model "%s"!' \
|
||||
% (name, self._model._name))
|
||||
# build the list of fields we will fetch
|
||||
# fetch the definition of the field which was asked for
|
||||
if name in self._model._columns:
|
||||
col = self._model._columns[name]
|
||||
elif name in self._model._inherit_fields:
|
||||
col = self._model._inherit_fields[name][2]
|
||||
elif hasattr(self._model, name):
|
||||
return getattr(self._model, name)
|
||||
else:
|
||||
raise Exception('Error', 'Programming error: field "%s" ' \
|
||||
'does not exist in model "%s"!' \
|
||||
% (name, self._model._name))
|
||||
|
||||
ffields = {}
|
||||
if col.loading == 'eager':
|
||||
field_access_obj = self._model.pool.get('ir.model.field.access')
|
||||
fread_accesses = {}
|
||||
for inherit_name in self._model._inherits:
|
||||
inherit_obj = self._model.pool.get(inherit_name)
|
||||
fread_accesses.update(field_access_obj.check(inherit_name,
|
||||
inherit_obj._columns.keys(), 'read', access=True))
|
||||
fread_accesses.update(field_access_obj.check(self._model._name,
|
||||
self._model._columns.keys(), 'read', access=True))
|
||||
to_remove = set(x for x, y in fread_accesses.iteritems()
|
||||
if not y and x != name)
|
||||
ffields = {}
|
||||
if col.loading == 'eager':
|
||||
field_access_obj = self._pool.get('ir.model.field.access')
|
||||
fread_accesses = {}
|
||||
for inherit_name in self._model._inherits:
|
||||
inherit_obj = self._pool.get(inherit_name)
|
||||
fread_accesses.update(field_access_obj.check(inherit_name,
|
||||
inherit_obj._columns.keys(), 'read', access=True))
|
||||
fread_accesses.update(field_access_obj.check(self._model._name,
|
||||
self._model._columns.keys(), 'read', access=True))
|
||||
to_remove = set(x for x, y in fread_accesses.iteritems()
|
||||
if not y and x != name)
|
||||
|
||||
threshold = BROWSE_FIELD_TRESHOLD
|
||||
inherit_threshold = threshold - len(self._model._columns)
|
||||
threshold = BROWSE_FIELD_TRESHOLD
|
||||
inherit_threshold = threshold - len(self._model._columns)
|
||||
|
||||
def not_cached(item):
|
||||
fname, field = item
|
||||
return (fname not in self._data[self._id]
|
||||
and fname not in self._local_data[self._id])
|
||||
def to_load(item):
|
||||
fname, field = item
|
||||
return (field.loading == 'eager'
|
||||
and fname not in to_remove)
|
||||
def overrided(item):
|
||||
fname, field = item
|
||||
return fname in self._model._columns
|
||||
def not_cached(item):
|
||||
fname, field = item
|
||||
return (fname not in self._data.get(self.id, {})
|
||||
and fname not in self._local_data.get(self.id, {}))
|
||||
def to_load(item):
|
||||
fname, field = item
|
||||
return (field.loading == 'eager'
|
||||
and fname not in to_remove)
|
||||
def overrided(item):
|
||||
fname, field = item
|
||||
return fname in self._model._columns
|
||||
|
||||
if inherit_threshold > 0:
|
||||
ifields = ((fname, field)
|
||||
for fname, (_, _, field) in
|
||||
self._model._inherit_fields.iteritems())
|
||||
ifields = ifilterfalse(overrided,
|
||||
ifilter(to_load,
|
||||
ifilter(not_cached, ifields)))
|
||||
ifields = islice(ifields, 0, inherit_threshold)
|
||||
ffields.update(ifields)
|
||||
threshold -= inherit_threshold
|
||||
|
||||
ifields = ifilter(to_load,
|
||||
ifilter(not_cached,
|
||||
self._model._columns.iteritems()))
|
||||
ifields = islice(ifields, 0, threshold)
|
||||
if inherit_threshold > 0:
|
||||
ifields = ((fname, field)
|
||||
for fname, (_, _, field) in
|
||||
self._model._inherit_fields.iteritems())
|
||||
ifields = ifilterfalse(overrided,
|
||||
ifilter(to_load,
|
||||
ifilter(not_cached, ifields)))
|
||||
ifields = islice(ifields, 0, inherit_threshold)
|
||||
ffields.update(ifields)
|
||||
threshold -= inherit_threshold
|
||||
|
||||
ffields[name] = col
|
||||
ifields = ifilter(to_load,
|
||||
ifilter(not_cached,
|
||||
self._model._columns.iteritems()))
|
||||
ifields = islice(ifields, 0, threshold)
|
||||
ffields.update(ifields)
|
||||
|
||||
# add datetime_field
|
||||
for field in ffields:
|
||||
if hasattr(field, 'datetime_field') and field.datetime_field:
|
||||
if field.datetime_field in self._model._columns:
|
||||
date_field = self._model._columns[field.datetime_field]
|
||||
else:
|
||||
date_field = self._model._inherit_fields[
|
||||
field.datetime_field][2]
|
||||
ffields[field.datetime_field] = datetime_field
|
||||
ffields[name] = col
|
||||
|
||||
if len(self._data) <= self._cursor.IN_MAX:
|
||||
iterids = self._data.iterkeys()
|
||||
else:
|
||||
iterids = self._local_data.iterkeys()
|
||||
ids = [x for x in iterids \
|
||||
if not self._data.setdefault(x, {}).has_key(name) \
|
||||
and not self._local_data.setdefault(x, {}).has_key(name)]
|
||||
# read the data
|
||||
with contextlib.nested(Transaction().set_cursor(self._cursor),
|
||||
Transaction().set_user(self._user),
|
||||
Transaction().set_context(self._context)):
|
||||
datas = self._model.read(ids, ffields.keys())
|
||||
# add datetime_field
|
||||
for field in ffields:
|
||||
if hasattr(field, 'datetime_field') and field.datetime_field:
|
||||
if field.datetime_field in self._model._columns:
|
||||
date_field = self._model._columns[field.datetime_field]
|
||||
else:
|
||||
date_field = self._model._inherit_fields[
|
||||
field.datetime_field][2]
|
||||
ffields[field.datetime_field] = datetime_field
|
||||
|
||||
# create browse records for 'remote' models
|
||||
for data in datas:
|
||||
for i, j in ffields.iteritems():
|
||||
model = None
|
||||
if (hasattr(j, 'model_name') and
|
||||
j.model_name in
|
||||
self._model.pool.object_name_list()):
|
||||
model = self._model.pool.get(j.model_name)
|
||||
elif hasattr(j, 'get_target'):
|
||||
model = j.get_target(self._model.pool)
|
||||
if model and j._type in ('many2one', 'one2one'):
|
||||
if (not data[i]
|
||||
and not (isinstance(data[i], (int, long))
|
||||
and not isinstance(data[i],
|
||||
type(False)))):
|
||||
data[i] = BrowseRecordNull()
|
||||
else:
|
||||
_datetime = None
|
||||
if (hasattr(j, 'datetime_field')
|
||||
and j.datetime_field):
|
||||
_datetime = data[j.datetime_field]
|
||||
with Transaction().set_context(
|
||||
_datetime=_datetime):
|
||||
data[i] = BrowseRecord(data[i], model,
|
||||
local_cache=self._local_cache)
|
||||
elif (model
|
||||
and j._type in ('one2many', 'many2many')
|
||||
and len(data[i])):
|
||||
def filter_(id_):
|
||||
if (id_ in self._local_data
|
||||
and name in self._local_data[id_]):
|
||||
return False
|
||||
if id_ in self._data and name in self._data[id_]:
|
||||
return False
|
||||
return True
|
||||
index = self._ids.index(self.id)
|
||||
ids = chain(islice(self._ids, index, None),
|
||||
islice(self._ids, 0, max(index - 1, 0)))
|
||||
ids = list(islice(ifilter(filter_, ids), self._cursor.IN_MAX))
|
||||
model2ids = {}
|
||||
model2cache = {}
|
||||
# read the data
|
||||
with contextlib.nested(Transaction().set_cursor(self._cursor),
|
||||
Transaction().set_user(self._user),
|
||||
Transaction().set_context(self._context)):
|
||||
# create browse records for 'remote' models
|
||||
for data in self._model.read(ids, ffields.keys()):
|
||||
for i, j in ffields.iteritems():
|
||||
model = None
|
||||
if (hasattr(j, 'model_name') and
|
||||
j.model_name in
|
||||
self._pool.object_name_list()):
|
||||
model = self._pool.get(j.model_name)
|
||||
elif hasattr(j, 'get_target'):
|
||||
model = j.get_target()
|
||||
if model and j._type in ('many2one', 'one2one'):
|
||||
if (not data[i]
|
||||
and not (isinstance(data[i], (int, long))
|
||||
and not isinstance(data[i],
|
||||
type(False)))):
|
||||
data[i] = BrowseRecordNull()
|
||||
else:
|
||||
_datetime = None
|
||||
if hasattr(j, 'datetime_field') and j.datetime_field:
|
||||
if (hasattr(j, 'datetime_field')
|
||||
and j.datetime_field):
|
||||
_datetime = data[j.datetime_field]
|
||||
with Transaction().set_context(
|
||||
_datetime=_datetime):
|
||||
data[i] = BrowseRecordList(BrowseRecord(
|
||||
x, model, local_cache=self._local_cache)
|
||||
for x in data[i])
|
||||
if isinstance(j, fields.Function):
|
||||
self._local_data.setdefault(data['id'], {})[i] = data[i]
|
||||
del data[i]
|
||||
self._data[data['id']].update(data)
|
||||
if name in self._local_data[self._id]:
|
||||
return self._local_data[self._id][name]
|
||||
return self._data[self._id][name]
|
||||
ids = model2ids.setdefault(model, [])
|
||||
ids.append(data[i])
|
||||
local_cache = model2cache.setdefault(model,
|
||||
LRUDict(RECORD_CACHE_SIZE))
|
||||
data[i] = BrowseRecord(data[i], model,
|
||||
ids, local_cache)
|
||||
elif (model
|
||||
and j._type in ('one2many', 'many2many')
|
||||
and len(data[i])):
|
||||
_datetime = None
|
||||
if hasattr(j, 'datetime_field') and j.datetime_field:
|
||||
_datetime = data[j.datetime_field]
|
||||
with Transaction().set_context(
|
||||
_datetime=_datetime):
|
||||
ids = model2ids.setdefault(model, [])
|
||||
ids.extend(data[i])
|
||||
local_cache = model2cache.setdefault(model,
|
||||
LRUDict(RECORD_CACHE_SIZE))
|
||||
data[i] = BrowseRecordList(
|
||||
BrowseRecord(x, model, ids, local_cache)
|
||||
for x in data[i])
|
||||
if isinstance(j, fields.Function):
|
||||
if data['id'] == self.id and i == name:
|
||||
result = data[i]
|
||||
self._local_data.setdefault(data['id'], {})[i] = data[i]
|
||||
del data[i]
|
||||
self._data.setdefault(data['id'], {}).update(data)
|
||||
if data['id'] == self.id and name in data:
|
||||
result = data[name]
|
||||
return result
|
||||
|
||||
def __getattr__(self, name):
|
||||
# TODO raise an AttributeError exception
|
||||
@@ -218,16 +234,16 @@ class BrowseRecord(object):
|
||||
return name in self
|
||||
|
||||
def __int__(self):
|
||||
return self._id
|
||||
return self.id
|
||||
|
||||
def __str__(self):
|
||||
return "BrowseRecord(%s, %d)" % (self._model_name, self._id)
|
||||
return "BrowseRecord(%s, %d)" % (self._model_name, self.id)
|
||||
|
||||
def __eq__(self, other):
|
||||
return (self._model_name, self._id) == (other._model_name, other._id)
|
||||
return (self._model_name, self.id) == (other._model_name, other.id)
|
||||
|
||||
def __ne__(self, other):
|
||||
return (self._model_name, self._id) != (other._model_name, other._id)
|
||||
return (self._model_name, self.id) != (other._model_name, other.id)
|
||||
|
||||
# we need to define __unicode__ even though we've already defined __str__
|
||||
# because we have overridden __getattr__
|
||||
@@ -235,7 +251,7 @@ class BrowseRecord(object):
|
||||
return unicode(str(self))
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self._model_name, self._id))
|
||||
return hash((self._model_name, self.id))
|
||||
|
||||
def __nonzero__(self):
|
||||
return True
|
||||
@@ -246,22 +262,23 @@ class BrowseRecord(object):
|
||||
self._context = self._context.copy()
|
||||
prev_lang = self._context.get('language') or 'en_US'
|
||||
self._context['language'] = lang
|
||||
for cache in (self._cache, self._local_cache):
|
||||
language_cache = cache['_language_cache']
|
||||
for cache in (self._cache, self._local_data):
|
||||
language_cache = cache.setdefault('_language_cache', {})
|
||||
for model in cache:
|
||||
if model == '_language_cache':
|
||||
continue
|
||||
for record_id in cache[model]:
|
||||
language_cache.setdefault(prev_lang,
|
||||
{}).setdefault(model, {})[record_id] = \
|
||||
cache[model][record_id]
|
||||
LRUDict(MODEL_CACHE_SIZE)).setdefault(model,
|
||||
LRUDict(RECORD_CACHE_SIZE))[record_id] = \
|
||||
cache[model][record_id]
|
||||
if lang in language_cache \
|
||||
and model in language_cache[lang] \
|
||||
and record_id in language_cache[lang][model]:
|
||||
cache[model][record_id] = \
|
||||
language_cache[lang][model][record_id]
|
||||
else:
|
||||
cache[model][record_id] = {'id': record_id}
|
||||
cache[model][record_id] = {}
|
||||
|
||||
def get_eval(self, name):
|
||||
res = self[name]
|
||||
@@ -280,6 +297,7 @@ class EvalEnvironment(dict):
|
||||
super(EvalEnvironment, self).__init__()
|
||||
self._record = record
|
||||
self._model = model
|
||||
self._pool = Pool()
|
||||
|
||||
def __getitem__(self, item):
|
||||
if item.startswith('_parent_'):
|
||||
@@ -288,7 +306,7 @@ class EvalEnvironment(dict):
|
||||
model_name = self._model._columns[field].model_name
|
||||
else:
|
||||
model_name = self._model._inherit_fields[field][2].model_name
|
||||
model = self._model.pool.get(model_name)
|
||||
model = self._pool.get(model_name)
|
||||
return EvalEnvironment(self._record[field], model)
|
||||
if item in self._model._columns \
|
||||
or item in self._model._inherit_fields:
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
from itertools import chain
|
||||
from trytond.model.fields.field import Field
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.pool import Pool
|
||||
|
||||
|
||||
class Many2Many(Field):
|
||||
@@ -63,7 +64,12 @@ class Many2Many(Field):
|
||||
for i in ids:
|
||||
res[i] = []
|
||||
|
||||
relation_obj = model.pool.get(self.relation_name)
|
||||
if self.order is None:
|
||||
order = [(self.target, 'ASC')]
|
||||
else:
|
||||
order = self.order
|
||||
|
||||
relation_obj = Pool().get(self.relation_name)
|
||||
|
||||
relation_ids = []
|
||||
for i in range(0, len(ids), Transaction().cursor.IN_MAX):
|
||||
@@ -71,12 +77,11 @@ class Many2Many(Field):
|
||||
relation_ids.append(relation_obj.search([
|
||||
(self.origin, 'in', sub_ids),
|
||||
(self.target + '.id', '!=', False),
|
||||
], order=self.order))
|
||||
], order=order))
|
||||
relation_ids = list(chain(*relation_ids))
|
||||
|
||||
for relation in relation_obj.read(relation_ids,
|
||||
[self.origin, self.target]):
|
||||
res[relation[self.origin]].append(relation[self.target])
|
||||
for relation in relation_obj.browse(relation_ids):
|
||||
res[relation[self.origin].id].append(relation[self.target].id)
|
||||
return res
|
||||
|
||||
def set(self, ids, model, name, values):
|
||||
@@ -97,8 +102,8 @@ class Many2Many(Field):
|
||||
'''
|
||||
if not values:
|
||||
return
|
||||
relation_obj = model.pool.get(self.relation_name)
|
||||
target_obj = self.get_target(model.pool)
|
||||
relation_obj = Pool().get(self.relation_name)
|
||||
target_obj = self.get_target()
|
||||
for act in values:
|
||||
if act[0] == 'create':
|
||||
for record_id in ids:
|
||||
@@ -173,20 +178,19 @@ class Many2Many(Field):
|
||||
else:
|
||||
raise Exception('Bad arguments')
|
||||
|
||||
def get_target(self, pool):
|
||||
def get_target(self):
|
||||
'''
|
||||
Return the target model.
|
||||
|
||||
:param pool: The pool
|
||||
:return: A Model
|
||||
'''
|
||||
relation_obj = pool.get(self.relation_name)
|
||||
relation_obj = Pool().get(self.relation_name)
|
||||
if not self.target:
|
||||
return relation_obj
|
||||
if self.target in relation_obj._columns:
|
||||
target_obj = pool.get(
|
||||
target_obj = Pool().get(
|
||||
relation_obj._columns[self.target].model_name)
|
||||
else:
|
||||
target_obj = pool.get(
|
||||
target_obj = Pool().get(
|
||||
relation_obj._inherit_fields[self.target][2].model_name)
|
||||
return target_obj
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
from itertools import chain
|
||||
from trytond.model.fields.field import Field
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.pool import Pool
|
||||
|
||||
def add_remove_validate(value):
|
||||
if value:
|
||||
@@ -70,13 +71,14 @@ class One2Many(Field):
|
||||
:param values: a dictionary with the read values
|
||||
:return: a dictionary with ids as key and values as value
|
||||
'''
|
||||
pool = Pool()
|
||||
res = {}
|
||||
for i in ids:
|
||||
res[i] = []
|
||||
ids2 = []
|
||||
for i in range(0, len(ids), Transaction().cursor.IN_MAX):
|
||||
sub_ids = ids[i:i + Transaction().cursor.IN_MAX]
|
||||
ids2.append(model.pool.get(self.model_name).search([
|
||||
ids2.append(pool.get(self.model_name).search([
|
||||
(self.field, 'in', sub_ids),
|
||||
], order=self.order))
|
||||
|
||||
@@ -91,12 +93,12 @@ class One2Many(Field):
|
||||
ids3.append(i)
|
||||
|
||||
if ids3:
|
||||
for i in model.pool.get(self.model_name).read(ids3, [self.field]):
|
||||
for i in pool.get(self.model_name).read(ids3, [self.field]):
|
||||
res[i[self.field]].append(i['id'])
|
||||
|
||||
index_of_ids2 = dict((i, index) for index, i in enumerate(chain(*ids2)))
|
||||
for val in res.values():
|
||||
val.sort(lambda x, y: cmp(index_of_ids2[x], index_of_ids2[y]))
|
||||
val.sort(key=lambda x: index_of_ids2[x])
|
||||
return res
|
||||
|
||||
def set(self, ids, model, name, values):
|
||||
@@ -116,9 +118,10 @@ class One2Many(Field):
|
||||
(``unlink_all``),
|
||||
(``set``, ``<ids>``)
|
||||
'''
|
||||
pool = Pool()
|
||||
if not values:
|
||||
return
|
||||
model = model.pool.get(self.model_name)
|
||||
model = pool.get(self.model_name)
|
||||
for act in values:
|
||||
if act[0] == 'create':
|
||||
for record_id in ids:
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
from trytond.model.fields.many2many import Many2Many
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.pool import Pool
|
||||
|
||||
|
||||
class One2One(Many2Many):
|
||||
@@ -35,7 +36,8 @@ class One2One(Many2Many):
|
||||
:param name: A string with the name of the field
|
||||
:param value: The id to link
|
||||
'''
|
||||
relation_obj = model.pool.get(self.relation_name)
|
||||
pool = Pool()
|
||||
relation_obj = pool.get(self.relation_name)
|
||||
relation_ids = relation_obj.search([
|
||||
(self.origin, 'in', ids),
|
||||
])
|
||||
|
||||
@@ -6,6 +6,7 @@ from trytond.model.fields.function import Function
|
||||
from trytond.model.fields.field import Field
|
||||
from trytond import backend
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.pool import Pool
|
||||
|
||||
|
||||
class Property(Function):
|
||||
@@ -34,7 +35,8 @@ class Property(Function):
|
||||
:param values:
|
||||
:return: a dictionary with ids as key and values as value
|
||||
'''
|
||||
property_obj = model.pool.get('ir.property')
|
||||
pool = Pool()
|
||||
property_obj = pool.get('ir.property')
|
||||
res = property_obj.get(name, model._name, ids)
|
||||
return res
|
||||
|
||||
@@ -48,7 +50,8 @@ class Property(Function):
|
||||
:param name: The name of the field.
|
||||
:param value: The value to set.
|
||||
'''
|
||||
property_obj = model.pool.get('ir.property')
|
||||
pool = Pool()
|
||||
property_obj = pool.get('ir.property')
|
||||
return property_obj.set(name, model._name, ids,
|
||||
(value and getattr(self, 'model_name', '') + ',' + str(value)) or
|
||||
False)
|
||||
@@ -60,10 +63,11 @@ class Property(Function):
|
||||
:param clause: The search domain clause. See ModelStorage.search
|
||||
:return: New list of domain.
|
||||
'''
|
||||
rule_obj = model.pool.get('ir.rule')
|
||||
property_obj = model.pool.get('ir.property')
|
||||
model_obj = model.pool.get('ir.model')
|
||||
field_obj = model.pool.get('ir.model.field')
|
||||
pool = Pool()
|
||||
rule_obj = pool.get('ir.rule')
|
||||
property_obj = pool.get('ir.property')
|
||||
model_obj = pool.get('ir.model')
|
||||
field_obj = pool.get('ir.model.field')
|
||||
cursor = Transaction().cursor
|
||||
|
||||
field_class = backend.FIELDS[self._type]
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
import contextlib
|
||||
from trytond.model.fields.field import Field
|
||||
from trytond.tools import safe_eval
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.pool import Pool
|
||||
|
||||
|
||||
class Reference(Field):
|
||||
@@ -42,6 +42,7 @@ class Reference(Field):
|
||||
:param values: a dictionary with the read values
|
||||
:return: a dictionary with ids as key and values as value
|
||||
'''
|
||||
pool = Pool()
|
||||
if values is None:
|
||||
values = {}
|
||||
res = {}
|
||||
@@ -76,10 +77,10 @@ class Reference(Field):
|
||||
with contextlib.nested(Transaction().set_context(active_test=False),
|
||||
Transaction().set_user(0)):
|
||||
for ref_model, (ref_ids, ids) in ref_to_check.iteritems():
|
||||
if ref_model not in model.pool.object_name_list():
|
||||
if ref_model not in pool.object_name_list():
|
||||
res.update(dict((i, False) for i in ids))
|
||||
continue
|
||||
ref_obj = model.pool.get(ref_model)
|
||||
ref_obj = pool.get(ref_model)
|
||||
ref_ids = ref_obj.search([
|
||||
('id', 'in', list(ref_ids)),
|
||||
], order=[])
|
||||
|
||||
+34
-27
@@ -2,6 +2,7 @@
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
|
||||
import copy
|
||||
import collections
|
||||
from trytond.model import fields
|
||||
from trytond.error import WarningErrorMixin
|
||||
from trytond.pool import Pool
|
||||
@@ -16,7 +17,6 @@ class Model(WarningErrorMixin):
|
||||
_name = None
|
||||
_inherits = {}
|
||||
_description = ''
|
||||
pool = None #XXX change to avoid collision with field
|
||||
__columns = None
|
||||
__xxx2many_targets = None
|
||||
__defaults = None
|
||||
@@ -54,7 +54,7 @@ class Model(WarningErrorMixin):
|
||||
fields_names += self._inherit_fields.keys()
|
||||
for field_name in fields_names:
|
||||
default_method = getattr(self, 'default_%s' % field_name, False)
|
||||
if callable(default_method):
|
||||
if isinstance(default_method, collections.Callable):
|
||||
res[field_name] = default_method
|
||||
self.__defaults = res
|
||||
return res
|
||||
@@ -98,16 +98,19 @@ class Model(WarningErrorMixin):
|
||||
for attribute in ('on_change', 'on_change_with', 'autocomplete'):
|
||||
function_name = '%s_%s' % (attribute, field_name)
|
||||
if (getattr(field, attribute, False)
|
||||
and callable(getattr(self, function_name, False))):
|
||||
and isinstance(getattr(self, function_name, False),
|
||||
collections.Callable)):
|
||||
self._rpc.setdefault(function_name, False)
|
||||
|
||||
def __getattr__(self, name):
|
||||
pool = Pool()
|
||||
# Search if a function exists in inherits parents
|
||||
for model_name, field_name in self._inherits.iteritems():
|
||||
model_obj = self.pool.get(model_name)
|
||||
if hasattr(model_obj, name) and \
|
||||
callable(getattr(model_obj, name)):
|
||||
return getattr(model_obj, name)
|
||||
model_obj = pool.get(model_name)
|
||||
if (hasattr(model_obj, name)
|
||||
and isinstance(getattr(model_obj, name),
|
||||
collections.Callable)):
|
||||
return getattr(model_obj, name)
|
||||
raise AttributeError(name)
|
||||
|
||||
def _inherits_reload(self):
|
||||
@@ -115,19 +118,20 @@ class Model(WarningErrorMixin):
|
||||
Reconstruct _inherit_fields
|
||||
"""
|
||||
res = {}
|
||||
pool = Pool()
|
||||
for model in self._inherits:
|
||||
res.update(self.pool.get(model)._inherit_fields)
|
||||
for field_name in self.pool.get(model)._columns.keys():
|
||||
res.update(pool.get(model)._inherit_fields)
|
||||
for field_name in pool.get(model)._columns.keys():
|
||||
res[field_name] = (model, self._inherits[model],
|
||||
self.pool.get(model)._columns[field_name])
|
||||
for field_name in self.pool.get(model)._inherit_fields.keys():
|
||||
pool.get(model)._columns[field_name])
|
||||
for field_name in pool.get(model)._inherit_fields.keys():
|
||||
res[field_name] = (model, self._inherits[model],
|
||||
self.pool.get(model)._inherit_fields[field_name][2])
|
||||
pool.get(model)._inherit_fields[field_name][2])
|
||||
self._inherit_fields = res
|
||||
self._reset_xxx2many_targets()
|
||||
# Update objects that uses this one to update their _inherits fields
|
||||
for obj_name in self.pool.object_name_list():
|
||||
obj = self.pool.get(obj_name)
|
||||
for obj_name in pool.object_name_list():
|
||||
obj = pool.get(obj_name)
|
||||
if self._name in obj._inherits:
|
||||
obj._inherits_reload()
|
||||
|
||||
@@ -148,7 +152,7 @@ class Model(WarningErrorMixin):
|
||||
continue
|
||||
if hasattr(field, 'get_target'):
|
||||
try:
|
||||
model_name = field.get_target(self.pool)._name
|
||||
model_name = field.get_target()._name
|
||||
except KeyError:
|
||||
to_cache = False
|
||||
continue
|
||||
@@ -166,7 +170,7 @@ class Model(WarningErrorMixin):
|
||||
continue
|
||||
if hasattr(field, 'get_target'):
|
||||
try:
|
||||
model_name = field.get_target(self.pool)._name
|
||||
model_name = field.get_target()._name
|
||||
except KeyError:
|
||||
to_cache = False
|
||||
continue
|
||||
@@ -186,7 +190,7 @@ class Model(WarningErrorMixin):
|
||||
|
||||
:param module_name: the module name
|
||||
"""
|
||||
translation_obj = self.pool.get('ir.translation')
|
||||
translation_obj = Pool().get('ir.translation')
|
||||
|
||||
cursor = Transaction().cursor
|
||||
# Add model in ir_model
|
||||
@@ -388,7 +392,8 @@ class Model(WarningErrorMixin):
|
||||
:return: a dictionary with field name as key
|
||||
and default value as value
|
||||
'''
|
||||
property_obj = self.pool.get('ir.property')
|
||||
pool = Pool()
|
||||
property_obj = pool.get('ir.property')
|
||||
value = {}
|
||||
|
||||
# get the default values defined in the object
|
||||
@@ -407,7 +412,7 @@ class Model(WarningErrorMixin):
|
||||
if (with_rec_name
|
||||
and field._type in ('many2one',)
|
||||
and value.get(field_name)):
|
||||
obj = self.pool.get(field.model_name)
|
||||
obj = pool.get(field.model_name)
|
||||
if 'rec_name' in obj._columns:
|
||||
value[field_name + '.rec_name'] = obj.browse(
|
||||
value[field_name]).rec_name
|
||||
@@ -427,10 +432,11 @@ class Model(WarningErrorMixin):
|
||||
:param value: a dictionnary with the default value
|
||||
:return: a new dictionnary of default value
|
||||
"""
|
||||
pool = Pool()
|
||||
res = value.copy()
|
||||
val = {}
|
||||
for i in self._inherits.keys():
|
||||
val.update(self.pool.get(i)._default_on_change(value))
|
||||
val.update(pool.get(i)._default_on_change(value))
|
||||
for field in value.keys():
|
||||
if field in self._columns:
|
||||
if self._columns[field].on_change:
|
||||
@@ -443,7 +449,7 @@ class Model(WarningErrorMixin):
|
||||
args[arg] = args[arg][0]
|
||||
val.update(getattr(self, 'on_change_' + field)(args))
|
||||
if self._columns[field]._type in ('one2many',):
|
||||
obj = self.pool.get(self._columns[field].model_name)
|
||||
obj = pool.get(self._columns[field].model_name)
|
||||
for val2 in res[field]:
|
||||
val2.update(obj._default_on_change(val2))
|
||||
res.update(val)
|
||||
@@ -457,12 +463,13 @@ class Model(WarningErrorMixin):
|
||||
:return: a dictionary with field name as key and definition as value
|
||||
"""
|
||||
res = {}
|
||||
translation_obj = self.pool.get('ir.translation')
|
||||
model_access_obj = self.pool.get('ir.model.access')
|
||||
field_access_obj = self.pool.get('ir.model.field.access')
|
||||
pool = Pool()
|
||||
translation_obj = pool.get('ir.translation')
|
||||
model_access_obj = pool.get('ir.model.access')
|
||||
field_access_obj = pool.get('ir.model.field.access')
|
||||
|
||||
for parent in self._inherits:
|
||||
res.update(self.pool.get(parent).fields_get(fields_names))
|
||||
res.update(pool.get(parent).fields_get(fields_names))
|
||||
write_access = model_access_obj.check(self._name, 'write',
|
||||
raise_exception=False)
|
||||
|
||||
@@ -576,8 +583,8 @@ class Model(WarningErrorMixin):
|
||||
if hasattr(self._columns[field], 'model_name'):
|
||||
relation = copy.copy(self._columns[field].model_name)
|
||||
else:
|
||||
relation = copy.copy(self._columns[field].get_target(
|
||||
self.pool)._name)
|
||||
relation = copy.copy(
|
||||
self._columns[field].get_target()._name)
|
||||
res[field]['relation'] = relation
|
||||
res[field]['domain'] = copy.copy(self._columns[field].domain)
|
||||
res[field]['context'] = copy.copy(self._columns[field].context)
|
||||
|
||||
+69
-55
@@ -1,17 +1,20 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
import contextlib
|
||||
import datetime
|
||||
import re
|
||||
from functools import reduce
|
||||
from decimal import Decimal
|
||||
from itertools import islice
|
||||
from trytond.model import ModelStorage
|
||||
from trytond.model import fields
|
||||
from trytond.backend import FIELDS, TableHandler
|
||||
from trytond.backend import DatabaseIntegrityError, Database
|
||||
from trytond.tools import reduce_ids
|
||||
from trytond.const import OPERATORS
|
||||
from trytond.const import OPERATORS, RECORD_CACHE_SIZE
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.pool import Pool
|
||||
from trytond.cache import LRUDict
|
||||
_RE_UNIQUE = re.compile('UNIQUE\s*\((.*)\)', re.I)
|
||||
_RE_CHECK = re.compile('CHECK\s*\((.*)\)', re.I)
|
||||
|
||||
@@ -43,6 +46,8 @@ class ModelSQL(ModelStorage):
|
||||
if self.table_query():
|
||||
return
|
||||
|
||||
pool = Pool()
|
||||
|
||||
# create/update table in the database
|
||||
table = TableHandler(Transaction().cursor, self, module_name)
|
||||
if self._history:
|
||||
@@ -133,7 +138,7 @@ class ModelSQL(ModelStorage):
|
||||
if field.model_name in ('res.user', 'res.group'):
|
||||
ref = field.model_name.replace('.','_')
|
||||
else:
|
||||
ref = self.pool.get(field.model_name)._table
|
||||
ref = pool.get(field.model_name)._table
|
||||
table.add_fk(field_name, ref, field.ondelete)
|
||||
|
||||
table.index_action(
|
||||
@@ -202,10 +207,11 @@ class ModelSQL(ModelStorage):
|
||||
'''
|
||||
Return the default value for sequence field.
|
||||
'''
|
||||
pool = Pool()
|
||||
table = self._table
|
||||
if 'sequence' not in self._columns:
|
||||
for model in self._inherits:
|
||||
model_obj = self.pool.get(model)
|
||||
model_obj = pool.get(model)
|
||||
if 'sequence' in model_obj._columns:
|
||||
table = model_obj._table
|
||||
break
|
||||
@@ -229,6 +235,7 @@ class ModelSQL(ModelStorage):
|
||||
def create(self, values):
|
||||
super(ModelSQL, self).create(values)
|
||||
cursor = Transaction().cursor
|
||||
pool = Pool()
|
||||
|
||||
if self.table_query():
|
||||
return False
|
||||
@@ -284,11 +291,10 @@ class ModelSQL(ModelStorage):
|
||||
continue
|
||||
if inherits in tocreate:
|
||||
tocreate[inherits][i] = values[i]
|
||||
if i not in self._columns:
|
||||
del values[i]
|
||||
del values[i]
|
||||
|
||||
for inherits in tocreate:
|
||||
inherits_obj = self.pool.get(inherits)
|
||||
inherits_obj = pool.get(inherits)
|
||||
inherits_id = inherits_obj.create(tocreate[inherits])
|
||||
values[self._inherits[inherits]] = inherits_id
|
||||
|
||||
@@ -354,7 +360,7 @@ class ModelSQL(ModelStorage):
|
||||
field_name))
|
||||
if isinstance(field, fields.Many2One) \
|
||||
and values.get(field_name):
|
||||
model_obj = self.pool.get(field.model_name)
|
||||
model_obj = pool.get(field.model_name)
|
||||
create_records = Transaction().create_records.get(
|
||||
field.model_name, set())
|
||||
delete_records = Transaction().delete_records.get(
|
||||
@@ -375,7 +381,7 @@ class ModelSQL(ModelStorage):
|
||||
self.raise_user_error(error)
|
||||
raise
|
||||
|
||||
domain1, domain2 = self.pool.get('ir.rule').domain_get(self._name,
|
||||
domain1, domain2 = pool.get('ir.rule').domain_get(self._name,
|
||||
mode='create')
|
||||
if domain1:
|
||||
cursor.execute('SELECT id FROM "' + self._table + '" ' \
|
||||
@@ -388,7 +394,7 @@ class ModelSQL(ModelStorage):
|
||||
|
||||
for field in values:
|
||||
if getattr(self._columns[field], 'translate', False):
|
||||
self.pool.get('ir.translation')._set_ids(
|
||||
pool.get('ir.translation')._set_ids(
|
||||
self._name + ',' + field, 'model',
|
||||
Transaction().language, [id_new], values[field])
|
||||
|
||||
@@ -417,8 +423,9 @@ class ModelSQL(ModelStorage):
|
||||
return id_new
|
||||
|
||||
def read(self, ids, fields_names=None):
|
||||
rule_obj = self.pool.get('ir.rule')
|
||||
translation_obj = self.pool.get('ir.translation')
|
||||
pool = Pool()
|
||||
rule_obj = pool.get('ir.rule')
|
||||
translation_obj = pool.get('ir.translation')
|
||||
super(ModelSQL, self).read(ids, fields_names=fields_names)
|
||||
cursor = Transaction().cursor
|
||||
|
||||
@@ -561,7 +568,7 @@ class ModelSQL(ModelStorage):
|
||||
for field_related in fields_related[inherit_field]:
|
||||
inherit_related_fields.append(
|
||||
inherit_field + '.' + field_related)
|
||||
res2 = self.pool.get(table).read([x[field] for x in res],
|
||||
res2 = pool.get(table).read([x[field] for x in res],
|
||||
fields_names=inherits_fields + inherit_related_fields)
|
||||
|
||||
res3 = {}
|
||||
@@ -633,9 +640,9 @@ class ModelSQL(ModelStorage):
|
||||
fields_related2values.setdefault(field, {})
|
||||
if self._columns[field]._type in ('many2one', 'one2one'):
|
||||
if hasattr(self._columns[field], 'model_name'):
|
||||
obj = self.pool.get(self._columns[field].model_name)
|
||||
obj = pool.get(self._columns[field].model_name)
|
||||
else:
|
||||
obj = self._columns[field].get_target(self.pool)
|
||||
obj = self._columns[field].get_target()
|
||||
if hasattr(self._columns[field], 'datetime_field') \
|
||||
and self._columns[field].datetime_field:
|
||||
for record in res:
|
||||
@@ -669,7 +676,7 @@ class ModelSQL(ModelStorage):
|
||||
record_id = int(record_id)
|
||||
if not record_id:
|
||||
continue
|
||||
obj = self.pool.get(model_name)
|
||||
obj = pool.get(model_name)
|
||||
record2 = obj.read(record_id, fields_related[field])
|
||||
del record2['id']
|
||||
fields_related2values[field][record_id] = record2
|
||||
@@ -708,6 +715,8 @@ class ModelSQL(ModelStorage):
|
||||
|
||||
def write(self, ids, values):
|
||||
cursor = Transaction().cursor
|
||||
pool = Pool()
|
||||
translation_obj = pool.get('ir.translation')
|
||||
|
||||
# Call before cursor cache cleaning
|
||||
trigger_eligibles = self.trigger_write_get_eligibles(
|
||||
@@ -757,7 +766,7 @@ class ModelSQL(ModelStorage):
|
||||
cursor.execute("SELECT id " \
|
||||
'FROM "' + self._table + '" ' \
|
||||
'WHERE ' + ' OR '.join(
|
||||
(clause,) * (len(args)/2)), args)
|
||||
(clause,) * (len(args) // 2)), args)
|
||||
if cursor.fetchone():
|
||||
raise Exception('ConcurrencyException',
|
||||
'Records were modified in the meanwhile')
|
||||
@@ -816,7 +825,7 @@ class ModelSQL(ModelStorage):
|
||||
upd1.append(Transaction().user)
|
||||
upd1.append(datetime.datetime.now())
|
||||
|
||||
domain1, domain2 = self.pool.get('ir.rule').domain_get(self._name,
|
||||
domain1, domain2 = pool.get('ir.rule').domain_get(self._name,
|
||||
mode='write')
|
||||
if domain1:
|
||||
domain1 = ' AND (' + domain1 + ') '
|
||||
@@ -869,7 +878,7 @@ class ModelSQL(ModelStorage):
|
||||
field_name))
|
||||
if isinstance(field, fields.Many2One) \
|
||||
and values[field_name]:
|
||||
model_obj = self.pool.get(field.model_name)
|
||||
model_obj = pool.get(field.model_name)
|
||||
create_records = Transaction().create_records.get(
|
||||
field.model_name, set())
|
||||
delete_records = Transaction().delete_records.get(
|
||||
@@ -892,7 +901,7 @@ class ModelSQL(ModelStorage):
|
||||
|
||||
for field in direct:
|
||||
if getattr(self._columns[field], 'translate', False):
|
||||
self.pool.get('ir.translation')._set_ids(
|
||||
translation_obj._set_ids(
|
||||
self._name + ',' + field, 'model',
|
||||
Transaction().language, ids, values[field])
|
||||
|
||||
@@ -925,7 +934,7 @@ class ModelSQL(ModelStorage):
|
||||
for val in updend:
|
||||
if self._inherit_fields[val][0] == table:
|
||||
values2[val] = values[val]
|
||||
self.pool.get(table).write(nids, values2)
|
||||
pool.get(table).write(nids, values2)
|
||||
|
||||
self._validate(ids)
|
||||
|
||||
@@ -951,6 +960,7 @@ class ModelSQL(ModelStorage):
|
||||
|
||||
def delete(self, ids):
|
||||
cursor = Transaction().cursor
|
||||
pool = Pool()
|
||||
if not ids:
|
||||
return True
|
||||
|
||||
@@ -1006,7 +1016,7 @@ class ModelSQL(ModelStorage):
|
||||
foreign_keys_tocheck = []
|
||||
foreign_keys_toupdate = []
|
||||
foreign_keys_todelete = []
|
||||
for _, model in self.pool.iterobject():
|
||||
for _, model in pool.iterobject():
|
||||
if hasattr(model, 'table_query') \
|
||||
and model.table_query():
|
||||
continue
|
||||
@@ -1027,7 +1037,7 @@ class ModelSQL(ModelStorage):
|
||||
|
||||
Transaction().delete.setdefault(self._name, set()).update(ids)
|
||||
|
||||
domain1, domain2 = self.pool.get('ir.rule').domain_get(self._name,
|
||||
domain1, domain2 = pool.get('ir.rule').domain_get(self._name,
|
||||
mode='delete')
|
||||
if domain1:
|
||||
domain1 = ' AND (' + domain1 + ') '
|
||||
@@ -1123,7 +1133,8 @@ class ModelSQL(ModelStorage):
|
||||
|
||||
def search(self, domain, offset=0, limit=None, order=None, count=False,
|
||||
query_string=False):
|
||||
rule_obj = self.pool.get('ir.rule')
|
||||
pool = Pool()
|
||||
rule_obj = pool.get('ir.rule')
|
||||
cursor = Transaction().cursor
|
||||
|
||||
# Get domain clauses
|
||||
@@ -1196,11 +1207,11 @@ class ModelSQL(ModelStorage):
|
||||
|
||||
datas = cursor.dictfetchmany(cursor.IN_MAX)
|
||||
cache = cursor.get_cache()
|
||||
cache.setdefault(self._name, {})
|
||||
cache.setdefault(self._name, LRUDict(RECORD_CACHE_SIZE))
|
||||
delete_records = Transaction().delete_records.setdefault(self._name,
|
||||
set())
|
||||
keys = None
|
||||
for data in datas:
|
||||
for data in islice(datas, 0, cache.size_limit):
|
||||
if data['id'] in delete_records:
|
||||
continue
|
||||
if not keys:
|
||||
@@ -1215,8 +1226,7 @@ class ModelSQL(ModelStorage):
|
||||
continue
|
||||
for k in keys:
|
||||
del data[k]
|
||||
cache[self._name].setdefault(data['id'], {})
|
||||
cache[self._name][data['id']].update(data)
|
||||
cache[self._name].setdefault(data['id'], {}).update(data)
|
||||
|
||||
if len(datas) >= cursor.IN_MAX:
|
||||
select_fields2 = [select_fields[0]]
|
||||
@@ -1284,6 +1294,7 @@ class ModelSQL(ModelStorage):
|
||||
return qu1, qu2, tables, tables_args
|
||||
|
||||
def __search_domain_oper(self, domain, tables, tables_args):
|
||||
pool = Pool()
|
||||
operator = 'AND'
|
||||
if len(domain) and isinstance(domain[0], basestring):
|
||||
if domain[0] not in ('AND', 'OR'):
|
||||
@@ -1323,6 +1334,7 @@ class ModelSQL(ModelStorage):
|
||||
return qu1, qu2
|
||||
|
||||
def __search_domain_calc(self, domain, tables, tables_args):
|
||||
pool = Pool()
|
||||
domain = domain[:]
|
||||
cursor = Transaction().cursor
|
||||
|
||||
@@ -1336,7 +1348,7 @@ class ModelSQL(ModelStorage):
|
||||
table = self
|
||||
fargs = domain[i][0].split('.', 1)
|
||||
if fargs[0] in self._inherit_fields:
|
||||
itable = self.pool.get(self._inherit_fields[fargs[0]][0])
|
||||
itable = pool.get(self._inherit_fields[fargs[0]][0])
|
||||
table_query = ''
|
||||
table_arg = []
|
||||
if itable.table_query():
|
||||
@@ -1344,7 +1356,7 @@ class ModelSQL(ModelStorage):
|
||||
table_query = '(' + table_query + ') AS '
|
||||
table_join = 'LEFT JOIN ' + table_query + \
|
||||
'"' + itable._table + '" ON ' \
|
||||
'"%s".id = "%s".%s' % (itable._table, self._table,
|
||||
'"%s".id = "%s"."%s"' % (itable._table, self._table,
|
||||
self._inherits[itable._name])
|
||||
if table_join not in tables:
|
||||
tables.append(table_join)
|
||||
@@ -1354,11 +1366,11 @@ class ModelSQL(ModelStorage):
|
||||
if not fargs[0] in self._inherit_fields:
|
||||
raise Exception('ValidateError', 'Field "%s" doesn\'t ' \
|
||||
'exist on "%s"' % (fargs[0], self._name))
|
||||
table = self.pool.get(self._inherit_fields[fargs[0]][0])
|
||||
table = pool.get(self._inherit_fields[fargs[0]][0])
|
||||
field = table._columns.get(fargs[0], False)
|
||||
if len(fargs) > 1:
|
||||
if field._type == 'many2one':
|
||||
target_obj = self.pool.get(field.model_name)
|
||||
target_obj = pool.get(field.model_name)
|
||||
if hasattr(field, 'search'):
|
||||
domain.extend([(fargs[0], 'in', target_obj.search([
|
||||
(fargs[1], domain[i][1], domain[i][2]),
|
||||
@@ -1372,11 +1384,11 @@ class ModelSQL(ModelStorage):
|
||||
continue
|
||||
elif field._type in ('one2one', 'many2many', 'one2many'):
|
||||
if hasattr(field, 'model_name'):
|
||||
target_obj = self.pool.get(field.model_name)
|
||||
target_obj = pool.get(field.model_name)
|
||||
else:
|
||||
target_obj = field.get_target(self.pool)
|
||||
target_obj = field.get_target()
|
||||
if hasattr(field, 'relation_name'):
|
||||
relation_obj = self.pool.get(field.relation_name)
|
||||
relation_obj = pool.get(field.relation_name)
|
||||
origin, target = field.origin, field.target
|
||||
else:
|
||||
relation_obj = target_obj
|
||||
@@ -1403,7 +1415,7 @@ class ModelSQL(ModelStorage):
|
||||
clause = domain.pop(i)
|
||||
domain.extend(field.search(table, clause[0], clause))
|
||||
elif field._type == 'one2many':
|
||||
field_obj = self.pool.get(field.model_name)
|
||||
field_obj = pool.get(field.model_name)
|
||||
|
||||
if isinstance(domain[i][2], basestring):
|
||||
# get the ids of the records of the "distant" resource
|
||||
@@ -1459,9 +1471,9 @@ class ModelSQL(ModelStorage):
|
||||
elif field._type in ('many2many', 'one2one'):
|
||||
# XXX must find a solution for long id list
|
||||
if hasattr(field, 'model_name'):
|
||||
target_obj = self.pool.get(field.model_name)
|
||||
target_obj = pool.get(field.model_name)
|
||||
else:
|
||||
target_obj = field.get_target(self.pool)
|
||||
target_obj = field.get_target()
|
||||
if domain[i][1] in ('child_of', 'not child_of'):
|
||||
if isinstance(domain[i][2], basestring):
|
||||
ids2 = [x[0] for x in target_obj.search([
|
||||
@@ -1489,7 +1501,7 @@ class ModelSQL(ModelStorage):
|
||||
ids2 = target_obj.search([
|
||||
(domain[i][3], 'child_of', ids2),
|
||||
], order=[])
|
||||
relation_obj = self.pool.get(field.relation_name)
|
||||
relation_obj = pool.get(field.relation_name)
|
||||
red_sql, red_ids = reduce_ids('"' + field.target + '"',
|
||||
ids2)
|
||||
query1 = 'SELECT "' + field.origin + '" ' \
|
||||
@@ -1510,7 +1522,7 @@ class ModelSQL(ModelStorage):
|
||||
table, domain[i][0]))
|
||||
else:
|
||||
if isinstance(domain[i][2], bool):
|
||||
relation_obj = self.pool.get(field.relation_name)
|
||||
relation_obj = pool.get(field.relation_name)
|
||||
query1 = 'SELECT "' + field.origin + '" ' \
|
||||
'FROM "' + relation_obj._table + '" '\
|
||||
'WHERE "' + field.origin + '" IS NOT NULL'
|
||||
@@ -1524,7 +1536,7 @@ class ModelSQL(ModelStorage):
|
||||
target_field = 'rec_name'
|
||||
else:
|
||||
target_field = 'id'
|
||||
relation_obj = self.pool.get(field.relation_name)
|
||||
relation_obj = pool.get(field.relation_name)
|
||||
|
||||
query1, query2 = target_obj.search([
|
||||
(target_field, domain[i][1], domain[i][2]),
|
||||
@@ -1539,7 +1551,7 @@ class ModelSQL(ModelStorage):
|
||||
# XXX must find a solution for long id list
|
||||
if domain[i][1] in ('child_of', 'not child_of'):
|
||||
if isinstance(domain[i][2], basestring):
|
||||
field_obj = self.pool.get(field.model_name)
|
||||
field_obj = pool.get(field.model_name)
|
||||
ids2 = [x[0] for x in field_obj.search([
|
||||
('rec_name', 'like', domain[i][2]),
|
||||
], order=[])]
|
||||
@@ -1562,7 +1574,7 @@ class ModelSQL(ModelStorage):
|
||||
raise Exception('Error', 'Programming error: ' \
|
||||
'child_of on field "%s" is not allowed!' % \
|
||||
(domain[i][0],))
|
||||
ids2 = self.pool.get(field.model_name).search([
|
||||
ids2 = pool.get(field.model_name).search([
|
||||
(domain[i][3], 'child_of', ids2),
|
||||
], order=[])
|
||||
if domain[i][1] == 'child_of':
|
||||
@@ -1599,9 +1611,9 @@ class ModelSQL(ModelStorage):
|
||||
ids2, table, domain[i][0]), table)
|
||||
else:
|
||||
if isinstance(domain[i][2], basestring):
|
||||
field_obj = self.pool.get(field.model_name)
|
||||
field_obj = pool.get(field.model_name)
|
||||
res_ids = field_obj.search([
|
||||
(field_obj._rec_name, domain[i][1], domain[i][2]),
|
||||
('rec_name', domain[i][1], domain[i][2]),
|
||||
], order=[])
|
||||
domain[i] = (domain[i][0], 'in', res_ids, table)
|
||||
else:
|
||||
@@ -1652,7 +1664,7 @@ class ModelSQL(ModelStorage):
|
||||
table_query, table_args = table.table_query()
|
||||
table_query = '(' + table_query + ') AS '
|
||||
|
||||
translation_obj = self.pool.get('ir.translation')
|
||||
translation_obj = pool.get('ir.translation')
|
||||
|
||||
qu1, qu2, tables, table_args = \
|
||||
translation_obj.search_domain([
|
||||
@@ -1803,6 +1815,7 @@ class ModelSQL(ModelStorage):
|
||||
return qu1, qu2
|
||||
|
||||
def _order_calc(self, field, otype):
|
||||
pool = Pool()
|
||||
order_by = []
|
||||
tables = []
|
||||
tables_args = {}
|
||||
@@ -1820,7 +1833,7 @@ class ModelSQL(ModelStorage):
|
||||
field_name = self._columns[field].order_field
|
||||
|
||||
if isinstance(self._columns[field], fields.Many2One):
|
||||
obj = self.pool.get(self._columns[field].model_name)
|
||||
obj = pool.get(self._columns[field].model_name)
|
||||
table_name = obj._table
|
||||
link_field = field
|
||||
field_name = None
|
||||
@@ -1836,7 +1849,7 @@ class ModelSQL(ModelStorage):
|
||||
otype)
|
||||
table_join = 'LEFT JOIN "' + table_name + '" AS ' \
|
||||
'"' + table_name + '.' + link_field + '" ON ' \
|
||||
'"%s.%s".id = "%s".%s' % (table_name, link_field,
|
||||
'"%s.%s".id = "%s"."%s"' % (table_name, link_field,
|
||||
self._table, link_field)
|
||||
for i in range(len(order_by)):
|
||||
if table_name in order_by[i]:
|
||||
@@ -1855,12 +1868,12 @@ class ModelSQL(ModelStorage):
|
||||
|
||||
obj2 = None
|
||||
if obj._rec_name in obj._inherit_fields.keys():
|
||||
obj2 = self.pool.get(
|
||||
obj2 = pool.get(
|
||||
obj._inherit_fields[obj._rec_name][0])
|
||||
field_name = obj._rec_name
|
||||
|
||||
if obj._order_name in obj._inherit_fields.keys():
|
||||
obj2 = self.pool.get(
|
||||
obj2 = pool.get(
|
||||
obj._inherit_fields[obj._order_name][0])
|
||||
field_name = obj._order_name
|
||||
|
||||
@@ -1872,7 +1885,7 @@ class ModelSQL(ModelStorage):
|
||||
|
||||
table_join = 'LEFT JOIN "' + table_name + '" AS ' \
|
||||
'"' + table_name + '.' + link_field + '" ON ' \
|
||||
'"%s.%s".id = "%s".%s' % \
|
||||
'"%s.%s".id = "%s"."%s"' % \
|
||||
(table_name, link_field, self._table, link_field)
|
||||
for i in range(len(order_by)):
|
||||
if table_name in order_by[i]:
|
||||
@@ -1891,7 +1904,7 @@ class ModelSQL(ModelStorage):
|
||||
|
||||
table_join2 = 'LEFT JOIN "' + table_name2 + '" AS ' \
|
||||
'"' + table_name2 + '.' + link_field2 + '" ON ' \
|
||||
'"%s.%s".id = "%s.%s".%s' % \
|
||||
'"%s.%s".id = "%s.%s"."%s"' % \
|
||||
(table_name2, link_field2, table_name, link_field,
|
||||
link_field2)
|
||||
for i in range(len(order_by)):
|
||||
@@ -1994,18 +2007,19 @@ class ModelSQL(ModelStorage):
|
||||
return order_by, tables, tables_args
|
||||
|
||||
if field in self._inherit_fields.keys():
|
||||
obj = self.pool.get(self._inherit_fields[field][0])
|
||||
obj = pool.get(self._inherit_fields[field][0])
|
||||
table_name = obj._table
|
||||
link_field = self._inherits[obj._name]
|
||||
order_by, tables, tables_args = obj._order_calc(field, otype)
|
||||
table_join = 'LEFT JOIN "' + table_name + '" ON ' \
|
||||
'"%s".id = "%s".%s' % \
|
||||
'"%s".id = "%s"."%s"' % \
|
||||
(table_name, self._table, link_field)
|
||||
if table_join not in tables:
|
||||
tables.insert(0, table_join)
|
||||
return order_by, tables, tables_args
|
||||
|
||||
raise Exception('Error', 'Wrong field name (%s) in order!' % field)
|
||||
raise Exception('Error', 'Wrong field name (%s) for %s in order!' %
|
||||
(field, self._name))
|
||||
|
||||
def _rebuild_tree(self, parent, parent_id, left):
|
||||
'''
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
|
||||
from __future__ import with_statement
|
||||
import datetime
|
||||
import time
|
||||
from decimal import Decimal
|
||||
@@ -12,6 +11,9 @@ try:
|
||||
except ImportError:
|
||||
import StringIO
|
||||
import csv
|
||||
from functools import reduce
|
||||
import traceback
|
||||
import sys
|
||||
from trytond.model import Model
|
||||
from trytond.model import fields
|
||||
from trytond.model.browse import BrowseRecordList, BrowseRecord, \
|
||||
@@ -19,8 +21,10 @@ from trytond.model.browse import BrowseRecordList, BrowseRecord, \
|
||||
from trytond.model.browse import EvalEnvironment
|
||||
from trytond.tools import safe_eval, reduce_domain
|
||||
from trytond.pyson import PYSONEncoder, PYSONDecoder, PYSON
|
||||
from trytond.const import OPERATORS
|
||||
from trytond.const import OPERATORS, RECORD_CACHE_SIZE
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.pool import Pool
|
||||
from trytond.cache import LRUDict
|
||||
|
||||
|
||||
class ModelStorage(Model):
|
||||
@@ -62,7 +66,7 @@ class ModelStorage(Model):
|
||||
def __clean_xxx2many_cache(self):
|
||||
# Clean cursor cache
|
||||
to_clean = [(model._name, field_name)
|
||||
for model_name, model in self.pool.iterobject(type='model')
|
||||
for model_name, model in Pool().iterobject(type='model')
|
||||
for field_name, target_name in model._xxx2many_targets
|
||||
if target_name == self._name]
|
||||
for cache in Transaction().cursor.cache.values():
|
||||
@@ -81,8 +85,9 @@ class ModelStorage(Model):
|
||||
and created values as value
|
||||
:return: the id of the created record
|
||||
'''
|
||||
model_access_obj = self.pool.get('ir.model.access')
|
||||
model_field_access_obj = self.pool.get('ir.model.field.access')
|
||||
pool = Pool()
|
||||
model_access_obj = pool.get('ir.model.access')
|
||||
model_field_access_obj = pool.get('ir.model.field.access')
|
||||
|
||||
model_access_obj.check(self._name, 'create')
|
||||
model_field_access_obj.check(self._name,
|
||||
@@ -96,7 +101,7 @@ class ModelStorage(Model):
|
||||
|
||||
:param id: the created id
|
||||
'''
|
||||
trigger_obj = self.pool.get('ir.trigger')
|
||||
trigger_obj = Pool().get('ir.trigger')
|
||||
trigger_ids = trigger_obj.get_triggers(self._name, 'create')
|
||||
if not trigger_ids:
|
||||
return
|
||||
@@ -116,8 +121,9 @@ class ModelStorage(Model):
|
||||
the dictionnaries will have fields names as key
|
||||
and fields value as value. The list will not be in the same order.
|
||||
'''
|
||||
model_access_obj = self.pool.get('ir.model.access')
|
||||
model_field_access_obj = self.pool.get('ir.model.field.access')
|
||||
pool = Pool()
|
||||
model_access_obj = pool.get('ir.model.access')
|
||||
model_field_access_obj = pool.get('ir.model.field.access')
|
||||
|
||||
model_access_obj.check(self._name, 'read')
|
||||
model_field_access_obj.check(self._name,
|
||||
@@ -135,8 +141,9 @@ class ModelStorage(Model):
|
||||
and written values as value
|
||||
:return: True if succeed
|
||||
'''
|
||||
model_access_obj = self.pool.get('ir.model.access')
|
||||
model_field_access_obj = self.pool.get('ir.model.field.access')
|
||||
pool = Pool()
|
||||
model_access_obj = pool.get('ir.model.access')
|
||||
model_field_access_obj = pool.get('ir.model.field.access')
|
||||
|
||||
model_access_obj.check(self._name, 'write')
|
||||
model_field_access_obj.check(self._name,
|
||||
@@ -165,7 +172,7 @@ class ModelStorage(Model):
|
||||
:param ids: a list of ids
|
||||
:return: a dictionary of the lists of eligible ids by triggers
|
||||
'''
|
||||
trigger_obj = self.pool.get('ir.trigger')
|
||||
trigger_obj = Pool().get('ir.trigger')
|
||||
trigger_ids = trigger_obj.get_triggers(self._name, 'write')
|
||||
if not trigger_ids:
|
||||
return {}
|
||||
@@ -185,11 +192,11 @@ class ModelStorage(Model):
|
||||
|
||||
:param eligibles: a dictionary of the lists of eligible ids by triggers
|
||||
'''
|
||||
trigger_obj = self.pool.get('ir.trigger')
|
||||
trigger_obj = Pool().get('ir.trigger')
|
||||
trigger_ids = eligibles.keys()
|
||||
if not trigger_ids:
|
||||
return
|
||||
records = self.browse(chain(*eligibles.values()))
|
||||
records = self.browse(list(chain(*eligibles.values())))
|
||||
id2record = dict((x.id, x) for x in records)
|
||||
triggers = trigger_obj.browse(trigger_ids)
|
||||
for trigger in triggers:
|
||||
@@ -208,7 +215,7 @@ class ModelStorage(Model):
|
||||
:param ids: a list of ids or an id
|
||||
:return: True if succeed
|
||||
'''
|
||||
model_access_obj = self.pool.get('ir.model.access')
|
||||
model_access_obj = Pool().get('ir.model.access')
|
||||
|
||||
model_access_obj.check(self._name, 'delete')
|
||||
if not self.check_xml_record(ids, None):
|
||||
@@ -234,7 +241,7 @@ class ModelStorage(Model):
|
||||
|
||||
:param ids: the deleted ids
|
||||
'''
|
||||
trigger_obj = self.pool.get('ir.trigger')
|
||||
trigger_obj = Pool().get('ir.trigger')
|
||||
trigger_ids = trigger_obj.get_triggers(self._name, 'delete')
|
||||
if not trigger_ids:
|
||||
return
|
||||
@@ -257,7 +264,8 @@ class ModelStorage(Model):
|
||||
new value for the field as value
|
||||
:return: a list of new ids or the new id
|
||||
'''
|
||||
lang_obj = self.pool.get('ir.lang')
|
||||
pool = Pool()
|
||||
lang_obj = pool.get('ir.lang')
|
||||
if default is None:
|
||||
default = {}
|
||||
|
||||
@@ -314,7 +322,7 @@ class ModelStorage(Model):
|
||||
data, data_o2m = convert_data(field_defs, data)
|
||||
new_ids[data_id] = self.create(data)
|
||||
for field_name in data_o2m:
|
||||
relation_model = self.pool.get(
|
||||
relation_model = pool.get(
|
||||
field_defs[field_name]['relation'])
|
||||
relation_field = field_defs[field_name]['relation_field']
|
||||
if relation_field:
|
||||
@@ -511,13 +519,14 @@ class ModelStorage(Model):
|
||||
:param ids: a list of ids or an id
|
||||
:return: a BrowseRecordList or a BrowseRecord
|
||||
'''
|
||||
local_cache = LRUDict(RECORD_CACHE_SIZE)
|
||||
if isinstance(ids, (int, long)):
|
||||
return BrowseRecord(ids, self)
|
||||
local_cache = {}
|
||||
return BrowseRecordList((BrowseRecord(x, self, local_cache=local_cache)
|
||||
return BrowseRecord(ids, self, [ids], local_cache)
|
||||
return BrowseRecordList((BrowseRecord(x, self, ids, local_cache)
|
||||
for x in ids))
|
||||
|
||||
def __export_row(self, record, fields_names):
|
||||
pool = Pool()
|
||||
lines = []
|
||||
data = ['' for x in range(len(fields_names))]
|
||||
done = []
|
||||
@@ -531,7 +540,7 @@ class ModelStorage(Model):
|
||||
if not isinstance(value, BrowseRecord):
|
||||
break
|
||||
field_name = fields_tree[i]
|
||||
model_obj = self.pool.get(value._model_name)
|
||||
model_obj = pool.get(value._model_name)
|
||||
field = model_obj._columns[field_name]
|
||||
if field.states and 'invisible' in field.states:
|
||||
pyson_invisible = PYSONEncoder().encode(
|
||||
@@ -603,6 +612,7 @@ class ModelStorage(Model):
|
||||
- the exception if failed
|
||||
- the warning if failed
|
||||
'''
|
||||
pool = Pool()
|
||||
def process_lines(self, datas, prefix, fields_def, position=0):
|
||||
|
||||
def warn(msgname, *args):
|
||||
@@ -625,7 +635,7 @@ class ModelStorage(Model):
|
||||
def get_many2one(relation, value):
|
||||
if not value:
|
||||
return False
|
||||
relation_obj = self.pool.get(relation)
|
||||
relation_obj = pool.get(relation)
|
||||
res = relation_obj.search([
|
||||
('rec_name', '=', value),
|
||||
], limit=2)
|
||||
@@ -643,7 +653,7 @@ class ModelStorage(Model):
|
||||
if not value:
|
||||
return False
|
||||
res = []
|
||||
relation_obj = self.pool.get(relation)
|
||||
relation_obj = pool.get(relation)
|
||||
for word in csv.reader(StringIO.StringIO(value), delimiter=',',
|
||||
quoting=csv.QUOTE_NONE, escapechar='\\').next():
|
||||
res2 = relation_obj.search([
|
||||
@@ -670,7 +680,7 @@ class ModelStorage(Model):
|
||||
except Exception:
|
||||
warn('reference_syntax_error', value, '/'.join(field))
|
||||
return False
|
||||
relation_obj = self.pool.get(relation)
|
||||
relation_obj = pool.get(relation)
|
||||
res = relation_obj.search([
|
||||
('rec_name', '=', value),
|
||||
], limit=2)
|
||||
@@ -775,7 +785,7 @@ class ModelStorage(Model):
|
||||
# Import one2many fields
|
||||
nbrmax = 1
|
||||
for field in todo:
|
||||
newfd = self.pool.get(fields_def[field]['relation']
|
||||
newfd = pool.get(fields_def[field]['relation']
|
||||
).fields_get()
|
||||
res = process_lines(self, datas, prefix + [field], newfd,
|
||||
position)
|
||||
@@ -806,7 +816,7 @@ class ModelStorage(Model):
|
||||
datas.pop(0)
|
||||
return (row, nbrmax, translate)
|
||||
|
||||
ir_model_data_obj = self.pool.get('ir.model.data')
|
||||
ir_model_data_obj = pool.get('ir.model.data')
|
||||
|
||||
# logger for collecting warnings for the client
|
||||
warnings = logging.Logger("import")
|
||||
@@ -840,7 +850,9 @@ class ModelStorage(Model):
|
||||
logger.error(exp)
|
||||
# XXX should raise Exception
|
||||
Transaction().cursor.rollback()
|
||||
warning = '\n'.join(map(str, exp[1:]) + [warning])
|
||||
tb_s = reduce(lambda x, y: x + y,
|
||||
traceback.format_exception(*sys.exc_info()))
|
||||
warning = '%s\n%s' % (tb_s, warning)
|
||||
return (-1, res, exp, warning)
|
||||
done += 1
|
||||
return (done, 0, 0, 0)
|
||||
@@ -861,7 +873,7 @@ class ModelStorage(Model):
|
||||
written values as value
|
||||
:return: True or False
|
||||
"""
|
||||
model_data_obj = self.pool.get('ir.model.data')
|
||||
model_data_obj = Pool().get('ir.model.data')
|
||||
# Allow root user to update/delete
|
||||
if Transaction().user == 0:
|
||||
return True
|
||||
@@ -934,7 +946,8 @@ class ModelStorage(Model):
|
||||
return True
|
||||
|
||||
def _get_error_args(self, field_name):
|
||||
model_field_obj = self.pool.get('ir.model.field')
|
||||
pool = Pool()
|
||||
model_field_obj = pool.get('ir.model.field')
|
||||
error_args = (field_name, self._name)
|
||||
if model_field_obj:
|
||||
model_field_ids = model_field_obj.search([
|
||||
@@ -949,6 +962,7 @@ class ModelStorage(Model):
|
||||
|
||||
|
||||
def _validate(self, ids):
|
||||
pool = Pool()
|
||||
if (Transaction().user == 0
|
||||
and Transaction().context.get('user')):
|
||||
with Transaction().set_user(Transaction().context.get('user')):
|
||||
@@ -958,12 +972,12 @@ class ModelStorage(Model):
|
||||
if not getattr(self, field[0])(ids):
|
||||
self.raise_user_error(field[1])
|
||||
|
||||
if not 'res.user' in self.pool.object_name_list() \
|
||||
if not 'res.user' in pool.object_name_list() \
|
||||
or Transaction().user == 0:
|
||||
ctx_pref = {
|
||||
}
|
||||
else:
|
||||
user_obj = self.pool.get('res.user')
|
||||
user_obj = pool.get('res.user')
|
||||
ctx_pref = user_obj.get_preferences(context_only=True)
|
||||
|
||||
def is_pyson(test):
|
||||
@@ -989,9 +1003,9 @@ class ModelStorage(Model):
|
||||
('many2one', 'many2many', 'one2many', 'one2one')
|
||||
and field.domain):
|
||||
if field._type in ('many2one', 'one2many'):
|
||||
relation_obj = self.pool.get(field.model_name)
|
||||
relation_obj = pool.get(field.model_name)
|
||||
else:
|
||||
relation_obj = field.get_target(self.pool)
|
||||
relation_obj = field.get_target()
|
||||
if is_pyson(field.domain):
|
||||
pyson_domain = PYSONEncoder().encode(field.domain)
|
||||
for record in records:
|
||||
@@ -1110,6 +1124,7 @@ class ModelStorage(Model):
|
||||
field_name)
|
||||
|
||||
def _clean_defaults(self, defaults):
|
||||
pool = Pool()
|
||||
vals = {}
|
||||
for field in defaults.keys():
|
||||
fld_def = (field in self._columns) and self._columns[field] \
|
||||
@@ -1120,7 +1135,7 @@ class ModelStorage(Model):
|
||||
else:
|
||||
vals[field] = defaults[field]
|
||||
elif fld_def._type in ('one2many',):
|
||||
obj = self.pool.get(fld_def.model_name)
|
||||
obj = pool.get(fld_def.model_name)
|
||||
vals[field] = []
|
||||
for defaults2 in defaults[field]:
|
||||
vals2 = obj._clean_defaults(defaults2)
|
||||
@@ -1139,8 +1154,9 @@ class ModelStorage(Model):
|
||||
|
||||
:param ids: a list of id or an id
|
||||
'''
|
||||
trigger_obj = self.pool.get('workflow.trigger')
|
||||
instance_obj = self.pool.get('workflow.instance')
|
||||
pool = Pool()
|
||||
trigger_obj = pool.get('workflow.trigger')
|
||||
instance_obj = pool.get('workflow.instance')
|
||||
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
|
||||
+13
-10
@@ -12,6 +12,7 @@ from trytond.tools import safe_eval
|
||||
from trytond.pyson import PYSONEncoder, CONTEXT
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.cache import Cache
|
||||
from trytond.pool import Pool
|
||||
|
||||
def _find(tree, element):
|
||||
if element.tag == 'xpath':
|
||||
@@ -112,6 +113,7 @@ class ModelView(Model):
|
||||
- md5: the check sum of the dictionary without this checksum
|
||||
'''
|
||||
result = {'model': self._name}
|
||||
pool = Pool()
|
||||
|
||||
test = True
|
||||
model = True
|
||||
@@ -149,7 +151,7 @@ class ModelView(Model):
|
||||
|
||||
# Check if view is not from an inherited model
|
||||
if sql_res[5] != self._name:
|
||||
inherit_obj = self.pool.get(sql_res[5])
|
||||
inherit_obj = pool.get(sql_res[5])
|
||||
result['arch'] = inherit_obj.fields_view_get(
|
||||
result['view_id'])['arch']
|
||||
view_id = inherit_view_id
|
||||
@@ -164,9 +166,8 @@ class ModelView(Model):
|
||||
raise_p = False
|
||||
while True:
|
||||
try:
|
||||
sql_inherit.sort(lambda x, y: \
|
||||
cmp(self._modules_list.index(x[2] or None),
|
||||
self._modules_list.index(y[2] or None)))
|
||||
sql_inherit.sort(key=lambda x:
|
||||
self._modules_list.index(x[2] or None))
|
||||
break
|
||||
except ValueError:
|
||||
if raise_p:
|
||||
@@ -261,7 +262,8 @@ class ModelView(Model):
|
||||
return value
|
||||
|
||||
def _view_look_dom_arch(self, tree, type, field_children=None):
|
||||
field_access_obj = self.pool.get('ir.model.field.access')
|
||||
pool = Pool()
|
||||
field_access_obj = pool.get('ir.model.field.access')
|
||||
|
||||
fields_width = {}
|
||||
tree_root = tree.getroottree().getroot()
|
||||
@@ -278,7 +280,7 @@ class ModelView(Model):
|
||||
|
||||
# Find field inherited without read access
|
||||
for inherit_name in self._inherits:
|
||||
inherit_obj = self.pool.get(inherit_name)
|
||||
inherit_obj = pool.get(inherit_name)
|
||||
fread_accesses = field_access_obj.check(inherit_obj._name,
|
||||
inherit_obj._columns.keys(), 'read', access=True)
|
||||
fields_to_remove += list(x for x, y in fread_accesses.iteritems()
|
||||
@@ -301,7 +303,7 @@ class ModelView(Model):
|
||||
parent.remove(element)
|
||||
|
||||
if type == 'tree':
|
||||
viewtreewidth_obj = self.pool.get('ir.ui.view_tree_width')
|
||||
viewtreewidth_obj = pool.get('ir.ui.view_tree_width')
|
||||
viewtreewidth_ids = viewtreewidth_obj.search([
|
||||
('model', '=', self._name),
|
||||
('user', '=', Transaction().user),
|
||||
@@ -345,7 +347,8 @@ class ModelView(Model):
|
||||
return arch, fields2
|
||||
|
||||
def __view_look_dom(self, element, type, fields_width=None):
|
||||
translation_obj = self.pool.get('ir.translation')
|
||||
pool = Pool()
|
||||
translation_obj = pool.get('ir.translation')
|
||||
|
||||
if fields_width is None:
|
||||
fields_width = {}
|
||||
@@ -366,7 +369,7 @@ class ModelView(Model):
|
||||
if hasattr(field, 'model_name'):
|
||||
relation = field.model_name
|
||||
else:
|
||||
relation = field.get_target(self.pool)._name
|
||||
relation = field.get_target()._name
|
||||
except Exception:
|
||||
relation = False
|
||||
if relation and element.tag == 'field':
|
||||
@@ -396,7 +399,7 @@ class ModelView(Model):
|
||||
if Transaction().language != 'en_US':
|
||||
_translate_field(field2)
|
||||
|
||||
relation_obj = self.pool.get(relation)
|
||||
relation_obj = pool.get(relation)
|
||||
if hasattr(relation_obj, '_view_look_dom_arch'):
|
||||
xarch, xfields = \
|
||||
relation_obj._view_look_dom_arch(
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
from trytond.model import ModelStorage
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.pool import Pool
|
||||
|
||||
|
||||
class ModelWorkflow(ModelStorage):
|
||||
@@ -27,7 +27,7 @@ class ModelWorkflow(ModelStorage):
|
||||
return res
|
||||
|
||||
def delete(self, ids):
|
||||
instance_obj = self.pool.get('workflow.instance')
|
||||
instance_obj = Pool().get('workflow.instance')
|
||||
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
@@ -49,8 +49,9 @@ class ModelWorkflow(ModelStorage):
|
||||
|
||||
:param ids: a list of id or an id
|
||||
'''
|
||||
workflow_obj = self.pool.get('workflow')
|
||||
instance_obj = self.pool.get('workflow.instance')
|
||||
pool = Pool()
|
||||
workflow_obj = pool.get('workflow')
|
||||
instance_obj = pool.get('workflow.instance')
|
||||
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
@@ -75,7 +76,7 @@ class ModelWorkflow(ModelStorage):
|
||||
|
||||
:param ids: a list of id or an id
|
||||
'''
|
||||
instance_obj = self.pool.get('workflow.instance')
|
||||
instance_obj = Pool().get('workflow.instance')
|
||||
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
@@ -96,7 +97,7 @@ class ModelWorkflow(ModelStorage):
|
||||
|
||||
:param ids: a list of id or an id
|
||||
'''
|
||||
instance_obj = self.pool.get('workflow.instance')
|
||||
instance_obj = Pool().get('workflow.instance')
|
||||
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
@@ -119,7 +120,7 @@ class ModelWorkflow(ModelStorage):
|
||||
'''
|
||||
if self._name == 'workflow.instance':
|
||||
return
|
||||
instance_obj = self.pool.get('workflow.instance')
|
||||
instance_obj = Pool().get('workflow.instance')
|
||||
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
import os, sys, imp
|
||||
import itertools
|
||||
import traceback
|
||||
import logging
|
||||
import contextlib
|
||||
from functools import reduce
|
||||
import imp
|
||||
import operator
|
||||
from trytond.backend import Database
|
||||
import trytond.tools as tools
|
||||
from trytond.config import CONFIG
|
||||
@@ -91,7 +93,7 @@ class Node(Singleton):
|
||||
for attr in ('init', 'update'):
|
||||
if hasattr(self, attr):
|
||||
setattr(node, attr, True)
|
||||
self.childs.sort(lambda x, y: cmp(x.name, y.name))
|
||||
self.childs.sort(key=operator.attrgetter('name'))
|
||||
|
||||
def all_childs(self):
|
||||
res = []
|
||||
@@ -334,7 +336,7 @@ def register_classes(reload_p=False):
|
||||
if i.startswith(module) \
|
||||
and i != module:
|
||||
del sys.modules[i]
|
||||
reload(sys.modules[module])
|
||||
imp.reload(sys.modules[module])
|
||||
|
||||
logger = logging.getLogger('modules')
|
||||
|
||||
@@ -352,7 +354,7 @@ def register_classes(reload_p=False):
|
||||
and i != 'trytond.modules.' + module \
|
||||
and getattr(sys.modules[i], '_TRYTON_RELOAD', True):
|
||||
del sys.modules[i]
|
||||
reload(sys.modules['trytond.modules.' + module])
|
||||
imp.reload(sys.modules['trytond.modules.' + module])
|
||||
continue
|
||||
|
||||
if os.path.isdir(OPJ(MODULES_PATH, module)):
|
||||
|
||||
+58
-60
@@ -1,8 +1,10 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from trytond.modules import load_modules, register_classes
|
||||
from threading import RLock
|
||||
import logging
|
||||
from trytond.modules import load_modules, register_classes
|
||||
from trytond.transaction import Transaction
|
||||
import __builtin__
|
||||
|
||||
|
||||
class Pool(object):
|
||||
@@ -15,32 +17,27 @@ class Pool(object):
|
||||
_lock = RLock()
|
||||
_locks = {}
|
||||
_pool = {}
|
||||
_pools = {}
|
||||
test = False
|
||||
_instances = {}
|
||||
|
||||
def __new__(cls, database_name):
|
||||
cls._lock.acquire()
|
||||
lock = cls._locks.setdefault(database_name, RLock())
|
||||
cls._lock.release()
|
||||
lock.acquire()
|
||||
if database_name in cls._pools:
|
||||
res = cls._pools[database_name]
|
||||
lock.release()
|
||||
return res
|
||||
lock.release()
|
||||
return object.__new__(cls)
|
||||
def __new__(cls, database_name=None):
|
||||
if database_name is None:
|
||||
database_name = Transaction().cursor.database_name
|
||||
result = cls._instances.get(database_name)
|
||||
if result:
|
||||
return result
|
||||
lock = cls._locks.get(database_name)
|
||||
if not lock:
|
||||
with cls._lock:
|
||||
lock = cls._locks.setdefault(database_name, RLock())
|
||||
with lock:
|
||||
return cls._instances.setdefault(database_name,
|
||||
super(Pool, cls).__new__(cls))
|
||||
|
||||
def __init__(self, database_name):
|
||||
def __init__(self, database_name=None):
|
||||
if database_name is None:
|
||||
database_name = Transaction().cursor.database_name
|
||||
self.database_name = database_name
|
||||
self._lock.acquire()
|
||||
lock = self._locks.setdefault(database_name, RLock())
|
||||
self._lock.release()
|
||||
lock.acquire()
|
||||
self._pool.setdefault(database_name, {})
|
||||
for type in self.classes.keys():
|
||||
self._pool[database_name].setdefault(type, {})
|
||||
self._pools.setdefault(database_name, self)
|
||||
lock.release()
|
||||
|
||||
@staticmethod
|
||||
def register(klass, type='model'):
|
||||
@@ -57,53 +54,47 @@ class Pool(object):
|
||||
if module:
|
||||
Pool.classes[type].setdefault(module, []).append(klass)
|
||||
|
||||
@staticmethod
|
||||
def start():
|
||||
@classmethod
|
||||
def start(cls):
|
||||
'''
|
||||
Start/restart the Pool
|
||||
'''
|
||||
Pool._lock.acquire()
|
||||
try:
|
||||
with cls._lock:
|
||||
reload_p = False
|
||||
prev_classes = {}
|
||||
for type in Pool.classes:
|
||||
if Pool.classes[type]:
|
||||
for type in cls.classes:
|
||||
if cls.classes.get(type):
|
||||
reload_p = True
|
||||
prev_classes[type] = Pool.classes[type]
|
||||
Pool.classes[type] = {}
|
||||
prev_classes[type] = cls.classes.get(type)
|
||||
cls.classes[type] = {}
|
||||
try:
|
||||
register_classes(reload_p=reload_p)
|
||||
except Exception:
|
||||
if not reload_p:
|
||||
raise
|
||||
for type in prev_classes:
|
||||
Pool.classes[type] = prev_classes[type]
|
||||
for db_name in Pool.database_list():
|
||||
Pool(db_name).init()
|
||||
finally:
|
||||
Pool._lock.release()
|
||||
cls.classes[type] = prev_classes[type]
|
||||
for db_name in cls.database_list():
|
||||
cls(db_name).init()
|
||||
|
||||
@staticmethod
|
||||
def stop(database_name):
|
||||
@classmethod
|
||||
def stop(cls, database_name):
|
||||
'''
|
||||
Stop the Pool
|
||||
'''
|
||||
Pool._lock.acquire()
|
||||
lock = Pool._locks.setdefault(database_name, RLock())
|
||||
Pool._lock.release()
|
||||
lock.acquire()
|
||||
if database_name in Pool._pool:
|
||||
del Pool._pool[database_name]
|
||||
if database_name in Pool._pools:
|
||||
del Pool._pools[database_name]
|
||||
lock.release()
|
||||
with cls._lock:
|
||||
if database_name in cls._instances:
|
||||
del cls._instances[database_name]
|
||||
with cls._locks[database_name]:
|
||||
if database_name in cls._pool:
|
||||
del cls._pool[database_name]
|
||||
|
||||
@staticmethod
|
||||
def database_list():
|
||||
@classmethod
|
||||
def database_list(cls):
|
||||
'''
|
||||
:return: database list
|
||||
'''
|
||||
return Pool._pool.keys()
|
||||
return cls._pool.keys()
|
||||
|
||||
def init(self, update=False, lang=None):
|
||||
'''
|
||||
@@ -115,11 +106,8 @@ class Pool(object):
|
||||
'''
|
||||
logger = logging.getLogger('pool')
|
||||
logger.info('init pool for "%s"' % self.database_name)
|
||||
self._lock.acquire()
|
||||
lock = self._locks.setdefault(self.database_name, RLock())
|
||||
self._lock.release()
|
||||
lock.acquire()
|
||||
try:
|
||||
with self._locks[self.database_name]:
|
||||
self._pool.setdefault(self.database_name, {})
|
||||
#Clean the _pool before loading modules
|
||||
for type in self.classes.keys():
|
||||
self._pool[self.database_name][type] = {}
|
||||
@@ -127,8 +115,6 @@ class Pool(object):
|
||||
lang=lang)
|
||||
if restart:
|
||||
self.init()
|
||||
finally:
|
||||
lock.release()
|
||||
|
||||
def get(self, name, type='model'):
|
||||
'''
|
||||
@@ -142,7 +128,19 @@ class Pool(object):
|
||||
for type in self.classes.keys():
|
||||
if name in self._pool[self.database_name][type]:
|
||||
break
|
||||
return self._pool[self.database_name][type][name]
|
||||
try:
|
||||
return self._pool[self.database_name][type][name]
|
||||
except KeyError:
|
||||
if type == 'report':
|
||||
from trytond.report import Report
|
||||
# Keyword argument 'type' conflicts with builtin function
|
||||
cls = __builtin__.type(str(name), (Report,), {})
|
||||
obj = object.__new__(cls)
|
||||
obj._name = name
|
||||
self.add(obj, type)
|
||||
obj.__init__()
|
||||
return obj
|
||||
raise
|
||||
|
||||
def add(self, obj, type='model'):
|
||||
'''
|
||||
@@ -151,8 +149,8 @@ class Pool(object):
|
||||
:param obj: the object
|
||||
:param type: the type
|
||||
'''
|
||||
self._pool[self.database_name][type][obj._name] = obj
|
||||
obj.pool = self
|
||||
with self._locks[self.database_name]:
|
||||
self._pool[self.database_name][type][obj._name] = obj
|
||||
|
||||
def object_name_list(self, type='model'):
|
||||
'''
|
||||
|
||||
@@ -55,6 +55,9 @@ class Float(float):
|
||||
return self.decimal.__eq__(other)
|
||||
return super(Float, self).__eq__(other)
|
||||
|
||||
def __hash__(self):
|
||||
return super(Float, self).__hash__()
|
||||
|
||||
def __floordiv__(self, other, context=None):
|
||||
if isinstance(other, Decimal):
|
||||
return self.decimal.__floordiv__(other, context=context)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
import traceback
|
||||
import logging
|
||||
import time
|
||||
|
||||
@@ -22,10 +22,7 @@ import posixpath
|
||||
import urllib
|
||||
import datetime
|
||||
from decimal import Decimal
|
||||
if sys.version_info < (2, 6):
|
||||
import simplejson as json
|
||||
else:
|
||||
import json
|
||||
import json
|
||||
|
||||
def object_hook(dct):
|
||||
if '__class__' in dct:
|
||||
@@ -279,8 +276,6 @@ class SimpleThreadedJSONRPCServer(SocketServer.ThreadingMixIn,
|
||||
timeout = 1
|
||||
|
||||
def server_bind(self):
|
||||
# Python < 2.6 doesn't handle self.timeout
|
||||
self.socket.settimeout(1)
|
||||
self.socket.setsockopt(socket.SOL_SOCKET,
|
||||
socket.SO_REUSEADDR, 1)
|
||||
SimpleJSONRPCServer.server_bind(self)
|
||||
|
||||
@@ -81,11 +81,6 @@ class BaseThreadedHTTPServer(SocketServer.ThreadingMixIn,
|
||||
max_children = CONFIG['max_thread']
|
||||
|
||||
def server_bind(self):
|
||||
# Python < 2.6 doesn't handle self.timeout
|
||||
if sys.version_info < (2, 6):
|
||||
# breaks the socket under BSD, see http://bugs.python.org/issue7995
|
||||
self.socket.settimeout(1)
|
||||
|
||||
self.socket.setsockopt(socket.SOL_SOCKET,
|
||||
socket.SO_REUSEADDR, 1)
|
||||
BaseHTTPServer.HTTPServer.server_bind(self)
|
||||
|
||||
@@ -204,8 +204,6 @@ class SimpleThreadedXMLRPCServer(SocketServer.ThreadingMixIn,
|
||||
timeout = 1
|
||||
|
||||
def server_bind(self):
|
||||
# Python < 2.6 doesn't handle self.timeout
|
||||
self.socket.settimeout(1)
|
||||
self.socket.setsockopt(socket.SOL_SOCKET,
|
||||
socket.SO_REUSEADDR, 1)
|
||||
SimpleXMLRPCServer.SimpleXMLRPCServer.server_bind(self)
|
||||
|
||||
+63
-29
@@ -12,6 +12,12 @@ try:
|
||||
except ImportError:
|
||||
ssl = None
|
||||
import gzip
|
||||
try:
|
||||
import hashlib
|
||||
except ImportError:
|
||||
hashlib = None
|
||||
import sha
|
||||
import os
|
||||
|
||||
DNS_CACHE = {}
|
||||
MAX_SIZE = 999999999
|
||||
@@ -32,7 +38,7 @@ def checkfunction(module, klass):
|
||||
|
||||
class PySocket:
|
||||
|
||||
def __init__(self, sock=None):
|
||||
def __init__(self, sock=None, fingerprints=None, ca_certs=None):
|
||||
self.sock = sock
|
||||
self.host = None
|
||||
self.hostname = None
|
||||
@@ -41,6 +47,11 @@ class PySocket:
|
||||
self.ssl_sock = None
|
||||
self.connected = False
|
||||
self.buffer = ''
|
||||
self.fingerprints = fingerprints
|
||||
if ca_certs and os.path.isfile(ca_certs):
|
||||
self.ca_certs = ca_certs
|
||||
else:
|
||||
self.ca_certs = None
|
||||
|
||||
def connect(self, host, port=False):
|
||||
if not port:
|
||||
@@ -57,7 +68,7 @@ class PySocket:
|
||||
socket.SOCK_STREAM)
|
||||
self.sock.settimeout(CONNECT_TIMEOUT)
|
||||
self.sock.connect((host, int(port)))
|
||||
except Exception:
|
||||
except socket.error:
|
||||
self.sock = None
|
||||
if self.sock is None:
|
||||
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
@@ -72,31 +83,54 @@ class PySocket:
|
||||
sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
|
||||
sock.settimeout(CONNECT_TIMEOUT)
|
||||
sock.connect((host, int(port)))
|
||||
except Exception:
|
||||
except socket.error:
|
||||
sock = None
|
||||
if sock is None:
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sock.settimeout(CONNECT_TIMEOUT)
|
||||
sock.connect((host, int(port)))
|
||||
if ssl:
|
||||
ssl.wrap_socket(sock)
|
||||
ssl_sock = ssl.wrap_socket(sock)
|
||||
self.ssl = True
|
||||
elif hasattr(socket, 'ssl'):
|
||||
socket.ssl(sock)
|
||||
ssl_sock = socket.ssl(sock)
|
||||
self.ssl = True
|
||||
except Exception:
|
||||
except socket.error:
|
||||
pass
|
||||
self.sock.settimeout(TIMEOUT)
|
||||
fingerprint = None
|
||||
if self.ssl:
|
||||
if ssl:
|
||||
self.ssl_sock = ssl.wrap_socket(self.sock)
|
||||
self.ssl_sock = ssl.wrap_socket(self.sock,
|
||||
ca_certs=self.ca_certs, cert_reqs=(self.ca_certs and
|
||||
ssl.CERT_REQUIRED or ssl.CERT_NONE))
|
||||
elif hasattr(socket, 'ssl'):
|
||||
self.ssl_sock = socket.ssl(self.sock)
|
||||
self.ssl_sock = socket.ssl(self.sock, certfile=self.ca_certs)
|
||||
try:
|
||||
peercert = self.ssl_sock.getpeercert(True)
|
||||
except socket.error:
|
||||
peercert = None
|
||||
def format_hash(value):
|
||||
return reduce(lambda x, y: x + y[1].upper() +
|
||||
((y[0] % 2 and y[0] + 1 < len(value)) and ':' or ''),
|
||||
enumerate(value), '')
|
||||
if peercert and hashlib:
|
||||
fingerprint = format_hash(hashlib.sha1(peercert).hexdigest())
|
||||
elif peercert:
|
||||
fingerprint = format_hash(sha1.new(peercert).hexdigest())
|
||||
self.host = host
|
||||
self.hostname = hostname
|
||||
self.port = port
|
||||
self.connected = True
|
||||
self.buffer = ''
|
||||
if self.fingerprints is not None:
|
||||
key = (self.hostname, str(self.port))
|
||||
if key in self.fingerprints:
|
||||
if self.fingerprints[key] != fingerprint:
|
||||
self.disconnect()
|
||||
raise Exception('BadFingerprint')
|
||||
elif fingerprint:
|
||||
self.fingerprints[key] = fingerprint
|
||||
|
||||
def disconnect(self):
|
||||
try:
|
||||
@@ -111,10 +145,10 @@ class PySocket:
|
||||
sock.sock_shutdown(shutdown_value)
|
||||
else:
|
||||
sock.shutdown(shutdown_value)
|
||||
except Exception:
|
||||
except socket.error:
|
||||
pass
|
||||
sock.close()
|
||||
except Exception:
|
||||
except socket.error:
|
||||
pass
|
||||
self.sock = None
|
||||
self.ssl = False
|
||||
@@ -123,20 +157,20 @@ class PySocket:
|
||||
self.buffer = ''
|
||||
|
||||
def reconnect(self):
|
||||
if self.host and self.port:
|
||||
if self.hostname and self.port:
|
||||
self.disconnect()
|
||||
self.connect(self.host, self.port)
|
||||
self.connect(self.hostname, self.port)
|
||||
|
||||
def send(self, msg, exception=False, traceback=None):
|
||||
msg = cPickle.dumps([msg, traceback], protocol=2)
|
||||
gzip_p = False
|
||||
if len(msg) > GZIP_THRESHOLD:
|
||||
buf = StringIO.StringIO()
|
||||
output = gzip.GzipFile(mode='wb', fileobj=buf)
|
||||
buffer = StringIO.StringIO()
|
||||
output = gzip.GzipFile(mode='wb', fileobj=buffer)
|
||||
output.write(msg)
|
||||
output.close()
|
||||
buf.seek(0)
|
||||
msg = buf.getvalue()
|
||||
buffer.seek(0)
|
||||
msg = buffer.getvalue()
|
||||
gzip_p = True
|
||||
size = len(msg)
|
||||
msg = str(size) + ' ' + (exception and "1" or "0") \
|
||||
@@ -148,14 +182,14 @@ class PySocket:
|
||||
while totalsent < size:
|
||||
sent = self.ssl_sock.write(msg[totalsent:])
|
||||
if sent == 0:
|
||||
raise RuntimeError, "socket connection broken"
|
||||
raise RuntimeError("socket connection broken")
|
||||
totalsent = totalsent + sent
|
||||
else:
|
||||
self.sock.sendall(msg)
|
||||
|
||||
def receive(self):
|
||||
buf = self.buffer
|
||||
buf_list = []
|
||||
L = []
|
||||
size_remaining = MAX_LENGHT
|
||||
while size_remaining:
|
||||
chunk_size = min(size_remaining, 4096)
|
||||
@@ -164,18 +198,18 @@ class PySocket:
|
||||
else:
|
||||
chunk = self.sock.recv(chunk_size)
|
||||
if chunk == '':
|
||||
raise RuntimeError, "socket connection broken"
|
||||
buf_list.append(chunk)
|
||||
raise RuntimeError("socket connection broken")
|
||||
L.append(chunk)
|
||||
size_remaining -= len(chunk)
|
||||
if ' ' in chunk:
|
||||
break
|
||||
if size_remaining < 0:
|
||||
raise RuntimeError, "socket connection broken"
|
||||
buf += ''.join(buf_list)
|
||||
raise RuntimeError("socket connection broken")
|
||||
buf += ''.join(L)
|
||||
size, msg = buf.split(' ', 1)
|
||||
size = int(size)
|
||||
if size > MAX_SIZE:
|
||||
raise RuntimeError, "socket connection broken"
|
||||
raise RuntimeError("socket connection broken")
|
||||
while len(msg) < 2:
|
||||
chunk_size = min(size + 2, 4096)
|
||||
if self.ssl:
|
||||
@@ -183,11 +217,11 @@ class PySocket:
|
||||
else:
|
||||
msg += self.sock.recv(chunk_size)
|
||||
if msg == '':
|
||||
raise RuntimeError, "socket connection broken"
|
||||
raise RuntimeError("socket connection broken")
|
||||
exception = msg[0] != "0"
|
||||
gzip_p = msg[1] != "0"
|
||||
buf_list = [msg[2:]]
|
||||
size_remaining = size - len(buf_list[0])
|
||||
L = [msg[2:]]
|
||||
size_remaining = size - len(L[0])
|
||||
while size_remaining:
|
||||
chunk_size = min(size_remaining, 4096)
|
||||
if self.ssl:
|
||||
@@ -195,10 +229,10 @@ class PySocket:
|
||||
else:
|
||||
chunk = self.sock.recv(chunk_size)
|
||||
if chunk == '':
|
||||
raise RuntimeError, "socket connection broken"
|
||||
buf_list.append(chunk)
|
||||
raise RuntimeError("socket connection broken")
|
||||
L.append(chunk)
|
||||
size_remaining -= len(chunk)
|
||||
msg = ''.join(buf_list)
|
||||
msg = ''.join(L)
|
||||
if len(msg) > size:
|
||||
self.buffer = msg[size:]
|
||||
msg = msg[:size]
|
||||
|
||||
+3
-5
@@ -1,11 +1,9 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
import sys
|
||||
if sys.version_info < (2, 6):
|
||||
import simplejson as json
|
||||
else:
|
||||
import json
|
||||
import json
|
||||
import datetime
|
||||
from functools import reduce
|
||||
|
||||
|
||||
class PYSON(object):
|
||||
@@ -405,7 +403,7 @@ class Date(PYSON):
|
||||
date = date.replace(year=year)
|
||||
if dct['dM']:
|
||||
month = date.month + dct['dM']
|
||||
year = date.year + month / 12
|
||||
year = date.year + month // 12
|
||||
month = month % 12
|
||||
date = date.replace(year=year, month=month)
|
||||
if dct['dd']:
|
||||
|
||||
@@ -104,7 +104,8 @@ class Report(object):
|
||||
a boolean to direct print,
|
||||
the report name
|
||||
'''
|
||||
action_report_obj = self.pool.get('ir.action.report')
|
||||
pool = Pool()
|
||||
action_report_obj = pool.get('ir.action.report')
|
||||
action_report_ids = action_report_obj.search([
|
||||
('report_name', '=', self._name)
|
||||
])
|
||||
@@ -119,7 +120,8 @@ class Report(object):
|
||||
action_report.name)
|
||||
|
||||
def _get_objects(self, ids, model, datas):
|
||||
model_obj = self.pool.get(model)
|
||||
pool = Pool()
|
||||
model_obj = pool.get(model)
|
||||
return model_obj.browse(ids)
|
||||
|
||||
def parse(self, report, objects, datas, localcontext):
|
||||
@@ -135,8 +137,9 @@ class Report(object):
|
||||
report type
|
||||
report
|
||||
'''
|
||||
pool = Pool()
|
||||
localcontext['datas'] = datas
|
||||
localcontext['user'] = self.pool.get('res.user'
|
||||
localcontext['user'] = pool.get('res.user'
|
||||
).browse(Transaction().user)
|
||||
localcontext['formatLang'] = lambda *args, **kargs: \
|
||||
self.format_lang(*args, **kargs)
|
||||
@@ -147,7 +150,7 @@ class Report(object):
|
||||
localcontext['context'] = Transaction().context
|
||||
|
||||
translate = TranslateFactory(self._name, Transaction().language,
|
||||
self.pool.get('ir.translation'))
|
||||
pool.get('ir.translation'))
|
||||
localcontext['setLang'] = lambda language: translate.set_language(language)
|
||||
|
||||
if not report.report_content:
|
||||
@@ -297,7 +300,8 @@ class Report(object):
|
||||
|
||||
def format_lang(self, value, lang, digits=2, grouping=True, monetary=False,
|
||||
date=False, currency=None, symbol=True):
|
||||
lang_obj = self.pool.get('ir.lang')
|
||||
pool = Pool()
|
||||
lang_obj = pool.get('ir.lang')
|
||||
|
||||
if date:
|
||||
if lang:
|
||||
|
||||
+16
-12
@@ -4,12 +4,13 @@
|
||||
from itertools import chain
|
||||
from trytond.model import ModelView, ModelSQL, fields
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.pool import Pool
|
||||
|
||||
|
||||
class MenuMany2Many(fields.Many2Many):
|
||||
|
||||
def get(self, ids, model, name, values=None):
|
||||
menu_obj = self.get_target(model.pool)
|
||||
menu_obj = self.get_target()
|
||||
res = super(MenuMany2Many, self).get(ids, model, name,
|
||||
values=values)
|
||||
menu_ids = list(set(chain(*res.values())))
|
||||
@@ -36,10 +37,10 @@ class Group(ModelSQL, ModelView):
|
||||
field_access = fields.One2Many('ir.model.field.access', 'group',
|
||||
'Access Field')
|
||||
rule_groups = fields.Many2Many('ir.rule.group-res.group',
|
||||
'group_id', 'rule_group_id', 'Rules',
|
||||
'group', 'rule_group', 'Rules',
|
||||
domain=[('global_p', '!=', True), ('default_p', '!=', True)])
|
||||
menu_access = MenuMany2Many('ir.ui.menu-res.group',
|
||||
'gid', 'menu_id', 'Access Menu')
|
||||
'group', 'menu', 'Access Menu')
|
||||
|
||||
def __init__(self):
|
||||
super(Group, self).__init__()
|
||||
@@ -72,32 +73,35 @@ class Group(ModelSQL, ModelView):
|
||||
|
||||
def create(self, vals):
|
||||
res = super(Group, self).create(vals)
|
||||
pool = Pool()
|
||||
# Restart the cache on the domain_get method
|
||||
self.pool.get('ir.rule').domain_get.reset()
|
||||
pool.get('ir.rule').domain_get.reset()
|
||||
# Restart the cache for get_groups
|
||||
self.pool.get('res.user').get_groups.reset()
|
||||
pool.get('res.user').get_groups.reset()
|
||||
# Restart the cache for get_preferences
|
||||
self.pool.get('res.user').get_preferences.reset()
|
||||
pool.get('res.user').get_preferences.reset()
|
||||
return res
|
||||
|
||||
def write(self, ids, vals):
|
||||
res = super(Group, self).write(ids, vals)
|
||||
pool = Pool()
|
||||
# Restart the cache on the domain_get method
|
||||
self.pool.get('ir.rule').domain_get.reset()
|
||||
pool.get('ir.rule').domain_get.reset()
|
||||
# Restart the cache for get_groups
|
||||
self.pool.get('res.user').get_groups.reset()
|
||||
pool.get('res.user').get_groups.reset()
|
||||
# Restart the cache for get_preferences
|
||||
self.pool.get('res.user').get_preferences.reset()
|
||||
pool.get('res.user').get_preferences.reset()
|
||||
return res
|
||||
|
||||
def delete(self, ids):
|
||||
res = super(Group, self).delete(ids)
|
||||
pool = Pool()
|
||||
# Restart the cache on the domain_get method
|
||||
self.pool.get('ir.rule').domain_get.reset()
|
||||
pool.get('ir.rule').domain_get.reset()
|
||||
# Restart the cache for get_groups
|
||||
self.pool.get('res.user').get_groups.reset()
|
||||
pool.get('res.user').get_groups.reset()
|
||||
# Restart the cache for get_preferences
|
||||
self.pool.get('res.user').get_preferences.reset()
|
||||
pool.get('res.user').get_preferences.reset()
|
||||
return res
|
||||
|
||||
Group()
|
||||
|
||||
@@ -16,15 +16,12 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="name"/>
|
||||
<notebook>
|
||||
<page string="Members" col="2" id="members">
|
||||
<separator name="users" colspan="2"/>
|
||||
<field name="users" colspan="2"/>
|
||||
</page>
|
||||
<page string="Access Permissions" col="2" id="permissions">
|
||||
<field name="model_access"/>
|
||||
<field name="field_access"/>
|
||||
<separator name="menu_access" colspan="2"/>
|
||||
<field name="menu_access" colspan="2"/>
|
||||
<separator name="rule_groups" colspan="2"/>
|
||||
<field name="rule_groups" colspan="2"/>
|
||||
</page>
|
||||
</notebook>
|
||||
@@ -60,8 +57,13 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="view" ref="group_view_form"/>
|
||||
<field name="act_window" ref="act_group_form"/>
|
||||
</record>
|
||||
<menuitem parent="res.menu_res" groups="group_admin"
|
||||
<menuitem parent="res.menu_res"
|
||||
action="act_group_form" id="menu_group_form"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_group_form_admin">
|
||||
<field name="menu" ref="menu_group_form"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_group">
|
||||
<field name="model" search="[('model', '=', 'res.group')]"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
|
||||
+47
-20
@@ -3,15 +3,16 @@
|
||||
from trytond.model import ModelView, ModelSQL, fields
|
||||
from trytond.backend import TableHandler
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.pool import Pool
|
||||
|
||||
|
||||
class UIMenuGroup(ModelSQL):
|
||||
"UI Menu - Group"
|
||||
_name = 'ir.ui.menu-res.group'
|
||||
_description = __doc__
|
||||
menu_id = fields.Many2One('ir.ui.menu', 'Menu', ondelete='CASCADE',
|
||||
menu = fields.Many2One('ir.ui.menu', 'Menu', ondelete='CASCADE',
|
||||
select=1, required=True)
|
||||
gid = fields.Many2One('res.group', 'Group', ondelete='CASCADE',
|
||||
group = fields.Many2One('res.group', 'Group', ondelete='CASCADE',
|
||||
select=1, required=True)
|
||||
|
||||
def init(self, module_name):
|
||||
@@ -20,24 +21,28 @@ class UIMenuGroup(ModelSQL):
|
||||
TableHandler.table_rename(cursor, 'ir_ui_menu_group_rel', self._table)
|
||||
TableHandler.sequence_rename(cursor, 'ir_ui_menu_group_rel_id_seq',
|
||||
self._table + '_id_seq')
|
||||
# Migration from 2.0 menu_id and gid renamed into menu group
|
||||
table = TableHandler(cursor, self, module_name)
|
||||
table.column_rename('menu_id', 'menu')
|
||||
table.column_rename('gid', 'group')
|
||||
super(UIMenuGroup, self).init(module_name)
|
||||
|
||||
def create(self, vals):
|
||||
res = super(UIMenuGroup, self).create(vals)
|
||||
# Restart the cache on the domain_get method
|
||||
self.pool.get('ir.rule').domain_get.reset()
|
||||
Pool().get('ir.rule').domain_get.reset()
|
||||
return res
|
||||
|
||||
def write(self, ids, vals):
|
||||
res = super(UIMenuGroup, self).write(ids, vals)
|
||||
# Restart the cache on the domain_get method
|
||||
self.pool.get('ir.rule').domain_get.reset()
|
||||
Pool().get('ir.rule').domain_get.reset()
|
||||
return res
|
||||
|
||||
def delete(self, ids):
|
||||
res = super(UIMenuGroup, self).delete(ids)
|
||||
# Restart the cache on the domain_get method
|
||||
self.pool.get('ir.rule').domain_get.reset()
|
||||
Pool().get('ir.rule').domain_get.reset()
|
||||
return res
|
||||
|
||||
UIMenuGroup()
|
||||
@@ -47,9 +52,9 @@ class ActionGroup(ModelSQL):
|
||||
"Action - Group"
|
||||
_name = 'ir.action-res.group'
|
||||
_description = __doc__
|
||||
action_id = fields.Many2One('ir.action', 'Action', ondelete='CASCADE',
|
||||
action = fields.Many2One('ir.action', 'Action', ondelete='CASCADE',
|
||||
select=1, required=True)
|
||||
gid = fields.Many2One('res.group', 'Group', ondelete='CASCADE',
|
||||
group = fields.Many2One('res.group', 'Group', ondelete='CASCADE',
|
||||
select=1, required=True)
|
||||
|
||||
def init(self, module_name):
|
||||
@@ -58,24 +63,36 @@ class ActionGroup(ModelSQL):
|
||||
TableHandler.table_rename(cursor, 'ir_action_group_rel', self._table)
|
||||
TableHandler.sequence_rename(cursor, 'ir_action_group_rel_id_seq',
|
||||
self._table + '_id_seq')
|
||||
# Migration from 2.0 action_id and gid renamed into action and group
|
||||
table = TableHandler(cursor, self, module_name)
|
||||
table.column_rename('action_id', 'action')
|
||||
table.column_rename('gid', 'group')
|
||||
super(ActionGroup, self).init(module_name)
|
||||
|
||||
def create(self, vals):
|
||||
action_obj = Pool().get('ir.action')
|
||||
if vals.get('action'):
|
||||
vals = vals.copy()
|
||||
vals['action'] = action_obj.get_action_id(vals['action'])
|
||||
res = super(ActionGroup, self).create(vals)
|
||||
# Restart the cache on the domain_get method
|
||||
self.pool.get('ir.rule').domain_get.reset()
|
||||
Pool().get('ir.rule').domain_get.reset()
|
||||
return res
|
||||
|
||||
def write(self, ids, vals):
|
||||
action_obj = Pool().get('ir.action')
|
||||
if vals.get('action'):
|
||||
vals = vals.copy()
|
||||
vals['action'] = action_obj.get_action_id(vals['action'])
|
||||
res = super(ActionGroup, self).write(ids, vals)
|
||||
# Restart the cache on the domain_get method
|
||||
self.pool.get('ir.rule').domain_get.reset()
|
||||
Pool().get('ir.rule').domain_get.reset()
|
||||
return res
|
||||
|
||||
def delete(self, ids):
|
||||
res = super(ActionGroup, self).delete(ids)
|
||||
# Restart the cache on the domain_get method
|
||||
self.pool.get('ir.rule').domain_get.reset()
|
||||
Pool().get('ir.rule').domain_get.reset()
|
||||
return res
|
||||
|
||||
ActionGroup()
|
||||
@@ -105,9 +122,9 @@ class RuleGroupGroup(ModelSQL):
|
||||
"Rule Group - Group"
|
||||
_name = 'ir.rule.group-res.group'
|
||||
_description = __doc__
|
||||
rule_group_id = fields.Many2One('ir.rule.group', 'Rule Group',
|
||||
rule_group = fields.Many2One('ir.rule.group', 'Rule Group',
|
||||
ondelete='CASCADE', select=1, required=True)
|
||||
group_id = fields.Many2One('res.group', 'Group', ondelete='CASCADE',
|
||||
group = fields.Many2One('res.group', 'Group', ondelete='CASCADE',
|
||||
select=1, required=True)
|
||||
|
||||
def init(self, module_name):
|
||||
@@ -116,6 +133,11 @@ class RuleGroupGroup(ModelSQL):
|
||||
TableHandler.table_rename(cursor, 'group_rule_group_rel', self._table)
|
||||
TableHandler.sequence_rename(cursor, 'group_rule_group_rel_id_seq',
|
||||
self._table + '_id_seq')
|
||||
# Migration from 2.0 rule_group_id and group_id renamed into rule_group
|
||||
# and group
|
||||
table = TableHandler(cursor, self, module_name)
|
||||
table.column_rename('rule_group_id', 'rule_group')
|
||||
table.column_rename('group_id', 'group')
|
||||
super(RuleGroupGroup, self).init(module_name)
|
||||
|
||||
RuleGroupGroup()
|
||||
@@ -125,9 +147,9 @@ class RuleGroupUser(ModelSQL):
|
||||
"Rule Group - User"
|
||||
_name = 'ir.rule.group-res.user'
|
||||
_description = __doc__
|
||||
rule_group_id = fields.Many2One('ir.rule.group', 'Rule Group',
|
||||
rule_group = fields.Many2One('ir.rule.group', 'Rule Group',
|
||||
ondelete='CASCADE', select=1, required=True)
|
||||
user_id = fields.Many2One('res.user', 'User', ondelete='CASCADE',
|
||||
user = fields.Many2One('res.user', 'User', ondelete='CASCADE',
|
||||
select=1, required=True)
|
||||
|
||||
def init(self, module_name):
|
||||
@@ -136,6 +158,11 @@ class RuleGroupUser(ModelSQL):
|
||||
TableHandler.table_rename(cursor, 'user_rule_group_rel', self._table)
|
||||
TableHandler.sequence_rename(cursor, 'user_rule_group_rel_id_seq',
|
||||
self._table + '_id_seq')
|
||||
# Migration from 2.0 rule_group_id and user_id renamed into rule_group
|
||||
# and user
|
||||
table = TableHandler(cursor, self, module_name)
|
||||
table.column_rename('rule_group_id', 'rule_group')
|
||||
table.column_rename('user_id', 'user')
|
||||
super(RuleGroupUser, self).init(module_name)
|
||||
|
||||
RuleGroupUser()
|
||||
@@ -147,7 +174,7 @@ class Lang(ModelSQL, ModelView):
|
||||
def write(self, ids, vals):
|
||||
res = super(Lang, self).write(ids, vals)
|
||||
# Restart the cache for get_preferences
|
||||
self.pool.get('res.user').get_preferences.reset()
|
||||
Pool().get('res.user').get_preferences.reset()
|
||||
return res
|
||||
|
||||
Lang()
|
||||
@@ -172,21 +199,21 @@ class SequenceTypeGroup(ModelSQL):
|
||||
ondelete='CASCADE', select=1, required=True)
|
||||
|
||||
def delete(self, ids):
|
||||
rule_obj = self.pool.get('ir.rule')
|
||||
rule_obj = Pool().get('ir.rule')
|
||||
res = super(SequenceTypeGroup, self).delete(ids)
|
||||
# Restart the cache on the domain_get method of ir.rule
|
||||
rule_obj.domain_get.reset()
|
||||
return res
|
||||
|
||||
def create(self, vals):
|
||||
rule_obj = self.pool.get('ir.rule')
|
||||
rule_obj = Pool().get('ir.rule')
|
||||
res = super(SequenceTypeGroup, self).create(vals)
|
||||
# Restart the cache on the domain_get method of ir.rule
|
||||
rule_obj.domain_get.reset()
|
||||
return res
|
||||
|
||||
def write(self, ids, vals):
|
||||
rule_obj = self.pool.get('ir.rule')
|
||||
rule_obj = Pool().get('ir.rule')
|
||||
res = super(SequenceTypeGroup, self).write(ids, vals)
|
||||
# Restart the cache on the domain_get method
|
||||
rule_obj.domain_get.reset()
|
||||
@@ -201,7 +228,7 @@ class Sequence(ModelSQL, ModelView):
|
||||
'User Groups'), 'get_groups', searcher='search_groups')
|
||||
|
||||
def get_groups(self, ids, name):
|
||||
sequence_type_obj = self.pool.get('ir.sequence.type')
|
||||
sequence_type_obj = Pool().get('ir.sequence.type')
|
||||
sequences= self.browse(ids)
|
||||
code2seq = {}
|
||||
for sequence in sequences:
|
||||
@@ -221,7 +248,7 @@ class Sequence(ModelSQL, ModelView):
|
||||
return res
|
||||
|
||||
def search_groups(self, name, clause):
|
||||
sequence_type_obj = self.pool.get('ir.sequence.type')
|
||||
sequence_type_obj = Pool().get('ir.sequence.type')
|
||||
ids = sequence_type_obj.search([clause], order=[])
|
||||
seq_types = sequence_type_obj.browse(ids)
|
||||
codes = set(st.code for st in seq_types)
|
||||
|
||||
+142
-94
@@ -425,141 +425,186 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="operand">False</field>
|
||||
<field name="rule_group" ref="rule_group_action"/>
|
||||
</record>
|
||||
<record model="ir.action.wizard" id="ir.act_module_install_upgrade">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.action-res.group" id="act_module_install_upgrade_group_admin">
|
||||
<field name="action" ref="ir.act_module_install_upgrade"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.action.wizard" id="ir.act_translation_update">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.action-res.group" id="act_translation_update_group_admin">
|
||||
<field name="action" ref="ir.act_translation_update"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.action.wizard" id="ir.act_translation_export">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.action-res.group" id="act_translation_export_group_admin">
|
||||
<field name="action" ref="ir.act_translation_export"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.menu" id="ir.menu_administration">
|
||||
<field name="groups" eval="[('add', ref('group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_administration_group_admin">
|
||||
<field name="menu" ref="ir.menu_administration"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_ui">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_ui_group_admin">
|
||||
<field name="menu" ref="ir.menu_ui"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_icon_form">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_icon_form_group_admin">
|
||||
<field name="menu" ref="ir.menu_icon_form"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_menu_tree">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_menu_tree_group_admin">
|
||||
<field name="menu" ref="ir.menu_menu_list"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_view">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_view_group_admin">
|
||||
<field name="menu" ref="ir.menu_view"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_view_sc">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_view_sc_group_admin">
|
||||
<field name="menu" ref="ir.menu_view_sc"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_view_tree_width">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_view_tree_width_group_admin">
|
||||
<field name="menu" ref="ir.menu_view_tree_width"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_action">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_action_group_admin">
|
||||
<field name="menu" ref="ir.menu_action"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_act_action">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_act_action_group_admin">
|
||||
<field name="menu" ref="ir.menu_act_action"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_action_report_form">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_action_report_form_group_admin">
|
||||
<field name="menu" ref="ir.menu_action_report_form"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_action_act_window">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_action_act_window_group_admin">
|
||||
<field name="menu" ref="ir.menu_action_act_window"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_action_wizard">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_action_wizard_group_admin">
|
||||
<field name="menu" ref="ir.menu_action_wizard"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_action_wizard_size">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_action_wizard_size_group_admin">
|
||||
<field name="menu" ref="ir.menu_action_wizard_size"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_action_url">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_action_url_group_admin">
|
||||
<field name="menu" ref="ir.menu_action_url"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_models">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_models_group_admin">
|
||||
<field name="menu" ref="ir.menu_models"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_model_form">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_model_form_group_admin">
|
||||
<field name="menu" ref="ir.menu_model_form"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.model_model_fields_form">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="model_model_fields_form_group_admin">
|
||||
<field name="menu" ref="ir.model_model_fields_form"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_model_access_form">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_model_access_form_group_admin">
|
||||
<field name="menu" ref="ir.menu_model_access_form"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_model_field_access_form">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_model_field_access_form_group_admin">
|
||||
<field name="menu" ref="ir.menu_model_field_access_form"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_sequences">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_sequences_group_admin">
|
||||
<field name="menu" ref="ir.menu_sequences"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_sequence_form">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_sequence_form_group_admin">
|
||||
<field name="menu" ref="ir.menu_sequence_form"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_sequence_strict_form">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_sequence_strict_form_group_admin">
|
||||
<field name="menu" ref="ir.menu_sequence_strict_form"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_ir_sequence_type">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_ir_sequence_type_group_admin">
|
||||
<field name="menu" ref="ir.menu_ir_sequence_type"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_attachment_form">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_attachment_form_group_admin">
|
||||
<field name="menu" ref="ir.menu_attachment_form"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_scheduler">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_scheduler_group_admin">
|
||||
<field name="menu" ref="ir.menu_scheduler"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_cron_form">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_cron_form_group_admin">
|
||||
<field name="menu" ref="ir.menu_cron_form"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_localization">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_localization_group_admin">
|
||||
<field name="menu" ref="ir.menu_localization"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_lang_form">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_lang_form_group_admin">
|
||||
<field name="menu" ref="ir.menu_lang_form"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_translation_form">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_translation_form_group_admin">
|
||||
<field name="menu" ref="ir.menu_translation_form"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_translation_set_report">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_translation_set_report_group_admin">
|
||||
<field name="menu" ref="ir.menu_translation_set_report"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_translation_clean">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_translation_clean_group_admin">
|
||||
<field name="menu" ref="ir.menu_translation_clean"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_translation_update">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_translation_update_group_admin">
|
||||
<field name="menu" ref="ir.menu_translation_update"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_translation_export">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_translation_export_group_admin">
|
||||
<field name="menu" ref="ir.menu_translation_export"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_export_form">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_export_form_group_admin">
|
||||
<field name="menu" ref="ir.menu_export_form"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_rule_group_form">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_rule_group_form_group_admin">
|
||||
<field name="menu" ref="ir.menu_rule_group_form"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_property_form_default">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_property_form_default_group_admin">
|
||||
<field name="menu" ref="ir.menu_property_form_default"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_property_form">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_property_form_group_admin">
|
||||
<field name="menu" ref="ir.menu_property_form"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_modules">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_modules_group_admin">
|
||||
<field name="menu" ref="ir.menu_modules"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_module_form">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_module_form_group_admin">
|
||||
<field name="menu" ref="ir.menu_module_form"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_config_wizard_item_form">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_config_wizard_item_form_group_admin">
|
||||
<field name="menu" ref="ir.menu_config_wizard_item_form"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_module_install_upgrade">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_module_install_upgrade_group_admin">
|
||||
<field name="menu" ref="ir.menu_module_install_upgrade"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.menu" id="ir.menu_trigger_form">
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_trigger_form_group_admin">
|
||||
<field name="menu" ref="ir.menu_trigger_form"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="module_view_form">
|
||||
<field name="model">ir.module.module</field>
|
||||
@@ -627,7 +672,6 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<xpath
|
||||
expr="/form/field[@name="code"]"
|
||||
position="after">
|
||||
<separator name="groups" colspan="4"/>
|
||||
<field name="groups" colspan="4"/>
|
||||
</xpath>
|
||||
</data>
|
||||
@@ -662,7 +706,11 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<record model="res.user" id="user_trigger">
|
||||
<field name="login">user_cron_trigger</field>
|
||||
<field name="name">Cron Trigger</field>
|
||||
<field name="groups" eval="[('add', ref('group_admin'))]"/>
|
||||
<field name="active" eval="False"/>
|
||||
</record>
|
||||
<record model="res.user-res.group" id="user_trigger_group_admin">
|
||||
<field name="user" ref="user_trigger"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.cron" id="cron_trigger_time">
|
||||
@@ -672,8 +720,8 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="active" eval="True"/>
|
||||
<field name="interval_number">5</field>
|
||||
<field name="interval_type">minutes</field>
|
||||
<field name="numbercall">-1</field>
|
||||
<field name="doall" eval="False"/>
|
||||
<field name="number_calls">-1</field>
|
||||
<field name="repeat_missed" eval="False"/>
|
||||
<field name="model">ir.trigger</field>
|
||||
<field name="function">trigger_time</field>
|
||||
</record>
|
||||
|
||||
@@ -5,6 +5,7 @@ import datetime
|
||||
from trytond.model import ModelView, ModelSQL, fields
|
||||
from trytond.pyson import Eval, In, If, Not, Equal
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.pool import Pool
|
||||
|
||||
_STATES = [
|
||||
('draft', 'Draft'),
|
||||
@@ -101,7 +102,8 @@ class Request(ModelSQL, ModelView):
|
||||
return res
|
||||
|
||||
def request_send(self, ids):
|
||||
request_history_obj = self.pool.get('res.request.history')
|
||||
pool = Pool()
|
||||
request_history_obj = pool.get('res.request.history')
|
||||
for request in self.browse(ids):
|
||||
values = {
|
||||
'request': request.id,
|
||||
@@ -177,7 +179,8 @@ class RequestLink(ModelSQL, ModelView):
|
||||
return 5
|
||||
|
||||
def models_get(self):
|
||||
model_obj = self.pool.get('ir.model')
|
||||
pool = Pool()
|
||||
model_obj = pool.get('ir.model')
|
||||
model_ids = model_obj.search([])
|
||||
res = []
|
||||
for model in model_obj.browse(model_ids):
|
||||
@@ -239,7 +242,8 @@ class RequestReference(ModelSQL, ModelView):
|
||||
required=True)
|
||||
|
||||
def links_get(self):
|
||||
request_link_obj = self.pool.get('res.request.link')
|
||||
pool = Pool()
|
||||
request_link_obj = pool.get('res.request.link')
|
||||
ids = request_link_obj.search([])
|
||||
request_links = request_link_obj.browse(ids)
|
||||
return [(x.model, x.name) for x in request_links]
|
||||
|
||||
+11
-2
@@ -90,8 +90,13 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="view" ref="request_view_form"/>
|
||||
<field name="act_window" ref="act_request_form"/>
|
||||
</record>
|
||||
<menuitem parent="res.menu_res" groups="group_admin"
|
||||
<menuitem parent="res.menu_res"
|
||||
action="act_request_form" id="menu_request_form"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_request_form_group_admin">
|
||||
<field name="menu" ref="menu_request_form"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="request_link_view_form">
|
||||
<field name="model">res.request.link</field>
|
||||
<field name="type">form</field>
|
||||
@@ -136,8 +141,12 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="view" ref="request_link_view_form"/>
|
||||
<field name="act_window" ref="act_request_link_form"/>
|
||||
</record>
|
||||
<menuitem parent="res.menu_res" groups="group_admin"
|
||||
<menuitem parent="res.menu_res"
|
||||
action="act_request_link_form" id="menu_request_link_form"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_request_link_form_group_admin">
|
||||
<field name="menu" ref="menu_request_link_form"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="request_history_view_tree">
|
||||
<field name="model">res.request.history</field>
|
||||
|
||||
+27
-16
@@ -1,7 +1,6 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
"User"
|
||||
from __future__ import with_statement
|
||||
import copy
|
||||
import string
|
||||
import random
|
||||
@@ -18,6 +17,7 @@ from trytond.security import get_connections
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.cache import Cache
|
||||
from trytond.pyson import Eval, Greater
|
||||
from trytond.pool import Pool
|
||||
|
||||
|
||||
class User(ModelSQL, ModelView):
|
||||
@@ -36,9 +36,9 @@ class User(ModelSQL, ModelView):
|
||||
menu = fields.Many2One('ir.action', 'Menu Action',
|
||||
domain=[('usage','=','menu')], required=True)
|
||||
groups = fields.Many2Many('res.user-res.group',
|
||||
'uid', 'gid', 'Groups')
|
||||
'user', 'group', 'Groups')
|
||||
rule_groups = fields.Many2Many('ir.rule.group-res.user',
|
||||
'user_id', 'rule_group_id', 'Rules',
|
||||
'user', 'rule_group', 'Rules',
|
||||
domain=[('global_p', '!=', True), ('default_p', '!=', True)])
|
||||
language = fields.Many2One('ir.lang', 'Language',
|
||||
domain=['OR', ('translatable', '=', True), ('code', '=', 'en_US')])
|
||||
@@ -112,7 +112,8 @@ class User(ModelSQL, ModelView):
|
||||
return 1
|
||||
|
||||
def default_menu(self):
|
||||
action_obj = self.pool.get('ir.action')
|
||||
pool = Pool()
|
||||
action_obj = pool.get('ir.action')
|
||||
action_ids = action_obj.search([
|
||||
('usage', '=', 'menu'),
|
||||
], limit=1)
|
||||
@@ -125,7 +126,8 @@ class User(ModelSQL, ModelView):
|
||||
|
||||
def get_language_direction(self, ids, name):
|
||||
res = {}
|
||||
lang_obj = self.pool.get('ir.lang')
|
||||
pool = Pool()
|
||||
lang_obj = pool.get('ir.lang')
|
||||
default_direction = lang_obj.default_direction()
|
||||
for user in self.browse(ids):
|
||||
if user.language:
|
||||
@@ -150,7 +152,8 @@ class User(ModelSQL, ModelView):
|
||||
|
||||
def _convert_vals(self, vals):
|
||||
vals = vals.copy()
|
||||
action_obj = self.pool.get('ir.action')
|
||||
pool = Pool()
|
||||
action_obj = pool.get('ir.action')
|
||||
if 'action' in vals:
|
||||
vals['action'] = action_obj.get_action_id(vals['action'])
|
||||
if 'menu' in vals:
|
||||
@@ -175,7 +178,8 @@ class User(ModelSQL, ModelView):
|
||||
vals = self._convert_vals(vals)
|
||||
res = super(User, self).write(ids, vals)
|
||||
# Restart the cache for domain_get method
|
||||
self.pool.get('ir.rule').domain_get.reset()
|
||||
pool = Pool()
|
||||
pool.get('ir.rule').domain_get.reset()
|
||||
# Restart the cache for get_groups
|
||||
self.get_groups.reset()
|
||||
# Restart the cache for _get_login
|
||||
@@ -183,9 +187,9 @@ class User(ModelSQL, ModelView):
|
||||
# Restart the cache for get_preferences
|
||||
self.get_preferences.reset()
|
||||
# Restart the cache of check
|
||||
self.pool.get('ir.model.access').check.reset()
|
||||
pool.get('ir.model.access').check.reset()
|
||||
# Restart the cache
|
||||
for _, model in self.pool.iterobject():
|
||||
for _, model in pool.iterobject():
|
||||
try:
|
||||
model.fields_view_get.reset()
|
||||
except Exception:
|
||||
@@ -290,7 +294,8 @@ class User(ModelSQL, ModelView):
|
||||
:param values: a dictionary with values
|
||||
:param old_password: the previous password if password is in values
|
||||
'''
|
||||
lang_obj = self.pool.get('ir.lang')
|
||||
pool = Pool()
|
||||
lang_obj = pool.get('ir.lang')
|
||||
values_clean = values.copy()
|
||||
fields = self._preferences_fields + self._context_fields
|
||||
user_id = Transaction().user
|
||||
@@ -314,8 +319,9 @@ class User(ModelSQL, ModelView):
|
||||
self.write(user_id, values_clean)
|
||||
|
||||
def get_preferences_fields_view(self):
|
||||
model_data_obj = self.pool.get('ir.model.data')
|
||||
lang_obj = self.pool.get('ir.lang')
|
||||
pool = Pool()
|
||||
model_data_obj = pool.get('ir.model.data')
|
||||
lang_obj = pool.get('ir.lang')
|
||||
|
||||
view_id = model_data_obj.get_id('res', 'user_view_form_preferences')
|
||||
res = self.fields_view_get(view_id=view_id)
|
||||
@@ -396,9 +402,9 @@ class UserGroup(ModelSQL):
|
||||
'User - Group'
|
||||
_name = 'res.user-res.group'
|
||||
_description = __doc__
|
||||
uid = fields.Many2One('res.user', 'User', ondelete='CASCADE', select=1,
|
||||
user = fields.Many2One('res.user', 'User', ondelete='CASCADE', select=1,
|
||||
required=True)
|
||||
gid = fields.Many2One('res.group', 'Group', ondelete='CASCADE', select=1,
|
||||
group = fields.Many2One('res.group', 'Group', ondelete='CASCADE', select=1,
|
||||
required=True)
|
||||
|
||||
def init(self, module_name):
|
||||
@@ -407,6 +413,10 @@ class UserGroup(ModelSQL):
|
||||
TableHandler.table_rename(cursor, 'res_group_user_rel', self._table)
|
||||
TableHandler.sequence_rename(cursor, 'res_group_user_rel_id_seq',
|
||||
self._table + '_id_seq')
|
||||
# Migration from 2.0 uid and gid rename into user and group
|
||||
table = TableHandler(cursor, self, module_name)
|
||||
table.column_rename('uid', 'user')
|
||||
table.column_rename('gid', 'group')
|
||||
super(UserGroup, self).init(module_name)
|
||||
|
||||
UserGroup()
|
||||
@@ -415,7 +425,7 @@ UserGroup()
|
||||
class Group(ModelSQL, ModelView):
|
||||
"Group"
|
||||
_name = "res.group"
|
||||
users = fields.Many2Many('res.user-res.group', 'gid', 'uid', 'Users')
|
||||
users = fields.Many2Many('res.user-res.group', 'group', 'user', 'Users')
|
||||
|
||||
Group()
|
||||
|
||||
@@ -492,7 +502,8 @@ class UserConfig(Wizard):
|
||||
return {}
|
||||
|
||||
def _add(self, data):
|
||||
res_obj = self.pool.get('res.user')
|
||||
pool = Pool()
|
||||
res_obj = pool.get('res.user')
|
||||
res_obj.create(data['form'])
|
||||
return {}
|
||||
|
||||
|
||||
@@ -9,7 +9,10 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="signature">Administrator</field>
|
||||
<field name="action" ref="ir.act_module_config_wizard"/>
|
||||
<field name="menu" ref="ir.act_menu_tree"/>
|
||||
<field name="groups" eval="[('add', ref('group_admin'))]"/>
|
||||
</record>
|
||||
<record model="res.user-res.group" id="user_admin_group_admin">
|
||||
<field name="user" ref="user_admin"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="user_view_form">
|
||||
<field name="model">res.user</field>
|
||||
@@ -38,9 +41,7 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="signature" colspan="4"/>
|
||||
</page>
|
||||
<page string="Access Permissions" col="1" id="permissions">
|
||||
<separator name="groups"/>
|
||||
<field name="groups"/>
|
||||
<separator name="rule_groups"/>
|
||||
<field name="rule_groups"/>
|
||||
</page>
|
||||
<page string="Preferences" col="2" id="preferences">
|
||||
@@ -77,7 +78,6 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="signature" colspan="4"/>
|
||||
</page>
|
||||
<page string="Group Membership" col="1" id="membership">
|
||||
<separator name="groups"/>
|
||||
<field name="groups"/>
|
||||
</page>
|
||||
<page string="Preferences" col="2" id="preferences">
|
||||
@@ -122,8 +122,12 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="view" ref="user_view_form"/>
|
||||
<field name="act_window" ref="act_user_form"/>
|
||||
</record>
|
||||
<menuitem parent="res.menu_res" groups="group_admin"
|
||||
<menuitem parent="res.menu_res"
|
||||
action="act_user_form" id="menu_user_form"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_user_form_group_admin">
|
||||
<field name="menu" ref="menu_user_form"/>
|
||||
<field name="group" ref="group_admin"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_user">
|
||||
<field name="model" search="[('model', '=', 'res.user')]"/>
|
||||
|
||||
+3
-4
@@ -1,6 +1,5 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
from trytond.backend import Database
|
||||
from trytond.session import Session
|
||||
from trytond.pool import Pool
|
||||
@@ -41,7 +40,7 @@ def login(dbname, loginname, password, cache=True):
|
||||
|
||||
def logout(dbname, user, session):
|
||||
name = ''
|
||||
if _USER_CACHE.get(dbname, {}).has_key(user):
|
||||
if user in _USER_CACHE.get(dbname, {}):
|
||||
for i, real_session \
|
||||
in enumerate(_USER_CACHE[dbname][user]):
|
||||
if real_session.session == session:
|
||||
@@ -62,7 +61,7 @@ def check(dbname, user, session):
|
||||
result = None
|
||||
now = time.time()
|
||||
timeout = int(CONFIG['session_timeout'])
|
||||
if _USER_CACHE.get(dbname, {}).has_key(user):
|
||||
if user in _USER_CACHE.get(dbname, {}):
|
||||
to_del = []
|
||||
for i, real_session \
|
||||
in enumerate(_USER_CACHE[dbname][user]):
|
||||
@@ -81,7 +80,7 @@ def get_connections(dbname, user):
|
||||
res = 0
|
||||
now = time.time()
|
||||
timeout = int(CONFIG['session_timeout'])
|
||||
if _USER_CACHE.get(dbname, {}).has_key(int(user)):
|
||||
if int(user) in _USER_CACHE.get(dbname, {}):
|
||||
for _, session in enumerate(_USER_CACHE[dbname][int(user)]):
|
||||
if abs(session.timestamp - now) < timeout:
|
||||
res += 1
|
||||
|
||||
+15
-10
@@ -3,7 +3,6 @@
|
||||
"""
|
||||
%prog [options]
|
||||
"""
|
||||
from __future__ import with_statement
|
||||
import logging
|
||||
import logging.handlers
|
||||
import sys, os, signal
|
||||
@@ -235,19 +234,25 @@ class TrytonServer(object):
|
||||
import psyco
|
||||
psyco.full()
|
||||
|
||||
threads = {}
|
||||
while True:
|
||||
if CONFIG['auto_reload'] and monitor():
|
||||
try:
|
||||
Pool.start()
|
||||
except Exception:
|
||||
pass
|
||||
for dbname in Pool.database_list():
|
||||
pool = Pool(dbname)
|
||||
if 'ir.cron' not in pool.object_name_list():
|
||||
continue
|
||||
cron_obj = pool.get('ir.cron')
|
||||
thread = threading.Thread(
|
||||
target=cron_obj.pool_jobs,
|
||||
args=(dbname,), kwargs={})
|
||||
thread.start()
|
||||
if CONFIG['cron']:
|
||||
for dbname in Pool.database_list():
|
||||
thread = threads.get(dbname)
|
||||
if thread and thread.is_alive():
|
||||
continue
|
||||
pool = Pool(dbname)
|
||||
if 'ir.cron' not in pool.object_name_list():
|
||||
continue
|
||||
cron_obj = pool.get('ir.cron')
|
||||
thread = threading.Thread(
|
||||
target=cron_obj.run,
|
||||
args=(dbname,), kwargs={})
|
||||
thread.start()
|
||||
threads[dbname] = thread
|
||||
time.sleep(60)
|
||||
|
||||
@@ -7,7 +7,11 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<record model="ir.sequence.type" id="sequence_type_test">
|
||||
<field name="name">Test</field>
|
||||
<field name="code">test</field>
|
||||
<field name="groups" eval="[('add', ref('res.group_admin'))]"/>
|
||||
</record>
|
||||
<record model="ir.sequence.type-res.group"
|
||||
id="sequence_type_test_group_admin">
|
||||
<field name="sequence_type" ref="sequence_type_test"/>
|
||||
<field name="group" ref="res.group_admin"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
import unittest
|
||||
from trytond.tests.test_tryton import POOL, DB_NAME, USER, CONTEXT, \
|
||||
install_module
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
import unittest
|
||||
from decimal import Decimal
|
||||
import datetime
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
import unittest
|
||||
import datetime
|
||||
from decimal import Decimal
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
import unittest
|
||||
from trytond.tests.test_tryton import POOL, DB_NAME, USER, CONTEXT, \
|
||||
install_module
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
import unittest
|
||||
from datetime import datetime
|
||||
from trytond.tests.test_tryton import POOL, DB_NAME, USER, CONTEXT, \
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
import unittest
|
||||
from trytond.tests.test_tryton import POOL, DB_NAME, USER, CONTEXT, \
|
||||
install_module
|
||||
@@ -23,8 +22,7 @@ class MPTTTestCase(unittest.TestCase):
|
||||
('parent', '=', parent_id),
|
||||
])
|
||||
childs = self.mptt.read(child_ids, ['left', 'right'])
|
||||
childs.sort(lambda x, y: cmp(child_ids.index(x['id']),
|
||||
child_ids.index(y['id'])))
|
||||
childs.sort(key=lambda x: child_ids.index(x['id']))
|
||||
for child in childs:
|
||||
assert child['left'] > left, \
|
||||
'Record (%d): left %d <= parent left %d' % \
|
||||
@@ -152,7 +150,7 @@ class MPTTTestCase(unittest.TestCase):
|
||||
|
||||
with Transaction().start(DB_NAME, USER, CONTEXT) as transaction:
|
||||
record_ids = self.mptt.search([])
|
||||
self.mptt.write(record_ids[:len(record_ids)/2], {
|
||||
self.mptt.write(record_ids[:len(record_ids) // 2], {
|
||||
'active': False
|
||||
})
|
||||
self.CheckTree()
|
||||
@@ -186,7 +184,7 @@ class MPTTTestCase(unittest.TestCase):
|
||||
|
||||
with Transaction().start(DB_NAME, USER, CONTEXT) as transaction:
|
||||
record_ids = self.mptt.search([])
|
||||
self.mptt.delete(record_ids[:len(record_ids)/2])
|
||||
self.mptt.delete(record_ids[:len(record_ids) // 2])
|
||||
self.CheckTree()
|
||||
|
||||
transaction.cursor.rollback()
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
import unittest
|
||||
import datetime
|
||||
from trytond.tests.test_tryton import POOL, DB_NAME, USER, CONTEXT, \
|
||||
|
||||
@@ -118,6 +118,8 @@ class ToolsTestCase(unittest.TestCase):
|
||||
['OR', clause, ['AND', clause, ['OR', clause, clause]]]),
|
||||
(['OR', [clause]], ['OR', ['AND', clause]]),
|
||||
([], []),
|
||||
(['OR', clause, []], ['OR', clause, []]),
|
||||
(['AND', clause, []], ['AND', clause, []]),
|
||||
)
|
||||
for i, j in tests:
|
||||
self.assertEqual(reduce_domain(i), j,
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
import unittest
|
||||
import sys
|
||||
import time
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
import logging
|
||||
logging.basicConfig(level=logging.ERROR)
|
||||
import sys, os
|
||||
@@ -11,13 +10,6 @@ DIR = os.path.abspath(os.path.normpath(os.path.join(__file__,
|
||||
if os.path.isdir(DIR):
|
||||
sys.path.insert(0, os.path.dirname(DIR))
|
||||
|
||||
if sys.version_info[:2] <= (2, 5):
|
||||
# ugly monkeypatch to make doctests work. For the reasons see
|
||||
# http://mail.python.org/pipermail/python-dev/2008-July/081420.html
|
||||
# It can go away once we drop Python 2.5
|
||||
import decimal
|
||||
decimal.Decimal.__repr__ = lambda s: "Decimal('%s')" % str(s)
|
||||
|
||||
import unittest
|
||||
import doctest
|
||||
from lxml import etree
|
||||
|
||||
@@ -2,3 +2,7 @@
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from misc import *
|
||||
from datetime_strftime import *
|
||||
try:
|
||||
from collections import OrderedDict
|
||||
except ImportError:
|
||||
from ordereddict import OrderedDict
|
||||
|
||||
@@ -446,4 +446,6 @@ def reduce_domain(domain):
|
||||
result.extend(sub_domain[1:])
|
||||
else:
|
||||
result.append(sub_domain)
|
||||
else:
|
||||
result.append(arg)
|
||||
return result
|
||||
|
||||
@@ -0,0 +1,278 @@
|
||||
# Copyright (C) 2009 by Raymond Hettinger
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
#
|
||||
# Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pypy.
|
||||
# Passes Python2.7's test suite and incorporates all the latest updates.
|
||||
|
||||
try:
|
||||
from thread import get_ident as _get_ident
|
||||
except ImportError:
|
||||
from dummy_thread import get_ident as _get_ident
|
||||
|
||||
try:
|
||||
from _abcoll import KeysView, ValuesView, ItemsView
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
class OrderedDict(dict):
|
||||
'Dictionary that remembers insertion order'
|
||||
# An inherited dict maps keys to values.
|
||||
# The inherited dict provides __getitem__, __len__, __contains__, and get.
|
||||
# The remaining methods are order-aware.
|
||||
# Big-O running times for all methods are the same as for regular dictionaries.
|
||||
|
||||
# The internal self.__map dictionary maps keys to links in a doubly linked list.
|
||||
# The circular doubly linked list starts and ends with a sentinel element.
|
||||
# The sentinel element never gets deleted (this simplifies the algorithm).
|
||||
# Each link is stored as a list of length three: [PREV, NEXT, KEY].
|
||||
|
||||
def __init__(self, *args, **kwds):
|
||||
'''Initialize an ordered dictionary. Signature is the same as for
|
||||
regular dictionaries, but keyword arguments are not recommended
|
||||
because their insertion order is arbitrary.
|
||||
|
||||
'''
|
||||
if len(args) > 1:
|
||||
raise TypeError('expected at most 1 arguments, got %d' % len(args))
|
||||
try:
|
||||
self.__root
|
||||
except AttributeError:
|
||||
self.__root = root = [] # sentinel node
|
||||
root[:] = [root, root, None]
|
||||
self.__map = {}
|
||||
self.__update(*args, **kwds)
|
||||
|
||||
def __setitem__(self, key, value, dict_setitem=dict.__setitem__):
|
||||
'od.__setitem__(i, y) <==> od[i]=y'
|
||||
# Setting a new item creates a new link which goes at the end of the linked
|
||||
# list, and the inherited dictionary is updated with the new key/value pair.
|
||||
if key not in self:
|
||||
root = self.__root
|
||||
last = root[0]
|
||||
last[1] = root[0] = self.__map[key] = [last, root, key]
|
||||
dict_setitem(self, key, value)
|
||||
|
||||
def __delitem__(self, key, dict_delitem=dict.__delitem__):
|
||||
'od.__delitem__(y) <==> del od[y]'
|
||||
# Deleting an existing item uses self.__map to find the link which is
|
||||
# then removed by updating the links in the predecessor and successor nodes.
|
||||
dict_delitem(self, key)
|
||||
link_prev, link_next, key = self.__map.pop(key)
|
||||
link_prev[1] = link_next
|
||||
link_next[0] = link_prev
|
||||
|
||||
def __iter__(self):
|
||||
'od.__iter__() <==> iter(od)'
|
||||
root = self.__root
|
||||
curr = root[1]
|
||||
while curr is not root:
|
||||
yield curr[2]
|
||||
curr = curr[1]
|
||||
|
||||
def __reversed__(self):
|
||||
'od.__reversed__() <==> reversed(od)'
|
||||
root = self.__root
|
||||
curr = root[0]
|
||||
while curr is not root:
|
||||
yield curr[2]
|
||||
curr = curr[0]
|
||||
|
||||
def clear(self):
|
||||
'od.clear() -> None. Remove all items from od.'
|
||||
try:
|
||||
for node in self.__map.itervalues():
|
||||
del node[:]
|
||||
root = self.__root
|
||||
root[:] = [root, root, None]
|
||||
self.__map.clear()
|
||||
except AttributeError:
|
||||
pass
|
||||
dict.clear(self)
|
||||
|
||||
def popitem(self, last=True):
|
||||
'''od.popitem() -> (k, v), return and remove a (key, value) pair.
|
||||
Pairs are returned in LIFO order if last is true or FIFO order if false.
|
||||
|
||||
'''
|
||||
if not self:
|
||||
raise KeyError('dictionary is empty')
|
||||
root = self.__root
|
||||
if last:
|
||||
link = root[0]
|
||||
link_prev = link[0]
|
||||
link_prev[1] = root
|
||||
root[0] = link_prev
|
||||
else:
|
||||
link = root[1]
|
||||
link_next = link[1]
|
||||
root[1] = link_next
|
||||
link_next[0] = root
|
||||
key = link[2]
|
||||
del self.__map[key]
|
||||
value = dict.pop(self, key)
|
||||
return key, value
|
||||
|
||||
# -- the following methods do not depend on the internal structure --
|
||||
|
||||
def keys(self):
|
||||
'od.keys() -> list of keys in od'
|
||||
return list(self)
|
||||
|
||||
def values(self):
|
||||
'od.values() -> list of values in od'
|
||||
return [self[key] for key in self]
|
||||
|
||||
def items(self):
|
||||
'od.items() -> list of (key, value) pairs in od'
|
||||
return [(key, self[key]) for key in self]
|
||||
|
||||
def iterkeys(self):
|
||||
'od.iterkeys() -> an iterator over the keys in od'
|
||||
return iter(self)
|
||||
|
||||
def itervalues(self):
|
||||
'od.itervalues -> an iterator over the values in od'
|
||||
for k in self:
|
||||
yield self[k]
|
||||
|
||||
def iteritems(self):
|
||||
'od.iteritems -> an iterator over the (key, value) items in od'
|
||||
for k in self:
|
||||
yield (k, self[k])
|
||||
|
||||
def update(*args, **kwds):
|
||||
'''od.update(E, **F) -> None. Update od from dict/iterable E and F.
|
||||
|
||||
If E is a dict instance, does: for k in E: od[k] = E[k]
|
||||
If E has a .keys() method, does: for k in E.keys(): od[k] = E[k]
|
||||
Or if E is an iterable of items, does: for k, v in E: od[k] = v
|
||||
In either case, this is followed by: for k, v in F.items(): od[k] = v
|
||||
|
||||
'''
|
||||
if len(args) > 2:
|
||||
raise TypeError('update() takes at most 2 positional '
|
||||
'arguments (%d given)' % (len(args),))
|
||||
elif not args:
|
||||
raise TypeError('update() takes at least 1 argument (0 given)')
|
||||
self = args[0]
|
||||
# Make progressively weaker assumptions about "other"
|
||||
other = ()
|
||||
if len(args) == 2:
|
||||
other = args[1]
|
||||
if isinstance(other, dict):
|
||||
for key in other:
|
||||
self[key] = other[key]
|
||||
elif hasattr(other, 'keys'):
|
||||
for key in other.keys():
|
||||
self[key] = other[key]
|
||||
else:
|
||||
for key, value in other:
|
||||
self[key] = value
|
||||
for key, value in kwds.items():
|
||||
self[key] = value
|
||||
|
||||
__update = update # let subclasses override update without breaking __init__
|
||||
|
||||
__marker = object()
|
||||
|
||||
def pop(self, key, default=__marker):
|
||||
'''od.pop(k[,d]) -> v, remove specified key and return the corresponding value.
|
||||
If key is not found, d is returned if given, otherwise KeyError is raised.
|
||||
|
||||
'''
|
||||
if key in self:
|
||||
result = self[key]
|
||||
del self[key]
|
||||
return result
|
||||
if default is self.__marker:
|
||||
raise KeyError(key)
|
||||
return default
|
||||
|
||||
def setdefault(self, key, default=None):
|
||||
'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od'
|
||||
if key in self:
|
||||
return self[key]
|
||||
self[key] = default
|
||||
return default
|
||||
|
||||
def __repr__(self, _repr_running={}):
|
||||
'od.__repr__() <==> repr(od)'
|
||||
call_key = id(self), _get_ident()
|
||||
if call_key in _repr_running:
|
||||
return '...'
|
||||
_repr_running[call_key] = 1
|
||||
try:
|
||||
if not self:
|
||||
return '%s()' % (self.__class__.__name__,)
|
||||
return '%s(%r)' % (self.__class__.__name__, self.items())
|
||||
finally:
|
||||
del _repr_running[call_key]
|
||||
|
||||
def __reduce__(self):
|
||||
'Return state information for pickling'
|
||||
items = [[k, self[k]] for k in self]
|
||||
inst_dict = vars(self).copy()
|
||||
for k in vars(OrderedDict()):
|
||||
inst_dict.pop(k, None)
|
||||
if inst_dict:
|
||||
return (self.__class__, (items,), inst_dict)
|
||||
return self.__class__, (items,)
|
||||
|
||||
def copy(self):
|
||||
'od.copy() -> a shallow copy of od'
|
||||
return self.__class__(self)
|
||||
|
||||
@classmethod
|
||||
def fromkeys(cls, iterable, value=None):
|
||||
'''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S
|
||||
and values equal to v (which defaults to None).
|
||||
|
||||
'''
|
||||
d = cls()
|
||||
for key in iterable:
|
||||
d[key] = value
|
||||
return d
|
||||
|
||||
def __eq__(self, other):
|
||||
'''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive
|
||||
while comparison to a regular mapping is order-insensitive.
|
||||
|
||||
'''
|
||||
if isinstance(other, OrderedDict):
|
||||
return len(self)==len(other) and self.items() == other.items()
|
||||
return dict.__eq__(self, other)
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
# -- the following methods are only used in Python 2.7 --
|
||||
|
||||
def viewkeys(self):
|
||||
"od.viewkeys() -> a set-like object providing a view on od's keys"
|
||||
return KeysView(self)
|
||||
|
||||
def viewvalues(self):
|
||||
"od.viewvalues() -> an object providing a view on od's values"
|
||||
return ValuesView(self)
|
||||
|
||||
def viewitems(self):
|
||||
"od.viewitems() -> a set-like object providing a view on od's items"
|
||||
return ItemsView(self)
|
||||
+27
-16
@@ -7,6 +7,7 @@ from trytond.model import ModelView, ModelSQL, fields
|
||||
from trytond.version import PACKAGE, VERSION, WEBSITE
|
||||
from trytond.tools import reduce_ids, safe_eval
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.pool import Pool
|
||||
|
||||
|
||||
class Collection(ModelSQL, ModelView):
|
||||
@@ -47,7 +48,8 @@ class Collection(ModelSQL, ModelView):
|
||||
return '[]'
|
||||
|
||||
def check_attachment(self, ids):
|
||||
attachment_obj = self.pool.get('ir.attachment')
|
||||
pool = Pool()
|
||||
attachment_obj = pool.get('ir.attachment')
|
||||
for collection in self.browse(ids):
|
||||
if collection.parent:
|
||||
attachment_ids = attachment_obj.search([
|
||||
@@ -60,8 +62,9 @@ class Collection(ModelSQL, ModelView):
|
||||
return True
|
||||
|
||||
def _uri2object(self, uri, object_name=_name, object_id=False, cache=None):
|
||||
attachment_obj = self.pool.get('ir.attachment')
|
||||
report_obj = self.pool.get('ir.action.report')
|
||||
pool = Pool()
|
||||
attachment_obj = pool.get('ir.attachment')
|
||||
report_obj = pool.get('ir.action.report')
|
||||
cache_uri = uri
|
||||
|
||||
if cache is not None:
|
||||
@@ -233,7 +236,8 @@ class Collection(ModelSQL, ModelView):
|
||||
return object_name, object_id
|
||||
|
||||
def get_childs(self, uri, filter=None, cache=None):
|
||||
report_obj = self.pool.get('ir.action.report')
|
||||
pool = Pool()
|
||||
report_obj = pool.get('ir.action.report')
|
||||
res = []
|
||||
if filter:
|
||||
return []
|
||||
@@ -253,7 +257,7 @@ class Collection(ModelSQL, ModelView):
|
||||
if object_name == self._name and object_id:
|
||||
collection = self.browse(object_id)
|
||||
if collection.model:
|
||||
model_obj = self.pool.get(collection.model.model)
|
||||
model_obj = pool.get(collection.model.model)
|
||||
if not model_obj:
|
||||
return res
|
||||
model_ids = model_obj.search(
|
||||
@@ -289,7 +293,7 @@ class Collection(ModelSQL, ModelView):
|
||||
cache.setdefault(report_obj._name, {})
|
||||
cache[report_obj._name][report.id] = {}
|
||||
|
||||
attachment_obj = self.pool.get('ir.attachment')
|
||||
attachment_obj = pool.get('ir.attachment')
|
||||
attachment_ids = attachment_obj.search([
|
||||
('resource', '=', '%s,%s' % (object_name, object_id)),
|
||||
])
|
||||
@@ -312,11 +316,12 @@ class Collection(ModelSQL, ModelView):
|
||||
|
||||
def get_displayname(self, uri, cache=None):
|
||||
object_name, object_id = self._uri2object(uri, cache=cache)
|
||||
model_obj = self.pool.get(object_name)
|
||||
model_obj = Pool().get(object_name)
|
||||
return model_obj.browse(object_id).rec_name
|
||||
|
||||
def get_contentlength(self, uri, cache=None):
|
||||
attachment_obj = self.pool.get('ir.attachment')
|
||||
pool = Pool()
|
||||
attachment_obj = pool.get('ir.attachment')
|
||||
|
||||
object_name, object_id = self._uri2object(uri, cache=cache)
|
||||
if object_name == 'ir.attachment':
|
||||
@@ -360,9 +365,10 @@ class Collection(ModelSQL, ModelView):
|
||||
return "application/octet-stream"
|
||||
|
||||
def get_creationdate(self, uri, cache=None):
|
||||
pool = Pool()
|
||||
object_name, object_id = self._uri2object(uri, cache=cache)
|
||||
if object_name == 'ir.attachment':
|
||||
model_obj = self.pool.get(object_name)
|
||||
model_obj = pool.get(object_name)
|
||||
if object_id:
|
||||
if cache is not None:
|
||||
cache.setdefault(model_obj._name, {})
|
||||
@@ -394,9 +400,10 @@ class Collection(ModelSQL, ModelView):
|
||||
return time.time()
|
||||
|
||||
def get_lastmodified(self, uri, cache=None):
|
||||
pool = Pool()
|
||||
object_name, object_id = self._uri2object(uri, cache=cache)
|
||||
if object_name == 'ir.attachment':
|
||||
model_obj = self.pool.get(object_name)
|
||||
model_obj = pool.get(object_name)
|
||||
if object_id:
|
||||
if cache is not None:
|
||||
cache.setdefault(model_obj._name, {})
|
||||
@@ -430,8 +437,9 @@ class Collection(ModelSQL, ModelView):
|
||||
|
||||
def get_data(self, uri, cache=None):
|
||||
from DAV.errors import DAV_NotFound
|
||||
attachment_obj = self.pool.get('ir.attachment')
|
||||
report_obj = self.pool.get('ir.action.report')
|
||||
pool = Pool()
|
||||
attachment_obj = pool.get('ir.attachment')
|
||||
report_obj = pool.get('ir.action.report')
|
||||
|
||||
if uri:
|
||||
object_name, object_id = self._uri2object(uri, cache=cache)
|
||||
@@ -473,7 +481,7 @@ class Collection(ModelSQL, ModelView):
|
||||
1)[-1].rsplit('.', 1)[0])
|
||||
report = report_obj.browse(report_id)
|
||||
if report.report_name:
|
||||
report_obj = self.pool.get(report.report_name,
|
||||
report_obj = pool.get(report.report_name,
|
||||
type='report')
|
||||
val = report_obj.execute([object_id],
|
||||
{'id': object_id, 'ids': [object_id]})
|
||||
@@ -489,7 +497,8 @@ class Collection(ModelSQL, ModelView):
|
||||
or object_name in ('ir.attachment') \
|
||||
or not object_id:
|
||||
raise DAV_Forbidden
|
||||
attachment_obj = self.pool.get('ir.attachment')
|
||||
pool = Pool()
|
||||
attachment_obj = pool.get('ir.attachment')
|
||||
object_name2, object_id2 = self._uri2object(uri, cache=cache)
|
||||
if not object_id2:
|
||||
name = get_urifilename(uri)
|
||||
@@ -550,7 +559,8 @@ class Collection(ModelSQL, ModelView):
|
||||
if object_name != 'ir.attachment' \
|
||||
or not object_id:
|
||||
raise DAV_Forbidden
|
||||
model_obj = self.pool.get(object_name)
|
||||
pool = Pool()
|
||||
model_obj = pool.get(object_name)
|
||||
try:
|
||||
model_obj.delete(object_id)
|
||||
except Exception:
|
||||
@@ -584,7 +594,8 @@ class Attachment(ModelSQL, ModelView):
|
||||
})
|
||||
|
||||
def check_collection(self, ids):
|
||||
collection_obj = self.pool.get('webdav.collection')
|
||||
pool = Pool()
|
||||
collection_obj = pool.get('webdav.collection')
|
||||
for attachment in self.browse(ids):
|
||||
if attachment.resource:
|
||||
model_name, record_id = attachment.resource.split(',')
|
||||
|
||||
@@ -3,8 +3,13 @@
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tryton>
|
||||
<data>
|
||||
<menuitem name="WebDAV" id="menu_webdav" groups="res.group_admin"
|
||||
<menuitem name="WebDAV" id="menu_webdav"
|
||||
parent="ir.menu_administration"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_webdav_group_admin">
|
||||
<field name="menu" ref="menu_webdav"/>
|
||||
<field name="group" ref="res.group_admin"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="collection_view_tree">
|
||||
<field name="model">webdav.collection</field>
|
||||
<field name="type">tree</field>
|
||||
@@ -57,8 +62,12 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="view" ref="collection_view_form"/>
|
||||
<field name="act_window" ref="act_collection_tree"/>
|
||||
</record>
|
||||
<menuitem parent="menu_webdav" groups="res.group_admin"
|
||||
<menuitem parent="menu_webdav"
|
||||
action="act_collection_tree" id="menu_collection_tree"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_collection_tree_group_admin">
|
||||
<field name="menu" ref="menu_collection_tree"/>
|
||||
<field name="group" ref="res.group_admin"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_collection_form">
|
||||
<field name="name">Collections</field>
|
||||
@@ -77,7 +86,10 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="act_window" ref="act_collection_form"/>
|
||||
</record>
|
||||
<menuitem name="New Collection" parent="menu_collection_tree"
|
||||
action="act_collection_form" id="menu_collection_form"
|
||||
groups="res.group_admin"/>
|
||||
action="act_collection_form" id="menu_collection_form"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_collection_form_group_admin">
|
||||
<field name="menu" ref="menu_collection_form"/>
|
||||
<field name="group" ref="res.group_admin"/>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
||||
|
||||
@@ -12,7 +12,6 @@ from trytond.error import WarningErrorMixin
|
||||
class Wizard(WarningErrorMixin):
|
||||
_name = ""
|
||||
states = {}
|
||||
pool = None
|
||||
|
||||
def __new__(cls):
|
||||
Pool.register(cls, type='wizard')
|
||||
@@ -29,7 +28,8 @@ class Wizard(WarningErrorMixin):
|
||||
self._datas = {}
|
||||
|
||||
def init(self, module_name):
|
||||
translation_obj = self.pool.get('ir.translation')
|
||||
pool = Pool()
|
||||
translation_obj = pool.get('ir.translation')
|
||||
cursor = Transaction().cursor
|
||||
for state in self.states.keys():
|
||||
if self.states[state]['result']['type'] == 'form':
|
||||
@@ -100,8 +100,9 @@ class Wizard(WarningErrorMixin):
|
||||
self._lock.release()
|
||||
|
||||
def execute(self, wiz_id, data, state='init'):
|
||||
translation_obj = self.pool.get('ir.translation')
|
||||
wizard_size_obj = self.pool.get('ir.action.wizard_size')
|
||||
pool = Pool()
|
||||
translation_obj = pool.get('ir.translation')
|
||||
wizard_size_obj = pool.get('ir.action.wizard_size')
|
||||
res = {}
|
||||
|
||||
if self._datas.get(wiz_id, {}).get('user') != Transaction().user:
|
||||
@@ -129,7 +130,7 @@ class Wizard(WarningErrorMixin):
|
||||
if result_def['type'] == 'action':
|
||||
res['action'] = getattr(self, result_def['action'])(data)
|
||||
elif result_def['type'] == 'form':
|
||||
obj = self.pool.get(result_def['object'])
|
||||
obj = pool.get(result_def['object'])
|
||||
|
||||
view = obj.fields_view_get(view_type='form')
|
||||
fields = view['fields']
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
#this repository contains the full copyright notices and license terms.
|
||||
from __future__ import with_statement
|
||||
import os
|
||||
import expr
|
||||
import base64
|
||||
@@ -10,6 +9,7 @@ from trytond.tools import exec_command_pipe
|
||||
from trytond.backend import TableHandler
|
||||
from trytond.pyson import Eval, Equal, Not
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.pool import Pool
|
||||
|
||||
|
||||
class Workflow(ModelSQL, ModelView):
|
||||
@@ -172,8 +172,9 @@ class WorkflowInstance(ModelSQL, ModelView):
|
||||
return res
|
||||
|
||||
def create(self, values):
|
||||
activity_obj = self.pool.get('workflow.activity')
|
||||
workitem_obj = self.pool.get('workflow.workitem')
|
||||
pool = Pool()
|
||||
activity_obj = pool.get('workflow.activity')
|
||||
workitem_obj = pool.get('workflow.workitem')
|
||||
|
||||
instance_id = super(WorkflowInstance, self).create(values)
|
||||
|
||||
@@ -196,7 +197,8 @@ class WorkflowInstance(ModelSQL, ModelView):
|
||||
def update(self, instance):
|
||||
'''
|
||||
'''
|
||||
workitem_obj = self.pool.get('workflow.workitem')
|
||||
pool = Pool()
|
||||
workitem_obj = pool.get('workflow.workitem')
|
||||
for workitem in instance.workitems:
|
||||
workitem_obj.process(workitem)
|
||||
instance = self.browse(instance.id)
|
||||
@@ -205,7 +207,8 @@ class WorkflowInstance(ModelSQL, ModelView):
|
||||
def validate(self, instance, signal, force_running=False):
|
||||
'''
|
||||
'''
|
||||
workitem_obj = self.pool.get('workflow.workitem')
|
||||
pool = Pool()
|
||||
workitem_obj = pool.get('workflow.workitem')
|
||||
for workitem in instance.workitems:
|
||||
workitem_obj.process(workitem, signal=signal,
|
||||
force_running=force_running)
|
||||
@@ -213,7 +216,8 @@ class WorkflowInstance(ModelSQL, ModelView):
|
||||
return self._update_end(instance)
|
||||
|
||||
def _update_end(self, instance):
|
||||
workitem_obj = self.pool.get('workflow.workitem')
|
||||
pool = Pool()
|
||||
workitem_obj = pool.get('workflow.workitem')
|
||||
res = True
|
||||
for workitem in instance.workitems:
|
||||
if (workitem.state != 'complete') \
|
||||
@@ -309,15 +313,14 @@ class WorkflowWorkitem(ModelSQL, ModelView):
|
||||
:param signal: the signal
|
||||
:param force_running: a boolean
|
||||
'''
|
||||
trigger_obj = self.pool.get('workflow.trigger')
|
||||
pool = Pool()
|
||||
trigger_obj = pool.get('workflow.trigger')
|
||||
activity = workitem.activity
|
||||
triggers = False
|
||||
if workitem.state == 'active':
|
||||
triggers = True
|
||||
if not self._execute(workitem, activity):
|
||||
return False
|
||||
elif workitem.state == 'running':
|
||||
pass
|
||||
|
||||
if workitem.state == 'complete' or force_running:
|
||||
res = self._split_test(workitem, activity.split_mode, signal)
|
||||
@@ -347,7 +350,8 @@ class WorkflowWorkitem(ModelSQL, ModelView):
|
||||
workitem._data[workitem.id]['state'] = state
|
||||
|
||||
def _execute(self, workitem, activity):
|
||||
instance_obj = self.pool.get('workflow.instance')
|
||||
pool = Pool()
|
||||
instance_obj = pool.get('workflow.instance')
|
||||
#send a signal to overflow
|
||||
if (workitem.state == 'active') and activity.signal_send:
|
||||
for overflow in workitem.overflows:
|
||||
@@ -409,7 +413,8 @@ class WorkflowWorkitem(ModelSQL, ModelView):
|
||||
return True
|
||||
|
||||
def _split_test(self, workitem, split_mode, signal=None):
|
||||
instance_obj = self.pool.get('workflow.instance')
|
||||
pool = Pool()
|
||||
instance_obj = pool.get('workflow.instance')
|
||||
test = False
|
||||
transitions = []
|
||||
if split_mode == 'XOR' or split_mode == 'OR':
|
||||
@@ -443,7 +448,8 @@ class WorkflowWorkitem(ModelSQL, ModelView):
|
||||
return False
|
||||
|
||||
def _join_test(self, transition, instance):
|
||||
instance_obj = self.pool.get('workflow.instance')
|
||||
pool = Pool()
|
||||
instance_obj = pool.get('workflow.instance')
|
||||
activity = transition.act_to
|
||||
if activity.join_mode == 'XOR':
|
||||
self.create({
|
||||
@@ -515,9 +521,10 @@ class InstanceGraph(Report):
|
||||
|
||||
def execute(self, ids, datas):
|
||||
import pydot
|
||||
lang_obj = self.pool.get('ir.lang')
|
||||
workflow_obj = self.pool.get('workflow')
|
||||
instance_obj = self.pool.get('workflow.instance')
|
||||
pool = Pool()
|
||||
lang_obj = pool.get('ir.lang')
|
||||
workflow_obj = pool.get('workflow')
|
||||
instance_obj = pool.get('workflow.instance')
|
||||
|
||||
lang_id = lang_obj.search([
|
||||
('code', '=', Transaction().language),
|
||||
@@ -562,14 +569,16 @@ class InstanceGraph(Report):
|
||||
return ('png', base64.encodestring(data), False, workflow.name)
|
||||
|
||||
def graph_instance_get(self, graph, instance_id, nested=False):
|
||||
instance_obj = self.pool.get('workflow.instance')
|
||||
pool = Pool()
|
||||
instance_obj = pool.get('workflow.instance')
|
||||
instance = instance_obj.browse(instance_id)
|
||||
self.graph_get(graph, instance.workflow.id, nested,
|
||||
self.workitem_get(instance.id))
|
||||
|
||||
def workitem_get(self, instance_id):
|
||||
res = {}
|
||||
workitem_obj = self.pool.get('workflow.workitem')
|
||||
pool = Pool()
|
||||
workitem_obj = pool.get('workflow.workitem')
|
||||
workitem_ids = workitem_obj.search([
|
||||
('instance', '=', instance_id),
|
||||
])
|
||||
@@ -585,9 +594,10 @@ class InstanceGraph(Report):
|
||||
import pydot
|
||||
if workitem is None:
|
||||
workitem = {}
|
||||
activity_obj = self.pool.get('workflow.activity')
|
||||
workflow_obj = self.pool.get('workflow')
|
||||
transition_obj = self.pool.get('workflow.transition')
|
||||
pool = Pool()
|
||||
activity_obj = pool.get('workflow.activity')
|
||||
workflow_obj = pool.get('workflow')
|
||||
transition_obj = pool.get('workflow.transition')
|
||||
activity_ids = activity_obj.search([
|
||||
('workflow', '=', workflow_id),
|
||||
])
|
||||
|
||||
@@ -4,7 +4,12 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<tryton>
|
||||
<data>
|
||||
<menuitem name="Workflow" id="menu_workflow"
|
||||
parent="ir.menu_administration" groups="res.group_admin"/>
|
||||
parent="ir.menu_administration"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_workflow_group_admin">
|
||||
<field name="menu" ref="menu_workflow"/>
|
||||
<field name="group" ref="res.group_admin"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="workflow_view_form">
|
||||
<field name="model">workflow</field>
|
||||
<field name="type">form</field>
|
||||
@@ -51,8 +56,13 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="view" ref="workflow_view_form"/>
|
||||
<field name="act_window" ref="act_workflow_form"/>
|
||||
</record>
|
||||
<menuitem parent="menu_workflow" groups="res.group_admin"
|
||||
<menuitem parent="menu_workflow"
|
||||
action="act_workflow_form" id="menu_workflow_form"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_workflow_form_group_admin">
|
||||
<field name="menu" ref="menu_workflow"/>
|
||||
<field name="group" ref="res.group_admin"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_workflow">
|
||||
<field name="model" search="[('model', '=', 'workflow')]"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
@@ -95,7 +105,6 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="join_mode"/>
|
||||
<label name="split_mode"/>
|
||||
<field name="split_mode"/>
|
||||
<separator name="out_transitions" colspan="4"/>
|
||||
<field name="out_transitions" colspan="4">
|
||||
<tree string="Transitions">
|
||||
<field name="act_to"/>
|
||||
@@ -121,7 +130,6 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="trigger_expr_id"/>
|
||||
</form>
|
||||
</field>
|
||||
<separator name="in_transitions" colspan="4"/>
|
||||
<field name="in_transitions" colspan="4">
|
||||
<tree string="Transitions">
|
||||
<field name="act_from"/>
|
||||
@@ -182,8 +190,13 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="view" ref="activity_view_form"/>
|
||||
<field name="act_window" ref="act_activity_form"/>
|
||||
</record>
|
||||
<menuitem parent="menu_workflow" groups="res.group_admin"
|
||||
<menuitem parent="menu_workflow"
|
||||
action="act_activity_form" id="menu_activity_form"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_activity_form_group_admin">
|
||||
<field name="menu" ref="menu_activity_form"/>
|
||||
<field name="group" ref="res.group_admin"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_workflow_activity">
|
||||
<field name="model" search="[('model', '=', 'workflow.activity')]"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
@@ -256,8 +269,13 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="view" ref="transition_view_form"/>
|
||||
<field name="act_window" ref="act_transition_form"/>
|
||||
</record>
|
||||
<menuitem parent="menu_workflow" groups="res.group_admin"
|
||||
<menuitem parent="menu_workflow"
|
||||
action="act_transition_form" id="menu_transition_form"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_transition_form_group_admin">
|
||||
<field name="menu" ref="menu_transition_form"/>
|
||||
<field name="group" ref="res.group_admin"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_workflow_transition">
|
||||
<field name="model" search="[('model', '=', 'workflow.transition')]"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
@@ -324,8 +342,12 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="view" ref="instance_view_form"/>
|
||||
<field name="act_window" ref="act_instance_form"/>
|
||||
</record>
|
||||
<menuitem parent="menu_workflow" groups="res.group_admin"
|
||||
<menuitem parent="menu_workflow"
|
||||
action="act_instance_form" id="menu_instance_form"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_instance_form_group_admin">
|
||||
<field name="menu" ref="menu_instance_form"/>
|
||||
<field name="group" ref="res.group_admin"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="workitem_view_form">
|
||||
<field name="model">workflow.workitem</field>
|
||||
@@ -375,7 +397,11 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="view" ref="workitem_view_form"/>
|
||||
<field name="act_window" ref="act_workitem_form"/>
|
||||
</record>
|
||||
<menuitem parent="menu_workflow" groups="res.group_admin"
|
||||
<menuitem parent="menu_workflow"
|
||||
action="act_workitem_form" id="menu_workitem_form"/>
|
||||
<record model="ir.ui.menu-res.group" id="menu_workitem_form_group_admin">
|
||||
<field name="menu" ref="menu_workitem_form"/>
|
||||
<field name="group" ref="res.group_admin"/>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
||||
|
||||
Reference in New Issue
Block a user