class CatalogBlacklist(UniqueObject, SimpleItem): implements(ICatalogBlacklist) id = 'portal_catalogblacklist' meta_type = 'Catalog Blacklist Tool' security = ClassSecurityInfo() def __init__(self, id=None): self._blacklisted_types = PersistentDict() self._blacklisted_interfaces = PersistentDict() security.declarePrivate('extend') def extend(self, blacklisted_types=None, blacklisted_interfaces=None): """ extend the blacklisted indexes for the given types or interfaces """ if blacklisted_types is not None: for pt, indexnames in blacklisted_types.items(): self._blacklisted_types.setdefault(pt, []) for name in indexnames: if name not in self._blacklisted_types[pt]: self._blacklisted_types[pt].append(name) self._blacklisted_types._p_changed = 1 if blacklisted_interfaces is not None: for iface, indexnames in blacklisted_interfaces.items(): if isinstance(iface, StringTypes): iface = resolve(iface) self._blacklisted_interfaces.setdefault(iface, []) for name in indexnames: if name not in self._blacklisted_interfaces[iface]: self._blacklisted_interfaces[iface].append(name) self._blacklisted_interfaces._p_changed = 1 security.declarePrivate('getBlackListedIndexesForObject') def getBlackListedIndexesForObject(self, object): """ return blacklisted indexes for object """ portal_type = getattr(object, 'portal_type', None) blacklisted = [] for indexname in self._blacklisted_types.get(portal_type, []): blacklisted.append(indexname) # Inspect the interfaces for iface, indexes in \ self._blacklisted_interfaces.items(): if iface.providedBy(object): for indexname in indexes: if indexname not in blacklisted: blacklisted.append(indexname) return blacklisted
class ViewletSettingsStorage(Persistent): implements(IViewletSettingsStorage) def __init__(self): self._order = PersistentDict() self._hidden = PersistentDict() self._defaults = PersistentDict() def getOrder(self, name, skinname): skin = self._order.get(skinname, {}) order = skin.get(name, ()) if not order: skinname = self.getDefault(name) if skinname is not None: skin = self._order.get(skinname, {}) order = skin.get(name, ()) return order def setOrder(self, name, skinname, order): skin = self._order.setdefault(skinname, PersistentDict()) skin[name] = tuple(order) if self.getDefault(name) is None: self.setDefault(name, skinname) def getHidden(self, name, skinname): skin = self._hidden.get(skinname, {}) hidden = skin.get(name, ()) if not hidden: skinname = self.getDefault(name) if skinname is not None: skin = self._hidden.get(skinname, {}) hidden = skin.get(name, ()) return hidden def setHidden(self, name, skinname, hidden): skin = self._hidden.setdefault(skinname, PersistentDict()) skin[name] = tuple(hidden) def getDefault(self, name): try: return self._defaults.get(name) except AttributeError: # Backward compatibility self._defaults = PersistentDict() self.setDefault(name, 'Plone Default') return self.getDefault(name) def setDefault(self, name, skinname): try: self._defaults[name] = skinname except AttributeError: # Backward compatibility self._defaults = PersistentDict() self.setDefault(name, skinname)
class JobStats(BaseStats): # jobs: # <job_type>: ... the algorithm id (or content type) # CREATED: # count: ... over all count # runtime: ... should always be 0 # <state>: # count: ... count per state # runtime: ... over all runtime per state # <year>: # <month>: # CREATED: # count: # runtime: ... always 0 # <state>: # count: # runtime: def __init__(self): self._stats = PersistentDict() def inc(self, function, portal_type, runtime, state, date): # count jobs per type if portal_type: jobstats = self._stats.setdefault(portal_type, PersistentDict()) statestats = jobstats.setdefault(state, PersistentDict()) statestats.setdefault('count', PCounter()).inc() statestats.setdefault('runtime', PCounter()).inc(runtime) # years/months ystats = jobstats.setdefault(date.year, PersistentDict()) mstats = ystats.setdefault(date.month, PersistentDict()) statestats = mstats.setdefault(state, PersistentDict()) statestats.setdefault('count', PCounter()).inc() statestats.setdefault('runtime', PCounter()).inc(runtime) if function: # count jobs per function jobstats = self._stats.setdefault(function, PersistentDict()) statestats = jobstats.setdefault(state, PersistentDict()) statestats.setdefault('count', PCounter()).inc() statestats.setdefault('runtime', PCounter()).inc(runtime) # years/months ystats = jobstats.setdefault(date.year, PersistentDict()) mstats = ystats.setdefault(date.month, PersistentDict()) statestats = mstats.setdefault(state, PersistentDict()) statestats.setdefault('count', PCounter()).inc() statestats.setdefault('runtime', PCounter()).inc(runtime)
class ContextKeys(Persistent): grok.implements(IContextKeys) def __init__(self): self._items = PersistentDict() def link(self, key, context): id = hash(IKeyReference(context)) ids = self._items.setdefault(key, PersistentSet()) ids.add(id) def unlink(self, key, context): id = hash(IKeyReference(context)) ids = self._items.setdefault(key, PersistentSet()) ids.discard(id) if not ids: del self._items[key] def unlinkKey(self, key): if key in self._items: del self._items[key] def unlinkContext(self, context): id = hash(IKeyReference(context)) keys_removed = set() for key, ids in self._items.items(): ids.discard(id) if not ids: keys_removed.add(key) for key in keys_removed: del self._items[key] return keys_removed def isLinked(self, key, context): id = hash(IKeyReference(context)) return id in self._items.get(key, set()) def __contains__(self, key): return key in self._items
class MarscatsSettingsStorage(Persistent): implements(IMarscatsSettingsStorage) def __init__(self): self._fields = PersistentDict() def setStartupDir(self, fieldname, startup_dir, portal_type=None): field = self._fields.setdefault(fieldname, PersistentDict()) if portal_type is not None: portal_types = field.setdefault('portal_types', PersistentDict()) portal_types[portal_type] = startup_dir else: self._fields[fieldname]['startup_directory'] = startup_dir def getStartupDir(self, fieldname, portal_type=None, fallback=True, ispath=False): sd = '' if fallback: sd = CAT_CONTAINER if fieldname in self._fields.keys(): field = self._fields.get(fieldname) sd = field.get('startup_directory', sd) if portal_type is not None: pts = field.get('portal_types') if pts is not None: sd = pts.get(portal_type, sd) if ispath: if not sd.startswith(CAT_CONTAINER): sd = CAT_CONTAINER + '/' + sd # sd = '/' + sd return sd def getFieldNames(self): return list(self._fields) def getTypesForField(self, fieldname): if fieldname in self._fields: field = self._fields[fieldname] if 'portal_types' in field and len(field['portal_types']): return list(field['portal_types']) return list()
class ExperimentStats(BaseStats): # experiments # <portal_type> # jobs: ... overall number of jobs # CREATED: # count: ... overall count # runtime: ... should always be 0 # <state> # count: ... count per state # runtime ... runtime per state # <year>: # <month>: # jobs: ... overall number of jobs within experiment # CREATED: # count: ... overall count by year/month # runtime: ... should always be 0 # <state>: # count: ... count yer state by year/month # runtime: ... runtime per state by year/month def __init__(self): self._stats = PersistentDict() def inc(self, portal_type, runtime, state, date): # experiment type stats expstats = self._stats.setdefault(portal_type, PersistentDict()) # per state stats statestats = expstats.setdefault(state, PersistentDict()) statestats.setdefault('count', PCounter()).inc() statestats.setdefault('runtime', PCounter()).inc(runtime) # years ystat = expstats.setdefault(date.year, PersistentDict()) # months mstat = ystat.setdefault(date.month, PersistentDict()) # per state stats statestats = mstat.setdefault(state, PersistentDict()) statestats.setdefault('count', PCounter()).inc() statestats.setdefault('runtime', PCounter()).inc(runtime)
class Tokenable(Entity): """Question class""" tokens_opposition = CompositeMultipleProperty('tokens_opposition') tokens_support = CompositeMultipleProperty('tokens_support') def __init__(self, **kwargs): super(Tokenable, self).__init__(**kwargs) self.set_data(kwargs) self.allocated_tokens = OOBTree() self.len_allocated_tokens = PersistentDict({}) def add_token(self, user, evaluation_type): user_oid = get_oid(user) if user_oid in self.allocated_tokens: self.remove_token(user) self.allocated_tokens[user_oid] = evaluation_type self.len_allocated_tokens.setdefault(evaluation_type, 0) self.len_allocated_tokens[evaluation_type] += 1 def remove_token(self, user): user_oid = get_oid(user) if user_oid in self.allocated_tokens: evaluation_type = self.allocated_tokens.pop(user_oid) self.len_allocated_tokens.setdefault(evaluation_type, 0) self.len_allocated_tokens[evaluation_type] -= 1 def evaluators(self, evaluation_type=None): if evaluation_type: return [ get_obj(key) for value, key in self.allocated_tokens.byValue( evaluation_type) ] return [get_obj(key) for key in self.allocated_tokens.keys()] def evaluation(self, user): user_oid = get_oid(user, None) return self.allocated_tokens.get(user_oid, None) def remove_tokens(self, force=False): evaluators = self.evaluators() for user in evaluators: user.remove_token(self) if force: self.remove_token(user) def user_has_token(self, user, root=None): if hasattr(user, 'has_token'): return user.has_token(self, root) return False def init_support_history(self): # [(user_oid, date, support_type), ...], support_type = {1:support, 0:oppose, -1:withdraw} if not hasattr(self, '_support_history'): setattr(self, '_support_history', PersistentList()) @property def len_support(self): return self.len_allocated_tokens.get(Evaluations.support, 0) @property def len_opposition(self): return self.len_allocated_tokens.get(Evaluations.oppose, 0)
class SearchableEntity(VisualisableElement, Entity): """ A Searchable entity is an entity that can be searched""" templates = { 'default': 'novaideo:templates/views/default_result.pt', 'bloc': 'novaideo:templates/views/default_result.pt' } def __init__(self, **kwargs): super(SearchableEntity, self).__init__(**kwargs) self.keywords = PersistentList() @property def is_published(self): return 'published' in self.state @property def is_workable(self): return self.is_published @property def relevant_data(self): return [ getattr(self, 'title', ''), getattr(self, 'description', ''), ', '.join(getattr(self, 'keywords', [])) ] def set_source_data(self, source_data): if not hasattr(self, 'source_data'): self.source_data = PersistentDict({}) app_name = source_data.get('app_name') self.source_data.setdefault(app_name, {}) self.source_data[app_name] = source_data def get_source_data(self, app_id): if not hasattr(self, 'source_data'): return {} return self.source_data.get(app_id, {}) def is_managed(self, root): return True def get_title(self, user=None): return getattr(self, 'title', '') def _init_presentation_text(self): pass def get_release_date(self): return getattr(self, 'release_date', self.modified_at) def presentation_text(self, nb_characters=400): return getattr(self, 'description', "")[:nb_characters] + '...' def get_more_contents_criteria(self): "return specific query, filter values" return None, { 'metadata_filter': { 'states': ['published'], 'keywords': list(self.keywords) } }
class Taxonomy(SimpleItem): order = None count = None version = None def __init__(self, name, title, default_language): self.data = PersistentDict() self.order = PersistentDict() self.count = PersistentDict() self.version = PersistentDict() self.name = name self.title = title self.default_language = default_language @property def sm(self): return api.portal.get().getSiteManager() def __call__(self, context): if not self.data: return Vocabulary(self.name, {}, {}, {}, 2) request = getattr(context, "REQUEST", None) language = self.getCurrentLanguage(request) return self.makeVocabulary(language) @property @ram.cache(lambda method, self: (self.name, self.data._p_mtime)) def inverted_data(self): inv_data = {} for (language, elements) in self.data.items(): inv_data[language] = {} for (path, identifier) in elements.items(): inv_data[language][identifier] = path return inv_data def getShortName(self): return self.name.split('.')[-1] def getGeneratedName(self): return 'collective.taxonomy.generated.' + self.getShortName() def getVocabularyName(self): return 'collective.taxonomy.' + self.getShortName() def makeVocabulary(self, language): self._fixup() data = self.data.get(language, {}) order = self.order.get(language) version = self.version.get(language, 1) inverted_data = self.inverted_data.get(language, {}) return Vocabulary(self.name, data, inverted_data, order, version) def getCurrentLanguage(self, request): language = get_lang_code() if language in self.data: return language elif self.default_language in self.data: return self.default_language else: # our best guess! return self.data.keys()[0] def getLanguages(self): return tuple(self.data) def iterLanguage(self, language=None): if language is None: language = self.default_language vocabulary = self.makeVocabulary(language) for path, identifier in vocabulary.iterEntries(): parent_path = path.rsplit(PATH_SEPARATOR, 1)[0] if parent_path: parent = vocabulary.getTermByValue(parent_path) else: parent = None yield path, identifier, parent def registerBehavior(self, **kwargs): new_args = copy(kwargs) new_args['name'] = self.getGeneratedName() new_args['title'] = self.title new_args['description'] = kwargs.get('field_description', u'') new_args['field_description'] = new_args['description'] behavior = TaxonomyBehavior(**new_args) self.sm.registerUtility(behavior, IBehavior, name=self.getGeneratedName()) behavior.addIndex() behavior.activateSearchable() def cleanupFTI(self): """Cleanup the FTIs""" generated_name = self.getGeneratedName() for (name, fti) in self.sm.getUtilitiesFor(IDexterityFTI): if generated_name in fti.behaviors: fti.behaviors = [behavior for behavior in fti.behaviors if behavior != generated_name] modified(fti, DexterityFTIModificationDescription("behaviors", '')) def updateBehavior(self, **kwargs): behavior_name = self.getGeneratedName() short_name = self.getShortName() utility = self.sm.queryUtility(IBehavior, name=behavior_name) if utility: utility.deactivateSearchable() utility.activateSearchable() if 'field_title' in kwargs: utility.title = kwargs.pop('field_title') for k, v in kwargs.items(): setattr(utility, k, v) delattr(generated, short_name) for (name, fti) in self.sm.getUtilitiesFor(IDexterityFTI): if behavior_name in fti.behaviors: modified(fti, DexterityFTIModificationDescription("behaviors", '')) def unregisterBehavior(self): behavior_name = self.getGeneratedName() utility = self.sm.queryUtility(IBehavior, name=behavior_name) if utility is None: return self.cleanupFTI() utility.removeIndex() utility.deactivateSearchable() utility.unregisterInterface() self.sm.unregisterUtility(utility, IBehavior, name=behavior_name) def clean(self): self.data.clear() def add(self, language, value, key): self._fixup() tree = self.data.get(language) if tree is None: tree = self.data[language] = OOBTree() else: # Make sure we update the modification time. self.data[language] = tree update = key in tree tree[key] = value order = self.order.get(language) if order is None: order = self.order[language] = IOBTree() count = self.count[language] = 0 else: if update: pop_value(tree, key) count = self.count[language] + 1 self.count[language] = count order[count] = key def update(self, language, items, clear=False): self._fixup() tree = self.data.setdefault(language, OOBTree()) if clear: tree.clear() # A new tree always uses the newest version. if not tree: version = self.version[language] = 2 else: version = self.version.get(language, 1) order = self.order.setdefault(language, IOBTree()) count = self.count.get(language, 0) if clear: order.clear() count = 0 # Always migrate to newest version. if version == 1: def fix(path): return path.replace(LEGACY_PATH_SEPARATOR, PATH_SEPARATOR) for i in list(order): path = order[i] order[i] = fix(path) for path in list(tree): value = tree.pop(path) tree[fix(path)] = value version = self.version[language] = 2 logger.info( "Taxonomy '%s' upgraded to version %d for language '%s'." % ( self.name, version, language ) ) # Make sure we update the modification time. self.data[language] = tree # The following structure is used to expunge updated entries. inv = {} if not clear: for i, key in order.items(): inv[key] = i seen = set() for key, value in items: if key in seen: logger.warning("Duplicate key entry: %r" % (key, )) continue seen.add(key) update = key in tree tree[key] = value order[count] = key count += 1 # If we're updating, then we have to pop out the old ordering # information in order to maintain relative ordering of new items. if update: i = inv.get(key) if i is not None: del order[i] self.count[language] = count def translate(self, msgid, mapping=None, context=None, target_language=None, default=None, msgid_plural=None, default_plural=None, number=None): if target_language is None or \ target_language not in self.inverted_data: target_language = str(api.portal.get_current_language()) if msgid not in self.inverted_data[target_language]: return '' if self.version is not None and self.version.get(target_language) != 2: path_sep = LEGACY_PATH_SEPARATOR else: path_sep = PATH_SEPARATOR path = self.inverted_data[target_language][msgid] pretty_path = path[1:].replace(path_sep, PRETTY_PATH_SEPARATOR) if mapping is not None and mapping.get(NODE): pretty_path = pretty_path.rsplit(PRETTY_PATH_SEPARATOR, 1)[-1] return pretty_path def _fixup(self): # due to compatibility reasons this method fixes data structure # for old Taxonomy instances. # XXX: remove this in version 2.0 to prevent write on read if self.order is None: safeWrite(self, getRequest()) self.order = PersistentDict() self.count = PersistentDict() if self.version is None: safeWrite(self, getRequest()) self.version = PersistentDict()
class Person(User, SearchableEntity, CorrelableEntity, Debatable): """Person class""" type_title = _('Person') icon = 'icon glyphicon glyphicon-user' #'icon novaideo-icon icon-user' templates = { 'default': 'novaideo:views/templates/person_result.pt', 'bloc': 'novaideo:views/templates/person_bloc.pt', 'small': 'novaideo:views/templates/small_person_result.pt', 'popover': 'novaideo:views/templates/person_popover.pt', 'card': 'novaideo:views/templates/person_card.pt', 'header': 'novaideo:views/templates/person_header.pt', } default_picture = 'novaideo:static/images/user100.png' name = renamer() tokens = CompositeMultipleProperty('tokens') tokens_ref = SharedMultipleProperty('tokens_ref') organization = SharedUniqueProperty('organization', 'members') events = SharedMultipleProperty('events', 'author') picture = CompositeUniqueProperty('picture') cover_picture = CompositeUniqueProperty('cover_picture') ideas = SharedMultipleProperty('ideas', 'author') selections = SharedMultipleProperty('selections') working_groups = SharedMultipleProperty('working_groups', 'members') wg_participations = SharedMultipleProperty('wg_participations', 'wating_list_participation') old_alerts = SharedMultipleProperty('old_alerts') following_channels = SharedMultipleProperty('following_channels', 'members') folders = SharedMultipleProperty('folders', 'author') questions = SharedMultipleProperty('questions', 'author') challenges = SharedMultipleProperty('challenges', 'author') ballots = CompositeMultipleProperty('ballots') mask = SharedUniqueProperty('mask', 'member') def __init__(self, **kwargs): self.branches = PersistentList() self.keywords = PersistentList() super(Person, self).__init__(**kwargs) kwargs.pop('password', None) self.set_data(kwargs) self.set_title() self.last_connection = datetime.datetime.now(tz=pytz.UTC) self._read_at = OOBTree() self.guide_tour_data = PersistentDict({}) self.confidence_index = 0 self._notes = OOBTree() self.allocated_tokens = OOBTree() self.len_allocated_tokens = PersistentDict({}) self.reserved_tokens = PersistentList([]) self._submited_at = OOBTree() self._reported_at = OOBTree() def __setattr__(self, name, value): super(Person, self).__setattr__(name, value) if name == 'organization' and value: self.init_contents_organizations() def get_len_tokens(self, root=None, exclude_reserved_tokens=False): root = root or getSite() return root.tokens_mini if exclude_reserved_tokens \ else root.tokens_mini + len(self.reserved_tokens) def get_len_evaluations(self, exclude_reserved_tokens=False): total = self.len_allocated_tokens.get(Evaluations.support, 0) + \ self.len_allocated_tokens.get(Evaluations.oppose, 0) if exclude_reserved_tokens: return total - len([ o for o in self.reserved_tokens if o in self.allocated_tokens ]) return total def get_len_free_tokens(self, root=None, exclude_reserved_tokens=False): root = root or getSite() return self.get_len_tokens(root, exclude_reserved_tokens) - \ self.get_len_evaluations(exclude_reserved_tokens) def has_token(self, obj=None, root=None): root = root or getSite() obj_oid = get_oid(obj, None) if obj_oid and obj_oid in self.reserved_tokens: return obj_oid not in self.allocated_tokens return self.get_len_free_tokens(root, True) > 0 def add_token(self, obj, evaluation_type, root=None): if self.has_token(obj, root): self.allocated_tokens[get_oid(obj)] = evaluation_type self.len_allocated_tokens.setdefault(evaluation_type, 0) self.len_allocated_tokens[evaluation_type] += 1 def remove_token(self, obj): obj_oid = get_oid(obj) if obj_oid in self.allocated_tokens: evaluation_type = self.allocated_tokens.pop(obj_oid) self.len_allocated_tokens.setdefault(evaluation_type, 0) self.len_allocated_tokens[evaluation_type] -= 1 def add_reserved_token(self, obj): obj_oid = get_oid(obj) if obj_oid not in self.reserved_tokens: self.reserved_tokens.append(obj_oid) def remove_reserved_token(self, obj): obj_oid = get_oid(obj) if obj_oid in self.reserved_tokens: self.reserved_tokens.remove(obj_oid) def evaluated_objs(self, evaluation_type=None): if evaluation_type: return [ get_obj(key) for value, key in self.allocated_tokens.byValue( evaluation_type) ] return [get_obj(key) for key in self.allocated_tokens.keys()] def evaluated_objs_ids(self, evaluation_type=None): if evaluation_type: return [ key for value, key in self.allocated_tokens.byValue( evaluation_type) ] return list(self.allocated_tokens.keys()) def init_contents_organizations(self): novaideo_catalog = find_catalog('novaideo') dace_catalog = find_catalog('dace') organizations_index = novaideo_catalog['organizations'] object_authors_index = novaideo_catalog['object_authors'] object_provides_index = dace_catalog['object_provides'] query = object_authors_index.any([get_oid(self)]) & \ object_provides_index.any( [Iidea.__identifier__, IProposal.__identifier__]) & \ organizations_index.any([0]) for entity in query.execute().all(): entity.init_organization() entity.reindex() def set_read_date(self, channel, date): self._read_at[get_oid(channel)] = date def get_read_date(self, channel): return self._read_at.get(get_oid(channel), datetime.datetime.now(tz=pytz.UTC)) def get_channel(self, user): all_channels = list(self.channels) all_channels.extend(list(getattr(user, 'channels', []))) for channel in all_channels: if user in channel.members and self in channel.members: return channel return None def addtoproperty(self, name, value, moving=None): super(Person, self).addtoproperty(name, value, moving) if name == 'selections': value.len_selections = getattr(value, 'len_selections', 0) value.len_selections += 1 def delfromproperty(self, name, value, moving=None): super(Person, self).delfromproperty(name, value, moving) if name == 'selections': value.len_selections = getattr(value, 'len_selections', 0) if value.len_selections > 0: value.len_selections -= 1 def set_title(self): if getattr(self, 'pseudonym', ''): self.title = self.pseudonym else: self.title = getattr(self, 'first_name', '') + ' ' + \ getattr(self, 'last_name', '') def add_note(self, user, context, note, date, time_constant): self._notes[date] = (get_oid(user), get_oid(context), note) self.calculate_confidence_index(time_constant) def get_questions(self, user): if user is self: return self.questions + getattr(self.mask, 'questions', []) return self.questions def get_ideas(self, user): if user is self: return self.ideas + getattr(self.mask, 'ideas', []) return self.ideas def get_working_groups(self, user): if user is self: return self.working_groups + getattr(self.mask, 'working_groups', []) return self.working_groups @property def proposals(self): return [wg.proposal for wg in self.working_groups] def get_proposals(self, user): if user is self: return self.proposals + getattr(self.mask, 'proposals', []) return self.proposals @property def contacts(self): return [s for s in self.selections if isinstance(s, Person)] @property def participations(self): result = [ p for p in list(self.proposals) if any(s in p.state for s in [ 'amendable', 'open to a working group', 'votes for publishing', 'votes for amendments' ]) ] return result def get_participations(self, user): if user is self: return self.participations + getattr(self.mask, 'participations', []) return self.participations @property def contents(self): result = [i for i in list(self.ideas) if i is i.current_version] result.extend(self.proposals) result.extend(self.questions) result.extend(self.challenges) result.extend(self.events) return result def get_contents(self, user): if user is self: return self.contents + getattr(self.mask, 'contents', []) return self.contents @property def active_working_groups(self): return [p.working_group for p in self.participations] def get_active_working_groups(self, user): if user is self: return self.active_working_groups + getattr( self.mask, 'active_working_groups', []) return self.active_working_groups def get_wg_participations(self, user): if user is self: return self.wg_participations + getattr(self.mask, 'wg_participations', []) return self.wg_participations @property def is_published(self): return 'active' in self.state @property def managed_organization(self): return get_objects_with_role(user=self, role='OrganizationResponsible') def get_confidence_index(self): return getattr(self, 'confidence_index', 0) def reindex(self): super(Person, self).reindex() root = getSite() self.__access_keys__ = PersistentList(generate_access_keys(self, root)) def get_picture_url(self, kind, default): if self.picture: img = getattr(self.picture, kind, None) if img: return img.url return default def get_more_contents_criteria(self): "return specific query, filter values" return None, None def set_organization(self, organization): current_organization = self.organization if organization: if current_organization is not organization: is_manager = current_organization and has_role( ('OrganizationResponsible', current_organization), self, ignore_superiors=True) if current_organization and is_manager: revoke_roles( self, (('OrganizationResponsible', current_organization), )) self.setproperty('organization', organization) elif current_organization: is_manager = has_role( ('OrganizationResponsible', current_organization), self, ignore_superiors=True) if is_manager: revoke_roles( self, (('OrganizationResponsible', current_organization), )) self.delfromproperty('organization', current_organization) @property def all_alerts(self): novaideo_catalog = find_catalog('novaideo') dace_catalog = find_catalog('dace') alert_keys_index = novaideo_catalog['alert_keys'] alert_exclude_keys_index = novaideo_catalog['alert_exclude_keys'] object_provides_index = dace_catalog['object_provides'] exclude = [str(get_oid(self))] if self.mask: exclude.append(str(get_oid(self.mask))) query = object_provides_index.any([IAlert.__identifier__]) & \ alert_keys_index.any(self.get_alerts_keys()) & \ alert_exclude_keys_index.notany(exclude) return query.execute() @property def alerts(self): old_alerts = [get_oid(a) for a in self.old_alerts] result = self.all_alerts def exclude(result_set, docids): filtered_ids = list(result_set.ids) for _id in docids: if _id in docids and _id in filtered_ids: filtered_ids.remove(_id) return result_set.__class__(filtered_ids, len(filtered_ids), result_set.resolver) return exclude(result, old_alerts) def get_alerts_keys(self): result = ['all', str(get_oid(self))] if self.mask: result.append(str(get_oid(self.mask))) return result def get_alerts(self, alerts=None, kind=None, subject=None, **kwargs): if alerts is None: alerts = self.alerts if kind: alerts = [a for a in alerts if a.is_kind_of(kind)] if subject: alerts = [a for a in alerts if subject in a.subjects] if kwargs: alerts = [a for a in alerts if a.has_args(**kwargs)] return alerts def calculate_confidence_index(self, time_constant): now = datetime.datetime.utcnow().timestamp() notes = np.array([v[2] for v in self._notes.values()]) dates = np.array([int(t.timestamp()) for t in self._notes.keys()]) time_c = time_constant * 86400 confidence_index = np.sum( np.dot(notes, np.exp(-np.log(2) * (now - dates) / time_c))) self.confidence_index = round(confidence_index, 1) @property def user_groups(self): groups = list(self.groups) if self.organization: groups.append(self.organization) if self.mask: groups.append(self.mask) return groups @property def user_locale(self): locale = getattr(self, 'locale', None) if not locale: locale = getSite(self).locale return locale def _init_mask(self, root): if not self.mask: mask = Mask() root.addtoproperty('masks', mask) self.setproperty('mask', mask) def get_mask(self, root=None): root = root if root else getSite() if not getattr(root, 'anonymisation', False): return self self._init_mask(root) return self.mask def add_submission(self, obj): now = datetime.datetime.now(tz=pytz.UTC) self._submited_at[now] = get_oid(obj) def add_report(self, obj): now = datetime.datetime.now(tz=pytz.UTC) self._reported_at[now] = get_oid(obj) def can_submit_idea(self, root=None): root = root if root else getSite() now = datetime.datetime.now(tz=pytz.UTC) monday = datetime.datetime.combine((now - datetime.timedelta(days=7)), datetime.time(0, 0, 0, tzinfo=pytz.UTC)) return len(self._submited_at.values(min=monday, max=now)) < getattr( root, 'nb_submission_maxi', 3) def can_report(self, root=None): root = root if root else getSite() now = datetime.datetime.now(tz=pytz.UTC) monday = datetime.datetime.combine((now - datetime.timedelta(days=7)), datetime.time(0, 0, 0, tzinfo=pytz.UTC)) return len(self._reported_at.values(min=monday, max=now)) < getattr( root, 'nb_reports_maxi', 3)
class Tokenable(Entity): """Question class""" tokens_opposition = CompositeMultipleProperty('tokens_opposition') tokens_support = CompositeMultipleProperty('tokens_support') def __init__(self, **kwargs): super(Tokenable, self).__init__(**kwargs) self.set_data(kwargs) self.allocated_tokens = OOBTree() self.len_allocated_tokens = PersistentDict({}) def add_token(self, user, evaluation_type): user_oid = get_oid(user) if user_oid in self.allocated_tokens: self.remove_token(user) self.allocated_tokens[user_oid] = evaluation_type self.len_allocated_tokens.setdefault(evaluation_type, 0) self.len_allocated_tokens[evaluation_type] += 1 def remove_token(self, user): user_oid = get_oid(user) if user_oid in self.allocated_tokens: evaluation_type = self.allocated_tokens.pop(user_oid) self.len_allocated_tokens.setdefault(evaluation_type, 0) self.len_allocated_tokens[evaluation_type] -= 1 def evaluators(self, evaluation_type=None): if evaluation_type: return [get_obj(key) for value, key in self.allocated_tokens.byValue(evaluation_type)] return [get_obj(key) for key in self.allocated_tokens.keys()] def evaluation(self, user): user_oid = get_oid(user, None) return self.allocated_tokens.get(user_oid, None) def remove_tokens(self, force=False): evaluators = self.evaluators() for user in evaluators: user.remove_token(self) if force: self.remove_token(user) def user_has_token(self, user, root=None): if hasattr(user, 'has_token'): return user.has_token(self, root) return False def init_support_history(self): # [(user_oid, date, support_type), ...], support_type = {1:support, 0:oppose, -1:withdraw} if not hasattr(self, '_support_history'): setattr(self, '_support_history', PersistentList()) @property def len_support(self): return self.len_allocated_tokens.get(Evaluations.support, 0) @property def len_opposition(self): return self.len_allocated_tokens.get(Evaluations.oppose, 0)
class SearchableEntity(VisualisableElement, Entity): """ A Searchable entity is an entity that can be searched""" templates = {'default': 'novaideo:templates/views/default_result.pt', 'bloc': 'novaideo:templates/views/default_result.pt'} def __init__(self, **kwargs): super(SearchableEntity, self).__init__(**kwargs) self.keywords = PersistentList() @property def is_published(self): return 'published' in self.state @property def is_workable(self): return self.is_published @property def relevant_data(self): return [getattr(self, 'title', ''), getattr(self, 'description', ''), ', '.join(getattr(self, 'keywords', []))] def set_source_data(self, source_data): if not hasattr(self, 'source_data'): self.source_data = PersistentDict({}) app_name = source_data.get('app_name') self.source_data.setdefault(app_name, {}) self.source_data[app_name] = source_data def get_source_data(self, app_id): if not hasattr(self, 'source_data'): return {} return self.source_data.get(app_id, {}) def is_managed(self, root): return True def get_title(self, user=None): return getattr(self, 'title', '') def _init_presentation_text(self): pass def get_release_date(self): return getattr(self, 'release_date', self.modified_at) def presentation_text(self, nb_characters=400): return getattr(self, 'description', "")[:nb_characters]+'...' def get_more_contents_criteria(self): "return specific query, filter values" return None, { 'metadata_filter': { 'states': ['published'], 'keywords': list(self.keywords) } }
class DataRoot(Evolvable): """ The DataRoot has the following attributes: :ivar repositories: a `PersistentList` of `Repository` instances. :ivar archives: an `OOBTree` mapping hex archive IDs to `Archive` instances. :ivar clients: an `OOBTree` mapping host names to `Client` instances. :ivar jobs: an `OOBTree` mapping TODO to `Job` instances. :ivar jobs_by_state: an `OOBTree` mapping job states to trees of `Job` instances. :ivar schedules: a `PersistentList` of `Schedule` instances. :ivar ext: a `PersistentDict` of extension data (see `plugin_data`, **do not use directly**). """ version = 6 @evolve(1, 2) def add_ext_dict(self): self.ext = PersistentDict() @evolve(2, 3) def ensure_base_job_states(self): pass # superseded @evolve(3, 4) def defaultdict(self): self.jobs_by_state = PersistentDefaultDict(self.jobs_by_state, factory=TimestampTree) @evolve(4, 5) def numbered_jobs(self): self.jobs = NumberTree(self.jobs) for state in self.jobs_by_state: self.jobs_by_state[state] = LOBTree() for id, job in self.jobs.items(): self.jobs_by_state[state][id] = job @evolve(5, 6) def add_triggers(self): self.trigger_ids = OOBTree() def __init__(self): self.repositories = PersistentList() # hex archive id -> Archive self.archives = OOBTree() # client hostname -> Client self.clients = OOBTree() # job number -> Job # note: this tree is the canonical source of job numbers. self.jobs = NumberTree() # job state (str) -> NumberTree self.jobs_by_state = PersistentDefaultDict(factory=LOBTree) self.schedules = PersistentList() self.trigger_ids = OOBTree() self.ext = PersistentDict() def plugin_data(self, factory): """ Return an instance generated (at some point in time) by *factory*. This should be used for storing plugin data, eg.:: class AwesomePluginData(Evolvable): name = 'awesome-plugin' def __init__(self): self.some_data = OOBTree() ... def show_some_data(request): # You might want to just put this in a separate helper (below) plugdat = data_root().plugin_data(AwesomePluginData) return TemplateResponse(...) # A sample helper def plugin_root(): return data_root().plugin_data(AwesomePluginData) A good *name* would be the entrypoint name of your plugin, or it's root module/package name. The *name* attribute on *factory* is not mandatory. If it is not present the qualified class name is used instead (eg. ``awesomeplugin.data.AwesomePluginData``) """ try: name = factory.name except AttributeError: name = factory.__module__ + '.' + factory.__qualname__ try: return self.ext[name] except KeyError: log.debug('Initialized new data root for plugin %s', name) return self.ext.setdefault(name, factory())
class Taxonomy(SimpleItem): order = None count = None version = None def __init__(self, name, title, default_language): self.data = PersistentDict() self.order = PersistentDict() self.count = PersistentDict() self.version = PersistentDict() self.name = name self.title = title self.default_language = default_language @property def sm(self): return api.portal.get().getSiteManager() def __call__(self, context): if not self.data: return Vocabulary(self.name, {}, {}, {}, 2) request = getattr(context, "REQUEST", None) language = self.getCurrentLanguage(request) return self.makeVocabulary(language) @property @ram.cache(lambda method, self: (self.name, self.data._p_mtime)) def inverted_data(self): inv_data = {} for (language, elements) in self.data.items(): inv_data[language] = {} for (path, identifier) in elements.items(): inv_data[language][identifier] = path return inv_data def getShortName(self): return self.name.split('.')[-1] def getGeneratedName(self): return 'collective.taxonomy.generated.' + self.getShortName() def getVocabularyName(self): return 'collective.taxonomy.' + self.getShortName() def makeVocabulary(self, language): self._fixup() data = self.data.get(language, {}) order = self.order.get(language) version = self.version.get(language, 1) inverted_data = self.inverted_data.get(language, {}) return Vocabulary(self.name, data, inverted_data, order, version) def getCurrentLanguage(self, request): language = get_lang_code() if language in self.data: return language elif self.default_language in self.data: return self.default_language else: # our best guess! return self.data.keys()[0] def getLanguages(self): return tuple(self.data) def iterLanguage(self, language=None): if language is None: language = self.default_language vocabulary = self.makeVocabulary(language) for path, identifier in vocabulary.iterEntries(): parent_path = path.rsplit(PATH_SEPARATOR, 1)[0] if parent_path: parent = vocabulary.getTermByValue(parent_path) else: parent = None yield path, identifier, parent def registerBehavior(self, **kwargs): new_args = copy(kwargs) new_args['name'] = self.getGeneratedName() new_args['title'] = self.title new_args['description'] = kwargs.get('field_description', u'') new_args['field_description'] = new_args['description'] behavior = TaxonomyBehavior(**new_args) self.sm.registerUtility(behavior, IBehavior, name=self.getGeneratedName()) behavior.addIndex() behavior.activateSearchable() def cleanupFTI(self): """Cleanup the FTIs""" generated_name = self.getGeneratedName() for (name, fti) in self.sm.getUtilitiesFor(IDexterityFTI): if generated_name in fti.behaviors: fti.behaviors = [behavior for behavior in fti.behaviors if behavior != generated_name] modified(fti, DexterityFTIModificationDescription("behaviors", '')) def updateBehavior(self, **kwargs): behavior_name = self.getGeneratedName() short_name = self.getShortName() utility = self.sm.queryUtility(IBehavior, name=behavior_name) if utility: utility.deactivateSearchable() utility.activateSearchable() if 'field_title' in kwargs: utility.title = kwargs.pop('field_title') for k, v in kwargs.items(): setattr(utility, k, v) delattr(generated, short_name) for (name, fti) in self.sm.getUtilitiesFor(IDexterityFTI): if behavior_name in fti.behaviors: modified(fti, DexterityFTIModificationDescription("behaviors", '')) def unregisterBehavior(self): behavior_name = self.getGeneratedName() utility = self.sm.queryUtility(IBehavior, name=behavior_name) if utility is None: return self.cleanupFTI() utility.removeIndex() utility.deactivateSearchable() utility.unregisterInterface() self.sm.unregisterUtility(utility, IBehavior, name=behavior_name) def clean(self): self.data.clear() def add(self, language, value, key): self._fixup() tree = self.data.get(language) if tree is None: tree = self.data[language] = OOBTree() else: # Make sure we update the modification time. self.data[language] = tree update = key in tree tree[key] = value order = self.order.get(language) if order is None: order = self.order[language] = IOBTree() count = self.count[language] = 0 else: if update: pop_value(tree, key) count = self.count[language] + 1 self.count[language] = count order[count] = key def update(self, language, items, clear=False): self._fixup() tree = self.data.setdefault(language, OOBTree()) if clear: tree.clear() # A new tree always uses the newest version. if not tree: version = self.version[language] = 2 else: version = self.version.get(language, 1) order = self.order.setdefault(language, IOBTree()) count = self.count.get(language, 0) if clear: order.clear() count = 0 # Always migrate to newest version. if version == 1: def fix(path): return path.replace(LEGACY_PATH_SEPARATOR, PATH_SEPARATOR) for i in list(order): path = order[i] order[i] = fix(path) for path in list(tree): value = tree.pop(path) tree[fix(path)] = value version = self.version[language] = 2 logger.info( "Taxonomy '%s' upgraded to version %d for language '%s'." % ( self.name, version, language ) ) # Make sure we update the modification time. self.data[language] = tree # The following structure is used to expunge updated entries. inv = {} if not clear: for i, key in order.items(): inv[key] = i seen = set() for key, value in items: if key in seen: logger.warning("Duplicate key entry: %r" % (key, )) seen.add(key) update = key in tree tree[key] = value order[count] = key count += 1 # If we're updating, then we have to pop out the old ordering # information in order to maintain relative ordering of new items. if update: i = inv.get(key) if i is not None: del order[i] self.count[language] = count def translate(self, msgid, mapping=None, context=None, target_language=None, default=None, msgid_plural=None, default_plural=None, number=None): if target_language is None or \ target_language not in self.inverted_data: target_language = str(self.getCurrentLanguage( getattr(context, 'REQUEST') )) if msgid not in self.inverted_data[target_language]: return '' if self.version is not None and self.version.get(target_language) != 2: path_sep = LEGACY_PATH_SEPARATOR else: path_sep = PATH_SEPARATOR path = self.inverted_data[target_language][msgid] pretty_path = path[1:].replace(path_sep, PRETTY_PATH_SEPARATOR) if mapping is not None and mapping.get(NODE): pretty_path = pretty_path.rsplit(PRETTY_PATH_SEPARATOR, 1)[-1] return pretty_path def _fixup(self): # due to compatibility reasons this method fixes data structure # for old Taxonomy instances. # XXX: remove this in version 2.0 to prevent write on read if self.order is None: safeWrite(self, getRequest()) self.order = PersistentDict() self.count = PersistentDict() if self.version is None: safeWrite(self, getRequest()) self.version = PersistentDict()
class Person(User, SearchableEntity, CorrelableEntity, Debatable): """Person class""" type_title = _('Person') icon = 'icon glyphicon glyphicon-user' #'icon novaideo-icon icon-user' templates = {'default': 'novaideo:views/templates/person_result.pt', 'bloc': 'novaideo:views/templates/person_bloc.pt', 'small': 'novaideo:views/templates/small_person_result.pt', 'popover': 'novaideo:views/templates/person_popover.pt', 'card': 'novaideo:views/templates/person_card.pt', 'header': 'novaideo:views/templates/person_header.pt',} default_picture = 'novaideo:static/images/user100.png' name = renamer() tokens = CompositeMultipleProperty('tokens') tokens_ref = SharedMultipleProperty('tokens_ref') organization = SharedUniqueProperty('organization', 'members') picture = CompositeUniqueProperty('picture') cover_picture = CompositeUniqueProperty('cover_picture') ideas = SharedMultipleProperty('ideas', 'author') selections = SharedMultipleProperty('selections') working_groups = SharedMultipleProperty('working_groups', 'members') old_alerts = SharedMultipleProperty('old_alerts') following_channels = SharedMultipleProperty('following_channels', 'members') folders = SharedMultipleProperty('folders', 'author') questions = SharedMultipleProperty('questions', 'author') challenges = SharedMultipleProperty('challenges', 'author') mask = SharedUniqueProperty('mask', 'member') def __init__(self, **kwargs): super(Person, self).__init__(**kwargs) kwargs.pop('password', None) self.set_data(kwargs) self.set_title() self.last_connection = datetime.datetime.now(tz=pytz.UTC) self._read_at = OOBTree() self.guide_tour_data = PersistentDict({}) self.allocated_tokens = OOBTree() self.len_allocated_tokens = PersistentDict({}) self.reserved_tokens = PersistentList([]) def __setattr__(self, name, value): super(Person, self).__setattr__(name, value) if name == 'organization' and value: self.init_contents_organizations() def get_len_tokens(self, root=None, exclude_reserved_tokens=False): root = root or getSite() return root.tokens_mini if exclude_reserved_tokens \ else root.tokens_mini + len(self.reserved_tokens) def get_len_evaluations(self, exclude_reserved_tokens=False): total = self.len_allocated_tokens.get(Evaluations.support, 0) + \ self.len_allocated_tokens.get(Evaluations.oppose, 0) if exclude_reserved_tokens: return total - len([o for o in self.reserved_tokens if o in self.allocated_tokens]) return total def get_len_free_tokens(self, root=None, exclude_reserved_tokens=False): root = root or getSite() return self.get_len_tokens(root, exclude_reserved_tokens) - \ self.get_len_evaluations(exclude_reserved_tokens) def has_token(self, obj=None, root=None): root = root or getSite() obj_oid = get_oid(obj, None) if obj_oid and obj_oid in self.reserved_tokens: return obj_oid not in self.allocated_tokens return self.get_len_free_tokens(root, True)>0 def add_token(self, obj, evaluation_type, root=None): if self.has_token(obj, root): self.allocated_tokens[get_oid(obj)] = evaluation_type self.len_allocated_tokens.setdefault(evaluation_type, 0) self.len_allocated_tokens[evaluation_type] += 1 def remove_token(self, obj): obj_oid = get_oid(obj) if obj_oid in self.allocated_tokens: evaluation_type = self.allocated_tokens.pop(obj_oid) self.len_allocated_tokens.setdefault(evaluation_type, 0) self.len_allocated_tokens[evaluation_type] -= 1 def add_reserved_token(self, obj): obj_oid = get_oid(obj) if obj_oid not in self.reserved_tokens: self.reserved_tokens.append(obj_oid) def remove_reserved_token(self, obj): obj_oid = get_oid(obj) if obj_oid in self.reserved_tokens: self.reserved_tokens.remove(obj_oid) def evaluated_objs(self, evaluation_type=None): if evaluation_type: return [get_obj(key) for value, key in self.allocated_tokens.byValue(evaluation_type)] return [get_obj(key) for key in self.allocated_tokens.keys()] def evaluated_objs_ids(self, evaluation_type=None): if evaluation_type: return [key for value, key in self.allocated_tokens.byValue(evaluation_type)] return list(self.allocated_tokens.keys()) def init_contents_organizations(self): novaideo_catalog = find_catalog('novaideo') dace_catalog = find_catalog('dace') organizations_index = novaideo_catalog['organizations'] object_authors_index = novaideo_catalog['object_authors'] object_provides_index = dace_catalog['object_provides'] query = object_authors_index.any([get_oid(self)]) & \ object_provides_index.any( [Iidea.__identifier__, IProposal.__identifier__]) & \ organizations_index.any([0]) for entity in query.execute().all(): entity.init_organization() entity.reindex() def set_read_date(self, channel, date): self._read_at[get_oid(channel)] = date def get_read_date(self, channel): return self._read_at.get( get_oid(channel), datetime.datetime.now(tz=pytz.UTC)) def get_channel(self, user): all_channels = list(self.channels) all_channels.extend(list(getattr(user, 'channels', []))) for channel in all_channels: if user in channel.members and self in channel.members: return channel return None def addtoproperty(self, name, value, moving=None): super(Person, self).addtoproperty(name, value, moving) if name == 'selections': value.len_selections = getattr(value, 'len_selections', 0) value.len_selections += 1 def delfromproperty(self, name, value, moving=None): super(Person, self).delfromproperty(name, value, moving) if name == 'selections': value.len_selections = getattr(value, 'len_selections', 0) if value.len_selections > 0: value.len_selections -= 1 def set_title(self): self.title = getattr(self, 'first_name', '') + ' ' + \ getattr(self, 'last_name', '') def get_questions(self, user): if user is self: return self.questions + getattr(self.mask, 'questions', []) return self.questions def get_ideas(self, user): if user is self: return self.ideas + getattr(self.mask, 'ideas', []) return self.ideas def get_working_groups(self, user): if user is self: return self.working_groups + getattr(self.mask, 'working_groups', []) return self.working_groups @property def proposals(self): return [wg.proposal for wg in self.working_groups] def get_proposals(self, user): if user is self: return self.proposals + getattr(self.mask, 'proposals', []) return self.proposals @property def contacts(self): return [s for s in self.selections if isinstance(s, Person)] @property def participations(self): result = [p for p in list(self.proposals) if any(s in p.state for s in ['amendable', 'open to a working group', 'votes for publishing', 'votes for amendments'])] return result def get_participations(self, user): if user is self: return self.participations + getattr(self.mask, 'participations', []) return self.participations @property def contents(self): result = [i for i in list(self.ideas) if i is i.current_version] result.extend(self.proposals) result.extend(self.questions) result.extend(self.challenges) return result def get_contents(self, user): if user is self: return self.contents + getattr(self.mask, 'contents', []) return self.contents @property def active_working_groups(self): return [p.working_group for p in self.participations] def get_active_working_groups(self, user): if user is self: return self.active_working_groups + getattr(self.mask, 'active_working_groups', []) return self.active_working_groups @property def is_published(self): return 'active' in self.state @property def managed_organization(self): return get_objects_with_role(user=self, role='OrganizationResponsible') def reindex(self): super(Person, self).reindex() root = getSite() self.__access_keys__ = PersistentList(generate_access_keys( self, root)) def get_picture_url(self, kind, default): if self.picture: img = getattr(self.picture, kind, None) if img: return img.url return default def get_more_contents_criteria(self): "return specific query, filter values" return None, None def set_organization(self, organization): current_organization = self.organization if organization: if current_organization is not organization: is_manager = current_organization and has_role( ('OrganizationResponsible', current_organization), self, ignore_superiors=True) if current_organization and is_manager: revoke_roles( self, (('OrganizationResponsible', current_organization),)) self.setproperty('organization', organization) elif current_organization: is_manager = has_role( ('OrganizationResponsible', current_organization), self, ignore_superiors=True) if is_manager: revoke_roles( self, (('OrganizationResponsible', current_organization),)) self.delfromproperty('organization', current_organization) @property def all_alerts(self): novaideo_catalog = find_catalog('novaideo') dace_catalog = find_catalog('dace') alert_keys_index = novaideo_catalog['alert_keys'] alert_exclude_keys_index = novaideo_catalog['alert_exclude_keys'] object_provides_index = dace_catalog['object_provides'] exclude = [str(get_oid(self))] if self.mask: exclude.append(str(get_oid(self.mask))) query = object_provides_index.any([IAlert.__identifier__]) & \ alert_keys_index.any(self.get_alerts_keys()) & \ alert_exclude_keys_index.notany(exclude) return query.execute() @property def alerts(self): old_alerts = [get_oid(a) for a in self.old_alerts] result = self.all_alerts def exclude(result_set, docids): filtered_ids = list(result_set.ids) for _id in docids: if _id in docids and _id in filtered_ids: filtered_ids.remove(_id) return result_set.__class__( filtered_ids, len(filtered_ids), result_set.resolver) return exclude(result, old_alerts) def get_alerts_keys(self): result = ['all', str(get_oid(self))] if self.mask: result.append(str(get_oid(self.mask))) return result def get_alerts(self, alerts=None, kind=None, subject=None, **kwargs): if alerts is None: alerts = self.alerts if kind: alerts = [a for a in alerts if a.is_kind_of(kind)] if subject: alerts = [a for a in alerts if subject in a.subjects] if kwargs: alerts = [a for a in alerts if a.has_args(**kwargs)] return alerts @property def user_groups(self): groups = list(self.groups) if self.organization: groups.append(self.organization) if self.mask: groups.append(self.mask) return groups @property def user_locale(self): locale = getattr(self, 'locale', None) if not locale: locale = getSite(self).locale return locale def _init_mask(self, root): if not self.mask: mask = Mask() root.addtoproperty('masks', mask) self.setproperty('mask', mask) def get_mask(self, root=None): root = root if root else getSite() if not getattr(root, 'anonymisation', False): return self self._init_mask(root) return self.mask