Skip to content

Commit 55b02fe

Browse files
feature: Support TypeAlias and ClassVar type hints
1 parent d6e5911 commit 55b02fe

File tree

3 files changed

+47
-7
lines changed

3 files changed

+47
-7
lines changed

.changelog/_unreleased.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[[entries]]
2+
id = "0e037f5f-10c3-4e38-92c5-9bef92c74e91"
3+
type = "feature"
4+
description = "Support `TypeAlias` and `ClassVar` type hints"
5+
author = "@NiklasRosenstein"

src/typeapi/typehint.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from types import ModuleType
55
from typing import (
66
Any,
7+
ClassVar,
78
Dict,
89
Generator,
910
Generic,
@@ -91,6 +92,10 @@ def _make_wrapper(cls, hint: object, source: "Any | None") -> "TypeHint":
9192
return TypeVarTypeHint(hint, source)
9293
elif origin == tuple:
9394
return TupleTypeHint(hint, source)
95+
elif origin is None and getattr(hint, "__name__") == "TypeAlias":
96+
return TypeAliasTypeHint(hint, source)
97+
elif origin is ClassVar or hint is ClassVar:
98+
return ClassVarTypeHint(hint, source)
9499

95100
return ClassTypeHint(hint, source)
96101

@@ -486,7 +491,7 @@ def __init__(self, hint: object, source: "Any | None") -> None:
486491
if self._args == ((),):
487492
self._args = ()
488493
elif self._args == () and self._hint == tuple:
489-
raise ValueError(f"TupleTypeHint can only represent a parameterized tuple.")
494+
raise ValueError("TupleTypeHint can only represent a parameterized tuple.")
490495
if ... in self._args:
491496
assert self._args[-1] == ..., "Tuple Ellipsis not as last arg"
492497
assert len(self._args) == 2, "Tuple with Ellipsis has more than two args"
@@ -511,3 +516,11 @@ def repeated(self) -> bool:
511516
"""
512517

513518
return self._repeated
519+
520+
521+
class TypeAliasTypeHint(TypeHint):
522+
pass
523+
524+
525+
class ClassVarTypeHint(TypeHint):
526+
pass

src/typeapi/typehint_test.py

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
from typing import Any, Dict, Generic, List, Optional, Sequence, Tuple, TypeVar, Union
1+
from typing import Any, ClassVar, Dict, Generic, List, Optional, Sequence, Tuple, TypeVar, Union
22

33
from pytest import mark
4-
from typing_extensions import Annotated, Literal
4+
from typing_extensions import Annotated, Literal, TypeAlias
55

66
from typeapi.typehint import (
77
AnnotatedTypeHint,
88
ClassTypeHint,
9+
ClassVarTypeHint,
910
ForwardRefTypeHint,
1011
LiteralTypeHint,
1112
TupleTypeHint,
13+
TypeAliasTypeHint,
1214
TypeHint,
1315
TypeVarTypeHint,
1416
UnionTypeHint,
@@ -543,7 +545,7 @@ class D(C[T]):
543545
hint = TypeHint(D[int])
544546
assert isinstance(hint, ClassTypeHint)
545547
assert hint.type is D
546-
assert hint.bases == (C[T],)
548+
assert hint.bases == (C[T],) # type: ignore[valid-type]
547549
assert list(hint.recurse_bases("bfs")) == [
548550
TypeHint(D[int]),
549551
TypeHint(C[int]),
@@ -564,19 +566,39 @@ class CustomList(List[T]):
564566
hint = TypeHint(CustomList)
565567
assert isinstance(hint, ClassTypeHint)
566568
assert hint.type is CustomList
567-
assert hint.bases == (List[T],)
569+
assert hint.bases == (List[T],) # type: ignore[valid-type]
568570
assert list(hint.recurse_bases("bfs")) == [
569571
TypeHint(CustomList),
570-
TypeHint(List[T]),
572+
TypeHint(List[T]), # type: ignore[valid-type]
571573
TypeHint(object),
572574
]
573575

574576
hint = TypeHint(CustomList[int])
575577
assert isinstance(hint, ClassTypeHint)
576578
assert hint.type is CustomList
577-
assert hint.bases == (List[T],)
579+
assert hint.bases == (List[T],) # type: ignore[valid-type]
578580
assert list(hint.recurse_bases("bfs")) == [
579581
TypeHint(CustomList[int]),
580582
TypeHint(List[int]),
581583
TypeHint(object),
582584
]
585+
586+
587+
def test__TypeHint__with_TypeAlias() -> None:
588+
hint = TypeHint(TypeAlias)
589+
assert isinstance(hint, TypeAliasTypeHint)
590+
assert hint.hint == TypeAlias
591+
assert hint.args == ()
592+
593+
594+
def test__TypeHint__with_ClassVar() -> None:
595+
hint = TypeHint(ClassVar)
596+
assert isinstance(hint, ClassVarTypeHint)
597+
assert hint.hint == ClassVar
598+
assert hint.args == ()
599+
600+
hint = TypeHint(ClassVar[Union[int, str]])
601+
assert isinstance(hint, ClassVarTypeHint)
602+
assert hint.hint == ClassVar[Union[int, str]]
603+
assert hint.args == (Union[int, str],)
604+
assert hint[0] == TypeHint(Union[int, str])

0 commit comments

Comments
 (0)