示例#1
0
class Annotations(Persistent, Location):
    """Stores annotations."""

    def __init__(self, principalId, store=None):
        self.principalId = principalId
        self.data = PersistentDict() # We don't really expect that many

        # _v_store is used to remember a mapping object that we should
        # be saved in if we ever change
        self._v_store = store

    def __bool__(self):
        nz = bool(self.data)
        if not nz:
            # maybe higher-level utility's annotations will be non-zero
            next = queryNextUtility(self, IPrincipalAnnotationUtility)
            if next is not None:
                annotations = next.getAnnotationsById(self.principalId)
                return bool(next)
        return nz

    __nonzero__ = __bool__

    def __getitem__(self, key):
        try:
            return self.data[key]
        except KeyError:
            # We failed locally: delegate to a higher-level utility.
            next = queryNextUtility(self, IPrincipalAnnotationUtility)
            if next is not None:
                annotations = next.getAnnotationsById(self.principalId)
                return annotations[key]
            raise

    def get(self, key, default=None):
        try:
            return self[key]
        except KeyError:
            return default

    def __setitem__(self, key, value):
        if getattr(self, '_v_store', None) is not None:
            # _v_store is used to remember a mapping object that we should
            # be saved in if we ever change
            self._v_store[self.principalId] = self
            del self._v_store

        self.data[key] = value

    def __delitem__(self, key):
        del self.data[key]

    def __iter__(self):
        return iter(self.data)

    def __contains__(self, key):
        return key in self.data

    def items(self):
        return self.data.items()
示例#2
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
示例#3
0
class UserAnnotation(object):
    """Stores annotations."""

    def __init__(self, principalId, store=None):
        self.principalId = principalId
        # _v_store is used to remember a mapping object that we should
        # be saved in if we ever change
        self._v_store = store
        self._data = PersistentDict() if store is None else store.get(principalId, PersistentDict())

    def __bool__(self):
        return bool(self._data)

    __nonzero__ = __bool__

    def __getitem__(self, key):
        return self._data[key]

    def get(self, key, default=None):
        return self._data.get(key, default)

    def keys(self):
        return self._data.keys()

    def __iter__(self):
        return iter(self._data)

    def __len__(self):
        return len(self._data)

    def __setitem__(self, key, value):
        if getattr(self, '_v_store', None) is not None:
            # _v_store is used to remember a mapping object that we should
            # be saved in if we ever change
            self._v_store[self.principalId] = self._data
            del self._v_store

        self._data[key] = value

    def __delitem__(self, key):
        del self._data[key]

    def __contains__(self, key):
        return key in self._data

    def items(self):
        return self._data.items()
示例#4
0
class UserAnnotation(object):
    """Stores annotations."""
    def __init__(self, principalId, store=None):
        self.principalId = principalId
        # _v_store is used to remember a mapping object that we should
        # be saved in if we ever change
        self._v_store = store
        self._data = PersistentDict() if store is None else store.get(
            principalId, PersistentDict())

    def __bool__(self):
        return bool(self._data)

    __nonzero__ = __bool__

    def __getitem__(self, key):
        return self._data[key]

    def get(self, key, default=None):
        return self._data.get(key, default)

    def keys(self):
        return self._data.keys()

    def __iter__(self):
        return iter(self._data)

    def __len__(self):
        return len(self._data)

    def __setitem__(self, key, value):
        if getattr(self, '_v_store', None) is not None:
            # _v_store is used to remember a mapping object that we should
            # be saved in if we ever change
            self._v_store[self.principalId] = self._data
            del self._v_store

        self._data[key] = value

    def __delitem__(self, key):
        del self._data[key]

    def __contains__(self, key):
        return key in self._data

    def items(self):
        return self._data.items()
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
示例#6
0
class MockContainer(PortalContent):
    """ """
    implements(IUIDKeyedContainer, IAttributeUUID)

    def __init__(self, id, items=None):
        super(MockContainer, self).__init__()
        self.id = id
        self._items = PersistentDict(items)

    def get(self, uid, default=None):
        v = self._items.get(str(uid), None)
        if v and getattr(v, '_v_parent', None) is None:
            v._v_parent = self  # container marks obtained item with context
        return v

    # just here for test use:
    def register(self, uid, item):
        self._items[uid] = item

    def unregister(self, uid):
        del(self._items[uid])

    def __contains__(self, uid):
        return uid in self._items

    # here for indexing purposes, even though these indexes may
    # be handled differently in real life (e.g. indexer adapter):

    def UID(self):
        return IUUID(self)

    def contains(self):
        return self._items.keys()  # UUIDs of contained items

    def items(self):
        return self._items.items()
示例#7
0
class MockContainer(PortalContent):
    """ """
    implements(IUIDKeyedContainer, IAttributeUUID)

    def __init__(self, id, items=None):
        super(MockContainer, self).__init__()
        self.id = id
        self._items = PersistentDict(items)

    def get(self, uid, default=None):
        v = self._items.get(str(uid), None)
        if v and getattr(v, '_v_parent', None) is None:
            v._v_parent = self  # container marks obtained item with context
        return v

    # just here for test use:
    def register(self, uid, item):
        self._items[uid] = item

    def unregister(self, uid):
        del (self._items[uid])

    def __contains__(self, uid):
        return uid in self._items

    # here for indexing purposes, even though these indexes may
    # be handled differently in real life (e.g. indexer adapter):

    def UID(self):
        return IUUID(self)

    def contains(self):
        return self._items.keys()  # UUIDs of contained items

    def items(self):
        return self._items.items()
class Taxonomy(SimpleItem):
    implements(ITaxonomy)

    def __init__(self, name, title, default_language):
        super(Taxonomy, self).__init__(self)
        self.data = PersistentDict()
        self.name = name
        self.title = title
        self.default_language = default_language

    def __call__(self, context):

        if not self.data:
            return Vocabulary(self.name, {}, {})

        request = getattr(context, "REQUEST", None)

        current_language = self.getCurrentLanguage(request)
        data = self.data[current_language]
        inverted_data = self.inverted_data[current_language]

        return Vocabulary(self.name, data, inverted_data)

    @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 getCurrentLanguage(self, request):
        try:
            portal_state = getMultiAdapter(
                (self, request), name=u'plone_portal_state'
            )

            language = portal_state.language().split('-', 1)[0]
        except ComponentLookupError:
            language = ''  # Force to return default language.

        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 registerBehavior(self, **kwargs):
        context = getSite()
        sm = context.getSiteManager()
        new_args = copy(kwargs)

        new_args['name'] = self.name
        new_args['title'] = self.title
        new_args['description'] = kwargs.get('field_description', u'')
        new_args['field_description'] = new_args['description']

        behavior = TaxonomyBehavior(**new_args)
        sm.registerUtility(behavior, IBehavior,
                           name=self.getGeneratedName())

        behavior.addIndex()
        behavior.activateSearchable()

    def cleanupFTI(self):
        """Cleanup the FTIs"""
        generated_name = self.getGeneratedName()
        context = getSite()
        sm = context.getSiteManager()
        for (name, fti) in 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):
        sm = getSite().getSiteManager()

        behavior_name = self.getGeneratedName()
        short_name = self.getShortName()

        utility = sm.queryUtility(IBehavior, name=behavior_name)
        if utility:
            utility.deactivateSearchable()
            utility.activateSearchable()
            utility.title = kwargs['field_title']

        delattr(generated, short_name)

        for (name, fti) in sm.getUtilitiesFor(IDexterityFTI):
            if behavior_name in fti.behaviors:
                modified(fti, DexterityFTIModificationDescription("behaviors", ''))

    def unregisterBehavior(self):
        context = getSite()
        sm = context.getSiteManager()
        behavior_name = self.getGeneratedName()
        utility = sm.queryUtility(IBehavior, name=behavior_name)

        if utility is None:
            return

        self.cleanupFTI()

        utility.removeIndex()
        utility.deactivateSearchable()
        utility.unregisterInterface()

        sm.unregisterUtility(utility, IBehavior, name=behavior_name)

    def clean(self):
        self.data.clear()

    def add(self, language, identifier, path):
        if not language in self.data:
            self.data[language] = OOBTree()

        self.data[language][path] = identifier

    def translate(self, msgid, mapping=None, context=None,
                  target_language=None, default=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 ''

        path = self.inverted_data[target_language][msgid]
        pretty_path = path[1:].replace(PATH_SEPARATOR, u' » ')

        return pretty_path
示例#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
class Taxonomy(SimpleItem):
    def __init__(self, name, title, default_language):
        self.data = 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, {}, {})

        request = getattr(context, "REQUEST", None)

        current_language = self.getCurrentLanguage(request)
        data = self.data[current_language]
        inverted_data = self.inverted_data[current_language]

        return Vocabulary(self.name, data, inverted_data)

    @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 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 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.iteritems():
                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, identifier, path):
        if language not in self.data:
            self.data[language] = OOBTree()

        self.data[language][path] = identifier

    def translate(self,
                  msgid,
                  mapping=None,
                  context=None,
                  target_language=None,
                  default=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 ''

        path = self.inverted_data[target_language][msgid]
        pretty_path = path[1:].replace(PATH_SEPARATOR, u' » ')

        return pretty_path
示例#11
0
class OrderStorage(BTreeContainer):

    def __init__(self):
        super(OrderStorage, self).__init__()
        self.indexes = PersistentDict({
            'products': KeywordIndex(),
            'user_id': FieldIndex(),
            'processor_order_id': FieldIndex(),
            'finance_state': FieldIndex(),
            'fulfillment_state': FieldIndex(),
            'creation_date': FieldIndex(),
            'renewal_date': FieldIndex()
            }
        )

    def query(self, **args):
        results = self.apply(args)
        return ResultSet(results, self)

    def apply(self, query):
        results = []
        for index_name, index_query in query.items():
            index = self.indexes.get(index_name)
            if index is None:
                continue
            r = index.apply(index_query)
            if r is None:
                continue
            if not r:
                # empty results
                return r
            results.append((len(r), r))

        if not results:
            # no applicable indexes, so catalog was not applicable
            return None

        results.sort()  # order from smallest to largest

        _, result = results.pop(0)
        for _, r in results:
            _, result = weightedIntersection(result, r)

        return result

    def __setitem__(self, key, object):
        super(OrderStorage, self).__setitem__(key, object)
        self.index(object)

    def reset_index(self):
        # reindex all orders
        for index in self.indexes.values():
            index.clear()
        for order in self.values():
            self.index(order)

    def reindex(self, object):
        self.unindex(object.order_id)
        self.index(object)

    def index(self, object):
        doc_id = int(object.order_id)
        for attr, index in self.indexes.items():
            value = getattr(object, attr, None)
            if callable(value):
                value = value()
            if value is None:
                continue
            index.index_doc(doc_id, value)

    def unindex(self, order_id):
        for index in self.indexes.values():
            index.unindex_doc(int(order_id))

    def __delitem__(self, key):
        super(OrderStorage, self).__delitem__(key)
        doc_id = int(key)
        self.unindex(doc_id)
示例#12
0
class Product(Persistent):
	"""Models a product composition by listing the materials and activities
	needed to produce it.
	
	Attributes:
	
	Code: A key that uniquely identifies the product.
	Name: Name of the product.
	Materials: List of materials, and amounts needed to make the product.
	Activities: List of activities and its consumption needed to make the product. 
	"""

	def __init__(self, code, name, description, base_unit):
		"""Creates a new product"""
		self.code = code
		self.name = name
		self.description = description
		self.bill_of_materials = PersistentDict()
		self.bill_of_activities = PersistentDict()
		
	def addMaterial(self, material_code, consumption, consumption_unit, 
						  production_ratio, production_unit,  waste, cost_per_unit= 0 ):
		''' Adds a new material to the product list and the information related 
		to the consumption to the F.P. production the parameters are the following:
		material_code : Code of the material to be consumed.
		consumption: Amount of material consumed.
		consumption_unit: Unit in which the consumption amount is expressed.
		production_ratio: Units of F.P. to which the consumption is referred.
		production_unit : Unit of production to which the production ratio is related.
		waste: % of the material thrown to the waste.
		
		The function returns a Boolean and an error dictionary. If any of the parameters
		is not valid False and errors are returned. 
		'''
		
		# First of all the the information validity is checked
		
		# access material information to check code's validity
		materialtrax = MaterialTrax().materials
		# initializes a dictionary where to save the information errors.
		errors = {}
		# flag to stop saving the information if an error arises.
		information_is_valid = True
		
		if is_number(material_code) :
			material_code =int(material_code)
			if material_code not in materialtrax:
				errors['material_code'] = "Material code does not exist"
				information_is_valid = False
		else:
			errors['material_code'] = "Material code must be an integer"
			information_is_valid = False
		
		if is_number(consumption):
			consumption = float(consumption)
		else:
			errors['consumption'] = "Consumption must be a number"
			information_is_valid = False
		
		if is_number(production_ratio):
			production_ratio = float(production_ratio)
		else:
			errors['production_ratio'] = "Production ratio must be a number"
			
		if is_number(waste):
			if waste > 100 or waste < 0:
				errors['waste'] = "Waste cannot be greater than 100"
				information_is_valid = False
			else:
				waste = float(waste)
		else:
			errors['waste'] = "Waste must be a number between 0 and 100"
			information_is_valid = False
			
		# if it is not valid it returns the errors detected so they can be 
		# correct		
		if information_is_valid :
			self.bill_of_materials[material_code] = {'material_code': material_code,
								'consumption': consumption,
								'consumption_unit' : consumption_unit,
								'production_unit': production_unit,
								'production_ratio': production_ratio * 1.0,
								'waste' : waste * 1.0 ,
								'cost_per_unit': cost_per_unit * 1.0}
			self._p_changed = True
			return True, errors
		else:		
			return False, errors
			

		
	def addActivity(self, activity_code, consumption, activity_unit, 
						  production_ratio, production_unit, cost_per_unit = 0):
		"""Adds a new activity in the product list needed to make the product and
		the information related with the consumption for each unit on F.P. 
		Parameters:
		consumption: Amount of activity consumed.
		activiy_unit: Unit in which the consumption amount is expressed.
		production_ratio: Units of F.P. to which the consumption is referred.
		production_unit : Unit of production to which the production ratio is related.
		"""
		
				# First of all the the information validity is checked
		
		# access material information to check code's validity
		activitytrax = ActivityTrax().activities
		# initializes a dictionary where to save the information errors.
		errors = {}
		# flag to stop saving the information if an error arises.
		information_is_valid = True
		
		if is_number(activity_code) :
			activity_code =int(activity_code)
			if activity_code not in activitytrax:
				errors['material_code'] = "Activity code does not exist"
				information_is_valid = False
		else:
			errors['activity_code'] = "Activity code must be an integer"
			information_is_valid = False

		if is_number(consumption) :
			consumption = float(consumption)
		else:
			errors['consumption'] = "Consumption must be a number"
			information_is_valid = False
			
		if is_number(production_ratio):
			production_ratio = float(production_ratio)
		else:
			errors['production_ratio'] = "Production ratio must be a number"
			information_is_valid = False
			
			
		if information_is_valid:	
			
			self.bill_of_activities[activity_code] = {	'activity_code': activity_code, 
												'consumption': consumption * 1.0 ,
												'activity_unit': activity_unit,
												'production_ratio': production_ratio * 1.0 ,
												'production_unit': production_unit,
												'cost_per_unit' : cost_per_unit * 1.0	}
			self._p_changed = True
			return True, errors
			
		return False, errors
		
		
	def CalculateCost(self):
		"""Calculates the direct product cost based on materials and activities consumption.
		This function doesn't check yet:
		A. Consumption units and price units for the activities are homogeneous.
		B. production ratios per unit of output are homogeneous among the activities.
		Parameters:
		Product code
		Returns two values:
			1. Total material cost.
			2. Total activity cost.
		"""
	
		 # Recovers the information about activities and materials needed to calculate the cost
		 # Maybe it would be better to filter the activities and materials in the bill of materials
		 # and bill of activities. I will implement this later if too many materials or activities
		 # are loaded in memory. One alternative is to save a reference to the material object as
		 # ZODB database works exactly as if were python objects.
		 
		activitytrax = ActivityTrax().activities
		materialtrax = MaterialTrax().materials
		
		# initialize the accum for the cost of materials and activities
		material_cost = 0
		activity_cost = 0
		
		# calculates the cost of each material and adds it to the material accum.
		# takes into account the production ratio and material waste
		for material_code, material in self.bill_of_materials.items():
			material_cost += ( 	materialtrax[material_code].cost_per_unit * 
								material["consumption"] / 
								material["production_ratio"] *
								(1 + material["waste"]/100) 
							)
		# Idem as above for activities but no waste is introduced
		for activity_code, activity in self.bill_of_activities.items():
			activity_cost += ( 	activitytrax[activity_code].cost_per_unit * 
								activity["consumption"] /
								activity["production_ratio"] 
							)
		
	
		return    material_cost , activity_cost 
		
	def PrintCost(self):
	
		material_cost, activity_cost = self.CalculateCost()
		
		total_cost = material_cost + activity_cost
		
		product_str = self.__str__()
		
		cost_str = "Product cost: {:.2f} Material's cost: {:.2f} Activity's cost: {:.2f}".format(total_cost, material_cost, activity_cost)
					
		return  product_str + cost_str + "\n"
		
	def __str__(self):
	
		materials = MaterialTrax().materials
	
		header = ("Product code: " + str(self.code) + "\nProduct name: " + self.name
				  + "\nProduct description: " + self.description + "\n" + "*" * 80 + "\n" )
				  
		material_string = "Code   Material                 Cost  Consumption  Unit       x F.P. units  Waste \n"

		for code, material in self.bill_of_materials.items():
		
			material_string += (
				str(code) + "      " +
				materials[code].name + " " * ( 25 - len(materials[code].name))  +  
				str(materials[code].cost_per_unit) + " " * (6 - len(str(materials[code].cost_per_unit))) +
				str(material["consumption"]) + " " * (13 - len(str(material["consumption"]))) +
				material["consumption_unit"] + " " * (13 - len(material["consumption_unit"])) +
				str(material["production_ratio"]) + " " +
				material["production_unit"] + "        " +
				str(material["waste"]) + "\n"
				)
				
		material_string += "*" * 80 + "\n"
		
		# will it be possible to close the materials variable once finished ? 
		# This way the memory will be emptied
		
		header += material_string	
		
		activities = ActivityTrax().activities
		
		activity_string =  "Code   Activity                Cost  Usage         Unit       x F.P. units  \n"
		
		for code, activity in self.bill_of_activities.items():
		
			activity_string += (
				str(code) + "      " +
				activities[code].name + " " * ( 25 - len(activities[code].name))  +  
				str(activities[code].cost_per_unit) + " " * (6 - len(str(activities[code].cost_per_unit))) +
				str(activity["consumption"]) + " " * (13 - len(str(activity["consumption"]))) +
				activity["activity_unit"] + " " * (13 - len(activity["activity_unit"])) +
				str(activity["production_ratio"]) + " " +
				activity["production_unit"] + "\n"
				)
		
		activity_string += "*" * 80 + "\n"
		
		header += activity_string
				
		return header
示例#13
0
class Taxonomy(SimpleItem):
    implements(ITaxonomy)

    def __init__(self, name, title, default_language):
        super(Taxonomy, self).__init__(self)
        self.data = PersistentDict()
        self.name = name
        self.title = title
        self.default_language = default_language

    def __call__(self, context):
        request = getattr(context, "REQUEST", None)

        current_language = self.getCurrentLanguage(request)
        data = self.data[current_language]
        inverted_data = self.inverted_data[current_language]

        return Vocabulary(self.name, data, inverted_data)

    @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 getCurrentLanguage(self, request):
        try:
            portal_state = getMultiAdapter((self, request),
                                           name=u'plone_portal_state')

            language = portal_state.language().split('-', 1)[0]
        except ComponentLookupError:
            language = ''  # Force to return default language.

        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 registerBehavior(self, **kwargs):
        context = getSite()
        sm = context.getSiteManager()
        new_args = copy(kwargs)

        new_args['name'] = self.name
        new_args['title'] = self.title
        new_args['description'] = kwargs['field_description']

        behavior = TaxonomyBehavior(**new_args)
        sm.registerUtility(behavior, IBehavior, name=self.getGeneratedName())

        behavior.addIndex()
        behavior.activateSearchable()

    def cleanupFTI(self):
        """Cleanup the FTIs"""
        generated_name = self.getGeneratedName()
        context = getSite()
        sm = context.getSiteManager()
        for (name, fti) in 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):
        sm = getSite().getSiteManager()

        behavior_name = self.getGeneratedName()
        short_name = self.getShortName()

        utility = sm.queryUtility(IBehavior, name=behavior_name)
        if utility:
            utility.deactivateSearchable()
            utility.activateSearchable()

        delattr(generated, short_name)

        for (name, fti) in sm.getUtilitiesFor(IDexterityFTI):
            if behavior_name in fti.behaviors:
                modified(fti,
                         DexterityFTIModificationDescription("behaviors", ''))

    def unregisterBehavior(self):
        context = getSite()
        sm = context.getSiteManager()
        behavior_name = self.getGeneratedName()
        utility = sm.queryUtility(IBehavior, name=behavior_name)

        if utility is None:
            return

        self.cleanupFTI()

        utility.removeIndex()
        utility.deactivateSearchable()
        utility.unregisterInterface()

        sm.unregisterUtility(utility, IBehavior, name=behavior_name)

    def clean(self):
        self.data.clear()

    def add(self, language, identifier, path):
        if not language in self.data:
            self.data[language] = OOBTree()

        self.data[language][path] = identifier

    def translate(self,
                  msgid,
                  mapping=None,
                  context=None,
                  target_language=None,
                  default=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 ''

        path = self.inverted_data[target_language][msgid]
        #we may have non-ascii now
        if not isinstance(path, unicode):
            path = path.decode('utf-8')
        pretty_path = path[1:].replace('/', u' » ')

        return pretty_path
示例#14
0
class VideoContainer(PersistentMapping):
    """ A simple container for Video objects
        
        >>> from mint.repoze.interfaces import IVideoContainer
        >>> from mint.repoze.models import VideoContainer, Video
        >>> ob = VideoContainer()
        >>> IVideoContainer.providedBy(ob)
        True
        >>> len(ob)
        0
        >>> ob[u'vid1'] = Video('vid1', 'Video 1', 'description', [])
        >>> len(ob)
        1
        >>> ob.keys()
        [u'vid1']
        
    """
    __acl__ = [
            (Allow, Everyone, 'view'),
            (Allow, 'admin', 'add'),
            (Allow, 'admin', 'edit'),
            ]
    
    implements(IVideoContainer,ILocation)
    
    encode_dir = 'var/videos/'
    
    def __init__(self, *args, **kwargs):
        self.data = PersistentDict()
        for data in args:
            self.add_video(*data)
        for v in kwargs.values():
            pass
    
    def __getitem__(self, key):
        return self.data.__getitem__(key)
    
    def __setitem__(self, key, value):
        return self.data.__setitem__(key, value)
    
    def items(self):
        return self.data.items()
    
    def keys(self):
        return self.data.keys()
    
    def values(self):
        return self.data.values()
    
    def __repr__(self):
        return u'<VideoContainer object>'
    
    def add_video(self, name, description, tags, encodes={}):
        uid = name.lower().replace(' ', '_')
        counter = 1
        while uid in self:
            uid = '%s_%03d' % (uid, counter)
            counter += 1
        self.data[uid] = Video(uid, name, description, tags, encodes, self.encode_dir)
        import transaction
        transaction.commit()
    
    def get_videos_by_tag(self, tag):
        """ Returns a list of video objects with the given tag
            >>> from mint.repoze.test.data import video_container
            >>> video_container.get_videos_by_tag('feature') # doctest: +ELLIPSIS
            [<Video name=...]
        """
        return [video for video in self.data.values() if tag in video.tags]
示例#15
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()
示例#16
0
class BaseContainer(PersistentMapping):
    """ Provides a basis for `container` objects
        >>> container = BaseContainer()
        >>> container[u'foo'] = u'bar'
        >>> container[u'foo']
        u'bar'
        >>> container.items()
        [(u'foo', u'bar')]
        >>> container.keys()
        [u'foo']
        >>> container.values()
        [u'bar']
        
    """
    def __init__(self):
        self.data = PersistentDict()
    
    def __getitem__(self, key):
        return self.data.__getitem__(key)
    
    def __setitem__(self, key, value):
        """ Acts as a proxy to the self.data PersistentDict. As it is a
            persistent object, it will also try and assign the __parent__
            attrubute to any object stored through this interface.
            
            >>> container = BaseContainer()
            >>> container.__setitem__('foo', 'bar')
            >>> 'foo' in container.data
            True
            >>> container['foo'].__parent__ # doctest: +ELLIPSIS
            Traceback (most recent call last):
            ...
            AttributeError: 'str' object has no attribute '__parent__'
            >>> class Child(object):
            ...     __parent__ = None
            ...
            >>> container.__setitem__('baz', Child())
            >>> 'baz' in container.data
            True
            >>> container['baz'].__parent__ == container
            True
        """
        ret = self.data.__setitem__(key, value)
        try: self.data[key].__parent__ = self
        except: pass
        return ret
    
    def items(self):
        return self.data.items()
    
    def keys(self):
        return self.data.keys()
    
    def values(self):
        return self.data.values()
    
    def update(self, _data={}, **kwargs):
        """ BaseContainers can be updated much the same as any Python dictionary.
            
            By passing another mapping object:
            
            >>> container = BaseContainer()
            >>> container.update({'foo':'bar'})
            
            By passing a list of iterables with length 2:
            
            >>> container = BaseContainer()
            >>> container.update([('foo', 'bar'),])
            
            By passing a set of keyword arguments:
            
            >>> container = BaseContainer()
            >>> container.update(foo='bar')
            
        """
        if kwargs:
            for k,v in kwargs.items():
                self.__setitem__(k,v)
            return
        elif isinstance(_data, dict):
            for k,v in _data.items():
                self.__setitem__(k,v)
        elif isinstance(_data, dict):
            for k,v in _data:
                self.__setitem__(k,v)