diff --git a/HISTORY.md b/HISTORY.md index c9e97e01..019b6be1 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -9,6 +9,11 @@ The third number is for emergencies when we need to start branches for older rel Our backwards-compatibility policy can be found [here](https://github.com/python-attrs/cattrs/blob/main/.github/SECURITY.md). +## 24.1.2 (UNRELEASED) + +- Fix {meth}`BaseConverter.register_structure_hook` and {meth}`BaseConverter.register_unstructure_hook` type hints. + ([#581](https://github.com/python-attrs/cattrs/issues/581) [#582](https://github.com/python-attrs/cattrs/pull/582)) + ## 24.1.1 (2024-09-11) - Fix {meth}`BaseConverter.register_structure_hook_factory` and {meth}`BaseConverter.register_unstructure_hook_factory` type hints. diff --git a/src/cattrs/converters.py b/src/cattrs/converters.py index 2759ee7a..1490ec26 100644 --- a/src/cattrs/converters.py +++ b/src/cattrs/converters.py @@ -133,6 +133,9 @@ bound="HookFactory[StructureHook] | ExtendedStructureHookFactory[Converter]", ) +UnstructureHookT = TypeVar("UnstructureHookT", bound=UnstructureHook) +StructureHookT = TypeVar("StructureHookT", bound=StructureHook) + class UnstructureStrategy(Enum): """`attrs` classes unstructuring strategies.""" @@ -308,7 +311,7 @@ def unstruct_strat(self) -> UnstructureStrategy: ) @overload - def register_unstructure_hook(self) -> Callable[[UnstructureHook], None]: ... + def register_unstructure_hook(self, cls: UnstructureHookT) -> UnstructureHookT: ... @overload def register_unstructure_hook(self, cls: Any, func: UnstructureHook) -> None: ... @@ -335,7 +338,7 @@ def register_unstructure_hook( cls = next(iter(sig.parameters.values())).annotation self.register_unstructure_hook(cls, func) - return None + return func if attrs_has(cls): resolve_types(cls) @@ -440,10 +443,10 @@ def get_unstructure_hook( ) @overload - def register_structure_hook(self) -> Callable[[StructureHook], None]: ... + def register_structure_hook(self, cl: StructureHookT) -> StructureHookT: ... @overload - def register_structure_hook(self, cl: Any, func: StructuredValue) -> None: ... + def register_structure_hook(self, cl: Any, func: StructureHook) -> None: ... def register_structure_hook( self, cl: Any, func: StructureHook | None = None @@ -469,7 +472,7 @@ def register_structure_hook( func = cl sig = signature(func) self.register_structure_hook(sig.return_annotation, func) - return + return func if attrs_has(cl): resolve_types(cl) @@ -481,6 +484,7 @@ def register_structure_hook( self._structure_func.register_func_list([(lambda t: t is cl, func)]) else: self._structure_func.register_cls_list([(cl, func)]) + return None def register_structure_hook_func( self, check_func: Predicate, func: StructureHook