aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken2/libshiboken/embed/signature_bootstrap.py
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken2/libshiboken/embed/signature_bootstrap.py')
-rw-r--r--sources/shiboken2/libshiboken/embed/signature_bootstrap.py87
1 files changed, 69 insertions, 18 deletions
diff --git a/sources/shiboken2/libshiboken/embed/signature_bootstrap.py b/sources/shiboken2/libshiboken/embed/signature_bootstrap.py
index dd8df2b63..902864267 100644
--- a/sources/shiboken2/libshiboken/embed/signature_bootstrap.py
+++ b/sources/shiboken2/libshiboken/embed/signature_bootstrap.py
@@ -77,10 +77,11 @@ def bootstrap():
recursion_trap += 1
@contextmanager
- def ensure_shibokensupport(support_path):
+ def ensure_shibokensupport(target, support_path):
# Make sure that we always have the shibokensupport containing package first.
# Also remove any prior loaded module of this name, just in case.
- sys.path.insert(0, support_path)
+ # PYSIDE-1621: support_path can also be a finder instance.
+ target.insert(0, support_path)
sbks = "shibokensupport"
if sbks in sys.modules:
@@ -100,7 +101,7 @@ def bootstrap():
print(" " + p)
sys.stdout.flush()
sys.exit(-1)
- sys.path.remove(support_path)
+ target.remove(support_path)
try:
import shiboken2 as root
@@ -119,8 +120,6 @@ def bootstrap():
# Here we decide if we work embedded or not.
embedding_var = "pyside_uses_embedding"
use_embedding = bool(getattr(sys, embedding_var, False))
- # We keep the zip file for inspection if the sys variable has been set.
- keep_zipfile = hasattr(sys, embedding_var)
loader_path = os.path.join(rp, look_for)
files_dir = os.path.abspath(os.path.join(loader_path, "..", "..", ".."))
assert files_dir.endswith("files.dir")
@@ -131,41 +130,54 @@ def bootstrap():
support_path = prepare_zipfile() if use_embedding else files_dir
setattr(sys, embedding_var, use_embedding)
+ if use_embedding:
+ target, support_path = prepare_zipfile()
+ else:
+ target, support_path = sys.path, files_dir
+
try:
- with ensure_shibokensupport(support_path):
+ with ensure_shibokensupport(target, support_path):
from shibokensupport.signature import loader
except Exception as e:
print('Exception:', e)
traceback.print_exc(file=sys.stdout)
- finally:
- if use_embedding and not keep_zipfile:
- # clear the temp zipfile
- try:
- os.remove(support_path)
- except OSError as e:
- print(e)
- print("Error deleting {support_path}, ignored".format(**locals()))
- return loader
+ return loader
+
# New functionality: Loading from a zip archive.
# There exists the zip importer, but as it is written, only real zip files are
# supported. Before I will start an own implementation, it is easiest to use
# a temporary zip file.
+# PYSIDE-1621: make zip file access totally virtual
def prepare_zipfile():
"""
Write the zip file to a real file and return its name.
It will be implicitly opened as such when we add the name to sys.path .
+
+ New approach (Python 3, only):
+
+ Use EmbeddableZipImporter and pass the zipfile structure directly.
+ The sys.path way does not work, instead we need to use sys.meta_path .
+ See https://docs.python.org/3/library/sys.html#sys.meta_path
"""
import base64
- import tempfile
- import os
+ import io
+ import sys
import zipfile
# 'zipstring_sequence' comes from signature.cpp
zipbytes = base64.b64decode(''.join(zipstring_sequence))
+ if sys.version_info[0] >= 3:
+ vzip = zipfile.ZipFile(io.BytesIO(zipbytes))
+ return sys.meta_path, EmbeddableZipImporter(vzip)
+
+ # Old version for Python 2.7, only.
+ import os
+ import tempfile
+
fd, fname = tempfile.mkstemp(prefix='embedded.', suffix='.zip')
os.write(fd, zipbytes)
os.close(fd)
@@ -178,6 +190,45 @@ def prepare_zipfile():
print('Broken Zip File:', e)
traceback.print_exc(file=sys.stdout)
finally:
- return fname
+ return sys.path, fname
+
+
+class EmbeddableZipImporter(object):
+
+ def __init__(self, zip_file):
+ def p2m(filename):
+ if filename.endswith("/__init__.py"):
+ return filename[:-12].replace("/", ".")
+ if filename.endswith(".py"):
+ return filename[:-3].replace("/", ".")
+ return None
+
+ self.zfile = zip_file
+ self._path2mod = {_.filename : p2m(_.filename) for _ in zip_file.filelist}
+ self._mod2path = {_[1] : _[0] for _ in self._path2mod.items()}
+
+ def find_module(self, fullname, path):
+ return self if self._mod2path.get(fullname) else None
+
+ def load_module(self, fullname):
+ import importlib
+ import sys
+
+ filename = self._mod2path.get(fullname)
+ if filename not in self._path2mod:
+ raise ImportError(fullname)
+ module_spec = importlib.machinery.ModuleSpec(fullname, None)
+ new_module = importlib.util.module_from_spec(module_spec)
+ with self.zfile.open(filename, "r") as f: # "rb" not for zipfile
+ exec(f.read(), new_module.__dict__)
+ new_module.__file__ = filename
+ new_module.__loader__ = self
+ if filename.endswith("/__init__.py"):
+ new_module.__path__ = []
+ new_module.__package__ = fullname
+ else:
+ new_module.__package__ = fullname.rpartition('.')[0]
+ sys.modules[fullname] = new_module
+ return new_module
# eof