Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Another attempt at fixing the collections.abc issue for Python 3.13 #2665

Merged
merged 9 commits into from
Dec 24, 2024
6 changes: 6 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -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
jacobtylerwalls marked this conversation as resolved.
Show resolved Hide resolved
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.

Expand Down
59 changes: 34 additions & 25 deletions astroid/interpreter/_import/spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,15 +142,46 @@ 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
# `find_spec` actually imports the module, so we want to make sure we only run this code
# 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
):
jacobtylerwalls marked this conversation as resolved.
Show resolved Hide resolved
spec = importlib.util.find_spec(".".join((*processed, modname)))
try:
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=Warning)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about limiting this to UserWarning for parity with #2121?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ran into issues with DeprecationWarnings for lib2to3 in the stdlib primer for pylint which is why I had to bump this to Warning.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright. It seems like a little bit of a regression that we're importing stdlib modules in more cases now, but I guess we have no choice really.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah.. I really don't know of any other way to fix this.

spec = importlib.util.find_spec(".".join((*processed, modname)))
except ValueError:
jacobtylerwalls marked this conversation as resolved.
Show resolved Hide resolved
spec = None

if (
spec
and spec.loader # type: ignore[comparison-overlap] # noqa: E501
Expand Down Expand Up @@ -186,28 +217,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(
Expand Down