bpo-40260: Update modulefinder to use io.open_code() and respect coding comments (GH-19488)
This commit is contained in:
parent
aade1cc453
commit
d42e582063
|
@ -5,6 +5,7 @@ import importlib._bootstrap_external
|
||||||
import importlib.machinery
|
import importlib.machinery
|
||||||
import marshal
|
import marshal
|
||||||
import os
|
import os
|
||||||
|
import io
|
||||||
import sys
|
import sys
|
||||||
import types
|
import types
|
||||||
import warnings
|
import warnings
|
||||||
|
@ -68,35 +69,32 @@ def _find_module(name, path=None):
|
||||||
# Some special cases:
|
# Some special cases:
|
||||||
|
|
||||||
if spec.loader is importlib.machinery.BuiltinImporter:
|
if spec.loader is importlib.machinery.BuiltinImporter:
|
||||||
return None, None, ("", "", _C_BUILTIN)
|
return None, None, ("", _C_BUILTIN)
|
||||||
|
|
||||||
if spec.loader is importlib.machinery.FrozenImporter:
|
if spec.loader is importlib.machinery.FrozenImporter:
|
||||||
return None, None, ("", "", _PY_FROZEN)
|
return None, None, ("", _PY_FROZEN)
|
||||||
|
|
||||||
file_path = spec.origin
|
file_path = spec.origin
|
||||||
|
|
||||||
if spec.loader.is_package(name):
|
if spec.loader.is_package(name):
|
||||||
return None, os.path.dirname(file_path), ("", "", _PKG_DIRECTORY)
|
return None, os.path.dirname(file_path), ("", _PKG_DIRECTORY)
|
||||||
|
|
||||||
if isinstance(spec.loader, importlib.machinery.SourceFileLoader):
|
if isinstance(spec.loader, importlib.machinery.SourceFileLoader):
|
||||||
kind = _PY_SOURCE
|
kind = _PY_SOURCE
|
||||||
mode = "r"
|
|
||||||
|
|
||||||
elif isinstance(spec.loader, importlib.machinery.ExtensionFileLoader):
|
elif isinstance(spec.loader, importlib.machinery.ExtensionFileLoader):
|
||||||
kind = _C_EXTENSION
|
kind = _C_EXTENSION
|
||||||
mode = "rb"
|
|
||||||
|
|
||||||
elif isinstance(spec.loader, importlib.machinery.SourcelessFileLoader):
|
elif isinstance(spec.loader, importlib.machinery.SourcelessFileLoader):
|
||||||
kind = _PY_COMPILED
|
kind = _PY_COMPILED
|
||||||
mode = "rb"
|
|
||||||
|
|
||||||
else: # Should never happen.
|
else: # Should never happen.
|
||||||
return None, None, ("", "", _SEARCH_ERROR)
|
return None, None, ("", _SEARCH_ERROR)
|
||||||
|
|
||||||
file = open(file_path, mode)
|
file = io.open_code(file_path)
|
||||||
suffix = os.path.splitext(file_path)[-1]
|
suffix = os.path.splitext(file_path)[-1]
|
||||||
|
|
||||||
return file, file_path, (suffix, mode, kind)
|
return file, file_path, (suffix, kind)
|
||||||
|
|
||||||
|
|
||||||
class Module:
|
class Module:
|
||||||
|
@ -160,15 +158,15 @@ class ModuleFinder:
|
||||||
|
|
||||||
def run_script(self, pathname):
|
def run_script(self, pathname):
|
||||||
self.msg(2, "run_script", pathname)
|
self.msg(2, "run_script", pathname)
|
||||||
with open(pathname) as fp:
|
with io.open_code(pathname) as fp:
|
||||||
stuff = ("", "r", _PY_SOURCE)
|
stuff = ("", _PY_SOURCE)
|
||||||
self.load_module('__main__', fp, pathname, stuff)
|
self.load_module('__main__', fp, pathname, stuff)
|
||||||
|
|
||||||
def load_file(self, pathname):
|
def load_file(self, pathname):
|
||||||
dir, name = os.path.split(pathname)
|
dir, name = os.path.split(pathname)
|
||||||
name, ext = os.path.splitext(name)
|
name, ext = os.path.splitext(name)
|
||||||
with open(pathname) as fp:
|
with io.open_code(pathname) as fp:
|
||||||
stuff = (ext, "r", _PY_SOURCE)
|
stuff = (ext, _PY_SOURCE)
|
||||||
self.load_module(name, fp, pathname, stuff)
|
self.load_module(name, fp, pathname, stuff)
|
||||||
|
|
||||||
def import_hook(self, name, caller=None, fromlist=None, level=-1):
|
def import_hook(self, name, caller=None, fromlist=None, level=-1):
|
||||||
|
@ -333,14 +331,14 @@ class ModuleFinder:
|
||||||
return m
|
return m
|
||||||
|
|
||||||
def load_module(self, fqname, fp, pathname, file_info):
|
def load_module(self, fqname, fp, pathname, file_info):
|
||||||
suffix, mode, type = file_info
|
suffix, type = file_info
|
||||||
self.msgin(2, "load_module", fqname, fp and "fp", pathname)
|
self.msgin(2, "load_module", fqname, fp and "fp", pathname)
|
||||||
if type == _PKG_DIRECTORY:
|
if type == _PKG_DIRECTORY:
|
||||||
m = self.load_package(fqname, pathname)
|
m = self.load_package(fqname, pathname)
|
||||||
self.msgout(2, "load_module ->", m)
|
self.msgout(2, "load_module ->", m)
|
||||||
return m
|
return m
|
||||||
if type == _PY_SOURCE:
|
if type == _PY_SOURCE:
|
||||||
co = compile(fp.read()+'\n', pathname, 'exec')
|
co = compile(fp.read()+b'\n', pathname, 'exec')
|
||||||
elif type == _PY_COMPILED:
|
elif type == _PY_COMPILED:
|
||||||
try:
|
try:
|
||||||
data = fp.read()
|
data = fp.read()
|
||||||
|
@ -504,7 +502,7 @@ class ModuleFinder:
|
||||||
|
|
||||||
if path is None:
|
if path is None:
|
||||||
if name in sys.builtin_module_names:
|
if name in sys.builtin_module_names:
|
||||||
return (None, None, ("", "", _C_BUILTIN))
|
return (None, None, ("", _C_BUILTIN))
|
||||||
|
|
||||||
path = self.path
|
path = self.path
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,8 @@ a/module.py
|
||||||
from c import something
|
from c import something
|
||||||
b/__init__.py
|
b/__init__.py
|
||||||
from sys import *
|
from sys import *
|
||||||
"""]
|
""",
|
||||||
|
]
|
||||||
|
|
||||||
maybe_test_new = [
|
maybe_test_new = [
|
||||||
"a.module",
|
"a.module",
|
||||||
|
@ -245,6 +246,48 @@ b/__init__.py
|
||||||
b/c.py
|
b/c.py
|
||||||
"""]
|
"""]
|
||||||
|
|
||||||
|
coding_default_utf8_test = [
|
||||||
|
"a_utf8",
|
||||||
|
["a_utf8", "b_utf8"],
|
||||||
|
[], [],
|
||||||
|
"""\
|
||||||
|
a_utf8.py
|
||||||
|
# use the default of utf8
|
||||||
|
print('Unicode test A code point 2090 \u2090 that is not valid in cp1252')
|
||||||
|
import b_utf8
|
||||||
|
b_utf8.py
|
||||||
|
# use the default of utf8
|
||||||
|
print('Unicode test B code point 2090 \u2090 that is not valid in cp1252')
|
||||||
|
"""]
|
||||||
|
|
||||||
|
coding_explicit_utf8_test = [
|
||||||
|
"a_utf8",
|
||||||
|
["a_utf8", "b_utf8"],
|
||||||
|
[], [],
|
||||||
|
"""\
|
||||||
|
a_utf8.py
|
||||||
|
# coding=utf8
|
||||||
|
print('Unicode test A code point 2090 \u2090 that is not valid in cp1252')
|
||||||
|
import b_utf8
|
||||||
|
b_utf8.py
|
||||||
|
# use the default of utf8
|
||||||
|
print('Unicode test B code point 2090 \u2090 that is not valid in cp1252')
|
||||||
|
"""]
|
||||||
|
|
||||||
|
coding_explicit_cp1252_test = [
|
||||||
|
"a_cp1252",
|
||||||
|
["a_cp1252", "b_utf8"],
|
||||||
|
[], [],
|
||||||
|
b"""\
|
||||||
|
a_cp1252.py
|
||||||
|
# coding=cp1252
|
||||||
|
# 0xe2 is not allowed in utf8
|
||||||
|
print('CP1252 test P\xe2t\xe9')
|
||||||
|
import b_utf8
|
||||||
|
b_utf8.py
|
||||||
|
# use the default of utf8
|
||||||
|
print('Unicode test A code point 2090 \u2090 that is not valid in cp1252')
|
||||||
|
"""]
|
||||||
|
|
||||||
def open_file(path):
|
def open_file(path):
|
||||||
dirname = os.path.dirname(path)
|
dirname = os.path.dirname(path)
|
||||||
|
@ -253,18 +296,22 @@ def open_file(path):
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
if e.errno != errno.EEXIST:
|
if e.errno != errno.EEXIST:
|
||||||
raise
|
raise
|
||||||
return open(path, "w")
|
return open(path, 'wb')
|
||||||
|
|
||||||
|
|
||||||
def create_package(source):
|
def create_package(source):
|
||||||
ofi = None
|
ofi = None
|
||||||
try:
|
try:
|
||||||
for line in source.splitlines():
|
for line in source.splitlines():
|
||||||
if line.startswith(" ") or line.startswith("\t"):
|
if type(line) != bytes:
|
||||||
ofi.write(line.strip() + "\n")
|
line = line.encode('utf-8')
|
||||||
|
if line.startswith(b' ') or line.startswith(b'\t'):
|
||||||
|
ofi.write(line.strip() + b'\n')
|
||||||
else:
|
else:
|
||||||
if ofi:
|
if ofi:
|
||||||
ofi.close()
|
ofi.close()
|
||||||
|
if type(line) == bytes:
|
||||||
|
line = line.decode('utf-8')
|
||||||
ofi = open_file(os.path.join(TEST_DIR, line.strip()))
|
ofi = open_file(os.path.join(TEST_DIR, line.strip()))
|
||||||
finally:
|
finally:
|
||||||
if ofi:
|
if ofi:
|
||||||
|
@ -337,7 +384,7 @@ class ModuleFinderTest(unittest.TestCase):
|
||||||
source_path = base_path + importlib.machinery.SOURCE_SUFFIXES[0]
|
source_path = base_path + importlib.machinery.SOURCE_SUFFIXES[0]
|
||||||
bytecode_path = base_path + importlib.machinery.BYTECODE_SUFFIXES[0]
|
bytecode_path = base_path + importlib.machinery.BYTECODE_SUFFIXES[0]
|
||||||
with open_file(source_path) as file:
|
with open_file(source_path) as file:
|
||||||
file.write('testing_modulefinder = True\n')
|
file.write('testing_modulefinder = True\n'.encode('utf-8'))
|
||||||
py_compile.compile(source_path, cfile=bytecode_path)
|
py_compile.compile(source_path, cfile=bytecode_path)
|
||||||
os.remove(source_path)
|
os.remove(source_path)
|
||||||
self._do_test(bytecode_test)
|
self._do_test(bytecode_test)
|
||||||
|
@ -365,6 +412,14 @@ b.py
|
||||||
""" % list(range(2**16))] # 2**16 constants
|
""" % list(range(2**16))] # 2**16 constants
|
||||||
self._do_test(extended_opargs_test)
|
self._do_test(extended_opargs_test)
|
||||||
|
|
||||||
|
def test_coding_default_utf8(self):
|
||||||
|
self._do_test(coding_default_utf8_test)
|
||||||
|
|
||||||
|
def test_coding_explicit_utf8(self):
|
||||||
|
self._do_test(coding_explicit_utf8_test)
|
||||||
|
|
||||||
|
def test_coding_explicit_cp1252(self):
|
||||||
|
self._do_test(coding_explicit_cp1252_test)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Ensure :mod:`modulefinder` uses :func:`io.open_code` and respects coding comments.
|
Loading…
Reference in New Issue