From e476d0c3c9010ebba346a2f31dfcf0151b54eda3 Mon Sep 17 00:00:00 2001 From: Claudiu Popa Date: Thu, 28 May 2020 08:49:13 +0200 Subject: [PATCH] Properly construct the arguments of infered property descriptors (#796) Close PyCQA/pylint#3648 --- ChangeLog | 4 ++++ astroid/interpreter/objectmodel.py | 33 ++++++++++++++++++++++-------- tests/unittest_inference.py | 17 +++++++++++++++ 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index 86a19daf8..c51c98da2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,6 +10,10 @@ Release Date: TBA Close PyCQA/pylint#3519 +* Properly construct the arguments of infered property descriptors + + Close PyCQA/pylint#3648 + What's New in astroid 2.4.1? ============================ diff --git a/astroid/interpreter/objectmodel.py b/astroid/interpreter/objectmodel.py index 55665a4a1..277c8250b 100644 --- a/astroid/interpreter/objectmodel.py +++ b/astroid/interpreter/objectmodel.py @@ -743,6 +743,27 @@ class PropertyModel(ObjectModel): """Model for a builtin property""" # pylint: disable=import-outside-toplevel + def _init_function(self, name): + from astroid.node_classes import Arguments + from astroid.scoped_nodes import FunctionDef + + args = Arguments() + args.postinit( + args=[], + defaults=[], + kwonlyargs=[], + kw_defaults=[], + annotations=[], + posonlyargs=[], + posonlyargs_annotations=[], + kwonlyargs_annotations=[], + ) + + function = FunctionDef(name=name, parent=self._instance) + + function.postinit(args=args, body=[]) + return function + @property def attr_fget(self): from astroid.scoped_nodes import FunctionDef @@ -767,20 +788,14 @@ def infer_call_result(self, caller=None, context=None): @property def attr_setter(self): - from astroid.scoped_nodes import FunctionDef - - return FunctionDef(name="setter", parent=self._instance) + return self._init_function("setter") @property def attr_deleter(self): - from astroid.scoped_nodes import FunctionDef - - return FunctionDef(name="deleter", parent=self._instance) + return self._init_function("deleter") @property def attr_getter(self): - from astroid.scoped_nodes import FunctionDef - - return FunctionDef(name="getter", parent=self._instance) + return self._init_function("getter") # pylint: enable=import-outside-toplevel diff --git a/tests/unittest_inference.py b/tests/unittest_inference.py index cfbcd6f86..d99298bca 100644 --- a/tests/unittest_inference.py +++ b/tests/unittest_inference.py @@ -5846,5 +5846,22 @@ def test(self): assert len(test) == 2 +def test_infer_generated_setter(): + code = """ + class A: + @property + def test(self): + pass + A.test.setter + """ + node = extract_node(code) + inferred = next(node.infer()) + assert isinstance(inferred, nodes.FunctionDef) + assert isinstance(inferred.args, nodes.Arguments) + # This line used to crash because property generated functions + # did not have args properly set + assert list(inferred.nodes_of_class(nodes.Const)) == [] + + if __name__ == "__main__": unittest.main()