def getArray(self, default=None): """ Get numpy view of Parent Data Array according to index. """ getindex = GetIndex("getindex") index = evaluateExpressionFromString( createExpressionContext(None, portal=getindex), "python: portal[%s]" % self.getIndexExpression()) zbigarray = self.getParentValue().getArray() try: array_view = zbigarray[index] except TypeError: array = zbigarray[:] new_dtype = np.dtype( {name: array.dtype.fields[name] for name in index}) array_view = np.ndarray(array.shape, new_dtype, array, 0, array.strides) name_list = self.getNameList() dtype_expression = self.getDtypeExpression() if dtype_expression is not None or name_list: if dtype_expression is None: dtype = np.dtype(array_view.dtype) else: dtype = evaluateExpressionFromString( createExpressionContext(None, portal=getindex), dtype_expression) dtype.names = name_list return array_view.view(dtype=dtype) return array_view
def getDefaultViewFor(self, ob, view='view'): """Return the object that renders the default view for the given object """ ec = createExpressionContext(ob) other_action = None for action in self.getActionList(): if action['id'] == view or (action['category'] is not None and action['category'].endswith('_' + view)): if action.test(ec): break elif other_action is None: # In case that "view" (or "list") action is not present or not allowed, # find something that's allowed (of the same category, if possible). if action.test(ec): other_action = action else: action = other_action if action is None: raise AccessControl_Unauthorized( 'No accessible views available for %r' % ob.getPath()) target = action.cook(ec)['url'].strip().split(ec.vars['object_url'])[-1] if target.startswith('/'): target = target[1:] __traceback_info__ = self.getId(), target return ob.restrictedTraverse(target)
def _checkConsistency(self, obj, fixit=0): """Check the object's consistency. We will make sure that each non None constraint_definition is satisfied (unicity) This Constraint use portal_catalog """ errors = PropertyExistence._checkConsistency(self, obj, fixit=fixit) for attribute_name, expression_criterion_dict in self.constraint_definition.items(): message_id = None mapping = dict(attribute_name=attribute_name) #Evaluate expression_criterion_dict expression = Expression(expression_criterion_dict) from Products.ERP5Type.Utils import createExpressionContext econtext = createExpressionContext(obj) criterion_dict = expression(econtext) from Products.ZSQLCatalog.SQLCatalog import Query, NegatedQuery # Add uid in criterion keys to avoid fetching current object. criterion_dict['query'] = NegatedQuery(Query(uid=obj.getUid())) portal = obj.getPortalObject() result = portal.portal_catalog.countResults(**criterion_dict)[0][0] if result >= 1: mapping['value'] = criterion_dict.get(attribute_name) message_id = 'message_invalid_attribute_unicity' # Generate error if message_id is not None: errors.append(self._generateError(obj, self._getMessage(message_id), mapping)) return errors
def getDefaultViewFor(self, ob, view='view'): """Return the object that renders the default view for the given object """ ec = createExpressionContext(ob) other_action = None for action in self.getActionList(): if action['id'] == view or (action['category'] is not None and action['category'].endswith('_' + view)): if action.test(ec): break elif other_action is None: # In case that "view" (or "list") action is not present or not allowed, # find something that's allowed (of the same category, if possible). if action.test(ec): other_action = action else: action = other_action if action is None: raise AccessControl_Unauthorized( 'No accessible views available for %r' % ob.getPath()) target = action.cook(ec)['url'].strip().split( ec.vars['object_url'])[-1] if target.startswith('/'): target = target[1:] __traceback_info__ = self.getId(), target return ob.restrictedTraverse(target)
def _checkConsistency(self, obj, fixit=0): """Check the object's consistency. We will make sure that each non None constraint_definition is satisfied (unicity) This Constraint use portal_catalog """ error_list = PropertyExistenceConstraint._checkConsistency(self, obj, fixit=fixit) attribute_name = self.getConstraintProperty() expression_criterion_dict = self.getFilterParameter() message_id = None mapping = dict(attribute_name=attribute_name) #Evaluate expression_criterion_dict expression = Expression(expression_criterion_dict) econtext = createExpressionContext(obj) criterion_dict = expression(econtext) # Add uid in criterion keys to avoid fetching current object. criterion_dict['query'] = NegatedQuery(Query(uid=obj.getUid())) portal = obj.getPortalObject() result = portal.portal_catalog.countResults(**criterion_dict)[0][0] if result >= 1: mapping['value'] = criterion_dict.get(attribute_name) message_id = 'message_invalid_attribute_unicity' # Generate error if message_id is not None: error_list.append(self._generateError(obj, self._getMessage(message_id), mapping)) return error_list
def asDict(self, expression_context=None): """ Convert the current property to a dict, which is then applied on the accessor holder. @param expression_context: Expression context for TALES Expression @type expression_context: Products.PageTemplates.Expressions.ZopeContext @return: The current property as a dict @rtype: dict """ # If no expression context has been given, create one, meaningful # when being called from the browser for example if expression_context is None: expression_context = createExpressionContext( self.getPortalObject()) property_default = evaluateExpressionFromString( expression_context, self.getPropertyDefault()) return { 'reference': self.getReference(), 'description': self.getDescription(), 'elementary_type': self.getElementaryType(), 'storage_id': self.getStorageId(), 'multivalued': self.getMultivalued(), 'property_default': property_default, 'range': self.getRange(), 'preference': self.getPreference(), 'read_permission': self.getReadPermission(), 'write_permission': self.getWritePermission(), 'translatable': self.getTranslatable(), 'translation_domain': self.getTranslationDomain(), 'select_variable': self.getSelectVariable() }
def _checkConsistency(self, obj, fixit=0): """Check the object's consistency. """ # import this later to prevent circular import from Products.ERP5Type.Utils import createExpressionContext error_list = [] expression_text = self.constraint_definition['expression'] expression = Expression(expression_text) econtext = createExpressionContext(obj) try: if not expression(econtext): error_list.append( self._generateError( obj, self._getMessage('message_expression_false'))) except (ConflictError, CompilerError): raise except Exception, e: LOG('ERP5Type', PROBLEM, 'TALESConstraint error on "%s" on %s' % (self.constraint_definition['expression'], obj), error=sys.exc_info()) error_list.append( self._generateError( obj, self._getMessage('message_expression_error'), mapping=dict(error_text=str(e))))
def asDict(self, expression_context=None): """ Convert the current property to a dict, which is then applied on the accessor holder. @param expression_context: Expression context for TALES Expression @type expression_context: Products.PageTemplates.Expressions.ZopeContext @return: The current property as a dict @rtype: dict """ # If no expression context has been given, create one, meaningful # when being called from the browser for example if expression_context is None: expression_context = createExpressionContext(self.getPortalObject()) property_default = evaluateExpressionFromString(expression_context, self.getPropertyDefault()) return {'reference': self.getReference(), 'description': self.getDescription(), 'elementary_type': self.getElementaryType(), 'storage_id': self.getStorageId(), 'multivalued': self.getMultivalued(), 'property_default': property_default, 'range': self.getRange(), 'preference': self.getPreference(), 'read_permission': self.getReadPermission(), 'write_permission': self.getWritePermission(), 'translatable': self.getTranslatable(), 'translation_domain': self.getTranslationDomain()}
def _getExpressionValue(self, obj, expression_string): """ Get the Python value from an Expression string, but check before whether it is None as a getter may returns the default value which could be None """ if expression_string is None: return None return Expression(expression_string)(createExpressionContext(obj))
def listFilteredActionsFor(self, object=None): """ List all actions available to the user. This patch removes inclusion of actions from the object itself. It was never used and now, it breaks objects inside Types Tool. It also checks for a new ERP5-only actions API (getActionListFor), but this API should be moved to listActionInfos() of each tool so as not to create duplicate code paths that are sources of bugs. Finally, this patch detects tools that are no longer action providers and invokes the migration of their actions to portal_actions """ actions = [] # Include actions from specific tools. for provider_name in self.listActionProviders(): provider = getattr(self, provider_name) if hasattr(provider, 'getActionListFor'): from Products.ERP5Type.Utils import createExpressionContext ec = createExpressionContext(object) actions.extend(action.cook(ec) for action in provider.getActionListFor(object) if action.test(ec)) elif IActionProvider_providedBy(provider): actions.extend( provider.listActionInfos(object=object) ) elif getattr(provider, '_listActionInfos', None) is not None: # BACK: drop this clause and the 'else' clause below when we # drop CMF 1.5 # for Action Providers written for CMF versions before 1.5 actions.extend( self._listActionInfos(provider, object) ) else: # This should only be triggered once # We're in 2.12 and we need to migrate objects that are no longer # IActionProviders: migrateNonProviders(self) # Recompute from beginning return self.listFilteredActionsFor(object=object) actions.sort(key=lambda x:x.get('priority', 0)) # Reorganize the actions by category. filtered_actions={'user':[], 'folder':[], 'object':[], 'global':[], 'workflow':[], } for action in actions: filtered_actions.setdefault(action['category'], []).append(action) return filtered_actions
def PropertyManager_getProperty(self, id, d=None, evaluate=1, local_properties=False): """Get the property 'id', returning the optional second argument or None if no such property is found.""" property_type = self.getPropertyType(id, local_properties=local_properties) if evaluate and property_type == 'tales': value = getattr(self, id) expression = Expression(value) econtext = createExpressionContext(self) return expression(econtext) elif property_type: return getattr(self, id, d) return d
def _checkConstraintCondition(self, obj): """ method that will check if the TALES condition is true. It should be called by checkConsistency, which should ignore constraints if TALES is False """ from Products.ERP5Type.Utils import createExpressionContext condition = getattr(self, 'condition', None) if condition not in (None, ''): expression = Expression(condition) econtext = createExpressionContext(obj) if not expression(econtext): return 0 # a condition was defined and is False return 1 # no condition or a True condition was defined
def getFilteredRoleListFor(self, ob=None): """Return all role generators applicable to the object.""" ec = None # createExpressionContext is slow so we call it only if needed for role in self.getRoleInformationList(): if ec is None: ec = createExpressionContext(ob) if role.testCondition(ec): yield role # Return also explicit local roles defined as subobjects of the document if getattr(aq_base(ob), "isPrincipiaFolderish", 0) and self.allowType("Role Definition"): for role in ob.objectValues(spec="ERP5 Role Definition"): if role.getRoleName(): yield role
def getFilteredRoleListFor(self, ob=None): """Return all role generators applicable to the object.""" ec = None # createExpressionContext is slow so we call it only if needed for role in self.getRoleInformationList(): if ec is None: ec = createExpressionContext(ob) if role.testCondition(ec): yield role # Return also explicit local roles defined as subobjects of the document if getattr(aq_base(ob), 'isPrincipiaFolderish', 0) and \ self.allowType('Role Definition'): for role in ob.objectValues(spec='ERP5 Role Definition'): if role.getRoleName(): yield role
def listFilteredActionsFor(self, object=None): """ List all actions available to the user. This patch removes inclusion of actions from the object itself. It was never used and now, it breaks objects inside Types Tool. It also checks for a new ERP5-only actions API (getActionListFor), but this API should be moved to listActionInfos() of each tool so as not to create duplicate code paths that are sources of bugs. Finally, this patch detects tools that are no longer action providers and invokes the migration of their actions to portal_actions """ actions = [] # Include actions from specific tools. for provider_name in self.listActionProviders(): provider = getattr(self, provider_name) if hasattr(provider, 'getActionListFor'): from Products.ERP5Type.Utils import createExpressionContext ec = createExpressionContext(object) actions.extend( action.cook(ec) for action in provider.getActionListFor(object) if action.test(ec)) elif IActionProvider.providedBy(provider): actions.extend(provider.listActionInfos(object=object)) else: # This should only be triggered once # We're in 2.12 and we need to migrate objects that are no longer # IActionProviders: migrateNonProviders(self) # Recompute from beginning return self.listFilteredActionsFor(object=object) actions.sort(key=lambda x: x.get('priority', 0)) # Reorganize the actions by category. filtered_actions = { 'user': [], 'folder': [], 'object': [], 'global': [], 'workflow': [], } for action in actions: filtered_actions.setdefault(action['category'], []).append(action) return filtered_actions
def getArray(self, default=None): """ Get numpy view of Parent Data Array according to index. """ getindex = GetIndex("getindex") expression_context = createExpressionContext(None, portal=getindex) index = evaluateExpressionFromString( expression_context, "python: portal[%s]" %self.getIndexExpression() ) array_view = self.getParentValue().getArray()[index] dtype = self.getDtype() if dtype is not None: return array_view.view(dtype=dtype) else: return array_view
def _checkConsistency(self, obj, fixit=0): """Check the object's consistency. """ # import this later to prevent circular import from Products.ERP5Type.Utils import createExpressionContext error_list = [] expression_text = self.constraint_definition['expression'] expression = Expression(expression_text) econtext = createExpressionContext(obj) try: if not expression(econtext): error_list.append(self._generateError(obj, self._getMessage('message_expression_false'))) except (ConflictError, CompilerError): raise except Exception, e: LOG('ERP5Type', PROBLEM, 'TALESConstraint error on "%s" on %s' % (self.constraint_definition['expression'], obj), error=sys.exc_info()) error_list.append(self._generateError(obj, self._getMessage('message_expression_error'), mapping=dict(error_text=str(e))))
def _checkConsistency(self, obj, fixit=0): """Check the object's consistency. """ error_list = [] base_category = self.getBaseCategory() workflow_variable = self.getWorkflowVariable() expression_context = createExpressionContext(obj) portal_type_list_expression = self.getMembershipPortalTypeList() workflow_state_list_expression = self.getWorkflowStateList() portal_type_list = evaluateExpressionFromString( expression_context, portal_type_list_expression) workflow_state_list = evaluateExpressionFromString( expression_context, workflow_state_list_expression) membership_list = self._getObjectCategoryMembershipList( obj, base_category, portal_type_list) for membership in membership_list: current_state = membership.getProperty(workflow_variable) if current_state not in workflow_state_list: mapping = dict( workflow_variable=workflow_variable, membership_url=membership.getRelativeUrl(), membership_title=membership.getTitle(), current_state=current_state, workflow_state_list=str(workflow_state_list), ) if getattr(membership, 'getReference', None) is not None: mapping['membership_reference'] = membership.getReference() message_id = 'message_different_state' error_list.append( self._generateError(obj, self._getMessage(message_id), mapping=mapping)) return error_list
def _checkConsistency(self, obj, fixit=0): """Check the object's consistency. We will make sure that each non None constraint_definition is satisfied """ errors = PropertyExistence._checkConsistency(self, obj, fixit=fixit) for attribute_name, expression_blacklisted_list in self.constraint_definition.items(): message_id = None mapping = dict(attribute_name=attribute_name) # Evaluate expression_criterion_dict expression = Expression(expression_blacklisted_list) from Products.ERP5Type.Utils import createExpressionContext econtext = createExpressionContext(obj) blacklisted_list = expression(econtext) value = obj.getProperty(attribute_name) if value in blacklisted_list: message_id = "message_invalid_attribute_blacklisted" # Generate error if message_id is not None: errors.append(self._generateError(obj, self._getMessage(message_id), mapping)) return errors
def getAccessorHolderList(site, portal_type_name, property_sheet_value_list): import erp5.accessor_holder accessor_holder_list = [] expression_context = None for property_sheet in property_sheet_value_list: # LOG("ERP5Type.dynamic", INFO, # "Getting accessor holder for " + property_sheet_name) property_sheet_name = property_sheet.getId() if property_sheet.isTempObject(): accessor_holder_module = getattr(erp5.accessor_holder.portal_type, portal_type_name) else: accessor_holder_module = erp5.accessor_holder.property_sheet try: accessor_holder_list.append( getattr(accessor_holder_module, property_sheet_name)) except AttributeError: # lazily create the context, only if needed. if expression_context is None: expression_context = createExpressionContext(site) # Generate the accessor holder as it has not been done yet accessor_holder_class = property_sheet.createAccessorHolder( expression_context, site) accessor_holder_module.registerAccessorHolder( accessor_holder_class) accessor_holder_list.append(accessor_holder_class) # LOG("ERP5Type.dynamic", INFO, # "Created accessor holder for %s" % property_sheet_name) return accessor_holder_list
def _checkConsistency(self, obj, fixit=0): """Check the object's consistency. We will make sure that each non None constraint_definition is satisfied """ error_list = PropertyExistenceConstraint._checkConsistency( self, obj, fixit=fixit) blacklisted_list_expression = self.getBlacklistedList() expression_context = createExpressionContext(obj) blacklisted_list = evaluateExpressionFromString(expression_context, blacklisted_list_expression) message_id = 'message_invalid_attribute_blacklisted' for property_id in self.getConstraintPropertyList(): value = obj.getProperty(property_id) if value in blacklisted_list: mapping = dict(attribute_name=property_id) # Generate error error_list.append(self._generateError(obj, self._getMessage(message_id), mapping=mapping) ) return error_list
def getAccessorHolderList(site, portal_type_name, property_sheet_value_list): import erp5.accessor_holder accessor_holder_list = [] expression_context = None for property_sheet in property_sheet_value_list: # LOG("ERP5Type.dynamic", INFO, # "Getting accessor holder for " + property_sheet_name) property_sheet_name = property_sheet.getId() if property_sheet.isTempObject(): accessor_holder_module = getattr(erp5.accessor_holder.portal_type, portal_type_name) else: accessor_holder_module = erp5.accessor_holder.property_sheet try: accessor_holder_list.append(getattr(accessor_holder_module, property_sheet_name)) except AttributeError: # lazily create the context, only if needed. if expression_context is None: expression_context = createExpressionContext(site) # Generate the accessor holder as it has not been done yet accessor_holder_class = property_sheet.createAccessorHolder( expression_context, site) accessor_holder_module.registerAccessorHolder(accessor_holder_class) accessor_holder_list.append(accessor_holder_class) # LOG("ERP5Type.dynamic", INFO, # "Created accessor holder for %s" % property_sheet_name) return accessor_holder_list
def _checkConsistency(self, obj, fixit=0): """Check the object's consistency. We will make sure that each non None constraint_definition is satisfied """ errors = PropertyExistence._checkConsistency(self, obj, fixit=fixit) for attribute_name, expression_blacklisted_list in self.constraint_definition.items( ): message_id = None mapping = dict(attribute_name=attribute_name) #Evaluate expression_criterion_dict expression = Expression(expression_blacklisted_list) from Products.ERP5Type.Utils import createExpressionContext econtext = createExpressionContext(obj) blacklisted_list = expression(econtext) value = obj.getProperty(attribute_name) if value in blacklisted_list: message_id = 'message_invalid_attribute_blacklisted' # Generate error if message_id is not None: errors.append( self._generateError(obj, self._getMessage(message_id), mapping)) return errors
def _checkConsistency(self, obj, fixit=0): """Check the object's consistency. """ error_list = [] base_category = self.getBaseCategory() workflow_variable = self.getWorkflowVariable() expression_context = createExpressionContext(obj) portal_type_list_expression = self.getMembershipPortalTypeList() workflow_state_list_expression = self.getWorkflowStateList() portal_type_list = evaluateExpressionFromString(expression_context, portal_type_list_expression) workflow_state_list = evaluateExpressionFromString(expression_context, workflow_state_list_expression) membership_list = self._getObjectCategoryMembershipList(obj, base_category, portal_type_list) for membership in membership_list: current_state = membership.getProperty(workflow_variable) if current_state not in workflow_state_list: mapping = dict(workflow_variable=workflow_variable, membership_url=membership.getRelativeUrl(), membership_title=membership.getTitle(), current_state=current_state, workflow_state_list=str(workflow_state_list),) if getattr(membership, 'getReference', None) is not None: mapping['membership_reference'] = membership.getReference() message_id = 'message_different_state' error_list.append(self._generateError(obj, self._getMessage(message_id), mapping=mapping) ) return error_list
def test(self, context, tested_base_category_list=None, strict_membership=0, **kw): """ A Predicate can be tested on a given context. Parameters can passed in order to ignore some conditions. - tested_base_category_list: this is the list of category that we do want to test. For example, we might want to test only the destination or the source of a predicate. - if strict_membership is specified, we should make sure that we are strictly a member of tested categories """ self = self.asPredicate() result = 1 if getattr(aq_base(self), '_identity_criterion', None) is None: self._identity_criterion = PersistentMapping() self._range_criterion = PersistentMapping() # LOG('PREDICATE TEST', 0, # 'testing %s on context of %s' % \ # (self.getRelativeUrl(), context.getRelativeUrl())) for property, value in self._identity_criterion.iteritems(): if isinstance(value, (list, tuple)): result = context.getProperty(property) in value else: result = context.getProperty(property) == value # LOG('predicate test', 0, # '%s after prop %s : %s == %s' % \ # (result, property, context.getProperty(property), value)) if not result: return result for property, (min, max) in self._range_criterion.iteritems(): value = context.getProperty(property) if min is not None: result = value >= min # LOG('predicate test', 0, # '%s after prop %s : %s >= %s' % \ # (result, property, value, min)) if not result: return result if max is not None: result = value < max # LOG('predicate test', 0, # '%s after prop %s : %s < %s' % \ # (result, property, value, max)) if not result: return result multimembership_criterion_base_category_list = \ self.getMultimembershipCriterionBaseCategoryList() membership_criterion_base_category_list = \ self.getMembershipCriterionBaseCategoryList() tested_base_category = {} # LOG('predicate test', 0, # 'categories will be tested in multi %s single %s as %s' % \ # (multimembership_criterion_base_category_list, # membership_criterion_base_category_list, # self.getMembershipCriterionCategoryList())) membership_criterion_category_list = \ self.getMembershipCriterionCategoryList() if tested_base_category_list is not None: membership_criterion_category_list = [x for x in \ membership_criterion_category_list if x.split('/', 1)[0] in \ tested_base_category_list] # Test category memberships. Enable the read-only transaction cache # temporarily, if not enabled, because this part is strictly read-only, # and context.isMemberOf is very expensive, when the category list has # many items. enabled = getReadOnlyTransactionCache() is not None try: if not enabled: enableReadOnlyTransactionCache() for c in membership_criterion_category_list: bc = c.split('/', 1)[0] if (bc not in tested_base_category) and \ (bc in multimembership_criterion_base_category_list): tested_base_category[bc] = 1 elif (bc not in tested_base_category) and \ (bc in membership_criterion_base_category_list): tested_base_category[bc] = 0 if (bc in multimembership_criterion_base_category_list): tested_base_category[bc] = tested_base_category[bc] and \ context.isMemberOf(c, strict_membership=strict_membership) # LOG('predicate test', 0, # '%s after multi membership to %s' % \ # (tested_base_category[bc], c)) elif (bc in membership_criterion_base_category_list): tested_base_category[bc] = tested_base_category[bc] or \ context.isMemberOf(c, strict_membership=strict_membership) finally: if not enabled: disableReadOnlyTransactionCache() # LOG('predicate test', 0, # '%s after single membership to %s' % \ # (tested_base_category[bc], c)) result = 0 not in tested_base_category.values() # LOG('predicate test', 0, # '%s after category %s ' % (result, tested_base_category.items())) if not result: return result # Test method calls test_method_id_list = self.getTestMethodIdList() if test_method_id_list is not None : for test_method_id in test_method_id_list : if test_method_id is not None: method = getattr(context,test_method_id) try: result = method(self) except TypeError: if method.func_code.co_argcount != isinstance(method, MethodType): raise # backward compatibilty with script that takes no argument warn('Predicate %s uses an old-style method (%s) that does not' ' take the predicate as argument' % ( self.getRelativeUrl(), method.__name__), DeprecationWarning) result = method() # LOG('predicate test', 0, # '%s after method %s ' % (result, test_method_id)) if not result: return result test_tales_expression = self.getTestTalesExpression() if test_tales_expression != 'python: True': expression = Expression(test_tales_expression) from Products.ERP5Type.Utils import createExpressionContext # evaluate a tales expression with the tested value as context result = expression(createExpressionContext(context)) return result
def test(self, context, tested_base_category_list=None, strict_membership=0, isMemberOf=None, **kw): """ A Predicate can be tested on a given context. Parameters can passed in order to ignore some conditions. - tested_base_category_list: this is the list of category that we do want to test. For example, we might want to test only the destination or the source of a predicate. - if strict_membership is specified, we should make sure that we are strictly a member of tested categories - isMemberOf can be a function caching results for CategoryTool.isMemberOf: it is always called with given 'context' and 'strict_membership' values, and different categories. """ self = self.asPredicate() if self is None: # asPredicate returned None, so this predicate never applies. # But if we reach this it is because catalog is not up to date. return False result = 1 if getattr(aq_base(self), '_identity_criterion', None) is None: self._identity_criterion = PersistentMapping() self._range_criterion = PersistentMapping() # LOG('PREDICATE TEST', 0, # 'testing %s on context of %s' % \ # (self.getRelativeUrl(), context.getRelativeUrl())) for property, value in self._identity_criterion.iteritems(): if isinstance(value, (list, tuple)): result = context.getProperty(property) in value else: result = context.getProperty(property) == value # LOG('predicate test', 0, # '%s after prop %s : %s == %s' % \ # (result, property, context.getProperty(property), value)) if not result: return result for property, (min, max) in self._range_criterion.iteritems(): value = context.getProperty(property) if min is not None: result = value >= min # LOG('predicate test', 0, # '%s after prop %s : %s >= %s' % \ # (result, property, value, min)) if not result: return result if max is not None: result = value < max # LOG('predicate test', 0, # '%s after prop %s : %s < %s' % \ # (result, property, value, max)) if not result: return result multimembership_criterion_base_category_list = \ self.getMultimembershipCriterionBaseCategoryList() membership_criterion_base_category_list = \ self.getMembershipCriterionBaseCategoryList() tested_base_category = {} # LOG('predicate test', 0, # 'categories will be tested in multi %s single %s as %s' % \ # (multimembership_criterion_base_category_list, # membership_criterion_base_category_list, # self.getMembershipCriterionCategoryList())) # Test category memberships. Enable the read-only transaction cache # because this part is strictly read-only, and context.isMemberOf # is very expensive when the category list has many items. if isMemberOf is None: isMemberOf = context._getCategoryTool().isMemberOf with readOnlyTransactionCache(): for c in self.getMembershipCriterionCategoryList(): bc = c.split('/', 1)[0] if tested_base_category_list is None or bc in tested_base_category_list: if bc in multimembership_criterion_base_category_list: if not isMemberOf(context, c, strict_membership=strict_membership): return 0 elif bc in membership_criterion_base_category_list and \ not tested_base_category.get(bc): tested_base_category[bc] = \ isMemberOf(context, c, strict_membership=strict_membership) if 0 in tested_base_category.itervalues(): return 0 # Test method calls test_method_id_list = self.getTestMethodIdList() if test_method_id_list is not None : for test_method_id in test_method_id_list : if test_method_id is not None: method = getattr(context,test_method_id) try: result = method(self) except TypeError: if method.func_code.co_argcount != isinstance(method, MethodType): raise # backward compatibilty with script that takes no argument warn('Predicate %s uses an old-style method (%s) that does not' ' take the predicate as argument' % ( self.getRelativeUrl(), method.__name__), DeprecationWarning) result = method() # LOG('predicate test', 0, # '%s after method %s ' % (result, test_method_id)) if not result: return result test_tales_expression = self.getTestTalesExpression() if test_tales_expression != 'python: True': expression = Expression(test_tales_expression) from Products.ERP5Type.Utils import createExpressionContext # evaluate a tales expression with the tested value as context result = expression(createExpressionContext(context)) return result
def _evaluateTales(instance=None, value=None): from Products.ERP5Type.Utils import createExpressionContext __traceback_info__ = (instance, value) return Expression(value)(createExpressionContext(instance))