From a973cae81ae16ce63d98f7ce8690d732b162a21f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tin=20Tvrtkovi=C4=87?= Date: Fri, 12 Jan 2024 01:18:56 +0100 Subject: [PATCH] Fix counters --- src/cattrs/gen/__init__.py | 17 ++++++++++------- src/cattrs/gen/_shared.py | 6 +++--- src/cattrs/preconf/msgspec.py | 21 ++++++++++----------- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/cattrs/gen/__init__.py b/src/cattrs/gen/__init__.py index f60ab142..f1acb6a4 100644 --- a/src/cattrs/gen/__init__.py +++ b/src/cattrs/gen/__init__.py @@ -166,7 +166,9 @@ def make_dict_unstructure_fn( # type of the default to dispatch on. t = a.default.__class__ try: - handler = converter._unstructure_func.dispatch(t) + handler = converter.get_unstructure_hook( + t, cache_result=False + ) except RecursionError: # There's a circular reference somewhere down the line handler = converter.unstructure @@ -674,7 +676,7 @@ def make_iterable_unstructure_fn( # We don't know how to handle the TypeVar on this level, # so we skip doing the dispatch here. if not isinstance(type_arg, TypeVar): - handler = converter._unstructure_func.dispatch(type_arg) + handler = converter.get_unstructure_hook(type_arg, cache_result=False) globs = {"__cattr_seq_cl": unstructure_to or cl, "__cattr_u": handler} lines = [] @@ -703,7 +705,8 @@ def make_hetero_tuple_unstructure_fn( # We can do the dispatch here and now. handlers = [ - converter._unstructure_func.dispatch(type_arg) for type_arg in type_args + converter.get_unstructure_hook(type_arg, cache_result=False) + for type_arg in type_args ] globs = {f"__cattr_u_{i}": h for i, h in enumerate(handlers)} @@ -758,11 +761,11 @@ def make_mapping_unstructure_fn( # Probably a Counter key_arg, val_arg = args, Any # We can do the dispatch here and now. - kh = key_handler or converter._unstructure_func.dispatch(key_arg) + kh = key_handler or converter.get_unstructure_hook(key_arg, cache_result=False) if kh == identity: kh = None - val_handler = converter._unstructure_func.dispatch(val_arg) + val_handler = converter.get_unstructure_hook(val_arg, cache_result=False) if val_handler == identity: val_handler = None @@ -830,11 +833,11 @@ def make_mapping_structure_fn( is_bare_dict = val_type is Any and key_type is Any if not is_bare_dict: # We can do the dispatch here and now. - key_handler = converter.get_structure_hook(key_type) + key_handler = converter.get_structure_hook(key_type, cache_result=False) if key_handler == converter._structure_call: key_handler = key_type - val_handler = converter.get_structure_hook(val_type) + val_handler = converter.get_structure_hook(val_type, cache_result=False) if val_handler == converter._structure_call: val_handler = val_type diff --git a/src/cattrs/gen/_shared.py b/src/cattrs/gen/_shared.py index 2bd1007f..78c2bc09 100644 --- a/src/cattrs/gen/_shared.py +++ b/src/cattrs/gen/_shared.py @@ -23,7 +23,7 @@ def find_structure_handler( # so it falls back to that. handler = None elif a.converter is not None and not prefer_attrs_converters and type is not None: - handler = c.get_structure_hook(type) + handler = c.get_structure_hook(type, cache_result=False) if handler == raise_error: handler = None elif type is not None: @@ -35,7 +35,7 @@ def find_structure_handler( # This is a special case where we can use the # type of the default to dispatch on. type = a.default.__class__ - handler = c.get_structure_hook(type) + handler = c.get_structure_hook(type, cache_result=False) if handler == c._structure_call: # Finals can't really be used with _structure_call, so # we wrap it so the rest of the toolchain doesn't get @@ -45,7 +45,7 @@ def handler(v, _, _h=handler): return _h(v, type) else: - handler = c.get_structure_hook(type) + handler = c.get_structure_hook(type, cache_result=False) else: handler = c.structure return handler diff --git a/src/cattrs/preconf/msgspec.py b/src/cattrs/preconf/msgspec.py index 1ebafebd..a9225970 100644 --- a/src/cattrs/preconf/msgspec.py +++ b/src/cattrs/preconf/msgspec.py @@ -120,18 +120,17 @@ def make_unstructure_mapping_factory( def unstructure_mapping_factory(type) -> UnstructureHook: if is_bare(type): key_arg = Any - value_arg = Any + val_arg = Any key_handler = converter.get_unstructure_hook(key_arg, cache_result=False) - value_handler = converter.get_unstructure_hook( - value_arg, cache_result=False - ) - elif getattr(type, "__args__", None) not in (None, ()): - key_arg = type.__args__[0] - value_arg = type.__args__[1] + value_handler = converter.get_unstructure_hook(val_arg, cache_result=False) + elif (args := getattr(type, "__args__", None)) not in (None, ()): + if len(args) == 2: + key_arg, val_arg = args + else: + # Probably a Counter + key_arg, val_arg = args, Any key_handler = converter.get_unstructure_hook(key_arg, cache_result=False) - value_handler = converter.get_unstructure_hook( - value_arg, cache_result=False - ) + value_handler = converter.get_unstructure_hook(val_arg, cache_result=False) else: key_handler = value_handler = None @@ -140,7 +139,7 @@ def unstructure_mapping_factory(type) -> UnstructureHook: to_builtins, ): return to_builtins - return converter.gen_unstructure_iterable(type) + return converter.gen_unstructure_mapping(type) return unstructure_mapping_factory