Skip to content

Commit 3c2bd15

Browse files
fix: Fix repr for Literal types (#29)
* ci(pre-commit.ci): autoupdate updates: - [github.com/abravalheri/validate-pyproject: v0.23 → v0.24.1](abravalheri/validate-pyproject@v0.23...v0.24.1) - [github.com/astral-sh/ruff-pre-commit: v0.9.1 → v0.11.12](astral-sh/ruff-pre-commit@v0.9.1...v0.11.12) - [github.com/pre-commit/mirrors-mypy: v1.14.1 → v1.16.0](pre-commit/mirrors-mypy@v1.14.1...v1.16.0) * style(pre-commit.ci): auto fixes [...] * fix * fix literal repr --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent eed1988 commit 3c2bd15

File tree

3 files changed

+14
-2
lines changed

3 files changed

+14
-2
lines changed

src/fieldz/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@
1414
"Field",
1515
"asdict",
1616
"astuple",
17+
"display_as_type",
1718
"fields",
1819
"get_adapter",
1920
"params",
2021
"replace",
2122
]
2223

2324
from ._functions import asdict, astuple, fields, get_adapter, params, replace
25+
from ._repr import display_as_type
2426
from ._types import Constraints, DataclassParams, Field
2527
from .adapters import Adapter

src/fieldz/_repr.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ def origin_is_union(tp: type[Any] | None) -> bool:
3535
WithArgsTypes = (typing._GenericAlias, types.GenericAlias, types.UnionType) # type: ignore[attr-defined]
3636

3737

38+
def origin_is_literal(tp: type[Any] | None) -> bool:
39+
return tp is typing_extensions.Literal # type: ignore
40+
41+
3842
class PlainRepr(str):
3943
"""String class where repr doesn't include quotes.
4044
@@ -67,7 +71,12 @@ def display_as_type(obj: Any, *, modern_union: bool = False) -> str:
6771
if not isinstance(obj, (typing_base, WithArgsTypes, type)):
6872
obj = obj.__class__
6973

70-
if origin_is_union(typing_extensions.get_origin(obj)):
74+
origin = typing_extensions.get_origin(obj)
75+
if origin_is_literal(origin):
76+
# For Literal types, represent the actual values, not their types
77+
arg_reprs = [repr(arg) for arg in typing_extensions.get_args(obj)]
78+
return f"Literal[{', '.join(arg_reprs)}]"
79+
elif origin_is_union(origin):
7180
args = [display_as_type(x) for x in typing_extensions.get_args(obj)]
7281
if modern_union:
7382
return " | ".join(args)

tests/test_repr.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Any, Generic, Optional, TypeVar, Union
1+
from typing import Any, Generic, Literal, Optional, TypeVar, Union
22

33
from typing_extensions import Annotated
44

@@ -28,6 +28,7 @@ def test_PlainRepr() -> None:
2828
assert PlainRepr.for_type(Optional[int]) == "Optional[int]"
2929
assert PlainRepr.for_type(Union[int, str]) == "Union[int, str]"
3030
assert PlainRepr.for_type(Optional[int], modern_union=True) == "int | None"
31+
assert PlainRepr.for_type(Literal[1, "2", (1, 2)]) == "Literal[1, '2', (1, 2)]"
3132

3233
assert PlainRepr.for_type(func) == "func"
3334
assert PlainRepr.for_type(Foo()) == "Foo"

0 commit comments

Comments
 (0)