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()
class CatalogBlacklist(UniqueObject, SimpleItem): implements(ICatalogBlacklist) id = 'portal_catalogblacklist' meta_type = 'Catalog Blacklist Tool' security = ClassSecurityInfo() def __init__(self, id=None): self._blacklisted_types = PersistentDict() self._blacklisted_interfaces = PersistentDict() security.declarePrivate('extend') def extend(self, blacklisted_types=None, blacklisted_interfaces=None): """ extend the blacklisted indexes for the given types or interfaces """ if blacklisted_types is not None: for pt, indexnames in blacklisted_types.items(): self._blacklisted_types.setdefault(pt, []) for name in indexnames: if name not in self._blacklisted_types[pt]: self._blacklisted_types[pt].append(name) self._blacklisted_types._p_changed = 1 if blacklisted_interfaces is not None: for iface, indexnames in blacklisted_interfaces.items(): if isinstance(iface, StringTypes): iface = resolve(iface) self._blacklisted_interfaces.setdefault(iface, []) for name in indexnames: if name not in self._blacklisted_interfaces[iface]: self._blacklisted_interfaces[iface].append(name) self._blacklisted_interfaces._p_changed = 1 security.declarePrivate('getBlackListedIndexesForObject') def getBlackListedIndexesForObject(self, object): """ return blacklisted indexes for object """ portal_type = getattr(object, 'portal_type', None) blacklisted = [] for indexname in self._blacklisted_types.get(portal_type, []): blacklisted.append(indexname) # Inspect the interfaces for iface, indexes in \ self._blacklisted_interfaces.items(): if iface.providedBy(object): for indexname in indexes: if indexname not in blacklisted: blacklisted.append(indexname) return blacklisted
class 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 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
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 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
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): 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 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)
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
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 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]
class Taxonomy(SimpleItem): order = None count = None version = None def __init__(self, name, title, default_language): self.data = PersistentDict() self.order = PersistentDict() self.count = PersistentDict() self.version = PersistentDict() self.name = name self.title = title self.default_language = default_language @property def sm(self): return api.portal.get().getSiteManager() def __call__(self, context): if not self.data: return Vocabulary(self.name, {}, {}, {}, 2) request = getattr(context, "REQUEST", None) language = self.getCurrentLanguage(request) return self.makeVocabulary(language) @property @ram.cache(lambda method, self: (self.name, self.data._p_mtime)) def inverted_data(self): inv_data = {} for (language, elements) in self.data.items(): inv_data[language] = {} for (path, identifier) in elements.items(): inv_data[language][identifier] = path return inv_data def getShortName(self): return self.name.split('.')[-1] def getGeneratedName(self): return 'collective.taxonomy.generated.' + self.getShortName() def getVocabularyName(self): return 'collective.taxonomy.' + self.getShortName() def makeVocabulary(self, language): self._fixup() data = self.data.get(language, {}) order = self.order.get(language) version = self.version.get(language, 1) inverted_data = self.inverted_data.get(language, {}) return Vocabulary(self.name, data, inverted_data, order, version) def getCurrentLanguage(self, request): language = get_lang_code() if language in self.data: return language elif self.default_language in self.data: return self.default_language else: # our best guess! return self.data.keys()[0] def getLanguages(self): return tuple(self.data) def iterLanguage(self, language=None): if language is None: language = self.default_language vocabulary = self.makeVocabulary(language) for path, identifier in vocabulary.iterEntries(): parent_path = path.rsplit(PATH_SEPARATOR, 1)[0] if parent_path: parent = vocabulary.getTermByValue(parent_path) else: parent = None yield path, identifier, parent def registerBehavior(self, **kwargs): new_args = copy(kwargs) new_args['name'] = self.getGeneratedName() new_args['title'] = self.title new_args['description'] = kwargs.get('field_description', u'') new_args['field_description'] = new_args['description'] behavior = TaxonomyBehavior(**new_args) self.sm.registerUtility(behavior, IBehavior, name=self.getGeneratedName()) behavior.addIndex() behavior.activateSearchable() def cleanupFTI(self): """Cleanup the FTIs""" generated_name = self.getGeneratedName() for (name, fti) in self.sm.getUtilitiesFor(IDexterityFTI): if generated_name in fti.behaviors: fti.behaviors = [behavior for behavior in fti.behaviors if behavior != generated_name] modified(fti, DexterityFTIModificationDescription("behaviors", '')) def updateBehavior(self, **kwargs): behavior_name = self.getGeneratedName() short_name = self.getShortName() utility = self.sm.queryUtility(IBehavior, name=behavior_name) if utility: utility.deactivateSearchable() utility.activateSearchable() if 'field_title' in kwargs: utility.title = kwargs.pop('field_title') for k, v in kwargs.items(): setattr(utility, k, v) delattr(generated, short_name) for (name, fti) in self.sm.getUtilitiesFor(IDexterityFTI): if behavior_name in fti.behaviors: modified(fti, DexterityFTIModificationDescription("behaviors", '')) def unregisterBehavior(self): behavior_name = self.getGeneratedName() utility = self.sm.queryUtility(IBehavior, name=behavior_name) if utility is None: return self.cleanupFTI() utility.removeIndex() utility.deactivateSearchable() utility.unregisterInterface() self.sm.unregisterUtility(utility, IBehavior, name=behavior_name) def clean(self): self.data.clear() def add(self, language, value, key): self._fixup() tree = self.data.get(language) if tree is None: tree = self.data[language] = OOBTree() else: # Make sure we update the modification time. self.data[language] = tree update = key in tree tree[key] = value order = self.order.get(language) if order is None: order = self.order[language] = IOBTree() count = self.count[language] = 0 else: if update: pop_value(tree, key) count = self.count[language] + 1 self.count[language] = count order[count] = key def update(self, language, items, clear=False): self._fixup() tree = self.data.setdefault(language, OOBTree()) if clear: tree.clear() # A new tree always uses the newest version. if not tree: version = self.version[language] = 2 else: version = self.version.get(language, 1) order = self.order.setdefault(language, IOBTree()) count = self.count.get(language, 0) if clear: order.clear() count = 0 # Always migrate to newest version. if version == 1: def fix(path): return path.replace(LEGACY_PATH_SEPARATOR, PATH_SEPARATOR) for i in list(order): path = order[i] order[i] = fix(path) for path in list(tree): value = tree.pop(path) tree[fix(path)] = value version = self.version[language] = 2 logger.info( "Taxonomy '%s' upgraded to version %d for language '%s'." % ( self.name, version, language ) ) # Make sure we update the modification time. self.data[language] = tree # The following structure is used to expunge updated entries. inv = {} if not clear: for i, key in order.items(): inv[key] = i seen = set() for key, value in items: if key in seen: logger.warning("Duplicate key entry: %r" % (key, )) seen.add(key) update = key in tree tree[key] = value order[count] = key count += 1 # If we're updating, then we have to pop out the old ordering # information in order to maintain relative ordering of new items. if update: i = inv.get(key) if i is not None: del order[i] self.count[language] = count def translate(self, msgid, mapping=None, context=None, target_language=None, default=None, msgid_plural=None, default_plural=None, number=None): if target_language is None or \ target_language not in self.inverted_data: target_language = str(self.getCurrentLanguage( getattr(context, 'REQUEST') )) if msgid not in self.inverted_data[target_language]: return '' if self.version is not None and self.version.get(target_language) != 2: path_sep = LEGACY_PATH_SEPARATOR else: path_sep = PATH_SEPARATOR path = self.inverted_data[target_language][msgid] pretty_path = path[1:].replace(path_sep, PRETTY_PATH_SEPARATOR) if mapping is not None and mapping.get(NODE): pretty_path = pretty_path.rsplit(PRETTY_PATH_SEPARATOR, 1)[-1] return pretty_path def _fixup(self): # due to compatibility reasons this method fixes data structure # for old Taxonomy instances. # XXX: remove this in version 2.0 to prevent write on read if self.order is None: safeWrite(self, getRequest()) self.order = PersistentDict() self.count = PersistentDict() if self.version is None: safeWrite(self, getRequest()) self.version = PersistentDict()
class 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)