diff --git a/doc/whatsnew/fragments/10632.false_positive b/doc/whatsnew/fragments/10632.false_positive new file mode 100644 index 0000000000..c3d52d0c63 --- /dev/null +++ b/doc/whatsnew/fragments/10632.false_positive @@ -0,0 +1,3 @@ +Fix :ref:`no-name-in-module` for members of ``concurrent.futures`` with Python 3.14. + +Closes #10632 diff --git a/doc/whatsnew/fragments/10633.false_negative b/doc/whatsnew/fragments/10633.false_negative new file mode 100644 index 0000000000..38d8002407 --- /dev/null +++ b/doc/whatsnew/fragments/10633.false_negative @@ -0,0 +1,3 @@ +Fix false-negative where :ref:`unused-import` was not reported for names referenced in a preceding ``global`` statement. + +Refs #10633 diff --git a/pylint/checkers/variables.py b/pylint/checkers/variables.py index c46db5676b..9d0c6ba6a6 100644 --- a/pylint/checkers/variables.py +++ b/pylint/checkers/variables.py @@ -1608,7 +1608,7 @@ def visit_global(self, node: nodes.Global) -> None: module = frame.root() default_message = True - locals_ = node.scope().locals + module_locals = node.root().locals for name in node.names: try: assign_nodes = module.getattr(name) @@ -1618,7 +1618,7 @@ def visit_global(self, node: nodes.Global) -> None: not_defined_locally_by_import = not any( isinstance(local, (nodes.Import, nodes.ImportFrom)) - for local in locals_.get(name, ()) + for local in module_locals.get(name, ()) ) if ( not utils.is_reassigned_after_current(node, name) diff --git a/pyproject.toml b/pyproject.toml index e9861b6d43..36fd5579a7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,7 +40,7 @@ dependencies = [ # Also upgrade requirements_test_min.txt. # Pinned to dev of second minor update to allow editable installs and fix primer issues, # see https://github.com/pylint-dev/astroid/issues/1341 - "astroid>=4,<=4.1.dev0", + "astroid>=4.0.1,<=4.1.dev0", "colorama>=0.4.5; sys_platform=='win32'", "dill>=0.2; python_version<'3.11'", "dill>=0.3.6; python_version>='3.11'", @@ -94,7 +94,7 @@ docs = [ # Configuration for the build system test-min = [ # Base test dependencies - "astroid==4", # Pinned to a specific version for tests + "astroid==4.0.1", # Pinned to a specific version for tests "py~=1.11.0", "pytest~=8.4", "pytest-benchmark~=5.1", diff --git a/requirements_test_min.txt b/requirements_test_min.txt index fb1a368520..5966b31576 100644 --- a/requirements_test_min.txt +++ b/requirements_test_min.txt @@ -1,6 +1,6 @@ .[testutils,spelling] # astroid dependency is also defined in pyproject.toml -astroid==4.0.0 # Pinned to a specific version for tests +astroid==4.0.1 # Pinned to a specific version for tests typing-extensions~=4.15 py~=1.11.0 pytest~=8.4 diff --git a/tests/functional/g/globals.py b/tests/functional/g/globals.py index 7f4e3077e9..f74a907d52 100644 --- a/tests/functional/g/globals.py +++ b/tests/functional/g/globals.py @@ -37,13 +37,13 @@ def define_constant(): def global_with_import(): """should only warn for global-statement when using `Import` node""" global sys # [global-statement] - import sys + import sys # [unused-import] def global_with_import_from(): """should only warn for global-statement when using `ImportFrom` node""" global namedtuple # [global-statement] - from collections import namedtuple + from collections import namedtuple # [unused-import] def global_no_assign(): diff --git a/tests/functional/g/globals.txt b/tests/functional/g/globals.txt index f3879ed3c9..c00b8c4ce5 100644 --- a/tests/functional/g/globals.txt +++ b/tests/functional/g/globals.txt @@ -5,7 +5,9 @@ global-variable-not-assigned:27:4:27:14:other:Using global for 'HOP' but no assi undefined-variable:28:10:28:13:other:Undefined variable 'HOP':UNDEFINED global-variable-undefined:33:4:33:18:define_constant:Global variable 'SOMEVAR' undefined at the module level:HIGH global-statement:39:4:39:14:global_with_import:Using the global statement:HIGH +unused-import:40:4:40:14:global_with_import:Unused import sys:UNDEFINED global-statement:45:4:45:21:global_with_import_from:Using the global statement:HIGH +unused-import:46:4:46:38:global_with_import_from:Unused namedtuple imported from collections:UNDEFINED global-variable-not-assigned:51:4:51:19:global_no_assign:Using global for 'CONSTANT' but no assignment is done:HIGH global-statement:57:4:57:19:global_del:Using the global statement:HIGH global-statement:64:4:64:19:global_operator_assign:Using the global statement:HIGH diff --git a/tests/functional/u/unused/unused_variable.py b/tests/functional/u/unused/unused_variable.py index b4f5263d56..adbd98be65 100644 --- a/tests/functional/u/unused/unused_variable.py +++ b/tests/functional/u/unused/unused_variable.py @@ -95,10 +95,10 @@ def test_global(): """ # pylint: disable=redefined-outer-name global PATH, OS, collections, deque # [global-statement] - from os import path as PATH - import os as OS - import collections - from collections import deque + from os import path as PATH # [unused-import] + import os as OS # [unused-import] + import collections # [unused-import] + from collections import deque # [unused-import] # make sure that these triggers unused-variable from sys import platform # [unused-import] from sys import version as VERSION # [unused-import] diff --git a/tests/functional/u/unused/unused_variable.txt b/tests/functional/u/unused/unused_variable.txt index 8800488bfb..2a1ff1b017 100644 --- a/tests/functional/u/unused/unused_variable.txt +++ b/tests/functional/u/unused/unused_variable.txt @@ -14,6 +14,10 @@ unused-import:59:4:59:40:unused_import_in_function:Unused hexdigits imported fro unused-variable:64:4:64:10:hello:Unused variable 'my_var':UNDEFINED unused-variable:75:4:75:8:function:Unused variable 'aaaa':UNDEFINED global-statement:97:4:97:39:test_global:Using the global statement:HIGH +unused-import:98:4:98:31:test_global:Unused path imported from os as PATH:UNDEFINED +unused-import:99:4:99:19:test_global:Unused os imported as OS:UNDEFINED +unused-import:100:4:100:22:test_global:Unused import collections:UNDEFINED +unused-import:101:4:101:33:test_global:Unused deque imported from collections:UNDEFINED unused-import:103:4:103:28:test_global:Unused platform imported from sys:UNDEFINED unused-import:104:4:104:38:test_global:Unused version imported from sys as VERSION:UNDEFINED unused-import:105:4:105:15:test_global:Unused import this:UNDEFINED