class Taxonomy(SimpleItem): order = None count = None version = None def __init__(self, name, title, default_language): self.data = PersistentDict() self.order = PersistentDict() self.count = PersistentDict() self.version = PersistentDict() self.name = name self.title = title self.default_language = default_language @property def sm(self): return api.portal.get().getSiteManager() def __call__(self, context): if not self.data: return Vocabulary(self.name, {}, {}, {}, 2) request = getattr(context, "REQUEST", None) language = self.getCurrentLanguage(request) return self.makeVocabulary(language) @property @ram.cache(lambda method, self: (self.name, self.data._p_mtime)) def inverted_data(self): inv_data = {} for (language, elements) in self.data.items(): inv_data[language] = {} for (path, identifier) in elements.items(): inv_data[language][identifier] = path return inv_data def getShortName(self): return self.name.split('.')[-1] def getGeneratedName(self): return 'collective.taxonomy.generated.' + self.getShortName() def getVocabularyName(self): return 'collective.taxonomy.' + self.getShortName() def makeVocabulary(self, language): self._fixup() data = self.data.get(language, {}) order = self.order.get(language) version = self.version.get(language, 1) inverted_data = self.inverted_data.get(language, {}) return Vocabulary(self.name, data, inverted_data, order, version) def getCurrentLanguage(self, request): language = get_lang_code() if language in self.data: return language elif self.default_language in self.data: return self.default_language else: # our best guess! return self.data.keys()[0] def getLanguages(self): return tuple(self.data) def iterLanguage(self, language=None): if language is None: language = self.default_language vocabulary = self.makeVocabulary(language) for path, identifier in vocabulary.iterEntries(): parent_path = path.rsplit(PATH_SEPARATOR, 1)[0] if parent_path: parent = vocabulary.getTermByValue(parent_path) else: parent = None yield path, identifier, parent def registerBehavior(self, **kwargs): new_args = copy(kwargs) new_args['name'] = self.getGeneratedName() new_args['title'] = self.title new_args['description'] = kwargs.get('field_description', u'') new_args['field_description'] = new_args['description'] behavior = TaxonomyBehavior(**new_args) self.sm.registerUtility(behavior, IBehavior, name=self.getGeneratedName()) behavior.addIndex() behavior.activateSearchable() def cleanupFTI(self): """Cleanup the FTIs""" generated_name = self.getGeneratedName() for (name, fti) in self.sm.getUtilitiesFor(IDexterityFTI): if generated_name in fti.behaviors: fti.behaviors = [behavior for behavior in fti.behaviors if behavior != generated_name] modified(fti, DexterityFTIModificationDescription("behaviors", '')) def updateBehavior(self, **kwargs): behavior_name = self.getGeneratedName() short_name = self.getShortName() utility = self.sm.queryUtility(IBehavior, name=behavior_name) if utility: utility.deactivateSearchable() utility.activateSearchable() if 'field_title' in kwargs: utility.title = kwargs.pop('field_title') for k, v in kwargs.items(): setattr(utility, k, v) delattr(generated, short_name) for (name, fti) in self.sm.getUtilitiesFor(IDexterityFTI): if behavior_name in fti.behaviors: modified(fti, DexterityFTIModificationDescription("behaviors", '')) def unregisterBehavior(self): behavior_name = self.getGeneratedName() utility = self.sm.queryUtility(IBehavior, name=behavior_name) if utility is None: return self.cleanupFTI() utility.removeIndex() utility.deactivateSearchable() utility.unregisterInterface() self.sm.unregisterUtility(utility, IBehavior, name=behavior_name) def clean(self): self.data.clear() def add(self, language, value, key): self._fixup() tree = self.data.get(language) if tree is None: tree = self.data[language] = OOBTree() else: # Make sure we update the modification time. self.data[language] = tree update = key in tree tree[key] = value order = self.order.get(language) if order is None: order = self.order[language] = IOBTree() count = self.count[language] = 0 else: if update: pop_value(tree, key) count = self.count[language] + 1 self.count[language] = count order[count] = key def update(self, language, items, clear=False): self._fixup() tree = self.data.setdefault(language, OOBTree()) if clear: tree.clear() # A new tree always uses the newest version. if not tree: version = self.version[language] = 2 else: version = self.version.get(language, 1) order = self.order.setdefault(language, IOBTree()) count = self.count.get(language, 0) if clear: order.clear() count = 0 # Always migrate to newest version. if version == 1: def fix(path): return path.replace(LEGACY_PATH_SEPARATOR, PATH_SEPARATOR) for i in list(order): path = order[i] order[i] = fix(path) for path in list(tree): value = tree.pop(path) tree[fix(path)] = value version = self.version[language] = 2 logger.info( "Taxonomy '%s' upgraded to version %d for language '%s'." % ( self.name, version, language ) ) # Make sure we update the modification time. self.data[language] = tree # The following structure is used to expunge updated entries. inv = {} if not clear: for i, key in order.items(): inv[key] = i seen = set() for key, value in items: if key in seen: logger.warning("Duplicate key entry: %r" % (key, )) continue seen.add(key) update = key in tree tree[key] = value order[count] = key count += 1 # If we're updating, then we have to pop out the old ordering # information in order to maintain relative ordering of new items. if update: i = inv.get(key) if i is not None: del order[i] self.count[language] = count def translate(self, msgid, mapping=None, context=None, target_language=None, default=None, msgid_plural=None, default_plural=None, number=None): if target_language is None or \ target_language not in self.inverted_data: target_language = str(api.portal.get_current_language()) if msgid not in self.inverted_data[target_language]: return '' if self.version is not None and self.version.get(target_language) != 2: path_sep = LEGACY_PATH_SEPARATOR else: path_sep = PATH_SEPARATOR path = self.inverted_data[target_language][msgid] pretty_path = path[1:].replace(path_sep, PRETTY_PATH_SEPARATOR) if mapping is not None and mapping.get(NODE): pretty_path = pretty_path.rsplit(PRETTY_PATH_SEPARATOR, 1)[-1] return pretty_path def _fixup(self): # due to compatibility reasons this method fixes data structure # for old Taxonomy instances. # XXX: remove this in version 2.0 to prevent write on read if self.order is None: safeWrite(self, getRequest()) self.order = PersistentDict() self.count = PersistentDict() if self.version is None: safeWrite(self, getRequest()) self.version = PersistentDict()
class 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
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
class ShibbolethPermissions(BasePlugin): """Extend folder_localrole_form to grant permissions to Shibboleth users. Most testing is done in tests/ShibbolethPermissions.txt.""" security = ClassSecurityInfo() def __init__(self, pluginId, title=None): self.id = pluginId self.title = title self.localRoles = PersistentDict() self.retest = re.compile(' ') config = ((httpSharingTokensKey, 'lines', 'w', []), (httpSharingLabelsKey, 'lines', 'w', [])) # Create any missing properties ids = {} for prop in config: # keep track of property names for quick lookup ids[prop[0]] = True if prop[0] not in self.propertyIds(): self.manage_addProperty(id=prop[0], type=prop[1], value=prop[3]) self._properties[-1]['mode'] = prop[2] # Delete any existing properties that aren't in config ids.update({'prefix':'', 'title':''}) for prop in self._properties: if prop['id'] not in ids: self.manage_delProperties(prop['id']) security.declarePublic('getSharingConfig') def getSharingConfig(self): """Return the items end users can use to share with. Verify it returns an empty configuration. >>> from Products.ShibbolethPermissions.permissions import ShibbolethPermissions >>> handler = ShibbolethPermissions() >>> handler.getSharingConfig() {'http_sharing_tokens': (), 'http_sharing_labels': ()} """ if IS_AUMPAS_INSTALLED: autoUserMaker = getToolByName(self, 'AutoUserMakerPASPlugin', None) if autoUserMaker is not None: return autoUserMaker.getSharingConfig() return {httpSharingTokensKey: self.getProperty(httpSharingTokensKey), httpSharingLabelsKey: self.getProperty(httpSharingLabelsKey)} security.declarePrivate('getShibValues') def getShibValues(self): config = self.getSharingConfig() request = getattr(self, 'REQUEST') req_environ = getattr(request, 'environ', {}) return dict([(ii, req_environ.get(ii)) for ii in config[httpSharingTokensKey] if ii in req_environ]) security.declarePublic('getLocalRoles') def getLocalRoles(self, path=None, **params): """Return the self.localRoles as a dictionary or list. Return a dictionay if neither path nor params is set (whole dictionary of lists of dictionaries). Return a dictionary if params is set, but path is not (subset of the whole dictionary of lists of dictionaries). Return a list of dictionaries when path is set, which may be an empty list if the path is not found or params is given in addition to path and none of the params match. This simple test returns everything, which at this point is nothing. """ roles = {} param_keys = params.keys().sort() for ii in self.localRoles.iterkeys(): roles[ii] = list(self.localRoles[ii]) if not path and not params: return roles # no select given, so return everything if path: if not path in roles: return [] # path not found, so return nothing if not params: # path found, but no subcriteria so return whole list return roles[path] return _searchParams(roles[path], param_keys, **params) # no path, but params, so return a path keyed dict of lists of dicts rval = {} for ii in roles.iterkeys(): # each key is a Plone path found = _searchParams(roles[ii], param_keys, **params) if found: # Don't save empty lists rval[ii] = found return rval security.declarePublic('addLocalRoles') def addLocalRoles(self, path, params, roles): """Add a pattern for path of params.""" params['_roles'] = roles if path in self.localRoles: self.localRoles[path].append(params) else: self.localRoles[path] = PersistentList([params,]) security.declarePublic('delLocalRoles') def delLocalRoles(self, path=None, row=None): """ Delete the specified roles. """ if path is None and row is None: self.localRoles.clear() elif path in self.localRoles: if row is not None: del self.localRoles[path][row] else: del self.localRoles[path] security.declarePublic('updLocalRoles') def updLocalRoles(self, path=None, row=None, roles=None): """ Update the specified roles. """ if roles is None: roles = [] if path and path in self.localRoles and row is not None: try: self.localRoles[path][row]['_roles'] = roles except (IndexError, TypeError): logger.warning("updLocalRoles error updating row %s from %s" % (str(row), str(path)), exc_info=True) def _findroles(self, context): uservals = self.getShibValues() regexs = self.getLocalRoles().get('/'.join(context.getPhysicalPath()), None) if regexs is None: return [] for ii in regexs: # Make sure the incoming user has all of the # needed attributes for name in ii.iterkeys(): if name == '_roles': continue if not name in uservals: break else: for name, pattern in ii.iteritems(): if name == '_roles' or uservals[name] is None: continue try: regex = re.compile(pattern) if not regex.search(uservals[name]): break except (ConflictError, KeyboardInterrupt): raise except Exception: break else: return list(ii['_roles']) return [] def refreshlocalroles(self, user=None): if user is None: userid = _getAuthenticatedUser(None).getId() else: userid = user.getId() if not userid: return for path in self.localRoles.iterkeys(): obj = self.unrestrictedTraverse(path, None) if obj is not None: roles = self._findroles(obj) reindex = False current_localroles = obj.get_local_roles_for_userid(userid) if not roles and current_localroles: obj.manage_delLocalRoles((userid,)) reindex = True elif tuple(roles) != current_localroles: obj.manage_setLocalRoles(userid, roles) reindex = True if reindex: obj.reindexObjectSecurity()
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
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()