Пример #1
0
  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
Пример #2
0
  def test(self, context, tested_base_category_list=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.

      This method returns portal type name if test success, else returns False.
    """
    self = self.asPredicate()
    result = 1
    if getattr(aq_base(self), '_identity_criterion', None) is None:
      self._identity_criterion = {}
      self._range_criterion = {}
    for property, value in self._identity_criterion.iteritems():
      result = result and (context.getProperty(property) in value)
    for property, (min, max) in self._range_criterion.iteritems():
      value = context.getProperty(property)
      if min is not None:
        result = result and (value >= min)
      if max is not None:
        result = result and (value < max)
    multimembership_criterion_base_category_list = \
        self.getMultimembershipCriterionBaseCategoryList()
    membership_criterion_base_category_list = \
        self.getMembershipCriterionBaseCategoryList()
    tested_base_category = {}
    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
    # because this part is strictly read-only, and context.isMemberOf
    # is very expensive when the category list has many items.
    with readOnlyTransactionCache():
      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)
        elif (bc in membership_criterion_base_category_list):
          tested_base_category[bc] = tested_base_category[bc] or \
                                     context.isMemberOf(c)

    result = result and (0 not in tested_base_category.values())
    # Test method calls
    test_method_id_list = self.getTestMethodIdList()
    if test_method_id_list:
      for test_method_id in test_method_id_list:
        if (test_method_id is not None) and result:
          method = getattr(context, test_method_id)
          result = result and method(self)
    else:
      result = result and self.getDestinationPortalType()
    return result