diff options
| -rw-r--r-- | ChangeLog | 10 | ||||
| -rw-r--r-- | astroid/protocols.py | 3 | ||||
| -rw-r--r-- | tests/unittest_inference.py | 19 |
3 files changed, 32 insertions, 0 deletions
@@ -12,6 +12,16 @@ Release Date: TBA * Allow inferring positional only arguments. +* Infer args unpacking of ``self`` + + Certain stdlib modules use ``*args`` to encapsulate + the ``self`` parameter, which results in uninferable + instances given we rely on the presence of the ``self`` + argument to figure out the instance where we should be + setting attributes. + + Close PyCQA/pylint#3216 + What's New in astroid 2.3.2? ============================ diff --git a/astroid/protocols.py b/astroid/protocols.py index 8b682e48..84e3571b 100644 --- a/astroid/protocols.py +++ b/astroid/protocols.py @@ -339,6 +339,9 @@ def _arguments_infer_argname(self, name, context): if name == self.vararg: vararg = nodes.const_factory(()) vararg.parent = self + if not self.arguments and self.parent.name == "__init__": + cls = self.parent.parent.scope() + vararg.elts = [bases.Instance(cls)] yield vararg return if name == self.kwarg: diff --git a/tests/unittest_inference.py b/tests/unittest_inference.py index a2ad7e6d..9ce0c8d2 100644 --- a/tests/unittest_inference.py +++ b/tests/unittest_inference.py @@ -5319,5 +5319,24 @@ def test_posonlyargs_inference(): assert inferred.type == "method" +def test_infer_args_unpacking_of_self(): + code = """ + class A: + def __init__(*args, **kwargs): + self, *args = args + self.data = {1: 2} + self #@ + A().data #@ + """ + self, data = extract_node(code) + inferred_self = next(self.infer()) + assert isinstance(inferred_self, Instance) + assert inferred_self.name == "A" + + inferred_data = next(data.infer()) + assert isinstance(inferred_data, nodes.Dict) + assert inferred_data.as_string() == "{1: 2}" + + if __name__ == "__main__": unittest.main() |
