Esempio n. 1
0
 def send(self, from_url, to_url, xml, sync_id, content_type):
   to_address = to_url[len('mailto:'):]
   from_address = from_url[len('mailto:'):]
   try:
     getSite().sendMail(from_address, to_address, sync_id, xml)
   except:
     raise ConnectionError
Esempio n. 2
0
 def runGetAndActivate(self, subscription, tag, after_method_id=None):
   """
   Launch the browsing of GID that will call the generation of syncml commands
   """
   activate_kw = {
     'activity' : 'SQLQueue',
     'after_method_id' : after_method_id,
     'tag' :tag,
     'priority' :ACTIVITY_PRIORITY
     }
   pref = getSite().portal_preferences
   subscription.getAndActivate(
     callback="sendSyncCommand",
     activate_kw=activate_kw,
     packet_size=pref.getPreferredDocumentRetrievedPerActivityCount(),
     activity_count=pref.getPreferredRetrievalActivityCount(),
     )
   # then send the final message of this sync part
   if pref.getPreferredCheckDeleteAtEnd():
     subscription.activate(after_tag=tag,
                         priority=ACTIVITY_PRIORITY+1).getDeletedSyncMLData()
   else:
     subscription.activate(after_tag=tag,
                           priority=ACTIVITY_PRIORITY+1)._sendFinalMessage()
   return True
Esempio n. 3
0
 def runGetAndActivate(self, subscription, tag, after_method_id=None):
   """
   Generate tag and method parameter and call the getAndActivate method
   """
   activate_kw = {
     'activity' : 'SQLQueue',
     'after_method_id' : after_method_id,
     'tag' :tag,
     'priority' :ACTIVITY_PRIORITY
     }
   method_kw = {
     'subscription_path' : subscription.getRelativeUrl(),
     }
   pref = getSite().portal_preferences
   count = subscription.getAndActivate(
     callback="sendSyncCommand",
     method_kw=method_kw,
     activate_kw=activate_kw,
     packet_size=pref.getPreferredDocumentRetrievedPerActivityCount(),
     activity_count=pref.getPreferredRetrievalActivityCount(),
     )
   # Then get deleted document
   # this will send also the final message of this sync part
   subscription.activate(after_tag=tag)._getDeletedData()
   return True
Esempio n. 4
0
def checkAlertCommand(syncml_request):
  """
  This parse the alert commands received and return a
  dictionnary mapping database to sync mode
  """
  database_alert_list = []
  # XXX To be moved on engine
  search = getSite().portal_categories.syncml_alert_code.searchFolder
  for alert in syncml_request.alert_list:
    if alert["data"] == "222":
      # 222 is for asking next message, do not care
      continue
    # Retrieve the category
    # XXX Categories must be redefined, ID must be code, not title so
    # that we can drop the use of searchFolder
    alert_code_category_list = search(reference=alert['data'])
    if len(alert_code_category_list) == 1:
      alert_code_category = alert_code_category_list[0].getId()
    else:
      # Must return (405) Command not allowed
      raise NotImplementedError("Alert code is %s, got %s category" %
                                (alert['data'],
                                 len(alert_code_category_list)))
    # Copy the whole dict & add the category id
    alert["code"] = alert_code_category
    database_alert_list.append(alert)

  return database_alert_list
Esempio n. 5
0
 def __call__(self, *args, **kw):
     portal = getSite()
     method_name = "SQLConnector_%s" % (self._method)
     method = getattr(portal, method_name, None)
     if method:
         response = method(*args, **kw)
         return method.absolute_url(), response
     else:
         raise ConnectionError("Method %s does not exist" % (method_name))
Esempio n. 6
0
def resolveSyncmlAlertCode(category_id):
  """Return reference of syncml_alert_code category
  """
  try:
    return str(int(category_id))
  except ValueError:
    return getSite().portal_categories.getCategoryValue(
            category_id,
            base_category='syncml_alert_code').getReference()
Esempio n. 7
0
File: Form.py Progetto: poses/erp5
  def clear(self):
    super(FieldValueCacheDict, self).clear()

    from Products.ERP5.ERP5Site import getSite
    try:
      portal = getSite()
    except IndexError:
      pass
    else:
      portal.newCacheCookie('form_field_value_cache')
      self._last_sync = portal.getCacheCookie('form_field_value_cache')
Esempio n. 8
0
  def get_source(self, fullname):
    """
    Get the source code of the given module name from the ID defined on the
    dynamic module (setting getTextContent() on the module directly may not
    work properly upon reset and there is no need for performance there as it
    is only used for traceback or pdb anyway)
    """
    module = __import__(fullname, fromlist=[fullname.rsplit('.', 1)[0]],
                        level=0)

    return getattr(getSite().portal_components,
                   module.__file__[1:-1]).getTextContent(validated_only=True)
 def resetDynamic(self, method_call_object, *args, **kw):
   """
   Call resetDynamicDocuments at the end of the transaction
   """
   from Products.ERP5.ERP5Site import getSite
   # method_call_object might be an unwrapped DCWorflowDefinition method,
   # no even belonging to a container.
   portal = getSite()
   types_tool = getattr(portal, 'portal_types', None)
   if types_tool is None:
     return
   types_tool.resetDynamicDocumentsOnceAtTransactionBoundary()
Esempio n. 10
0
    def get_source(self, fullname):
        """
    Get the source code of the given module name from the ID defined on the
    dynamic module (setting getTextContent() on the module directly may not
    work properly upon reset and there is no need for performance there as it
    is only used for traceback or pdb anyway)
    """
        module = __import__(fullname,
                            fromlist=[fullname.rsplit('.', 1)[0]],
                            level=0)

        return getattr(
            getSite().portal_components,
            module.__file__[1:-1]).getTextContent(validated_only=True)
Esempio n. 11
0
def _buildAstroidModuleFromComponentModuleName(modname):
    from Products.ERP5.ERP5Site import getSite
    from Acquisition import aq_base
    portal = getSite()
    component_tool = aq_base(portal.portal_components)
    component_obj = None
    component_id = modname[len('erp5.component.'):]
    if '_version' in modname:
        try:
            obj = getattr(component_tool,
                          component_id.replace('_version', '', 1))
        except AttributeError:
            raise AstroidBuildingException()
        if obj.getValidationState() in ('modified', 'validated'):
            component_obj = obj
        else:
            raise AstroidBuildingException()

    else:
        try:
            package, reference = component_id.split('.', 1)
        except ValueError:
            raise AstroidBuildingException()
        for version in portal.getVersionPriorityNameList():
            try:
                obj = getattr(component_tool,
                              '%s.%s.%s' % (package, version, reference))
            except AttributeError:
                continue

            if obj.getValidationState() in ('modified', 'validated'):
                version_modname = 'erp5.component.%s.%s_version.%s' % (
                    package, version, reference)
                module = MANAGER.astroid_cache.get(
                    version_modname,
                    _buildAstroidModuleFromComponentModuleName(
                        version_modname))
                MANAGER.astroid_cache[modname] = module
                return module

    if component_obj is None:
        raise AstroidBuildingException()

    # module_build() could also be used but this requires importing
    # the ZODB Component and also monkey-patch it to support PEP-302
    # for __file__ starting with '<'
    module = AstroidBuilder(MANAGER).string_build(
        component_obj.getTextContent(validated_only=True), modname)
    return module
Esempio n. 12
0
  def __call__(self, *args, **kw):
    portal = getSite()
    method_name = "DocumentConnector_%s" %(self._method)
    method = getattr(portal, method_name, None)
    kw["reference"] = self._conn.reference
    if method:
      response = method(*args, **kw)
      return method.absolute_url(), response
##       try:
##       except ValueError, msg:
##         raise ConnectionError(msg)
##       except Exception, msg:
##         raise ConnectionError(msg)
    else:
      raise ConnectionError("Method %s does not exist" %(method_name))
Esempio n. 13
0
File: Form.py Progetto: poses/erp5
  def __getitem__(self, cache_id):
    from Products.ERP5.ERP5Site import getSite
    try:
      portal = getSite()
    except IndexError:
      pass
    else:
      cookie = portal.getCacheCookie('form_field_value_cache')
      if cookie != self._last_sync:
        LOG("ERP5Form.Form", 0, "Resetting form field value cache")
        self._last_sync = cookie
        self.clear()
        raise KeyError('Field cache is outdated and has been reset')

    return super(FieldValueCacheDict, self).__getitem__(cache_id)
Esempio n. 14
0
    def _registry_dict(self):
        """
    Create the component registry, this is very similar to
    Products.ERP5Type.document_class_registry and avoids checking whether a
    Component exists at each call at the expense of being slower when being
    re-generated after a reset. Moreover, it allows to handle reference
    easily.
    """
        if not self.__registry_dict:
            portal = getSite()

            try:
                component_tool = portal.portal_components
            # When installing ERP5 site, erp5_core_components has not been installed
            # yet, thus this will obviously failed...
            #
            # XXX-arnau: Is this needed as it is now done in synchronizeDynamicModules?
            except AttributeError:
                return {}

            version_priority_set = set(portal.getVersionPriorityNameList())

            # objectValues should not be used for a large number of objects, but
            # this is only done upon reset, moreover using the Catalog is too risky
            # as it lags behind and depends upon objects being reindexed
            for component in component_tool.objectValues(
                    portal_type=self._portal_type):
                # Only consider modified or validated states as state transition will
                # be handled by component_validation_workflow which will take care of
                # updating the registry
                try:
                    validation_state_tuple = component.getValidationState()
                except AttributeError:
                    # XXX: Accessors may have not been generated yet
                    pass
                else:
                    if validation_state_tuple in ('modified', 'validated'):
                        version = component.getVersion(validated_only=True)
                        # The versions should have always been set on ERP5Site property
                        # beforehand
                        if version in version_priority_set:
                            reference = component.getReference(
                                validated_only=True)
                            self.__registry_dict.setdefault(
                                reference, {})[version] = (component.getId(),
                                                           component.getUid())

        return self.__registry_dict
Esempio n. 15
0
 def runApplySyncCommand(self, subscription, syncml_request, tag):
     """
 Launch the apply sync command in activity
 """
     send_response = subscription.getSyncmlAlertCode(
     ) != "refresh_from_client_only"
     if send_response and len(syncml_request.sync_command_list):
         # Generate a list of responses ID here to be scallable
         response_id_list = subscription.getNextMessageIdList(
             id_count=len(syncml_request.sync_command_list))
         response_id_list.reverse()
     else:
         response_id_list = [
             None for x in xrange(len(syncml_request.sync_command_list))
         ]
     split = getSite(
     ).portal_preferences.getPreferredSyncActionPerActivityCount()
     if not split:  # We do not use activities
         if send_response:
             syncml_response = subscription.generateBaseResponse()
         else:
             syncml_response = None
         subscription.applyActionList(syncml_request, syncml_response)
         if syncml_response:
             subscription.activate(
                 activity="SQLQueue",
                 priority=ACTIVITY_PRIORITY,
                 tag=subscription.getRelativeUrl()).sendMessage(
                     xml=str(syncml_response))
     else:
         # XXX For now always split by one
         activate = subscription.activate
         activate_kw = {
             "activity": "SQLQueue",
             "priority": ACTIVITY_PRIORITY,
             "tag": tag,
             "group_method_id": None,
             "group_method_cost": 1. / float(split),
         }
         for action in syncml_request.sync_command_list:
             syncml_logger.info("---> launch action in activity %s" %
                                (action, ))
             activate(**activate_kw).applySyncCommand(
                 response_message_id=response_id_list.pop(),
                 activate_kw=activate_kw,
                 action=action,
                 request_message_id=syncml_request.header["message_id"],
                 simulate=False)
Esempio n. 16
0
    def __load_module(self, fullname):
        """
    Load a module with given fullname (see PEP 302) if it's not already in
    sys.modules. It is assumed that imports are filtered properly in
    find_module().

    Also, when the top-level Component module is requested
    (erp5.component.XXX.COMPONENT_NAME), the Component with the highest
    version priority will be loaded into the Version package
    (erp5.component.XXX.VERSION_version.COMPONENT_NAME. Therefore, the
    top-level Component module will just be an alias of the versioned one.

    As per PEP-302, raise an ImportError if the Loader could not load the
    module for any reason...
    """
        site = getSite()

        if fullname.startswith('Products.'):
            module_fullname_filesystem = fullname
            import erp5.component
            fullname = erp5.component.filesystem_import_dict[
                module_fullname_filesystem]
        else:
            module_fullname_filesystem = None

        name = fullname[len(self._namespace_prefix):]

        # if only Version package (erp5.component.XXX.VERSION_version) is
        # requested to be loaded, then create it if necessary
        if name.endswith('_version'):
            version = name[:-self.__version_suffix_len]
            return (version in site.getVersionPriorityNameList()
                    and self._getVersionPackage(version) or None)

        module_fullname_alias = None
        version_package_name = name[:-self.__version_suffix_len]

        # If a specific version of the Component has been requested
        if '.' in name:
            try:
                version, name = name.split('.')
                version = version[:-self.__version_suffix_len]
            except ValueError, error:
                raise ImportError("%s: should be %s.VERSION.COMPONENT_REFERENCE (%s)" % \
                                    (fullname, self._namespace, error))

            component_id = "%s.%s.%s" % (self._id_prefix, version, name)
Esempio n. 17
0
  def _registry_dict(self):
    """
    Create the component registry, this is very similar to
    Products.ERP5Type.document_class_registry and avoids checking whether a
    Component exists at each call at the expense of being slower when being
    re-generated after a reset. Moreover, it allows to handle reference
    easily.
    """
    if not self.__registry_dict:
      portal = getSite()

      try:
        component_tool = portal.portal_components
      # When installing ERP5 site, erp5_core_components has not been installed
      # yet, thus this will obviously failed...
      #
      # XXX-arnau: Is this needed as it is now done in synchronizeDynamicModules?
      except AttributeError:
        return {}

      version_priority_set = set(portal.getVersionPriorityNameList())

      # objectValues should not be used for a large number of objects, but
      # this is only done upon reset, moreover using the Catalog is too risky
      # as it lags behind and depends upon objects being reindexed
      for component in component_tool.objectValues(portal_type=self._portal_type):
        # Only consider modified or validated states as state transition will
        # be handled by component_validation_workflow which will take care of
        # updating the registry
        try:
          validation_state_tuple = component.getValidationState()
        except AttributeError:
          # XXX: Accessors may have not been generated yet
          pass
        else:
          if validation_state_tuple in ('modified', 'validated'):
            version = component.getVersion(validated_only=True)
            # The versions should have always been set on ERP5Site property
            # beforehand
            if version in version_priority_set:
              reference = component.getReference(validated_only=True)
              self.__registry_dict.setdefault(reference, {})[version] = (
                component.getId(),
                component.getUid())

    return self.__registry_dict
Esempio n. 18
0
  def testConstraintAfterClosingZODBConnection(self):
    """
    Make sure that constraint works even if ZODB connection close.
    This test is added for the bug #20110628-ABAA76.
    """
    # Open new connection and add a new constraint.
    db = self.app._p_jar.db()
    con = db.open()
    app = con.root()['Application'].__of__(self.app.aq_parent)
    portal = app[self.getPortalName()]
    from Products.ERP5.ERP5Site import getSite, setSite
    old_site = getSite()
    setSite(portal)

    import erp5
    dummy = getattr(erp5.portal_type, 'TALES Constraint')(id='dummy')
    portal.portal_property_sheets.TestMigration._setObject('dummy', dummy)
    dummy = portal.portal_property_sheets.TestMigration.dummy
    dummy.edit(reference='test_dummy_constraint',
               expression='python: object.getTitle() == "my_tales_constraint_title"')
    dummy.Predicate_view()

    transaction.commit()

    # Recreate class with a newly added constraint
    synchronizeDynamicModules(portal, force=True)
    # Load test_module
    test_module = getattr(portal, 'Test Migration')
    test_module.objectValues()
    # Then close this new connection.
    transaction.abort()
    con.close()
    # This code depends on ZODB implementation.
    for i in db.pool.available[:]:
      if i[1] == con:
        db.pool.available.remove(i)
    db.pool.all.remove(con)
    del con

    # Back to the default connection.
    transaction.abort()
    self.app._p_jar._resetCache()
    setSite(old_site)

    # Call checkConsistency and make sure that ConnectionStateError does not occur.
    self.assert_(self.test_module.checkConsistency())
Esempio n. 19
0
    def __call__(self, *args, **kw):
        portal = getSite()
        method_name = "DocumentConnector_%s" % (self._method)
        method = getattr(portal, method_name, None)
        kw["reference"] = self._conn.reference
        if method:
            response = method(*args, **kw)
            return method.absolute_url(), response


##       try:
##       except ValueError, msg:
##         raise ConnectionError(msg)
##       except Exception, msg:
##         raise ConnectionError(msg)
        else:
            raise ConnectionError("Method %s does not exist" % (method_name))
Esempio n. 20
0
  def runApplySyncCommand(self, subscription, syncml_request, tag):
    """
    Launch the apply sync command in activity
    """
    send_response = subscription.getSyncmlAlertCode() != "refresh_from_client_only"
    if send_response and len(syncml_request.sync_command_list):
      # Generate a list of responses ID here to be scallable
      response_id_list = subscription.getNextMessageIdList(
        id_count=len(syncml_request.sync_command_list))
      response_id_list.reverse()
    else:
      response_id_list = [None for x in
                          xrange(len(syncml_request.sync_command_list))]
    split = getSite().portal_preferences.getPreferredSyncActionPerActivityCount()
    if not split:
      if send_response:
        syncml_response = self._generateBaseResponse(subscription)
      else:
        syncml_response = None
      subscription.applyActionList(syncml_request, syncml_response)
      if syncml_response:
        subscription.activate(
          activity="SQLQueue",
          priority=ACTIVITY_PRIORITY,
          tag=subscription.getRelativeUrl()).sendMessage(xml=str(syncml_response))

    else:
      # XXX For now always split by one
      activate = subscription.getPortalObject().portal_synchronizations.activate
      activate_kw = {
        "activity" :"SQLQueue",
        "priority" : ACTIVITY_PRIORITY,
        "tag" : tag,
        "group_method_id" : None,
        "group_method_cost" : 1./float(split),
        }
      for action in syncml_request.sync_command_list:
        syncml_logger.info("---> launch action in activity %s" %(action,))
        activate(**activate_kw).applySyncCommand(
          subscription_path=subscription.getRelativeUrl(),
          response_message_id=response_id_list.pop(),
          activate_kw=activate_kw,
          action=action,
          request_message_id=syncml_request.header["message_id"],
          simulate=False)
Esempio n. 21
0
 def _fixPortalTypeBeforeMigration(self, portal_type):
   # Tools are causing problems: they used to have no type_class, or wrong
   # type_class, or sometimes have no type definitions at all.
   # Fix type definition if possible before any migration.
   from Products.ERP5.ERP5Site import getSite
   types_tool = getSite().portal_types
   type_definition = getattr(types_tool, portal_type, None)
   if type_definition is not None and \
      type_definition.getTypeClass() in ('Folder', None):
     # wrong type_class, fix it manually:
     from Products.ERP5Type import document_class_registry
     try:
       type_definition.type_class = document_class_registry[
         portal_type.replace(' ', '')]
     except KeyError:
       LOG('BaseTool._migratePortalType', WARNING,
           'No document class could be found for portal type %r'
           % portal_type)
Esempio n. 22
0
  def find_module(self, fullname, path=None):
    """
    PEP-302 Finder which determines which packages and modules will be handled
    by this class. It must be done carefully to avoid handling packages and
    modules the Loader (load_module()) will not be handled later as the latter
    would raise ImportError...

    As per PEP-302, returns None if this Finder cannot handle the given name,
    perhaps because the Finder of another Component Package could do it or
    because this is a filesystem module...
    """
    # Ignore imports with a path which are filesystem-only and any
    # absolute imports which does not start with this package prefix,
    # None there means that "normal" sys.path will be used
    if path or not fullname.startswith(self._namespace_prefix):
      return None

    site = getSite()

    # __import__ will first try a relative import, for example
    # erp5.component.XXX.YYY.ZZZ where erp5.component.XXX.YYY is the current
    # Component where an import is done
    name = fullname[len(self._namespace_prefix):]
    if '.' in name:
      try:
        version, name = name.split('.')
        version = version[:-self.__version_suffix_len]
      except ValueError:
        return None

      try:
        self._registry_dict[name][version]
      except KeyError:
        return None

    # Skip unavailable components, otherwise Products for example could be
    # wrongly considered as importable and thus the actual filesystem class
    # ignored
    elif (name not in self._registry_dict and
          name[:-self.__version_suffix_len] not in site.getVersionPriorityNameList()):
      return None

    return self
Esempio n. 23
0
 def _fixPortalTypeBeforeMigration(self, portal_type):
     # Tools are causing problems: they used to have no type_class, or wrong
     # type_class, or sometimes have no type definitions at all.
     # Fix type definition if possible before any migration.
     from Products.ERP5.ERP5Site import getSite
     types_tool = getSite().portal_types
     type_definition = getattr(types_tool, portal_type, None)
     if type_definition is not None and \
        type_definition.getTypeClass() in ('Folder', None):
         # wrong type_class, fix it manually:
         from Products.ERP5Type import document_class_registry
         try:
             type_definition.type_class = document_class_registry[
                 portal_type.replace(' ', '')]
         except KeyError:
             LOG(
                 'BaseTool._migratePortalType', WARNING,
                 'No document class could be found for portal type %r' %
                 portal_type)
Esempio n. 24
0
    def getPortal(self):
        """Returns the portal object, i.e. the "fixture root".

      Rewrap the portal in an independant request for this test.
      """
        if self.portal is not None:
            return self.portal

        # _module_cache_set is used to keep a reference to the code of modules
        # before they get reloaded. As we will use another request we need to
        # make sure that we still have a reference to _module_cache_set so that
        # it does not get garbage collected.
        module_cache_set = getattr(get_request(), '_module_cache_set', None)

        from Products.ERP5.ERP5Site import getSite
        site = getSite()
        # reconstruct the acquistion chain with an independant request.
        #   RequestContainer -> Application -> Site
        from Testing.ZopeTestCase.utils import makerequest
        portal = getattr(makerequest(site.aq_parent), site.getId())

        if module_cache_set:
            portal.REQUEST._module_cache_set = module_cache_set

        # Make the various get_request patches return this request.
        # This is for ERP5TypeTestCase patch
        from Testing.ZopeTestCase.connections import registry
        if registry:
            registry._conns[-1] = portal

        # This is for Localizer patch
        from Products.Localizer import patches
        request = portal.REQUEST
        with patches._requests_lock:
            patches._requests[thread.get_ident()] = request

        # Make live tests run under the same server URL than the host instance.
        if _request_server_url:
            request['SERVER_URL'] = _request_server_url
            request._resetURLS()

        self.portal = portal
        return portal
Esempio n. 25
0
    def getPortal(self):
      """Returns the portal object, i.e. the "fixture root".

      Rewrap the portal in an independant request for this test.
      """
      if self.portal is not None:
        return self.portal

      # _module_cache_set is used to keep a reference to the code of modules
      # before they get reloaded. As we will use another request we need to
      # make sure that we still have a reference to _module_cache_set so that
      # it does not get garbage collected.
      module_cache_set = getattr(get_request(), '_module_cache_set', None)

      from Products.ERP5.ERP5Site import getSite
      site = getSite()
      # reconstruct the acquistion chain with an independant request.
      #   RequestContainer -> Application -> Site
      from Testing.ZopeTestCase.utils import makerequest
      portal = getattr(makerequest(site.aq_parent), site.getId())

      if module_cache_set:
        portal.REQUEST._module_cache_set = module_cache_set

      # Make the various get_request patches return this request.
      # This is for ERP5TypeTestCase patch
      from Testing.ZopeTestCase.connections import registry
      if registry:
        registry._conns[-1] = portal

      # This is for Localizer patch
      from Products.Localizer import patches
      request = portal.REQUEST
      with patches._requests_lock:
        patches._requests[thread.get_ident()] = request

      # Make live tests run under the same server URL than the host instance.
      if _request_server_url:
        request['SERVER_URL'] = _request_server_url
        request._resetURLS()

      self.portal = portal
      return portal
Esempio n. 26
0
  def __load_module(self, fullname):
    """
    Load a module with given fullname (see PEP 302) if it's not already in
    sys.modules. It is assumed that imports are filtered properly in
    find_module().

    Also, when the top-level Component module is requested
    (erp5.component.XXX.COMPONENT_NAME), the Component with the highest
    version priority will be loaded into the Version package
    (erp5.component.XXX.VERSION_version.COMPONENT_NAME. Therefore, the
    top-level Component module will just be an alias of the versioned one.

    As per PEP-302, raise an ImportError if the Loader could not load the
    module for any reason...
    """
    site = getSite()
    name = fullname[len(self._namespace_prefix):]

    # if only Version package (erp5.component.XXX.VERSION_version) is
    # requested to be loaded, then create it if necessary
    if name.endswith('_version'):
      version = name[:-self.__version_suffix_len]
      return (version in site.getVersionPriorityNameList() and
              self._getVersionPackage(version) or None)

    module_fullname_alias = None
    version_package_name = name[:-self.__version_suffix_len]

    # If a specific version of the Component has been requested
    if '.' in name:
      try:
        version, name = name.split('.')
        version = version[:-self.__version_suffix_len]
      except ValueError, error:
        raise ImportError("%s: should be %s.VERSION.COMPONENT_REFERENCE (%s)" % \
                            (fullname, self._namespace, error))

      try:
        component_id = self._registry_dict[name][version][0]
      except KeyError:
        raise ImportError("%s: version %s of Component %s could not be found" % \
                            (fullname, version, name))
Esempio n. 27
0
  def translate(self):
    """
    Return the translated message. If the original is a string object,
    the return value is a string object. If it is a unicode object,
    the return value is a unicode object.
    """
    message = self.message
    if self.domain is None:
      # Map the translated string with given parameters
      if type(self.mapping) is dict:
        if isinstance(message, six.text_type) :
          message = message.encode('utf-8')
        message = Template(message).substitute(self.mapping)
    else:
      from Products.ERP5.ERP5Site import getSite
      request = Globals.get_request()
      translation_service = getGlobalTranslationService()
      if self.mapping:
        unicode_mapping = {}
        for k, v in six.iteritems(self.mapping):
          if isinstance(v, str):
            v = v.decode('utf-8')
          unicode_mapping[k] = v
      else:
        unicode_mapping = self.mapping
      translated_message = translation_service.translate(
                                             self.domain,
                                             message,
                                             mapping=unicode_mapping,
                                             context=getSite(request),
                                             default=self.default)
      if translated_message is not None:
        message = translated_message

    if isinstance(self.message, str):
      if isinstance(message, six.text_type):
        message = message.encode('utf-8')
    elif isinstance(message, str):
      message = message.decode('utf-8')

    return message
Esempio n. 28
0
  def translate(self):
    """
    Return the translated message. If the original is a string object,
    the return value is a string object. If it is a unicode object,
    the return value is a unicode object.
    """
    message = self.message
    if self.domain is None:
      # Map the translated string with given parameters
      if type(self.mapping) is dict:
        if isinstance(message, unicode) :
          message = message.encode('utf-8')
        message = Template(message).substitute(self.mapping)
    else:
      from Products.ERP5.ERP5Site import getSite
      request = Globals.get_request()
      translation_service = getGlobalTranslationService()
      if self.mapping:
        unicode_mapping = {}
        for k, v in self.mapping.iteritems():
          if isinstance(v, str):
            v = v.decode('utf-8')
          unicode_mapping[k] = v
      else:
        unicode_mapping = self.mapping
      translated_message = translation_service.translate(
                                             self.domain,
                                             message,
                                             mapping=unicode_mapping,
                                             context=getSite(request),
                                             default=self.default)
      if translated_message is not None:
        message = translated_message

    if isinstance(self.message, str):
      if isinstance(message, unicode):
        message = message.encode('utf-8')
    elif isinstance(message, str):
      message = message.decode('utf-8')

    return message
Esempio n. 29
0
def formatLine(self, tb, *args, **kwargs):
  """
  Monkey patched to add links to ZODB Components and Python Script. The
  regex part is a bit dirty but there is no other way besides of a copy/paste
  of formatLine()...
  """
  f = tb.tb_frame
  filename = f.f_code.co_filename.replace('<', '').replace('>', '')
  lineno = tb.tb_lineno
  f_globals = f.f_globals
  line_str = HTMLExceptionFormatter_formatLine(self, tb, *args, **kwargs)

  from Products.ERP5.ERP5Site import getSite
  try:
    portal_absolute_url = getSite().absolute_url()

    import re
    # Use the supplement defined in the module.
    # This is used by Scripts (Python).
    if '__traceback_supplement__' in f_globals:
      tbs = f_globals['__traceback_supplement__']
      line_str = re.sub(
        '^(<li>\s*)(Module script,[^<]*)(.*)$',
        r'\1<a href="%s/manage_main?line=%s">\2</a>\3' % (tbs[1].absolute_url(),
                                                          lineno),
        line_str,
        flags=re.DOTALL)

    else:
      line_str = re.sub(
        '^(<li>\s*)(Module erp5\.component\.[^<]*)(.*)$',
        r'\1<a href="/%s/%s?line=%s">\2</a>\3' % (portal_absolute_url,
                                                  filename,
                                                  lineno),
        line_str,
        flags=re.DOTALL)

  except Exception, e:
    pass
Esempio n. 30
0
def formatLine(self, tb, *args, **kwargs):
    """
  Monkey patched to add links to ZODB Components and Python Script. The
  regex part is a bit dirty but there is no other way besides of a copy/paste
  of formatLine()...
  """
    f = tb.tb_frame
    filename = f.f_code.co_filename.replace('<', '').replace('>', '')
    lineno = tb.tb_lineno
    f_globals = f.f_globals
    line_str = HTMLExceptionFormatter_formatLine(self, tb, *args, **kwargs)

    from Products.ERP5.ERP5Site import getSite
    try:
        portal_absolute_url = getSite().absolute_url()

        import re
        # Use the supplement defined in the module.
        # This is used by Scripts (Python).
        if '__traceback_supplement__' in f_globals:
            tbs = f_globals['__traceback_supplement__']
            line_str = re.sub('^(<li>\s*)(Module script,[^<]*)(.*)$',
                              r'\1<a href="%s/manage_main?line=%s">\2</a>\3' %
                              (tbs[1].absolute_url(), lineno),
                              line_str,
                              flags=re.DOTALL)

        else:
            line_str = re.sub('^(<li>\s*)(Module erp5\.component\.[^<]*)(.*)$',
                              r'\1<a href="/%s/%s?line=%s">\2</a>\3' %
                              (portal_absolute_url, filename, lineno),
                              line_str,
                              flags=re.DOTALL)

    except Exception as e:
        pass

    return line_str
Esempio n. 31
0
def unrestricted_apply(function, args=(), kw={}):  # XXX-JPS: naming
    """Function to bypass all security checks

    This function is as dangerous as 'UnrestrictedMethod' decorator. Read its
    docstring for more information. Never use this, until you are 100% certain
    that you have no other way.
    """
    security_manager = getSecurityManager()
    user = security_manager.getUser()
    anonymous = (user.getUserName() == 'Anonymous User')
    if user.getId() is None and not anonymous:
        # This is a special user, thus the user is not allowed to own objects.
        super_user = UnrestrictedUser(user.getUserName(), None,
                                      user.getRoles(), user.getDomains())
    else:
        try:
            # XXX is it better to get roles from the parent (i.e. portal)?
            uf = user.aq_inner.aq_parent
        except AttributeError:
            # XXX: local imports are bad, getSite should be moved to ERP5Type.
            from Products.ERP5.ERP5Site import getSite
            uf = getSite().acl_users
        role_list = uf.valid_roles()
        if anonymous:
            # If the user is anonymous, use the id of the system user,
            # so that it would not be treated as an unauthorized user.
            user_id = str(system)
        else:
            user_id = user.getId()
        super_user = PrivilegedUser(user_id, None, role_list,
                                    user.getDomains()).__of__(uf)
    newSecurityManager(None, super_user)
    try:
        return apply(function, args, kw)
    finally:
        # Make sure that the original user is back.
        setSecurityManager(security_manager)
Esempio n. 32
0
def super_user():
    """Context manager to bypass all security checks

    This function is as dangerous as 'UnrestrictedMethod' decorator. Read its
    docstring for more information. Never use this, until you are 100% certain
    that you have no other way.
    """
    security_manager = getSecurityManager()
    user = security_manager.getUser()
    anonymous = (user.getUserName() == 'Anonymous User')
    if user.getId() is None and not anonymous:
      # This is a special user, thus the user is not allowed to own objects.
      super_user = UnrestrictedUser(user.getUserName(), None,
                                    user.getRoles(), user.getDomains())
    else:
      try:
        # XXX is it better to get roles from the parent (i.e. portal)?
        uf = user.aq_inner.aq_parent
      except AttributeError:
        # XXX: local imports are bad, getSite should be moved to ERP5Type.
        from Products.ERP5.ERP5Site import getSite
        uf = getSite().acl_users
      role_list = uf.valid_roles()
      if anonymous:
        # If the user is anonymous, use the id of the system user,
        # so that it would not be treated as an unauthorized user.
        user_id = str(system)
      else:
        user_id = user.getId()
      super_user = PrivilegedUser(user_id, None,
                                  role_list, user.getDomains()).__of__(uf)
    newSecurityManager(None, super_user)
    try:
      yield
    finally:
      # Make sure that the original user is back.
      setSecurityManager(security_manager)
Esempio n. 33
0
 def getPortal(self):
   """Returns the portal object, i.e. the "fixture root".
   """
   from Products.ERP5.ERP5Site import getSite
   return getSite(get_request())
Esempio n. 34
0
  def loadClass(cls):
    """
    - mro before load:
      erp5.portal_type.XXX, GhostBaseMetaClass instance, *TAIL
    - mro after:
      erp5.portal_type.XXX, *new_bases_fetched_from_ZODB
    """
    __traceback_info__ = cls.__name__
    # Do not load the class again if it has already been loaded
    if not cls.__isghost__:
      return

    # cls might be a subclass of a portal type class
    # we need to find the right class to change
    for klass in cls.__mro__:
      # XXX hardcoded, this doesnt look too good
      if klass.__module__ == "erp5.portal_type":
        break
    else:
      raise AttributeError("Could not find a portal type class in"
                           " class hierarchy")

    portal_type = klass.__name__
    from Products.ERP5.ERP5Site import getSite
    site = getSite()
    ERP5Base.aq_method_lock.acquire()
    try:
      try:
        class_definition = generatePortalTypeClass(site, portal_type)
      except AttributeError:
        LOG("ERP5Type.Dynamic", WARNING,
            "Could not access Portal Type Object for type %r"
            % portal_type, error=sys.exc_info())
        base_tuple = (ERP5BaseBroken, )
        portal_type_category_list = []
        attribute_dict = dict(_categories=[], constraints=[])
        interface_list = []
      else:
        base_tuple, portal_type_category_list, \
          interface_list, attribute_dict = class_definition

      klass.__isghost__ = False
      klass.__bases__ = base_tuple

      klass.resetAcquisition()

      for key, value in attribute_dict.iteritems():
        setattr(klass, key, value)

      if getattr(klass.__setstate__, 'im_func', None) is \
         persistent_migration.__setstate__:
        # optimization to reduce overhead of compatibility code
        klass.__setstate__ = persistent_migration.Base__setstate__

      for interface in interface_list:
        classImplements(klass, interface)

      # skip this during the early Base Type / Types Tool generation
      # because they dont have accessors, and will mess up
      # workflow methods. We KNOW that we will re-load this type anyway
      if len(base_tuple) > 1:
        klass.generatePortalTypeAccessors(site, portal_type_category_list)
        # need to set %s__roles__ for generated methods
        cls.setupSecurity()

    except Exception:
      import traceback; traceback.print_exc()
      raise
    finally:
      ERP5Base.aq_method_lock.release()
Esempio n. 35
0
  def __load_module(self, fullname):
    """
    Load a module with given fullname (see PEP 302) if it's not already in
    sys.modules. It is assumed that imports are filtered properly in
    find_module().

    Also, when the top-level Component module is requested
    (erp5.component.XXX.COMPONENT_NAME), the Component with the highest
    version priority will be loaded into the Version package
    (erp5.component.XXX.VERSION_version.COMPONENT_NAME. Therefore, the
    top-level Component module will just be an alias of the versioned one.

    As per PEP-302, raise an ImportError if the Loader could not load the
    module for any reason...
    """
    # In Python < 3.3, the import lock is a global lock for all modules:
    # http://bugs.python.org/issue9260
    #
    # So, release the import lock acquired by import statement on all hooks to
    # load objects from ZODB. When an object is requested from ZEO, it sends a
    # RPC request and lets the asyncore thread gets the reply. This reply may
    # be a tuple (PICKLE, TID), sent directly to the first thread, or an
    # Exception, which tries to import a ZODB module and thus creates a
    # deadlock because of the global import lock
    #
    # Also, handle the case where find_module() may be called without import
    # statement as it does change anything in sys.modules
    import_lock_held = True
    try:
      imp.release_lock()
    except RuntimeError:
      import_lock_held = False

    try:
      site = getSite()
      name = fullname[len(self._namespace_prefix):]

      # if only Version package (erp5.component.XXX.VERSION_version) is
      # requested to be loaded, then create it if necessary
      if name.endswith('_version'):
        version = name[:-self.__version_suffix_len]
        return (version in site.getVersionPriorityNameList() and
                self._getVersionPackage(version) or None)

      module_fullname_alias = None
      version_package_name = name[:-self.__version_suffix_len]

      # If a specific version of the Component has been requested
      if '.' in name:
        try:
          version, name = name.split('.')
          version = version[:-self.__version_suffix_len]
        except ValueError, error:
          raise ImportError("%s: should be %s.VERSION.COMPONENT_REFERENCE (%s)" % \
                              (fullname, self._namespace, error))

        try:
          component_id = self._registry_dict[name][version][0]
        except KeyError:
          raise ImportError("%s: version %s of Component %s could not be found" % \
                              (fullname, version, name))

      # Otherwise, find the Component with the highest version priority
      else:
Esempio n. 36
0
  def find_module(self, fullname, path=None):
    """
    PEP-302 Finder which determines which packages and modules will be handled
    by this class. It must be done carefully to avoid handling packages and
    modules the Loader (load_module()) will not be handled later as the latter
    would raise ImportError...

    As per PEP-302, returns None if this Finder cannot handle the given name,
    perhaps because the Finder of another Component Package could do it or
    because this is a filesystem module...
    """
    # Ignore imports with a path which are filesystem-only and any
    # absolute imports which does not start with this package prefix,
    # None there means that "normal" sys.path will be used
    if path or not fullname.startswith(self._namespace_prefix):
      return None

    import_lock_held = True
    try:
      imp.release_lock()
    except RuntimeError:
      import_lock_held = False

    # The import lock has been released, but as _registry_dict may be
    # initialized or cleared, no other Components should access this critical
    # region
    #
    # TODO-arnau: Too coarse-grain?
    aq_method_lock.acquire()
    try:
      site = getSite()

      # __import__ will first try a relative import, for example
      # erp5.component.XXX.YYY.ZZZ where erp5.component.XXX.YYY is the current
      # Component where an import is done
      name = fullname[len(self._namespace_prefix):]
      if '.' in name:
        try:
          version, name = name.split('.')
          version = version[:-self.__version_suffix_len]
        except ValueError:
          return None

        try:
          self._registry_dict[name][version]
        except KeyError:
          return None

      # Skip unavailable components, otherwise Products for example could be
      # wrongly considered as importable and thus the actual filesystem class
      # ignored
      elif (name not in self._registry_dict and
            name[:-self.__version_suffix_len] not in site.getVersionPriorityNameList()):
        return None

      return self

    finally:
      aq_method_lock.release()

      # Internal release of import lock at the end of import machinery will
      # fail if the hook is not acquired
      if import_lock_held:
        imp.acquire_lock()
Esempio n. 37
0
    def find_module(self, fullname, path=None):
        """
    PEP-302 Finder which determines which packages and modules will be handled
    by this class. It must be done carefully to avoid handling packages and
    modules the Loader (load_module()) will not be handled later as the latter
    would raise ImportError...

    As per PEP-302, returns None if this Finder cannot handle the given name,
    perhaps because the Finder of another Component Package could do it or
    because this is a filesystem module...
    """
        # Ignore imports with a path which are filesystem-only and any
        # absolute imports which does not start with this package prefix,
        # None there means that "normal" sys.path will be used
        if path or not fullname.startswith(self._namespace_prefix):
            return None

        import_lock_held = True
        try:
            imp.release_lock()
        except RuntimeError:
            import_lock_held = False

        try:
            site = getSite()

            # __import__ will first try a relative import, for example
            # erp5.component.XXX.YYY.ZZZ where erp5.component.XXX.YYY is the current
            # Component where an import is done
            name = fullname[len(self._namespace_prefix):]
            # name=VERSION_version.REFERENCE
            if '.' in name:
                try:
                    version, name = name.split('.')
                    version = version[:-self.__version_suffix_len]
                except ValueError:
                    return None

                id_ = "%s.%s.%s" % (self._id_prefix, version, name)
                # aq_base() because this should not go up to ERP5Site and trigger
                # side-effects, after all this only check for existence...
                try:
                    component_tool = aq_base(site.portal_components)
                except AttributeError:
                    # For old sites, just use FS Documents...
                    return None

                component = getattr(component_tool, id_, None)
                if component is None or component.getValidationState() not in (
                        'modified', 'validated'):
                    return None

            # Skip unavailable components, otherwise Products for example could be
            # wrongly considered as importable and thus the actual filesystem class
            # ignored
            #
            # name=VERSION_version
            elif name.endswith('_version'):
                if name[:-self.
                        __version_suffix_len] not in site.getVersionPriorityNameList(
                        ):
                    return None

            # name=REFERENCE
            else:
                try:
                    component_tool = aq_base(site.portal_components)
                except AttributeError:
                    # For old sites, just use FS Documents...
                    return None

                for version in site.getVersionPriorityNameList():
                    id_ = "%s.%s.%s" % (self._id_prefix, version, name)
                    component = getattr(component_tool, id_, None)
                    if component is not None and component.getValidationState(
                    ) in ('modified', 'validated'):
                        break
                else:
                    return None

            return self

        finally:
            # Internal release of import lock at the end of import machinery will
            # fail if the hook is not acquired
            if import_lock_held:
                imp.acquire_lock()
Esempio n. 38
0
    def __init__(self):
        """
    """
        from Products.ERP5.ERP5Site import getSite

        self.context = getSite()
Esempio n. 39
0
 def getPortal(self):
   """Returns the portal object, i.e. the "fixture root".
   """
   from Products.ERP5.ERP5Site import getSite
   return getSite(get_request())
Esempio n. 40
0
 def __init__(self):
     """
 """
     from Products.ERP5.ERP5Site import getSite
     self.context = getSite()
Esempio n. 41
0
 def send(self, to_url, data, sync_id, content_type):
   getSite().portal_synchronizations.readResponse(text=data,
                                                  sync_id=sync_id)
Esempio n. 42
0
    def __load_module(self, fullname):
        """
    Load a module with given fullname (see PEP 302) if it's not already in
    sys.modules. It is assumed that imports are filtered properly in
    find_module().

    Also, when the top-level Component module is requested
    (erp5.component.XXX.COMPONENT_NAME), the Component with the highest
    version priority will be loaded into the Version package
    (erp5.component.XXX.VERSION_version.COMPONENT_NAME. Therefore, the
    top-level Component module will just be an alias of the versioned one.

    As per PEP-302, raise an ImportError if the Loader could not load the
    module for any reason...
    """
        # In Python < 3.3, the import lock is a global lock for all modules:
        # http://bugs.python.org/issue9260
        #
        # So, release the import lock acquired by import statement on all hooks to
        # load objects from ZODB. When an object is requested from ZEO, it sends a
        # RPC request and lets the asyncore thread gets the reply. This reply may
        # be a tuple (PICKLE, TID), sent directly to the first thread, or an
        # Exception, which tries to import a ZODB module and thus creates a
        # deadlock because of the global import lock
        #
        # Also, handle the case where find_module() may be called without import
        # statement as it does change anything in sys.modules
        import_lock_held = True
        try:
            imp.release_lock()
        except RuntimeError:
            import_lock_held = False

        try:
            site = getSite()
            name = fullname[len(self._namespace_prefix):]

            # if only Version package (erp5.component.XXX.VERSION_version) is
            # requested to be loaded, then create it if necessary
            if name.endswith('_version'):
                version = name[:-self.__version_suffix_len]
                return (version in site.getVersionPriorityNameList()
                        and self._getVersionPackage(version) or None)

            module_fullname_alias = None
            version_package_name = name[:-self.__version_suffix_len]

            # If a specific version of the Component has been requested
            if '.' in name:
                try:
                    version, name = name.split('.')
                    version = version[:-self.__version_suffix_len]
                except ValueError, error:
                    raise ImportError("%s: should be %s.VERSION.COMPONENT_REFERENCE (%s)" % \
                                        (fullname, self._namespace, error))

                try:
                    component_id = self._registry_dict[name][version][0]
                except KeyError:
                    raise ImportError("%s: version %s of Component %s could not be found" % \
                                        (fullname, version, name))

            # Otherwise, find the Component with the highest version priority
            else:
Esempio n. 43
0
    def find_module(self, fullname, path=None):
        """
    PEP-302 Finder which determines which packages and modules will be handled
    by this class. It must be done carefully to avoid handling packages and
    modules the Loader (load_module()) will not be handled later as the latter
    would raise ImportError...

    As per PEP-302, returns None if this Finder cannot handle the given name,
    perhaps because the Finder of another Component Package could do it or
    because this is a filesystem module...
    """
        # Ignore imports with a path which are filesystem-only and any
        # absolute imports which does not start with this package prefix,
        # None there means that "normal" sys.path will be used
        if path or not fullname.startswith(self._namespace_prefix):
            return None

        import_lock_held = True
        try:
            imp.release_lock()
        except RuntimeError:
            import_lock_held = False

        # The import lock has been released, but as _registry_dict may be
        # initialized or cleared, no other Components should access this critical
        # region
        #
        # TODO-arnau: Too coarse-grain?
        aq_method_lock.acquire()
        try:
            site = getSite()

            # __import__ will first try a relative import, for example
            # erp5.component.XXX.YYY.ZZZ where erp5.component.XXX.YYY is the current
            # Component where an import is done
            name = fullname[len(self._namespace_prefix):]
            if '.' in name:
                try:
                    version, name = name.split('.')
                    version = version[:-self.__version_suffix_len]
                except ValueError:
                    return None

                try:
                    self._registry_dict[name][version]
                except KeyError:
                    return None

            # Skip unavailable components, otherwise Products for example could be
            # wrongly considered as importable and thus the actual filesystem class
            # ignored
            elif (name not in self._registry_dict
                  and name[:-self.__version_suffix_len]
                  not in site.getVersionPriorityNameList()):
                return None

            return self

        finally:
            aq_method_lock.release()

            # Internal release of import lock at the end of import machinery will
            # fail if the hook is not acquired
            if import_lock_held:
                imp.acquire_lock()
Esempio n. 44
0
    def loadClass(cls):
        """
    - mro before load:
      erp5.portal_type.XXX, GhostBaseMetaClass instance, *TAIL
    - mro after:
      erp5.portal_type.XXX, *new_bases_fetched_from_ZODB
    """
        __traceback_info__ = cls.__name__
        # Do not load the class again if it has already been loaded
        if not cls.__isghost__:
            return

        # cls might be a subclass of a portal type class
        # we need to find the right class to change
        for klass in cls.__mro__:
            # XXX hardcoded, this doesnt look too good
            if klass.__module__ == "erp5.portal_type":
                break
        else:
            raise AttributeError("Could not find a portal type class in"
                                 " class hierarchy")

        portal_type = klass.__name__
        from Products.ERP5.ERP5Site import getSite
        site = getSite()
        with aq_method_lock:
            try:
                class_definition = generatePortalTypeClass(site, portal_type)
            except AttributeError:
                LOG("ERP5Type.Dynamic",
                    WARNING,
                    "Could not access Portal Type Object for type %r" %
                    portal_type,
                    error=True)
                base_tuple = (ERP5BaseBroken, )
                portal_type_category_list = []
                attribute_dict = dict(_categories=[], constraints=[])
                interface_list = []
            else:
                base_tuple, portal_type_category_list, \
                  interface_list, attribute_dict = class_definition

            klass.__isghost__ = False
            klass.__bases__ = base_tuple

            klass.resetAcquisition()

            for key, value in attribute_dict.iteritems():
                setattr(klass, key, value)

            if getattr(klass.__setstate__, 'im_func', None) is \
               persistent_migration.__setstate__:
                # optimization to reduce overhead of compatibility code
                klass.__setstate__ = persistent_migration.Base__setstate__

            for interface in interface_list:
                classImplements(klass, interface)

            # skip this during the early Base Type / Types Tool generation
            # because they dont have accessors, and will mess up
            # workflow methods. We KNOW that we will re-load this type anyway
            if len(base_tuple) > 1:
                klass.generatePortalTypeAccessors(site,
                                                  portal_type_category_list)
                # need to set %s__roles__ for generated methods
                cls.setupSecurity()
Esempio n. 45
0
  def find_module(self, fullname, path=None):
    """
    PEP-302 Finder which determines which packages and modules will be handled
    by this class. It must be done carefully to avoid handling packages and
    modules the Loader (load_module()) will not be handled later as the latter
    would raise ImportError...

    As per PEP-302, returns None if this Finder cannot handle the given name,
    perhaps because the Finder of another Component Package could do it or
    because this is a filesystem module...
    """
    import erp5.component

    # ZODB Components
    if not path:
      if not fullname.startswith(self._namespace_prefix):
        return None
    # FS import backward compatibility
    else:
      try:
        fullname = erp5.component.filesystem_import_dict[fullname]
      except (TypeError, KeyError):
        return None
      else:
        if not fullname.startswith(self._namespace_prefix):
          return None

    import_lock_held = True
    try:
      imp.release_lock()
    except RuntimeError:
      import_lock_held = False

    try:
      site = getSite()

      if erp5.component.filesystem_import_dict is None:
        filesystem_import_dict = {}
        try:
          component_tool = aq_base(site.portal_components)
        except AttributeError:
          # For old sites, just use FS Documents...
          return None
        else:
          for component in component_tool.objectValues():
            if component.getValidationState() == 'validated':
              component_module_name = '%s.%s' % (component._getDynamicModuleNamespace(),
                                                 component.getReference())
              if component.getSourceReference() is not None:
                filesystem_import_dict[component.getSourceReference()] = component_module_name

              if component.getPortalType() == 'Document Component':
                filesystem_import_dict[('Products.ERP5Type.Document.' +
                                        component.getReference())] = component_module_name
          erp5.component.filesystem_import_dict = filesystem_import_dict

      # __import__ will first try a relative import, for example
      # erp5.component.XXX.YYY.ZZZ where erp5.component.XXX.YYY is the current
      # Component where an import is done
      name = fullname[len(self._namespace_prefix):]
      # name=VERSION_version.REFERENCE
      if '.' in name:
        try:
          version, name = name.split('.')
          version = version[:-self.__version_suffix_len]
        except ValueError:
          return None

        id_ = "%s.%s.%s" % (self._id_prefix, version, name)
        # aq_base() because this should not go up to ERP5Site and trigger
        # side-effects, after all this only check for existence...
        component = getattr(aq_base(site.portal_components), id_, None)
        if component is None or component.getValidationState() not in ('modified',
                                                                       'validated'):
          return None

      # Skip unavailable components, otherwise Products for example could be
      # wrongly considered as importable and thus the actual filesystem class
      # ignored
      #
      # name=VERSION_version
      elif name.endswith('_version'):
        if name[:-self.__version_suffix_len] not in site.getVersionPriorityNameList():
          return None

      # name=REFERENCE
      else:
        component_tool = aq_base(site.portal_components)
        for version in site.getVersionPriorityNameList():
          id_ = "%s.%s.%s" % (self._id_prefix, version, name)
          component = getattr(component_tool, id_, None)
          if component is not None and component.getValidationState() in ('modified',
                                                                          'validated'):
            break
        else:
          return None

      return self

    finally:
      # Internal release of import lock at the end of import machinery will
      # fail if the hook is not acquired
      if import_lock_held:
        imp.acquire_lock()
Esempio n. 46
0
  def __load_module(self, fullname):
    """
    Load a module with given fullname (see PEP 302) if it's not already in
    sys.modules. It is assumed that imports are filtered properly in
    find_module().

    Also, when the top-level Component module is requested
    (erp5.component.XXX.COMPONENT_NAME), the Component with the highest
    version priority will be loaded into the Version package
    (erp5.component.XXX.VERSION_version.COMPONENT_NAME. Therefore, the
    top-level Component module will just be an alias of the versioned one.

    As per PEP-302, raise an ImportError if the Loader could not load the
    module for any reason...
    """
    site = getSite()

    if fullname.startswith('Products.'):
      module_fullname_filesystem = fullname
      import erp5.component
      fullname = erp5.component.filesystem_import_dict[module_fullname_filesystem]
    else:
      module_fullname_filesystem = None

    name = fullname[len(self._namespace_prefix):]

    # if only Version package (erp5.component.XXX.VERSION_version) is
    # requested to be loaded, then create it if necessary
    if name.endswith('_version'):
      version = name[:-self.__version_suffix_len]
      return (version in site.getVersionPriorityNameList() and
              self._getVersionPackage(version) or None)

    module_fullname_alias = None
    version_package_name = name[:-self.__version_suffix_len]

    # If a specific version of the Component has been requested
    if '.' in name:
      try:
        version, name = name.split('.')
        version = version[:-self.__version_suffix_len]
      except ValueError as error:
        raise ImportError("%s: should be %s.VERSION.COMPONENT_REFERENCE (%s)" % \
                            (fullname, self._namespace, error))

      component_id = "%s.%s.%s" % (self._id_prefix, version, name)

    # Otherwise, find the Component with the highest version priority
    else:
      component_tool = aq_base(site.portal_components)
      # Version priority name list is ordered in descending order
      for version in site.getVersionPriorityNameList():
        component_id = "%s.%s.%s" % (self._id_prefix, version, name)
        component = getattr(component_tool, component_id, None)
        if component is not None and component.getValidationState() in ('modified',
                                                                        'validated'):
          break
      else:
        raise ImportError("%s: no version of Component %s in Site priority" % \
                            (fullname, name))

      module_fullname_alias = self._namespace + '.' + name

      # Check whether this module has already been loaded before for a
      # specific version, if so, just add it to the upper level
      try:
        module = getattr(getattr(self, version + '_version'), name)
      except AttributeError:
        pass
      else:
        setattr(self, name, module)
        sys.modules[module_fullname_alias] = module
        MNAME_MAP[module_fullname_alias] = module.__name__
        if module_fullname_filesystem:
          sys.modules[module_fullname_filesystem] = module
          MNAME_MAP[module_fullname_filesystem] = module.__name__
        return module

    component = getattr(site.portal_components, component_id)
    relative_url = component.getRelativeUrl()

    module_fullname = '%s.%s_version.%s' % (self._namespace, version, name)
    module = ModuleType(module_fullname, component.getDescription())

    source_code_str = component.getTextContent(validated_only=True)
    version_package = self._getVersionPackage(version)

    # All the required objects have been loaded, acquire import lock to modify
    # sys.modules and execute PEP302 requisites
    imp.acquire_lock()
    try:
      # The module *must* be in sys.modules before executing the code in case
      # the module code imports (directly or indirectly) itself (see PEP 302)
      sys.modules[module_fullname] = module
      if module_fullname_alias:
        sys.modules[module_fullname_alias] = module
      if module_fullname_filesystem:
        sys.modules[module_fullname_filesystem] = module

      # This must be set for imports at least (see PEP 302)
      module.__file__ = '<' + relative_url + '>'

      # Only useful for get_source(), do it before exec'ing the source code
      # so that the source code is properly display in case of error
      module.__loader__ = self
      module.__path__ = []
      module.__name__ = module_fullname
      self.__fullname_source_code_dict[module_fullname] = source_code_str

      try:
        # XXX: Any loading from ZODB while exec'ing the source code will result
        # in a deadlock
        source_code_obj = compile(source_code_str, module.__file__, 'exec')
        exec(source_code_obj, module.__dict__)
      except Exception as error:
        del sys.modules[module_fullname]
        if module_fullname_alias:
          del sys.modules[module_fullname_alias]
        if module_fullname_filesystem:
          del sys.modules[module_fullname_filesystem]

        reraise(ImportError,
          "%s: cannot load Component %s (%s)" % (fullname, name, error),
                sys.exc_info()[2])

      # Add the newly created module to the Version package and add it as an
      # alias to the top-level package as well
      setattr(version_package, name, module)
      if module_fullname_alias:
        setattr(self, name, module)
        MNAME_MAP[module_fullname_alias] = module_fullname
        if module_fullname_filesystem:
          MNAME_MAP[module_fullname_filesystem] = module.__name__

      import erp5.component
      erp5.component.ref_manager.add_module(module)

    finally:
      imp.release_lock()

    component._hookAfterLoad(module)
    return module