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

Prevent special case for virtualenv's patching of distutils from catching other submodules #1544

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions ChangeLog
Expand Up @@ -16,6 +16,11 @@ Release date: TBA
* Rename ``ModuleSpec`` -> ``module_type`` constructor parameter to match attribute
name and improve typing. Use ``type`` instead.

* Fix a bug where in attempting to handle the patching of ``distutils`` by ``virtualenv``,
library submodules called ``distutils`` (e.g. ``numpy.distutils``) were included also.

Refs PyCQA/pylint#6497


What's New in astroid 2.11.4?
=============================
Expand Down
7 changes: 6 additions & 1 deletion astroid/interpreter/_import/spec.py
Expand Up @@ -14,6 +14,8 @@
from pathlib import Path
from typing import List, NamedTuple, Optional, Sequence, Tuple

from astroid.modutils import EXT_LIB_DIRS

from . import util


Expand Down Expand Up @@ -150,7 +152,10 @@ def contribute_to_path(self, spec, processed):
for p in sys.path
if os.path.isdir(os.path.join(p, *processed))
]
elif spec.name == "distutils":
elif spec.name == "distutils" and not any(
spec.location.lower().startswith(ext_lib_dir.lower())
for ext_lib_dir in EXT_LIB_DIRS
):
# virtualenv below 20.0 patches distutils in an unexpected way
# so we just find the location of distutils that will be
# imported to avoid spurious import-error messages
Expand Down
17 changes: 17 additions & 0 deletions tests/unittest_regrtest.py
Expand Up @@ -81,6 +81,23 @@ def test_numpy_crash(self):
inferred = callfunc.inferred()
self.assertEqual(len(inferred), 1)

@unittest.skipUnless(HAS_NUMPY, "Needs numpy")
def test_numpy_distutils(self):
"""Special handling of virtualenv's patching of distutils shouldn't interfere
with numpy.distutils.

PY312_PLUS -- This test will likely become unnecessary when Python 3.12 is
numpy's minimum version. (numpy.distutils will be removed then.)
"""
node = extract_node(
"""
from numpy.distutils.misc_util import is_sequence
is_sequence("ABC") #@
"""
)
inferred = node.inferred()
self.assertIsInstance(inferred[0], nodes.Const)

def test_nameconstant(self) -> None:
# used to fail for Python 3.4
builder = AstroidBuilder()
Expand Down