def _default_values(self): """Return the values not stored. By default, the value of a field is its internal representation except: - for Many2One and One2One field: the id - for Reference field: the string model,id - for Many2Many: the list of ids - for One2Many: the list of `_default_values` """ values = {} # JCA : preload rec names if in called from _changed_values add_rec_names = ServerContext().get('_default_rec_names', False) if self._values: for fname, value in self._values._items(): field = self._fields[fname] rec_name = None if field._type in ('many2one', 'one2one', 'reference'): if value: if add_rec_names: rec_name = getattr(value, 'rec_name', '') if field._type == 'reference': value = str(value) else: value = value.id elif field._type in ('one2many', 'many2many'): if field._type == 'one2many': value = [r._default_values for r in value] else: value = [r.id for r in value] values[fname] = value if rec_name is not None: values['%s.' % fname] = {'rec_name': rec_name} return values
def init(self, update=None, lang=None, activatedeps=False): ''' Init pool Set update to proceed to update lang is a list of language code to be updated ''' # ABDC: inter-workers communication from trytond import iwc with self._lock: # ABDC: inter-workers communication iwc.start(self.database_name) if not self._started: self.start() with self._locks[self.database_name]: # Don't reset pool if already init and not to update if not update and self._pool.get(self.database_name): return logger.info('init pool for "%s"', self.database_name) self._pool.setdefault(self.database_name, {}) # Clean the _pool before loading modules for type in list(self.classes.keys()): self._pool[self.database_name][type] = {} self._post_init_calls[self.database_name] = [] with ServerContext().set_context(disable_auto_cache=True): restart = not load_modules(self.database_name, self, update=update, lang=lang, activatedeps=activatedeps) if restart: self.init() # ABDC: inter-workers communication if update: iwc.broadcast_init_pool(self.database_name)
def init(self, update=None, lang=None, activatedeps=False): ''' Init pool Set update to proceed to update lang is a list of language code to be updated ''' with self._lock: if not self._started: self.start() with self._locks[self.database_name]: # Don't reset pool if already init and not to update if not update and self._pool.get(self.database_name): return logger.info('init pool for "%s"', self.database_name) self._pool.setdefault(self.database_name, {}) self._modules = [] # Clean the _pool before loading modules for type in self.classes.keys(): self._pool[self.database_name][type] = {} self._post_init_calls[self.database_name] = [] try: with ServerContext().set_context(disable_auto_cache=True): restart = not load_modules(self.database_name, self, update=update, lang=lang, activatedeps=activatedeps) except Exception: del self._pool[self.database_name] self._modules = None raise if restart: self.init()
def test_server_context(self): with ServerContext().set_context(a=1): self.assertEqual(ServerContext().context.get('a'), 1) self.assertEqual(ServerContext().context.get('b', 10), 10) self.assertEqual(ServerContext().get('a'), 1) self.assertEqual(ServerContext().get('b', 10), 10) with ServerContext().set_context(a=10): self.assertEqual(ServerContext().context.get('a'), 10) self.assertEqual(ServerContext().context.get('a'), 1) with ServerContext().set_context(c=10): self.assertEqual(ServerContext().context.get('a'), 1) self.assertEqual(ServerContext().context.get('c'), 10) self.assertEqual(ServerContext().context.get('c', 1), 1) self.assertEqual(ServerContext().context, {'a': 1}) self.assertEqual(ServerContext().context, {})
def _changed_values(self): """Return the values changed since the instantiation. By default, the value of a field is its internal representation except: - for Many2One and One2One field: the id. - for Reference field: the string model,id - for Many2Many: the list of ids - for One2Many: a dictionary composed of three keys: - add: a list of tuple, the first element is the index where the new line is added, the second element is `_default_values` - update: a list of dictionary of `_changed_values` including the `id` - remove: a list of ids """ from .modelstorage import ModelStorage changed = {} init_values = self._init_values or {} if not self._values: return changed for fname, value in self._values.iteritems(): field = self._fields[fname] # Always test key presence in case value is None if (fname in init_values and value == init_values[fname] and field._type != 'one2many'): continue if field._type in ('many2one', 'one2one', 'reference'): if value: if value.id is None or value.id < 0: # Don't consider temporary instance as a change continue if isinstance(value, ModelStorage): changed['%s.rec_name' % fname] = value.rec_name if field._type == 'reference': value = str(value) else: value = value.id elif field._type == 'one2many': targets = value init_targets = list(init_values.get(fname, [])) value = collections.defaultdict(list) value['remove'] = [t.id for t in init_targets if t.id] for i, target in enumerate(targets): if target.id in value['remove']: value['remove'].remove(target.id) target_changed = target._changed_values if target_changed: target_changed['id'] = target.id value['update'].append(target_changed) else: # JACK: redmine issue #5873 # automatically get a one2Many rec_name # to limit number of requests with ServerContext().set_context( _default_rec_names=True): if isinstance(target, ModelView): # Ensure initial values are returned because # target was instantiated on server side. target_init_values = target._init_values target._init_values = None try: added_values = target._changed_values finally: target._init_values = target_init_values else: added_values = target._default_values value['add'].append((i, added_values)) if not value['remove']: del value['remove'] if not value: continue value = dict(value) elif field._type == 'many2many': value = [r.id for r in value] changed[fname] = value return changed
def _changed_values(self): """Return the values changed since the instantiation. By default, the value of a field is its internal representation except: - for Many2One and One2One field: the id. - for Reference field: the string model,id - for Many2Many: the list of ids - for One2Many: a dictionary composed of three keys: - add: a list of tuple, the first element is the index where the new line is added, the second element is `_default_values` - update: a list of dictionary of `_changed_values` including the `id` - remove: a list of ids """ from .modelstorage import ModelStorage changed = {} init_values = self._init_values or {} if not self._values: return changed init_record = self.__class__(self.id) for fname, value in self._values.items(): field = self._fields[fname] # Always test key presence in case value is None if (fname in init_values and value == init_values[fname] and field._type != 'one2many'): continue if field._type in ('many2one', 'one2one', 'reference'): if value: if isinstance(value, ModelStorage): try: changed['%s.' % fname] = { 'rec_name': value.rec_name, } except AttributeError: pass if value.id is None: # Don't consider temporary instance as a change continue if field._type == 'reference': value = str(value) else: value = value.id elif field._type in ['one2many', 'many2many']: targets = value if fname in init_values: init_targets = init_values.get(fname) else: init_targets = getattr(init_record, fname, []) value = collections.defaultdict(list) previous = [t.id for t in init_targets if t.id] for i, target in enumerate(targets): if (field._type == 'one2many' and field.field and target._values): t_values = target._values.copy() # Don't look at reverse field target._values.pop(field.field, None) else: t_values = None try: if target.id in previous: previous.remove(target.id) if isinstance(target, ModelView): target_changed = target._changed_values if target_changed: target_changed['id'] = target.id value['update'].append(target_changed) else: # JACK: redmine issue #5873 # automatically get a one2Many rec_name # to limit number of requests with ServerContext().set_context( _default_rec_names=True): if isinstance(target, ModelView): # Ensure initial values are returned because # target was instantiated on server side. target_init_values = target._init_values target._init_values = None try: added_values = target._changed_values finally: target._init_values = target_init_values else: added_values = target._default_values added_values['id'] = target.id value['add'].append((i, added_values)) finally: if t_values: target._values = t_values if previous: to_delete, to_remove = [], [] deleted = removed = None if self._deleted: deleted = self._deleted[fname] if self._removed: removed = self._removed[fname] for id_ in previous: if deleted and id_ in deleted: to_delete.append(id_) elif removed and id_ in removed: to_remove.append(id_) elif field._type == 'one2many': to_delete.append(id_) else: to_remove.append(id_) if to_delete: value['delete'] = to_delete if to_remove: value['remove'] = to_remove if not value: continue value = dict(value) changed[fname] = value return changed