Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
3 changes: 3 additions & 0 deletions Doc/library/typing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2120,6 +2120,9 @@ types.
disallowed in Python 3.15. To create a NamedTuple class with 0 fields,
use ``class NT(NamedTuple): pass`` or ``NT = NamedTuple("NT", [])``.

.. versionchanged:: 3.13
Added support of multiple inheritence.

.. class:: NewType(name, tp)

Helper class to create low-overhead :ref:`distinct types <distinct>`.
Expand Down
3 changes: 3 additions & 0 deletions Doc/whatsnew/3.13.rst
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,9 @@ typing
check whether a class is a :class:`typing.Protocol`. (Contributed by Jelle Zijlstra in
:gh:`104873`.)

* Add support of multiple inheritance with :class:`~typing.NamedTuple`.
(Contributed by Serhiy Storchaka in :gh:`116241`.)

unicodedata
-----------

Expand Down
35 changes: 34 additions & 1 deletion Lib/test/test_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -7457,7 +7457,40 @@ def _source(self):

def test_multiple_inheritance(self):
class A:
pass
@property
def x(self):
return 4
@property
def y(self):
return 5
def __len__(self):
return 10

class X(NamedTuple, A):
x: int
self.assertEqual(X.__bases__, (tuple, A))
self.assertEqual(X.__orig_bases__, (NamedTuple, A))
self.assertEqual(X.__mro__, (X, tuple, A, object))

a = X(3)
self.assertEqual(a.x, 3)
self.assertEqual(a.y, 5)
self.assertEqual(len(a), 1)

class Y(A, NamedTuple):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a test to check the order of the members as well when doing unpacking? And maybe test class Z(X, Y, NamedTuple)? (I don't know if this leads to a MRO incompatibilty though)

x: int
self.assertEqual(Y.__bases__, (A, tuple))
self.assertEqual(Y.__orig_bases__, (A, NamedTuple))
self.assertEqual(Y.__mro__, (Y, A, tuple, object))

a = Y(3)
self.assertEqual(a.x, 3)
self.assertEqual(a.y, 5)
self.assertEqual(len(a), 10)

def test_multiple_inheritance_errors(self):
class A(NamedTuple):
x: int
with self.assertRaises(TypeError):
class X(NamedTuple, A):
x: int
Expand Down
4 changes: 0 additions & 4 deletions Lib/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -2794,10 +2794,6 @@ def _make_nmtuple(name, types, module, defaults = ()):
class NamedTupleMeta(type):
def __new__(cls, typename, bases, ns):
assert _NamedTuple in bases
for base in bases:
if base is not _NamedTuple and base is not Generic:
raise TypeError(
'can only inherit from a NamedTuple type and Generic')
bases = tuple(tuple if base is _NamedTuple else base for base in bases)
types = ns.get('__annotations__', {})
default_names = []
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add support of multiple inheritance with :class:`typing.NamedTuple`.