From 8f919b7e405e0a880f5af5ee36a3447de552d813 Mon Sep 17 00:00:00 2001 From: Mitchell Stokes Date: Mon, 12 Feb 2018 17:47:55 -0800 Subject: [PATCH] deploy-ng: Fix to handle utf-8 Python source files on all systems NOTE: This only works for Python 3 --- direct/src/showutil/FreezeTool.py | 58 ++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 9 deletions(-) diff --git a/direct/src/showutil/FreezeTool.py b/direct/src/showutil/FreezeTool.py index e55468c2c6..891b6b2108 100644 --- a/direct/src/showutil/FreezeTool.py +++ b/direct/src/showutil/FreezeTool.py @@ -8,7 +8,7 @@ import marshal import imp import platform import struct -from io import StringIO, BytesIO, TextIOWrapper +import io import distutils.sysconfig as sysconf import zipfile @@ -1143,11 +1143,14 @@ class Freezer: stuff = ("", "rb", imp.PY_COMPILED) self.mf.load_module(mdef.moduleName, fp, pathname, stuff) else: - if mdef.text: - fp = StringIO(mdef.text) - else: - fp = open(pathname, 'U') stuff = ("", "r", imp.PY_SOURCE) + if mdef.text: + fp = io.StringIO(mdef.text) + elif sys.version_info >= (3, 0): + fp = open(pathname, 'rb') + stuff = ("", "rb", imp.PY_SOURCE) + else: + fp = open(pathname, 'r') self.mf.load_module(mdef.moduleName, fp, pathname, stuff) if tempPath: @@ -1910,7 +1913,7 @@ class Freezer: if data.startswith(b'MZ'): # A Windows PE file. pe = pefile.PEFile() - pe.read(BytesIO(data)) + pe.read(io.BytesIO(data)) addr = pe.get_export_address(symbol_name) if addr is not None: # We found it, return its offset in the file. @@ -2162,8 +2165,8 @@ class PandaModuleFinder(modulefinder.ModuleFinder): Returns None if the module could not be found. """ if os.path.isfile(path): - if sys.version_info >= (3, 0) and 'b' not in mode: - return open(path, mode, encoding='utf8') + if 'b' not in mode: + return io.open(path, mode, encoding='utf8') else: return open(path, mode) @@ -2189,7 +2192,7 @@ class PandaModuleFinder(modulefinder.ModuleFinder): return None if sys.version_info >= (3, 0) and 'b' not in mode: - return TextIOWrapper(fp, encoding='utf8') + return io.TextIOWrapper(fp, encoding='utf8') return fp # Look at the parent directory. @@ -2198,6 +2201,43 @@ class PandaModuleFinder(modulefinder.ModuleFinder): return None + def load_module(self, fqname, fp, pathname, file_info): + """Copied from ModuleFinder.load_module with fixes to handle sending bytes + to compile() for PY_SOURCE types. Sending bytes to compile allows it to + handle file encodings.""" + + if sys.version_info < (3, 0): + # fallback to original version for Python 2 + return super.load_module(fqname, fp, pathname, file_info) + + suffix, mode, type = file_info + self.msgin(2, "load_module", fqname, fp and "fp", pathname) + if type == imp.PKG_DIRECTORY: + m = self.load_package(fqname, pathname) + self.msgout(2, "load_module ->", m) + return m + if type == imp.PY_SOURCE: + newline = b'\n' if 'b' in mode else '\n' + co = compile(fp.read()+newline, pathname, 'exec') + elif type == imp.PY_COMPILED: + try: + marshal_data = importlib._bootstrap_external._validate_bytecode_header(fp.read()) + except ImportError as exc: + self.msgout(2, "raise ImportError: " + str(exc), pathname) + raise + co = marshal.loads(marshal_data) + else: + co = None + m = self.add_module(fqname) + m.__file__ = pathname + if co: + if self.replace_paths: + co = self.replace_paths_in_code(co) + m.__code__ = co + self.scan_code(co, m) + self.msgout(2, "load_module ->", m) + return m + def find_module(self, name, path=None, parent=None): """ Finds a module with the indicated name on the given search path (or self.path if None). Returns a tuple like (fp, path, stuff), where