Skip to content

Commit

Permalink
fix: Handling of _SpecialForm objects in repr_type in 3.8. (#39)
Browse files Browse the repository at this point in the history
* fix: Handling of _SpecialForm objects in repr_type in 3.8.

* chore: bump version to 0.2.1.
  • Loading branch information
DanCardin authored Sep 27, 2024
1 parent 08ba15c commit e2df15d
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 14 deletions.
8 changes: 3 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ maintainers = [
{ name = "Janek Nouvertné", email = "[email protected]" },
{ name = "Peter Schutt", email = "[email protected]" },
{ name = "Visakh Unnikrishnan", email = "[email protected]" },
{ name = "Alc", email = "[email protected]" }
{ name = "Alc", email = "[email protected]" },
{ name = "Dan Cardin", email = "[email protected]" },
]
keywords = [
"programming",
Expand Down Expand Up @@ -37,7 +38,7 @@ classifiers = [
"Intended Audience :: Developers",
]
name = "type-lens"
version = "0.2.0"
version = "0.2.1"
description = "type-lens is a Python template project designed to simplify the setup of a new project."
readme = "README.md"
license = { text = "MIT" }
Expand Down Expand Up @@ -104,9 +105,6 @@ omit = ["*/tests/*"]
plugins = ["covdefaults"]
source = ["type_lens"]

[tool.coverage.report]
fail-under = 100

[tool.pytest.ini_options]
addopts = "--strict-markers --strict-config"
testpaths = ["tests"]
Expand Down
4 changes: 4 additions & 0 deletions tests/test_type_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import pytest
from typing_extensions import Annotated, NotRequired, Required, get_type_hints
from typing_extensions import Literal as ExtensionsLiteral

from type_lens import TypeView
from type_lens.types.builtins import NoneType
Expand Down Expand Up @@ -349,6 +350,9 @@ def test_repr() -> None:
assert repr(TypeView(int)) == "TypeView(int)"
assert repr(TypeView(Optional[str])) == "TypeView(Union[str, NoneType])"
assert repr(TypeView(Literal["1", 2, True])) == "TypeView(Literal['1', 2, True])"
assert repr(TypeView(Tuple[Literal["1"], int])) == "TypeView(Tuple[Literal['1'], int])"
assert repr(TypeView(ExtensionsLiteral["1", 2, True])) == "TypeView(Literal['1', 2, True])"
assert repr(TypeView(Any)) == "TypeView(Any)"


def test_is_none_type() -> None:
Expand Down
28 changes: 19 additions & 9 deletions type_lens/type_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

from collections import abc
from collections.abc import Collection, Mapping
from typing import Any, AnyStr, Final, ForwardRef, Generic, Literal, TypeVar, Union
from typing import Any, AnyStr, Final, ForwardRef, Generic, Literal, TypeVar, Union, _SpecialForm

from typing_extensions import Annotated, NotRequired, Required, get_args, get_origin
from typing_extensions import Literal as ExtensionsLiteral

from type_lens.types.builtins import UNION_TYPES, NoneType
from type_lens.utils import INSTANTIABLE_TYPE_MAPPING, SAFE_GENERIC_ORIGIN_MAP, unwrap_annotation
Expand Down Expand Up @@ -71,13 +72,22 @@ def __repr__(self) -> str:

@property
def repr_type(self) -> str:
if isinstance(self.annotation, type) or self.origin:
if self.is_literal:
name = "Literal"
elif self.is_union:
name = "Union"
else:
name = self.annotation.__name__
"""Returns a consistent, canonical repr of the contained annotation.
Removes preceding `typing.` prefix for built-in typing constructs. Python's
native repr for `typing` types is inconsistent across python versions!
"""
# Literal/Union both appear to have no name on some versions of python.
if self.is_literal:
name = "Literal"
elif self.is_union:
name = "Union"
elif isinstance(self.annotation, (type, _SpecialForm)) or self.origin:
try:
name = self.annotation.__name__ # pyright: ignore[reportAttributeAccessIssue]
except AttributeError:
# Certain _SpecialForm items have no __name__ python 3.8.
name = self.annotation._name # pyright: ignore[reportAttributeAccessIssue]
else:
name = repr(self.annotation)

Expand Down Expand Up @@ -128,7 +138,7 @@ def is_forward_ref(self) -> bool:
@property
def is_literal(self) -> bool:
"""Whether the annotation is a literal value or not."""
return self.origin is Literal
return self.origin in {Literal, ExtensionsLiteral}

@property
def is_mapping(self) -> bool:
Expand Down

0 comments on commit e2df15d

Please sign in to comment.