diff --git a/doc/user_guide/installation/ide_integration/index.rst b/doc/user_guide/installation/ide_integration/index.rst index c359c8ee15..cd230eee69 100644 --- a/doc/user_guide/installation/ide_integration/index.rst +++ b/doc/user_guide/installation/ide_integration/index.rst @@ -40,7 +40,7 @@ Below you can find tutorials for some of the most common ones. .. _Sublime Text: https://packagecontrol.io/packages/SublimeLinter-pylint .. _Vim: https://www.vim.org/scripts/script.php?script_id=891 .. _Visual Studio: https://docs.microsoft.com/visualstudio/python/code-pylint -.. _Visual Studio Code: https://code.visualstudio.com/docs/python/linting#_pylint +.. _Visual Studio Code: https://code.visualstudio.com/docs/python/linting .. _Visual Studio Code Pylint Extension: https://marketplace.visualstudio.com/items?itemName=ms-python.pylint .. _WingIDE: https://wingware.com/doc/warnings/external-checkers diff --git a/doc/whatsnew/fragments/8774.bugfix b/doc/whatsnew/fragments/8774.bugfix new file mode 100644 index 0000000000..3f8f7fb5b1 --- /dev/null +++ b/doc/whatsnew/fragments/8774.bugfix @@ -0,0 +1,3 @@ +Fixed a crash when calling ``copy.copy()`` without arguments. + +Closes #8774 diff --git a/pylint/checkers/stdlib.py b/pylint/checkers/stdlib.py index b2f4a709b7..e383150af8 100644 --- a/pylint/checkers/stdlib.py +++ b/pylint/checkers/stdlib.py @@ -511,14 +511,23 @@ def _check_for_check_kw_in_run(self, node: nodes.Call) -> None: self.add_message("subprocess-run-check", node=node, confidence=INFERENCE) def _check_shallow_copy_environ(self, node: nodes.Call) -> None: - arg = utils.get_argument_from_call(node, position=0) + confidence = HIGH + try: + arg = utils.get_argument_from_call(node, position=0, keyword="x") + except utils.NoSuchArgumentError: + arg = utils.infer_kwarg_from_call(node, keyword="x") + if not arg: + return + confidence = INFERENCE try: inferred_args = arg.inferred() except astroid.InferenceError: return for inferred in inferred_args: if inferred.qname() == OS_ENVIRON: - self.add_message("shallow-copy-environ", node=node) + self.add_message( + "shallow-copy-environ", node=node, confidence=confidence + ) break @utils.only_required_for_messages( diff --git a/tests/functional/s/shallow_copy_environ.py b/tests/functional/s/shallow_copy_environ.py index ee931d71a3..90710fae70 100644 --- a/tests/functional/s/shallow_copy_environ.py +++ b/tests/functional/s/shallow_copy_environ.py @@ -27,3 +27,11 @@ import os copy.deepcopy(os.environ) + +# Edge cases +copy.copy() # [no-value-for-parameter] +copy.copy(x=test_dict) +copy.copy(x=os.environ) # [shallow-copy-environ] +copy.copy(**{"x": os.environ}) # [shallow-copy-environ] +copy.copy(**{"y": os.environ}) # [unexpected-keyword-arg] +copy.copy(y=os.environ) # [no-value-for-parameter, unexpected-keyword-arg] diff --git a/tests/functional/s/shallow_copy_environ.txt b/tests/functional/s/shallow_copy_environ.txt index b7e37e2621..beb47f7538 100644 --- a/tests/functional/s/shallow_copy_environ.txt +++ b/tests/functional/s/shallow_copy_environ.txt @@ -1,2 +1,8 @@ -shallow-copy-environ:7:0:7:21::Using copy.copy(os.environ). Use os.environ.copy() instead.:UNDEFINED -shallow-copy-environ:17:0:17:18::Using copy.copy(os.environ). Use os.environ.copy() instead.:UNDEFINED +shallow-copy-environ:7:0:7:21::Using copy.copy(os.environ). Use os.environ.copy() instead.:HIGH +shallow-copy-environ:17:0:17:18::Using copy.copy(os.environ). Use os.environ.copy() instead.:HIGH +no-value-for-parameter:32:0:32:11::No value for argument 'x' in function call:UNDEFINED +shallow-copy-environ:34:0:34:23::Using copy.copy(os.environ). Use os.environ.copy() instead.:HIGH +shallow-copy-environ:35:0:35:30::Using copy.copy(os.environ). Use os.environ.copy() instead.:INFERENCE +unexpected-keyword-arg:36:0:36:30::Unexpected keyword argument 'y' in function call:UNDEFINED +no-value-for-parameter:37:0:37:23::No value for argument 'x' in function call:UNDEFINED +unexpected-keyword-arg:37:0:37:23::Unexpected keyword argument 'y' in function call:UNDEFINED