bpo-35936: Updates to modulefinder (GH-11787)

* Properly handle SyntaxErrors in Python source files.

SyntaxErrors in the target module will rise normally, while SyntaxErrors in dependencies will be added to badmodules. This includes a new regression test.

* Fix name collision bug.

This fixes an issue where a "fromlist" import with the same name as a previously failed import would be incorrectly added to badmodules. This includes a new regression test.

* Replace mutable default values.

Bound empty lists have been replaced with the "if param is None" idiom.

* Replace deprecated imp usage.

Constants imported from imp have been moved to private module-level constants, and ModuleFinder.find_module has been refactored to use importlib. Other than an improvement on how frozen builtin imports are reported (as the frozen imports they are, rather than the stdlib modules they *may* have originated from), these changes maintain complete compatibility with past versions... including odd behavior for returning relative (below current directory, but not a C extension) vs. absolute (above current directory, or a C extension) paths.

Patch by Brandt Bucher.
This commit is contained in:
Brandt Bucher 2019-04-07 01:00:41 -07:00 committed by Nick Coghlan
parent 2dad96013c
commit 9d7b2c0909
6 changed files with 116 additions and 16 deletions

View file

@ -218,6 +218,33 @@ bytecode_test = [
""
]
syntax_error_test = [
"a.module",
["a", "a.module", "b"],
["b.module"], [],
"""\
a/__init__.py
a/module.py
import b.module
b/__init__.py
b/module.py
? # SyntaxError: invalid syntax
"""]
same_name_as_bad_test = [
"a.module",
["a", "a.module", "b", "b.c"],
["c"], [],
"""\
a/__init__.py
a/module.py
import c
from b import c
b/__init__.py
b/c.py
"""]
def open_file(path):
dirname = os.path.dirname(path)
@ -299,6 +326,12 @@ class ModuleFinderTest(unittest.TestCase):
def test_relative_imports_4(self):
self._do_test(relative_import_test_4)
def test_syntax_error(self):
self._do_test(syntax_error_test)
def test_same_name_as_bad(self):
self._do_test(same_name_as_bad_test)
def test_bytecode(self):
base_path = os.path.join(TEST_DIR, 'a')
source_path = base_path + importlib.machinery.SOURCE_SUFFIXES[0]