From dbc9c0c0a01744bf9b654e750b2dbd03d80f3ed5 Mon Sep 17 00:00:00 2001 From: Andrew Haigh Date: Mon, 12 Apr 2021 18:44:34 +1000 Subject: [PATCH] Add tests of failing property inference Ref #940 --- tests/unittest_scoped_nodes.py | 130 +++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/tests/unittest_scoped_nodes.py b/tests/unittest_scoped_nodes.py index 9303f1c7eb..103f799c19 100644 --- a/tests/unittest_scoped_nodes.py +++ b/tests/unittest_scoped_nodes.py @@ -1923,6 +1923,136 @@ def update(self): builder.parse(data) +def test_issue940_metaclass_subclass_property(): + node = builder.extract_node( + """ + class BaseMeta(type): + @property + def __members__(cls): + return ['a', 'property'] + class Parent(metaclass=BaseMeta): + pass + class Derived(Parent): + pass + Derived.__members__ + """ + ) + inferred = next(node.infer()) + assert isinstance(inferred, nodes.List) + assert [c.value for c in inferred.elts] == ["a", "property"] + + +def test_issue940_property_grandchild(): + node = builder.extract_node( + """ + class Grandparent: + @property + def __members__(self): + return ['a', 'property'] + class Parent(Grandparent): + pass + class Child(Parent): + pass + Child().__members__ + """ + ) + inferred = next(node.infer()) + assert isinstance(inferred, nodes.List) + assert [c.value for c in inferred.elts] == ["a", "property"] + + +def test_issue940_metaclass_property(): + node = builder.extract_node( + """ + class BaseMeta(type): + @property + def __members__(cls): + return ['a', 'property'] + class Parent(metaclass=BaseMeta): + pass + Parent.__members__ + """ + ) + inferred = next(node.infer()) + assert isinstance(inferred, nodes.List) + assert [c.value for c in inferred.elts] == ["a", "property"] + + +def test_issue940_with_metaclass_class_context_property(): + node = builder.extract_node( + """ + class BaseMeta(type): + pass + class Parent(metaclass=BaseMeta): + @property + def __members__(self): + return ['a', 'property'] + class Derived(Parent): + pass + Derived.__members__ + """ + ) + inferred = next(node.infer()) + assert not isinstance(inferred, nodes.List) + assert isinstance(inferred, objects.Property) + + +def test_issue940_metaclass_values_funcdef(): + node = builder.extract_node( + """ + class BaseMeta(type): + def __members__(cls): + return ['a', 'func'] + class Parent(metaclass=BaseMeta): + pass + Parent.__members__() + """ + ) + inferred = next(node.infer()) + assert isinstance(inferred, nodes.List) + assert [c.value for c in inferred.elts] == ["a", "func"] + + +def test_issue940_metaclass_derived_funcdef(): + node = builder.extract_node( + """ + class BaseMeta(type): + def __members__(cls): + return ['a', 'func'] + class Parent(metaclass=BaseMeta): + pass + class Derived(Parent): + pass + Derived.__members__() + """ + ) + inferred_result = next(node.infer()) + assert isinstance(inferred_result, nodes.List) + assert [c.value for c in inferred_result.elts] == ["a", "func"] + + +@pytest.mark.xfail(reason="attribute is Uninferable") +def test_issue940_metaclass_funcdef_is_not_datadescriptor(): + node = builder.extract_node( + """ + class BaseMeta(type): + def __members__(cls): + return ['a', 'property'] + class Parent(metaclass=BaseMeta): + __members__ = property(BaseMeta.__members__) + class Derived(Parent): + pass + Derived.__members__ + """ + ) + # Here the function is defined on the metaclass, but the property + # is defined on the base class. When loading the attribute in a + # class context, this should return the property object instead of + # resolving the data descriptor + inferred = next(node.infer()) + assert isinstance(inferred, objects.Property) + + def test_metaclass_cannot_infer_call_yields_an_instance(): node = builder.extract_node( """