diff planemo/lib/python3.7/site-packages/galaxy/util/pastescript/loadwsgi.py @ 1:56ad4e20f292 draft

"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
author guerler
date Fri, 31 Jul 2020 00:32:28 -0400
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/planemo/lib/python3.7/site-packages/galaxy/util/pastescript/loadwsgi.py	Fri Jul 31 00:32:28 2020 -0400
@@ -0,0 +1,777 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+
+# Mostly taken from PasteDeploy and stripped down for Galaxy
+
+import inspect
+import os
+import re
+import sys
+
+import pkg_resources
+from six import iteritems
+from six.moves.urllib.parse import unquote
+
+from galaxy.util.getargspec import getfullargspec
+from galaxy.util.properties import NicerConfigParser
+
+
+__all__ = ('loadapp', 'loadserver', 'loadfilter', 'appconfig')
+
+# ---- from paste.deploy.compat --------------------------------------
+
+"""Python 2<->3 compatibility module"""
+
+
+def print_(template, *args, **kwargs):
+    template = str(template)
+    if args:
+        template = template % args
+    elif kwargs:
+        template = template % kwargs
+    sys.stdout.writelines(template)
+
+
+if sys.version_info < (3, 0):
+    def reraise(t, e, tb):
+        exec('raise t, e, tb', dict(t=t, e=e, tb=tb))
+else:
+    def reraise(t, e, tb):
+        exec('raise e from tb', dict(e=e, tb=tb))
+
+# ---- from paste.deploy.util ----------------------------------------
+
+
+def fix_type_error(exc_info, callable, varargs, kwargs):
+    """
+    Given an exception, this will test if the exception was due to a
+    signature error, and annotate the error with better information if
+    so.
+
+    Usage::
+
+      try:
+          val = callable(*args, **kw)
+      except TypeError:
+          exc_info = fix_type_error(None, callable, args, kw)
+          raise exc_info[0], exc_info[1], exc_info[2]
+    """
+    if exc_info is None:
+        exc_info = sys.exc_info()
+    if (exc_info[0] != TypeError or
+            str(exc_info[1]).find('argument') == -1 or
+            getattr(exc_info[1], '_type_error_fixed', False)):
+        return exc_info
+    exc_info[1]._type_error_fixed = True
+    argspec = inspect.formatargspec(*getfullargspec(callable))
+    args = ', '.join(map(_short_repr, varargs))
+    if kwargs and args:
+        args += ', '
+    if kwargs:
+        kwargs = sorted(kwargs.keys())
+        args += ', '.join('%s=...' % n for n in kwargs)
+    gotspec = '(%s)' % args
+    msg = '%s; got %s, wanted %s' % (exc_info[1], gotspec, argspec)
+    exc_info[1].args = (msg,)
+    return exc_info
+
+
+def _short_repr(v):
+    v = repr(v)
+    if len(v) > 12:
+        v = v[:8] + '...' + v[-4:]
+    return v
+
+
+def fix_call(callable, *args, **kw):
+    """
+    Call ``callable(*args, **kw)`` fixing any type errors that come out.
+    """
+    try:
+        val = callable(*args, **kw)
+    except TypeError:
+        exc_info = fix_type_error(None, callable, args, kw)
+        reraise(*exc_info)
+    return val
+
+
+def lookup_object(spec):
+    """
+    Looks up a module or object from a some.module:func_name specification.
+    To just look up a module, omit the colon and everything after it.
+    """
+    parts, target = spec.split(':') if ':' in spec else (spec, None)
+    module = __import__(parts)
+
+    for part in parts.split('.')[1:] + ([target] if target else []):
+        module = getattr(module, part)
+
+    return module
+
+# ---- from paste.deploy.loadwsgi ------------------------------------
+
+############################################################
+# Utility functions
+############################################################
+
+
+def import_string(s):
+    return pkg_resources.EntryPoint.parse("x=" + s).load(False)
+
+
+def _aslist(obj):
+    """
+    Turn object into a list; lists and tuples are left as-is, None
+    becomes [], and everything else turns into a one-element list.
+    """
+    if obj is None:
+        return []
+    elif isinstance(obj, (list, tuple)):
+        return obj
+    else:
+        return [obj]
+
+
+def _flatten(lst):
+    """
+    Flatten a nested list.
+    """
+    if not isinstance(lst, (list, tuple)):
+        return [lst]
+    result = []
+    for item in lst:
+        result.extend(_flatten(item))
+    return result
+
+
+############################################################
+# Object types
+############################################################
+
+
+class _ObjectType(object):
+
+    name = None
+    egg_protocols = None
+    config_prefixes = None
+
+    def __init__(self):
+        # Normalize these variables:
+        self.egg_protocols = [_aslist(p) for p in _aslist(self.egg_protocols)]
+        self.config_prefixes = [_aslist(p) for p in _aslist(self.config_prefixes)]
+
+    def __repr__(self):
+        return '<%s protocols=%r prefixes=%r>' % (
+            self.name, self.egg_protocols, self.config_prefixes)
+
+    def invoke(self, context):
+        assert context.protocol in _flatten(self.egg_protocols)
+        return fix_call(context.object,
+                        context.global_conf, **context.local_conf)
+
+
+class _App(_ObjectType):
+
+    name = 'application'
+    egg_protocols = ['paste.app_factory', 'paste.composite_factory',
+                     'paste.composit_factory']
+    config_prefixes = [['app', 'application'], ['composite', 'composit'],
+                       'pipeline', 'filter-app']
+
+    def invoke(self, context):
+        if context.protocol in ('paste.composit_factory',
+                                'paste.composite_factory'):
+            return fix_call(context.object,
+                            context.loader, context.global_conf,
+                            **context.local_conf)
+        elif context.protocol == 'paste.app_factory':
+            return fix_call(context.object, context.global_conf, **context.local_conf)
+        else:
+            assert 0, "Protocol %r unknown" % context.protocol
+
+
+APP = _App()
+
+
+class _Filter(_ObjectType):
+    name = 'filter'
+    egg_protocols = [['paste.filter_factory', 'paste.filter_app_factory']]
+    config_prefixes = ['filter']
+
+    def invoke(self, context):
+        if context.protocol == 'paste.filter_factory':
+            return fix_call(context.object,
+                            context.global_conf, **context.local_conf)
+        elif context.protocol == 'paste.filter_app_factory':
+            def filter_wrapper(wsgi_app):
+                # This should be an object, so it has a nicer __repr__
+                return fix_call(context.object,
+                                wsgi_app, context.global_conf,
+                                **context.local_conf)
+            return filter_wrapper
+        else:
+            assert 0, "Protocol %r unknown" % context.protocol
+
+
+FILTER = _Filter()
+
+
+class _Server(_ObjectType):
+    name = 'server'
+    egg_protocols = [['paste.server_factory', 'paste.server_runner']]
+    config_prefixes = ['server']
+
+    def invoke(self, context):
+        if context.protocol == 'paste.server_factory':
+            return fix_call(context.object,
+                            context.global_conf, **context.local_conf)
+        elif context.protocol == 'paste.server_runner':
+            def server_wrapper(wsgi_app):
+                # This should be an object, so it has a nicer __repr__
+                return fix_call(context.object,
+                                wsgi_app, context.global_conf,
+                                **context.local_conf)
+            return server_wrapper
+        else:
+            assert 0, "Protocol %r unknown" % context.protocol
+
+
+SERVER = _Server()
+
+
+# Virtual type: (@@: There's clearly something crufty here;
+# this probably could be more elegant)
+class _PipeLine(_ObjectType):
+    name = 'pipeline'
+
+    def invoke(self, context):
+        app = context.app_context.create()
+        filters = [c.create() for c in context.filter_contexts]
+        filters.reverse()
+        for filter_ in filters:
+            app = filter_(app)
+        return app
+
+
+PIPELINE = _PipeLine()
+
+
+class _FilterApp(_ObjectType):
+    name = 'filter_app'
+
+    def invoke(self, context):
+        next_app = context.next_context.create()
+        filter_ = context.filter_context.create()
+        return filter_(next_app)
+
+
+FILTER_APP = _FilterApp()
+
+
+class _FilterWith(_App):
+    name = 'filtered_with'
+
+    def invoke(self, context):
+        filter_ = context.filter_context.create()
+        filtered = context.next_context.create()
+        if context.next_context.object_type is APP:
+            return filter_(filtered)
+        else:
+            # filtering a filter
+            def composed(app):
+                return filter_(filtered(app))
+            return composed
+
+
+FILTER_WITH = _FilterWith()
+
+############################################################
+# Loaders
+############################################################
+
+
+def loadapp(uri, name=None, **kw):
+    return loadobj(APP, uri, name=name, **kw)
+
+
+def loadfilter(uri, name=None, **kw):
+    return loadobj(FILTER, uri, name=name, **kw)
+
+
+def loadserver(uri, name=None, **kw):
+    return loadobj(SERVER, uri, name=name, **kw)
+
+
+def appconfig(uri, name=None, relative_to=None, global_conf=None):
+    context = loadcontext(APP, uri, name=name,
+                          relative_to=relative_to,
+                          global_conf=global_conf)
+    return context.config()
+
+
+_loaders = {}
+
+
+def loadobj(object_type, uri, name=None, relative_to=None,
+            global_conf=None):
+    context = loadcontext(
+        object_type, uri, name=name, relative_to=relative_to,
+        global_conf=global_conf)
+    return context.create()
+
+
+def loadcontext(object_type, uri, name=None, relative_to=None,
+                global_conf=None):
+    if '#' in uri:
+        if name is None:
+            uri, name = uri.split('#', 1)
+        else:
+            # @@: Ignore fragment or error?
+            uri = uri.split('#', 1)[0]
+    if name is None:
+        name = 'main'
+    if ':' not in uri:
+        raise LookupError("URI has no scheme: %r" % uri)
+    scheme, path = uri.split(':', 1)
+    scheme = scheme.lower()
+    if scheme not in _loaders:
+        raise LookupError(
+            "URI scheme not known: %r (from %s)"
+            % (scheme, ', '.join(_loaders.keys())))
+    return _loaders[scheme](
+        object_type,
+        uri, path, name=name, relative_to=relative_to,
+        global_conf=global_conf)
+
+
+def _loadconfig(object_type, uri, path, name, relative_to,
+                global_conf):
+    isabs = os.path.isabs(path)
+    # De-Windowsify the paths:
+    path = path.replace('\\', '/')
+    if not isabs:
+        if not relative_to:
+            raise ValueError(
+                "Cannot resolve relative uri %r; no relative_to keyword "
+                "argument given" % uri)
+        relative_to = relative_to.replace('\\', '/')
+        if relative_to.endswith('/'):
+            path = relative_to + path
+        else:
+            path = relative_to + '/' + path
+    if path.startswith('///'):
+        path = path[2:]
+    path = unquote(path)
+    loader = ConfigLoader(path)
+    if global_conf:
+        loader.update_defaults(global_conf, overwrite=False)
+    return loader.get_context(object_type, name, global_conf)
+
+
+_loaders['config'] = _loadconfig
+
+
+def _loadegg(object_type, uri, spec, name, relative_to,
+             global_conf):
+    loader = EggLoader(spec)
+    return loader.get_context(object_type, name, global_conf)
+
+
+_loaders['egg'] = _loadegg
+
+
+def _loadfunc(object_type, uri, spec, name, relative_to,
+              global_conf):
+
+    loader = FuncLoader(spec)
+    return loader.get_context(object_type, name, global_conf)
+
+
+_loaders['call'] = _loadfunc
+
+############################################################
+# Loaders
+############################################################
+
+
+class _Loader(object):
+
+    def get_app(self, name=None, global_conf=None):
+        return self.app_context(
+            name=name, global_conf=global_conf).create()
+
+    def get_filter(self, name=None, global_conf=None):
+        return self.filter_context(
+            name=name, global_conf=global_conf).create()
+
+    def get_server(self, name=None, global_conf=None):
+        return self.server_context(
+            name=name, global_conf=global_conf).create()
+
+    def app_context(self, name=None, global_conf=None):
+        return self.get_context(
+            APP, name=name, global_conf=global_conf)
+
+    def filter_context(self, name=None, global_conf=None):
+        return self.get_context(
+            FILTER, name=name, global_conf=global_conf)
+
+    def server_context(self, name=None, global_conf=None):
+        return self.get_context(
+            SERVER, name=name, global_conf=global_conf)
+
+    _absolute_re = re.compile(r'^[a-zA-Z]+:')
+
+    def absolute_name(self, name):
+        """
+        Returns true if the name includes a scheme
+        """
+        if name is None:
+            return False
+        return self._absolute_re.search(name)
+
+
+class ConfigLoader(_Loader):
+
+    def __init__(self, filename):
+        self.filename = filename = filename.strip()
+        defaults = {
+            'here': os.path.dirname(os.path.abspath(filename)),
+            '__file__': os.path.abspath(filename)
+        }
+        self.parser = NicerConfigParser(filename, defaults=defaults)
+        self.parser.optionxform = str  # Don't lower-case keys
+        with open(filename) as f:
+            self.parser.read_file(f)
+
+    def update_defaults(self, new_defaults, overwrite=True):
+        for key, value in iteritems(new_defaults):
+            if not overwrite and key in self.parser._defaults:
+                continue
+            self.parser._defaults[key] = value
+
+    def get_context(self, object_type, name=None, global_conf=None):
+        if self.absolute_name(name):
+            return loadcontext(object_type, name,
+                               relative_to=os.path.dirname(self.filename),
+                               global_conf=global_conf)
+        section = self.find_config_section(
+            object_type, name=name)
+        if global_conf is None:
+            global_conf = {}
+        else:
+            global_conf = global_conf.copy()
+        defaults = self.parser.defaults()
+        global_conf.update(defaults)
+        local_conf = {}
+        global_additions = {}
+        get_from_globals = {}
+        for option in self.parser.options(section):
+            if option.startswith('set '):
+                name = option[4:].strip()
+                global_additions[name] = global_conf[name] = (
+                    self.parser.get(section, option))
+            elif option.startswith('get '):
+                name = option[4:].strip()
+                get_from_globals[name] = self.parser.get(section, option)
+            else:
+                if option in defaults:
+                    # @@: It's a global option (?), so skip it
+                    continue
+                local_conf[option] = self.parser.get(section, option)
+        for local_var, glob_var in get_from_globals.items():
+            local_conf[local_var] = global_conf[glob_var]
+        if object_type in (APP, FILTER) and 'filter-with' in local_conf:
+            filter_with = local_conf.pop('filter-with')
+        else:
+            filter_with = None
+        if 'require' in local_conf:
+            for spec in local_conf['require'].split():
+                pkg_resources.require(spec)
+            del local_conf['require']
+        if section.startswith('filter-app:'):
+            context = self._filter_app_context(
+                object_type, section, name=name,
+                global_conf=global_conf, local_conf=local_conf,
+                global_additions=global_additions)
+        elif section.startswith('pipeline:'):
+            context = self._pipeline_app_context(
+                object_type, section, name=name,
+                global_conf=global_conf, local_conf=local_conf,
+                global_additions=global_additions)
+        elif 'use' in local_conf:
+            context = self._context_from_use(
+                object_type, local_conf, global_conf, global_additions,
+                section)
+        else:
+            context = self._context_from_explicit(
+                object_type, local_conf, global_conf, global_additions,
+                section)
+        if filter_with is not None:
+            filter_with_context = LoaderContext(
+                obj=None,
+                object_type=FILTER_WITH,
+                protocol=None,
+                global_conf=global_conf, local_conf=local_conf,
+                loader=self)
+            filter_with_context.filter_context = self.filter_context(
+                name=filter_with, global_conf=global_conf)
+            filter_with_context.next_context = context
+            return filter_with_context
+        return context
+
+    def _context_from_use(self, object_type, local_conf, global_conf,
+                          global_additions, section):
+        use = local_conf.pop('use')
+        context = self.get_context(
+            object_type, name=use, global_conf=global_conf)
+        context.global_conf.update(global_additions)
+        context.local_conf.update(local_conf)
+        if '__file__' in global_conf:
+            # use sections shouldn't overwrite the original __file__
+            context.global_conf['__file__'] = global_conf['__file__']
+        # @@: Should loader be overwritten?
+        context.loader = self
+
+        if context.protocol is None:
+            # Determine protocol from section type
+            section_protocol = section.split(':', 1)[0]
+            if section_protocol in ('application', 'app'):
+                context.protocol = 'paste.app_factory'
+            elif section_protocol in ('composit', 'composite'):
+                context.protocol = 'paste.composit_factory'
+            else:
+                # This will work with 'server' and 'filter', otherwise it
+                # could fail but there is an error message already for
+                # bad protocols
+                context.protocol = 'paste.%s_factory' % section_protocol
+
+        return context
+
+    def _context_from_explicit(self, object_type, local_conf, global_conf,
+                               global_addition, section):
+        possible = []
+        for protocol_options in object_type.egg_protocols:
+            for protocol in protocol_options:
+                if protocol in local_conf:
+                    possible.append((protocol, local_conf[protocol]))
+                    break
+        if len(possible) > 1:
+            raise LookupError(
+                "Multiple protocols given in section %r: %s"
+                % (section, possible))
+        if not possible:
+            raise LookupError(
+                "No loader given in section %r" % section)
+        found_protocol, found_expr = possible[0]
+        del local_conf[found_protocol]
+        value = import_string(found_expr)
+        context = LoaderContext(
+            value, object_type, found_protocol,
+            global_conf, local_conf, self)
+        return context
+
+    def _filter_app_context(self, object_type, section, name,
+                            global_conf, local_conf, global_additions):
+        if 'next' not in local_conf:
+            raise LookupError(
+                "The [%s] section in %s is missing a 'next' setting"
+                % (section, self.filename))
+        next_name = local_conf.pop('next')
+        context = LoaderContext(None, FILTER_APP, None, global_conf,
+                                local_conf, self)
+        context.next_context = self.get_context(
+            APP, next_name, global_conf)
+        if 'use' in local_conf:
+            context.filter_context = self._context_from_use(
+                FILTER, local_conf, global_conf, global_additions,
+                section)
+        else:
+            context.filter_context = self._context_from_explicit(
+                FILTER, local_conf, global_conf, global_additions,
+                section)
+        return context
+
+    def _pipeline_app_context(self, object_type, section, name,
+                              global_conf, local_conf, global_additions):
+        if 'pipeline' not in local_conf:
+            raise LookupError(
+                "The [%s] section in %s is missing a 'pipeline' setting"
+                % (section, self.filename))
+        pipeline = local_conf.pop('pipeline').split()
+        if local_conf:
+            raise LookupError(
+                "The [%s] pipeline section in %s has extra "
+                "(disallowed) settings: %s"
+                % (', '.join(local_conf.keys())))
+        context = LoaderContext(None, PIPELINE, None, global_conf,
+                                local_conf, self)
+        context.app_context = self.get_context(
+            APP, pipeline[-1], global_conf)
+        context.filter_contexts = [
+            self.get_context(FILTER, pname, global_conf)
+            for pname in pipeline[:-1]]
+        return context
+
+    def find_config_section(self, object_type, name=None):
+        """
+        Return the section name with the given name prefix (following the
+        same pattern as ``protocol_desc`` in ``config``.  It must have the
+        given name, or for ``'main'`` an empty name is allowed.  The
+        prefix must be followed by a ``:``.
+
+        Case is *not* ignored.
+        """
+        possible = []
+        for name_options in object_type.config_prefixes:
+            for name_prefix in name_options:
+                found = self._find_sections(
+                    self.parser.sections(), name_prefix, name)
+                if found:
+                    possible.extend(found)
+                    break
+        if not possible:
+            raise LookupError(
+                "No section %r (prefixed by %s) found in config %s"
+                % (name,
+                   ' or '.join(map(repr, _flatten(object_type.config_prefixes))),
+                   self.filename))
+        if len(possible) > 1:
+            raise LookupError(
+                "Ambiguous section names %r for section %r (prefixed by %s) "
+                "found in config %s"
+                % (possible, name,
+                   ' or '.join(map(repr, _flatten(object_type.config_prefixes))),
+                   self.filename))
+        return possible[0]
+
+    def _find_sections(self, sections, name_prefix, name):
+        found = []
+        if name is None:
+            if name_prefix in sections:
+                found.append(name_prefix)
+            name = 'main'
+        for section in sections:
+            if section.startswith(name_prefix + ':'):
+                if section[len(name_prefix) + 1:].strip() == name:
+                    found.append(section)
+        return found
+
+
+class EggLoader(_Loader):
+
+    def __init__(self, spec):
+        self.spec = spec
+
+    def get_context(self, object_type, name=None, global_conf=None):
+        if self.absolute_name(name):
+            return loadcontext(object_type, name,
+                               global_conf=global_conf)
+        entry_point, protocol, ep_name = self.find_egg_entry_point(
+            object_type, name=name)
+        return LoaderContext(
+            entry_point,
+            object_type,
+            protocol,
+            global_conf or {}, {},
+            self,
+            distribution=pkg_resources.get_distribution(self.spec),
+            entry_point_name=ep_name)
+
+    def find_egg_entry_point(self, object_type, name=None):
+        """
+        Returns the (entry_point, protocol) for the with the given
+        ``name``.
+        """
+        if name is None:
+            name = 'main'
+        possible = []
+        for protocol_options in object_type.egg_protocols:
+            for protocol in protocol_options:
+                pkg_resources.require(self.spec)
+                entry = pkg_resources.get_entry_info(
+                    self.spec,
+                    protocol,
+                    name)
+                if entry is not None:
+                    possible.append((entry.load(), protocol, entry.name))
+                    break
+        if not possible:
+            # Better exception
+            dist = pkg_resources.get_distribution(self.spec)
+            raise LookupError(
+                "Entry point %r not found in egg %r (dir: %s; protocols: %s; "
+                "entry_points: %s)"
+                % (name, self.spec,
+                    dist.location,
+                    ', '.join(_flatten(object_type.egg_protocols)),
+                    ', '.join(_flatten([
+                        list((pkg_resources.get_entry_info(self.spec, prot, name) or {}).keys())
+                        for prot in protocol_options] or '(no entry points)'))))
+        if len(possible) > 1:
+            raise LookupError(
+                "Ambiguous entry points for %r in egg %r (protocols: %s)"
+                % (name, self.spec, ', '.join(_flatten(protocol_options))))
+        return possible[0]
+
+
+class FuncLoader(_Loader):
+    """ Loader that supports specifying functions inside modules, without
+    using eggs at all. Configuration should be in the format:
+        use = call:my.module.path:function_name
+
+    Dot notation is supported in both the module and function name, e.g.:
+        use = call:my.module.path:object.method
+    """
+
+    def __init__(self, spec):
+        self.spec = spec
+        if ':' not in spec:
+            raise LookupError("Configuration not in format module:function")
+
+    def get_context(self, object_type, name=None, global_conf=None):
+        obj = lookup_object(self.spec)
+        return LoaderContext(
+            obj,
+            object_type,
+            None,  # determine protocol from section type
+            global_conf or {},
+            {},
+            self,
+        )
+
+
+class LoaderContext(object):
+
+    def __init__(self, obj, object_type, protocol,
+                 global_conf, local_conf, loader,
+                 distribution=None, entry_point_name=None):
+        self.object = obj
+        self.object_type = object_type
+        self.protocol = protocol
+        # assert protocol in _flatten(object_type.egg_protocols), (
+        #    "Bad protocol %r; should be one of %s"
+        #    % (protocol, ', '.join(map(repr, _flatten(object_type.egg_protocols)))))
+        self.global_conf = global_conf
+        self.local_conf = local_conf
+        self.loader = loader
+        self.distribution = distribution
+        self.entry_point_name = entry_point_name
+
+    def create(self):
+        return self.object_type.invoke(self)
+
+    def config(self):
+        conf = AttrDict(self.global_conf)
+        conf.update(self.local_conf)
+        conf.local_conf = self.local_conf
+        conf.global_conf = self.global_conf
+        conf.context = self
+        return conf
+
+
+class AttrDict(dict):
+    """
+    A dictionary that can be assigned to.
+    """
+    pass