diff --git a/doc/whatsnew/fragments/7979.false_positive b/doc/whatsnew/fragments/7979.false_positive new file mode 100644 index 0000000000..1c10641aeb --- /dev/null +++ b/doc/whatsnew/fragments/7979.false_positive @@ -0,0 +1,4 @@ +Prevent ``used-before-assignment`` when imports guarded by ``if TYPE_CHECKING`` +are guarded again when used. + +Closes #7979 diff --git a/pylint/checkers/variables.py b/pylint/checkers/variables.py index 8e9a3c9bb5..1128577c40 100644 --- a/pylint/checkers/variables.py +++ b/pylint/checkers/variables.py @@ -27,12 +27,7 @@ in_type_checking_block, is_postponed_evaluation_enabled, ) -from pylint.constants import ( - PY39_PLUS, - TYPING_NEVER, - TYPING_NORETURN, - TYPING_TYPE_CHECKS_GUARDS, -) +from pylint.constants import PY39_PLUS, TYPING_NEVER, TYPING_NORETURN from pylint.interfaces import CONTROL_FLOW, HIGH, INFERENCE, INFERENCE_FAILURE from pylint.typing import MessageDefinitionTuple @@ -2003,7 +1998,8 @@ def _is_variable_violation( if ( isinstance(defstmt, (nodes.Import, nodes.ImportFrom)) and isinstance(defstmt.parent, nodes.If) - and defstmt.parent.test.as_string() in TYPING_TYPE_CHECKS_GUARDS + and in_type_checking_block(defstmt) + and not in_type_checking_block(node) ): defstmt_parent = defstmt.parent diff --git a/tests/functional/u/used/used_before_assignment_typing.py b/tests/functional/u/used/used_before_assignment_typing.py index a6ad926178..e2cefc7986 100644 --- a/tests/functional/u/used/used_before_assignment_typing.py +++ b/tests/functional/u/used/used_before_assignment_typing.py @@ -6,6 +6,7 @@ if TYPE_CHECKING: import datetime + from urllib.request import urlopen class MyClass: """Type annotation or default values for first level methods can't refer to their own class""" @@ -90,3 +91,9 @@ class VariableAnnotationsGuardedByTypeChecking: # pylint: disable=too-few-publi def print_date(self, date) -> None: date: datetime.date = date print(date) + + +class ConditionalImportGuardedWhenUsed: # pylint: disable=too-few-public-methods + """Conditional imports also guarded by TYPE_CHECKING when used.""" + if TYPE_CHECKING: + print(urlopen) diff --git a/tests/functional/u/used/used_before_assignment_typing.txt b/tests/functional/u/used/used_before_assignment_typing.txt index 4000013bf9..551bad98c3 100644 --- a/tests/functional/u/used/used_before_assignment_typing.txt +++ b/tests/functional/u/used/used_before_assignment_typing.txt @@ -1,4 +1,4 @@ -undefined-variable:14:21:14:28:MyClass.incorrect_typing_method:Undefined variable 'MyClass':UNDEFINED -undefined-variable:19:26:19:33:MyClass.incorrect_nested_typing_method:Undefined variable 'MyClass':UNDEFINED -undefined-variable:24:20:24:27:MyClass.incorrect_default_method:Undefined variable 'MyClass':UNDEFINED -used-before-assignment:88:20:88:28:VariableAnnotationsGuardedByTypeChecking:Using variable 'datetime' before assignment:HIGH +undefined-variable:15:21:15:28:MyClass.incorrect_typing_method:Undefined variable 'MyClass':UNDEFINED +undefined-variable:20:26:20:33:MyClass.incorrect_nested_typing_method:Undefined variable 'MyClass':UNDEFINED +undefined-variable:25:20:25:27:MyClass.incorrect_default_method:Undefined variable 'MyClass':UNDEFINED +used-before-assignment:89:20:89:28:VariableAnnotationsGuardedByTypeChecking:Using variable 'datetime' before assignment:HIGH