[MERGE] osv_memory removed, merged into database-backed Model/TransientModel

bzr revid: odo@openerp.com-20110927213712-9aa0x0aqoh13f6ga
This commit is contained in:
Olivier Dony 2011-09-27 23:37:12 +02:00
commit 762637518b
14 changed files with 542 additions and 819 deletions

View File

@ -22,6 +22,8 @@
""" OpenERP core library.
"""
# The hard-coded super-user id (a.k.a. administrator, or root user).
SUPERUSER_ID = 1
import addons
import conf

View File

@ -63,7 +63,7 @@ class ir_model(osv.osv):
models = self.browse(cr, uid, ids, context=context)
res = dict.fromkeys(ids)
for model in models:
res[model.id] = isinstance(self.pool.get(model.model), osv.osv_memory)
res[model.id] = self.pool.get(model.model).is_transient()
return res
def _search_osv_memory(self, cr, uid, model, name, domain, context=None):
@ -165,7 +165,7 @@ class ir_model(osv.osv):
pass
x_custom_model._name = model
x_custom_model._module = False
a = x_custom_model.createInstance(self.pool, cr)
a = x_custom_model.create_instance(self.pool, cr)
if (not a._columns) or ('x_name' in a._columns.keys()):
x_name = 'x_name'
else:
@ -481,14 +481,12 @@ class ir_model_access(osv.osv):
if isinstance(model, browse_record):
assert model._table_name == 'ir.model', 'Invalid model object'
model_name = model.name
model_name = model.model
else:
model_name = model
# osv_memory objects can be read by everyone, as they only return
# results that belong to the current user (except for superuser)
model_obj = self.pool.get(model_name)
if isinstance(model_obj, osv.osv_memory):
# TransientModel records have no access rights, only an implicit access rule
if self.pool.get(model_name).is_transient():
return True
# We check if a specific rule exists
@ -523,7 +521,7 @@ class ir_model_access(osv.osv):
}
raise except_orm(_('AccessError'), msgs[mode] % (model_name, groups) )
return r
return r or False
__cache_clearing_methods = []

View File

@ -26,8 +26,7 @@ from functools import partial
import tools
from tools.safe_eval import safe_eval as eval
from tools.misc import unquote as unquote
SUPERUSER_UID = 1
from openerp import SUPERUSER_ID
class ir_rule(osv.osv):
_name = 'ir.rule'
@ -68,7 +67,7 @@ class ir_rule(osv.osv):
return res
def _check_model_obj(self, cr, uid, ids, context=None):
return not any(isinstance(self.pool.get(rule.model_id.model), osv.osv_memory) for rule in self.browse(cr, uid, ids, context))
return not any(self.pool.get(rule.model_id.model).is_transient() for rule in self.browse(cr, uid, ids, context))
_columns = {
'name': fields.char('Name', size=128, select=1),
@ -104,7 +103,7 @@ class ir_rule(osv.osv):
if mode not in self._MODES:
raise ValueError('Invalid mode: %r' % (mode,))
if uid == SUPERUSER_UID:
if uid == SUPERUSER_ID:
return None
cr.execute("""SELECT r.id
FROM ir_rule r
@ -117,10 +116,10 @@ class ir_rule(osv.osv):
rule_ids = [x[0] for x in cr.fetchall()]
if rule_ids:
# browse user as super-admin root to avoid access errors!
user = self.pool.get('res.users').browse(cr, SUPERUSER_UID, uid)
user = self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid)
global_domains = [] # list of domains
group_domains = {} # map: group -> list of domains
for rule in self.browse(cr, SUPERUSER_UID, rule_ids):
for rule in self.browse(cr, SUPERUSER_ID, rule_ids):
# read 'domain' as UID to have the correct eval context for the rule.
rule_domain = self.read(cr, uid, rule.id, ['domain'])['domain']
dom = expression.normalize(rule_domain)

View File

@ -19,18 +19,15 @@
#
##############################################################################
from osv import osv
from osv.orm import orm_memory
import openerp
class osv_memory_autovacuum(osv.osv_memory):
class osv_memory_autovacuum(openerp.osv.osv.osv_memory):
""" Expose the osv_memory.vacuum() method to the cron jobs mechanism. """
_name = 'osv_memory.autovacuum'
def power_on(self, cr, uid, context=None):
for model in self.pool.obj_list():
obj = self.pool.get(model)
if isinstance(obj, orm_memory):
obj.vaccum(cr, uid)
for model in self.pool.models.values():
if model.is_transient():
model._transient_vacuum(cr, uid)
return True
osv_memory_autovacuum()

View File

@ -91,7 +91,7 @@ class res_currency(osv.osv):
(name, (COALESCE(company_id,-1)))""")
def read(self, cr, user, ids, fields=None, context=None, load='_classic_read'):
res = super(osv.osv, self).read(cr, user, ids, fields, context, load)
res = super(res_currency, self).read(cr, user, ids, fields, context, load)
currency_rate_obj = self.pool.get('res.currency.rate')
for r in res:
if r.__contains__('rate_ids'):

View File

@ -144,45 +144,3 @@
!python {model: res.partner.category}: |
self.pool._init = True
-
"OSV Memory: Verify that osv_memory properly handles large data allocation"
-
1. No "count-based" auto-vaccuum when max_count is disabled
-
!python {model: base.language.export}: |
# setup special limits for the test, these will be reset at next pool reload anyway
self._max_count = None
num_recs = 250
for i in xrange(num_recs):
self.create(cr, uid, {'format':'po'})
assert (len(self.datas) >= num_recs), "OSV Memory must not auto-vaccum records from the current transaction if max_count is not set"
-
2. Auto-vaccuum should be enabled when max_count is set
-
!python {model: base.language.export}: |
# setup special limits for the test, these will be reset at next pool reload anyway
self._max_count = 100
num_recs = 219
for i in xrange(num_recs):
self.create(cr, uid, {'name': i, 'format':'po'})
assert (self._max_count <= len(self.datas) < self._max_count + self._check_time), "OSV Memory must auto-expire records when max_count is reached"
for k,v in self.datas.iteritems():
assert (int(v['name']) >= (num_recs - (self._max_count + self._check_time))), "OSV Memory must auto-expire records based on age"
-
3. Auto-vaccuum should be based on age only when max_count is not set
-
!python {model: base.language.export}: |
# setup special limits for the test, these will be reset at next pool reload anyway
self._max_count = None
self._max_hours = 0.01 #36 seconds
num_recs = 200
for i in xrange(num_recs):
self.create(cr, uid, {'format':'po'})
assert (len(self.datas) >= num_recs), "OSV Memory must not auto-expire records from the current transaction"
# expire all records
for k,v in self.datas.iteritems():
v['internal.date_access'] = 0
self.vaccum(cr, 1, force=True)
assert (len(self.datas) == 0), "OSV Memory must expire old records after vaccuum"

View File

@ -339,16 +339,16 @@ def load_modules(db, force_demo=False, status=None, update_module=False):
cr.execute("""select model,name from ir_model where id NOT IN (select distinct model_id from ir_model_access)""")
for (model, name) in cr.fetchall():
model_obj = pool.get(model)
if model_obj and not isinstance(model_obj, osv.osv.osv_memory):
logger.notifyChannel('init', netsvc.LOG_WARNING, 'object %s (%s) has no access rules!' % (model, name))
if model_obj and not model_obj.is_transient():
logger.notifyChannel('init', netsvc.LOG_WARNING, 'Model %s (%s) has no access rules!' % (model, name))
# Temporary warning while we remove access rights on osv_memory objects, as they have
# been replaced by owner-only access rights
cr.execute("""select distinct mod.model, mod.name from ir_model_access acc, ir_model mod where acc.model_id = mod.id""")
for (model, name) in cr.fetchall():
model_obj = pool.get(model)
if isinstance(model_obj, osv.osv.osv_memory) and not isinstance(model_obj, osv.osv.osv):
logger.notifyChannel('init', netsvc.LOG_WARNING, 'In-memory object %s (%s) should not have explicit access rules!' % (model, name))
if model_obj and model_obj.is_transient():
logger.notifyChannel('init', netsvc.LOG_WARNING, 'The transient model %s (%s) should not have explicit access rules!' % (model, name))
cr.execute("SELECT model from ir_model")
for (model,) in cr.fetchall():
@ -356,7 +356,7 @@ def load_modules(db, force_demo=False, status=None, update_module=False):
if obj:
obj._check_removed_columns(cr, log=True)
else:
logger.notifyChannel('init', netsvc.LOG_WARNING, "Model %s is referenced but not present in the orm pool!" % model)
logger.notifyChannel('init', netsvc.LOG_WARNING, "Model %s is declared but cannot be loaded! (Perhaps a module was partially removed or renamed)" % model)
# Cleanup orphan records
pool.get('ir.model.data')._process_end(cr, 1, processed_modules)

View File

@ -277,7 +277,6 @@ def init_module_models(cr, module_name, obj_list):
TODO better explanation of _auto_init and init.
"""
logger.notifyChannel('init', netsvc.LOG_INFO,
'module %s: creating or updating database tables' % module_name)
todo = []

View File

@ -89,10 +89,10 @@ class Registry(object):
res = []
# Instantiate registered classes (via metamodel discovery or via explicit
# constructor call), and add them to the pool.
# Instantiate registered classes (via the MetaModel automatic discovery
# or via explicit constructor call), and add them to the pool.
for cls in openerp.osv.orm.MetaModel.module_to_models.get(module.name, []):
res.append(cls.createInstance(self, cr))
res.append(cls.create_instance(self, cr))
return res

View File

@ -450,7 +450,7 @@ class expression(object):
# field could not be found in model columns, it's probably invalid, unless
# it's one of the _log_access special fields
# TODO: make these fields explicitly available in self.columns instead!
if (field_path[0] not in MAGIC_COLUMNS) and (left not in MAGIC_COLUMNS):
if field_path[0] not in MAGIC_COLUMNS:
raise ValueError("Invalid field %r in domain expression %r" % (left, exp))
continue

View File

@ -72,7 +72,7 @@ class _column(object):
_symbol_set = (_symbol_c, _symbol_f)
_symbol_get = None
def __init__(self, string='unknown', required=False, readonly=False, domain=None, context=None, states=None, priority=0, change_default=False, size=None, ondelete="set null", translate=False, select=False, manual=False, **args):
def __init__(self, string='unknown', required=False, readonly=False, domain=None, context=None, states=None, priority=0, change_default=False, size=None, ondelete=None, translate=False, select=False, manual=False, **args):
"""
The 'manual' keyword argument specifies if the field is a custom one.
@ -91,7 +91,7 @@ class _column(object):
self.help = args.get('help', '')
self.priority = priority
self.change_default = change_default
self.ondelete = ondelete
self.ondelete = ondelete.lower() if ondelete else None # defaults to 'set null' in ORM
self.translate = translate
self._domain = domain
self._context = context
@ -112,12 +112,6 @@ class _column(object):
def set(self, cr, obj, id, name, value, user=None, context=None):
cr.execute('update '+obj._table+' set '+name+'='+self._symbol_set[0]+' where id=%s', (self._symbol_set[1](value), id))
def set_memory(self, cr, obj, id, name, value, user=None, context=None):
raise Exception(_('Not implemented set_memory method !'))
def get_memory(self, cr, obj, ids, name, user=None, context=None, values=None):
raise Exception(_('Not implemented get_memory method !'))
def get(self, cr, obj, ids, name, user=None, offset=0, context=None, values=None):
raise Exception(_('undefined get method !'))
@ -126,9 +120,6 @@ class _column(object):
res = obj.read(cr, uid, ids, [name], context=context)
return [x[name] for x in res]
def search_memory(self, cr, obj, args, name, value, offset=0, limit=None, uid=None, context=None):
raise Exception(_('Not implemented search_memory method !'))
# ---------------------------------------------------------
# Simple fields
@ -269,7 +260,7 @@ class binary(_column):
_column.__init__(self, string=string, **args)
self.filters = filters
def get_memory(self, cr, obj, ids, name, user=None, context=None, values=None):
def get(self, cr, obj, ids, name, user=None, context=None, values=None):
if not context:
context = {}
if not values:
@ -293,9 +284,6 @@ class binary(_column):
res[i] = val
return res
get = get_memory
class selection(_column):
_type = 'selection'
@ -355,30 +343,6 @@ class many2one(_column):
_column.__init__(self, string=string, **args)
self._obj = obj
def set_memory(self, cr, obj, id, field, values, user=None, context=None):
obj.datas.setdefault(id, {})
obj.datas[id][field] = values
def get_memory(self, cr, obj, ids, name, user=None, context=None, values=None):
result = {}
for id in ids:
result[id] = obj.datas[id].get(name, False)
# build a dictionary of the form {'id_of_distant_resource': name_of_distant_resource}
# we use uid=1 because the visibility of a many2one field value (just id and name)
# must be the access right of the parent form and not the linked object itself.
obj = obj.pool.get(self._obj)
records = dict(obj.name_get(cr, 1,
list(set([x for x in result.values() if x and isinstance(x, (int,long))])),
context=context))
for id in ids:
if result[id] in records:
result[id] = (result[id], records[result[id]])
else:
result[id] = False
return result
def get(self, cr, obj, ids, name, user=None, context=None, values=None):
if context is None:
context = {}
@ -447,55 +411,6 @@ class one2many(_column):
#one2many can't be used as condition for defaults
assert(self.change_default != True)
def get_memory(self, cr, obj, ids, name, user=None, offset=0, context=None, values=None):
if context is None:
context = {}
if self._context:
context = context.copy()
context.update(self._context)
if not values:
values = {}
res = {}
for id in ids:
res[id] = []
ids2 = obj.pool.get(self._obj).search(cr, user, [(self._fields_id, 'in', ids)], limit=self._limit, context=context)
for r in obj.pool.get(self._obj).read(cr, user, ids2, [self._fields_id], context=context, load='_classic_write'):
if r[self._fields_id] in res:
res[r[self._fields_id]].append(r['id'])
return res
def set_memory(self, cr, obj, id, field, values, user=None, context=None):
if not context:
context = {}
if self._context:
context = context.copy()
context.update(self._context)
if not values:
return
obj = obj.pool.get(self._obj)
for act in values:
if act[0] == 0:
act[2][self._fields_id] = id
obj.create(cr, user, act[2], context=context)
elif act[0] == 1:
obj.write(cr, user, [act[1]], act[2], context=context)
elif act[0] == 2:
obj.unlink(cr, user, [act[1]], context=context)
elif act[0] == 3:
obj.datas[act[1]][self._fields_id] = False
elif act[0] == 4:
obj.datas[act[1]][self._fields_id] = id
elif act[0] == 5:
for o in obj.datas.values():
if o[self._fields_id] == id:
o[self._fields_id] = False
elif act[0] == 6:
for id2 in (act[2] or []):
obj.datas[id2][self._fields_id] = id
def search_memory(self, cr, obj, args, name, value, offset=0, limit=None, uid=None, operator='like', context=None):
raise _('Not Implemented')
def get(self, cr, obj, ids, name, user=None, offset=0, context=None, values=None):
if context is None:
context = {}
@ -578,14 +493,34 @@ class one2many(_column):
# (6, ?, ids) set a list of links
#
class many2many(_column):
"""Encapsulates the logic of a many-to-many bidirectional relationship, handling the
low-level details of the intermediary relationship table transparently.
:param str obj: destination model
:param str rel: optional name of the intermediary relationship table. If not specified,
a canonical name will be derived based on the alphabetically-ordered
model names of the source and destination (in the form: ``amodel_bmodel_rel``).
Automatic naming is not possible when the source and destination are
the same, for obvious ambiguity reasons.
:param str id1: optional name for the column holding the foreign key to the current
model in the relationship table. If not specified, a canonical name
will be derived based on the model name (in the form: `src_model_id`).
:param str id2: optional name for the column holding the foreign key to the destination
model in the relationship table. If not specified, a canonical name
will be derived based on the model name (in the form: `dest_model_id`)
:param str string: field label
"""
_classic_read = False
_classic_write = False
_prefetch = False
_type = 'many2many'
def __init__(self, obj, rel, id1, id2, string='unknown', limit=None, **args):
def __init__(self, obj, rel=None, id1=None, id2=None, string='unknown', limit=None, **args):
"""
"""
_column.__init__(self, string=string, **args)
self._obj = obj
if '.' in rel:
if rel and '.' in rel:
raise Exception(_('The second argument of the many2many field %s must be a SQL table !'\
'You used %s, which is not a valid SQL table name.')% (string,rel))
self._rel = rel
@ -593,7 +528,30 @@ class many2many(_column):
self._id2 = id2
self._limit = limit
def get(self, cr, obj, ids, name, user=None, offset=0, context=None, values=None):
def _sql_names(self, source_model):
"""Return the SQL names defining the structure of the m2m relationship table
:return: (m2m_table, local_col, dest_col) where m2m_table is the table name,
local_col is the name of the column holding the current model's FK, and
dest_col is the name of the column holding the destination model's FK, and
"""
tbl, col1, col2 = self._rel, self._id1, self._id2
if not all((tbl, col1, col2)):
# the default table name is based on the stable alphabetical order of tables
dest_model = source_model.pool.get(self._obj)
tables = tuple(sorted([source_model._table, dest_model._table]))
if not tbl:
assert tables[0] != tables[1], 'Implicit/Canonical naming of m2m relationship table '\
'is not possible when source and destination models are '\
'the same'
tbl = '%s_%s_rel' % tables
if not col1:
col1 = '%s_id' % source_model._table
if not col2:
col2 = '%s_id' % dest_model._table
return (tbl, col1, col2)
def get(self, cr, model, ids, name, user=None, offset=0, context=None, values=None):
if not context:
context = {}
if not values:
@ -606,7 +564,8 @@ class many2many(_column):
if offset:
warnings.warn("Specifying offset at a many2many.get() may produce unpredictable results.",
DeprecationWarning, stacklevel=2)
obj = obj.pool.get(self._obj)
obj = model.pool.get(self._obj)
rel, id1, id2 = self._sql_names(model)
# static domains are lists, and are evaluated both here and on client-side, while string
# domains supposed by dynamic and evaluated on client-side only (thus ignored here)
@ -636,11 +595,11 @@ class many2many(_column):
%(order_by)s \
%(limit)s \
OFFSET %(offset)d' \
% {'rel': self._rel,
% {'rel': rel,
'from_c': from_c,
'tbl': obj._table,
'id1': self._id1,
'id2': self._id2,
'id1': id1,
'id2': id2,
'where_c': where_c,
'limit': limit_str,
'order_by': order_by,
@ -651,31 +610,32 @@ class many2many(_column):
res[r[1]].append(r[0])
return res
def set(self, cr, obj, id, name, values, user=None, context=None):
def set(self, cr, model, id, name, values, user=None, context=None):
if not context:
context = {}
if not values:
return
obj = obj.pool.get(self._obj)
rel, id1, id2 = self._sql_names(model)
obj = model.pool.get(self._obj)
for act in values:
if not (isinstance(act, list) or isinstance(act, tuple)) or not act:
continue
if act[0] == 0:
idnew = obj.create(cr, user, act[2], context=context)
cr.execute('insert into '+self._rel+' ('+self._id1+','+self._id2+') values (%s,%s)', (id, idnew))
cr.execute('insert into '+rel+' ('+id1+','+id2+') values (%s,%s)', (id, idnew))
elif act[0] == 1:
obj.write(cr, user, [act[1]], act[2], context=context)
elif act[0] == 2:
obj.unlink(cr, user, [act[1]], context=context)
elif act[0] == 3:
cr.execute('delete from '+self._rel+' where ' + self._id1 + '=%s and '+ self._id2 + '=%s', (id, act[1]))
cr.execute('delete from '+rel+' where ' + id1 + '=%s and '+ id2 + '=%s', (id, act[1]))
elif act[0] == 4:
# following queries are in the same transaction - so should be relatively safe
cr.execute('SELECT 1 FROM '+self._rel+' WHERE '+self._id1+' = %s and '+self._id2+' = %s', (id, act[1]))
cr.execute('SELECT 1 FROM '+rel+' WHERE '+id1+' = %s and '+id2+' = %s', (id, act[1]))
if not cr.fetchone():
cr.execute('insert into '+self._rel+' ('+self._id1+','+self._id2+') values (%s,%s)', (id, act[1]))
cr.execute('insert into '+rel+' ('+id1+','+id2+') values (%s,%s)', (id, act[1]))
elif act[0] == 5:
cr.execute('delete from '+self._rel+' where ' + self._id1 + ' = %s', (id,))
cr.execute('delete from '+rel+' where ' + id1 + ' = %s', (id,))
elif act[0] == 6:
d1, d2,tables = obj.pool.get('ir.rule').domain_get(cr, user, obj._name, context=context)
@ -683,10 +643,10 @@ class many2many(_column):
d1 = ' and ' + ' and '.join(d1)
else:
d1 = ''
cr.execute('delete from '+self._rel+' where '+self._id1+'=%s AND '+self._id2+' IN (SELECT '+self._rel+'.'+self._id2+' FROM '+self._rel+', '+','.join(tables)+' WHERE '+self._rel+'.'+self._id1+'=%s AND '+self._rel+'.'+self._id2+' = '+obj._table+'.id '+ d1 +')', [id, id]+d2)
cr.execute('delete from '+rel+' where '+id1+'=%s AND '+id2+' IN (SELECT '+rel+'.'+id2+' FROM '+rel+', '+','.join(tables)+' WHERE '+rel+'.'+id1+'=%s AND '+rel+'.'+id2+' = '+obj._table+'.id '+ d1 +')', [id, id]+d2)
for act_nbr in act[2]:
cr.execute('insert into '+self._rel+' ('+self._id1+','+self._id2+') values (%s, %s)', (id, act_nbr))
cr.execute('insert into '+rel+' ('+id1+','+id2+') values (%s, %s)', (id, act_nbr))
#
# TODO: use a name_search
@ -694,32 +654,6 @@ class many2many(_column):
def search(self, cr, obj, args, name, value, offset=0, limit=None, uid=None, operator='like', context=None):
return obj.pool.get(self._obj).search(cr, uid, args+self._domain+[('name', operator, value)], offset, limit, context=context)
def get_memory(self, cr, obj, ids, name, user=None, offset=0, context=None, values=None):
result = {}
for id in ids:
result[id] = obj.datas[id].get(name, [])
return result
def set_memory(self, cr, obj, id, name, values, user=None, context=None):
if not values:
return
for act in values:
# TODO: use constants instead of these magic numbers
if act[0] == 0:
raise _('Not Implemented')
elif act[0] == 1:
raise _('Not Implemented')
elif act[0] == 2:
raise _('Not Implemented')
elif act[0] == 3:
raise _('Not Implemented')
elif act[0] == 4:
raise _('Not Implemented')
elif act[0] == 5:
raise _('Not Implemented')
elif act[0] == 6:
obj.datas[id][name] = act[2]
def get_nice_size(value):
size = 0
@ -801,8 +735,8 @@ class function(_column):
Implements the function field.
:param orm_template model: model to which the field belongs (should be ``self`` for
a model method)
:param orm model: model to which the field belongs (should be ``self`` for
a model method)
:param field_name(s): name of the field to compute, or if ``multi`` is provided,
list of field names to compute.
:type field_name(s): str | [str]
@ -865,8 +799,8 @@ class function(_column):
Callable that implements the ``write`` operation for the function field.
:param orm_template model: model to which the field belongs (should be ``self`` for
a model method)
:param orm model: model to which the field belongs (should be ``self`` for
a model method)
:param int id: the identifier of the object to write on
:param str field_name: name of the field to set
:param fnct_inv_arg: arbitrary value passed when declaring the function field
@ -887,10 +821,10 @@ class function(_column):
a search criterion based on the function field into a new domain based only on
columns that are stored in the database.
:param orm_template model: model to which the field belongs (should be ``self`` for
a model method)
:param orm_template model_again: same value as ``model`` (seriously! this is for backwards
compatibility)
:param orm model: model to which the field belongs (should be ``self`` for
a model method)
:param orm model_again: same value as ``model`` (seriously! this is for backwards
compatibility)
:param str field_name: name of the field to search on
:param list criterion: domain component specifying the search criterion on the field.
:rtype: list
@ -935,7 +869,7 @@ class function(_column):
corresponding records in the source model (whose field values
need to be recomputed).
:param orm_template model: trigger_model
:param orm model: trigger_model
:param list trigger_ids: ids of the records of trigger_model that were
modified
:rtype: list
@ -1064,14 +998,11 @@ class function(_column):
result[id] = self.postprocess(cr, uid, obj, name, result[id], context)
return result
get_memory = get
def set(self, cr, obj, id, name, value, user=None, context=None):
if not context:
context = {}
if self._fnct_inv:
self._fnct_inv(obj, cr, user, id, name, value, self._fnct_inv_arg, context)
set_memory = set
# ---------------------------------------------------------
# Related fields

File diff suppressed because it is too large Load Diff

View File

@ -21,16 +21,17 @@
#.apidoc title: Objects Services (OSV)
import logging
from psycopg2 import IntegrityError, errorcodes
import orm
import openerp
import openerp.netsvc as netsvc
import openerp.pooler as pooler
import openerp.sql_db as sql_db
import logging
from psycopg2 import IntegrityError, errorcodes
from openerp.tools.func import wraps
from openerp.tools.translate import translate
from openerp.osv.orm import MetaModel
from openerp.osv.orm import MetaModel, Model, TransientModel, AbstractModel
class except_osv(Exception):
def __init__(self, name, value, exc_type='warning'):
@ -198,17 +199,10 @@ class object_proxy():
cr.close()
return res
class osv_memory(orm.orm_memory):
""" Deprecated class. """
__metaclass__ = MetaModel
_register = False # Set to false if the model shouldn't be automatically discovered.
class osv(orm.orm):
""" Deprecated class. """
__metaclass__ = MetaModel
_register = False # Set to false if the model shouldn't be automatically discovered.
# deprecated - for backward compatibility.
osv = Model
osv_memory = TransientModel
osv_abstract = AbstractModel # ;-)
def start_object_proxy():

View File

@ -307,7 +307,7 @@ class YamlInterpreter(object):
import openerp.osv as osv
record, fields = node.items()[0]
model = self.get_model(record.model)
if isinstance(model, osv.osv.osv_memory):
if model.is_transient():
record_dict=self.create_osv_memory_record(record, fields)
else:
self.validate_xml_id(record.id)