From 824abdbf5f6821b46f512f3f38d6788662b1eff6 Mon Sep 17 00:00:00 2001 From: Jacob Walls Date: Wed, 8 Jun 2022 21:48:30 -0400 Subject: [PATCH] `argparse` brain: avoid spurious addition of "namespace" to function locals --- ChangeLog | 4 ++++ astroid/brain/brain_argparse.py | 5 ++++- tests/unittest_brain_argparse.py | 21 +++++++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 tests/unittest_brain_argparse.py diff --git a/ChangeLog b/ChangeLog index e1a27561eb..843bdb8366 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16,6 +16,10 @@ Release date: TBA * The Qt brain now correctly treats calling ``.disconnect()`` (with no arguments) on a slot as valid. +* The argparse brain no longer incorrectly adds ``"Namespace"`` to the locals + of functions that return an ``argparse.Namespace`` object. + + Refs PyCQA/pylint#6895 What's New in astroid 2.11.5? ============================= diff --git a/astroid/brain/brain_argparse.py b/astroid/brain/brain_argparse.py index ee0127c7e0..ea97179a57 100644 --- a/astroid/brain/brain_argparse.py +++ b/astroid/brain/brain_argparse.py @@ -13,7 +13,10 @@ def infer_namespace(node, context=None): # Cannot make sense of it. raise UseInferenceDefault() - class_node = nodes.ClassDef("Namespace", parent=node.parent) + class_node = nodes.ClassDef("Namespace") + # Set parent manually until ClassDef constructor fixed: + # https://github.com/PyCQA/astroid/issues/1490 + class_node.parent = node.parent for attr in set(callsite.keyword_arguments): fake_node = nodes.EmptyNode() fake_node.parent = class_node diff --git a/tests/unittest_brain_argparse.py b/tests/unittest_brain_argparse.py new file mode 100644 index 0000000000..c92f6b49bb --- /dev/null +++ b/tests/unittest_brain_argparse.py @@ -0,0 +1,21 @@ +# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html +# For details: https://github.com/PyCQA/astroid/blob/main/LICENSE +# Copyright (c) https://github.com/PyCQA/astroid/blob/main/CONTRIBUTORS.txt + +from astroid import bases, extract_node, nodes + + +class TestBrainArgparse: + @staticmethod + def test_infer_namespace() -> None: + func = extract_node( + """ + import argparse + def make_namespace(): #@ + return argparse.Namespace(debug=True) + """ + ) + assert isinstance(func, nodes.FunctionDef) + inferred = next(func.infer_call_result(func)) + assert isinstance(inferred, bases.Instance) + assert not func.locals