aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken6/libshiboken/embed/signature_bootstrap.py
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken6/libshiboken/embed/signature_bootstrap.py')
-rw-r--r--sources/shiboken6/libshiboken/embed/signature_bootstrap.py211
1 files changed, 102 insertions, 109 deletions
diff --git a/sources/shiboken6/libshiboken/embed/signature_bootstrap.py b/sources/shiboken6/libshiboken/embed/signature_bootstrap.py
index 3078ac90a..37f95cd35 100644
--- a/sources/shiboken6/libshiboken/embed/signature_bootstrap.py
+++ b/sources/shiboken6/libshiboken/embed/signature_bootstrap.py
@@ -1,41 +1,5 @@
-#############################################################################
-##
-## Copyright (C) 2019 The Qt Company Ltd.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is part of PySide6.
-##
-## $QT_BEGIN_LICENSE:LGPL$
-## Commercial License Usage
-## Licensees holding valid commercial Qt licenses may use this file in
-## accordance with the commercial license agreement provided with the
-## Software or, alternatively, in accordance with the terms contained in
-## a written agreement between you and The Qt Company. For licensing terms
-## and conditions see https://www.qt.io/terms-conditions. For further
-## information use the contact form at https://www.qt.io/contact-us.
-##
-## GNU Lesser General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU Lesser
-## General Public License version 3 as published by the Free Software
-## Foundation and appearing in the file LICENSE.LGPL3 included in the
-## packaging of this file. Please review the following information to
-## ensure the GNU Lesser General Public License version 3 requirements
-## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-##
-## GNU General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU
-## General Public License version 2.0 or (at your option) the GNU General
-## Public license version 3 or any later version approved by the KDE Free
-## Qt Foundation. The licenses are as published by the Free Software
-## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-## included in the packaging of this file. Please review the following
-## information to ensure the GNU General Public License requirements will
-## be met: https://www.gnu.org/licenses/gpl-2.0.html and
-## https://www.gnu.org/licenses/gpl-3.0.html.
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
"""
signature_bootstrap.py
@@ -52,22 +16,27 @@ This file replaces the hard to read Python stub in 'signature.cpp', and we
could distinguish better between bootstrap related functions and loader
functions.
It is embedded into 'signature.cpp' as "embed/signature_bootstrap.inc".
+
+# PYSIDE-1436: Python 3.10 had a problem with EmbeddableZipImporter because the
+imports were in the functions. Moved them outside into the globals.
"""
recursion_trap = 0
-# We avoid real imports in phase 1 that could fail (simply removed all).
-# Python 2 is not able to import when the extension import is still active.
-# Phase 1 simply defines the functions, which will be used in Phase 2.
-# PYSIDE-1621: This can be removed after the backport but we leave it so.
+import base64
+import importlib
+import io
+import os
+import sys
+import traceback
+import zipfile
+
+from contextlib import contextmanager
+from importlib.machinery import ModuleSpec
+from pathlib import Path
+
def bootstrap():
- import sys
- import os
- import tempfile
- import traceback
- from contextlib import contextmanager
- from pathlib import Path
global recursion_trap
if recursion_trap:
@@ -93,52 +62,83 @@ def bootstrap():
import shibokensupport
yield
except Exception as e:
- print("Problem importing shibokensupport:")
- print(f"{e.__class__.__name__}: {e}")
+ f = sys.stderr
+ print("Problem importing shibokensupport:", file=f)
+ print(f"{e.__class__.__name__}: {e}", file=f)
traceback.print_exc()
- print("sys.path:")
+ print("sys.path:", file=f)
for p in sys.path:
- print(" " + p)
- sys.stdout.flush()
+ print(" " + p, file=f)
+ f.flush()
sys.exit(-1)
target.remove(support_path)
- import shiboken6 as root
- path = Path(root.__file__)
- rp = path.parent.resolve()
- # This can be the shiboken6 directory or the binary module, so search.
- look_for = Path("files.dir") / "shibokensupport" / "signature" / "loader.py"
- while not (rp / look_for).exists():
- dir = rp.parent
- if dir == rp: # Hit root, '/', 'C:\', '\\server\share'
- break
- rp = dir
-
- # Here we decide if we work embedded or not.
- embedding_var = "pyside_uses_embedding"
- use_embedding = bool(getattr(sys, embedding_var, False))
- loader_path = rp / look_for
- files_dir = loader_path.parents[2]
- assert files_dir.name == "files.dir"
-
- if not loader_path.exists():
- use_embedding = True
- setattr(sys, embedding_var, use_embedding)
-
- if use_embedding:
- target, support_path = prepare_zipfile()
+ # Here we decide if we re-incarnate the embedded files or use embedding.
+ incarnated = find_incarnated_files()
+ if incarnated:
+ target, support_path = sys.path, os.fspath(incarnated)
else:
- target, support_path = sys.path, os.fspath(files_dir)
+ target, support_path = prepare_zipfile()
+ with ensure_shibokensupport(target, support_path):
+ from shibokensupport.signature import loader
+ return loader
+
+# Newer functionality:
+# This function checks if the support directory exist and returns it.
+# If does not exist, we try to create it and return it.
+# Otherwise, we return None.
+def find_incarnated_files():
+ import shiboken6 as root
+ files_dir = Path(root.__file__).resolve().parent / "files.dir"
+ handle_embedding_switch(files_dir)
+ if files_dir.exists():
+ sys.path.insert(0, os.fspath(files_dir))
+ # Note: To avoid recursion problems, we need to preload the loader.
+ # But that has the side-effect that we need to delay the feature
+ # initialization until all function pointers are set.
+ # See `post_init_func` in signature_globals.cpp .
+ import shibokensupport.signature.loader
+ del sys.path[0]
+ return files_dir
+ return None
+
+
+def handle_embedding_switch(files_dir):
+ """
+ This handles the optional environment variable `SBK_EMBED`
+ if not set : do nothing
+ if set to 0, false, no : de-virtualize the Python files
+ if set to 1, true, yes : virtualize again (delete "files.dir")
+ """
+ env_name = "SBK_EMBED"
+ env_var = os.environ.get(env_name)
+ if not env_var:
+ return
+ if env_var.lower() in ("1", "t", "true", "y", "yes"):
+ import shutil
+ shutil.rmtree(files_dir, ignore_errors=True)
+ elif env_var.lower() in ("0", "f", "false", "n", "no"):
+ reincarnate_files(files_dir)
+
+
+def reincarnate_files(files_dir):
+ target, zip = prepare_zipfile()
+ names = (_ for _ in zip.zfile.namelist() if _.endswith(".py"))
+ try:
+ # First check mkdir to get an error when we cannot write.
+ files_dir.mkdir(exist_ok=True)
+ except os.error as e:
+ print(f"SBK_EMBED=False: Warning: Cannot write into {files_dir}")
+ return None
try:
- with ensure_shibokensupport(target, support_path):
- from shibokensupport.signature import loader
+ # Then check for a real error when unpacking the zip file.
+ zip.zfile.extractall(path=files_dir, members=names)
+ return files_dir
except Exception as e:
- print('Exception:', e)
- traceback.print_exc(file=sys.stdout)
-
- return loader
-
+ print(f"{e.__class__.__name__}: {e}", file=sys.stderr)
+ traceback.print_exc()
+ raise
# New functionality: Loading from a zip archive.
# There exists the zip importer, but as it is written, only real zip files are
@@ -159,10 +159,6 @@ def prepare_zipfile():
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 io
- import sys
- import zipfile
# 'zipstring_sequence' comes from signature.cpp
zipbytes = base64.b64decode(''.join(zipstring_sequence))
@@ -181,31 +177,28 @@ class EmbeddableZipImporter(object):
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()}
+ self._mod2path = {p2m(_.filename) : _.filename for _ in zip_file.filelist}
- def find_module(self, fullname, path):
- return self if self._mod2path.get(fullname) else None
+ def find_spec(self, fullname, path, target=None):
+ path = self._mod2path.get(fullname)
+ return ModuleSpec(fullname, self) if path else None
- def load_module(self, fullname):
- import importlib
- import sys
+ def create_module(self, spec):
+ return None
- 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)
+ def exec_module(self, module):
+ fullname = module.__spec__.name
+ filename = self._mod2path[fullname]
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
+ codeob = compile(f.read(), filename, "exec")
+ exec(codeob, module.__dict__)
+ module.__file__ = filename
+ module.__loader__ = self
if filename.endswith("/__init__.py"):
- new_module.__path__ = []
- new_module.__package__ = fullname
+ module.__path__ = []
+ module.__package__ = fullname
else:
- new_module.__package__ = fullname.rpartition('.')[0]
- sys.modules[fullname] = new_module
- return new_module
+ module.__package__ = fullname.rpartition('.')[0]
+ sys.modules[fullname] = module
# eof