bpo-41747: Ensure all dataclass methods uses their parents' qualname (GH-22155)
* bpo-41747: Ensure all dataclass methods uses their parents' qualname Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
This commit is contained in:
parent
9a1ad2cf02
commit
c7437e2c02
|
@ -8,7 +8,7 @@ import builtins
|
|||
import functools
|
||||
import abc
|
||||
import _thread
|
||||
from types import GenericAlias
|
||||
from types import FunctionType, GenericAlias
|
||||
|
||||
|
||||
__all__ = ['dataclass',
|
||||
|
@ -757,12 +757,19 @@ def _get_field(cls, a_name, a_type):
|
|||
|
||||
return f
|
||||
|
||||
def _set_qualname(cls, value):
|
||||
# Ensure that the functions returned from _create_fn uses the proper
|
||||
# __qualname__ (the class they belong to).
|
||||
if isinstance(value, FunctionType):
|
||||
value.__qualname__ = f"{cls.__qualname__}.{value.__name__}"
|
||||
return value
|
||||
|
||||
def _set_new_attribute(cls, name, value):
|
||||
# Never overwrites an existing attribute. Returns True if the
|
||||
# attribute already exists.
|
||||
if name in cls.__dict__:
|
||||
return True
|
||||
_set_qualname(cls, value)
|
||||
setattr(cls, name, value)
|
||||
return False
|
||||
|
||||
|
@ -777,7 +784,7 @@ def _hash_set_none(cls, fields, globals):
|
|||
|
||||
def _hash_add(cls, fields, globals):
|
||||
flds = [f for f in fields if (f.compare if f.hash is None else f.hash)]
|
||||
return _hash_fn(flds, globals)
|
||||
return _set_qualname(cls, _hash_fn(flds, globals))
|
||||
|
||||
def _hash_exception(cls, fields, globals):
|
||||
# Raise an exception.
|
||||
|
|
|
@ -1936,6 +1936,30 @@ class TestCase(unittest.TestCase):
|
|||
self.assertEqual(new_sample.x, another_new_sample.x)
|
||||
self.assertEqual(sample.y, another_new_sample.y)
|
||||
|
||||
def test_dataclasses_qualnames(self):
|
||||
@dataclass(order=True, unsafe_hash=True, frozen=True)
|
||||
class A:
|
||||
x: int
|
||||
y: int
|
||||
|
||||
self.assertEqual(A.__init__.__name__, "__init__")
|
||||
for function in (
|
||||
'__eq__',
|
||||
'__lt__',
|
||||
'__le__',
|
||||
'__gt__',
|
||||
'__ge__',
|
||||
'__hash__',
|
||||
'__init__',
|
||||
'__repr__',
|
||||
'__setattr__',
|
||||
'__delattr__',
|
||||
):
|
||||
self.assertEqual(getattr(A, function).__qualname__, f"TestCase.test_dataclasses_qualnames.<locals>.A.{function}")
|
||||
|
||||
with self.assertRaisesRegex(TypeError, r"A\.__init__\(\) missing"):
|
||||
A()
|
||||
|
||||
|
||||
class TestFieldNoAnnotation(unittest.TestCase):
|
||||
def test_field_without_annotation(self):
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
Ensure all methods that generated from :func:`dataclasses.dataclass`
|
||||
objects now have the proper ``__qualname__`` attribute referring to
|
||||
the class they belong to. Patch by Batuhan Taskaya.
|
Loading…
Reference in New Issue