Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

introduce pyupgrade and update black #319

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 9 additions & 4 deletions .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:
Expand All @@ -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]
12 changes: 4 additions & 8 deletions README.rst
Expand Up @@ -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):
Expand All @@ -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):
Expand Down
15 changes: 5 additions & 10 deletions docs/index.rst
Expand Up @@ -319,17 +319,15 @@ 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)

return config


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):
Expand Down Expand Up @@ -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


Expand Down
20 changes: 9 additions & 11 deletions src/pluggy/_hooks.py
Expand Up @@ -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
Expand All @@ -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.
Expand Down Expand Up @@ -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
Expand All @@ -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.
Expand Down Expand Up @@ -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.

"""
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down
52 changes: 26 additions & 26 deletions src/pluggy/_manager.py
Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -186,31 +186,31 @@ 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)
<.PluginManager.get_name>` 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 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
Expand Down Expand Up @@ -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] != "_":
Expand All @@ -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``.
Expand All @@ -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.

Expand Down Expand Up @@ -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):
Expand All @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion src/pluggy/_result.py
Expand Up @@ -13,7 +13,7 @@ def _raise_wrapfail(wrap_controller, msg):


class HookCallError(Exception):
""" Hook was called wrongly. """
"""Hook was called wrongly."""


class _Result:
Expand Down
3 changes: 1 addition & 2 deletions testing/test_invocations.py
Expand Up @@ -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)
Expand Down