@@ -74,6 +74,94 @@ class HookimplOpts(TypedDict):
7474 specname : str | None
7575
7676
77+ @final
78+ class HookimplConfiguration :
79+ """Configuration class for hook implementations.
80+
81+ This class is intended to replace HookimplOpts in future versions.
82+ It provides a more structured and extensible way to configure hook implementations.
83+ """
84+
85+ __slots__ = (
86+ "wrapper" ,
87+ "hookwrapper" ,
88+ "optionalhook" ,
89+ "tryfirst" ,
90+ "trylast" ,
91+ "specname" ,
92+ )
93+
94+ def __init__ (
95+ self ,
96+ wrapper : bool = False ,
97+ hookwrapper : bool = False ,
98+ optionalhook : bool = False ,
99+ tryfirst : bool = False ,
100+ trylast : bool = False ,
101+ specname : str | None = None ,
102+ ) -> None :
103+ """Initialize hook implementation configuration.
104+
105+ :param wrapper:
106+ Whether the hook implementation is a :ref:`wrapper <hookwrapper>`.
107+ :param hookwrapper:
108+ Whether the hook implementation is an :ref:`old-style wrapper
109+ <old_style_hookwrappers>`.
110+ :param optionalhook:
111+ Whether validation against a hook specification is :ref:`optional
112+ <optionalhook>`.
113+ :param tryfirst:
114+ Whether to try to order this hook implementation :ref:`first
115+ <callorder>`.
116+ :param trylast:
117+ Whether to try to order this hook implementation :ref:`last
118+ <callorder>`.
119+ :param specname:
120+ The name of the hook specification to match, see :ref:`specname`.
121+ """
122+ #: Whether the hook implementation is a :ref:`wrapper <hookwrapper>`.
123+ self .wrapper : Final = wrapper
124+ #: Whether the hook implementation is an :ref:`old-style wrapper
125+ #: <old_style_hookwrappers>`.
126+ self .hookwrapper : Final = hookwrapper
127+ #: Whether validation against a hook specification is :ref:`optional
128+ #: <optionalhook>`.
129+ self .optionalhook : Final = optionalhook
130+ #: Whether to try to order this hook implementation :ref:`first
131+ #: <callorder>`.
132+ self .tryfirst : Final = tryfirst
133+ #: Whether to try to order this hook implementation :ref:`last
134+ #: <callorder>`.
135+ self .trylast : Final = trylast
136+ #: The name of the hook specification to match, see :ref:`specname`.
137+ self .specname : Final = specname
138+
139+ def to_opts (self ) -> HookimplOpts :
140+ """Convert to HookimplOpts for backward compatibility."""
141+ return {
142+ "wrapper" : self .wrapper ,
143+ "hookwrapper" : self .hookwrapper ,
144+ "optionalhook" : self .optionalhook ,
145+ "tryfirst" : self .tryfirst ,
146+ "trylast" : self .trylast ,
147+ "specname" : self .specname ,
148+ }
149+
150+ @classmethod
151+ def from_opts (cls , opts : HookimplOpts ) -> HookimplConfiguration :
152+ """Create from HookimplOpts for backward compatibility."""
153+ return cls (** opts )
154+
155+ def __repr__ (self ) -> str :
156+ attrs = []
157+ for slot in self .__slots__ :
158+ value = getattr (self , slot )
159+ if value :
160+ attrs .append (f"{ slot } ={ value !r} " )
161+ attrs_str = ", " .join (attrs )
162+ return f"HookimplConfiguration({ attrs_str } )"
163+
164+
77165@final
78166class HookspecMarker :
79167 """Decorator for marking functions as hook specifications.
@@ -548,17 +636,10 @@ def call_extra(
548636 "Cannot directly call a historic hook - use call_historic instead."
549637 )
550638 self ._verify_all_args_are_provided (kwargs )
551- opts : HookimplOpts = {
552- "wrapper" : False ,
553- "hookwrapper" : False ,
554- "optionalhook" : False ,
555- "trylast" : False ,
556- "tryfirst" : False ,
557- "specname" : None ,
558- }
639+ config = HookimplConfiguration ()
559640 hookimpls = self ._hookimpls .copy ()
560641 for method in methods :
561- hookimpl = HookImpl (None , "<temp>" , method , opts )
642+ hookimpl = HookImpl (None , "<temp>" , method , config )
562643 # Find last non-tryfirst nonwrapper method.
563644 i = len (hookimpls ) - 1
564645 while i >= 0 and (
@@ -649,14 +730,15 @@ class HookImpl:
649730 "optionalhook" ,
650731 "tryfirst" ,
651732 "trylast" ,
733+ "hookimpl_config" ,
652734 )
653735
654736 def __init__ (
655737 self ,
656738 plugin : _Plugin ,
657739 plugin_name : str ,
658740 function : _HookImplFunction [object ],
659- hook_impl_opts : HookimplOpts ,
741+ hook_impl_config : HookimplConfiguration ,
660742 ) -> None :
661743 """:meta private:"""
662744 #: The hook implementation function.
@@ -668,24 +750,28 @@ def __init__(
668750 self .kwargnames : Final = kwargnames
669751 #: The plugin which defined this hook implementation.
670752 self .plugin : Final = plugin
671- #: The :class:`HookimplOpts` used to configure this hook implementation.
672- self .opts : Final = hook_impl_opts
753+ #: The :class:`HookimplConfiguration` used to configure this hook
754+ #: implementation.
755+ self .hookimpl_config : Final = hook_impl_config
756+ #: The :class:`HookimplOpts` used to configure this hook implementation
757+ #: (deprecated).
758+ self .opts : Final = hook_impl_config .to_opts ()
673759 #: The name of the plugin which defined this hook implementation.
674760 self .plugin_name : Final = plugin_name
675761 #: Whether the hook implementation is a :ref:`wrapper <hookwrapper>`.
676- self .wrapper : Final = hook_impl_opts [ " wrapper" ]
762+ self .wrapper : Final = hook_impl_config . wrapper
677763 #: Whether the hook implementation is an :ref:`old-style wrapper
678764 #: <old_style_hookwrappers>`.
679- self .hookwrapper : Final = hook_impl_opts [ " hookwrapper" ]
765+ self .hookwrapper : Final = hook_impl_config . hookwrapper
680766 #: Whether validation against a hook specification is :ref:`optional
681767 #: <optionalhook>`.
682- self .optionalhook : Final = hook_impl_opts [ " optionalhook" ]
768+ self .optionalhook : Final = hook_impl_config . optionalhook
683769 #: Whether to try to order this hook implementation :ref:`first
684770 #: <callorder>`.
685- self .tryfirst : Final = hook_impl_opts [ " tryfirst" ]
771+ self .tryfirst : Final = hook_impl_config . tryfirst
686772 #: Whether to try to order this hook implementation :ref:`last
687773 #: <callorder>`.
688- self .trylast : Final = hook_impl_opts [ " trylast" ]
774+ self .trylast : Final = hook_impl_config . trylast
689775
690776 def __repr__ (self ) -> str :
691777 return f"<HookImpl plugin_name={ self .plugin_name !r} , plugin={ self .plugin !r} >"
0 commit comments