Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 14581d5

Browse files
committed
Port py_compile over to importlib
1 parent 80512de commit 14581d5

4 files changed

Lines changed: 4328 additions & 4315 deletions

File tree

Lib/importlib/_bootstrap.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,15 @@ def _compile_bytecode(data, name=None, bytecode_path=None, source_path=None):
689689
raise ImportError("Non-code object in {!r}".format(bytecode_path),
690690
name=name, path=bytecode_path)
691691

692+
def _code_to_bytecode(code, mtime=0, source_size=0):
693+
"""Compile a code object into bytecode for writing out to a byte-compiled
694+
file."""
695+
data = bytearray(_MAGIC_BYTES)
696+
data.extend(_w_long(mtime))
697+
data.extend(_w_long(source_size))
698+
data.extend(marshal.dumps(code))
699+
return data
700+
692701

693702
# Loaders #####################################################################
694703

@@ -951,13 +960,13 @@ def get_source(self, fullname):
951960
raise ImportError("Failed to decode source file",
952961
name=fullname) from exc
953962

954-
def source_to_code(self, data, path):
963+
def source_to_code(self, data, path, *, _optimize=-1):
955964
"""Return the code object compiled from source.
956965
957966
The 'data' argument can be any object type that compile() supports.
958967
"""
959968
return _call_with_frames_removed(compile, data, path, 'exec',
960-
dont_inherit=True)
969+
dont_inherit=True, optimize=_optimize)
961970

962971
def get_code(self, fullname):
963972
"""Concrete implementation of InspectLoader.get_code.
@@ -1000,11 +1009,9 @@ def get_code(self, fullname):
10001009
code_object = self.source_to_code(source_bytes, source_path)
10011010
_verbose_message('code object from {}', source_path)
10021011
if (not sys.dont_write_bytecode and bytecode_path is not None and
1003-
source_mtime is not None):
1004-
data = bytearray(_MAGIC_BYTES)
1005-
data.extend(_w_long(source_mtime))
1006-
data.extend(_w_long(len(source_bytes)))
1007-
data.extend(marshal.dumps(code_object))
1012+
source_mtime is not None):
1013+
data = _code_to_bytecode(code_object, source_mtime,
1014+
len(source_bytes))
10081015
try:
10091016
self._cache_bytecode(source_path, bytecode_path, data)
10101017
_verbose_message('wrote {!r}', bytecode_path)

Lib/py_compile.py

Lines changed: 17 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,13 @@
33
This module has intimate knowledge of the format of .pyc files.
44
"""
55

6-
import builtins
7-
import errno
86
import imp
9-
import marshal
7+
import importlib._bootstrap
8+
import importlib.machinery
109
import os
1110
import sys
12-
import tokenize
1311
import traceback
1412

15-
MAGIC = imp.get_magic()
16-
1713
__all__ = ["compile", "main", "PyCompileError"]
1814

1915

@@ -65,13 +61,6 @@ def __str__(self):
6561
return self.msg
6662

6763

68-
def wr_long(f, x):
69-
"""Internal; write a 32-bit int to a file in little-endian order."""
70-
f.write(bytes([x & 0xff,
71-
(x >> 8) & 0xff,
72-
(x >> 16) & 0xff,
73-
(x >> 24) & 0xff]))
74-
7564
def compile(file, cfile=None, dfile=None, doraise=False, optimize=-1):
7665
"""Byte-compile one Python source file to Python bytecode.
7766
@@ -108,44 +97,33 @@ def compile(file, cfile=None, dfile=None, doraise=False, optimize=-1):
10897
byte-compile all installed files (or all files in selected
10998
directories).
11099
"""
111-
with tokenize.open(file) as f:
112-
try:
113-
st = os.fstat(f.fileno())
114-
except AttributeError:
115-
st = os.stat(file)
116-
timestamp = int(st.st_mtime)
117-
size = st.st_size & 0xFFFFFFFF
118-
codestring = f.read()
100+
if cfile is None:
101+
if optimize >= 0:
102+
cfile = imp.cache_from_source(file, debug_override=not optimize)
103+
else:
104+
cfile = imp.cache_from_source(file)
105+
loader = importlib.machinery.SourceFileLoader('<py_compile>', file)
106+
source_bytes = loader.get_data(file)
119107
try:
120-
codeobject = builtins.compile(codestring, dfile or file, 'exec',
121-
optimize=optimize)
108+
code = loader.source_to_code(source_bytes, dfile or file,
109+
_optimize=optimize)
122110
except Exception as err:
123111
py_exc = PyCompileError(err.__class__, err, dfile or file)
124112
if doraise:
125113
raise py_exc
126114
else:
127115
sys.stderr.write(py_exc.msg + '\n')
128116
return
129-
if cfile is None:
130-
if optimize >= 0:
131-
cfile = imp.cache_from_source(file, debug_override=not optimize)
132-
else:
133-
cfile = imp.cache_from_source(file)
134117
try:
135118
dirname = os.path.dirname(cfile)
136119
if dirname:
137120
os.makedirs(dirname)
138-
except OSError as error:
139-
if error.errno != errno.EEXIST:
140-
raise
141-
with open(cfile, 'wb') as fc:
142-
fc.write(b'\0\0\0\0')
143-
wr_long(fc, timestamp)
144-
wr_long(fc, size)
145-
marshal.dump(codeobject, fc)
146-
fc.flush()
147-
fc.seek(0, 0)
148-
fc.write(MAGIC)
121+
except FileExistsError:
122+
pass
123+
source_stats = loader.path_stats(file)
124+
bytecode = importlib._bootstrap._code_to_bytecode(code,
125+
source_stats['mtime'], len(source_bytes))
126+
loader._cache_bytecode(file, cfile, bytecode)
149127
return cfile
150128

151129
def main(args=None):

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,8 @@ Core and Builtins
223223
Library
224224
-------
225225

226+
Have py_compile use importlib as much as possible to avoid code duplication.
227+
226228
- Issue #180022: Have site.addpackage() consider already known paths even when
227229
none are explicitly passed in. Bug report and fix by Kirill.
228230

0 commit comments

Comments
 (0)