コード例 #1
0
def make_hidden_input(*args, **kwargs):
  '''Construct a set of hidden input elements, with marshalling markup.

  If there are positional arguments, they must be dictionaries.
  They are combined with the dictionary of keyword arguments to form
  a dictionary of query names and values.

  Query names (the keys) must be strings.  Values may be strings,
  integers, floats, or DateTimes, and they may also be lists or
  namespaces containing these types.  All arguments are marshalled with
  complex_marshal().
  '''

  d = {}
  for arg in args:
      d.update(arg)
  d.update(kwargs)

  hq = lambda x:cgi.escape(x, quote=True)
  qlist = complex_marshal(ensure_list(d.items()))
  for i in range(len(qlist)):
      k, m, v = qlist[i]
      qlist[i] = ('<input type="hidden" name="%s%s" value="%s" />'
                  % (hq(k), m, hq(str(v))))

  return '\n'.join(qlist)
コード例 #2
0
    def gettext(self, message, lang=None, add=None, default=None):
        """Returns the message translation from the database if available.

        If add=1, add any unknown message to the database.
        If a default is provided, use it instead of the message id
        as a translation for unknown messages.
        """
        if not isinstance(message, basestring):
            raise TypeError('only strings can be translated, not: %r' %
                            (message, ))

        if default is None:
            default = message

        message = message.strip()

        # BBB call get_message_key to support both (old) str key and
        # (new) unicode key.
        message = self.get_message_key(message) or to_unicode(message)

        # Add it if it's not in the dictionary
        if add is None:
            add = getattr(self, 'policy', self.POLICY_ADD_TRUE)
        if add != self.POLICY_ADD_FALSE and message not in self._messages and message:
            if add == self.POLICY_ADD_LOG:
                LOG(
                    'New entry added to message catalog %s :' % self.id, INFO,
                    '%s\n%s' %
                    (message, ''.join(format_list(extract_stack()[:-1]))))
            self._messages[message] = PersistentMapping()

        # Get the string
        if message in self._messages:
            m = self._messages[message]

            if lang is None:
                # Builds the list of available languages
                # should the empty translations be filtered?
                available_languages = ensure_list(self._languages)

                # Imagine that the default language is 'en'. There is no
                # translation from 'en' to 'en' in the message catalog
                # The user has the preferences 'en' and 'nl' in that order
                # The next two lines make certain 'en' is shown, not 'nl'
                if not self._default_language in available_languages:
                    available_languages.append(self._default_language)

                # Get the language!
                lang = lang_negotiator(available_languages)

                # Is it None? use the default
                if lang is None:
                    lang = self._default_language

            if lang is not None:
                return m.get(lang) or default

        return default
コード例 #3
0
 def clearCacheForScope(self, scope):
   cache = self.getCacheStorage()
   for key in ensure_list(cache.keys()):
     if key[0] == scope:
       try:
         del cache[key]
       except KeyError:
         # The key might have disappeared, due to multi-threading.
         pass
コード例 #4
0
 def gc(self):
     """
 Remove cache items with no Request Left.
 """
     from Products.ERP5Type.Utils import ensure_list
     for (current_last_sync, (request_obj_weakset,
                              _)) in ensure_list(self.items()):
         if not request_obj_weakset:
             del self[current_last_sync]
コード例 #5
0
  def reset(self, sub_package=None):
    """
    Reset the content of the current package and its version package as well
    recursively. This method must be called within a lock to avoid side
    effects
    """
    if sub_package:
      package = sub_package
    else:
      # Clear the source code dict only once
      self.__fullname_source_code_dict.clear()
      package = self

      # Force reload of ModuleSecurityInfo() as it may have been changed in
      # the source code
      for modsec_dict in _moduleSecurity, _appliedModuleSecurity:
        for k in ensure_list(modsec_dict.keys()):
          if k.startswith(self._namespace):
            del modsec_dict[k]
      for k, v in ensure_list(MNAME_MAP.items()):
        if v.startswith(self._namespace):
          del MNAME_MAP[k]

          # Products import compatibility (module_fullname_filesystem)
          if k.startswith('Products.'):
            del sys.modules[k]

    for name, module in ensure_list(package.__dict__.items()):
      if name[0] == '_' or not isinstance(module, ModuleType):
        continue

      # Reset the content of the version package before resetting it
      elif isinstance(module, ComponentVersionPackage):
        self.reset(sub_package=module)

      module_name = package.__name__ + '.' + name
      LOG("ERP5Type.Tool.ComponentTool", BLATHER, "Resetting " + module_name)

      # The module must be deleted first from sys.modules to avoid imports in
      # the meantime
      del sys.modules[module_name]

      delattr(package, name)
コード例 #6
0
 def expireOldCacheEntries(self, forceCheck=False):
   now = time.time()
   if forceCheck or (now > self._next_cache_expire_check_at):
     ## time to check for expired cache items
     self._next_cache_expire_check_at = now + self.cache_expire_check_interval
     cache = self.getCacheStorage()
     for key, value in ensure_list(cache.items()):
       if value.isExpired():
         try:
           del cache[key]
         except KeyError:
           # The key might have disappeared, due to multi-threading.
           pass
コード例 #7
0
 def generateNewIdList(self,
                       id_group=None,
                       id_count=1,
                       default=None,
                       poison=False):
     """
   Generate a list of next ids in the sequence of ids of a particular group
 """
     new_id = 1 + self._generateNewId(id_group=id_group,
                                      id_count=id_count,
                                      default=default,
                                      poison=poison)
     return ensure_list(range(new_id - id_count, new_id))
コード例 #8
0
 def getResultList(self, **kw):
     """
   Returns the list of results
 """
     # Improve this to include sort order XXX
     try:
         result_list = self.result_list
     except AttributeError:
         # BBB: self was created before implementation of __init__
         return []
     # XXX: ConflictFreeLog does not support indexing so cast to list for the
     #      moment, although this is inefficient and the caller never needs a
     #      copy (currently). Same for IOBTree.itervalues().
     if type(result_list
             ) is not ConflictFreeLog:  # BBB: result_list is IOBTree
         return ensure_list(result_list.values())
     return list(result_list)
コード例 #9
0
    def setVariables(self, ids=[], REQUEST=None):
        ''' set values for Variables set by this state
        '''
        if self.var_exprs is None:
            self.var_exprs = PersistentMapping()

        ve = self.var_exprs

        if REQUEST is not None:
            for id in ensure_list(ve.keys()):
                fname = 'varexpr_%s' % id

                val = REQUEST[fname]
                expr = None
                if val:
                    expr = Expression(str(REQUEST[fname]))
                ve[id] = expr

            return self.manage_variables(REQUEST, 'Variables changed.')
コード例 #10
0
    def clear(self):
        """
    Clear the content of the module
    """
        for klass in ensure_list(self.__dict__.values()):
            if isinstance(klass, AccessorHolderType):
                # Delete these attributes (computed on the portal type class
                # from its accessor holder) before deleting the class itself
                # because a reference on the class will still be kept as bases
                # of erp5.portal_type, thus this ensures that
                # erp5.portal_type.Foo will be 'unghost' thanks to
                # PortalTypeMetaClass.__getattr__
                for attribute in ('constraints', '_categories'):
                    try:
                        delattr(klass, attribute)
                    except AttributeError:
                        pass

                delattr(self, klass.__name__)
コード例 #11
0
 def restoreGhostState(cls):
     """
 Insert in the __bases__ hierarchy an instance of GhostBaseMetaClass
 that will force reloading the class.
 - mro before reset:
    erp5.portal_type.XXX, *TAIL
 - after reset:
    erp5.portal_type.XXX, GhostBaseMetaClass instance, *TAIL
 """
     if not cls.__isghost__:
         for attr in ensure_list(cls.__dict__.keys()):
             if attr not in ('__module__', '__doc__', '__setstate__',
                             'workflow_method_registry', '__isghost__',
                             'portal_type'):
                 delattr(cls, attr)
         # generate a ghostbase that derives from all previous bases
         ghostbase = GhostBaseMetaClass('GhostBase', cls.__bases__, {})
         cls.workflow_method_registry.clear()
         cls.__bases__ = (ghostbase, )
         cls.__isghost__ = True
         cls.resetAcquisition()
         cls.security = ClassSecurityInfo()
コード例 #12
0
    def _process(self,kw):
        # sort out what encoding we're going to use
        encoding = kw.get('encoding',
                          self.getProperty('encoding',
                                           default_encoding))
        text = self.__class__.__bases__[1].__call__(self,**kw)
        # ZPT adds newline at the end, but it breaks backward compatibility.
        # So I remove it.
        if text.endswith('\n'):
            text = text[:-1]
        if not self.html() and isinstance(text, six.text_type):
            text = text.encode(encoding,'replace')
        # now turn the result into a MIMEText object
        msg = MIMEText(
            text.replace('\r',''),
            self.content_type.split('/')[1],
            encoding
            )
        # sort out what headers and addresses we're going to use
        headers = {}
        values = {}
        # headers from the headers property
        for header in getattr(self,'headers',()):
            name,value = header.split(':',1)
            headers[name]=value
        # headers from the headers parameter
        headers_param = kw.get('headers',{})
        headers.update(headers_param)
        # values and some specific headers
        for key,header in (('mfrom','From'),
                           ('mto','To'),
                           ('mcc','Cc'),
                           ('mbcc','Bcc'),
                           ('subject','Subject')):
            value = kw.get(key,
                           headers_param.get(header,
                                             getattr(self,
                                                     key,
                                                     headers.get(header))))
            if value is not None:
                values[key]=value

                if key == 'subject':
                    try:
                        # Try to keep header non encoded
                        value = Header(value)
                    except UnicodeDecodeError:
                        value = Header(value, "UTF-8")

                else:
                    dest_list = []
                    for name, email in getaddresses((value,)
                            if isinstance(value, basestring) else value):
                        try:
                            name = Header(name)
                        except UnicodeDecodeError:
                            name = Header(name, "UTF-8")
                        dest_list.append(formataddr((name.encode(), email)))
                    value = ", ".join(dest_list)

                headers[header]=value
        # check required values have been supplied
        errors = []
        for param in ('mfrom','mto'):
            if not values.get(param):
                errors.append(param)
        if errors:
            raise TypeError(
                'The following parameters were required by not specified: '+(
                ', '.join(errors)
                ))
        # add date header
        headers['Date']=DateTime().rfc822()
        # do not let the MTA to generate the Message-ID:
        # we want to have it stored in ERP5, for mail threading
        headers['Message-ID'] = make_msgid()
        # turn headers into an ordered list for predictable header order
        keys = ensure_list(headers.keys())
        keys.sort()
        return msg,values,[(key,headers[key]) for key in keys]
コード例 #13
0
def cacheIdGenerator(method_id, *args, **kw):
    context = args[0]
    return '%s%s%s' % (method_id, context.getUid(),
                       context.getModificationDate().timeTime())


cache_id_generator = cacheIdGenerator

getModifiedObjectList = CachingMethod(
    getModifiedObjectList,
    id='BusinessTemplate_getModifiedObjectList',
    cache_factory='erp5_ui_medium',
    cache_id_generator=cache_id_generator)

modified_object_list = getModifiedObjectList(context)
keys = ensure_list(modified_object_list.keys())
keys.sort()

no_backup_list = [
    'Action',
    'SiteProperty',
    'Module',
    'Document',
    'PropertySheet',
    'Extension',
    'Test',
    'Product',
    'Role',
    'CatalogResultKey',
    'CatalogRelatedKey',
    'CatalogResultTable',
コード例 #14
0
def synchronizeDynamicModules(context, force=False):
    """
  Allow resetting all classes to ghost state, most likely done after
  adding and removing mixins on the fly

  Most of the time, this reset is only hypothetic:
  * with force=False, the reset is only done if another node resetted
    the classes since the last reset on this node.
  * with force=True, forcefully reset the classes on the current node
    and send out an invalidation to other nodes
  """
    portal = context.getPortalObject()

    global last_sync
    if force:
        # hard invalidation to force sync between nodes
        portal.newCacheCookie('dynamic_classes')
        last_sync = portal.getCacheCookie('dynamic_classes')
    else:
        cookie = portal.getCacheCookie('dynamic_classes')
        if cookie == last_sync:
            # up to date, nothing to do
            return
        last_sync = cookie

    # Flush the entire ZODB.Connections pickle cache on next opening
    # (transaction beginning), for all connections.
    # There may be instances of the classes which are being reloaded in the
    # cache, and the code change may cause incompatible instance property
    # layouts. A very visible example is if the class does not exist prior to
    # the reload: if any instance was loaded, it is loaded as an instance of
    # the Broken class, which has a __setstate__ method which mangles
    # instance's properties. Then, post-reload the class cannot expect to
    # handle an instance with such property mangling, and will start behaving
    # in undefined ways.
    # Strictly, this issue also applies to any non-persistent instance of any
    # class defined in (or affected by) anything being reloaded. But as these
    # instances have not been made persistent, there is no guarantee that they
    # can be reloaded in any way.
    # Emptying the ZODB cache is the last thing short of restarting the whole
    # process.
    Connection.resetCaches()

    import erp5
    with aq_method_lock:
        # Thanks to TransactionalResource, the '_bootstrapped' global variable
        # is updated in a transactional way. Without it, it would be required to
        # restart the instance if anything went wrong.
        # XXX: In fact, TransactionalResource does not solve anything here, because
        #      portal cookie is unlikely to change and this function will return
        #      immediately, forcing the user to restart.
        #      This may not be so bad after all: it enables the user to do easily
        #      some changes that are required for the migration.
        if portal.id not in _bootstrapped and \
           TransactionalResource.registerOnce(__name__, 'bootstrap', portal.id):
            migrate = False
            from Products.ERP5Type.Tool.PropertySheetTool import PropertySheetTool
            from Products.ERP5Type.Tool.TypesTool import TypesTool
            from Products.ERP5Type.Tool.ComponentTool import ComponentTool
            from Products.ERP5.Tool.CategoryTool import CategoryTool
            from Products.ERP5Type.Tool.WorkflowTool import WorkflowTool
            from Products.ERP5Catalog.Tool.ERP5CatalogTool import ERP5CatalogTool
            try:
                for tool_class in TypesTool, PropertySheetTool, ComponentTool, ERP5CatalogTool, CategoryTool, WorkflowTool:
                    # if the instance has no property sheet tool, or incomplete
                    # property sheets, we need to import some data to bootstrap
                    # (only likely to happen on the first run ever)
                    tool_id = tool_class.id
                    tool = getattr(portal, tool_id, None)

                    if tool is None:
                        if tool_class == ERP5CatalogTool:
                            # Wait till we find that SQL Catalog Tool is installed
                            # Simpy said, we don't want  ERP5 Catalog Tool to be installed
                            # from here. So, we come to 2 cases:
                            # 1. Running ERP5Site with sql catalog_tool : In that case, we end up
                            # running _bootstrap from here, leading to migration.
                            # 2. New ERP5Site : In this case, we don't do anything here, cause
                            # the catalog_tool would be ERP5CatalogTool, so this would just pass.
                            continue
                        tool = tool_class()
                        portal._setObject(tool_id,
                                          tool,
                                          set_owner=False,
                                          suppress_events=True)
                        tool = getattr(portal, tool_id)
                    elif tool._isBootstrapRequired():
                        migrate = True
                    else:
                        continue
                    tool._bootstrap()
                    tool.__class__ = getattr(erp5.portal_type,
                                             tool.portal_type)
                # TODO: Create portal_activities here, and even before portal_types:
                #       - all code in ActiveObject could assume that it always exists
                #       - currently, some objects created very early are not indexed
                #         and this would fix this issue
                try:
                    portal.portal_activities.initialize()
                except AttributeError:
                    pass  # no Activity Tool yet

                for tool_id in ("portal_properties", "portal_uidannotation",
                                "portal_uidgenerator", "portal_uidhandler"):
                    if portal.hasObject(tool_id):
                        portal._delObject(tool_id, suppress_events=True)
                        migrate = True
                        if tool_id == 'portal_properties':
                            portal.portal_skins.erp5_xhtml_style.breadcrumbs.write(
                                'return []')

                if migrate:
                    portal.migrateToPortalTypeClass()
                    portal.portal_skins.changeSkin(None)
                    TransactionalResource(
                        tpc_finish=lambda txn: _bootstrapped.add(portal.id))
                    transaction.get().note('Site migrated')
                    LOG(
                        'ERP5Site', INFO,
                        'Transition successful, please update your'
                        ' business templates')
                else:
                    _bootstrapped.add(portal.id)

            except:
                # Required because the exception may be silently dropped by the caller.
                transaction.doom()
                LOG('ERP5Site',
                    PANIC,
                    "Automatic migration of core tools failed",
                    error=True)
                raise

        LOG("ERP5Type.dynamic", 0, "Resetting dynamic classes")
        try:
            for _, klass in inspect.getmembers(erp5.portal_type,
                                               inspect.isclass):
                # Zope Interface is implemented through __implements__,
                # __implemented__ (both implementedBy instances) and __provides__
                # (ClassProvides instance) attributes set on the class by
                # zope.interface.declarations.implementedByFallback.
                #
                # However both implementedBy and ClassProvides instances keep a
                # reference to the class itself, thus creating a circular references.
                for k in klass.mro():
                    module_name = k.__module__
                    if (module_name.startswith('erp5.') and
                            # Components are reset independently of Portal Types classes
                            not module_name.startswith('erp5.component.')):
                        for attr in ('__implements__', '__implemented__',
                                     '__provides__'):
                            if k.__dict__.get(attr) is not None:
                                delattr(k, attr)

                klass.restoreGhostState()

            # Clear accessor holders of ZODB Property Sheets and Portal Types
            erp5.accessor_holder.clear()
            erp5.accessor_holder.property_sheet.clear()

            for name in ensure_list(
                    erp5.accessor_holder.portal_type.__dict__.keys()):
                if name[0] != '_':
                    delattr(erp5.accessor_holder.portal_type, name)

        except Exception:
            # Allow easier debugging when the code is wrong as this
            # exception is catched later and re-raised as a BadRequest
            import traceback
            traceback.print_exc()
            raise

        # It's okay for classes to keep references to old methods - maybe.
        # but we absolutely positively need to clear the workflow chains
        # stored in WorkflowMethod objects: our generation of workflow
        # methods adds/registers/wraps existing methods, but does not
        # remove old chains. Do it now.
        resetRegisteredWorkflowMethod()

        # Some method generations are based on portal methods, and portal
        # methods cache results. So it is safer to invalidate the cache.
        cache_tool = getattr(portal, 'portal_caches', None)
        if cache_tool is not None:
            cache_tool.clearCache()

        # Clear Zope Component Registries (Zope Adapters/Utilities cache lookup)
        # because it contains references to reset dynamic classes (which prevents
        # them from being GC and may create inconsistencies when Interfaces have
        # been changed)
        import zope.component
        gsm = zope.component.getGlobalSiteManager()
        gsm.adapters.changed(gsm)
        gsm.utilities.changed(gsm)
コード例 #15
0
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
##############################################################################

from .Query import Query
from Products.ZSQLCatalog.interfaces.query import IQuery
from zope.interface.verify import verifyClass
from Products.ZSQLCatalog.SQLCatalog import list_type_list
from zLOG import LOG, WARNING
from Products.ERP5Type.Utils import ensure_list

NULL_SEARCH_TEXT_OPERATOR_DICT = {
    '=': 'is',
    '!=': 'is not',
}
for value in ensure_list(NULL_SEARCH_TEXT_OPERATOR_DICT.values()):
    NULL_SEARCH_TEXT_OPERATOR_DICT[value] = value


class SimpleQuery(Query):
    """
    A SimpleQuery represents a single comparison between a single column and
    one or more values.
  """
    def __init__(self,
                 search_key=None,
                 comparison_operator='=',
                 group=None,
                 **kw):
        """
      search_key (None, SearchKey instance)
コード例 #16
0
    def manage_export(self, x, REQUEST=None, RESPONSE=None):
        """Exports the content of the message catalog either to a template
        file (locale.pot) or to an language specific PO file (<x>.po).
        """
        # Get the PO header info
        header = self.get_po_header(x)
        last_translator_name = header['last_translator_name']
        last_translator_email = header['last_translator_email']
        language_team = header['language_team']
        charset = header['charset']

        # PO file header, empty message.
        po_revision_date = strftime('%Y-%m-%d %H:%m+%Z', gmtime(time()))
        pot_creation_date = po_revision_date
        last_translator = '%s <%s>' % (last_translator_name,
                                       last_translator_email)

        if x == 'locale.pot':
            language_team = 'LANGUAGE <*****@*****.**>'
        else:
            language_team = '%s <%s>' % (x, language_team)

        r = [
            'msgid ""',
            'msgstr "Project-Id-Version: %s\\n"' % self.title,
            '"POT-Creation-Date: %s\\n"' % pot_creation_date,
            '"PO-Revision-Date: %s\\n"' % po_revision_date,
            '"Last-Translator: %s\\n"' % last_translator,
            '"Language-Team: %s\\n"' % language_team, '"MIME-Version: 1.0\\n"',
            '"Content-Type: text/plain; charset=%s\\n"' % charset,
            '"Content-Transfer-Encoding: 8bit\\n"', '', ''
        ]

        # Get the messages, and perhaps its translations.
        # Convert keys to unicode for proper sorting.
        d = {}
        if x == 'locale.pot':
            filename = x
            for k in six.iterkeys(self._messages):
                d[to_unicode(k, encoding=charset)] = u""
        else:
            filename = '%s.po' % x
            for k, v in six.iteritems(self._messages):
                k = to_unicode(k, encoding=charset)
                d[k] = to_unicode(v.get(x, ""), encoding=charset)

        # Generate the file
        def backslashescape(x):
            x = to_str(x)
            quote_esc = compile(r'"')
            x = quote_esc.sub('\\"', x)

            trans = [('\n', '\\n'), ('\r', '\\r'), ('\t', '\\t')]
            for a, b in trans:
                x = x.replace(a, b)

            return x

        # Generate sorted msgids to simplify diffs
        dkeys = ensure_list(d.keys())
        dkeys.sort()
        for k in dkeys:
            r.append('msgid "%s"' % backslashescape(k))
            v = d[k]
            r.append('msgstr "%s"' % backslashescape(v))
            r.append('')

        if RESPONSE is not None:
            RESPONSE.setHeader('Content-type', 'application/data')
            RESPONSE.setHeader('Content-Disposition',
                               'inline;filename=%s' % filename)

        return '\n'.join(r)
コード例 #17
0
from Products.ERP5Type.Utils import ensure_list
for k, v in ensure_list(kw.items()):
    if v:
        if k == "str_object_path":
            kw["path"] = v
        elif k == "uid_activity":
            kw["uid"] = v
        elif k in ('method_id', 'processing_node', 'retry'):
            continue
    del kw[k]

message_list = context.getMessageTempObjectList(**kw)
for message in message_list:
    message.edit(
        str_object_path='/'.join(message.object_path),
        uid_activity=str(message.uid) + ' (' + message.activity[3:] + ')',
        delete='[Delete]',
        restart='[Restart]',
    )

return message_list
コード例 #18
0
  def getProcessableMessageList(self, activity_tool, processing_node,
                                node_family_id_list):
    """
      Always true:
        For each reserved message, delete redundant messages when it gets
        reserved (definitely lost, but they are expandable since redundant).

      - reserve a message
      - if this message has a group_method_id:
        - reserve a bunch of messages
        - until the total "cost" of the group goes over 1
          - get one message from the reserved bunch (this messages will be
            "needed")
          - update the total cost
        - unreserve "unneeded" messages
      - return still-reserved message list and a group_method_id

      If any error happens in above described process, try to unreserve all
      messages already reserved in that process.
      If it fails, complain loudly that some messages might still be in an
      unclean state.

      Returned values:
        4-tuple:
          - list of messages
          - group_method_id
          - uid_to_duplicate_uid_list_dict
    """
    db = activity_tool.getSQLConnection()
    now_date = getNow(db)
    uid_to_duplicate_uid_list_dict = {}
    try:
      while 1: # not a loop
        # Select messages that were either assigned manually or left
        # unprocessed after a shutdown. Most of the time, there's none.
        # To minimize the probability of deadlocks, we also COMMIT so that a
        # new transaction starts on the first 'FOR UPDATE' query, which is all
        # the more important as the current on started with getPriority().
        result = db.query(b"SELECT * FROM %s WHERE processing_node=%d"
          b" ORDER BY priority, date LIMIT 1\0COMMIT" % (
          str2bytes(self.sql_table), processing_node), 0)
        already_assigned = result[1]
        if already_assigned:
          result = Results(result)
        else:
          result = self.getReservedMessageList(db, now_date, processing_node,
                                               1, node_set=node_family_id_list)
          if not result:
            break
          # So reserved documents are properly released even if load raises.
          for line in result:
            uid_to_duplicate_uid_list_dict[line.uid] = []
        load = self.getProcessableMessageLoader(db, processing_node)
        m, uid, uid_list = load(result[0])
        message_list = [m]
        uid_to_duplicate_uid_list_dict[uid] = uid_list
        group_method_id = m.line.group_method_id
        if group_method_id[0] != '\0':
          # Count the number of objects to prevent too many objects.
          cost = m.getGroupMethodCost()
          assert 0 < cost <= 1, (self.sql_table, uid)
          count = m.getObjectCount(activity_tool)
          # this is heuristic (messages with same group_method_id
          # are likely to have the same group_method_cost)
          limit = int(1. / cost + 1 - count)
          if limit > 1: # <=> cost * count < 1
            cost *= count
            # Retrieve objects which have the same group method.
            result = iter(already_assigned
              and Results(db.query(b"SELECT * FROM %s"
                b" WHERE processing_node=%d AND group_method_id=%s"
                b" ORDER BY priority, date LIMIT %d" % (
                str2bytes(self.sql_table), processing_node,
                db.string_literal(group_method_id), limit), 0))
                # Do not optimize rare case: keep the code simple by not
                # adding more results from getReservedMessageList if the
                # limit is not reached.
              or self.getReservedMessageList(db, now_date, processing_node,
                limit, group_method_id, node_family_id_list))
            for line in result:
              if line.uid in uid_to_duplicate_uid_list_dict:
                continue
              m, uid, uid_list = load(line)
              if m is None:
                uid_to_duplicate_uid_list_dict[uid] += uid_list
                continue
              uid_to_duplicate_uid_list_dict[uid] = uid_list
              cost += m.getObjectCount(activity_tool) * \
                      m.getGroupMethodCost()
              message_list.append(m)
              if cost >= 1:
                # Unreserve extra messages as soon as possible.
                uid_list = [line.uid for line in result if line.uid != uid]
                if uid_list:
                  self.assignMessageList(db, 0, uid_list)
        return message_list, group_method_id, uid_to_duplicate_uid_list_dict
    except:
      self._log(WARNING, 'Exception while reserving messages.')
      if uid_to_duplicate_uid_list_dict:
        to_free_uid_list = ensure_list(uid_to_duplicate_uid_list_dict.keys())
        for uid_list in six.itervalues(uid_to_duplicate_uid_list_dict):
          to_free_uid_list += uid_list
        try:
          self.assignMessageList(db, 0, to_free_uid_list)
        except:
          self._log(ERROR, 'Failed to free messages: %r' % to_free_uid_list)
        else:
          if to_free_uid_list:
            self._log(TRACE, 'Freed messages %r' % to_free_uid_list)
      else:
        self._log(TRACE, '(no message was reserved)')
    return (), None, None
コード例 #19
0
 def getAvailableVarIds(self):
     return ensure_list(self.getWorkflow().variables.keys())
コード例 #20
0
 def getAvailableScriptIds(self):
     return ensure_list(self.getWorkflow().scripts.keys())
コード例 #21
0
 def getAvailableStateIds(self):
     return ensure_list(self.getWorkflow().states.keys())
コード例 #22
0
    def includeImageList(self, data):
        """Include Images in ODF archive

    - data: zipped archive content
    """
        builder = OOoBuilder(data)
        content = builder.extract('content.xml')
        xml_doc = etree.XML(content)
        image_tag_list = xml_doc.xpath('//*[name() = "draw:image"]')
        SVG_NAMESPACE = 'urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0'
        XLINK_NAMESPACE = 'http://www.w3.org/1999/xlink'
        ratio_px_cm = 2.54 / 100.
        # Flag to enable modification of OOoBuilder
        odt_content_modified = False
        for image_tag in image_tag_list:
            frame = image_tag.getparent()
            #Try to get image file from ZODB
            href_attribute_list = image_tag.xpath(
                './/@*[name() = "xlink:href"]')
            url = href_attribute_list[0]
            parse_result = urlparse(unquote(url))
            # urlparse return a 6-tuple: scheme, netloc, path, params, query, fragment
            netloc = parse_result[1]
            path = parse_result[2]
            if path and netloc in ('', None):
                # it makes sense to include only relative to current site images not remote ones which can be taken by OOo
                # OOo corrupt relative Links inside HTML content during odt conversion
                # <img src="REF.TO.IMAGE" ... /> become <draw:image xlink:href="../REF.TO.IMAGE" ... />
                # So remove "../" added by OOo
                path = CLEAN_RELATIVE_PATH.sub('', path)
                # in some cases like Web Page content "/../" can be contained in image URL which will break
                # restrictedTraverse calls, our best guess is to remove it
                path = path.replace('/../', '')
                # remove occurencies of '//' or '///' in path (happens with web pages) and leave
                # a traversable relative URL
                path = '/'.join(
                    [x for x in path.split('/') if x.strip() != ''])
                # retrieve http parameters and use them to convert image
                query_parameter_string = parse_result[4]
                image_parameter_dict = dict(parse_qsl(query_parameter_string))
                try:
                    image = self.context.restrictedTraverse(path)
                except (AttributeError, KeyError):
                    #Image not found, this image is probably not hosted by ZODB. Do nothing
                    image = None
                if image is not None:
                    odt_content_modified = True
                    content_type = image.getContentType()
                    format = image_parameter_dict.pop('format', None)
                    # convert API accepts only a certail range of arguments
                    for key, value in ensure_list(
                            image_parameter_dict.items()):
                        if key not in (
                                'format',
                                'display',
                                'quality',
                                'resolution',
                        ):
                            image_parameter_dict.pop(key)
                    if getattr(image, 'convert', None) is not None:
                        # The document support conversion so perform conversion
                        # according given parameters
                        mime, image_data = image.convert(
                            format, **image_parameter_dict)
                        # wrapp converted data into OFSImage in order to compute metadatas
                        # on converted result
                        image = OFSImage(image.getId(), image.getTitle(),
                                         image_data)

                    # image should be OFSImage
                    data = str(image.data)
                    width = image.width
                    height = image.height
                    if height:
                        frame.attrib.update({
                            '{%s}height' % SVG_NAMESPACE:
                            '%.3fcm' % (height * ratio_px_cm)
                        })
                    if width:
                        frame.attrib.update({
                            '{%s}width' % SVG_NAMESPACE:
                            '%.3fcm' % (width * ratio_px_cm)
                        })
                    if not format:
                        mimetype_list = self.context.getPortalObject(
                        ).mimetypes_registry.lookup(content_type)
                        # guess a format with help of mimetypes_registry
                        for mimetype_object in mimetype_list:
                            if mimetype_object.extensions:
                                format = mimetype_object.extensions[0]
                                break
                            elif mimetype_object.globs:
                                format = mimetype_object.globs[0].strip('*.')
                                break
                    new_path = builder.addImage(data, format=format)
                    image_tag.attrib.update(
                        {'{%s}href' % XLINK_NAMESPACE: new_path})
        if odt_content_modified:
            builder.replace(
                'content.xml',
                etree.tostring(xml_doc,
                               encoding='utf-8',
                               xml_declaration=True,
                               pretty_print=False))
        return builder.render()
コード例 #23
0
        return [('', '')]

    group_uid = portal.portal_categories.getCategoryUid(section_category)
    return [('', '')] + [
        (x.getTitle(), x.getRelativeUrl())
        for x in portal.portal_catalog(portal_type=portal_type,
                                       validation_state=validation_state,
                                       default_group_uid=group_uid,
                                       sort_on=('title', ))
    ]


getPreferredSectionItemList = CachingMethod(
    getPreferredSectionItemList,
    '%s.%s' %
    (script.getId(), getSecurityManager().getUser().getIdOrUserName()),
    cache_factory='erp5_ui_short')
section_item_list = getPreferredSectionItemList(portal_type, validation_state)

if base_category:
    section_item_list = section_item_list[::]  # make a copy not to modify the cache value
    current_category = context.getProperty(base_category)
    from Products.ERP5Type.Utils import ensure_list
    if current_category and current_category not in ensure_list(
            zip(*section_item_list))[1]:
        section_item_list.append(
            (context.getProperty('%s_title' % base_category),
             context.getProperty(base_category)))

return section_item_list