Skip to content

Commit 702c736

Browse files
Move Final annotations to class level and add type annotations to __slots__ classes
This change improves type safety and code organization by: - Moving all Final annotations from constructors to class level for consistency - Adding proper type annotations to all __slots__ classes - Simplifying constructor assignments by removing redundant type annotations Classes updated: - HistoricHookCaller: 5 Final attributes moved to class level - NormalHookCaller: 4 Final attributes moved to class level - HookImpl: 11 Final attributes moved to class level - HookspecMarker: _project_spec moved to class level with Final - HookimplMarker: _project_spec moved to class level with Final - HookspecConfiguration: 4 Final attributes moved to class level - HookimplConfiguration: 6 Final attributes moved to class level - HookRelay: Added __dict__ type annotation - SubsetHookCaller: Added type annotations for _orig and _remove_plugins - HookSpec: Added type annotations for all 8 attributes - Result: Added type annotations for all 3 attributes 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 32a6bc5 commit 702c736

File tree

4 files changed

+77
-31
lines changed

4 files changed

+77
-31
lines changed

src/pluggy/_hook_callers.py

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ class HookRelay:
9393
of registered plugins."""
9494

9595
__slots__ = ("__dict__",)
96+
__dict__: dict[str, HookCaller]
9697

9798
def __init__(self) -> None:
9899
""":meta private:"""
@@ -123,6 +124,11 @@ class HistoricHookCaller:
123124
"_hookimpls",
124125
"_call_history",
125126
)
127+
name: Final[str]
128+
spec: Final[HookSpec]
129+
_hookexec: Final[_HookExec]
130+
_hookimpls: Final[list[HookImpl]]
131+
_call_history: Final[_CallHistory]
126132

127133
def __init__(
128134
self,
@@ -134,13 +140,13 @@ def __init__(
134140
""":meta private:"""
135141
assert spec_config.historic, "HistoricHookCaller requires historic=True"
136142
#: Name of the hook getting called.
137-
self.name: Final = name
138-
self._hookexec: Final = hook_execute
143+
self.name = name
144+
self._hookexec = hook_execute
139145
# The hookimpls list for historic hooks (no wrappers supported)
140-
self._hookimpls: Final[list[HookImpl]] = []
141-
self._call_history: Final[_CallHistory] = []
146+
self._hookimpls = []
147+
self._call_history = []
142148
# TODO: Document, or make private.
143-
self.spec: Final = HookSpec(specmodule_or_class, name, spec_config)
149+
self.spec = HookSpec(specmodule_or_class, name, spec_config)
144150

145151
def has_spec(self) -> bool:
146152
return True # HistoricHookCaller always has a spec
@@ -258,6 +264,10 @@ class NormalHookCaller:
258264
"_hookexec",
259265
"_hookimpls",
260266
)
267+
name: Final[str]
268+
spec: HookSpec | None
269+
_hookexec: Final[_HookExec]
270+
_hookimpls: Final[list[HookImpl]]
261271

262272
def __init__(
263273
self,
@@ -268,16 +278,16 @@ def __init__(
268278
) -> None:
269279
""":meta private:"""
270280
#: Name of the hook getting called.
271-
self.name: Final = name
272-
self._hookexec: Final = hook_execute
281+
self.name = name
282+
self._hookexec = hook_execute
273283
# The hookimpls list. The caller iterates it *in reverse*. Format:
274284
# 1. trylast nonwrappers
275285
# 2. nonwrappers
276286
# 3. tryfirst nonwrappers
277287
# 4. trylast wrappers
278288
# 5. wrappers
279289
# 6. tryfirst wrappers
280-
self._hookimpls: Final[list[HookImpl]] = []
290+
self._hookimpls = []
281291
# TODO: Document, or make private.
282292
self.spec: HookSpec | None = None
283293
if specmodule_or_class is not None:
@@ -440,6 +450,8 @@ class SubsetHookCaller:
440450
"_orig",
441451
"_remove_plugins",
442452
)
453+
_orig: HookCaller
454+
_remove_plugins: Set[_Plugin]
443455

444456
def __init__(self, orig: HookCaller, remove_plugins: Set[_Plugin]) -> None:
445457
self._orig = orig
@@ -579,6 +591,17 @@ class HookImpl:
579591
"trylast",
580592
"hookimpl_config",
581593
)
594+
function: Final[_HookImplFunction[object]]
595+
argnames: Final[tuple[str, ...]]
596+
kwargnames: Final[tuple[str, ...]]
597+
plugin: Final[_Plugin]
598+
plugin_name: Final[str]
599+
wrapper: Final[bool]
600+
hookwrapper: Final[bool]
601+
optionalhook: Final[bool]
602+
tryfirst: Final[bool]
603+
trylast: Final[bool]
604+
hookimpl_config: Final[HookimplConfiguration]
582605

583606
def __init__(
584607
self,
@@ -589,33 +612,33 @@ def __init__(
589612
) -> None:
590613
""":meta private:"""
591614
#: The hook implementation function.
592-
self.function: Final = function
615+
self.function = function
593616
argnames, kwargnames = varnames(self.function)
594617
#: The positional parameter names of ``function```.
595-
self.argnames: Final = argnames
618+
self.argnames = argnames
596619
#: The keyword parameter names of ``function```.
597-
self.kwargnames: Final = kwargnames
620+
self.kwargnames = kwargnames
598621
#: The plugin which defined this hook implementation.
599-
self.plugin: Final = plugin
622+
self.plugin = plugin
600623
#: The :class:`HookimplConfiguration` used to configure this hook
601624
#: implementation.
602-
self.hookimpl_config: Final = hook_impl_config
625+
self.hookimpl_config = hook_impl_config
603626
#: The name of the plugin which defined this hook implementation.
604-
self.plugin_name: Final = plugin_name
627+
self.plugin_name = plugin_name
605628
#: Whether the hook implementation is a :ref:`wrapper <hookwrapper>`.
606-
self.wrapper: Final = hook_impl_config.wrapper
629+
self.wrapper = hook_impl_config.wrapper
607630
#: Whether the hook implementation is an :ref:`old-style wrapper
608631
#: <old_style_hookwrappers>`.
609-
self.hookwrapper: Final = hook_impl_config.hookwrapper
632+
self.hookwrapper = hook_impl_config.hookwrapper
610633
#: Whether validation against a hook specification is :ref:`optional
611634
#: <optionalhook>`.
612-
self.optionalhook: Final = hook_impl_config.optionalhook
635+
self.optionalhook = hook_impl_config.optionalhook
613636
#: Whether to try to order this hook implementation :ref:`first
614637
#: <callorder>`.
615-
self.tryfirst: Final = hook_impl_config.tryfirst
638+
self.tryfirst = hook_impl_config.tryfirst
616639
#: Whether to try to order this hook implementation :ref:`last
617640
#: <callorder>`.
618-
self.trylast: Final = hook_impl_config.trylast
641+
self.trylast = hook_impl_config.trylast
619642

620643
def __repr__(self) -> str:
621644
return f"<HookImpl plugin_name={self.plugin_name!r}, plugin={self.plugin!r}>"

src/pluggy/_hook_config.py

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ class HookspecConfiguration:
8181
"warn_on_impl",
8282
"warn_on_impl_args",
8383
)
84+
firstresult: Final[bool]
85+
historic: Final[bool]
86+
warn_on_impl: Final[Warning | None]
87+
warn_on_impl_args: Final[Mapping[str, Warning] | None]
8488

8589
def __init__(
8690
self,
@@ -104,14 +108,14 @@ def __init__(
104108
if historic and firstresult:
105109
raise ValueError("cannot have a historic firstresult hook")
106110
#: Whether the hook is :ref:`first result only <firstresult>`.
107-
self.firstresult: Final = firstresult
111+
self.firstresult = firstresult
108112
#: Whether the hook is :ref:`historic <historic>`.
109-
self.historic: Final = historic
113+
self.historic = historic
110114
#: Whether the hook :ref:`warns when implemented <warn_on_impl>`.
111-
self.warn_on_impl: Final = warn_on_impl
115+
self.warn_on_impl = warn_on_impl
112116
#: Whether the hook warns when :ref:`certain arguments are requested
113117
#: <warn_on_impl>`.
114-
self.warn_on_impl_args: Final = warn_on_impl_args
118+
self.warn_on_impl_args = warn_on_impl_args
115119

116120
def __repr__(self) -> str:
117121
attrs = []
@@ -139,6 +143,12 @@ class HookimplConfiguration:
139143
"trylast",
140144
"specname",
141145
)
146+
wrapper: Final[bool]
147+
hookwrapper: Final[bool]
148+
optionalhook: Final[bool]
149+
tryfirst: Final[bool]
150+
trylast: Final[bool]
151+
specname: Final[str | None]
142152

143153
def __init__(
144154
self,
@@ -169,21 +179,21 @@ def __init__(
169179
The name of the hook specification to match, see :ref:`specname`.
170180
"""
171181
#: Whether the hook implementation is a :ref:`wrapper <hookwrapper>`.
172-
self.wrapper: Final = wrapper
182+
self.wrapper = wrapper
173183
#: Whether the hook implementation is an :ref:`old-style wrapper
174184
#: <old_style_hookwrappers>`.
175-
self.hookwrapper: Final = hookwrapper
185+
self.hookwrapper = hookwrapper
176186
#: Whether validation against a hook specification is :ref:`optional
177187
#: <optionalhook>`.
178-
self.optionalhook: Final = optionalhook
188+
self.optionalhook = optionalhook
179189
#: Whether to try to order this hook implementation :ref:`first
180190
#: <callorder>`.
181-
self.tryfirst: Final = tryfirst
191+
self.tryfirst = tryfirst
182192
#: Whether to try to order this hook implementation :ref:`last
183193
#: <callorder>`.
184-
self.trylast: Final = trylast
194+
self.trylast = trylast
185195
#: The name of the hook specification to match, see :ref:`specname`.
186-
self.specname: Final = specname
196+
self.specname = specname
187197

188198
def __repr__(self) -> str:
189199
attrs = []

src/pluggy/_hook_markers.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,10 @@ class HookspecMarker:
100100
"""
101101

102102
__slots__ = ("_project_spec",)
103+
_project_spec: Final[_project.ProjectSpec]
103104

104105
def __init__(self, project_name_or_spec: str | _project.ProjectSpec) -> None:
105-
self._project_spec: Final = (
106+
self._project_spec = (
106107
_project.ProjectSpec(project_name_or_spec)
107108
if isinstance(project_name_or_spec, str)
108109
else project_name_or_spec
@@ -194,9 +195,10 @@ class HookimplMarker:
194195
"""
195196

196197
__slots__ = ("_project_spec",)
198+
_project_spec: Final[_project.ProjectSpec]
197199

198200
def __init__(self, project_name_or_spec: str | _project.ProjectSpec) -> None:
199-
self._project_spec: Final = (
201+
self._project_spec = (
200202
_project.ProjectSpec(project_name_or_spec)
201203
if isinstance(project_name_or_spec, str)
202204
else project_name_or_spec
@@ -322,6 +324,14 @@ class HookSpec:
322324
"warn_on_impl",
323325
"warn_on_impl_args",
324326
)
327+
namespace: _Namespace
328+
function: Callable[..., object]
329+
name: str
330+
argnames: tuple[str, ...]
331+
kwargnames: tuple[str, ...]
332+
config: HookspecConfiguration
333+
warn_on_impl: Warning | None
334+
warn_on_impl_args: Mapping[str, Warning] | None
325335

326336
def __init__(
327337
self, namespace: _Namespace, name: str, config: HookspecConfiguration

src/pluggy/_result.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ class Result(Generic[ResultType]):
2727
<hookwrappers>`."""
2828

2929
__slots__ = ("_result", "_exception", "_traceback")
30+
_result: ResultType | None
31+
_exception: BaseException | None
32+
_traceback: TracebackType | None
3033

3134
def __init__(
3235
self,

0 commit comments

Comments
 (0)