|
49 | 49 | import os
|
50 | 50 | import sys
|
51 | 51 | from distutils import sysconfig
|
52 |
| -from typing import Dict, List, Union |
| 52 | +from typing import Dict, List, Set, Union |
53 | 53 |
|
54 | 54 | import astroid
|
55 | 55 |
|
|
58 | 58 | check_messages,
|
59 | 59 | get_import_name,
|
60 | 60 | is_from_fallback_block,
|
| 61 | + is_node_in_guarded_import_block, |
61 | 62 | node_ignores_exception,
|
62 | 63 | )
|
63 | 64 | from pylint.exceptions import EmptyReportError
|
@@ -119,18 +120,10 @@ def _ignore_import_failure(node, modname, ignored_modules):
|
119 | 120 | if submodule in ignored_modules:
|
120 | 121 | return True
|
121 | 122 |
|
122 |
| - # ignore import failure if guarded by `sys.version_info` test |
123 |
| - if isinstance(node.parent, astroid.If) and isinstance( |
124 |
| - node.parent.test, astroid.Compare |
125 |
| - ): |
126 |
| - value = node.parent.test.left |
127 |
| - if isinstance(value, astroid.Subscript): |
128 |
| - value = value.value |
129 |
| - if ( |
130 |
| - isinstance(value, astroid.Attribute) |
131 |
| - and value.as_string() == "sys.version_info" |
132 |
| - ): |
133 |
| - return True |
| 123 | + if is_node_in_guarded_import_block(node): |
| 124 | + # Ignore import failure if part of guarded import block |
| 125 | + # I.e. `sys.version_info` or `typing.TYPE_CHECKING` |
| 126 | + return True |
134 | 127 |
|
135 | 128 | return node_ignores_exception(node, ImportError)
|
136 | 129 |
|
@@ -556,25 +549,30 @@ def visit_importfrom(self, node):
|
556 | 549 | self._add_imported_module(node, imported_module.name)
|
557 | 550 |
|
558 | 551 | @check_messages(*MSGS)
|
559 |
| - def leave_module(self, node): |
| 552 | + def leave_module(self, node: astroid.Module) -> None: |
560 | 553 | # Check imports are grouped by category (standard, 3rd party, local)
|
561 | 554 | std_imports, ext_imports, loc_imports = self._check_imports_order(node)
|
562 | 555 |
|
563 | 556 | # Check that imports are grouped by package within a given category
|
564 |
| - met_import = set() # set for 'import x' style |
565 |
| - met_from = set() # set for 'from x import y' style |
| 557 | + met_import: Set[str] = set() # set for 'import x' style |
| 558 | + met_from: Set[str] = set() # set for 'from x import y' style |
566 | 559 | current_package = None
|
567 | 560 | for import_node, import_name in std_imports + ext_imports + loc_imports:
|
568 | 561 | if not self.linter.is_message_enabled(
|
569 | 562 | "ungrouped-imports", import_node.fromlineno
|
570 | 563 | ):
|
571 | 564 | continue
|
572 |
| - if isinstance(import_node, astroid.node_classes.ImportFrom): |
| 565 | + if isinstance(import_node, astroid.ImportFrom): |
573 | 566 | met = met_from
|
574 | 567 | else:
|
575 | 568 | met = met_import
|
576 | 569 | package, _, _ = import_name.partition(".")
|
577 |
| - if current_package and current_package != package and package in met: |
| 570 | + if ( |
| 571 | + current_package |
| 572 | + and current_package != package |
| 573 | + and package in met |
| 574 | + and is_node_in_guarded_import_block(import_node) is False |
| 575 | + ): |
578 | 576 | self.add_message("ungrouped-imports", node=import_node, args=package)
|
579 | 577 | current_package = package
|
580 | 578 | met.add(package)
|
|
0 commit comments