Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion 16 Doc/library/typing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2243,7 +2243,7 @@ without the dedicated syntax, as documented below.
.. versionadded:: 3.10


.. class:: TypeAliasType(name, value, *, type_params=())
.. class:: TypeAliasType(name, value, *, type_params=(), qualname=None)

The type of type aliases created through the :keyword:`type` statement.

Expand All @@ -2267,6 +2267,20 @@ without the dedicated syntax, as documented below.
>>> Alias.__name__
'Alias'

.. attribute:: __qualname__

The :term:`qualified name` of the type alias:

.. doctest::

>>> class Class:
... type Alias = int
...
>>> Class.Alias.__qualname__
'Class.Alias'

.. versionadded:: 3.15

.. attribute:: __module__

The name of the module in which the type alias was defined::
Expand Down
1 change: 1 addition & 0 deletions 1 Include/internal/pycore_global_objects_fini_generated.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions 1 Include/internal/pycore_global_strings.h
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,7 @@ struct _Py_global_strings {
STRUCT_FOR_ID(ps1)
STRUCT_FOR_ID(ps2)
STRUCT_FOR_ID(qid)
STRUCT_FOR_ID(qualname)
STRUCT_FOR_ID(query)
STRUCT_FOR_ID(queuetype)
STRUCT_FOR_ID(quotetabs)
Expand Down
1 change: 1 addition & 0 deletions 1 Include/internal/pycore_runtime_init_generated.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions 4 Include/internal/pycore_unicodeobject_generated.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

82 changes: 69 additions & 13 deletions 82 Lib/test/test_type_aliases.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
Callable, TypeAliasType, TypeVar, TypeVarTuple, ParamSpec, Unpack, get_args,
)

type GlobalTypeAlias = int

def get_type_alias():
type TypeAliasInFunc = str
return TypeAliasInFunc

class TypeParamsInvalidTest(unittest.TestCase):
def test_name_collisions(self):
Expand Down Expand Up @@ -70,6 +75,8 @@ def inner[B](self):


class TypeParamsAliasValueTest(unittest.TestCase):
type TypeAliasInClass = dict

def test_alias_value_01(self):
type TA1 = int

Expand Down Expand Up @@ -142,33 +149,67 @@ def test_subscripting(self):
self.assertIs(specialized2.__origin__, VeryGeneric)
self.assertEqual(specialized2.__args__, (int, str, float, [bool, range]))

def test___name__(self):
type TypeAliasLocal = GlobalTypeAlias

self.assertEqual(GlobalTypeAlias.__name__, 'GlobalTypeAlias')
self.assertEqual(get_type_alias().__name__, 'TypeAliasInFunc')
self.assertEqual(self.TypeAliasInClass.__name__, 'TypeAliasInClass')
self.assertEqual(TypeAliasLocal.__name__, 'TypeAliasLocal')

with self.assertRaisesRegex(
AttributeError,
"readonly attribute",
):
setattr(TypeAliasLocal, '__name__', 'TA')

def test___qualname__(self):
type TypeAliasLocal = GlobalTypeAlias

self.assertEqual(GlobalTypeAlias.__qualname__,
'GlobalTypeAlias')
self.assertEqual(get_type_alias().__qualname__,
'get_type_alias.<locals>.TypeAliasInFunc')
self.assertEqual(self.TypeAliasInClass.__qualname__,
'TypeParamsAliasValueTest.TypeAliasInClass')
self.assertEqual(TypeAliasLocal.__qualname__,
'TypeParamsAliasValueTest.test___qualname__.<locals>.TypeAliasLocal')

with self.assertRaisesRegex(
AttributeError,
"readonly attribute",
):
setattr(TypeAliasLocal, '__qualname__', 'TA')

def test_repr(self):
type Simple = int
type VeryGeneric[T, *Ts, **P] = Callable[P, tuple[T, *Ts]]
self.assertEqual(repr(Simple), Simple.__qualname__)
Comment thread
efimov-mikhail marked this conversation as resolved.

self.assertEqual(repr(Simple), "Simple")
self.assertEqual(repr(VeryGeneric), "VeryGeneric")
type VeryGeneric[T, *Ts, **P] = Callable[P, tuple[T, *Ts]]
self.assertEqual(repr(VeryGeneric), VeryGeneric.__qualname__)
fullname = f"{VeryGeneric.__module__}.{VeryGeneric.__qualname__}"
self.assertEqual(repr(VeryGeneric[int, bytes, str, [float, object]]),
"VeryGeneric[int, bytes, str, [float, object]]")
f"{fullname}[int, bytes, str, [float, object]]")
self.assertEqual(repr(VeryGeneric[int, []]),
"VeryGeneric[int, []]")
f"{fullname}[int, []]")
self.assertEqual(repr(VeryGeneric[int, [VeryGeneric[int], list[str]]]),
"VeryGeneric[int, [VeryGeneric[int], list[str]]]")
f"{fullname}[int, [{fullname}[int], list[str]]]")

def test_recursive_repr(self):
type Recursive = Recursive
self.assertEqual(repr(Recursive), "Recursive")
self.assertEqual(repr(Recursive), Recursive.__qualname__)

type X = list[Y]
type Y = list[X]
self.assertEqual(repr(X), "X")
self.assertEqual(repr(Y), "Y")
self.assertEqual(repr(X), X.__qualname__)
self.assertEqual(repr(Y), Y.__qualname__)

type GenericRecursive[X] = list[X | GenericRecursive[X]]
self.assertEqual(repr(GenericRecursive), "GenericRecursive")
self.assertEqual(repr(GenericRecursive[int]), "GenericRecursive[int]")
self.assertEqual(repr(GenericRecursive), GenericRecursive.__qualname__)
fullname = f"{GenericRecursive.__module__}.{GenericRecursive.__qualname__}"
self.assertEqual(repr(GenericRecursive[int]), f"{fullname}[int]")
self.assertEqual(repr(GenericRecursive[GenericRecursive[int]]),
"GenericRecursive[GenericRecursive[int]]")
f"{fullname}[{fullname}[int]]")

def test_raising(self):
type MissingName = list[_My_X]
Expand All @@ -193,15 +234,25 @@ class TypeAliasConstructorTest(unittest.TestCase):
def test_basic(self):
TA = TypeAliasType("TA", int)
self.assertEqual(TA.__name__, "TA")
self.assertEqual(TA.__qualname__, "TA")
self.assertIs(TA.__value__, int)
self.assertEqual(TA.__type_params__, ())
self.assertEqual(TA.__module__, __name__)

def test_with_qualname(self):
TA = TypeAliasType("TA", str, qualname="Class.TA")
self.assertEqual(TA.__name__, "TA")
self.assertEqual(TA.__qualname__, "Class.TA")
self.assertIs(TA.__value__, str)
self.assertEqual(TA.__type_params__, ())
self.assertEqual(TA.__module__, __name__)

def test_attributes_with_exec(self):
ns = {}
exec("type TA = int", ns, ns)
TA = ns["TA"]
self.assertEqual(TA.__name__, "TA")
self.assertEqual(TA.__qualname__, "TA")
self.assertIs(TA.__value__, int)
self.assertEqual(TA.__type_params__, ())
self.assertIs(TA.__module__, None)
Expand All @@ -210,6 +261,7 @@ def test_generic(self):
T = TypeVar("T")
TA = TypeAliasType("TA", list[T], type_params=(T,))
self.assertEqual(TA.__name__, "TA")
self.assertEqual(TA.__qualname__, "TA")
self.assertEqual(TA.__value__, list[T])
self.assertEqual(TA.__type_params__, (T,))
self.assertEqual(TA.__module__, __name__)
Expand All @@ -218,6 +270,7 @@ def test_generic(self):
def test_not_generic(self):
TA = TypeAliasType("TA", list[int], type_params=())
self.assertEqual(TA.__name__, "TA")
self.assertEqual(TA.__qualname__, "TA")
self.assertEqual(TA.__value__, list[int])
self.assertEqual(TA.__type_params__, ())
self.assertEqual(TA.__module__, __name__)
Expand Down Expand Up @@ -268,8 +321,9 @@ def test_expects_type_like(self):
TypeAliasType("A", int, type_params=(T, 2))

def test_keywords(self):
TA = TypeAliasType(name="TA", value=int)
TA = TypeAliasType(name="TA", value=int, type_params=(), qualname=None)
self.assertEqual(TA.__name__, "TA")
self.assertEqual(TA.__qualname__, "TA")
self.assertIs(TA.__value__, int)
self.assertEqual(TA.__type_params__, ())
self.assertEqual(TA.__module__, __name__)
Expand All @@ -283,6 +337,8 @@ def test_errors(self):
TypeAliasType("TA", list, ())
with self.assertRaises(TypeError):
TypeAliasType("TA", list, type_params=42)
with self.assertRaises(TypeError):
TypeAliasType("TA", list, qualname=range(5))


class TypeAliasTypeTest(unittest.TestCase):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Attribute ``__qualname__`` is added to :class:`typing.TypeAliasType`.
Patch by Mikhail Efimov.
25 changes: 16 additions & 9 deletions 25 Objects/clinic/typevarobject.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.