diff --git a/ChangeLog b/ChangeLog index bcf244b1d9..2a80017f50 100644 --- a/ChangeLog +++ b/ChangeLog @@ -8,6 +8,10 @@ Release date: TBA * ``astroid`` now requires Python 3.7.2 to run. +* Avoid setting a Call as a base for classes created using ``six.with_metaclass()``. + + Refs PyCQA/pylint#5935 + * Fix detection of builtins on ``PyPy`` 3.9. * Fix ``re`` brain on Python ``3.11``. The flags now come from ``re._compile``. diff --git a/astroid/brain/brain_six.py b/astroid/brain/brain_six.py index 022fcf22e0..b72d5afdbe 100644 --- a/astroid/brain/brain_six.py +++ b/astroid/brain/brain_six.py @@ -219,6 +219,7 @@ def transform_six_with_metaclass(node): """ call = node.bases[0] node._metaclass = call.args[0] + node.bases = call.args[1:] return node diff --git a/tests/unittest_brain.py b/tests/unittest_brain.py index d86c273f32..e9a7e62d6b 100644 --- a/tests/unittest_brain.py +++ b/tests/unittest_brain.py @@ -569,13 +569,29 @@ class B(six.with_metaclass(A, C)): inferred = next(ast_node.infer()) self.assertIsInstance(inferred, nodes.ClassDef) self.assertEqual(inferred.name, "B") - self.assertIsInstance(inferred.bases[0], nodes.Call) + self.assertIsInstance(inferred.bases[0], nodes.Name) + self.assertEqual(inferred.bases[0].name, "C") ancestors = tuple(inferred.ancestors()) self.assertIsInstance(ancestors[0], nodes.ClassDef) self.assertEqual(ancestors[0].name, "C") self.assertIsInstance(ancestors[1], nodes.ClassDef) self.assertEqual(ancestors[1].name, "object") + @staticmethod + def test_six_with_metaclass_enum_ancestor() -> None: + code = """ + import six + from enum import Enum, EnumMeta + + class FooMeta(EnumMeta): + pass + + class Foo(six.with_metaclass(FooMeta, Enum)): #@ + bar = 1 + """ + klass = astroid.extract_node(code) + assert list(klass.ancestors())[-1].name == "Enum" + def test_six_with_metaclass_with_additional_transform(self) -> None: def transform_class(cls: Any) -> ClassDef: if cls.name == "A":