Fix base class inference for dataclasses with PEP 695 syntax (#2918)
diff --git a/ChangeLog b/ChangeLog index cbddc75..9f1b3f7 100644 --- a/ChangeLog +++ b/ChangeLog
@@ -39,6 +39,10 @@ ============================ Release date: TBA +* Fix base class inference for dataclasses using the PEP 695 typing syntax. + + Refs pylint-dev/pylint#10788 + What's New in astroid 4.0.2?
diff --git a/astroid/brain/brain_dataclasses.py b/astroid/brain/brain_dataclasses.py index bafd5f1..244665e 100644 --- a/astroid/brain/brain_dataclasses.py +++ b/astroid/brain/brain_dataclasses.py
@@ -54,7 +54,7 @@ ) -def dataclass_transform(node: nodes.ClassDef) -> None: +def dataclass_transform(node: nodes.ClassDef) -> nodes.ClassDef | None: """Rewrite a dataclass to be easily understood by pylint.""" node.is_dataclass = True @@ -70,7 +70,7 @@ node.instance_attrs[name] = [rhs_node] if not _check_generate_dataclass_init(node): - return + return None kw_only_decorated = False if node.decorators.nodes: @@ -102,6 +102,7 @@ new_assign = parse(f"{DEFAULT_FACTORY} = object()").body[0] new_assign.parent = root root.locals[DEFAULT_FACTORY] = [new_assign.targets[0]] + return node def _get_dataclass_attributes(
diff --git a/tests/test_scoped_nodes.py b/tests/test_scoped_nodes.py index da24621..85aebab 100644 --- a/tests/test_scoped_nodes.py +++ b/tests/test_scoped_nodes.py
@@ -29,7 +29,7 @@ util, ) from astroid.bases import BoundMethod, Generator, Instance, UnboundMethod -from astroid.const import WIN32 +from astroid.const import PY312_PLUS, WIN32 from astroid.exceptions import ( AstroidBuildingError, AttributeInferenceError, @@ -1967,6 +1967,34 @@ cls, [".E", ".C", ".A", ".B", "typing.Generic", ".D", "builtins.object"] ) + @pytest.mark.skipif(not PY312_PLUS, reason="PEP 695 syntax requires Python 3.12") + def test_mro_generic_8(self): + cls = builder.extract_node( + """ + class A: ... + class B[T]: ... + class C[T](A, B[T]): ... + """ + ) + assert isinstance(cls, nodes.ClassDef) + self.assertEqualMroQName(cls, [".C", ".A", ".B", "builtins.object"]) + + @pytest.mark.skipif(not PY312_PLUS, reason="PEP 695 syntax requires Python 3.12") + def test_mro_generic_9(self): + cls = builder.extract_node( + """ + from dataclasses import dataclass + @dataclass + class A: ... + @dataclass + class B[T]: ... + @dataclass + class C[T](A, B[T]): ... + """ + ) + assert isinstance(cls, nodes.ClassDef) + self.assertEqualMroQName(cls, [".C", ".A", ".B", "builtins.object"]) + def test_mro_generic_error_1(self): cls = builder.extract_node( """