diff --git a/openerp/addons/base/res/res_users.py b/openerp/addons/base/res/res_users.py index f1ddf4f1b42..f2bc917d09e 100644 --- a/openerp/addons/base/res/res_users.py +++ b/openerp/addons/base/res/res_users.py @@ -22,6 +22,7 @@ import itertools import logging from functools import partial +from itertools import repeat from lxml import etree from lxml.builder import E @@ -650,25 +651,30 @@ class users_implied(osv.osv): # Naming conventions for reified groups fields: # - boolean field 'in_group_ID' is True iff # ID is in 'groups_id' -# - boolean field 'in_groups_ID1_..._IDk' is True iff -# any of ID1, ..., IDk is in 'groups_id' # - selection field 'sel_groups_ID1_..._IDk' is ID iff # ID is in 'groups_id' and ID is maximal in the set {ID1, ..., IDk} #---------------------------------------------------------- -def name_boolean_group(id): return 'in_group_' + str(id) -def name_boolean_groups(ids): return 'in_groups_' + '_'.join(map(str, ids)) -def name_selection_groups(ids): return 'sel_groups_' + '_'.join(map(str, ids)) +def name_boolean_group(id): + return 'in_group_' + str(id) + +def name_selection_groups(ids): + return 'sel_groups_' + '_'.join(map(str, ids)) + +def is_boolean_group(name): + return name.startswith('in_group_') + +def is_selection_groups(name): + return name.startswith('sel_groups_') -def is_boolean_group(name): return name.startswith('in_group_') -def is_boolean_groups(name): return name.startswith('in_groups_') -def is_selection_groups(name): return name.startswith('sel_groups_') def is_reified_group(name): - return is_boolean_group(name) or is_boolean_groups(name) or is_selection_groups(name) + return is_boolean_group(name) or is_selection_groups(name) -def get_boolean_group(name): return int(name[9:]) -def get_boolean_groups(name): return map(int, name[10:].split('_')) -def get_selection_groups(name): return map(int, name[11:].split('_')) +def get_boolean_group(name): + return int(name[9:]) + +def get_selection_groups(name): + return map(int, name[11:].split('_')) def partition(f, xs): "return a pair equivalent to (filter(f, xs), filter(lambda x: not f(x), xs))" @@ -789,45 +795,39 @@ class users_view(osv.osv): _inherit = 'res.users' def create(self, cr, uid, values, context=None): - self._set_reified_groups(values) + values = self._remove_reified_groups(values) return super(users_view, self).create(cr, uid, values, context) def write(self, cr, uid, ids, values, context=None): - self._set_reified_groups(values) + values = self._remove_reified_groups(values) return super(users_view, self).write(cr, uid, ids, values, context) - def _set_reified_groups(self, values): - """ reflect reified group fields in values['groups_id'] """ - if 'groups_id' in values: - # groups are already given, ignore group fields - for f in filter(is_reified_group, values.iterkeys()): - del values[f] - return + def _remove_reified_groups(self, values): + """ return `values` without reified group fields """ + add, rem = [], [] + values1 = {} - add, remove = [], [] - for f in values.keys(): - if is_boolean_group(f): - target = add if values.pop(f) else remove - target.append(get_boolean_group(f)) - elif is_boolean_groups(f): - if not values.pop(f): - remove.extend(get_boolean_groups(f)) - elif is_selection_groups(f): - remove.extend(get_selection_groups(f)) - selected = values.pop(f) - if selected: - add.append(selected) - # update values *only* if groups are being modified, otherwise - # we introduce spurious changes that might break the super.write() call. - if add or remove: - # remove groups in 'remove' and add groups in 'add' - values['groups_id'] = [(3, id) for id in remove] + [(4, id) for id in add] + for key, val in values.iteritems(): + if is_boolean_group(key): + (add if val else rem).append(get_boolean_group(key)) + elif is_selection_groups(key): + rem += get_selection_groups(key) + if val: + add.append(val) + else: + values1[key] = val + + if 'groups_id' not in values and (add or rem): + # remove group ids in `rem` and add group ids in `add` + values1['groups_id'] = zip(repeat(3), rem) + zip(repeat(4), add) + + return values1 def default_get(self, cr, uid, fields, context=None): group_fields, fields = partition(is_reified_group, fields) fields1 = (fields + ['groups_id']) if group_fields else fields values = super(users_view, self).default_get(cr, uid, fields1, context) - self._get_reified_groups(group_fields, values) + self._add_reified_groups(group_fields, values) # add "default_groups_ref" inside the context to set default value for group_id with xml values if 'groups_id' in fields and isinstance(context.get("default_groups_ref"), list): @@ -846,29 +846,35 @@ class users_view(osv.osv): return values def read(self, cr, uid, ids, fields=None, context=None, load='_classic_read'): - fields_get = fields if fields is not None else self.fields_get(cr, uid, context=context).keys() - group_fields, _ = partition(is_reified_group, fields_get) + # determine whether reified groups fields are required, and which ones + fields1 = fields or self.fields_get(cr, uid, context=context).keys() + group_fields, other_fields = partition(is_reified_group, fields1) - inject_groups_id = group_fields and fields and 'groups_id' not in fields - if inject_groups_id: - fields.append('groups_id') - res = super(users_view, self).read(cr, uid, ids, fields, context=context, load=load) + # read regular fields (other_fields); add 'groups_id' if necessary + drop_groups_id = False + if group_fields and fields: + if 'groups_id' not in other_fields: + other_fields.append('groups_id') + drop_groups_id = True + else: + other_fields = fields - if res and group_fields: + res = super(users_view, self).read(cr, uid, ids, other_fields, context=context, load=load) + + # post-process result to add reified group fields + if group_fields: for values in (res if isinstance(res, list) else [res]): - self._get_reified_groups(group_fields, values) - if inject_groups_id: + self._add_reified_groups(group_fields, values) + if drop_groups_id: values.pop('groups_id', None) return res - def _get_reified_groups(self, fields, values): - """ compute the given reified group fields from values['groups_id'] """ + def _add_reified_groups(self, fields, values): + """ add the given reified group fields into `values` """ gids = set(parse_m2m(values.get('groups_id') or [])) for f in fields: if is_boolean_group(f): values[f] = get_boolean_group(f) in gids - elif is_boolean_groups(f): - values[f] = not gids.isdisjoint(get_boolean_groups(f)) elif is_selection_groups(f): selected = [gid for gid in get_selection_groups(f) if gid in gids] values[f] = selected and selected[-1] or False