Skip to content

Commit 3bf8e00

Browse files
committed
fix: Preserve metadata for inner_types, strip_optional(), and strip_type_alias().
1 parent 48210c6 commit 3bf8e00

File tree

4 files changed

+22
-8
lines changed

4 files changed

+22
-8
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ classifiers = [
3838
"Intended Audience :: Developers",
3939
]
4040
name = "type-lens"
41-
version = "0.2.5"
41+
version = "0.2.6"
4242
description = "type-lens is a Python template project designed to simplify the setup of a new project."
4343
readme = "README.md"
4444
license = { text = "MIT" }

tests/test_type_view.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,13 @@ def test_strip_optional() -> None:
346346
assert TypeView(Optional[Union[str, int]]).strip_optional() == TypeView(Union[str, int])
347347
assert TypeView(Union[str, int, None]).strip_optional() == TypeView(Union[str, int])
348348

349+
# Retain metadata
350+
assert (
351+
TypeView(Annotated[Union[int, None], 4]).strip_optional().metadata
352+
== TypeView(int, metadata=[4]).metadata
353+
== (4,)
354+
)
355+
349356

350357
def test_repr() -> None:
351358
assert repr(TypeView(int)) == "TypeView(int)"
@@ -453,10 +460,16 @@ def test_strip_type_alias() -> None:
453460
assert TypeView(Foo).strip_type_alias() == TypeView(int) # pyright: ignore
454461
assert TypeView(int).strip_type_alias() == TypeView(int)
455462

463+
# Retain metadata
464+
assert TypeView(Annotated[Foo, 4]).strip_type_alias().metadata == TypeView(int, metadata=[4]).metadata == (4,)
465+
456466

457467
def test_strip_type_alias_extensions() -> None:
458468
from typing_extensions import TypeAliasType
459469

460470
Foo = TypeAliasType("Foo", int) # pyright: ignore
461471
assert TypeView(Foo).strip_type_alias() == TypeView(int)
462472
assert TypeView(int).strip_type_alias() == TypeView(int)
473+
474+
# Retain metadata
475+
assert TypeView(Annotated[Foo, 4]).strip_type_alias().metadata == TypeView(int, metadata=[4]).metadata == (4,)

type_lens/type_view.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
Literal,
1414
TypeVar,
1515
Union,
16+
Sequence,
1617
_SpecialForm, # pyright: ignore[reportPrivateUsage]
1718
)
1819

@@ -43,7 +44,7 @@ class TypeView(Generic[T]):
4344
"_wrappers": "A set of wrapper types that were removed from the annotation.",
4445
}
4546

46-
def __init__(self, annotation: T) -> None:
47+
def __init__(self, annotation: T, *, metadata: Sequence[Any] = ()) -> None:
4748
"""Initialize ParsedType.
4849
4950
Args:
@@ -54,7 +55,7 @@ def __init__(self, annotation: T) -> None:
5455
Returns:
5556
ParsedType
5657
"""
57-
unwrapped, metadata, wrappers = unwrap_annotation(annotation)
58+
unwrapped, annotation_metadata, wrappers = unwrap_annotation(annotation)
5859
origin = get_origin(unwrapped)
5960

6061
args: tuple[Any, ...] = () if origin is abc.Callable else get_args(unwrapped) # pyright: ignore
@@ -64,9 +65,9 @@ def __init__(self, annotation: T) -> None:
6465
self.origin: Final[Any] = origin
6566
self.fallback_origin: Final[Any] = origin or unwrapped
6667
self.args: Final[tuple[Any, ...]] = args
67-
self.metadata: Final = metadata
68+
self.metadata: Final = (*annotation_metadata, *metadata)
6869
self._wrappers: Final = wrappers
69-
self.inner_types: Final = tuple(TypeView(arg) for arg in args)
70+
self.inner_types: Final = tuple(TypeView(arg, metadata=self.metadata) for arg in args)
7071

7172
def __eq__(self, other: object) -> bool:
7273
if not isinstance(other, TypeView):
@@ -285,7 +286,7 @@ def strip_optional(self) -> TypeView[Any]:
285286

286287
args = tuple(a for a in self.args if a is not NoneType)
287288
non_optional = Union[args] # type: ignore[valid-type]
288-
return TypeView(non_optional)
289+
return TypeView(non_optional, metadata=self.metadata)
289290

290291
def strip_type_alias(self) -> TypeView[Any]:
291292
"""Remove the type alias from a `type Type = T` type alias.
@@ -297,7 +298,7 @@ def strip_type_alias(self) -> TypeView[Any]:
297298
"""
298299
if not self.is_type_alias:
299300
return self
300-
return TypeView(self.annotation.__value__)
301+
return TypeView(self.annotation.__value__, metadata=self.metadata)
301302

302303

303304
def _is_typing_extensins_type_alias(type_view: TypeView[Any]) -> bool:

type_lens/typing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ def _get_type_hints( # noqa: C901
113113
if isinstance(obj, typing._allowed_types):
114114
return {}
115115

116-
raise TypeError(f"{obj!r} is not a module, class, method, " "or function.")
116+
raise TypeError(f"{obj!r} is not a module, class, method, or function.")
117117
defaults = typing._get_defaults(obj)
118118
hints = dict(hints)
119119
for name, value in hints.items():

0 commit comments

Comments
 (0)