Skip to content

Commit ae761dc

Browse files
[Backport maintenance/4.0.x] Fix base class inference for dataclasses with PEP 695 syntax (#2919)
(cherry picked from commit 3774c0a) Co-authored-by: Marc Mueller <30130371+cdce8p@users.noreply.github.com>
1 parent 077c51f commit ae761dc

3 files changed

Lines changed: 36 additions & 3 deletions

File tree

ChangeLog

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ What's New in astroid 4.0.3?
1313
============================
1414
Release date: TBA
1515

16+
* Fix base class inference for dataclasses using the PEP 695 typing syntax.
17+
18+
Refs pylint-dev/pylint#10788
19+
1620

1721

1822
What's New in astroid 4.0.2?

astroid/brain/brain_dataclasses.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def is_decorated_with_dataclass(
5454
)
5555

5656

57-
def dataclass_transform(node: nodes.ClassDef) -> None:
57+
def dataclass_transform(node: nodes.ClassDef) -> nodes.ClassDef | None:
5858
"""Rewrite a dataclass to be easily understood by pylint."""
5959
node.is_dataclass = True
6060

@@ -70,7 +70,7 @@ def dataclass_transform(node: nodes.ClassDef) -> None:
7070
node.instance_attrs[name] = [rhs_node]
7171

7272
if not _check_generate_dataclass_init(node):
73-
return
73+
return None
7474

7575
kw_only_decorated = False
7676
if node.decorators.nodes:
@@ -102,6 +102,7 @@ def dataclass_transform(node: nodes.ClassDef) -> None:
102102
new_assign = parse(f"{DEFAULT_FACTORY} = object()").body[0]
103103
new_assign.parent = root
104104
root.locals[DEFAULT_FACTORY] = [new_assign.targets[0]]
105+
return node
105106

106107

107108
def _get_dataclass_attributes(

tests/test_scoped_nodes.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
util,
3030
)
3131
from astroid.bases import BoundMethod, Generator, Instance, UnboundMethod
32-
from astroid.const import WIN32
32+
from astroid.const import PY312_PLUS, WIN32
3333
from astroid.exceptions import (
3434
AstroidBuildingError,
3535
AttributeInferenceError,
@@ -1967,6 +1967,34 @@ class E(C[str], D): ...
19671967
cls, [".E", ".C", ".A", ".B", "typing.Generic", ".D", "builtins.object"]
19681968
)
19691969

1970+
@pytest.mark.skipif(not PY312_PLUS, reason="PEP 695 syntax requires Python 3.12")
1971+
def test_mro_generic_8(self):
1972+
cls = builder.extract_node(
1973+
"""
1974+
class A: ...
1975+
class B[T]: ...
1976+
class C[T](A, B[T]): ...
1977+
"""
1978+
)
1979+
assert isinstance(cls, nodes.ClassDef)
1980+
self.assertEqualMroQName(cls, [".C", ".A", ".B", "builtins.object"])
1981+
1982+
@pytest.mark.skipif(not PY312_PLUS, reason="PEP 695 syntax requires Python 3.12")
1983+
def test_mro_generic_9(self):
1984+
cls = builder.extract_node(
1985+
"""
1986+
from dataclasses import dataclass
1987+
@dataclass
1988+
class A: ...
1989+
@dataclass
1990+
class B[T]: ...
1991+
@dataclass
1992+
class C[T](A, B[T]): ...
1993+
"""
1994+
)
1995+
assert isinstance(cls, nodes.ClassDef)
1996+
self.assertEqualMroQName(cls, [".C", ".A", ".B", "builtins.object"])
1997+
19701998
def test_mro_generic_error_1(self):
19711999
cls = builder.extract_node(
19722000
"""

0 commit comments

Comments
 (0)