Add new and find methods to ModelList. Added set_context on Config objects.
review501003
This commit is contained in:
@@ -75,9 +75,7 @@ Creating an address for the party
|
||||
Addresses are store on party with a `One2Many` field. So the new address just
|
||||
needs to be appended to the list `addresses`.
|
||||
|
||||
>>> Address = Model.get('party.address')
|
||||
>>> address = Address()
|
||||
>>> party.addresses.append(address)
|
||||
>>> address = party.addresses.new()
|
||||
>>> party.save()
|
||||
>>> party.addresses #doctest: +ELLIPSIS
|
||||
[proteus.Model.get('party.address')(...)]
|
||||
|
||||
+41
-9
@@ -211,9 +211,8 @@ class One2ManyDescriptor(FieldDescriptor):
|
||||
relation = Model.get(self.definition['relation'], instance._config)
|
||||
value = super(One2ManyDescriptor, self).__get__(instance, owner)
|
||||
if not isinstance(value, ModelList):
|
||||
value = ModelList((relation(id)
|
||||
for id in value or []), instance, self.name,
|
||||
self.definition.get('relation_field'))
|
||||
value = ModelList(self.definition, (relation(id)
|
||||
for id in value or []), instance, self.name)
|
||||
instance._values[self.name] = value
|
||||
return value
|
||||
|
||||
@@ -398,22 +397,26 @@ class MetaModelFactory(object):
|
||||
class ModelList(list):
|
||||
'List for Model'
|
||||
|
||||
def __init__(self, sequence=None, parent=None, parent_field_name='',
|
||||
parent_name=''):
|
||||
def __init__(self, definition, sequence=None, parent=None,
|
||||
parent_field_name=''):
|
||||
self.model_name = definition['relation']
|
||||
if sequence is None:
|
||||
sequence = []
|
||||
self.parent = parent
|
||||
if parent:
|
||||
assert parent_field_name
|
||||
self.parent_field_name = parent_field_name
|
||||
self.parent_name = parent_name
|
||||
self.parent_name = definition.get('relation_field', '')
|
||||
self.domain = definition.get('domain', [])
|
||||
self.context = definition.get('context')
|
||||
self.add_remove = definition.get('add_remove')
|
||||
self.record_removed = set()
|
||||
self.record_deleted = set()
|
||||
result = super(ModelList, self).__init__(sequence)
|
||||
for record in self:
|
||||
record._parent = parent
|
||||
record._parent_field_name = parent_field_name
|
||||
record._parent_name = parent_name
|
||||
record._parent_name = self.parent_name
|
||||
return result
|
||||
__init__.__doc__ = list.__init__.__doc__
|
||||
|
||||
@@ -423,6 +426,13 @@ class ModelList(list):
|
||||
self.parent._changed.add(self.parent_field_name)
|
||||
self.parent._on_change(self.parent_field_name)
|
||||
|
||||
def _get_context(self):
|
||||
from .pyson import PYSONDecoder
|
||||
decoder = PYSONDecoder(_EvalEnvironment(self.parent))
|
||||
ctx = self.parent._context.copy() if self.parent._context else {}
|
||||
ctx.update(decoder.decode(self.context) if self.context else {})
|
||||
return ctx
|
||||
|
||||
def append(self, record):
|
||||
assert isinstance(record, Model)
|
||||
if self.parent:
|
||||
@@ -497,6 +507,27 @@ class ModelList(list):
|
||||
raise NotImplementedError
|
||||
sort.__doc__ = list.sort.__doc__
|
||||
|
||||
def new(self):
|
||||
'Adds a new record to the ModelList and returns it'
|
||||
Relation = Model.get(self.model_name, self.parent._config)
|
||||
with Relation._config.set_context(self._get_context()):
|
||||
new_record = Relation()
|
||||
self.append(new_record)
|
||||
return new_record
|
||||
|
||||
def find(self, condition=None, offset=0, limit=None, order=None):
|
||||
'Returns records matching condition taking into account list domain'
|
||||
from .pyson import PYSONDecoder
|
||||
decoder = PYSONDecoder(_EvalEnvironment(self.parent))
|
||||
Relation = Model.get(self.model_name, self.parent._config)
|
||||
if condition is None:
|
||||
condition = []
|
||||
add_remove_domain = (decoder.decode(self.add_remove)
|
||||
if self.add_remove else [])
|
||||
new_domain = [self.domain, add_remove_domain, condition]
|
||||
with Relation._config.set_context(self._get_context()):
|
||||
return Relation.find(new_domain, offset, limit, order)
|
||||
|
||||
|
||||
class Model(object):
|
||||
'Model class for Tryton records'
|
||||
@@ -518,6 +549,7 @@ class Model(object):
|
||||
self._parent = None # store the parent record
|
||||
self._parent_field_name = '' # store the field name in parent record
|
||||
self._parent_name = '' # store the field name to parent record
|
||||
self._context = self._config.context # store the context
|
||||
if self.id < 0 and _default:
|
||||
self._default_get()
|
||||
|
||||
@@ -684,8 +716,8 @@ class Model(object):
|
||||
record = relation()
|
||||
record._default_set(vals)
|
||||
records.append(record)
|
||||
self._values[field] = ModelList(records, self, field,
|
||||
definition.get('relation_field', ''))
|
||||
self._values[field] = ModelList(definition, records, self,
|
||||
field)
|
||||
else:
|
||||
self._values[field] = value
|
||||
|
||||
|
||||
@@ -72,6 +72,20 @@ _CONFIG = threading.local()
|
||||
_CONFIG.current = None
|
||||
|
||||
|
||||
class ContextManager(object):
|
||||
'Context Manager for the tryton context'
|
||||
|
||||
def __init__(self, config):
|
||||
self.config = config
|
||||
self.context = config.context
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
self.config._context = self.context
|
||||
|
||||
|
||||
class Config(object):
|
||||
'Config interface'
|
||||
|
||||
@@ -83,6 +97,16 @@ class Config(object):
|
||||
def context(self):
|
||||
return self._context.copy()
|
||||
|
||||
def set_context(self, context=None, **kwargs):
|
||||
ctx_manager = ContextManager(self)
|
||||
|
||||
if context is None:
|
||||
context = None
|
||||
self._context = self.context
|
||||
self._context.update(context)
|
||||
self._context.update(kwargs)
|
||||
return ctx_manager
|
||||
|
||||
def get_proxy(self, name):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
# 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 unittest import TestCase
|
||||
from proteus import config
|
||||
|
||||
|
||||
class TestContext(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.config = config.set_trytond(database_type='sqlite')
|
||||
|
||||
def test_config(self):
|
||||
prev_ctx = self.config._context
|
||||
|
||||
with self.config.set_context({'a': 1}):
|
||||
self.assertEqual(self.config.context['a'], 1)
|
||||
for key, value in prev_ctx.items():
|
||||
self.assertEqual(self.config.context[key], value)
|
||||
|
||||
self.assertEqual(self.config.context, prev_ctx)
|
||||
Reference in New Issue
Block a user