From 5306ff5a1b9dfed7eaa1f7624a151e68fc9bc1c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABl=20van=20Noord?= <13665637+DanielNoord@users.noreply.github.com> Date: Mon, 23 Dec 2024 23:34:31 +0100 Subject: [PATCH 1/8] Fix issue with importing of frozen submodules --- ChangeLog | 6 +++ astroid/interpreter/_import/spec.py | 58 +++++++++++++++++------------ 2 files changed, 41 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5ec03e2fa..d20554ec0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -13,12 +13,18 @@ What's New in astroid 3.3.8? ============================ Release date: TBA +* Fix inability to import `collections.abc` in python 3.13.1. The reported fixes in astroid 3.3.6 + and 3.3.7 did not actually fix this issue. + + Closes pylint-dev/pylint#10112 What's New in astroid 3.3.7? ============================ Release date: 2024-12-20 +This release was yanked. + * Fix inability to import `collections.abc` in python 3.13.1. The reported fix in astroid 3.3.6 did not actually fix this issue. diff --git a/astroid/interpreter/_import/spec.py b/astroid/interpreter/_import/spec.py index 832432d94..d84d36944 100644 --- a/astroid/interpreter/_import/spec.py +++ b/astroid/interpreter/_import/spec.py @@ -142,6 +142,31 @@ def find_module( type=ModuleType.C_BUILTIN, ) + if submodule_path is not None: + search_paths = list(submodule_path) + else: + search_paths = sys.path + + # First try to find the module using normal search paths. If that fails, fall back to + # the frozen module finder. + suffixes = (".py", ".pyi", importlib.machinery.BYTECODE_SUFFIXES[0]) + for entry in search_paths: + package_directory = os.path.join(entry, modname) + for suffix in suffixes: + package_file_name = "__init__" + suffix + file_path = os.path.join(package_directory, package_file_name) + if os.path.isfile(file_path): + return ModuleSpec( + name=modname, + location=package_directory, + type=ModuleType.PKG_DIRECTORY, + ) + for suffix, type_ in ImportlibFinder._SUFFIXES: + file_name = modname + suffix + file_path = os.path.join(entry, file_name) + if os.path.isfile(file_path): + return ModuleSpec(name=modname, location=file_path, type=type_) + # sys.stdlib_module_names was added in Python 3.10 if PY310_PLUS: # If the module is a stdlib module, check whether this is a frozen module. Note that @@ -150,7 +175,16 @@ def find_module( if modname in sys.stdlib_module_names or ( processed and processed[0] in sys.stdlib_module_names ): - spec = importlib.util.find_spec(".".join((*processed, modname))) + try: + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=Warning) + spec = importlib.util.find_spec(".".join((*processed, modname))) + except ValueError: + # `find_spec` raises a ValueError for modules that are missing their `__spec__` + # attributes. We don't really understand why, but this is likely caused by + # us re-implementing the import behaviour but not correctly. + spec = None + if ( spec and spec.loader # type: ignore[comparison-overlap] # noqa: E501 @@ -186,28 +220,6 @@ def find_module( except ValueError: pass - if submodule_path is not None: - search_paths = list(submodule_path) - else: - search_paths = sys.path - - suffixes = (".py", ".pyi", importlib.machinery.BYTECODE_SUFFIXES[0]) - for entry in search_paths: - package_directory = os.path.join(entry, modname) - for suffix in suffixes: - package_file_name = "__init__" + suffix - file_path = os.path.join(package_directory, package_file_name) - if os.path.isfile(file_path): - return ModuleSpec( - name=modname, - location=package_directory, - type=ModuleType.PKG_DIRECTORY, - ) - for suffix, type_ in ImportlibFinder._SUFFIXES: - file_name = modname + suffix - file_path = os.path.join(entry, file_name) - if os.path.isfile(file_path): - return ModuleSpec(name=modname, location=file_path, type=type_) return None def contribute_to_path( From c3240c05842039baf019470ee05ff6f879bfa735 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABl=20van=20Noord?= <13665637+DanielNoord@users.noreply.github.com> Date: Tue, 24 Dec 2024 00:35:53 +0100 Subject: [PATCH 2/8] Update astroid/interpreter/_import/spec.py Co-authored-by: Jacob Walls --- astroid/interpreter/_import/spec.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/astroid/interpreter/_import/spec.py b/astroid/interpreter/_import/spec.py index d84d36944..2852c2d8e 100644 --- a/astroid/interpreter/_import/spec.py +++ b/astroid/interpreter/_import/spec.py @@ -169,7 +169,7 @@ def find_module( # sys.stdlib_module_names was added in Python 3.10 if PY310_PLUS: - # If the module is a stdlib module, check whether this is a frozen module. Note that + # If the module name might be a stdlib module, check whether this is a frozen module. Note that # `find_spec` actually imports the module, so we want to make sure we only run this code # for stuff that can be expected to be frozen. For now this is only stdlib. if modname in sys.stdlib_module_names or ( From 4665d93ad203aa70e96496eb091d5240a737aaf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABl=20van=20Noord?= <13665637+DanielNoord@users.noreply.github.com> Date: Tue, 24 Dec 2024 00:37:24 +0100 Subject: [PATCH 3/8] Update comments --- astroid/interpreter/_import/spec.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/astroid/interpreter/_import/spec.py b/astroid/interpreter/_import/spec.py index 2852c2d8e..8cfa0ef76 100644 --- a/astroid/interpreter/_import/spec.py +++ b/astroid/interpreter/_import/spec.py @@ -169,7 +169,7 @@ def find_module( # sys.stdlib_module_names was added in Python 3.10 if PY310_PLUS: - # If the module name might be a stdlib module, check whether this is a frozen module. Note that + # If the module name matches a stdlib module name, check whether this is a frozen module. Note that # `find_spec` actually imports the module, so we want to make sure we only run this code # for stuff that can be expected to be frozen. For now this is only stdlib. if modname in sys.stdlib_module_names or ( @@ -180,9 +180,6 @@ def find_module( warnings.filterwarnings("ignore", category=Warning) spec = importlib.util.find_spec(".".join((*processed, modname))) except ValueError: - # `find_spec` raises a ValueError for modules that are missing their `__spec__` - # attributes. We don't really understand why, but this is likely caused by - # us re-implementing the import behaviour but not correctly. spec = None if ( From 0c768c838d6de1b91ab12eeb395ffeab21b3ac09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABl=20van=20Noord?= <13665637+DanielNoord@users.noreply.github.com> Date: Tue, 24 Dec 2024 00:38:15 +0100 Subject: [PATCH 4/8] More comment updates --- astroid/interpreter/_import/spec.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/astroid/interpreter/_import/spec.py b/astroid/interpreter/_import/spec.py index 8cfa0ef76..4b2c75a4f 100644 --- a/astroid/interpreter/_import/spec.py +++ b/astroid/interpreter/_import/spec.py @@ -170,7 +170,7 @@ def find_module( # sys.stdlib_module_names was added in Python 3.10 if PY310_PLUS: # If the module name matches a stdlib module name, check whether this is a frozen module. Note that - # `find_spec` actually imports the module, so we want to make sure we only run this code + # `find_spec` actually imports parent modules, so we want to make sure we only run this code # for stuff that can be expected to be frozen. For now this is only stdlib. if modname in sys.stdlib_module_names or ( processed and processed[0] in sys.stdlib_module_names From 768768e6e2f2daf24aca7614f226083be599f9ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABl=20van=20Noord?= <13665637+DanielNoord@users.noreply.github.com> Date: Tue, 24 Dec 2024 00:54:12 +0100 Subject: [PATCH 5/8] Reorder comment to fix line length --- astroid/interpreter/_import/spec.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/astroid/interpreter/_import/spec.py b/astroid/interpreter/_import/spec.py index b83057dff..0fc8103e1 100644 --- a/astroid/interpreter/_import/spec.py +++ b/astroid/interpreter/_import/spec.py @@ -170,9 +170,10 @@ def find_module( # sys.stdlib_module_names was added in Python 3.10 if PY310_PLUS: - # If the module name matches a stdlib module name, check whether this is a frozen module. Note that - # `find_spec` actually imports parent modules, so we want to make sure we only run this code - # for stuff that can be expected to be frozen. For now this is only stdlib. + # If the module name matches a stdlib module name, check whether this is a frozen + # module. Note that `find_spec` actually imports parent modules, so we want to make + # sure we only run this code for stuff that can be expected to be frozen. For now + # this is only stdlib. if modname in sys.stdlib_module_names or ( processed and processed[0] in sys.stdlib_module_names ): From 18ccd48e6c3e07ee02cd8393645494fb28390001 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABl=20van=20Noord?= <13665637+DanielNoord@users.noreply.github.com> Date: Tue, 24 Dec 2024 00:57:47 +0100 Subject: [PATCH 6/8] Fix merge conflicts again --- astroid/interpreter/_import/spec.py | 44 ++++++++++++++--------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/astroid/interpreter/_import/spec.py b/astroid/interpreter/_import/spec.py index 0fc8103e1..ace390fb6 100644 --- a/astroid/interpreter/_import/spec.py +++ b/astroid/interpreter/_import/spec.py @@ -144,29 +144,27 @@ def find_module( ) if submodule_path is not None: - search_paths = list(submodule_path) - else: - search_paths = sys.path - - # First try to find the module using normal search paths. If that fails, fall back to - # the frozen module finder. - suffixes = (".py", ".pyi", importlib.machinery.BYTECODE_SUFFIXES[0]) - for entry in search_paths: - package_directory = os.path.join(entry, modname) - for suffix in suffixes: - package_file_name = "__init__" + suffix - file_path = os.path.join(package_directory, package_file_name) - if os.path.isfile(file_path): - return ModuleSpec( - name=modname, - location=package_directory, - type=ModuleType.PKG_DIRECTORY, - ) - for suffix, type_ in ImportlibFinder._SUFFIXES: - file_name = modname + suffix - file_path = os.path.join(entry, file_name) - if os.path.isfile(file_path): - return ModuleSpec(name=modname, location=file_path, type=type_) + search_paths = list(submodule_path) + else: + search_paths = sys.path + + suffixes = (".py", ".pyi", importlib.machinery.BYTECODE_SUFFIXES[0]) + for entry in search_paths: + package_directory = os.path.join(entry, modname) + for suffix in suffixes: + package_file_name = "__init__" + suffix + file_path = os.path.join(package_directory, package_file_name) + if cached_os_path_isfile(file_path): + return ModuleSpec( + name=modname, + location=package_directory, + type=ModuleType.PKG_DIRECTORY, + ) + for suffix, type_ in ImportlibFinder._SUFFIXES: + file_name = modname + suffix + file_path = os.path.join(entry, file_name) + if cached_os_path_isfile(file_path): + return ModuleSpec(name=modname, location=file_path, type=type_) # sys.stdlib_module_names was added in Python 3.10 if PY310_PLUS: From e9ff94971a8d5fa592f4d1c2b29fa280ecec5503 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABl=20van=20Noord?= <13665637+DanielNoord@users.noreply.github.com> Date: Tue, 24 Dec 2024 00:59:50 +0100 Subject: [PATCH 7/8] Fix better --- astroid/interpreter/_import/spec.py | 40 ++++++++++++++--------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/astroid/interpreter/_import/spec.py b/astroid/interpreter/_import/spec.py index ace390fb6..5477c25c0 100644 --- a/astroid/interpreter/_import/spec.py +++ b/astroid/interpreter/_import/spec.py @@ -145,26 +145,26 @@ def find_module( if submodule_path is not None: search_paths = list(submodule_path) - else: - search_paths = sys.path - - suffixes = (".py", ".pyi", importlib.machinery.BYTECODE_SUFFIXES[0]) - for entry in search_paths: - package_directory = os.path.join(entry, modname) - for suffix in suffixes: - package_file_name = "__init__" + suffix - file_path = os.path.join(package_directory, package_file_name) - if cached_os_path_isfile(file_path): - return ModuleSpec( - name=modname, - location=package_directory, - type=ModuleType.PKG_DIRECTORY, - ) - for suffix, type_ in ImportlibFinder._SUFFIXES: - file_name = modname + suffix - file_path = os.path.join(entry, file_name) - if cached_os_path_isfile(file_path): - return ModuleSpec(name=modname, location=file_path, type=type_) + else: + search_paths = sys.path + + suffixes = (".py", ".pyi", importlib.machinery.BYTECODE_SUFFIXES[0]) + for entry in search_paths: + package_directory = os.path.join(entry, modname) + for suffix in suffixes: + package_file_name = "__init__" + suffix + file_path = os.path.join(package_directory, package_file_name) + if cached_os_path_isfile(file_path): + return ModuleSpec( + name=modname, + location=package_directory, + type=ModuleType.PKG_DIRECTORY, + ) + for suffix, type_ in ImportlibFinder._SUFFIXES: + file_name = modname + suffix + file_path = os.path.join(entry, file_name) + if cached_os_path_isfile(file_path): + return ModuleSpec(name=modname, location=file_path, type=type_) # sys.stdlib_module_names was added in Python 3.10 if PY310_PLUS: From 11cf784cc3611e7bbf00c3e066b5f86c3089d95f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 24 Dec 2024 00:00:09 +0000 Subject: [PATCH 8/8] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- astroid/interpreter/_import/spec.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/astroid/interpreter/_import/spec.py b/astroid/interpreter/_import/spec.py index 5477c25c0..48a012a88 100644 --- a/astroid/interpreter/_import/spec.py +++ b/astroid/interpreter/_import/spec.py @@ -144,7 +144,7 @@ def find_module( ) if submodule_path is not None: - search_paths = list(submodule_path) + search_paths = list(submodule_path) else: search_paths = sys.path