1from collections.abc import Mapping
2from typing import Any
3
4from attrs import NOTHING
5from typing_extensions import Self
6
7from ._compat import copy_with, get_args, is_annotated, is_generic
8
9
10def deep_copy_with(t, mapping: Mapping[str, Any], self_is=NOTHING):
11 args = get_args(t)
12 rest = ()
13 if is_annotated(t) and args:
14 # If we're dealing with `Annotated`, we only map the first type parameter
15 rest = tuple(args[1:])
16 args = (args[0],)
17 new_args = (
18 tuple(
19 (
20 self_is
21 if a is Self and self_is is not NOTHING
22 else (
23 mapping[a.__name__]
24 if hasattr(a, "__name__") and a.__name__ in mapping
25 else (deep_copy_with(a, mapping, self_is) if is_generic(a) else a)
26 )
27 )
28 for a in args
29 )
30 + rest
31 )
32 return copy_with(t, new_args) if new_args != args else t