[Python-modules-commits] [python-pluggy] 01/03: Import python-pluggy_0.4.0.orig.tar.gz

Barry Warsaw barry at moszumanska.debian.org
Mon Oct 3 15:15:32 UTC 2016


This is an automated email from the git hooks/post-receive script.

barry pushed a commit to branch master
in repository python-pluggy.

commit c4e6c5b452f16f1574ec72249f3d6eff60f46b32
Author: Barry Warsaw <barry at python.org>
Date:   Mon Oct 3 11:11:21 2016 -0400

    Import python-pluggy_0.4.0.orig.tar.gz
---
 .gitignore                  |   58 --
 CHANGELOG                   |   36 +-
 LICENSE                     |   44 +-
 MANIFEST.in                 |   13 +-
 PKG-INFO                    |   76 +-
 README.rst                  |   18 +-
 pluggy.egg-info/PKG-INFO    |   76 +-
 pluggy.egg-info/SOURCES.txt |    2 -
 pluggy.egg-info/pbr.json    |    1 -
 pluggy.py                   | 1579 ++++++++++++++++----------------
 setup.cfg                   |   25 +-
 setup.py                    |   95 +-
 testing/test_pluggy.py      | 2085 ++++++++++++++++++++++---------------------
 tox.ini                     |   49 +-
 14 files changed, 2092 insertions(+), 2065 deletions(-)

diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index e5c7e98..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,58 +0,0 @@
-# Byte-compiled / optimized / DLL files
-__pycache__/
-*.py[cod]
-
-# C extensions
-*.so
-
-# Distribution / packaging
-.Python
-env/
-build/
-develop-eggs/
-dist/
-downloads/
-eggs/
-.eggs/
-lib/
-lib64/
-parts/
-sdist/
-var/
-*.egg-info/
-.installed.cfg
-*.egg
-
-# PyInstaller
-#  Usually these files are written by a python script from a template
-#  before PyInstaller builds the exe, so as to inject date/other infos into it.
-*.manifest
-*.spec
-
-# Installer logs
-pip-log.txt
-pip-delete-this-directory.txt
-
-# Unit test / coverage reports
-htmlcov/
-.tox/
-.coverage
-.coverage.*
-.cache
-nosetests.xml
-coverage.xml
-*,cover
-
-# Translations
-*.mo
-*.pot
-
-# Django stuff:
-*.log
-
-# Sphinx documentation
-docs/_build/
-
-# PyBuilder
-target/
-*.swp
diff --git a/CHANGELOG b/CHANGELOG
index b27c2c4..df7878f 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,11 +1,25 @@
-0.3.1
------
-
-- avoid using deprecated-in-python3.5 getargspec method. Thanks 
-  Michael Droettboom.
-
-
-0.3.0
------
-
-initial release
+0.4.0
+-----
+
+- add has_plugin(name) method to pluginmanager.  thanks Bruno Oliveira.
+
+- fix issue11: make plugin parsing more resilient against exceptions
+  from __getattr__ functions. Thanks Bruno Oliveira.
+
+- fix issue #4: specific HookCallError exception for when a hook call 
+  provides not enough arguments.
+
+- better error message when loading setuptools entrypoints fails
+  due to a VersionConflict.  Thanks Daniel Hahler.
+
+0.3.1
+-----
+
+- avoid using deprecated-in-python3.5 getargspec method. Thanks 
+  Michael Droettboom.
+
+
+0.3.0
+-----
+
+initial release
diff --git a/LICENSE b/LICENSE
index 121017d..b8763ce 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,22 +1,22 @@
-The MIT License (MIT)
-
-Copyright (c) 2015 holger krekel (rather uses bitbucket/hpk42) 
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
+The MIT License (MIT)
+
+Copyright (c) 2015 holger krekel (rather uses bitbucket/hpk42) 
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/MANIFEST.in b/MANIFEST.in
index c6621e2..83c7be0 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,6 +1,7 @@
-include CHANGELOG
-include README.rst
-include setup.py
-include tox.ini
-include LICENSE
-include test_pluggy.py
+include CHANGELOG
+include README.rst
+include setup.py
+include tox.ini
+include LICENSE
+graft testing
+recursive-exclude * *.pyc *.pyo
diff --git a/PKG-INFO b/PKG-INFO
index b16be9e..9de9567 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,38 +1,38 @@
-Metadata-Version: 1.1
-Name: pluggy
-Version: 0.3.1
-Summary: plugin and hook calling mechanisms for python
-Home-page: UNKNOWN
-Author: Holger Krekel
-Author-email: holger at merlinux.eu
-License: MIT license
-Description: 
-        Plugin registration and hook calling for Python
-        ===============================================
-        
-        This is the plugin manager as used by pytest but stripped
-        of pytest specific details.
-        
-        During the 0.x series this plugin does not have much documentation
-        except extensive docstrings in the pluggy.py module.
-        
-Platform: unix
-Platform: linux
-Platform: osx
-Platform: win32
-Classifier: Development Status :: 4 - Beta
-Classifier: Intended Audience :: Developers
-Classifier: License :: OSI Approved :: MIT License
-Classifier: Operating System :: POSIX
-Classifier: Operating System :: Microsoft :: Windows
-Classifier: Operating System :: MacOS :: MacOS X
-Classifier: Topic :: Software Development :: Testing
-Classifier: Topic :: Software Development :: Libraries
-Classifier: Topic :: Utilities
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.6
-Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.3
-Classifier: Programming Language :: Python :: 3.4
-Classifier: Programming Language :: Python :: 3.5
+Metadata-Version: 1.1
+Name: pluggy
+Version: 0.4.0
+Summary: plugin and hook calling mechanisms for python
+Home-page: https://github.com/pytest-dev/pluggy
+Author: Holger Krekel
+Author-email: holger at merlinux.eu
+License: MIT license
+Description: 
+        Plugin registration and hook calling for Python
+        ===============================================
+        
+        This is the plugin manager as used by pytest but stripped
+        of pytest specific details.
+        
+        During the 0.x series this plugin does not have much documentation
+        except extensive docstrings in the pluggy.py module.
+        
+Platform: unix
+Platform: linux
+Platform: osx
+Platform: win32
+Classifier: Development Status :: 4 - Beta
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Operating System :: POSIX
+Classifier: Operating System :: Microsoft :: Windows
+Classifier: Operating System :: MacOS :: MacOS X
+Classifier: Topic :: Software Development :: Testing
+Classifier: Topic :: Software Development :: Libraries
+Classifier: Topic :: Utilities
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
diff --git a/README.rst b/README.rst
index 8b15e9a..cb2e9fe 100644
--- a/README.rst
+++ b/README.rst
@@ -1,9 +1,9 @@
-
-Plugin registration and hook calling for Python
-===============================================
-
-This is the plugin manager as used by pytest but stripped
-of pytest specific details.
-
-During the 0.x series this plugin does not have much documentation
-except extensive docstrings in the pluggy.py module.
+
+Plugin registration and hook calling for Python
+===============================================
+
+This is the plugin manager as used by pytest but stripped
+of pytest specific details.
+
+During the 0.x series this plugin does not have much documentation
+except extensive docstrings in the pluggy.py module.
diff --git a/pluggy.egg-info/PKG-INFO b/pluggy.egg-info/PKG-INFO
index b16be9e..9de9567 100644
--- a/pluggy.egg-info/PKG-INFO
+++ b/pluggy.egg-info/PKG-INFO
@@ -1,38 +1,38 @@
-Metadata-Version: 1.1
-Name: pluggy
-Version: 0.3.1
-Summary: plugin and hook calling mechanisms for python
-Home-page: UNKNOWN
-Author: Holger Krekel
-Author-email: holger at merlinux.eu
-License: MIT license
-Description: 
-        Plugin registration and hook calling for Python
-        ===============================================
-        
-        This is the plugin manager as used by pytest but stripped
-        of pytest specific details.
-        
-        During the 0.x series this plugin does not have much documentation
-        except extensive docstrings in the pluggy.py module.
-        
-Platform: unix
-Platform: linux
-Platform: osx
-Platform: win32
-Classifier: Development Status :: 4 - Beta
-Classifier: Intended Audience :: Developers
-Classifier: License :: OSI Approved :: MIT License
-Classifier: Operating System :: POSIX
-Classifier: Operating System :: Microsoft :: Windows
-Classifier: Operating System :: MacOS :: MacOS X
-Classifier: Topic :: Software Development :: Testing
-Classifier: Topic :: Software Development :: Libraries
-Classifier: Topic :: Utilities
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.6
-Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.3
-Classifier: Programming Language :: Python :: 3.4
-Classifier: Programming Language :: Python :: 3.5
+Metadata-Version: 1.1
+Name: pluggy
+Version: 0.4.0
+Summary: plugin and hook calling mechanisms for python
+Home-page: https://github.com/pytest-dev/pluggy
+Author: Holger Krekel
+Author-email: holger at merlinux.eu
+License: MIT license
+Description: 
+        Plugin registration and hook calling for Python
+        ===============================================
+        
+        This is the plugin manager as used by pytest but stripped
+        of pytest specific details.
+        
+        During the 0.x series this plugin does not have much documentation
+        except extensive docstrings in the pluggy.py module.
+        
+Platform: unix
+Platform: linux
+Platform: osx
+Platform: win32
+Classifier: Development Status :: 4 - Beta
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Operating System :: POSIX
+Classifier: Operating System :: Microsoft :: Windows
+Classifier: Operating System :: MacOS :: MacOS X
+Classifier: Topic :: Software Development :: Testing
+Classifier: Topic :: Software Development :: Libraries
+Classifier: Topic :: Utilities
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
diff --git a/pluggy.egg-info/SOURCES.txt b/pluggy.egg-info/SOURCES.txt
index 29fc89c..65af274 100644
--- a/pluggy.egg-info/SOURCES.txt
+++ b/pluggy.egg-info/SOURCES.txt
@@ -1,4 +1,3 @@
-.gitignore
 CHANGELOG
 LICENSE
 MANIFEST.in
@@ -10,6 +9,5 @@ tox.ini
 pluggy.egg-info/PKG-INFO
 pluggy.egg-info/SOURCES.txt
 pluggy.egg-info/dependency_links.txt
-pluggy.egg-info/pbr.json
 pluggy.egg-info/top_level.txt
 testing/test_pluggy.py
\ No newline at end of file
diff --git a/pluggy.egg-info/pbr.json b/pluggy.egg-info/pbr.json
deleted file mode 100644
index d6b7986..0000000
--- a/pluggy.egg-info/pbr.json
+++ /dev/null
@@ -1 +0,0 @@
-{"is_release": false, "git_version": "7d4c9cd"}
\ No newline at end of file
diff --git a/pluggy.py b/pluggy.py
index 2090dbb..aa7d8c9 100644
--- a/pluggy.py
+++ b/pluggy.py
@@ -1,777 +1,802 @@
-"""
-PluginManager, basic initialization and tracing.
-
-pluggy is the cristallized core of plugin management as used
-by some 150 plugins for pytest.
-
-Pluggy uses semantic versioning. Breaking changes are only foreseen for
-Major releases (incremented X in "X.Y.Z").  If you want to use pluggy in
-your project you should thus use a dependency restriction like
-"pluggy>=0.1.0,<1.0" to avoid surprises.
-
-pluggy is concerned with hook specification, hook implementations and hook
-calling.  For any given hook specification a hook call invokes up to N implementations.
-A hook implementation can influence its position and type of execution:
-if attributed "tryfirst" or "trylast" it will be tried to execute
-first or last.  However, if attributed "hookwrapper" an implementation
-can wrap all calls to non-hookwrapper implementations.  A hookwrapper
-can thus execute some code ahead and after the execution of other hooks.
-
-Hook specification is done by way of a regular python function where
-both the function name and the names of all its arguments are significant.
-Each hook implementation function is verified against the original specification
-function, including the names of all its arguments.  To allow for hook specifications
-to evolve over the livetime of a project, hook implementations can
-accept less arguments.  One can thus add new arguments and semantics to
-a hook specification by adding another argument typically without breaking
-existing hook implementations.
-
-The chosen approach is meant to let a hook designer think carefuly about
-which objects are needed by an extension writer.  By contrast, subclass-based
-extension mechanisms often expose a lot more state and behaviour than needed,
-thus restricting future developments.
-
-Pluggy currently consists of functionality for:
-
-- a way to register new hook specifications.  Without a hook
-  specification no hook calling can be performed.
-
-- a registry of plugins which contain hook implementation functions.  It
-  is possible to register plugins for which a hook specification is not yet
-  known and validate all hooks when the system is in a more referentially
-  consistent state.  Setting an "optionalhook" attribution to a hook
-  implementation will avoid PluginValidationError's if a specification
-  is missing.  This allows to have optional integration between plugins.
-
-- a "hook" relay object from which you can launch 1:N calls to
-  registered hook implementation functions
-
-- a mechanism for ordering hook implementation functions
-
-- mechanisms for two different type of 1:N calls: "firstresult" for when
-  the call should stop when the first implementation returns a non-None result.
-  And the other (default) way of guaranteeing that all hook implementations
-  will be called and their non-None result collected.
-
-- mechanisms for "historic" extension points such that all newly
-  registered functions will receive all hook calls that happened
-  before their registration.
-
-- a mechanism for discovering plugin objects which are based on
-  setuptools based entry points.
-
-- a simple tracing mechanism, including tracing of plugin calls and
-  their arguments.
-
-"""
-import sys
-import inspect
-
-__version__ = '0.3.1'
-__all__ = ["PluginManager", "PluginValidationError",
-           "HookspecMarker", "HookimplMarker"]
-
-_py3 = sys.version_info > (3, 0)
-
-
-class HookspecMarker:
-    """ Decorator helper class for marking functions as hook specifications.
-
-    You can instantiate it with a project_name to get a decorator.
-    Calling PluginManager.add_hookspecs later will discover all marked functions
-    if the PluginManager uses the same project_name.
-    """
-
-    def __init__(self, project_name):
-        self.project_name = project_name
-
-    def __call__(self, function=None, firstresult=False, historic=False):
-        """ if passed a function, directly sets attributes on the function
-        which will make it discoverable to add_hookspecs().  If passed no
-        function, returns a decorator which can be applied to a function
-        later using the attributes supplied.
-
-        If firstresult is True the 1:N hook call (N being the number of registered
-        hook implementation functions) will stop at I<=N when the I'th function
-        returns a non-None result.
-
-        If historic is True calls to a hook will be memorized and replayed
-        on later registered plugins.
-
-        """
-        def setattr_hookspec_opts(func):
-            if historic and firstresult:
-                raise ValueError("cannot have a historic firstresult hook")
-            setattr(func, self.project_name + "_spec",
-                   dict(firstresult=firstresult, historic=historic))
-            return func
-
-        if function is not None:
-            return setattr_hookspec_opts(function)
-        else:
-            return setattr_hookspec_opts
-
-
-class HookimplMarker:
-    """ Decorator helper class for marking functions as hook implementations.
-
-    You can instantiate with a project_name to get a decorator.
-    Calling PluginManager.register later will discover all marked functions
-    if the PluginManager uses the same project_name.
-    """
-    def __init__(self, project_name):
-        self.project_name = project_name
-
-    def __call__(self, function=None, hookwrapper=False, optionalhook=False,
-                 tryfirst=False, trylast=False):
-
-        """ if passed a function, directly sets attributes on the function
-        which will make it discoverable to register().  If passed no function,
-        returns a decorator which can be applied to a function later using
-        the attributes supplied.
-
-        If optionalhook is True a missing matching hook specification will not result
-        in an error (by default it is an error if no matching spec is found).
-
-        If tryfirst is True this hook implementation will run as early as possible
-        in the chain of N hook implementations for a specfication.
-
-        If trylast is True this hook implementation will run as late as possible
-        in the chain of N hook implementations.
-
-        If hookwrapper is True the hook implementations needs to execute exactly
-        one "yield".  The code before the yield is run early before any non-hookwrapper
-        function is run.  The code after the yield is run after all non-hookwrapper
-        function have run.  The yield receives an ``_CallOutcome`` object representing
-        the exception or result outcome of the inner calls (including other hookwrapper
-        calls).
-
-        """
-        def setattr_hookimpl_opts(func):
-            setattr(func, self.project_name + "_impl",
-                   dict(hookwrapper=hookwrapper, optionalhook=optionalhook,
-                        tryfirst=tryfirst, trylast=trylast))
-            return func
-
-        if function is None:
-            return setattr_hookimpl_opts
-        else:
-            return setattr_hookimpl_opts(function)
-
-
-def normalize_hookimpl_opts(opts):
-    opts.setdefault("tryfirst", False)
-    opts.setdefault("trylast", False)
-    opts.setdefault("hookwrapper", False)
-    opts.setdefault("optionalhook", False)
-
-
-class _TagTracer:
-    def __init__(self):
-        self._tag2proc = {}
-        self.writer = None
-        self.indent = 0
-
-    def get(self, name):
-        return _TagTracerSub(self, (name,))
-
-    def format_message(self, tags, args):
-        if isinstance(args[-1], dict):
-            extra = args[-1]
-            args = args[:-1]
-        else:
-            extra = {}
-
-        content = " ".join(map(str, args))
-        indent = "  " * self.indent
-
-        lines = [
-            "%s%s [%s]\n" % (indent, content, ":".join(tags))
-        ]
-
-        for name, value in extra.items():
-            lines.append("%s    %s: %s\n" % (indent, name, value))
-        return lines
-
-    def processmessage(self, tags, args):
-        if self.writer is not None and args:
-            lines = self.format_message(tags, args)
-            self.writer(''.join(lines))
-        try:
-            self._tag2proc[tags](tags, args)
-        except KeyError:
-            pass
-
-    def setwriter(self, writer):
-        self.writer = writer
-
-    def setprocessor(self, tags, processor):
-        if isinstance(tags, str):
-            tags = tuple(tags.split(":"))
-        else:
-            assert isinstance(tags, tuple)
-        self._tag2proc[tags] = processor
-
-
-class _TagTracerSub:
-    def __init__(self, root, tags):
-        self.root = root
-        self.tags = tags
-
-    def __call__(self, *args):
-        self.root.processmessage(self.tags, args)
-
-    def setmyprocessor(self, processor):
-        self.root.setprocessor(self.tags, processor)
-
-    def get(self, name):
-        return self.__class__(self.root, self.tags + (name,))
-
-
-def _raise_wrapfail(wrap_controller, msg):
-    co = wrap_controller.gi_code
-    raise RuntimeError("wrap_controller at %r %s:%d %s" %
-                   (co.co_name, co.co_filename, co.co_firstlineno, msg))
-
-
-def _wrapped_call(wrap_controller, func):
-    """ Wrap calling to a function with a generator which needs to yield
-    exactly once.  The yield point will trigger calling the wrapped function
-    and return its _CallOutcome to the yield point.  The generator then needs
-    to finish (raise StopIteration) in order for the wrapped call to complete.
-    """
-    try:
-        next(wrap_controller)   # first yield
-    except StopIteration:
-        _raise_wrapfail(wrap_controller, "did not yield")
-    call_outcome = _CallOutcome(func)
-    try:
-        wrap_controller.send(call_outcome)
-        _raise_wrapfail(wrap_controller, "has second yield")
-    except StopIteration:
-        pass
-    return call_outcome.get_result()
-
-
-class _CallOutcome:
-    """ Outcome of a function call, either an exception or a proper result.
-    Calling the ``get_result`` method will return the result or reraise
-    the exception raised when the function was called. """
-    excinfo = None
-
-    def __init__(self, func):
-        try:
-            self.result = func()
-        except BaseException:
-            self.excinfo = sys.exc_info()
-
-    def force_result(self, result):
-        self.result = result
-        self.excinfo = None
-
-    def get_result(self):
-        if self.excinfo is None:
-            return self.result
-        else:
-            ex = self.excinfo
-            if _py3:
-                raise ex[1].with_traceback(ex[2])
-            _reraise(*ex)  # noqa
-
-if not _py3:
-    exec("""
-def _reraise(cls, val, tb):
-    raise cls, val, tb
-""")
-
-
-class _TracedHookExecution:
-    def __init__(self, pluginmanager, before, after):
-        self.pluginmanager = pluginmanager
-        self.before = before
-        self.after = after
-        self.oldcall = pluginmanager._inner_hookexec
-        assert not isinstance(self.oldcall, _TracedHookExecution)
-        self.pluginmanager._inner_hookexec = self
-
-    def __call__(self, hook, hook_impls, kwargs):
-        self.before(hook.name, hook_impls, kwargs)
-        outcome = _CallOutcome(lambda: self.oldcall(hook, hook_impls, kwargs))
-        self.after(outcome, hook.name, hook_impls, kwargs)
-        return outcome.get_result()
-
-    def undo(self):
-        self.pluginmanager._inner_hookexec = self.oldcall
-
-
-class PluginManager(object):
-    """ Core Pluginmanager class which manages registration
-    of plugin objects and 1:N hook calling.
-
-    You can register new hooks by calling ``addhooks(module_or_class)``.
-    You can register plugin objects (which contain hooks) by calling
-    ``register(plugin)``.  The Pluginmanager is initialized with a
-    prefix that is searched for in the names of the dict of registered
-    plugin objects.  An optional excludefunc allows to blacklist names which
-    are not considered as hooks despite a matching prefix.
-
-    For debugging purposes you can call ``enable_tracing()``
-    which will subsequently send debug information to the trace helper.
-    """
-
-    def __init__(self, project_name, implprefix=None):
-        """ if implprefix is given implementation functions
-        will be recognized if their name matches the implprefix. """
-        self.project_name = project_name
-        self._name2plugin = {}
-        self._plugin2hookcallers = {}
-        self._plugin_distinfo = []
-        self.trace = _TagTracer().get("pluginmanage")
-        self.hook = _HookRelay(self.trace.root.get("hook"))
-        self._implprefix = implprefix
-        self._inner_hookexec = lambda hook, methods, kwargs: \
-            _MultiCall(methods, kwargs, hook.spec_opts).execute()
-
-    def _hookexec(self, hook, methods, kwargs):
-        # called from all hookcaller instances.
-        # enable_tracing will set its own wrapping function at self._inner_hookexec
-        return self._inner_hookexec(hook, methods, kwargs)
-
-    def register(self, plugin, name=None):
-        """ Register a plugin and return its canonical name or None if the name
-        is blocked from registering.  Raise a ValueError if the plugin is already
-        registered. """
-        plugin_name = name or self.get_canonical_name(plugin)
-
-        if plugin_name in self._name2plugin or plugin in self._plugin2hookcallers:
-            if self._name2plugin.get(plugin_name, -1) is None:
-                return  # blocked plugin, return None to indicate no registration
-            raise ValueError("Plugin already registered: %s=%s\n%s" %
-                            (plugin_name, plugin, self._name2plugin))
-
-        # XXX if an error happens we should make sure no state has been
-        # changed at point of return
-        self._name2plugin[plugin_name] = plugin
-
-        # register matching hook implementations of the plugin
-        self._plugin2hookcallers[plugin] = hookcallers = []
-        for name in dir(plugin):
-            hookimpl_opts = self.parse_hookimpl_opts(plugin, name)
-            if hookimpl_opts is not None:
-                normalize_hookimpl_opts(hookimpl_opts)
-                method = getattr(plugin, name)
-                hookimpl = HookImpl(plugin, plugin_name, method, hookimpl_opts)
-                hook = getattr(self.hook, name, None)
-                if hook is None:
-                    hook = _HookCaller(name, self._hookexec)
-                    setattr(self.hook, name, hook)
-                elif hook.has_spec():
-                    self._verify_hook(hook, hookimpl)
-                    hook._maybe_apply_history(hookimpl)
-                hook._add_hookimpl(hookimpl)
-                hookcallers.append(hook)
-        return plugin_name
-
-    def parse_hookimpl_opts(self, plugin, name):
-        method = getattr(plugin, name)
-        res = getattr(method, self.project_name + "_impl", None)
-        if res is not None and not isinstance(res, dict):
-            # false positive
-            res = None
-        elif res is None and self._implprefix and name.startswith(self._implprefix):
-            res = {}
-        return res
-
-    def unregister(self, plugin=None, name=None):
-        """ unregister a plugin object and all its contained hook implementations
-        from internal data structures. """
-        if name is None:
-            assert plugin is not None, "one of name or plugin needs to be specified"
-            name = self.get_name(plugin)
-
-        if plugin is None:
-            plugin = self.get_plugin(name)
-
-        # if self._name2plugin[name] == None registration was blocked: ignore
-        if self._name2plugin.get(name):
-            del self._name2plugin[name]
-
-        for hookcaller in self._plugin2hookcallers.pop(plugin, []):
-            hookcaller._remove_plugin(plugin)
-
-        return plugin
-
-    def set_blocked(self, name):
-        """ block registrations of the given name, unregister if already registered. """
-        self.unregister(name=name)
-        self._name2plugin[name] = None
-
-    def is_blocked(self, name):
-        """ return True if the name blogs registering plugins of that name. """
-        return name in self._name2plugin and self._name2plugin[name] is None
-
-    def add_hookspecs(self, module_or_class):
-        """ add new hook specifications defined in the given module_or_class.
-        Functions are recognized if they have been decorated accordingly. """
-        names = []
-        for name in dir(module_or_class):
-            spec_opts = self.parse_hookspec_opts(module_or_class, name)
-            if spec_opts is not None:
-                hc = getattr(self.hook, name, None)
-                if hc is None:
-                    hc = _HookCaller(name, self._hookexec, module_or_class, spec_opts)
-                    setattr(self.hook, name, hc)
-                else:
-                    # plugins registered this hook without knowing the spec
-                    hc.set_specification(module_or_class, spec_opts)
-                    for hookfunction in (hc._wrappers + hc._nonwrappers):
-                        self._verify_hook(hc, hookfunction)
-                names.append(name)
-
-        if not names:
-            raise ValueError("did not find any %r hooks in %r" %
-                             (self.project_name, module_or_class))
-
-    def parse_hookspec_opts(self, module_or_class, name):
-        method = getattr(module_or_class, name)
-        return getattr(method, self.project_name + "_spec", None)
-
-    def get_plugins(self):
-        """ return the set of registered plugins. """
-        return set(self._plugin2hookcallers)
-
-    def is_registered(self, plugin):
-        """ Return True if the plugin is already registered. """
-        return plugin in self._plugin2hookcallers
-
-    def get_canonical_name(self, plugin):
-        """ Return canonical name for a plugin object. Note that a plugin
-        may be registered under a different name which was specified
-        by the caller of register(plugin, name). To obtain the name
-        of an registered plugin use ``get_name(plugin)`` instead."""
-        return getattr(plugin, "__name__", None) or str(id(plugin))
-
-    def get_plugin(self, name):
-        """ Return a plugin or None for the given name. """
-        return self._name2plugin.get(name)
-
-    def get_name(self, plugin):
-        """ Return name for registered plugin or None if not registered. """
-        for name, val in self._name2plugin.items():
-            if plugin == val:
-                return name
-
-    def _verify_hook(self, hook, hookimpl):
-        if hook.is_historic() and hookimpl.hookwrapper:
-            raise PluginValidationError(
-                "Plugin %r\nhook %r\nhistoric incompatible to hookwrapper" %
-                (hookimpl.plugin_name, hook.name))
-
-        for arg in hookimpl.argnames:
-            if arg not in hook.argnames:
-                raise PluginValidationError(
-                    "Plugin %r\nhook %r\nargument %r not available\n"
-                    "plugin definition: %s\n"
-                    "available hookargs: %s" %
-                    (hookimpl.plugin_name, hook.name, arg,
-                    _formatdef(hookimpl.function), ", ".join(hook.argnames)))
-
-    def check_pending(self):
-        """ Verify that all hooks which have not been verified against
-        a hook specification are optional, otherwise raise PluginValidationError"""
-        for name in self.hook.__dict__:
-            if name[0] != "_":
-                hook = getattr(self.hook, name)
-                if not hook.has_spec():
-                    for hookimpl in (hook._wrappers + hook._nonwrappers):
-                        if not hookimpl.optionalhook:
-                            raise PluginValidationError(
-                                "unknown hook %r in plugin %r" %
-                                (name, hookimpl.plugin))
-
-    def load_setuptools_entrypoints(self, entrypoint_name):
-        """ Load modules from querying the specified setuptools entrypoint name.
-        Return the number of loaded plugins. """
-        from pkg_resources import iter_entry_points, DistributionNotFound
-        for ep in iter_entry_points(entrypoint_name):
-            # is the plugin registered or blocked?
-            if self.get_plugin(ep.name) or self.is_blocked(ep.name):
-                continue
-            try:
-                plugin = ep.load()
-            except DistributionNotFound:
-                continue
-            self.register(plugin, name=ep.name)
-            self._plugin_distinfo.append((plugin, ep.dist))
-        return len(self._plugin_distinfo)
-
-    def list_plugin_distinfo(self):
-        """ return list of distinfo/plugin tuples for all setuptools registered
-        plugins. """
-        return list(self._plugin_distinfo)
-
-    def list_name_plugin(self):
-        """ return list of name/plugin pairs. """
-        return list(self._name2plugin.items())
-
-    def get_hookcallers(self, plugin):
-        """ get all hook callers for the specified plugin. """
-        return self._plugin2hookcallers.get(plugin)
-
-    def add_hookcall_monitoring(self, before, after):
-        """ add before/after tracing functions for all hooks
-        and return an undo function which, when called,
-        will remove the added tracers.
-
-        ``before(hook_name, hook_impls, kwargs)`` will be called ahead
-        of all hook calls and receive a hookcaller instance, a list
-        of HookImpl instances and the keyword arguments for the hook call.
-
-        ``after(outcome, hook_name, hook_impls, kwargs)`` receives the
-        same arguments as ``before`` but also a :py:class:`_CallOutcome`` object
-        which represents the result of the overall hook call.
-        """
-        return _TracedHookExecution(self, before, after).undo
-
-    def enable_tracing(self):
-        """ enable tracing of hook calls and return an undo function. """
-        hooktrace = self.hook._trace
-
-        def before(hook_name, methods, kwargs):
-            hooktrace.root.indent += 1
-            hooktrace(hook_name, kwargs)
-
-        def after(outcome, hook_name, methods, kwargs):
-            if outcome.excinfo is None:
-                hooktrace("finish", hook_name, "-->", outcome.result)
-            hooktrace.root.indent -= 1
-
-        return self.add_hookcall_monitoring(before, after)
-
-    def subset_hook_caller(self, name, remove_plugins):
-        """ Return a new _HookCaller instance for the named method
-        which manages calls to all registered plugins except the
-        ones from remove_plugins. """
-        orig = getattr(self.hook, name)
-        plugins_to_remove = [plug for plug in remove_plugins if hasattr(plug, name)]
-        if plugins_to_remove:
-            hc = _HookCaller(orig.name, orig._hookexec, orig._specmodule_or_class,
-                             orig.spec_opts)
-            for hookimpl in (orig._wrappers + orig._nonwrappers):
-                plugin = hookimpl.plugin
-                if plugin not in plugins_to_remove:
-                    hc._add_hookimpl(hookimpl)
-                    # we also keep track of this hook caller so it
-                    # gets properly removed on plugin unregistration
-                    self._plugin2hookcallers.setdefault(plugin, []).append(hc)
-            return hc
-        return orig
-
-
-class _MultiCall:
-    """ execute a call into multiple python functions/methods. """
-
-    # XXX note that the __multicall__ argument is supported only
-    # for pytest compatibility reasons.  It was never officially
-    # supported there and is explicitely deprecated since 2.8
-    # so we can remove it soon, allowing to avoid the below recursion
-    # in execute() and simplify/speed up the execute loop.
-
-    def __init__(self, hook_impls, kwargs, specopts={}):
-        self.hook_impls = hook_impls
-        self.kwargs = kwargs
-        self.kwargs["__multicall__"] = self
-        self.specopts = specopts
-
-    def execute(self):
-        all_kwargs = self.kwargs
-        self.results = results = []
-        firstresult = self.specopts.get("firstresult")
-
-        while self.hook_impls:
... 3262 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-pluggy.git



More information about the Python-modules-commits mailing list