예제 #1
0
파일: Worklist.py 프로젝트: yuanpli/erp5
class Worklist(IdAsReferenceMixin("worklist_"), GuardableMixin, Predicate):
    """
    ERP5 Worklist.

    Variables:
      - Workflow Variable where for_catalog == 1.
      - State Variable.
      - SECURITY_PARAMETER_ID (local_roles).
    """
    meta_type = 'ERP5 Worklist'
    portal_type = 'Worklist'
    add_permission = Permissions.AddPortalContent

    security = ClassSecurityInfo()
    security.declareObjectProtected(Permissions.AccessContentsInformation)

    property_sheets = (
        'Base',
        'XMLObject',
        'CategoryCore',
        'DublinCore',
        'Reference',
        'Comment',
        'Guard',
        'ActionInformation',
        'Predicate',
    )

    security.declareProtected(Permissions.AccessContentsInformation,
                              'getIdentityCriterionDict')

    def getIdentityCriterionDict(self):
        """
      XXX: Move this to Predicate class?
      """
        try:
            return dict(self._identity_criterion)
        except AttributeError:
            return {}

    # XXX(PERF): hack to see Category Tool responsability in new workflow slowness
    security.declareProtected(Permissions.AccessContentsInformation,
                              'getActionType')

    def getActionType(self):
        prefix_length = len('action_type/')
        action_type_list = [
            path[prefix_length:] for path in self.getCategoryList()
            if path.startswith('action_type/')
        ]
        try:
            return action_type_list[0]
        except IndexError:
            return None
예제 #2
0
class WorkflowVariable(IdAsReferenceMixin("variable_"), XMLObject,
                       GuardableMixin,
                       ExpressionMixin('variable_default_expression')):
    """
    A ERP5 Workflow Variable.
    """
    meta_type = 'ERP5 Variable'
    portal_type = 'Workflow Variable'
    add_permission = Permissions.AddPortalContent

    security = ClassSecurityInfo()
    security.declareObjectProtected(Permissions.AccessContentsInformation)

    property_sheets = (
        'Base',
        'XMLObject',
        'CategoryCore',
        'DublinCore',
        'Reference',
        'Comment',
        'Guard',
        'WorkflowVariable',
    )
예제 #3
0
class WorkflowScript(IdAsReferenceMixin(SCRIPT_PREFIX), PythonScript):
    """
  Script within a Workflow taking state_change as a parameter.

  Difference with Python Script: Reference added and ID automatically set to
  reference prefixed with SCRIPT_PREFIX (Workflow Sctrips are at the same
  level as Transitions, States, Variables and Worklists).
  """
    meta_type = 'ERP5 Workflow Script'
    portal_type = 'Workflow Script'
    add_permission = Permissions.AddPortalContent

    security = ClassSecurityInfo()
    security.declareObjectProtected(Permissions.AccessContentsInformation)

    property_sheets = (
        'Base',
        'XMLObject',
        'CategoryCore',
        'DublinCore',
        'PythonScript',
        'Reference',
    )
예제 #4
0
class StandardProperty(IdAsReferenceMixin('_property'), XMLObject):
    """
  Define a Standard Property Document for a ZODB Property Sheet

  A Standard Property contains the following attributes:
   - reference: string
   - description: string
   - elementary_type: string
   - storage_id: string
   - multivalued: boolean (default: False)
   - property_default: TALES Expression as a string
   - range: boolean (default: False)
   - preference: boolean (default: False)
   - read_permission: string (default: Permissions.AccessContentsInformation)
   - write_permission: string (default: Permissions.ModifyPortalContent)
   - translatable: boolean (default: False)
   - translation_domain: string
  """
    meta_type = 'ERP5 Standard Property'
    portal_type = 'Standard Property'

    # Declarative security
    security = ClassSecurityInfo()
    security.declareObjectProtected(Permissions.AccessContentsInformation)

    property_sheets = (PropertySheet.SimpleItem,
                       PropertySheet.StandardProperty, PropertySheet.Reference,
                       PropertySheet.TranslatableProperty)

    # Names mapping between filesystem to ZODB property, only meaningful
    # when importing a property from its filesystem definition
    _name_mapping_filesystem_to_zodb_dict = {
        'type': 'elementary_type',
        'default': 'property_default'
    }

    # ZODB name of attributes whose value is a TALES Expression string
    _expression_attribute_tuple = ('property_default', )

    # Define getters for the property. This is necessary for bootstrap
    # as a Standard Property is defined by Standard Properties which
    # also depends on Property Sheets defined by Standard Properties.
    #
    # There is no need to define the setter as this static definition of
    # the getter is only meaningful for the Standard Properties defined
    # within an Standard Property.
    getDescription = Base.Getter('getDescription',
                                 'description',
                                 'string',
                                 default='')

    security.declareProtected(Permissions.AccessContentsInformation,
                              'getElementaryType')

    def getElementaryType(self):
        """
    Define this getter manually as it is not possible to rely on
    CategoryTool during the bootstrap
    """
        for category in self.__dict__.get('categories', ()):
            if category.startswith('elementary_type/'):
                return category.split('elementary_type/')[1]

        return getattr(self, 'elementary_type', None)

    # The following getters have been defined to address bootstrap
    # issues
    getStorageId = Base.Getter('getStorageId', 'storage_id', 'string')

    getMultivalued = Base.Getter('getMultivalued',
                                 'multivalued',
                                 'boolean',
                                 default=False)

    # Define as a TALES expression string, use for Expression
    # instanciation when exporting the property to the filesystem
    # definition
    getPropertyDefault = Base.Getter('getPropertyDefault', 'property_default',
                                     'string')

    getRange = Base.Getter('getRange', 'range', 'boolean', default=False)

    getPreference = Base.Getter('getPreference',
                                'preference',
                                'boolean',
                                default=False)

    getReadPermission = Base.Getter(
        'getReadPermission',
        'read_permission',
        'string',
        default=Permissions.AccessContentsInformation)

    getWritePermission = Base.Getter('getWritePermission',
                                     'write_permission',
                                     'string',
                                     default=Permissions.ModifyPortalContent)

    getTranslatable = Base.Getter('getTranslatable',
                                  'translatable',
                                  'boolean',
                                  default=False)

    getTranslationDomain = Base.Getter('getTranslationDomain',
                                       'translation_domain', 'string')

    getSelectVariable = Base.Getter('getSelectVariable', 'select_variable',
                                    'string')

    @classmethod
    def _asPropertyMap(cls, property_dict):
        """
    Return the Zope definition of this ZODB property, as used by the
    PropertyManager (for the ZMI for example).

    ERP5 _properties and Zope _properties are somehow different. The
    id is converted to the Zope standard - we keep the original id as
    base_id.

    @param property_dict: ZODB property dict
    @type property_dict: dict
    @return: PropertyManager definition
    @rtype: dict
    """
        property_dict['type'] = property_dict.pop('elementary_type')
        property_dict['default'] = property_dict.pop('property_default')

        property_dict['id'] = property_dict.pop('reference')

        # In case, this property is a list, then display it as a list
        if property_dict['type'] in list_types or property_dict['multivalued']:
            property_dict['base_id'] = property_dict['id']
            property_dict['id'] = property_dict['id'] + '_list'

        # Maintain consistency while displaying properties form.
        # Addition of select_variable property is required for 'selection'
        # and 'multiple selection' property type as while rendering properties
        # dtml file, it asks for 'select_variable' property
        if property_dict['type'] in ['selection', 'multiple selection']:
            property_dict['select_variable'] = property_dict.pop(
                'select_variable')

        return property_dict

    @staticmethod
    def _applyDefinitionFormatDictOnAccessorHolder(reference, definition_dict,
                                                   accessor_holder,
                                                   argument_list, permission):
        """
    Apply a definition dict, a format string defining the accessor
    name as the key (formatted with the given reference) and the
    accessor class to be used as the value, on the given accessor
    holder class.

    The accessor class given in the definition dict is instanciated
    with the given argument list and the the accessor is protected
    using the given permission (which may be either read if it is a
    getter or tester, or write if it is a setter), it is then
    registered on the accessor holder.

    For most cases, the reference is used in the accessor name but
    there are exceptions, such as translation accessors.

    @param reference: Reference to be used to format accessor name
    @type reference: str
    @param definition_dict: Definition of accessors being created
    @type definition_dict: dict
    @param accessor_holder: Accessor holder to applied the accessors on
    @type accessor_holder: Products.ERP5Type.dynamic.accessor_holder.AccessorHolderType
    @param argument_list: Arguments to be given to the accessor class constructor
    @type argument_list: list
    @param permission: Permission to be applied on the accessor
    @type permission: str
    """
        uppercase_reference = UpperCase(reference)
        for format, klass in definition_dict.iteritems():
            name = format % uppercase_reference

            instance = klass(name, reference, *argument_list)
            accessor_holder.registerAccessor(instance, permission)

            # Public setters actually just calls the private one and then
            # perform a re-indexing
            if name.startswith('_set'):
                instance = Alias.Reindex(name[1:], name)
                accessor_holder.registerAccessor(instance, permission)

    @classmethod
    def _applyRangeOnAccessorHolder(cls, property_dict, accessor_holder, kind,
                                    portal):
        """
    Apply range accessors.

    @param property_dict: Property to generate getter for
    @type property_dict: dict
    @param accessor_holder: Accessor holder to applied the accessors on
    @type accessor_holder: Products.ERP5Type.dynamic.accessor_holder.AccessorHolderType
    @param kind: 'min' or 'max'
    @type kind: string
    @param portal: Portal object
    @type portal: Products.ERP5.ERP5Site.ERP5Site
    """
        property_dict['reference'] = '%s_range_%s' % (
            property_dict['reference'], kind)

        # Override storage_id to not store the value on the same attribute
        # as the "normal" accessor
        property_dict['storage_id'] = None

        # Set range to False to avoid infinite recursion upon
        # applyDefinitionOnAccessorHolder call
        property_dict['range'] = False

        cls.applyDefinitionOnAccessorHolder(property_dict,
                                            accessor_holder,
                                            portal,
                                            do_register=False)

    _translation_language_getter_definition_dict = {
        'get%s': Translation.TranslatedPropertyGetter,
        '_baseGet%s': Translation.TranslatedPropertyGetter
    }

    _translation_language_getter_definition_dict = {
        'get%s': Translation.TranslatedPropertyGetter,
        '_baseGet%s': Translation.TranslatedPropertyGetter
    }

    _translation_language_tester_definition_dict = {
        'has%s': Translation.TranslatedPropertyTester
    }

    _translation_language_setter_definition_dict = {
        '_set%s': Translation.TranslationPropertySetter
    }

    @classmethod
    def _applyTranslationLanguageOnAccessorHolder(cls, property_dict,
                                                  accessor_holder, portal):
        """
    Apply translation language accessors.

    @param property_dict: Property to generate getter for
    @type property_dict: dict
    @param accessor_holder: Accessor holder to applied the accessors on
    @type accessor_holder: Products.ERP5Type.dynamic.accessor_holder.AccessorHolderType
    @param portal: Portal object
    @type portal: Products.ERP5.ERP5Site.ERP5Site
    """
        try:
            localizer = portal._getOb('Localizer')
        except AttributeError:
            if not getattr(portal, '_v_bootstrapping', False):
                LOG("ERP5Type.Core.StandardProperty", WARNING,
                    "Localizer is missing. Accessors can not be generated")

            return

        # Apply language-specific accessors
        for language in localizer.get_languages():
            translation_language_id = '%s_translated_%s' % \
                (language.replace('-', '_'),
                 property_dict['reference'])

            # Prepare accessor arguments for getters
            getter_argument_list = (property_dict['reference'],
                                    property_dict['elementary_type'], language,
                                    property_dict['property_default'])

            cls._applyDefinitionFormatDictOnAccessorHolder(
                translation_language_id,
                cls._translation_language_getter_definition_dict,
                accessor_holder, getter_argument_list,
                property_dict['read_permission'])

            # Prepare accessor arguments for testers and setters
            tester_setter_argument_list = (property_dict['reference'],
                                           property_dict['elementary_type'],
                                           language)

            cls._applyDefinitionFormatDictOnAccessorHolder(
                translation_language_id,
                cls._translation_language_tester_definition_dict,
                accessor_holder, tester_setter_argument_list,
                property_dict['read_permission'])

            cls._applyDefinitionFormatDictOnAccessorHolder(
                translation_language_id,
                cls._translation_language_setter_definition_dict,
                accessor_holder, tester_setter_argument_list,
                property_dict['write_permission'])

    _primitive_getter_definition_dict = {
        'get%s': Base.Getter,
        '_baseGet%s': Base.Getter
    }

    _list_getter_definition_dict = {
        'get%s': List.Getter,
        '_baseGet%s': List.Getter,
        'getDefault%s': List.DefaultGetter,
        '_baseGetDefault%s': List.DefaultGetter,
        'get%sList': List.ListGetter,
        '_baseGet%sList': List.ListGetter,
        'get%sSet': List.SetGetter,
        '_baseGet%sSet': List.SetGetter
    }

    @classmethod
    def _applyGetterDefinitionDictOnAccessorHolder(cls, property_dict,
                                                   accessor_holder):
        """
    Apply getters for the given property on the given accessor holder.
    This method is overriden in AcquiredProperty for example to add
    accessors specific to Acquired Properties.

    @param property_dict: Property to generate getter for
    @type property_dict: dict
    @param accessor_holder: Accessor holder to applied the accessors on
    @type accessor_holder: Products.ERP5Type.dynamic.accessor_holder.AccessorHolderType

    @see _applyDefinitionFormatDictOnAccessorHolder
    """
        argument_list = (property_dict['elementary_type'],
                         property_dict['property_default'],
                         property_dict['storage_id'])

        if property_dict['elementary_type'] in list_types or \
           property_dict['multivalued']:
            definition_dict = cls._list_getter_definition_dict
        else:
            definition_dict = cls._primitive_getter_definition_dict

        cls._applyDefinitionFormatDictOnAccessorHolder(
            property_dict['reference'], definition_dict, accessor_holder,
            argument_list, property_dict['read_permission'])

    _list_setter_definition_dict = {
        '_set%s': List.Setter,
        '_baseSet%s': List.Setter,
        '_setDefault%s': List.DefaultSetter,
        '_baseSetDefault%s': List.DefaultSetter,
        '_set%sList': List.ListSetter,
        '_baseSet%sList': List.ListSetter,
        '_set%sSet': List.SetSetter,
        '_baseSet%sSet': List.SetSetter
    }

    _primitive_setter_definition_dict = {
        '_set%s': Base.Setter,
        '_baseSet%s': Base.Setter
    }

    @classmethod
    def _applySetterDefinitionDictOnAccessorHolder(cls, property_dict,
                                                   accessor_holder):
        """
    Apply setters for the given property on the given accessor holder.

    @param property_dict: Property to generate getter for
    @type property_dict: dict
    @param accessor_holder: Accessor holder to applied the accessors on
    @type accessor_holder: Products.ERP5Type.dynamic.accessor_holder.AccessorHolderType

    @see _applyGetterDefinitionDictOnAccessorHolder
    """
        argument_list = (property_dict['elementary_type'],
                         property_dict['storage_id'])

        if property_dict['elementary_type'] in list_types or \
           property_dict['multivalued']:
            definition_dict = cls._list_setter_definition_dict
        else:
            definition_dict = cls._primitive_setter_definition_dict

        cls._applyDefinitionFormatDictOnAccessorHolder(
            property_dict['reference'], definition_dict, accessor_holder,
            argument_list, property_dict['write_permission'])

    _tester_definition_dict = {
        'has%s': Base.Tester,
        '_baseHas%s': Base.Tester,
        'has%sList': List.Tester,
        '_baseHas%sList': List.Tester,
        'hasDefault%s': List.Tester,
        '_baseHasDefault%s': List.Tester
    }

    _boolean_definition_dict = {'is%s': Base.Getter, '_baseIs%s': Base.Getter}

    @classmethod
    def _applyTesterDefinitionDictOnAccessorHolder(cls, property_dict,
                                                   accessor_holder):
        """
    Apply testers and boolean accessors for the given property on the
    given accessor holder.

    @param property_dict: Property to generate getter for
    @type property_dict: dict
    @param accessor_holder: Accessor holder to applied the accessors on
    @type accessor_holder: Products.ERP5Type.dynamic.accessor_holder.AccessorHolderType

    @see _applyGetterDefinitionDictOnAccessorHolder
    """
        tester_argument_list = (property_dict['elementary_type'],
                                property_dict['storage_id'])

        cls._applyDefinitionFormatDictOnAccessorHolder(
            property_dict['reference'], cls._tester_definition_dict,
            accessor_holder, tester_argument_list,
            property_dict['read_permission'])

        boolean_argument_list = (property_dict['elementary_type'],
                                 property_dict['property_default'],
                                 property_dict['storage_id'])

        cls._applyDefinitionFormatDictOnAccessorHolder(
            property_dict['reference'], cls._boolean_definition_dict,
            accessor_holder, boolean_argument_list,
            property_dict['read_permission'])

    _translated_getter_definition_dict = {
        'get%s': Translation.TranslatedPropertyGetter,
        '_baseGet%s': Translation.TranslatedPropertyGetter
    }

    security.declareProtected(Permissions.ModifyPortalContent,
                              'applyDefinitionOnAccessorHolder')

    @classmethod
    def applyDefinitionOnAccessorHolder(cls,
                                        property_dict,
                                        accessor_holder,
                                        portal,
                                        do_register=True):
        """
    Apply getters, setters and testers for a list property or a
    primitive property.

    This class method may be called to apply a property dictionnary on
    an accessor holder. While applyOnAccessorHolder is commonly used
    to apply a property on an *existing* ZODB Property Sheet, this
    method can be used to apply accessors from a Property not defined
    in a ZODB Property Sheet.

    The property dictionnary must define all the attributes listed in
    the class docstring.

    The TALES Expression in the given property dict are considered to
    have been already evaluated, as performed through
    applyOnAccessorHolder by asDict method.

    @param property_dict: Property to generate getter for
    @type property_dict: dict
    @param accessor_holder: Accessor holder to applied the accessors on
    @type accessor_holder: Products.ERP5Type.dynamic.accessor_holder.AccessorHolderType
    @param portal: Portal object
    @type portal: Products.ERP5.ERP5Site.ERP5Site
    @param do_register: Register the property in the Zope property map
    @type do_register: bool
    """
        # Some attributes are required to generate accessors, if they have
        # not been set properly, then don't generate them at all for this
        # Property
        if property_dict['reference'] is None or \
           property_dict['elementary_type'] is None or \
           property_dict['elementary_type'] not in type_definition:
            raise ValueError("Invalid type or reference")

        # Create range accessors if relevant
        if property_dict['range']:
            for kind in ('min', 'max'):
                cls._applyRangeOnAccessorHolder(property_dict.copy(),
                                                accessor_holder, kind, portal)

        # Create translation accessors if relevant
        if property_dict['translatable']:
            translated_property_dict = property_dict.copy()

            if translated_property_dict['property_default'] is None:
                translated_property_dict['property_default'] = ''

            # Make accessors such as getTranslatedProperty
            translated_reference = 'translated_' + property_dict['reference']

            argument_list = (translated_property_dict['reference'],
                             translated_property_dict['elementary_type'], None,
                             translated_property_dict['property_default'])

            cls._applyDefinitionFormatDictOnAccessorHolder(
                translated_reference, cls._translated_getter_definition_dict,
                accessor_holder, argument_list,
                translated_property_dict['read_permission'])

            cls._applyTranslationLanguageOnAccessorHolder(
                translated_property_dict, accessor_holder, portal)

            # make accessor to translation_domain
            # first create default one as a normal property
            translation_domain_reference = translated_property_dict['reference'] + \
                                           '_translation_domain'

            translation_domain_property_dict = {
                'reference': translation_domain_reference,
                'elementary_type': 'string',
                'property_default': '',
                'multivalued': False,
                'storage_id': None,
                'range': False,
                'translatable': False,
                'read_permission': translated_property_dict['read_permission'],
                'write_permission':
                translated_property_dict['write_permission']
            }

            # This will always be a StandardProperty, so avoid calling
            # super() here
            StandardProperty.applyDefinitionOnAccessorHolder(
                translation_domain_property_dict,
                accessor_holder,
                portal,
                do_register=False)

            # Then override getPropertyTranslationDomain accessor
            accessor = Translation.PropertyTranslationDomainGetter(
                'get' + UpperCase(translation_domain_reference),
                translation_domain_reference, 'string',
                property_dict['translation_domain'])

            accessor_holder.registerAccessor(
                accessor, translated_property_dict['read_permission'])

        # After applying specific getters, setters and testers, apply
        # common getters, setters and testers
        cls._applyGetterDefinitionDictOnAccessorHolder(property_dict,
                                                       accessor_holder)

        cls._applySetterDefinitionDictOnAccessorHolder(property_dict,
                                                       accessor_holder)

        cls._applyTesterDefinitionDictOnAccessorHolder(property_dict,
                                                       accessor_holder)

        # By default, register the property as a Zope property map, by
        # adding it to _properties, which will be later used by
        # PropertyManager
        if do_register:
            property_map = cls._asPropertyMap(property_dict)
            if property_map:
                accessor_holder._properties.append(property_map)

    security.declareProtected(Permissions.AccessContentsInformation, 'asDict')

    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()
        }

    security.declareProtected(Permissions.ModifyPortalContent,
                              'applyOnAccessorHolder')

    def applyOnAccessorHolder(self, accessor_holder, expression_context,
                              portal):
        """
    Apply the ZODB Property to the given accessor holder

    @param accessor_holder: Accessor holder to applied the accessors on
    @type accessor_holder: Products.ERP5Type.dynamic.accessor_holder.AccessorHolderType
    @param expression_context: Expression context for TALES Expression
    @type expression_context: Products.PageTemplates.Expressions.ZopeContext
    @param portal: Portal object
    @type portal: Products.ERP5.ERP5Site.ERP5Site

    @see applyDefinitionOnAccessorHolder
    """
        self.applyDefinitionOnAccessorHolder(self.asDict(expression_context),
                                             accessor_holder, portal)

    @classmethod
    def _convertFromFilesystemPropertyDict(cls, filesystem_property_dict):
        """
    Convert a property dict coming from a Property Sheet on the
    filesystem to a ZODB property dict.

    This method is just kept for backward-compatibility with
    filesystem Property Sheets used before ZODB Property Sheets.

    @param filesystem_property_dict: Filesystem property definition
    @type filesystem_property_dict: dict
    @return: ZODB property definition
    @rtype: dict
    """
        # Prepare a dictionnary of the ZODB property
        zodb_property_dict = {}

        for fs_property_name, value in filesystem_property_dict.iteritems():
            # Convert filesystem property name to ZODB if necessary
            zodb_property_name = \
                fs_property_name in cls._name_mapping_filesystem_to_zodb_dict and \
                cls._name_mapping_filesystem_to_zodb_dict[fs_property_name] or \
                fs_property_name

            # Convert existing TALES expression class or primitive type to a
            # TALES expression string
            if zodb_property_name in cls._expression_attribute_tuple:
                value = isinstance(value, Expression) and \
                    value.text or 'python: ' + repr(value)

            # set correctly the id by following naming conventions
            if zodb_property_name == 'id':
                value += cls.getIdAsReferenceSuffix()

            zodb_property_dict[zodb_property_name] = value

        return zodb_property_dict

    security.declareProtected(Permissions.ModifyPortalContent,
                              'importFromFilesystemDefinition')

    @classmethod
    def importFromFilesystemDefinition(cls, context, filesystem_property_dict):
        """
    Create a new property on the given context from the given
    filesystem definition dict.

    This method is just kept for backward-compatibility with
    filesystem Property Sheets used before ZODB Property Sheets.

    @param context: Context to create the property in
    @type context: Products.ERP5Type.Core.PropertySheet
    @param filesystem_property_dict: Filesystem definition
    @param filesystem_property_dict: dict
    @return: The new Standard Property
    @rtype: StandardProperty
    """
        return context.newContent(
            portal_type=cls.portal_type,
            **cls._convertFromFilesystemPropertyDict(filesystem_property_dict))
예제 #5
0
class WorkflowState(IdAsReferenceMixin("state_"), XMLObject):
    """
  A ERP5 State.
  """
    meta_type = 'ERP5 Workflow State'
    portal_type = 'Workflow State'
    add_permission = Permissions.AddPortalContent

    state_permission_role_list_dict = None

    security = ClassSecurityInfo()
    security.declareObjectProtected(Permissions.AccessContentsInformation)

    property_sheets = (
        'Base',
        'XMLObject',
        'CategoryCore',
        'DublinCore',
        'Reference',
        'Comment',
        'SortIndex',
        'WorkflowState',
    )

    def addPossibleTransition(self, tr_ref):
        possible_transition_list = self.getCategoryList()
        transition = self.getParentValue()._getOb('transition_' + tr_ref, None)
        if transition is not None:
            tr_path = 'destination/' + '/'.join(
                transition.getPath().split('/')[2:])
            possible_transition_list.append(tr_path)
            self.setCategoryList(possible_transition_list)

    # XXX(PERF): hack to see Category Tool responsability in new workflow slowness
    security.declareProtected(Permissions.AccessContentsInformation,
                              'getDestinationList')

    def getDestinationList(self):
        """
    this getter is redefined to improve performance:
    instead of getting all the transition objects from the destination list
    to then use their ids, extract the information from the string
    """
        prefix_length = len('destination/')
        return [
            path[prefix_length:] for path in self.getCategoryList()
            if path.startswith('destination/')
        ]

    security.declareProtected(Permissions.AccessContentsInformation,
                              'getDestinationIdList')

    def getDestinationIdList(self):
        """
    this getter is redefined to improve performance:
    instead of getting all the transition objects from the destination list
    to then use their ids, extract the information from the string
    """
        return [
            path.split('/')[-1] for path in self.getCategoryList()
            if path.startswith('destination/')
        ]

    security.declareProtected(Permissions.AccessContentsInformation,
                              'getDestinationValueList')

    def getDestinationValueList(self):
        """
    this getter is redefined to improve performance:
    instead of getting all the transition objects from the destination list
    to then use their ids, extract the information from the string
    """
        parent = self.getParentValue()
        return [
            parent._getOb(destination_id)
            for destination_id in self.getDestinationIdList()
        ]

    security.declareProtected(Permissions.ModifyPortalContent,
                              'setStatePermissionRoleListDict')

    def setStatePermissionRoleListDict(self, permission_roles):
        """
    create a dict containing the state's permission (as key) and its
    associated role list (value)
    use a PersistentMapping so that the ZODB is updated
    when this dict is changed
    """
        self.state_permission_role_list_dict = PersistentMapping(
            {k: tuple(v)
             for (k, v) in permission_roles.items()})

    security.declareProtected(Permissions.AccessContentsInformation,
                              'getStatePermissionRoleListDict')

    def getStatePermissionRoleListDict(self):
        """
    return the permission/roles dict
    """
        if self.state_permission_role_list_dict is None:
            return {}
        return dict(self.state_permission_role_list_dict.items())

    security.declareProtected(Permissions.ModifyPortalContent, 'setPermission')

    def setPermission(self, permission, roles, REQUEST=None):
        """
    Set a permission for this State.
    """
        if self.state_permission_role_list_dict is None:
            self.state_permission_role_list_dict = PersistentMapping()
        self.state_permission_role_list_dict[permission] = tuple(roles)

    security.declareProtected(Permissions.AccessContentsInformation,
                              'getAvailableTypeList')

    def getAvailableTypeList(self):
        """
    This is a method specific to ERP5. This returns a list of state types,
    which are used for portal methods.
    """
        return ('draft_order', 'planned_order', 'future_inventory',
                'reserved_inventory', 'transit_inventory', 'current_inventory')
예제 #6
0
class ConstraintMixin(IdAsReferenceMixin('_constraint'), Predicate):
    """
  Mixin Constraint implementation (only relevant for ZODB Property
  sheets, use Products.ERP5Type.Constraint instead for filesystem
  Property Sheets) relying on Predicate

  @todo: Add code to import constraints requiring a new TALES
         Expression field in predicate to be able to import
         'condition' properly
  """
    # Declarative security
    security = ClassSecurityInfo()
    security.declareObjectProtected(Permissions.AccessContentsInformation)

    # IDs of error messages defined in each Constraint, only used when
    # importing or exporting from/to filesystem Constraint
    _message_id_tuple = ()

    __allow_access_to_unprotected_subobjects__ = 1
    implements(IConstraint, )

    property_sheets = (PropertySheet.SimpleItem, PropertySheet.Reference,
                       PropertySheet.Predicate)

    def _getMessage(self, message_id):
        """
    Get the message corresponding to this message_id.
    """
        return getattr(self, 'get' + UpperCase(message_id))()

    def _generateError(self, obj, error_message, mapping={}):
        """
    Generic method used to generate error in checkConsistency.
    """
        if error_message is not None:
            msg = ConsistencyMessage(self,
                                     object_relative_url=obj.getRelativeUrl(),
                                     message=error_message,
                                     mapping=mapping)
            return msg

    security.declareProtected(Permissions.AccessContentsInformation,
                              'checkConsistency')

    def checkConsistency(self, obj, fixit=0, **kw):
        """
    Check the pre-condition before checking the consistency.
    _checkConsistency() must be define in the child class.
    """
        if not self.test(obj):
            return []

        return self._checkConsistency(obj, fixit, **kw)

    security.declareProtected(Permissions.AccessContentsInformation,
                              'fixConsistency')

    def fixConsistency(self, obj, **kw):
        """
    Default method is to call checkConsistency with fixit set to 1
    """
        return self.checkConsistency(obj, fixit=1, **kw)

    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))

    @staticmethod
    def _preConvertBaseFromFilesystemDefinition(filesystem_definition_dict):
        """
    Call before actually converting the attributes common to all
    constraints
    """
        return {}

    @staticmethod
    def _convertFromFilesystemDefinition(*args, **kw):
        """
    Convert a filesystem property dict to a ZODB Property dict which
    will be given to newContent().

    Only attributes specific to this constraint will be given as
    parameters, e.g. not the ones common to all constraints such as
    'id', 'description', 'type' and 'condition' and error messages
    defined in '_message_id_tuple' class attribute.

    @see importFromFilesystemDefinition
    """
        yield {}

    security.declareProtected(Permissions.AccessContentsInformation,
                              'importFromFilesystemDefinition')

    @classmethod
    def importFromFilesystemDefinition(cls, context,
                                       filesystem_definition_dict):
        """
    Import the filesystem definition to a ZODB Constraint, without its
    condition as it is now a Predicate and has to be converted
    manually.

    Several ZODB Constraints may be created to handle Constraints such
    as Attribute Equality which defines an attribute name and its
    expected value, thus ending up creating one ZODB Constraint per
    attribute/expected value
    """
        # Copy the dictionnary as it is going to be modified to remove all
        # the common properties in order to have a dictionnary containing
        # only properties specific to the current constraint
        filesystem_definition_copy_dict = filesystem_definition_dict.copy()

        # This dict only contains definition attributes common to *all*
        # ZODB Constraints
        base_constraint_definition_dict = \
            cls._preConvertBaseFromFilesystemDefinition(filesystem_definition_copy_dict)

        base_constraint_definition_dict['portal_type'] = cls.portal_type

        base_constraint_definition_dict['id'] = \
            filesystem_definition_copy_dict.pop('id') + \
              cls.getIdAsReferenceSuffix()

        base_constraint_definition_dict['description'] = \
            filesystem_definition_copy_dict.pop('description', '')

        if 'condition' in filesystem_definition_copy_dict:
            base_constraint_definition_dict['test_tales_expression'] = \
                filesystem_definition_copy_dict.pop('condition')

        # The type is meaningless for ZODB Constraints as it is the portal
        # type itself
        filesystem_definition_copy_dict.pop('type')

        # Add specific error messages defined on the constraint document
        for message_name in cls._message_id_tuple:
            if message_name in filesystem_definition_copy_dict:
                base_constraint_definition_dict[message_name] = \
                    filesystem_definition_copy_dict.pop(message_name)

        # Call the method defined in the Constraint document which returns
        # N dictionnaries containing only attributes specific to the
        # Constraint
        constraint_definition_generator = \
            cls._convertFromFilesystemDefinition(**filesystem_definition_copy_dict)

        # Create all the constraint in the current ZODB Property Sheet
        for constraint_definition_dict in constraint_definition_generator:
            constraint_definition_dict.update(base_constraint_definition_dict)
            context.newContent(**constraint_definition_dict)

    security.declareProtected(Permissions.AccessContentsInformation,
                              'applyOnAccessorHolder')

    def applyOnAccessorHolder(self, accessor_holder, expression_context,
                              portal):
        # Do not use asContext. Temporary object generated by asContext may
        # contain persistent object. If persistent object is stored on memory like
        # this(accessor_holder is on-memory object and is kept beyond transaction)
        # then ConnectionStateError occurs after a long time.
        import copy
        constraint_definition = copy.deepcopy(self.aq_base)
        # note the relative url of this constraint to display it later in
        # checkConsistency messages
        constraint_definition.relative_url = self.getRelativeUrl()
        accessor_holder.constraints.append(constraint_definition)
예제 #7
0
class CategoryProperty(IdAsReferenceMixin('_category'), XMLObject):
    """
  Define a Category Property Document for a ZODB Property Sheets
  """
    meta_type = 'ERP5 Category Property'
    portal_type = 'Category Property'

    # Declarative security
    security = ClassSecurityInfo()
    security.declareObjectProtected(Permissions.AccessContentsInformation)

    property_sheets = (PropertySheet.SimpleItem, PropertySheet.Reference)

    security.declareProtected(Permissions.AccessContentsInformation,
                              'importFromFilesystemDefinition')

    @classmethod
    def importFromFilesystemDefinition(cls, context, category_name):
        """
    Set the Reference from a filesystem definition of a property
    """
        return context.newContent(portal_type=cls.portal_type,
                                  id=category_name +
                                  cls.getIdAsReferenceSuffix())

    getter_definition_dict = {
        # normal accessors
        'get%sList': Category.ListGetter,
        'get%sSet': Category.SetGetter,
        'get%sItemList': Category.ItemListGetter,
        'getDefault%s': Category.DefaultGetter,
        'get%s': Category.DefaultGetter,
        # value accessors
        'get%sValueList': Value.ListGetter,
        'get%sValueSet': Value.SetGetter,
        'get%sTitleList': Value.TitleListGetter,
        'get%sTitleSet': Value.TitleSetGetter,
        'get%sTranslatedTitleList': Value.TranslatedTitleListGetter,
        'get%sTranslatedTitleSet': Value.TranslatedTitleSetGetter,
        'get%sReferenceList': Value.ReferenceListGetter,
        'get%sReferenceSet': Value.ReferenceSetGetter,
        'get%sShortTitleList': Value.ShortTitleListGetter,
        'get%sShortTitleSet': Value.ShortTitleSetGetter,
        'get%sIdList': Value.IdListGetter,
        'get%sIdSet': Value.IdSetGetter,
        'get%sLogicalPathList': Value.LogicalPathListGetter,
        'get%sLogicalPathSet': Value.LogicalPathSetGetter,
        'get%sUidList': Value.UidListGetter,
        'get%sUidSet': Value.UidSetGetter,
        'get%sPropertyList': Value.PropertyListGetter,
        'get%sPropertySet': Value.PropertySetGetter,
        'getDefault%sValue': Value.DefaultGetter,
        'get%sValue': Value.DefaultGetter,
        'getDefault%sTitle': Value.DefaultTitleGetter,
        'get%sTitle': Value.DefaultTitleGetter,
        'getDefault%sTranslatedTitle': Value.DefaultTranslatedTitleGetter,
        'get%sTranslatedTitle': Value.DefaultTranslatedTitleGetter,
        'getDefault%sReference': Value.DefaultReferenceGetter,
        'get%sReference': Value.DefaultReferenceGetter,
        'getDefault%sShortTitle': Value.DefaultShortTitleGetter,
        'get%sShortTitle': Value.DefaultShortTitleGetter,
        'getDefault%sUid': Value.DefaultUidGetter,
        'get%sUid': Value.DefaultUidGetter,
        'getDefault%sId': Value.DefaultIdGetter,
        'get%sId': Value.DefaultIdGetter,
        'getDefault%sTitleOrId': Value.DefaultTitleOrIdGetter,
        'get%sTitleOrId': Value.DefaultTitleOrIdGetter,
        'getDefault%sProperty': Value.DefaultPropertyGetter,
        'get%sProperty': Value.DefaultPropertyGetter,
        'getDefault%sLogicalPath': Value.DefaultLogicalPathGetter,
        'get%sLogicalPath': Value.DefaultLogicalPathGetter,
        'get%sTranslatedLogicalPath': Value.DefaultTranslatedLogicalPathGetter,
    }
    setter_definition_dict = {
        # setters
        '_set%s': Category.Setter,
        '_categorySet%s': Category.Setter,
        '_set%sList': Category.ListSetter,
        '_categorySet%sList': Category.ListSetter,
        '_setDefault%s': Category.DefaultSetter,
        '_categorySetDefault%s': Category.DefaultSetter,
        '_set%sSet': Category.SetSetter,
        '_categorySet%sSet': Category.SetSetter,
        '_set%sValue': Value.Setter,
        '_categorySet%sValue': Value.Setter,
        '_set%sValueList': Value.ListSetter,
        '_categorySet%sValueList': Value.ListSetter,
        '_set%sValueSet': Value.SetSetter,
        '_categorySet%sValueSet': Value.SetSetter,
        '_setDefault%sValue': Value.DefaultSetter,
        '_categorySetDefault%sValue': Value.DefaultSetter,
        # uid setters
        '_set%sUid': Value.UidSetter,
        '_categorySet%sUid': Value.UidSetter,
        '_set%sUidList': Value.UidListSetter,
        '_categorySet%sUidList': Value.UidListSetter,
        '_set%sUidSet': Value.UidSetSetter,
        '_categorySet%sUidSet': Value.UidSetSetter,
        '_setDefault%sUid': Value.UidDefaultSetter,
        '_categorySetDefault%sUid': Value.UidDefaultSetter,
    }

    @classmethod
    def applyDefinitionOnAccessorHolder(cls, accessor_holder, category_id,
                                        portal):
        try:
            cat_object = portal.portal_categories._getOb(category_id)
        except KeyError:
            if portal.hasObject('portal_categories'):
                LOG("ERP5Type.Core.CategoryProperty", WARNING,
                    "Base Category %r is missing. Accessors can not be generated." % \
                      category_id)

            return
        except TypeError:
            # category_id is None
            raise ValueError("Invalid category reference")

        # Create free text accessors.
        # XXX These are only for backward compatibility.
        storage_id = None
        if category_id == 'group':
            storage_id = 'group'
        elif category_id == 'site':
            storage_id = 'location'

        property_dict = {
            'reference': '%s_free_text' % category_id,
            'elementary_type': 'text',
            'property_default': '',
            'multivalued': False,
            'storage_id': storage_id,
            'range': False,
            'translatable': False,
            'description': 'free text to specify %s' % category_id,
            'read_permission': Permissions.AccessContentsInformation,
            'write_permission': Permissions.ModifyPortalContent
        }

        StandardProperty.applyDefinitionOnAccessorHolder(property_dict,
                                                         accessor_holder,
                                                         portal,
                                                         do_register=False)

        # Get read and write permission
        read_permission = Permissions.__dict__.get(
            cat_object.getReadPermission(),
            Permissions.AccessContentsInformation)
        write_permission = Permissions.__dict__.get(
            cat_object.getWritePermission(), Permissions.ModifyPortalContent)

        # Actually create accessors
        uppercase_category_id = UpperCase(category_id)

        # three special cases
        accessor = Category.Tester('has' + uppercase_category_id, category_id)
        accessor_holder.registerAccessor(accessor, read_permission)

        accessor_name = uppercase_category_id[0].lower(
        ) + uppercase_category_id[1:]
        accessor = Value.ListGetter(accessor_name + 'Values', category_id)
        accessor_holder.registerAccessor(accessor, read_permission)
        accessor = Value.IdListGetter(accessor_name + 'Ids', category_id)
        accessor_holder.registerAccessor(accessor, read_permission)

        # then getters
        for id_format, accessor_class in cls.getter_definition_dict.iteritems(
        ):
            accessor_name = id_format % uppercase_category_id
            # XXX getSourceReference/getDestinationReference are already generated by
            # 'source_reference' and 'destination_reference' standard properties. To
            # prevent name conflict, we don't generate them as a category accessor.
            if not (SOURCE_DESTINATION_REFERENCE_LEGACY and accessor_name
                    in ('getSourceReference', 'getDestinationReference')):
                public_accessor = accessor_class(accessor_name, category_id)
                accessor_holder.registerAccessor(public_accessor,
                                                 read_permission)

            # create the private getter on the fly instead of having a definition dict
            # that's twice the size for the same info
            accessor_name = '_category' + accessor_name[0].upper(
            ) + accessor_name[1:]
            private_accessor = accessor_class(accessor_name, category_id)
            accessor_holder.registerAccessor(private_accessor, read_permission)

        # and setters
        for id_format, accessor_class in cls.setter_definition_dict.iteritems(
        ):
            accessor_name = id_format % uppercase_category_id
            # XXX setSourceReference/setDestinationReference are already generated by
            # 'source_reference' and 'destination_reference' standard properties. To
            # prevent name conflict, we don't generate them as a category accessor.
            if SOURCE_DESTINATION_REFERENCE_LEGACY and accessor_name in (
                    'setSourceReference', 'setDestinationReference'):
                continue

            accessor = accessor_class(accessor_name, category_id)
            accessor_holder.registerAccessor(accessor, write_permission)

            # TODO: merge with StandardProperty
            if accessor_name.startswith('_set'):
                accessor = Alias.Reindex(accessor_name[1:], accessor_name)
                accessor_holder.registerAccessor(accessor, write_permission)

        # Only add the category ID if it is not already in _categories,
        # which may happen when getting the categories with acquisition
        if category_id not in accessor_holder._categories:
            accessor_holder._categories.append(category_id)

    security.declareProtected(Permissions.AccessContentsInformation,
                              'applyOnAccessorHolder')

    def applyOnAccessorHolder(self, accessor_holder, expression_context,
                              portal):
        self.applyDefinitionOnAccessorHolder(accessor_holder,
                                             self.getReference(), portal)
예제 #8
0
class WorkflowTransition(IdAsReferenceMixin("transition_"), XMLObject,
                         GuardableMixin):
    """
  A ERP5 Transition.
  """
    meta_type = 'ERP5 Workflow Transition'
    portal_type = 'Workflow Transition'
    add_permission = Permissions.AddPortalContent

    security = ClassSecurityInfo()
    security.declareObjectProtected(Permissions.AccessContentsInformation)

    property_sheets = (
        'Base',
        'XMLObject',
        'CategoryCore',
        'DublinCore',
        'Reference',
        'Comment',
        'SortIndex',
        'WorkflowTransition',
        'Guard',
        'ActionInformation',
    )

    # following getters are redefined for performance improvements
    # they use the categories paths directly and string operations
    # instead of traversing from the portal to get the objects
    # in order to have their id or value

    # XXX(PERF): hack to see Category Tool responsability in new workflow slowness
    security.declareProtected(Permissions.AccessContentsInformation,
                              'getActionType')

    def getActionType(self):
        for path in self.getCategoryList():
            if path.startswith('action_type/'):
                return path[12:]  # 12 is len('action_type/')
        return None

    security.declareProtected(Permissions.AccessContentsInformation,
                              'getBeforeScriptList')

    def getBeforeScriptList(self):
        """
    returns the list of before script
    """
        prefix_length = len('before_script/')
        return [
            path[prefix_length:] for path in self.getCategoryList()
            if path.startswith('before_script/')
        ]

    security.declareProtected(Permissions.AccessContentsInformation,
                              'getAfterScriptList')

    def getAfterScriptList(self):
        """
    returns the list of after script
    """
        prefix_length = len('after_script/')
        return [
            path[prefix_length:] for path in self.getCategoryList()
            if path.startswith('after_script/')
        ]

    security.declareProtected(Permissions.AccessContentsInformation,
                              'getBeforeScriptIdList')

    def getBeforeScriptIdList(self):
        """
    returns the list of before script ids
    """
        return [path.split('/')[-1] for path in self.getBeforeScriptList()]

    security.declareProtected(Permissions.AccessContentsInformation,
                              'getBeforeScriptValueList')

    def getBeforeScriptValueList(self):
        """
    returns the list of before script values
    """
        parent = self.getParentValue()
        return [
            parent._getOb(transition_id)
            for transition_id in self.getBeforeScriptIdList()
        ]

    security.declareProtected(Permissions.AccessContentsInformation,
                              'getAfterScriptIdList')

    def getAfterScriptIdList(self):
        """
    returns the list of after script ids
    """
        return [path.split('/')[-1] for path in self.getAfterScriptList()]

    security.declareProtected(Permissions.AccessContentsInformation,
                              'getAfterScriptValueList')

    def getAfterScriptValueList(self):
        """
    returns the list of after script values
    """
        parent = self.getParentValue()
        return [
            parent._getOb(transition_id)
            for transition_id in self.getAfterScriptIdList()
        ]

    security.declareProtected(Permissions.AccessContentsInformation,
                              'getDestinationValue')

    def getDestinationValue(self):
        """
    returns the destination object
    """

        destination_path_list = [
            path for path in self.getCategoryList()
            if path.startswith('destination/')
        ]
        if destination_path_list:
            destination_id = destination_path_list[0].split('/')[-1]
            parent = self.getParentValue()
            return parent._getOb(destination_id)
        return None

    security.declareProtected(Permissions.AccessContentsInformation,
                              'getTransitionVariableValueList')

    def getTransitionVariableValueList(self):
        """
    Return Transition Variables
    """
        return self.objectValues(portal_type='Workflow Transition Variable')
예제 #9
0
class InteractionWorkflowInteraction(IdAsReferenceMixin('interaction_'),
                                     XMLObject,
                                     GuardableMixin):
  """
  An ERP5 Workflow Interaction (Interaction Workflow)
  """
  meta_type = 'ERP5 Interaction'
  portal_type = 'Interaction Workflow Interaction'
  add_permission = Permissions.AddPortalContent

  security = ClassSecurityInfo()
  security.declareObjectProtected(Permissions.AccessContentsInformation)

  # Declarative properties
  property_sheets = (
    'Base',
    'XMLObject',
    'CategoryCore',
    'DublinCore',
    'Reference',
    'InteractionWorkflowInteraction',
    'Guard',
  )

  # following getters are redefined for performance improvements
  # they use the categories paths directly and string operations
  # instead of traversing from the portal to get the objects
  # in order to have their id or value
  security.declareProtected(Permissions.AccessContentsInformation,
                            'getBeforeCommitScriptIdList')
  def getBeforeCommitScriptIdList(self):
    """
    returns the list of before commit script ids
    """
    return [path.split('/')[-1] for path in self.getBeforeCommitScriptList()]

  security.declareProtected(Permissions.AccessContentsInformation,
                            'getBeforeCommitScriptValueList')
  def getBeforeCommitScriptValueList(self):
    """
    returns the list of before commit script values
    """
    parent = self.getParentValue()
    return [parent._getOb(transition_id) for transition_id
            in self.getBeforeCommitScriptIdList()]

  security.declareProtected(Permissions.AccessContentsInformation,
                            'getActivateScriptIdList')
  def getActivateScriptIdList(self):
    """
    returns the list of activate script ids
    """
    return [path.split('/')[-1] for path in self.getActivateScriptList()]

  security.declareProtected(Permissions.AccessContentsInformation,
                            'getActivateScriptValueList')
  def getActivateScriptValueList(self):
    """
    returns the list of activate script values
    """
    parent = self.getParentValue()
    return [parent._getOb(transition_id) for transition_id
            in self.getActivateScriptIdList()]

  # XXX(PERF): hack to see Category Tool responsability in new workflow slowness
  security.declareProtected(Permissions.AccessContentsInformation,
                            'getActivateScriptList')
  def getActivateScriptList(self):
    """
    returns the list of activate script
    """
    prefix_length = len('activate_script/')
    return [path[prefix_length:] for path in self.getCategoryList()
            if path.startswith('activate_script/')]

  # XXX(PERF): hack to see Category Tool responsability in new workflow slowness
  security.declareProtected(Permissions.AccessContentsInformation,
                            'getBeforeCommitScriptList')
  def getBeforeCommitScriptList(self):
    """
    returns the list of before commit script
    """
    prefix_length = len('before_commit_script/')
    return [path[prefix_length:] for path in self.getCategoryList()
            if path.startswith('before_commit_script/')]