Skip to content

Commit 24f5da0

Browse files
cleanups
* switch ruff config to extend-select and enable UP rules * make mypy --strict pass for src
1 parent 4ba6441 commit 24f5da0

File tree

6 files changed

+246
-155
lines changed

6 files changed

+246
-155
lines changed

src/pluggy/_callers.py

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,38 @@
44

55
from __future__ import annotations
66

7-
from typing import cast
8-
from typing import Generator
9-
from typing import Mapping
10-
from typing import NoReturn
11-
from typing import Sequence
12-
from typing import Tuple
13-
from typing import Union
147
import warnings
158

169
from ._hooks import HookImpl
10+
from ._result import _raise_wrapfail
1711
from ._result import HookCallError
1812
from ._result import Result
19-
from ._warnings import PluggyTeardownRaisedWarning
20-
2113

22-
# Need to distinguish between old- and new-style hook wrappers.
23-
# Wrapping with a tuple is the fastest type-safe way I found to do it.
24-
Teardown = Union[
25-
Tuple[Generator[None, Result[object], None], HookImpl],
14+
TYPE_CHECKING = False
15+
if TYPE_CHECKING:
16+
from typing import cast
17+
from typing import Generator
18+
from typing import Mapping
19+
from typing import NoReturn
20+
from typing import Sequence
21+
from typing import Tuple
22+
from typing import Union
23+
24+
25+
# Need to distinguish between old- and new-style hook wrappers.
26+
# Wrapping with a tuple is the fastest type-safe way I found to do it.
27+
Teardown = Union[
28+
Tuple[Generator[None, Result[object], None], HookImpl],
2629
Generator[None, object, object],
2730
]
2831

32+
from ._hooks import HookImpl
33+
from ._result import HookCallError
34+
from ._result import Result
35+
from ._warnings import PluggyTeardownRaisedWarning
36+
37+
38+
2939

3040
def _raise_wrapfail(
3141
wrap_controller: (

src/pluggy/_hooks.py

Lines changed: 78 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -4,76 +4,87 @@
44

55
from __future__ import annotations
66

7-
import inspect
87
import sys
9-
from types import ModuleType
10-
from typing import AbstractSet
11-
from typing import Any
12-
from typing import Callable
13-
from typing import Final
14-
from typing import final
15-
from typing import Generator
16-
from typing import List
17-
from typing import Mapping
18-
from typing import Optional
19-
from typing import overload
20-
from typing import Sequence
21-
from typing import Tuple
22-
from typing import TYPE_CHECKING
23-
from typing import TypedDict
24-
from typing import TypeVar
25-
from typing import Union
268
import warnings
279

28-
from ._result import Result
10+
_Plugin = object
11+
12+
TYPE_CHECKING = False
13+
if TYPE_CHECKING:
14+
from types import ModuleType
15+
from typing import AbstractSet
16+
from typing import Any
17+
from typing import Callable
18+
from typing import Final
19+
from typing import final
20+
from typing import Generator
21+
from typing import List
22+
from typing import Mapping
23+
from typing import Optional
24+
from typing import overload
25+
from typing import Sequence
26+
from typing import Tuple
27+
from typing import TYPE_CHECKING
28+
from typing import TypedDict
29+
from typing import TypeVar
30+
from typing import Union
31+
32+
from ._result import Result
33+
34+
35+
_T = TypeVar("_T")
36+
_F = TypeVar("_F", bound=Callable[..., object])
37+
_Namespace = Union[ModuleType, type]
38+
_HookExec = Callable[
39+
[str, Sequence["HookImpl"], Mapping[str, object], bool],
40+
Union[object, List[object]],
41+
]
42+
_HookImplFunction = Callable[..., Union[_T, Generator[None, Result[_T], None]]]
43+
_CallHistory = List[Tuple[Mapping[str, object], Optional[Callable[[Any], None]]]]
44+
45+
46+
class HookspecOpts(TypedDict):
47+
"""Options for a hook specification."""
48+
49+
#: Whether the hook is :ref:`first result only <firstresult>`.
50+
firstresult: bool
51+
#: Whether the hook is :ref:`historic <historic>`.
52+
historic: bool
53+
#: Whether the hook :ref:`warns when implemented <warn_on_impl>`.
54+
warn_on_impl: Warning | None
55+
#: Whether the hook warns when :ref:`certain arguments are requested
56+
#: <warn_on_impl>`.
57+
#:
58+
#: .. versionadded:: 1.5
59+
warn_on_impl_args: Mapping[str, Warning] | None
60+
61+
62+
class HookimplOpts(TypedDict):
63+
"""Options for a hook implementation."""
64+
65+
#: Whether the hook implementation is a :ref:`wrapper <hookwrapper>`.
66+
wrapper: bool
67+
#: Whether the hook implementation is an :ref:`old-style wrapper
68+
#: <old_style_hookwrappers>`.
69+
hookwrapper: bool
70+
#: Whether validation against a hook specification is :ref:`optional
71+
#: <optionalhook>`.
72+
optionalhook: bool
73+
#: Whether to try to order this hook implementation :ref:`first
74+
#: <callorder>`.
75+
tryfirst: bool
76+
#: Whether to try to order this hook implementation :ref:`last
77+
#: <callorder>`.
78+
trylast: bool
79+
#: The name of the hook specification to match, see :ref:`specname`.
80+
specname: str | None
81+
82+
else:
83+
def final(func: _F) -> _F:
84+
return func
85+
overload = final
2986

3087

31-
_T = TypeVar("_T")
32-
_F = TypeVar("_F", bound=Callable[..., object])
33-
_Namespace = Union[ModuleType, type]
34-
_Plugin = object
35-
_HookExec = Callable[
36-
[str, Sequence["HookImpl"], Mapping[str, object], bool],
37-
Union[object, List[object]],
38-
]
39-
_HookImplFunction = Callable[..., Union[_T, Generator[None, Result[_T], None]]]
40-
41-
42-
class HookspecOpts(TypedDict):
43-
"""Options for a hook specification."""
44-
45-
#: Whether the hook is :ref:`first result only <firstresult>`.
46-
firstresult: bool
47-
#: Whether the hook is :ref:`historic <historic>`.
48-
historic: bool
49-
#: Whether the hook :ref:`warns when implemented <warn_on_impl>`.
50-
warn_on_impl: Warning | None
51-
#: Whether the hook warns when :ref:`certain arguments are requested
52-
#: <warn_on_impl>`.
53-
#:
54-
#: .. versionadded:: 1.5
55-
warn_on_impl_args: Mapping[str, Warning] | None
56-
57-
58-
class HookimplOpts(TypedDict):
59-
"""Options for a hook implementation."""
60-
61-
#: Whether the hook implementation is a :ref:`wrapper <hookwrapper>`.
62-
wrapper: bool
63-
#: Whether the hook implementation is an :ref:`old-style wrapper
64-
#: <old_style_hookwrappers>`.
65-
hookwrapper: bool
66-
#: Whether validation against a hook specification is :ref:`optional
67-
#: <optionalhook>`.
68-
optionalhook: bool
69-
#: Whether to try to order this hook implementation :ref:`first
70-
#: <callorder>`.
71-
tryfirst: bool
72-
#: Whether to try to order this hook implementation :ref:`last
73-
#: <callorder>`.
74-
trylast: bool
75-
#: The name of the hook specification to match, see :ref:`specname`.
76-
specname: str | None
7788

7889

7990
@final
@@ -299,6 +310,8 @@ def varnames(func: object) -> tuple[tuple[str, ...], tuple[str, ...]]:
299310
In case of a class, its ``__init__`` method is considered.
300311
For methods the ``self`` parameter is not included.
301312
"""
313+
import inspect
314+
302315
if inspect.isclass(func):
303316
try:
304317
func = func.__init__

src/pluggy/_importlib_metadata.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
"""this module contains importlib_metadata usage and importing
2+
3+
it's deferred to avoid import-time dependency on importlib_metadata
4+
5+
.. code-block:: console
6+
7+
python -X importtime -c 'import pluggy' 2> import0.log
8+
tuna import0.log
9+
10+
11+
"""
12+
from __future__ import annotations
13+
14+
import importlib.metadata
15+
from typing import Any
16+
17+
from . import _manager
18+
19+
20+
class DistFacade:
21+
"""Emulate a pkg_resources Distribution"""
22+
23+
def __init__(self, dist: importlib.metadata.Distribution) -> None:
24+
self._dist = dist
25+
26+
@property
27+
def project_name(self) -> str:
28+
name: str = self.metadata["name"]
29+
return name
30+
31+
def __getattr__(self, attr: str, default: object | None = None) -> Any:
32+
return getattr(self._dist, attr, default)
33+
34+
def __dir__(self) -> list[str]:
35+
return sorted(dir(self._dist) + ["_dist", "project_name"])
36+
37+
38+
def load_importlib_entrypoints(
39+
manager: _manager.PluginManager,
40+
group: str,
41+
name: str | None = None,
42+
) -> int:
43+
"""Load modules from querying the specified setuptools ``group``.
44+
45+
:param group:
46+
Entry point group to load plugins.
47+
:param name:
48+
If given, loads only plugins with the given ``name``.
49+
50+
:return:
51+
The number of plugins loaded by this call.
52+
"""
53+
count = 0
54+
for dist in list(importlib.metadata.distributions()):
55+
for ep in dist.entry_points:
56+
if (
57+
ep.group != group
58+
or (name is not None and ep.name != name)
59+
# already registered
60+
or manager.get_plugin(ep.name)
61+
or manager.is_blocked(ep.name)
62+
):
63+
continue
64+
plugin = ep.load()
65+
manager.register(plugin, name=ep.name)
66+
manager._plugin_dist_metadata.append((plugin, dist))
67+
count += 1
68+
return count

0 commit comments

Comments
 (0)