diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d8cc4abb..d919ffeb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,14 +1,14 @@ repos: - repo: https://github.com/ambv/black - rev: 19.10b0 + rev: 21.7b0 hooks: - id: black args: [--safe, --quiet] - repo: https://github.com/asottile/blacken-docs - rev: v0.5.0 + rev: v1.10.0 hooks: - id: blacken-docs - additional_dependencies: [black==19.10b0] + additional_dependencies: [black==21.7b0] - repo: https://github.com/pre-commit/pre-commit-hooks rev: v2.1.0 hooks: @@ -24,6 +24,11 @@ repos: language: python additional_dependencies: [pygments, restructuredtext_lint] - repo: https://github.com/pre-commit/pygrep-hooks - rev: v1.3.0 + rev: v1.9.0 hooks: - id: rst-backticks +- repo: https://github.com/asottile/pyupgrade + rev: v2.23.3 + hooks: + - id: pyupgrade + args: [--py36-plus] diff --git a/README.rst b/README.rst index 01e0aa81..3496617e 100644 --- a/README.rst +++ b/README.rst @@ -19,18 +19,15 @@ A definitive example class MySpec: - """A hook specification namespace. - """ + """A hook specification namespace.""" @hookspec def myhook(self, arg1, arg2): - """My special little hook that you can customize. - """ + """My special little hook that you can customize.""" class Plugin_1: - """A hook implementation namespace. - """ + """A hook implementation namespace.""" @hookimpl def myhook(self, arg1, arg2): @@ -39,8 +36,7 @@ A definitive example class Plugin_2: - """A 2nd hook implementation namespace. - """ + """A 2nd hook implementation namespace.""" @hookimpl def myhook(self, arg1, arg2): diff --git a/docs/index.rst b/docs/index.rst index 10367f93..eab08fcb 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -319,8 +319,7 @@ will be executed *first* or *last* respectively in the hook call loop: @hookimpl(trylast=True) def setup_project(config, args): - """Default implementation. - """ + """Default implementation.""" if args: config.process_args(args) @@ -328,8 +327,7 @@ will be executed *first* or *last* respectively in the hook call loop: class SomeOtherPlugin: - """Some other plugin defining the same hook. - """ + """Some other plugin defining the same hook.""" @hookimpl(tryfirst=True) def setup_project(self, config, args): @@ -696,24 +694,21 @@ assertion should not error: class Plugin1: @hookimpl def myhook(self, args): - """Default implementation. - """ + """Default implementation.""" return 1 class Plugin2: @hookimpl def myhook(self, args): - """Default implementation. - """ + """Default implementation.""" return 2 class Plugin3: @hookimpl def myhook(self, args): - """Default implementation. - """ + """Default implementation.""" return 3 diff --git a/src/pluggy/_hooks.py b/src/pluggy/_hooks.py index 6b2a8e4f..1e5fbb75 100644 --- a/src/pluggy/_hooks.py +++ b/src/pluggy/_hooks.py @@ -7,7 +7,7 @@ class HookspecMarker: - """ Decorator helper class for marking functions as hook specifications. + """Decorator helper class for marking functions as hook specifications. You can instantiate it with a project_name to get a decorator. Calling :py:meth:`.PluginManager.add_hookspecs` later will discover all marked functions @@ -20,7 +20,7 @@ def __init__(self, project_name): def __call__( self, function=None, firstresult=False, historic=False, warn_on_impl=None ): - """ if passed a function, directly sets attributes on the function + """if passed a function, directly sets attributes on the function which will make it discoverable to :py:meth:`.PluginManager.add_hookspecs`. If passed no function, returns a decorator which can be applied to a function later using the attributes supplied. @@ -55,7 +55,7 @@ def setattr_hookspec_opts(func): class HookimplMarker: - """ Decorator helper class for marking functions as hook implementations. + """Decorator helper class for marking functions as hook implementations. You can instantiate with a ``project_name`` to get a decorator. Calling :py:meth:`.PluginManager.register` later will discover all marked functions @@ -75,7 +75,7 @@ def __call__( specname=None, ): - """ if passed a function, directly sets attributes on the function + """if passed a function, directly sets attributes on the function which will make it discoverable to :py:meth:`.PluginManager.register`. If passed no function, returns a decorator which can be applied to a function later using the attributes supplied. @@ -175,7 +175,7 @@ def varnames(func): class _HookRelay: - """ hook holder object for performing 1:N hook calls where N is the number + """hook holder object for performing 1:N hook calls where N is the number of registered plugins. """ @@ -221,8 +221,7 @@ def get_hookimpls(self): return self._nonwrappers + self._wrappers def _add_hookimpl(self, hookimpl): - """Add an implementation to the callback chain. - """ + """Add an implementation to the callback chain.""" if hookimpl.hookwrapper: methods = self._wrappers else: @@ -282,8 +281,8 @@ def call_historic(self, result_callback=None, kwargs=None): result_callback(x) def call_extra(self, methods, kwargs): - """ Call the hook with some additional temporarily participating - methods using the specified ``kwargs`` as call parameters. """ + """Call the hook with some additional temporarily participating + methods using the specified ``kwargs`` as call parameters.""" old = list(self._nonwrappers), list(self._wrappers) for method in methods: opts = dict(hookwrapper=False, trylast=False, tryfirst=False) @@ -295,8 +294,7 @@ def call_extra(self, methods, kwargs): self._nonwrappers, self._wrappers = old def _maybe_apply_history(self, method): - """Apply call history to a new hookimpl if it is marked as historic. - """ + """Apply call history to a new hookimpl if it is marked as historic.""" if self.is_historic(): for kwargs, result_callback in self._call_history: res = self._hookexec(self.name, [method], kwargs, False) diff --git a/src/pluggy/_manager.py b/src/pluggy/_manager.py index 15a73309..65f4e508 100644 --- a/src/pluggy/_manager.py +++ b/src/pluggy/_manager.py @@ -22,7 +22,7 @@ def _warn_for_function(warning, function): class PluginValidationError(Exception): - """ plugin failed validation. + """plugin failed validation. :param object plugin: the plugin which failed validation, may be a module or an arbitrary object. @@ -51,7 +51,7 @@ def __dir__(self): class PluginManager: - """ Core :py:class:`.PluginManager` class which manages registration + """Core :py:class:`.PluginManager` class which manages registration of plugin objects and 1:N hook calling. You can register new hooks by calling :py:meth:`add_hookspecs(module_or_class) @@ -80,9 +80,9 @@ def _hookexec(self, hook_name, methods, kwargs, firstresult): return self._inner_hookexec(hook_name, methods, kwargs, firstresult) def register(self, plugin, name=None): - """ Register a plugin and return its canonical name or ``None`` if the name + """Register a plugin and return its canonical name or ``None`` if the name is blocked from registering. Raise a :py:class:`ValueError` if the plugin - is already registered. """ + is already registered.""" plugin_name = name or self.get_canonical_name(plugin) if plugin_name in self._name2plugin or plugin in self._plugin2hookcallers: @@ -131,8 +131,8 @@ def parse_hookimpl_opts(self, plugin, name): return res def unregister(self, plugin=None, name=None): - """ unregister a plugin object and all its contained hook implementations - from internal data structures. """ + """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) @@ -150,17 +150,17 @@ def unregister(self, plugin=None, name=None): return plugin def set_blocked(self, name): - """ block registrations of the given name, unregister if already registered. """ + """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 given plugin name is blocked. """ + """return ``True`` if the given plugin name is blocked.""" 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. """ + """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) @@ -186,15 +186,15 @@ def parse_hookspec_opts(self, module_or_class, name): return getattr(method, self.project_name + "_spec", None) def get_plugins(self): - """ return the set of registered plugins. """ + """return the set of registered plugins.""" return set(self._plugin2hookcallers) def is_registered(self, plugin): - """ Return ``True`` if the plugin is already registered. """ + """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 + """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 :py:meth:`register(plugin, name) <.PluginManager.register>`. To obtain the name of an registered plugin use :py:meth:`get_name(plugin) @@ -202,15 +202,15 @@ def get_canonical_name(self, plugin): return getattr(plugin, "__name__", None) or str(id(plugin)) def get_plugin(self, name): - """ Return a plugin or ``None`` for the given name. """ + """Return a plugin or ``None`` for the given name.""" return self._name2plugin.get(name) def has_plugin(self, name): - """ Return ``True`` if a plugin with the given name is registered. """ + """Return ``True`` if a plugin with the given name is registered.""" return self.get_plugin(name) is not None def get_name(self, plugin): - """ Return name for registered plugin or ``None`` if not registered. """ + """Return name for registered plugin or ``None`` if not registered.""" for name, val in self._name2plugin.items(): if plugin == val: return name @@ -251,7 +251,7 @@ def _verify_hook(self, hook, hookimpl): ) def check_pending(self): - """ Verify that all hooks which have not been verified against + """Verify that all hooks which have not been verified against a hook specification are optional, otherwise raise :py:class:`.PluginValidationError`.""" for name in self.hook.__dict__: if name[0] != "_": @@ -266,7 +266,7 @@ def check_pending(self): ) def load_setuptools_entrypoints(self, group, name=None): - """ Load modules from querying the specified setuptools ``group``. + """Load modules from querying the specified setuptools ``group``. :param str group: entry point group to load plugins :param str name: if given, loads only plugins with the given ``name``. @@ -291,20 +291,20 @@ def load_setuptools_entrypoints(self, group, name=None): return count def list_plugin_distinfo(self): - """ return list of distinfo/plugin tuples for all setuptools registered - plugins. """ + """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 of name/plugin pairs.""" return list(self._name2plugin.items()) def get_hookcallers(self, plugin): - """ get all hook callers for the specified 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 + """add before/after tracing functions for all hooks and return an undo function which, when called, will remove the added tracers. @@ -334,7 +334,7 @@ def undo(): return undo def enable_tracing(self): - """ enable tracing of hook calls and return an undo function. """ + """enable tracing of hook calls and return an undo function.""" hooktrace = self.trace.root.get("hook") def before(hook_name, methods, kwargs): @@ -349,9 +349,9 @@ def after(outcome, hook_name, methods, kwargs): return self.add_hookcall_monitoring(before, after) def subset_hook_caller(self, name, remove_plugins): - """ Return a new :py:class:`._hooks._HookCaller` instance for the named method + """Return a new :py:class:`._hooks._HookCaller` instance for the named method which manages calls to all registered plugins except the - ones from remove_plugins. """ + 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: diff --git a/src/pluggy/_result.py b/src/pluggy/_result.py index 9ac6af97..4c1f7f1f 100644 --- a/src/pluggy/_result.py +++ b/src/pluggy/_result.py @@ -13,7 +13,7 @@ def _raise_wrapfail(wrap_controller, msg): class HookCallError(Exception): - """ Hook was called wrongly. """ + """Hook was called wrongly.""" class _Result: diff --git a/testing/test_invocations.py b/testing/test_invocations.py index 08a13349..323b9b21 100644 --- a/testing/test_invocations.py +++ b/testing/test_invocations.py @@ -144,8 +144,7 @@ def hello(self, arg): def test_firstresult_force_result(pm): - """Verify forcing a result in a wrapper. - """ + """Verify forcing a result in a wrapper.""" class Api: @hookspec(firstresult=True)