예제 #1
0
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
예제 #2
0
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)
예제 #3
0
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
예제 #5
0
파일: storage.py 프로젝트: rockfruit/mars
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()
예제 #6
0
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)
예제 #7
0
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)
예제 #8
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)
            }
        }
예제 #9
0
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()
예제 #10
0
파일: person.py 프로젝트: ecreall/KuneAgi
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)
예제 #11
0
파일: core.py 프로젝트: ecreall/nova-ideo
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)
예제 #12
0
파일: core.py 프로젝트: ecreall/nova-ideo
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)
            }
        }
예제 #13
0
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())
예제 #14
0
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()
예제 #15
0
파일: person.py 프로젝트: ecreall/nova-ideo
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