Remove _inherits

review670002
This commit is contained in:
Cédric Krier committed 2013-03-20 22:49:16 +01:00
1 parent 9af0cc3039
commit a95ae0dad9
17 files changed
+261 -965

No files matched your search

+1
View File
@@ -1,3 +1,4 @@
* Remove _inherits
* Add dynamic label
* Add prefix, suffix on tree view
* Replace _constraints with validate in ModelStorage
-11
View File
@@ -17,17 +17,6 @@ Class attributes are:
It contains the a unique name to reference the model throughout the
platform.
.. attribute:: Model._inherits
It contains a dictionary with one or more :attr:`Model._name` as keys. For each
key a :class:`~trytond.model.fields.Many2One` field is defined as value. The
:class:`trytond.model.fields.Many2One` fields must be defined in the the current
model fields. A referenced model with ``_inherits`` is a generalization_ of the
current model which is *specialized*. In the specialized model it is possible to
interact with all attributes and methods of the general model.
.. _generalization: http://en.wikipedia.org/wiki/Class_diagram#Generalization
.. attribute:: Model.__rpc__
It contains a dictionary with method name as key and an instance of
+12 -92
View File
@@ -340,7 +340,6 @@ class Fs2bdAccessor:
self.fs2db[module] = {}
module_data_ids = self.ModelData.search([
('module', '=', module),
('inherit', '=', None),
], order=[('db_id', 'ASC')])
record_ids = {}
@@ -485,10 +484,7 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
"""
Model = record.__class__
# search the field type in the object or in a parent
if key in Model._fields:
field_type = Model._fields[key]._type
else:
field_type = Model._inherit_fields[key][2]._type
field_type = Model._fields[key]._type
# handle the value regarding to the type
if field_type == 'many2one':
@@ -520,7 +516,6 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
# problem when the corresponding recordds will be deleted:
module_data = self.ModelData.search([
('module', '=', self.module),
('inherit', '=', None),
], order=[('id', 'DESC')])
return set(rec.fs_id for rec in module_data)
@@ -558,8 +553,6 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
db_id, db_model, mdata_id, old_values = [
self.fs2db.get(module, fs_id)[x]
for x in ["db_id", "model", "id", "values"]]
inherit_db_ids = {}
inherit_mdata_ids = []
if not old_values:
old_values = {}
@@ -592,31 +585,6 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
record = self.fs2db.get_browserecord(
module, Model.__name__, record.id)
for table, field_name, field in \
Model._inherit_fields.values():
inherit_db_ids[table] = getattr(record, field_name).id
for table in inherit_db_ids.keys():
data = self.ModelData.search([
('fs_id', '=', fs_id),
('module', '=', module),
('model', '=', table),
], limit=1)
if data:
self.ModelData.write(data, {
'db_id': inherit_db_ids[table],
'inherit': True,
})
data, = data
else:
data, = self.ModelData.create([{
'fs_id': fs_id,
'module': module,
'model': table,
'db_id': inherit_db_ids[table],
'inherit': True,
}])
inherit_mdata_ids.append((table, data.id))
data = self.ModelData.search([
('fs_id', '=', fs_id),
@@ -643,22 +611,13 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
# we cannot update a field if it was changed by a user...
if key not in old_values:
if key in Model._fields:
expected_value = Model._defaults.get(
key, lambda *a: None)()
else:
Inherit = self.pool.get(
Model._inherit_fields[key][0])
expected_value = Inherit._defaults.get(
key, lambda *a: None)()
expected_value = Model._defaults.get(key,
lambda *a: None)()
else:
expected_value = old_values[key]
# Migration from 2.0: Reference field change value
if key in Model._fields:
field_type = Model._fields[key]._type
else:
field_type = Model._inherit_fields[key][2]._type
field_type = Model._fields[key]._type
if field_type == 'reference':
if (expected_value and expected_value.endswith(',0')
and not db_field):
@@ -688,19 +647,6 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
self.fs2db.reset_browsercord(
module, Model.__name__, [record.id])
if not inherit_db_ids:
for table, field_name, field in \
Model._inherit_fields.values():
inherit_db_ids[table] = getattr(record, field_name).id
if not inherit_mdata_ids:
for table in inherit_db_ids.keys():
data, = self.ModelData.search([
('fs_id', '=', fs_id),
('module', '=', module),
('model', '=', table),
], limit=1)
inherit_mdata_ids.append((table, data.id))
if to_update:
# re-read it: this ensure that we store the real value
# in the model_data table:
@@ -725,16 +671,6 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
'values': str(values),
'date_update': datetime.datetime.now(),
})
for table, inherit_mdata_id in inherit_mdata_ids:
self.ModelData.write(
[self.ModelData(inherit_mdata_id)], {
'fs_id': fs_id,
'model': table,
'module': module,
'db_id': inherit_db_ids[table],
'values': str(values),
'date_update': datetime.datetime.now(),
})
# reset_browsercord to keep cache memory low
self.fs2db.reset_browsercord(module, Model.__name__, [record.id])
@@ -742,11 +678,6 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
# this record is new, create it in the db:
with Transaction().set_context(module=module, language='en_US'):
record, = Model.create([values])
inherit_db_ids = {}
for table, field_name, field in (
Model._inherit_fields.values()):
inherit_db_ids[table] = getattr(record, field_name).id
# re-read it: this ensure that we store the real value
# in the model_data table:
@@ -754,25 +685,14 @@ class TrytondXmlHandler(sax.handler.ContentHandler):
for key in values:
values[key] = self._clean_value(key, record)
to_create = [{
'fs_id': fs_id,
'model': model,
'module': module,
'db_id': record.id,
'values': str(values),
'noupdate': self.noupdate,
}]
for table in inherit_db_ids.keys():
to_create.append({
'fs_id': fs_id,
'model': table,
'module': module,
'db_id': inherit_db_ids[table],
'values': str(values),
'inherit': True,
'noupdate': self.noupdate,
})
mdata = self.ModelData.create(to_create)[0]
mdata, = self.ModelData.create([{
'fs_id': fs_id,
'model': model,
'module': module,
'db_id': record.id,
'values': str(values),
'noupdate': self.noupdate,
}])
# update fs2db:
self.fs2db.set(module, fs_id, {
+123 -219
View File
@@ -4,8 +4,9 @@ import base64
import os
from operator import itemgetter
from collections import defaultdict
from functools import partial
from ..model import ModelView, ModelSQL, fields
from ..model import ModelView, ModelStorage, ModelSQL, fields
from ..tools import file_open, safe_eval
from ..backend import TableHandler
from ..pyson import PYSONEncoder, CONTEXT, PYSON
@@ -82,7 +83,7 @@ class Action(ModelSQL, ModelView):
@classmethod
def get_action_values(cls, type_, action_ids):
Action = Pool().get(type_)
columns = set(Action._fields.keys() + Action._inherit_fields.keys())
columns = set(Action._fields.keys())
columns.add('icon.rec_name')
to_remove = ()
if type_ == 'ir.action.report':
@@ -230,10 +231,125 @@ class ActionKeyword(ModelSQL, ModelView):
return keywords
class ActionReport(ModelSQL, ModelView):
class ActionMixin(ModelSQL):
@classmethod
def __setup__(cls):
super(ActionMixin, cls).__setup__()
for name in dir(Action):
field = getattr(Action, name)
if (isinstance(field, fields.Field)
and not getattr(cls, name, None)):
setattr(cls, name, fields.Function(field, 'get_action',
setter='set_action', searcher='search_action'))
default_func = 'default_' + name
if getattr(Action, default_func, None):
setattr(cls, default_func,
partial(ActionMixin.default_action, name))
@staticmethod
def default_action(name):
pool = Pool()
Action = pool.get('ir.action')
return getattr(Action, 'default_' + name, None)()
@classmethod
def get_action(cls, ids, names):
records = cls.browse(ids)
result = {}
for name in names:
result[name] = values = {}
for record in records:
value = getattr(record, 'action')
convert = lambda v: v
if value is not None:
value = getattr(value, name)
if isinstance(value, ModelStorage):
if cls._fields[name]._type == 'reference':
convert = str
else:
convert = int
elif isinstance(value, (list, tuple)):
convert = lambda v: [r.id for r in v]
values[record.id] = convert(value)
return result
@classmethod
def set_action(cls, records, name, value):
pool = Pool()
Action = pool.get('ir.action')
Action.write([r.action for r in records], {
name: value,
})
@classmethod
def search_action(cls, name, clause):
return [('action.' + name,) + tuple(clause[1:])]
@classmethod
def create(cls, vlist):
pool = Pool()
Action = pool.get('ir.action')
new_records = []
for values in vlist:
later = {}
action_values = {}
values = values.copy()
for field in values:
if field in Action._fields:
action_values[field] = values[field]
if hasattr(getattr(cls, field), 'set'):
later[field] = values[field]
for field in later:
del values[field]
action_values['type'] = cls.default_type()
cursor = Transaction().cursor
if cursor.nextid(cls._table):
cursor.setnextid(cls._table, cursor.currid(Action._table))
action, = Action.create([action_values])
values['action'] = action.id
record, = super(ActionMixin, cls).create([values])
cursor.execute('UPDATE "' + cls._table + '" SET id = %s '
'WHERE id = %s', (action.id, record.id))
cursor.update_auto_increment(cls._table, action.id)
record = cls(action.id)
new_records.append(record)
cls.write([record], later)
return new_records
@classmethod
def write(cls, records, values):
pool = Pool()
ActionKeyword = pool.get('ir.action.keyword')
super(ActionMixin, cls).write(records, values)
ActionKeyword._get_keyword_cache.clear()
@classmethod
def delete(cls, records):
pool = Pool()
Action = pool.get('ir.action')
actions = [x.action for x in records]
super(ActionMixin, cls).delete(records)
Action.delete(actions)
@classmethod
def copy(cls, records, default=None):
pool = Pool()
Action = pool.get('ir.action')
if default is None:
default = {}
default = default.copy()
new_records = []
for record in records:
default['action'] = Action.copy([record.action])[0].id
new_records.extend(super(ActionMixin, cls).copy([record],
default=default))
return new_records
class ActionReport(ActionMixin, ModelSQL, ModelView):
"Action report"
__name__ = 'ir.action.report'
_inherits = {'ir.action': 'action'}
model = fields.Char('Model')
report_name = fields.Char('Internal Name', required=True)
report = fields.Char('Path')
@@ -499,8 +615,6 @@ class ActionReport(ModelSQL, ModelView):
@classmethod
def copy(cls, reports, default=None):
Action = Pool().get('ir.action')
if default is None:
default = {}
default = default.copy()
@@ -511,62 +625,23 @@ class ActionReport(ModelSQL, ModelView):
if report.report:
default['report_content'] = None
default['report_name'] = report.report_name
default['action'] = Action.copy([report.action])[0].id
new_reports.extend(super(ActionReport, cls).copy([report],
default=default))
return new_reports
@classmethod
def create(cls, vlist):
new_vlist = []
for vals in vlist:
later = {}
vals = vals.copy()
for field in vals:
if (field in cls._fields
and hasattr(cls._fields[field], 'set')):
later[field] = vals[field]
for field in later:
del vals[field]
cursor = Transaction().cursor
if cursor.nextid(cls._table):
cursor.setnextid(cls._table, cursor.currid('ir_action'))
report, = super(ActionReport, cls).create([vals])
cursor.execute('SELECT action FROM "' + cls._table + '" '
'WHERE id = %s', (report.id,))
new_id, = cursor.fetchone()
cursor.execute('UPDATE "' + cls._table + '" SET id = %s '
'WHERE id = %s', (new_id, report.id))
cursor.update_auto_increment(cls._table, new_id)
report = cls(new_id)
new_vlist.append(report)
cls.write([report], later)
return new_vlist
@classmethod
def write(cls, reports, vals):
pool = Pool()
context = Transaction().context
if 'module' in context:
vals = vals.copy()
vals['module'] = context['module']
super(ActionReport, cls).write(reports, vals)
pool.get('ir.action.keyword')._get_keyword_cache.clear()
@classmethod
def delete(cls, reports):
Action = Pool().get('ir.action')
actions = [x.action for x in reports]
super(ActionReport, cls).delete(reports)
Action.delete(actions)
class ActionActWindow(ModelSQL, ModelView):
class ActionActWindow(ActionMixin, ModelSQL, ModelView):
"Action act window"
__name__ = 'ir.action.act_window'
_inherits = {'ir.action': 'action'}
domain = fields.Char('Domain Value')
context = fields.Char('Context Value')
res_model = fields.Char('Model')
@@ -771,47 +846,6 @@ class ActionActWindow(ModelSQL, ModelView):
or defaults.get(field, 'None'), CONTEXT))
return pysons
@classmethod
def create(cls, vlist):
new_vlist = []
for vals in vlist:
later = {}
vals = vals.copy()
for field in vals:
if (field in cls._fields
and hasattr(cls._fields[field], 'set')):
later[field] = vals[field]
for field in later:
del vals[field]
cursor = Transaction().cursor
if cursor.nextid(cls._table):
cursor.setnextid(cls._table, cursor.currid('ir_action'))
act_window, = super(ActionActWindow, cls).create([vals])
cursor.execute('SELECT action FROM "' + cls._table + '" '
'WHERE id = %s', (act_window.id,))
new_id, = cursor.fetchone()
cursor.execute('UPDATE "' + cls._table + '" SET id = %s '
'WHERE id = %s', (new_id, act_window.id))
cursor.update_auto_increment(cls._table, new_id)
act_window = cls(new_id)
new_vlist.append(act_window)
cls.write([act_window], later)
return new_vlist
@classmethod
def write(cls, act_windows, values):
pool = Pool()
super(ActionActWindow, cls).write(act_windows, values)
pool.get('ir.action.keyword')._get_keyword_cache.clear()
@classmethod
def delete(cls, act_windows):
Action = Pool().get('ir.action')
actions = [x.action for x in act_windows]
super(ActionActWindow, cls).delete(act_windows)
Action.delete(actions)
@classmethod
def get(cls, xml_id):
'Get values from XML id or id'
@@ -824,19 +858,6 @@ class ActionActWindow(ModelSQL, ModelView):
action_id = int(xml_id)
return Action.get_action_values(cls.__name__, [action_id])[0]
@classmethod
def copy(cls, actions, default=None):
Action = Pool().get('ir.action')
if default is None:
default = {}
default = default.copy()
new_actions = []
for act_window in actions:
default['action'] = Action.copy([act_window.action])[0].id
new_actions.extend(super(ActionActWindow, cls).copy([act_window],
default=default))
return new_actions
class ActionActWindowView(ModelSQL, ModelView):
"Action act window view"
@@ -901,10 +922,9 @@ class ActionActWindowDomain(ModelSQL, ModelView):
return True
class ActionWizard(ModelSQL, ModelView):
class ActionWizard(ActionMixin, ModelSQL, ModelView):
"Action wizard"
__name__ = 'ir.action.wizard'
_inherits = {'ir.action': 'action'}
wiz_name = fields.Char('Wizard name', required=True)
action = fields.Many2One('ir.action', 'Action', required=True,
ondelete='CASCADE')
@@ -916,68 +936,10 @@ class ActionWizard(ModelSQL, ModelView):
def default_type():
return 'ir.action.wizard'
@classmethod
def create(cls, vlist):
new_vlist = []
for vals in vlist:
later = {}
vals = vals.copy()
for field in vals:
if (field in cls._fields
and hasattr(cls._fields[field], 'set')):
later[field] = vals[field]
for field in later:
del vals[field]
cursor = Transaction().cursor
if cursor.nextid(cls._table):
cursor.setnextid(cls._table, cursor.currid('ir_action'))
wizard, = super(ActionWizard, cls).create([vals])
cursor.execute('SELECT action FROM "' + cls._table + '" '
'WHERE id = %s', (wizard.id,))
new_id, = cursor.fetchone()
cursor.execute('UPDATE "' + cls._table + '" SET id = %s '
'WHERE id = %s', (new_id, wizard.id))
cursor.update_auto_increment(cls._table, new_id)
wizard = cls(new_id)
new_vlist.append(wizard)
cls.write([wizard], later)
return new_vlist
@classmethod
def write(cls, wizards, values):
pool = Pool()
super(ActionWizard, cls).write(wizards, values)
pool.get('ir.action.keyword')._get_keyword_cache.clear()
@classmethod
def delete(cls, wizards):
pool = Pool()
Action = pool.get('ir.action')
actions = [x.action for x in wizards]
super(ActionWizard, cls).delete(wizards)
Action.delete(actions)
@classmethod
def copy(cls, wizards, default=None):
Action = Pool().get('ir.action')
if default is None:
default = {}
default = default.copy()
new_wizards = []
for wizard in wizards:
default['action'] = Action.copy([wizard.action])[0].id
new_wizards.extend(super(ActionWizard, cls).copy([wizard],
default=default))
return new_wizards
class ActionURL(ModelSQL, ModelView):
class ActionURL(ActionMixin, ModelSQL, ModelView):
"Action URL"
__name__ = 'ir.action.url'
_inherits = {'ir.action': 'action'}
url = fields.Char('Action Url', required=True)
action = fields.Many2One('ir.action', 'Action', required=True,
ondelete='CASCADE')
@@ -989,61 +951,3 @@ class ActionURL(ModelSQL, ModelView):
@staticmethod
def default_target():
return 'new'
@classmethod
def create(cls, vlist):
new_vlist = []
for vals in vlist:
later = {}
vals = vals.copy()
for field in vals:
if (field in cls._fields
and hasattr(cls._fields[field], 'set')):
later[field] = vals[field]
for field in later:
del vals[field]
cursor = Transaction().cursor
if cursor.nextid(cls._table):
cursor.setnextid(cls._table, cursor.currid('ir_action'))
url, = super(ActionURL, cls).create([vals])
cursor.execute('SELECT action FROM "' + cls._table + '" '
'WHERE id = %s', (url.id,))
new_id, = cursor.fetchone()
cls.write([url], {}) # simulate write to clear the cache
cursor.execute('UPDATE "' + cls._table + '" SET id = %s '
'WHERE id = %s', (new_id, url.id))
cursor.update_auto_increment(cls._table, new_id)
url = cls(new_id)
new_vlist.append(url)
cls.write([url], later)
return new_vlist
@classmethod
def write(cls, urls, values):
pool = Pool()
super(ActionURL, cls).write(urls, values)
pool.get('ir.action.keyword')._get_keyword_cache.clear()
@classmethod
def delete(cls, urls):
pool = Pool()
Action = pool.get('ir.action')
actions = [x.action for x in urls]
super(ActionURL, cls).delete(urls)
Action.delete(actions)
@classmethod
def copy(cls, urls, default=None):
Action = Pool().get('ir.action')
if default is None:
default = {}
default = default.copy()
new_urls = []
for url in urls:
default['action'] = Action.copy([url.action])[0].id
new_urls.extend(super(ActionURL, cls).copy([url],
default=default))
return new_urls
+14 -6
View File
@@ -666,7 +666,6 @@ class ModelData(ModelSQL, ModelView):
date_update = fields.DateTime('Update Date')
date_init = fields.DateTime('Init Date')
values = fields.Text('Values')
inherit = fields.Boolean('Inherit')
noupdate = fields.Boolean('No Update')
_get_id_cache = Cache('ir_model_data.get_id', context=False)
@@ -678,14 +677,24 @@ class ModelData(ModelSQL, ModelView):
'The triple (fs_id, module, model) must be unique!'),
]
@classmethod
def __register__(cls, module_name):
cursor = Transaction().cursor
super(ModelData, cls).__register__(module_name)
table = TableHandler(cursor, cls, module_name)
# Migration from 2.6: remove inherit
if table.column_exist('inherit'):
cursor.execute('DELETE FROM "' + cls._table + '" '
'WHERE inherit = %s', (True,))
table.drop_column('inherit', True)
@staticmethod
def default_date_init():
return datetime.datetime.now()
@staticmethod
def default_inherit():
return False
@staticmethod
def default_noupdate():
return False
@@ -708,7 +717,6 @@ class ModelData(ModelSQL, ModelView):
data = cls.search([
('module', '=', module),
('fs_id', '=', fs_id),
('inherit', '=', False),
], limit=1)
if not data:
raise Exception("Reference to %s not found"
+3 -12
View File
@@ -75,10 +75,7 @@ class Many2Many(Field):
order = self.order
Relation = Pool().get(self.relation_name)
if self.origin in Relation._fields:
origin_field = Relation._fields[self.origin]
else:
origin_field = Relation._inherit_fields[self.origin][2]
origin_field = Relation._fields[self.origin]
relations = []
for i in range(0, len(ids), Transaction().cursor.IN_MAX):
@@ -116,10 +113,7 @@ class Many2Many(Field):
return
Relation = pool.get(self.relation_name)
Target = self.get_target()
if self.origin in Relation._fields:
origin_field = Relation._fields[self.origin]
else:
origin_field = Relation._inherit_fields[self.origin][2]
origin_field = Relation._fields[self.origin]
def search_clause(ids):
if origin_field._type == 'reference':
@@ -228,10 +222,7 @@ class Many2Many(Field):
Relation = Pool().get(self.relation_name)
if not self.target:
return Relation
if self.target in Relation._fields:
return Relation._fields[self.target].get_target()
else:
return Relation._inherit_fields[self.target][2].get_target()
return Relation._fields[self.target].get_target()
def __set__(self, inst, value):
Target = self.get_target()
+2 -8
View File
@@ -79,10 +79,7 @@ class One2Many(Field):
'''
pool = Pool()
Relation = pool.get(self.model_name)
if self.field in Relation._fields:
field = Relation._fields[self.field]
else:
field = Relation._inherit_fields[self.field][2]
field = Relation._fields[self.field]
res = {}
for i in ids:
res[i] = []
@@ -119,10 +116,7 @@ class One2Many(Field):
if not values:
return
Target = self.get_target()
if self.field in Target._fields:
field = Target._fields[self.field]
else:
field = Target._inherit_fields[self.field][2]
field = Target._fields[self.field]
def search_clause(ids):
if field._type == 'reference':
+6 -85
View File
@@ -16,33 +16,11 @@ from trytond.rpc import RPC
__all__ = ['Model']
class ModelMeta(PoolMeta):
def __getattr__(self, name):
pool = Pool()
for model_name, _ in self._inherits.iteritems():
Model = pool.get(model_name)
if isinstance(getattr(Model, name, None),
collections.Callable):
meth = getattr(Model, name)
if not hasattr(meth, 'im_self') or meth.im_self:
# Return classmethod bounded to inherited class
return meth
else:
for cls in Model.__mro__:
if name in cls.__dict__:
# Return a method bounded to current class
return cls.__dict__[name].__get__(None, self)
raise AttributeError("'%s' Model has no attribute '%s'"
% (self.__name__, name))
class Model(WarningErrorMixin, URLMixin):
"""
Define a model in Tryton.
"""
__metaclass__ = ModelMeta
_inherits = {}
__metaclass__ = PoolMeta
_rec_name = 'name'
id = fields.Integer('ID', readonly=True)
@@ -76,48 +54,21 @@ class Model(WarningErrorMixin, URLMixin):
if isinstance(getattr(cls, attr), fields.Field):
cls._fields[attr] = getattr(cls, attr)
# Set _inherit_fields
cls._inherit_fields = {}
for model_name in cls._inherits:
Model = pool.get(model_name)
cls._inherit_fields.update(Model._inherit_fields)
for field_name in Model._fields.keys():
cls._inherit_fields[field_name] = (model_name,
cls._inherits[model_name],
Model._fields[field_name])
for field_name in Model._inherit_fields.keys():
cls._inherit_fields[field_name] = (model_name,
cls._inherits[model_name],
Model._inherit_fields[field_name][2])
# Update models that uses this one in _inherits
for _, Model in pool.iterobject():
if cls.__name__ in Model._inherits:
Model.__post_setup__()
# Set _defaults
cls._defaults = {}
fields_names = cls._fields.keys()
fields_names += cls._inherit_fields.keys()
for field_name in fields_names:
default_method = getattr(cls, 'default_%s' % field_name, False)
if not default_method and field_name in cls._inherit_fields:
icls = pool.get(cls._inherit_fields[field_name][0])
default_method = getattr(icls, 'default_%s' % field_name,
False)
if isinstance(default_method, collections.Callable):
cls._defaults[field_name] = default_method
for k in cls._defaults:
assert (k in cls._fields) or (k in cls._inherit_fields), \
assert k in cls._fields, \
'Default function defined in %s but field %s does not exist!' \
% (cls.__name__, k,)
# Update __rpc__
for field_name in cls._fields.keys() + cls._inherit_fields.keys():
if field_name in cls._fields:
field = cls._fields[field_name]
else:
field = cls._inherit_fields[field_name][2]
for field_name, field in cls._fields.iteritems():
if isinstance(field, (fields.Selection, fields.Reference)) \
and not isinstance(field.selection, (list, tuple)) \
and field.selection not in cls.__rpc__:
@@ -364,10 +315,7 @@ class Model(WarningErrorMixin, URLMixin):
for field_name in fields_names:
if field_name in cls._defaults:
value[field_name] = cls._defaults[field_name]()
if field_name in cls._fields:
field = cls._fields[field_name]
else:
field = cls._inherit_fields[field_name][2]
field = cls._fields[field_name]
if (field._type == 'boolean'
and not field_name in value):
value[field_name] = False
@@ -397,8 +345,6 @@ class Model(WarningErrorMixin, URLMixin):
pool = Pool()
res = value.copy()
val = {}
for i in cls._inherits.keys():
val.update(pool.get(i)._default_on_change(value))
for field in value.keys():
if field in cls._fields:
if cls._fields[field].on_change:
@@ -423,9 +369,6 @@ class Model(WarningErrorMixin, URLMixin):
Translation = pool.get('ir.translation')
FieldAccess = pool.get('ir.model.field.access')
for parent in cls._inherits:
res.update(pool.get(parent).fields_get(fields_names))
#Add translation to cache
language = Transaction().language
trans_args = []
@@ -619,19 +562,6 @@ class Model(WarningErrorMixin, URLMixin):
def __getattr__(self, name):
if name == 'id':
return self.__dict__['id']
if (name not in self._fields
and name not in self._inherit_fields):
# Search for method on inherits parents
pool = Pool()
for model_name, _ in self._inherits.iteritems():
iModel = pool.get(model_name)
if isinstance(getattr(iModel, name, None),
collections.Callable):
for cls in iModel.__mro__:
if name in cls.__dict__:
# Return a method bounded to current class
return cls.__dict__[name].__get__(self,
self.__class__)
elif self._values and name in self._values:
return self._values.get(name)
raise AttributeError("'%s' Model has no attribute '%s': %s"
@@ -641,11 +571,6 @@ class Model(WarningErrorMixin, URLMixin):
if name == 'id':
self.__dict__['id'] = value
return
if (name not in self._fields
and name in self._inherit_fields):
field = self._inherit_fields[name][2]
field.__set__(self, value)
return
super(Model, self).__setattr__(name, value)
def __getitem__(self, name):
@@ -654,8 +579,7 @@ class Model(WarningErrorMixin, URLMixin):
return getattr(self, name)
def __contains__(self, name):
return (name in self._fields
or name in self._inherit_fields)
return name in self._fields
def __int__(self):
return int(self.id)
@@ -700,10 +624,7 @@ class Model(WarningErrorMixin, URLMixin):
values = {}
if self._values:
for fname, value in self._values.iteritems():
if fname in self._fields:
field = self._fields[fname]
else:
field = self._inherit_fields[fname][2]
field = self._fields[fname]
if isinstance(field, fields.Reference):
if value is not None:
value = str(value)
+1 -2
View File
@@ -32,8 +32,7 @@ class ModelSingleton(ModelStorage):
if not singleton:
res = cls.default_get(fields_names, with_rec_name=False)
if not fields_names:
fields_names = (set(cls._fields.keys()
+ cls._inherit_fields.keys()))
fields_names = cls._fields.keys()
for field_name in fields_names:
if field_name not in res:
res[field_name] = None
+25 -235
View File
@@ -240,20 +240,11 @@ class ModelSQL(ModelStorage):
# Get default values
default = []
avoid_table = []
for (i, j) in cls._inherits.items():
if j in values:
avoid_table.append(i)
for i in cls._fields.keys():
if not i in values \
and i not in ('create_uid', 'create_date',
'write_uid', 'write_date'):
default.append(i)
for i in cls._inherit_fields.keys():
if ((not i in values)
and (not cls._inherit_fields[i][0] in avoid_table)
and i in cls._defaults):
default.append(i)
if len(default):
defaults = cls.default_get(default, with_rec_name=False)
@@ -269,26 +260,6 @@ class ModelSQL(ModelStorage):
(upd0, upd1, upd2) = ('', '', [])
# Create inherits
tocreate = {}
for i in cls._inherits:
if cls._inherits[i] not in values:
tocreate[i] = {}
for i in values.keys():
if i in cls._inherit_fields:
(inherits, _, _) = cls._inherit_fields[i]
if i in cls._fields:
continue
if inherits in tocreate:
tocreate[inherits][i] = values[i]
del values[i]
for inherits in tocreate:
Inherits = pool.get(inherits)
inherits_record, = Inherits.create([tocreate[inherits]])
values[cls._inherits[inherits]] = inherits_record.id
# Insert record
for fname, value in values.iteritems():
field = cls._fields[fname]
@@ -433,8 +404,7 @@ class ModelSQL(ModelStorage):
cursor = Transaction().cursor
if not fields_names:
fields_names = list(set(cls._fields.keys()
+ cls._inherit_fields.keys()))
fields_names = cls._fields.keys()
if not ids:
return []
@@ -451,19 +421,15 @@ class ModelSQL(ModelStorage):
field, field_related = field_name.split('.', 1)
fields_related.setdefault(field, [])
fields_related[field].append(field_related)
elif field_name in cls._fields:
field = cls._fields[field_name]
else:
field = cls._inherit_fields[field_name][2]
field = cls._fields[field_name]
if hasattr(field, 'datetime_field') and field.datetime_field:
datetime_fields.append(field.datetime_field)
# all inherited fields + all non inherited fields
fields_pre = [x for x in
fields_names + fields_related.keys() + datetime_fields
if ((x in cls._fields
and not hasattr(cls._fields[x], 'set'))
or (x == '_timestamp'))] + cls._inherits.values()
fields_pre = [x
for x in fields_names + fields_related.keys() + datetime_fields
if (x in cls._fields and not hasattr(cls._fields[x], 'set'))
or (x == '_timestamp')]
res = []
table_query = ''
@@ -546,41 +512,9 @@ class ModelSQL(ModelStorage):
for i in res:
i[field] = res_trans.get(i['id'], False) or i[field]
for table in cls._inherits:
field = cls._inherits[table]
inherits_fields = list(
set(cls._inherit_fields.keys()).intersection(
set(fields_names + fields_related.keys() + datetime_fields)
).difference(set(cls._fields.keys())))
if not inherits_fields:
for record in res:
if field not in fields_names + fields_related.keys() + \
datetime_fields:
del record[field]
continue
inherit_related_fields = []
for inherit_field in inherits_fields:
if inherit_field in fields_related:
for field_related in fields_related[inherit_field]:
inherit_related_fields.append(
inherit_field + '.' + field_related)
res2 = pool.get(table).read([x[field] for x in res],
fields_names=inherits_fields + inherit_related_fields)
res3 = {}
for i in res2:
res3[i['id']] = i
del i['id']
for record in res:
record.update(res3[record[field]])
if field not in \
fields_names + fields_related.keys() + datetime_fields:
del record[field]
ids = [x['id'] for x in res]
# all non inherited fields for which there is a get attribute
# all fields for which there is a get attribute
fields_post = [x for x in
fields_names + fields_related.keys() + datetime_fields
if x in cls._fields and hasattr(cls._fields[x], 'get')]
@@ -777,22 +711,17 @@ class ModelSQL(ModelStorage):
upd0 = []
upd1 = []
upd_todo = []
updend = []
direct = []
for field in values:
if field in cls._fields:
if not hasattr(cls._fields[field], 'set'):
if ((not getattr(cls._fields[field], 'translate', False))
or (Transaction().language
== Config.get_language())):
upd0.append(('"' + field + '"', '%s'))
upd1.append(FIELDS[cls._fields[field]._type]
.sql_format(values[field]))
direct.append(field)
else:
upd_todo.append(field)
if not hasattr(cls._fields[field], 'set'):
if ((not getattr(cls._fields[field], 'translate', False))
or (Transaction().language == Config.get_language())):
upd0.append(('"' + field + '"', '%s'))
upd1.append(FIELDS[cls._fields[field]._type]
.sql_format(values[field]))
direct.append(field)
else:
updend.append(field)
upd_todo.append(field)
upd0.append(('write_uid', '%s'))
upd0.append(('write_date', '%s'))
@@ -894,24 +823,6 @@ class ModelSQL(ModelStorage):
'FROM "' + cls._table + '" '
'WHERE id = %s', (obj_id,))
for iname in cls._inherits:
col = cls._inherits[iname]
iids = []
for i in range(0, len(ids), cursor.IN_MAX):
sub_ids = ids[i:i + cursor.IN_MAX]
red_sql, red_ids = reduce_ids('id', sub_ids)
cursor.execute('SELECT DISTINCT "' + col + '" '
'FROM "' + cls._table + '" WHERE ' + red_sql,
red_ids)
iids.extend([x[0] for x in cursor.fetchall()])
values2 = {}
for val in updend:
if cls._inherit_fields[val][0] == iname:
values2[val] = values[val]
IModel = pool.get(iname)
IModel.write(IModel.browse(iids), values2)
cls._validate(records)
# Check for Modified Preorder Tree Traversal
@@ -1330,41 +1241,6 @@ class ModelSQL(ModelStorage):
domain = domain[:]
cursor = Transaction().cursor
def column_get(model, field_name):
field = model._fields.get(field_name)
if not field:
if not field_name in model._inherit_fields:
raise Exception('ValidateError', 'Field "%s" doesn\'t '
'exist on "%s"' % (field_name, model.__name__))
parent_model = pool.get(model._inherit_fields[field_name][0])
field = column_get(parent_model, field_name)
return field
def get_model_for_field(model, field):
if field in model._fields:
return model
else:
parent_model = pool.get(model._inherit_fields[field][0])
return get_model_for_field(parent_model, field)
def get_inherits_join(model, field):
if field in model._fields:
return []
itable = pool.get(model._inherit_fields[field][0])
table_query = ''
table_arg = []
if itable.table_query():
table_query, table_args = model.table_query()
table_query = '(' + table_query + ') AS '
table_join = ('LEFT JOIN ' + table_query +
'"' + itable._table + '" ON '
'"%s".id = "%s"."%s"'
% (itable._table, model._table,
model._inherits[itable.__name__]))
inherits = [(table_join, table_arg)]
inherits.extend(get_inherits_join(itable, field))
return inherits
for arg in domain:
if arg[1] not in OPERATORS:
raise Exception('ValidateError', 'Argument "%s" not supported'
@@ -1373,21 +1249,13 @@ class ModelSQL(ModelStorage):
joins = []
while i < len(domain):
fargs = domain[i][0].split('.', 1)
if fargs[0] in cls._inherit_fields:
inherit_joins = get_inherits_join(cls, fargs[0])
for (table_join, table_arg) in inherit_joins:
if table_join not in tables:
tables.append(table_join)
tables_args.extend(table_arg)
field = column_get(cls, fargs[0])
table = get_model_for_field(cls, fargs[0])
field = getattr(cls, fargs[0])
table = cls
if len(fargs) > 1:
if field._type == 'many2one':
Target = pool.get(field.model_name)
m2o_search = [(fargs[1], domain[i][1], domain[i][2])]
if ('active' in Target._fields
or 'active' in Target._inherit_fields):
if 'active' in Target._fields:
m2o_search += [('active', 'in', (True, False))]
if hasattr(field, 'search'):
domain.extend([(fargs[0], 'in',
@@ -1411,10 +1279,7 @@ class ModelSQL(ModelStorage):
else:
Relation = Target
origin, target = field.field, 'id'
if origin in Relation._fields:
rev_field = Relation._fields[origin]
else:
rev_field = Relation._inherit_fields[origin][2]
rev_field = Relation._fields[origin]
if rev_field._type == 'reference':
sql_type = FIELDS[
cls.id._type].sql_type(cls.id)[0]
@@ -1452,10 +1317,7 @@ class ModelSQL(ModelStorage):
if Field.table_query():
table_query, table_args = Field.table_query()
table_query = '(' + table_query + ') AS '
if field.field in Field._fields:
rev_field = Field._fields[field.field]
else:
rev_field = Field._inherit_fields[field.field][2]
rev_field = Field._fields[field.field]
if rev_field._type == 'reference':
sql_type = FIELDS[cls.id._type].sql_type(cls.id)[0]
select = ('CAST(SPLIT_PART("%s", \',\', 2) AS %s)'
@@ -1546,11 +1408,7 @@ class ModelSQL(ModelStorage):
if Relation.table_query():
table_query, table_args = Relation.table_query()
table_query = '(' + table_query + ') AS '
if field.origin in Relation._fields:
origin_field = Relation._fields[field.origin]
else:
origin_field = \
Relation._inherit_fields[field.origin][2]
origin_field = Relation._fields[field.origin]
if origin_field._type == 'reference':
sql_type = FIELDS[cls.id._type].sql_type(cls.id)[0]
select = ('CAST(SPLIT_PART("%s", \',\', 2) AS %s)'
@@ -1650,8 +1508,7 @@ class ModelSQL(ModelStorage):
if isinstance(domain[i][2], basestring):
Field = pool.get(field.model_name)
m2o_search = [('rec_name', domain[i][1], domain[i][2])]
if ('active' in Field._fields
or 'active' in Field._inherit_fields):
if 'active' in Field._fields:
m2o_search += [('active', 'in', (True, False))]
res_ids = map(int, Field.search(m2o_search, order=[]))
domain[i] = (domain[i][0], 'in', res_ids, table)
@@ -1722,10 +1579,10 @@ class ModelSQL(ModelStorage):
qu1, qu2 = [], []
for arg in domain:
table = get_model_for_field(cls, arg[0])
if table == cls and len(arg) > 3:
table = cls
if len(arg) > 3:
table = arg[3]
column = column_get(table, arg[0])
column = getattr(table, arg[0])
if arg[1] in ('inselect', 'notinselect'):
clause = 'IN'
if arg[1] == 'notinselect':
@@ -1914,61 +1771,6 @@ class ModelSQL(ModelStorage):
tables.insert(0, table_join)
return order_by, tables, tables_args
obj2 = None
if obj._rec_name in obj._inherit_fields.keys():
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 = pool.get(
obj._inherit_fields[obj._order_name][0])
field_name = obj._order_name
if obj2 and field_name:
table_name2 = obj2._table
link_field2 = obj._inherits[obj2.__name__]
order_by, tables, tables_args = \
obj2._order_calc(field_name, otype)
table_join = ('LEFT JOIN "' + table_name + '" AS '
'"' + table_name + '.' + link_field + '" ON '
'"%s.%s".id = "%s"."%s"'
% (table_name, link_field, cls._table, link_field))
for i in range(len(order_by)):
if table_name in order_by[i]:
order_by[i] = order_by[i].replace(table_name,
table_name + '.' + link_field)
for i in range(len(tables)):
if table_name in tables[i]:
args = tables_args.pop(tables[i], [])
tables[i] = tables[i].replace(table_name,
table_name + '.' + link_field)
tables_args[tables[i]] = args
if table_join not in tables:
tables.insert(0, table_join)
tables_args[table_join] = []
table_join2 = ('LEFT JOIN "' + table_name2 + '" AS '
'"' + table_name2 + '.' + link_field2 + '" ON '
'"%s.%s".id = "%s.%s"."%s"'
% (table_name2, link_field2, table_name, link_field,
link_field2))
for i in range(len(order_by)):
if table_name2 in order_by[i]:
order_by[i] = order_by[i].replace(table_name2,
table_name2 + '.' + link_field2)
for i in range(1, len(tables)):
if table_name2 in tables[i]:
args = tables_args.pop(tables[i], [])
tables[i] = tables[i].replace(table_name2,
table_name2 + '.' + link_field2)
tables_args[tables[i]] = args
if table_join2 not in tables:
tables.insert(1, table_join2)
tables_args[table_join2] = []
return order_by, tables, tables_args
if (field_name in cls._fields
and getattr(cls._fields[field_name], 'translate', False)):
translation_table = ('ir_translation_%s_%s'
@@ -2049,18 +1851,6 @@ class ModelSQL(ModelStorage):
% (table_name, field_name, otype))
return order_by, tables, tables_args
if field in cls._inherit_fields.keys():
obj = pool.get(cls._inherit_fields[field][0])
table_name = obj._table
link_field = cls._inherits[obj.__name__]
order_by, tables, tables_args = obj._order_calc(field, otype)
table_join = ('LEFT JOIN "' + table_name + '" ON '
'"%s".id = "%s"."%s"'
% (table_name, cls._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) for %s in order!' %
(field, cls.__name__))
+18 -68
View File
@@ -15,7 +15,7 @@ except ImportError:
import StringIO
from decimal import Decimal
from itertools import islice, ifilter, ifilterfalse, chain, izip
from itertools import islice, ifilter, chain, izip
from functools import reduce
from trytond.model import Model
@@ -304,10 +304,7 @@ class ModelStorage(Model):
field_defs[field_name]['relation'])
relation_field = field_defs[field_name]['relation_field']
if relation_field:
if relation_field in Relation._fields:
field = Relation._fields[relation_field]
else:
field = Relation._inherit_fields[relation_field][2]
field = Relation._fields[relation_field]
if field._type == 'reference':
value = str(new_record)
else:
@@ -368,8 +365,7 @@ class ModelStorage(Model):
records = cls.search(domain, offset=offset, limit=limit, order=order)
if not fields_names:
fields_names = list(set(cls._fields.keys()
+ cls._inherit_fields.keys()))
fields_names = cls._fields.keys()
if 'id' not in fields_names:
fields_names.append('id')
return cls.read(map(int, records), fields_names)
@@ -380,10 +376,9 @@ class ModelStorage(Model):
domain = reduce_domain(domain)
# if the object has a field named 'active', filter out all inactive
# records unless they were explicitely asked for
if not (('active' in cls._fields
or 'active' in cls._inherit_fields.keys())
and (active_test
and Transaction().context.get('active_test', True))):
if not ('active' in cls._fields
and active_test
and Transaction().context.get('active_test', True)):
return domain
def process(domain):
@@ -417,8 +412,7 @@ class ModelStorage(Model):
It is used by the Function field rec_name.
'''
rec_name = self._rec_name
if (rec_name not in self._fields
and rec_name not in self._inherit_fields):
if rec_name not in self._fields:
rec_name = 'id'
return unicode(getattr(self, rec_name))
@@ -428,8 +422,7 @@ class ModelStorage(Model):
Return a list of arguments for search on rec_name.
'''
rec_name = cls._rec_name
if (rec_name not in cls._fields
and rec_name not in cls._inherit_fields):
if rec_name not in cls._fields:
return []
return [(rec_name,) + clause[1:]]
@@ -470,13 +463,7 @@ class ModelStorage(Model):
break
field_name = fields_tree[i]
eModel = pool.get(value.__name__)
if field_name in eModel._fields:
field = eModel._fields[field_name]
elif field_name in eModel._inherit_fields:
field = eModel._inherit_fields[field_name][2]
else:
raise Exception('Field %s not available on object "%s"'
% (field_name, eModel.__name__))
field = eModel._fields[field_name]
if field.states and 'invisible' in field.states:
pyson_invisible = PYSONEncoder().encode(
field.states['invisible'])
@@ -833,13 +820,7 @@ class ModelStorage(Model):
Function that checks if there is no recursion in the tree
composed with parent as parent field name.
'''
if parent in cls._fields:
parent_type = cls._fields[parent]._type
elif parent in cls._inherit_fields:
parent_type = cls._inherit_fields[parent][2]._type
else:
raise Exception('Field %s not available on object "%s"'
% (parent, cls.__name__))
parent_type = cls._fields[parent]._type
if parent_type not in ('many2one', 'many2many'):
raise Exception(
@@ -1161,8 +1142,7 @@ class ModelStorage(Model):
pool = Pool()
vals = {}
for field in defaults.keys():
fld_def = (field in cls._fields) and cls._fields[field] \
or cls._inherit_fields[field][2]
fld_def = cls._fields[field]
if fld_def._type in ('many2one', 'one2one'):
if isinstance(defaults[field], (list, tuple)):
vals[field] = defaults[field][0]
@@ -1223,13 +1203,10 @@ class ModelStorage(Model):
self._local_cache.counter = counter
# fetch the definition of the field
if name in self._fields:
try:
field = self._fields[name]
elif name in self._inherit_fields:
field = self._inherit_fields[name][2]
else:
raise AttributeError("'%s' Model has no attribute '%s'"
% (self.__name__, name))
except KeyError:
raise AttributeError('"%s" has no attribute "%s"' % (self, name))
try:
return self._local_cache[self.id][name]
@@ -1248,17 +1225,12 @@ class ModelStorage(Model):
if field.loading == 'eager':
FieldAccess = Pool().get('ir.model.field.access')
fread_accesses = {}
for inherit_name in self._inherits:
Inherit = Pool().get(inherit_name)
fread_accesses.update(FieldAccess.check(inherit_name,
Inherit._fields.keys(), 'read', access=True))
fread_accesses.update(FieldAccess.check(self.__name__,
self._fields.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._fields)
def not_cached(item):
fname, field = item
@@ -1274,17 +1246,6 @@ class ModelStorage(Model):
fname, field = item
return fname in self._fields
if inherit_threshold > 0:
ifields = ((fname, field)
for fname, (_, _, field) in
self._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._fields.iteritems()))
@@ -1294,11 +1255,7 @@ class ModelStorage(Model):
# add datetime_field
for field in ffields.values():
if hasattr(field, 'datetime_field') and field.datetime_field:
if field.datetime_field in self._fields:
datetime_field = self._fields[field.datetime_field]
else:
datetime_field = self._inherit_fields[
field.datetime_field][2]
datetime_field = self._fields[field.datetime_field]
ffields[field.datetime_field] = datetime_field
def filter_(id_):
@@ -1393,10 +1350,7 @@ class ModelStorage(Model):
if not self._values:
return values
for fname, value in self._values.iteritems():
if fname in self._fields:
field = self._fields[fname]
else:
field = self._inherit_fields[fname][2]
field = self._fields[fname]
if field._type in ('many2one', 'one2one', 'reference'):
if value:
if value.id < 0 and field._type != 'reference':
@@ -1453,14 +1407,10 @@ class EvalEnvironment(dict):
def __getitem__(self, item):
if item.startswith('_parent_'):
field = item[8:]
if field in self._model._fields:
model_name = self._model._fields[field].model_name
else:
model_name = self._model._inherit_fields[field][2].model_name
model_name = self._model._fields[field].model_name
ParentModel = Pool().get(model_name)
return EvalEnvironment(getattr(self._record, field), ParentModel)
if (item in self._model._fields
or item in self._model._inherit_fields):
if item in self._model._fields:
value = getattr(self._record, item)
if isinstance(value, Model):
return value.id
+2 -31
View File
@@ -327,24 +327,6 @@ class ModelView(Model):
if field_to_remove in field.depends:
fields_to_remove.append(name)
# Find field inherited without read access
for inherit_name in cls._inherits:
Inherit = pool.get(inherit_name)
fread_accesses = FieldAccess.check(Inherit.__name__,
Inherit._fields.keys(), 'read', access=True)
fields_to_remove += list(x for x, y in fread_accesses.iteritems()
if not y and x not in cls._fields.keys())
# Find relation field without read access
for name, field in Inherit._fields.iteritems():
if not check_relation(Inherit, field):
fields_to_remove.append(name)
for name, field in Inherit._fields.iteritems():
for field_to_remove in fields_to_remove:
if field_to_remove in field.depends:
fields_to_remove.append(name)
# Remove field without read access
for field in fields_to_remove:
for element in tree.xpath(
@@ -372,26 +354,19 @@ class ModelView(Model):
if field_children:
fields_def.setdefault(field_children, {'name': field_children})
model, field = None, None
if field_children in cls._fields:
model = cls
field = cls._fields[field_children]
elif field_children in cls._inherit_fields:
model_name, model, field = cls._inherit_fields[field_children]
if model and field and field.model_name == model.__name__:
fields_def.setdefault(field.field, {'name': field.field})
for field_name in fields_def.keys():
if field_name in cls._fields:
field = cls._fields[field_name]
elif field_name in cls._inherit_fields:
field = cls._inherit_fields[field_name][2]
else:
continue
for depend in field.depends:
fields_def.setdefault(depend, {'name': depend})
if ('active' in cls._fields) or ('active' in cls._inherit_fields):
if 'active' in cls._fields:
fields_def.setdefault('active', {'name': 'active'})
arch = etree.tostring(tree, encoding='utf-8', pretty_print=False)
@@ -424,11 +399,7 @@ class ModelView(Model):
if element.get(attr):
fields_attrs.setdefault(element.get(attr), {})
try:
if element.get(attr) in cls._fields:
field = cls._fields[element.get(attr)]
else:
field = cls._inherit_fields[element.get(
attr)][2]
field = cls._fields[element.get(attr)]
if hasattr(field, 'model_name'):
relation = field.model_name
else:
+53
View File
@@ -459,6 +459,59 @@ this repository contains the full copyright notices and license terms. -->
<field name="domain">[('groups', '=', None)]</field>
<field name="rule_group" ref="rule_group_action_keyword"/>
</record>
<record model="ir.rule.group" id="rule_group_action_report">
<field name="model" search="[('model', '=', 'ir.action.report')]"/>
<field name="global_p" eval="True"/>
</record>
<record model="ir.rule" id="rule_action_report1">
<field name="domain">[('groups', 'in', [g.id for g in user.groups])]</field>
<field name="rule_group" ref="rule_group_action_report"/>
</record>
<record model="ir.rule" id="rule_action_report2">
<field name="domain">[('groups', '=', None)]</field>
<field name="rule_group" ref="rule_group_action_report"/>
</record>
<record model="ir.rule.group" id="rule_group_action_act_window">
<field name="model" search="[('model', '=', 'ir.action.act_window')]"/>
<field name="global_p" eval="True"/>
</record>
<record model="ir.rule" id="rule_action_act_window1">
<field name="domain">[('groups', 'in', [g.id for g in user.groups])]</field>
<field name="rule_group" ref="rule_group_action_act_window"/>
</record>
<record model="ir.rule" id="rule_action_act_window2">
<field name="domain">[('groups', '=', None)]</field>
<field name="rule_group" ref="rule_group_action_act_window"/>
</record>
<record model="ir.rule.group" id="rule_group_action_wizard">
<field name="model" search="[('model', '=', 'ir.action.wizard')]"/>
<field name="global_p" eval="True"/>
</record>
<record model="ir.rule" id="rule_action_wizard1">
<field name="domain">[('groups', 'in', [g.id for g in user.groups])]</field>
<field name="rule_group" ref="rule_group_action_wizard"/>
</record>
<record model="ir.rule" id="rule_action_wizard2">
<field name="domain">[('groups', '=', None)]</field>
<field name="rule_group" ref="rule_group_action_wizard"/>
</record>
<record model="ir.rule.group" id="rule_group_action_url">
<field name="model" search="[('model', '=', 'ir.action.url')]"/>
<field name="global_p" eval="True"/>
</record>
<record model="ir.rule" id="rule_action_url1">
<field name="domain">[('groups', 'in', [g.id for g in user.groups])]</field>
<field name="rule_group" ref="rule_group_action_url"/>
</record>
<record model="ir.rule" id="rule_action_url2">
<field name="domain">[('groups', '=', None)]</field>
<field name="rule_group" ref="rule_group_action_url"/>
</record>
<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"/>
-5
View File
@@ -90,11 +90,6 @@ def register():
DictRequired,
Singleton,
URLObject,
ModelInherits,
ModelInheritsSubModel,
ModelInheritsSubSubModel,
ModelInheritsSubSubSubModel,
ModelInheritsOverriddenFieldModel,
ModelSQLRequiredField,
MPTT,
ImportDataBoolean,
+1 -50
View File
@@ -3,9 +3,7 @@
from trytond.model import ModelSingleton, ModelSQL, fields
__all__ = [
'Singleton', 'URLObject', 'ModelInherits', 'ModelInheritsSubModel',
'ModelInheritsSubSubModel', 'ModelInheritsSubSubSubModel',
'ModelInheritsOverriddenFieldModel', 'ModelSQLRequiredField'
'Singleton', 'URLObject', 'ModelSQLRequiredField',
]
@@ -25,53 +23,6 @@ class URLObject(ModelSQL):
name = fields.Char('Name')
class ModelInherits(ModelSQL):
'Model Inherits'
__name__ = 'test.model_inherits'
name = fields.Char('Name')
class ModelInheritsSubModel(ModelSQL):
'Model Inherits Sub-Model'
__name__ = 'test.submodel'
_inherits = {'test.model_inherits': 'parent_model'}
subfield = fields.Char('SubField')
parent_model = fields.Many2One('test.model_inherits', 'Parent model',
required=True)
class ModelInheritsSubSubModel(ModelSQL):
'Model Inherits Sub-Sub-Model'
__name__ = 'test.subsubmodel'
_inherits = {'test.submodel': 'parent_model'}
subsubfield = fields.Char('SubField')
parent_model = fields.Many2One('test.submodel', 'Parent model',
required=True)
class ModelInheritsSubSubSubModel(ModelSQL):
'Model Inherits Sub-Sub-Sub-Model'
__name__ = 'test.subsubsubmodel'
_inherits = {'test.subsubmodel': 'parent_model'}
subsubsubfield = fields.Char('SubField')
parent_model = fields.Many2One('test.subsubmodel', 'Parent model',
required=True)
class ModelInheritsOverriddenFieldModel(ModelSQL):
'Model Inherits Overridden Field Model'
__name__ = 'test.overriddeninheritedfieldmodel'
_inherits = {'test.subsubmodel': 'parent_model'}
subfield = fields.Integer('Overridden field')
parent_model = fields.Many2One('test.subsubmodel', 'Parent model',
required=True)
class ModelSQLRequiredField(ModelSQL):
'model with a required field'
__name__ = 'test.modelsql'
-139
View File
@@ -1,139 +0,0 @@
#!/usr/bin/env python
# -*- 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.
import unittest
from trytond.tests.test_tryton import POOL, DB_NAME, USER, CONTEXT, \
install_module
from trytond.transaction import Transaction
class ModelInheritsTestCase(unittest.TestCase):
'''
Test ModelInheritSearch
'''
def setUp(self):
install_module('test')
self.parent = POOL.get('test.model_inherits')
self.sub = POOL.get('test.submodel')
self.subsub = POOL.get('test.subsubmodel')
self.subsubsub = POOL.get('test.subsubsubmodel')
self.overridden = POOL.get('test.overriddeninheritedfieldmodel')
def create_data(self):
parent_id, = self.parent.create([{'name': 'parent'}])
sub_id, = self.sub.create([{
'name': 'sub',
'subfield': 'level1',
}])
subsub_id, = self.subsub.create([{
'name': 'subsub',
'subfield': 'level2',
'subsubfield': 'ssfcontent',
}])
subsubsub_id, = self.subsubsub.create([{
'name': 'subsubsub',
'subfield': 'level3',
'subsubfield': 'ssfcontent2',
'subsubsubfield': 'sssfcontent',
}])
overridden_id, = self.overridden.create([{
'name': 'overridden',
'subfield': 3,
}])
return (parent_id, sub_id, subsub_id, subsubsub_id, overridden_id)
def test0010selfsearch(self):
'''
Test searching on own field
'''
with Transaction().start(DB_NAME, USER,
context=CONTEXT) as transaction:
(_parent_id, _sub_id, _subsub_id, subsubsub_id, overridden_id) = \
self.create_data()
ids = self.subsubsub.search([
('subsubsubfield', '=', 'sssfcontent'),
])
self.assertEqual(ids, [subsubsub_id])
transaction.cursor.rollback()
def test0020parentsearch(self):
'''
Test searching on parent field
'''
with Transaction().start(DB_NAME, USER,
context=CONTEXT) as transaction:
(_parent_id, _sub_id, _subsub_id, subsubsub_id, overridden_id) = \
self.create_data()
ids = self.subsubsub.search([('subsubfield', '=', 'ssfcontent2')])
self.assertEqual(ids, [subsubsub_id])
ids = self.subsubsub.search([('subsubfield', '=', 'ssfcontent')])
self.assertEqual(ids, [])
transaction.cursor.rollback()
def test0030granparentsearch(self):
'''
Test searching on granparent field
'''
with Transaction().start(DB_NAME, USER,
context=CONTEXT) as transaction:
(_parent_id, _sub_id, _subsub_id, subsubsub_id, overridden_id) = \
self.create_data()
ids = self.subsubsub.search([('subfield', '=', 'level3')])
self.assertEqual(ids, [subsubsub_id])
ids = self.subsubsub.search([('subfield', '=', 'level1')])
self.assertEqual(ids, [])
transaction.cursor.rollback()
def test0040greatgranparentsearch(self):
'''
Test searching on greatgranparent field
'''
with Transaction().start(DB_NAME, USER,
context=CONTEXT) as transaction:
(_parent_id, _sub_id, _subsub_id, subsubsub_id, overridden_id) = \
self.create_data()
ids = self.subsubsub.search([('name', '=', 'subsubsub')])
self.assertEqual(ids, [subsubsub_id])
ids = self.subsubsub.search([('name', '=', 'parent')])
self.assertEqual(ids, [])
transaction.cursor.rollback()
def test0050overriddenfieldsearch(self):
'''
Test searching on greatgranparent field
'''
with Transaction().start(DB_NAME, USER,
context=CONTEXT) as transaction:
(_parent_id, _sub_id, _subsub_id, subsubsub_id, overridden_id) = \
self.create_data()
ids = self.overridden.search([('subfield', '=', 3)])
self.assertEqual(ids, [overridden_id])
transaction.cursor.rollback()
def suite():
return unittest.TestLoader().loadTestsFromTestCase(ModelInheritsTestCase)
if __name__ == '__main__':
suite = suite()
unittest.TextTestRunner(verbosity=2).run(suite)
-2
View File
@@ -255,8 +255,6 @@ def all_suite():
suite_.addTests(test_mixins.suite())
import trytond.tests.test_wizard as test_wizard
suite_.addTests(test_wizard.suite())
import trytond.tests.test_model_inherits as test_inherits
suite_.addTests(test_inherits.suite())
import trytond.tests.test_modelsql as test_modelsql
suite_.addTests(test_modelsql.suite())
import trytond.tests.test_cache as test_cache