mit neuen venv und exe-Files
This commit is contained in:
@@ -0,0 +1 @@
|
||||
#
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,37 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2013-2023, PyInstaller Development Team.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
def _pyi_rthook():
|
||||
import os
|
||||
import sys
|
||||
|
||||
# The directory names must match TCL_ROOTNAME and TK_ROOTNAME constants defined in `PyInstaller.utils.hooks.tcl_tk`.
|
||||
tcldir = os.path.join(sys._MEIPASS, '_tcl_data')
|
||||
tkdir = os.path.join(sys._MEIPASS, '_tk_data')
|
||||
|
||||
# Notify "tkinter" of data directories. On macOS, we do not collect data directories if system Tcl/Tk framework is
|
||||
# used. On other OSes, we always collect them, so their absence is considered an error.
|
||||
is_darwin = sys.platform == 'darwin'
|
||||
|
||||
if os.path.isdir(tcldir):
|
||||
os.environ["TCL_LIBRARY"] = tcldir
|
||||
elif not is_darwin:
|
||||
raise FileNotFoundError('Tcl data directory "%s" not found.' % tcldir)
|
||||
|
||||
if os.path.isdir(tkdir):
|
||||
os.environ["TK_LIBRARY"] = tkdir
|
||||
elif not is_darwin:
|
||||
raise FileNotFoundError('Tk data directory "%s" not found.' % tkdir)
|
||||
|
||||
|
||||
_pyi_rthook()
|
||||
del _pyi_rthook
|
||||
@@ -0,0 +1,34 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2005-2023, PyInstaller Development Team.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# This Django rthook was tested with Django 1.8.3.
|
||||
|
||||
|
||||
def _pyi_rthook():
|
||||
import django.utils.autoreload
|
||||
|
||||
_old_restart_with_reloader = django.utils.autoreload.restart_with_reloader
|
||||
|
||||
def _restart_with_reloader(*args):
|
||||
import sys
|
||||
a0 = sys.argv.pop(0)
|
||||
try:
|
||||
return _old_restart_with_reloader(*args)
|
||||
finally:
|
||||
sys.argv.insert(0, a0)
|
||||
|
||||
# Override restart_with_reloader() function, otherwise the app might complain that some commands do not exist;
|
||||
# e.g., runserver.
|
||||
django.utils.autoreload.restart_with_reloader = _restart_with_reloader
|
||||
|
||||
|
||||
_pyi_rthook()
|
||||
del _pyi_rthook
|
||||
@@ -0,0 +1,41 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2023, PyInstaller Development Team.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
def _pyi_rthook():
|
||||
import atexit
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
pixbuf_file = os.path.join(sys._MEIPASS, 'lib', 'gdk-pixbuf', 'loaders.cache')
|
||||
|
||||
# If we are not on Windows, we need to rewrite the cache -> we rewrite on Mac OS to support --onefile mode
|
||||
if os.path.exists(pixbuf_file) and sys.platform != 'win32':
|
||||
with open(pixbuf_file, 'rb') as fp:
|
||||
contents = fp.read()
|
||||
|
||||
# Create a temporary file with the cache and cleverly replace the prefix we injected with the actual path.
|
||||
fd, pixbuf_file = tempfile.mkstemp()
|
||||
with os.fdopen(fd, 'wb') as fp:
|
||||
libpath = os.path.join(sys._MEIPASS, 'lib').encode('utf-8')
|
||||
fp.write(contents.replace(b'@executable_path/lib', libpath))
|
||||
|
||||
try:
|
||||
atexit.register(os.unlink, pixbuf_file)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
os.environ['GDK_PIXBUF_MODULE_FILE'] = pixbuf_file
|
||||
|
||||
|
||||
_pyi_rthook()
|
||||
del _pyi_rthook
|
||||
@@ -0,0 +1,21 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2023, PyInstaller Development Team.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
def _pyi_rthook():
|
||||
import os
|
||||
import sys
|
||||
|
||||
os.environ['GI_TYPELIB_PATH'] = os.path.join(sys._MEIPASS, 'gi_typelibs')
|
||||
|
||||
|
||||
_pyi_rthook()
|
||||
del _pyi_rthook
|
||||
@@ -0,0 +1,21 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2023, PyInstaller Development Team.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
def _pyi_rthook():
|
||||
import os
|
||||
import sys
|
||||
|
||||
os.environ['GIO_MODULE_DIR'] = os.path.join(sys._MEIPASS, 'gio_modules')
|
||||
|
||||
|
||||
_pyi_rthook()
|
||||
del _pyi_rthook
|
||||
@@ -0,0 +1,37 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2023, PyInstaller Development Team.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
def _pyi_rthook():
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Prepend the frozen application's data dir to XDG_DATA_DIRS. We need to avoid overwriting the existing paths in
|
||||
# order to allow the frozen application to run system-installed applications (for example, launch a web browser via
|
||||
# the webbrowser module on Linux). Should the user desire complete isolation of the frozen application from the
|
||||
# system, they need to clean up XDG_DATA_DIRS at the start of their program (i.e., remove all entries but first).
|
||||
pyi_data_dir = os.path.join(sys._MEIPASS, 'share')
|
||||
|
||||
xdg_data_dirs = os.environ.get('XDG_DATA_DIRS', None)
|
||||
if xdg_data_dirs:
|
||||
if pyi_data_dir not in xdg_data_dirs:
|
||||
xdg_data_dirs = pyi_data_dir + os.pathsep + xdg_data_dirs
|
||||
else:
|
||||
xdg_data_dirs = pyi_data_dir
|
||||
os.environ['XDG_DATA_DIRS'] = xdg_data_dirs
|
||||
|
||||
# Cleanup aux variables
|
||||
del xdg_data_dirs
|
||||
del pyi_data_dir
|
||||
|
||||
|
||||
_pyi_rthook()
|
||||
del _pyi_rthook
|
||||
@@ -0,0 +1,32 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2013-2023, PyInstaller Development Team.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
def _pyi_rthook():
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Without this environment variable set to 'no' importing 'gst' causes 100% CPU load. (Tested on Mac OS.)
|
||||
os.environ['GST_REGISTRY_FORK'] = 'no'
|
||||
|
||||
gst_plugin_paths = [sys._MEIPASS, os.path.join(sys._MEIPASS, 'gst-plugins')]
|
||||
os.environ['GST_PLUGIN_PATH'] = os.pathsep.join(gst_plugin_paths)
|
||||
|
||||
# Prevent permission issues on Windows
|
||||
os.environ['GST_REGISTRY'] = os.path.join(sys._MEIPASS, 'registry.bin')
|
||||
|
||||
# Only use packaged plugins to prevent GStreamer from crashing when it finds plugins from another version which are
|
||||
# installed system wide.
|
||||
os.environ['GST_PLUGIN_SYSTEM_PATH'] = ''
|
||||
|
||||
|
||||
_pyi_rthook()
|
||||
del _pyi_rthook
|
||||
@@ -0,0 +1,27 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2023, PyInstaller Development Team.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
def _pyi_rthook():
|
||||
import os
|
||||
import sys
|
||||
|
||||
os.environ['GTK_DATA_PREFIX'] = sys._MEIPASS
|
||||
os.environ['GTK_EXE_PREFIX'] = sys._MEIPASS
|
||||
os.environ['GTK_PATH'] = sys._MEIPASS
|
||||
|
||||
# Include these here, as GTK will import pango automatically.
|
||||
os.environ['PANGO_LIBDIR'] = sys._MEIPASS
|
||||
os.environ['PANGO_SYSCONFDIR'] = os.path.join(sys._MEIPASS, 'etc') # TODO?
|
||||
|
||||
|
||||
_pyi_rthook()
|
||||
del _pyi_rthook
|
||||
@@ -0,0 +1,53 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2021-2023, PyInstaller Development Team.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
def _pyi_rthook():
|
||||
import inspect
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Use sys._MEIPASS with normalized path component separator. This is necessary on some platforms (i.e., msys2/mingw
|
||||
# python on Windows), because we use string comparisons on the paths.
|
||||
SYS_PREFIX = os.path.normpath(sys._MEIPASS)
|
||||
|
||||
_orig_inspect_getsourcefile = inspect.getsourcefile
|
||||
|
||||
# Provide custom implementation of inspect.getsourcefile() for frozen applications that properly resolves relative
|
||||
# filenames obtained from object (e.g., inspect stack-frames). See #5963.
|
||||
def _pyi_getsourcefile(object):
|
||||
filename = inspect.getfile(object)
|
||||
filename = os.path.normpath(filename) # Ensure path component separators are normalized.
|
||||
if not os.path.isabs(filename):
|
||||
# Check if given filename matches the basename of __main__'s __file__.
|
||||
main_file = getattr(sys.modules['__main__'], '__file__', None)
|
||||
if main_file and filename == os.path.basename(main_file):
|
||||
return main_file
|
||||
|
||||
# If filename ends with .py suffix and does not correspond to frozen entry-point script, convert it to
|
||||
# corresponding .pyc in sys._MEIPASS.
|
||||
if filename.endswith('.py'):
|
||||
filename = os.path.normpath(os.path.join(SYS_PREFIX, filename + 'c'))
|
||||
# Ensure the relative path did not try to jump out of sys._MEIPASS, just in case...
|
||||
if filename.startswith(SYS_PREFIX):
|
||||
return filename
|
||||
elif filename.startswith(SYS_PREFIX) and filename.endswith('.pyc'):
|
||||
# If filename is already PyInstaller-compatible, prevent any further processing (i.e., with original
|
||||
# implementation).
|
||||
return filename
|
||||
# Use original implementation as a fallback.
|
||||
return _orig_inspect_getsourcefile(object)
|
||||
|
||||
inspect.getsourcefile = _pyi_getsourcefile
|
||||
|
||||
|
||||
_pyi_rthook()
|
||||
del _pyi_rthook
|
||||
@@ -0,0 +1,24 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2015-2023, PyInstaller Development Team.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
def _pyi_rthook():
|
||||
import os
|
||||
import sys
|
||||
|
||||
root = os.path.join(sys._MEIPASS, 'kivy_install')
|
||||
|
||||
os.environ['KIVY_DATA_DIR'] = os.path.join(root, 'data')
|
||||
os.environ['KIVY_MODULES_DIR'] = os.path.join(root, 'modules')
|
||||
|
||||
|
||||
_pyi_rthook()
|
||||
del _pyi_rthook
|
||||
@@ -0,0 +1,46 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2013-2023, PyInstaller Development Team.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# matplotlib will create $HOME/.matplotlib folder in user's home directory. In this directory there is fontList.cache
|
||||
# file which lists paths to matplotlib fonts.
|
||||
#
|
||||
# When you run your onefile exe for the first time it's extracted to for example "_MEIxxxxx" temp directory and
|
||||
# fontList.cache file is created with fonts paths pointing to this directory.
|
||||
#
|
||||
# Second time you run your exe new directory is created "_MEIyyyyy" but fontList.cache file still points to previous
|
||||
# directory which was deleted. And then you will get error like:
|
||||
#
|
||||
# RuntimeError: Could not open facefile
|
||||
#
|
||||
# We need to force matplotlib to recreate config directory every time you run your app.
|
||||
|
||||
|
||||
def _pyi_rthook():
|
||||
import atexit
|
||||
import os
|
||||
import shutil
|
||||
|
||||
import _pyi_rth_utils.tempfile # PyInstaller's run-time hook utilities module
|
||||
|
||||
# Isolate matplotlib's config dir into temporary directory.
|
||||
# Use our replacement for `tempfile.mkdtemp` function that properly restricts access to directory on all platforms.
|
||||
configdir = _pyi_rth_utils.tempfile.secure_mkdtemp()
|
||||
os.environ['MPLCONFIGDIR'] = configdir
|
||||
|
||||
try:
|
||||
# Remove temp directory at application exit and ignore any errors.
|
||||
atexit.register(shutil.rmtree, configdir, ignore_errors=True)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
|
||||
_pyi_rthook()
|
||||
del _pyi_rthook
|
||||
@@ -0,0 +1,55 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2017-2023, PyInstaller Development Team.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
def _pyi_rthook():
|
||||
import sys
|
||||
|
||||
import multiprocessing
|
||||
import multiprocessing.spawn
|
||||
|
||||
from subprocess import _args_from_interpreter_flags
|
||||
|
||||
# Prevent `spawn` from trying to read `__main__` in from the main script
|
||||
multiprocessing.process.ORIGINAL_DIR = None
|
||||
|
||||
def _freeze_support():
|
||||
# We want to catch the two processes that are spawned by the multiprocessing code:
|
||||
# - the semaphore tracker, which cleans up named semaphores in the `spawn` multiprocessing mode
|
||||
# - the fork server, which keeps track of worker processes in the `forkserver` mode.
|
||||
# Both of these processes are started by spawning a new copy of the running executable, passing it the flags
|
||||
# from `_args_from_interpreter_flags` and then "-c" and an import statement.
|
||||
# Look for those flags and the import statement, then `exec()` the code ourselves.
|
||||
|
||||
if (
|
||||
len(sys.argv) >= 2 and sys.argv[-2] == '-c' and sys.argv[-1].startswith(
|
||||
('from multiprocessing.resource_tracker import main', 'from multiprocessing.forkserver import main')
|
||||
) and set(sys.argv[1:-2]) == set(_args_from_interpreter_flags())
|
||||
):
|
||||
exec(sys.argv[-1])
|
||||
sys.exit()
|
||||
|
||||
if multiprocessing.spawn.is_forking(sys.argv):
|
||||
kwds = {}
|
||||
for arg in sys.argv[2:]:
|
||||
name, value = arg.split('=')
|
||||
if value == 'None':
|
||||
kwds[name] = None
|
||||
else:
|
||||
kwds[name] = int(value)
|
||||
multiprocessing.spawn.spawn_main(**kwds)
|
||||
sys.exit()
|
||||
|
||||
multiprocessing.freeze_support = multiprocessing.spawn.freeze_support = _freeze_support
|
||||
|
||||
|
||||
_pyi_rthook()
|
||||
del _pyi_rthook
|
||||
@@ -0,0 +1,171 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2013-2023, PyInstaller Development Team.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# To make pkg_resources work with frozen modules we need to set the 'Provider' class for PyiFrozenImporter.
|
||||
# This class decides where to look for resources and other stuff.
|
||||
#
|
||||
# 'pkg_resources.NullProvider' is dedicated to PEP302 import hooks like PyiFileImporter is. It uses method
|
||||
# __loader__.get_data() in methods pkg_resources.resource_string() and pkg_resources.resource_stream()
|
||||
#
|
||||
# We provide PyiFrozenProvider, which subclasses the NullProvider and implements _has(), _isdir(), and _listdir()
|
||||
# methods, which are needed for pkg_resources.resource_exists(), resource_isdir(), and resource_listdir() to work. We
|
||||
# cannot use the DefaultProvider, because it provides filesystem-only implementations (and overrides _get() with a
|
||||
# filesystem-only one), whereas our provider needs to also support embedded resources.
|
||||
#
|
||||
# The PyiFrozenProvider allows querying/listing both PYZ-embedded and on-filesystem resources in a frozen package. The
|
||||
# results are typically combined for both types of resources (e.g., when listing a directory or checking whether a
|
||||
# resource exists). When the order of precedence matters, the PYZ-embedded resources take precedence over the
|
||||
# on-filesystem ones, to keep the behavior consistent with the actual file content retrieval via _get() method (which in
|
||||
# turn uses PyiFrozenImporter's get_data() method). For example, when checking whether a resource is a directory via
|
||||
# _isdir(), a PYZ-embedded file will take precedence over a potential on-filesystem directory. Also, in contrast to
|
||||
# unfrozen packages, the frozen ones do not contain source .py files, which are therefore absent from content listings.
|
||||
|
||||
|
||||
def _pyi_rthook():
|
||||
import os
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
import pkg_resources
|
||||
|
||||
import pyimod02_importers # PyInstaller's bootstrap module
|
||||
|
||||
SYS_PREFIX = pathlib.PurePath(sys._MEIPASS)
|
||||
|
||||
class _TocFilesystem:
|
||||
"""
|
||||
A prefix tree implementation for embedded filesystem reconstruction.
|
||||
|
||||
NOTE: as of PyInstaller 6.0, the embedded PYZ archive cannot contain data files anymore. Instead, it contains
|
||||
only .pyc modules - which are by design not returned by `PyiFrozenProvider`. So this implementation has been
|
||||
reduced to supporting only directories implied by collected packages.
|
||||
"""
|
||||
def __init__(self, tree_node):
|
||||
self._tree = tree_node
|
||||
|
||||
def _get_tree_node(self, path):
|
||||
path = pathlib.PurePath(path)
|
||||
current = self._tree
|
||||
for component in path.parts:
|
||||
if component not in current:
|
||||
return None
|
||||
current = current[component]
|
||||
return current
|
||||
|
||||
def path_exists(self, path):
|
||||
node = self._get_tree_node(path)
|
||||
return isinstance(node, dict) # Directory only
|
||||
|
||||
def path_isdir(self, path):
|
||||
node = self._get_tree_node(path)
|
||||
return isinstance(node, dict) # Directory only
|
||||
|
||||
def path_listdir(self, path):
|
||||
node = self._get_tree_node(path)
|
||||
if not isinstance(node, dict):
|
||||
return [] # Non-existent or file
|
||||
# Return only sub-directories
|
||||
return [entry_name for entry_name, entry_data in node.items() if isinstance(entry_data, dict)]
|
||||
|
||||
class PyiFrozenProvider(pkg_resources.NullProvider):
|
||||
"""
|
||||
Custom pkg_resources provider for PyiFrozenImporter.
|
||||
"""
|
||||
def __init__(self, module):
|
||||
super().__init__(module)
|
||||
|
||||
# Get top-level path; if "module" corresponds to a package, we need the path to the package itself.
|
||||
# If "module" is a submodule in a package, we need the path to the parent package.
|
||||
#
|
||||
# This is equivalent to `pkg_resources.NullProvider.module_path`, except we construct a `pathlib.PurePath`
|
||||
# for easier manipulation.
|
||||
#
|
||||
# NOTE: the path is NOT resolved for symbolic links, as neither are paths that are passed by `pkg_resources`
|
||||
# to `_has`, `_isdir`, `_listdir` (they are all anchored to `module_path`, which in turn is just
|
||||
# `os.path.dirname(module.__file__)`. As `__file__` returned by `PyiFrozenImporter` is always anchored to
|
||||
# `sys._MEIPASS`, we do not have to worry about cross-linked directories in macOS .app bundles, where the
|
||||
# resolved `__file__` could be either in the `Contents/Frameworks` directory (the "true" `sys._MEIPASS`), or
|
||||
# in the `Contents/Resources` directory due to cross-linking.
|
||||
self._pkg_path = pathlib.PurePath(module.__file__).parent
|
||||
|
||||
# Construct _TocFilesystem on top of pre-computed prefix tree provided by pyimod02_importers.
|
||||
self.embedded_tree = _TocFilesystem(pyimod02_importers.get_pyz_toc_tree())
|
||||
|
||||
def _normalize_path(self, path):
|
||||
# Avoid using `Path.resolve`, because it resolves symlinks. This is undesirable, because the pure path in
|
||||
# `self._pkg_path` does not have symlinks resolved, so comparison between the two would be faulty. Instead,
|
||||
# use `os.path.normpath` to normalize the path and get rid of any '..' elements (the path itself should
|
||||
# already be absolute).
|
||||
return pathlib.Path(os.path.normpath(path))
|
||||
|
||||
def _is_relative_to_package(self, path):
|
||||
return path == self._pkg_path or self._pkg_path in path.parents
|
||||
|
||||
def _has(self, path):
|
||||
# Prevent access outside the package.
|
||||
path = self._normalize_path(path)
|
||||
if not self._is_relative_to_package(path):
|
||||
return False
|
||||
|
||||
# Check the filesystem first to avoid unnecessarily computing the relative path...
|
||||
if path.exists():
|
||||
return True
|
||||
rel_path = path.relative_to(SYS_PREFIX)
|
||||
return self.embedded_tree.path_exists(rel_path)
|
||||
|
||||
def _isdir(self, path):
|
||||
# Prevent access outside the package.
|
||||
path = self._normalize_path(path)
|
||||
if not self._is_relative_to_package(path):
|
||||
return False
|
||||
|
||||
# Embedded resources have precedence over filesystem...
|
||||
rel_path = path.relative_to(SYS_PREFIX)
|
||||
node = self.embedded_tree._get_tree_node(rel_path)
|
||||
if node is None:
|
||||
return path.is_dir() # No match found; try the filesystem.
|
||||
else:
|
||||
# str = file, dict = directory
|
||||
return not isinstance(node, str)
|
||||
|
||||
def _listdir(self, path):
|
||||
# Prevent access outside the package.
|
||||
path = self._normalize_path(path)
|
||||
if not self._is_relative_to_package(path):
|
||||
return []
|
||||
|
||||
# Relative path for searching embedded resources.
|
||||
rel_path = path.relative_to(SYS_PREFIX)
|
||||
# List content from embedded filesystem...
|
||||
content = self.embedded_tree.path_listdir(rel_path)
|
||||
# ... as well as the actual one.
|
||||
if path.is_dir():
|
||||
# Use os.listdir() to avoid having to convert Path objects to strings... Also make sure to de-duplicate
|
||||
# the results.
|
||||
path = str(path) # not is_py36
|
||||
content = list(set(content + os.listdir(path)))
|
||||
return content
|
||||
|
||||
pkg_resources.register_loader_type(pyimod02_importers.PyiFrozenImporter, PyiFrozenProvider)
|
||||
|
||||
# With our PyiFrozenImporter now being a path entry finder, it effectively replaces python's FileFinder. So we need
|
||||
# to register it with `pkg_resources.find_on_path` to allow metadata to be found on filesystem.
|
||||
pkg_resources.register_finder(pyimod02_importers.PyiFrozenImporter, pkg_resources.find_on_path)
|
||||
|
||||
# For the above change to fully take effect, we need to re-initialize pkg_resources's master working set (since the
|
||||
# original one was built with assumption that sys.path entries are handled by python's FileFinder).
|
||||
# See https://github.com/pypa/setuptools/issues/373
|
||||
if hasattr(pkg_resources, '_initialize_master_working_set'):
|
||||
pkg_resources._initialize_master_working_set()
|
||||
|
||||
|
||||
_pyi_rthook()
|
||||
del _pyi_rthook
|
||||
@@ -0,0 +1,64 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2021-2023, PyInstaller Development Team.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#-----------------------------------------------------------------------------
|
||||
#
|
||||
# The run-time hook provides a custom module iteration function for our PyiFrozenImporter, which allows
|
||||
# `pkgutil.iter_modules()` to return entries for modules that are embedded in the PYZ archive. The non-embedded modules
|
||||
# (binary extensions, modules collected as only source .py files, etc.) are enumerated using the `fallback_finder`
|
||||
# provided by `PyiFrozenImporter` (which typically would be the python's `FileFinder`).
|
||||
def _pyi_rthook():
|
||||
import pkgutil
|
||||
|
||||
import pyimod02_importers # PyInstaller's bootstrap module
|
||||
|
||||
# This could, in fact, be implemented as `iter_modules()` method of the `PyiFrozenImporter`. However, we want to
|
||||
# avoid importing `pkgutil` in that bootstrap module (i.e., for the `pkgutil.iter_importer_modules()` call on the
|
||||
# fallback finder).
|
||||
def _iter_pyi_frozen_file_finder_modules(finder, prefix=''):
|
||||
# Fetch PYZ TOC tree from pyimod02_importers
|
||||
pyz_toc_tree = pyimod02_importers.get_pyz_toc_tree()
|
||||
|
||||
# Finder has already pre-computed the package prefix implied by the search path. Use it to find the starting
|
||||
# node in the prefix tree.
|
||||
if finder._pyz_entry_prefix:
|
||||
pkg_name_parts = finder._pyz_entry_prefix.split('.')
|
||||
else:
|
||||
pkg_name_parts = []
|
||||
|
||||
tree_node = pyz_toc_tree
|
||||
for pkg_name_part in pkg_name_parts:
|
||||
tree_node = tree_node.get(pkg_name_part)
|
||||
if not isinstance(tree_node, dict):
|
||||
# This check handles two cases:
|
||||
# a) path does not exist (`tree_node` is `None`)
|
||||
# b) path corresponds to a module instead of a package (`tree_node` is a leaf node (`str`)).
|
||||
tree_node = {}
|
||||
break
|
||||
|
||||
# Dump the contents of the tree node.
|
||||
for entry_name, entry_data in tree_node.items():
|
||||
is_pkg = isinstance(entry_data, dict)
|
||||
yield prefix + entry_name, is_pkg
|
||||
|
||||
# If our finder has a fall-back finder available, iterate its modules as well. By using the public
|
||||
# `fallback_finder` attribute, we force creation of the fallback finder as necessary.
|
||||
# NOTE: we do not care about potential duplicates here, because `pkgutil.iter_modules()` itself
|
||||
# keeps track of yielded names for purposes of de-duplication.
|
||||
if finder.fallback_finder is not None:
|
||||
yield from pkgutil.iter_importer_modules(finder.fallback_finder, prefix)
|
||||
|
||||
pkgutil.iter_importer_modules.register(
|
||||
pyimod02_importers.PyiFrozenImporter,
|
||||
_iter_pyi_frozen_file_finder_modules,
|
||||
)
|
||||
|
||||
|
||||
_pyi_rthook()
|
||||
del _pyi_rthook
|
||||
@@ -0,0 +1,68 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2014-2023, PyInstaller Development Team.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# The path to Qt's components may not default to the wheel layout for self-compiled PyQt5 installations. Mandate the
|
||||
# wheel layout. See ``utils/hooks/qt.py`` for more details.
|
||||
|
||||
|
||||
def _pyi_rthook():
|
||||
import os
|
||||
import sys
|
||||
|
||||
from _pyi_rth_utils import is_macos_app_bundle, prepend_path_to_environment_variable
|
||||
from _pyi_rth_utils import qt as qt_rth_utils
|
||||
|
||||
# Ensure this is the only Qt bindings package in the application.
|
||||
qt_rth_utils.ensure_single_qt_bindings_package("PyQt5")
|
||||
|
||||
# Try PyQt5 5.15.4-style path first...
|
||||
pyqt_path = os.path.join(sys._MEIPASS, 'PyQt5', 'Qt5')
|
||||
if not os.path.isdir(pyqt_path):
|
||||
# ... and fall back to the older version
|
||||
pyqt_path = os.path.join(sys._MEIPASS, 'PyQt5', 'Qt')
|
||||
|
||||
os.environ['QT_PLUGIN_PATH'] = os.path.join(pyqt_path, 'plugins')
|
||||
|
||||
if is_macos_app_bundle:
|
||||
# Special handling for macOS .app bundles. To satisfy codesign requirements, we are forced to split `qml`
|
||||
# directory into two parts; one that keeps only binaries (rooted in `Contents/Frameworks`) and one that keeps
|
||||
# only data files (rooted in `Contents/Resources), with files from one directory tree being symlinked to the
|
||||
# other to maintain illusion of a single mixed-content directory. As Qt seems to compute the identifier of its
|
||||
# QML components based on location of the `qmldir` file w.r.t. the registered QML import paths, we need to
|
||||
# register both paths, because the `qmldir` file for a component could be reached via either directory tree.
|
||||
pyqt_path_res = os.path.normpath(
|
||||
os.path.join(sys._MEIPASS, '..', 'Resources', os.path.relpath(pyqt_path, sys._MEIPASS))
|
||||
)
|
||||
os.environ['QML2_IMPORT_PATH'] = os.pathsep.join([
|
||||
os.path.join(pyqt_path_res, 'qml'),
|
||||
os.path.join(pyqt_path, 'qml'),
|
||||
])
|
||||
else:
|
||||
os.environ['QML2_IMPORT_PATH'] = os.path.join(pyqt_path, 'qml')
|
||||
|
||||
# Back in the day, this was required because PyQt5 5.12.3 explicitly checked that `Qt5Core.dll` was in `PATH`
|
||||
# (see #4293), and contemporary PyInstaller versions collected that DLL to `sys._MEIPASS`.
|
||||
#
|
||||
# Nowadays, we add `sys._MEIPASS` to `PATH` in order to ensure that `QtNetwork` can discover OpenSSL DLLs that might
|
||||
# have been collected there (i.e., when they were not shipped with the package, and were collected from an external
|
||||
# location).
|
||||
if sys.platform.startswith('win'):
|
||||
prepend_path_to_environment_variable(sys._MEIPASS, 'PATH')
|
||||
|
||||
# Qt bindings package installed via PyPI wheels typically ensures that its bundled Qt is relocatable, by creating
|
||||
# embedded `qt.conf` file during its initialization. This run-time generated qt.conf dynamically sets the Qt prefix
|
||||
# path to the package's Qt directory. For bindings packages that do not create embedded `qt.conf` during their
|
||||
# initialization (for example, conda-installed packages), try to perform this step ourselves.
|
||||
qt_rth_utils.create_embedded_qt_conf("PyQt5", pyqt_path)
|
||||
|
||||
|
||||
_pyi_rthook()
|
||||
del _pyi_rthook
|
||||
@@ -0,0 +1,70 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2021-2023, PyInstaller Development Team.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# The path to Qt's components may not default to the wheel layout for self-compiled PyQt6 installations. Mandate the
|
||||
# wheel layout. See ``utils/hooks/qt.py`` for more details.
|
||||
|
||||
|
||||
def _pyi_rthook():
|
||||
import os
|
||||
import sys
|
||||
|
||||
from _pyi_rth_utils import is_macos_app_bundle, prepend_path_to_environment_variable
|
||||
from _pyi_rth_utils import qt as qt_rth_utils
|
||||
|
||||
# Ensure this is the only Qt bindings package in the application.
|
||||
qt_rth_utils.ensure_single_qt_bindings_package("PyQt6")
|
||||
|
||||
# Try PyQt6 6.0.3-style path first...
|
||||
pyqt_path = os.path.join(sys._MEIPASS, 'PyQt6', 'Qt6')
|
||||
if not os.path.isdir(pyqt_path):
|
||||
# ... and fall back to the older version.
|
||||
pyqt_path = os.path.join(sys._MEIPASS, 'PyQt6', 'Qt')
|
||||
|
||||
os.environ['QT_PLUGIN_PATH'] = os.path.join(pyqt_path, 'plugins')
|
||||
|
||||
if is_macos_app_bundle:
|
||||
# Special handling for macOS .app bundles. To satisfy codesign requirements, we are forced to split `qml`
|
||||
# directory into two parts; one that keeps only binaries (rooted in `Contents/Frameworks`) and one that keeps
|
||||
# only data files (rooted in `Contents/Resources), with files from one directory tree being symlinked to the
|
||||
# other to maintain illusion of a single mixed-content directory. As Qt seems to compute the identifier of its
|
||||
# QML components based on location of the `qmldir` file w.r.t. the registered QML import paths, we need to
|
||||
# register both paths, because the `qmldir` file for a component could be reached via either directory tree.
|
||||
pyqt_path_res = os.path.normpath(
|
||||
os.path.join(sys._MEIPASS, '..', 'Resources', os.path.relpath(pyqt_path, sys._MEIPASS))
|
||||
)
|
||||
os.environ['QML2_IMPORT_PATH'] = os.pathsep.join([
|
||||
os.path.join(pyqt_path_res, 'qml'),
|
||||
os.path.join(pyqt_path, 'qml'),
|
||||
])
|
||||
else:
|
||||
os.environ['QML2_IMPORT_PATH'] = os.path.join(pyqt_path, 'qml')
|
||||
|
||||
# Add `sys._MEIPASS` to `PATH` in order to ensure that `QtNetwork` can discover OpenSSL DLLs that might have been
|
||||
# collected there (i.e., when they were not shipped with the package, and were collected from an external location).
|
||||
if sys.platform.startswith('win'):
|
||||
prepend_path_to_environment_variable(sys._MEIPASS, 'PATH')
|
||||
|
||||
# For macOS POSIX builds, we need to add `sys._MEIPASS` to `DYLD_LIBRARY_PATH` so that QtNetwork can discover
|
||||
# OpenSSL dynamic libraries for its `openssl` TLS backend. This also prevents fallback to external locations, such
|
||||
# as Homebrew. For .app bundles, this is unnecessary because `QtNetwork` explicitly searches `Contents/Frameworks`.
|
||||
if sys.platform == 'darwin' and not is_macos_app_bundle:
|
||||
prepend_path_to_environment_variable(sys._MEIPASS, 'DYLD_LIBRARY_PATH')
|
||||
|
||||
# Qt bindings package installed via PyPI wheels typically ensures that its bundled Qt is relocatable, by creating
|
||||
# embedded `qt.conf` file during its initialization. This run-time generated qt.conf dynamically sets the Qt prefix
|
||||
# path to the package's Qt directory. For bindings packages that do not create embedded `qt.conf` during their
|
||||
# initialization (for example, conda-installed packages), try to perform this step ourselves.
|
||||
qt_rth_utils.create_embedded_qt_conf("PyQt6", pyqt_path)
|
||||
|
||||
|
||||
_pyi_rthook()
|
||||
del _pyi_rthook
|
||||
@@ -0,0 +1,63 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2013-2023, PyInstaller Development Team.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# The path to Qt's components may not default to the wheel layout for self-compiled PySide2 installations. Mandate the
|
||||
# wheel layout. See ``utils/hooks/qt.py`` for more details.
|
||||
|
||||
|
||||
def _pyi_rthook():
|
||||
import os
|
||||
import sys
|
||||
|
||||
from _pyi_rth_utils import is_macos_app_bundle, prepend_path_to_environment_variable
|
||||
from _pyi_rth_utils import qt as qt_rth_utils
|
||||
|
||||
# Ensure this is the only Qt bindings package in the application.
|
||||
qt_rth_utils.ensure_single_qt_bindings_package("PySide2")
|
||||
|
||||
if sys.platform.startswith('win'):
|
||||
pyqt_path = os.path.join(sys._MEIPASS, 'PySide2')
|
||||
else:
|
||||
pyqt_path = os.path.join(sys._MEIPASS, 'PySide2', 'Qt')
|
||||
|
||||
os.environ['QT_PLUGIN_PATH'] = os.path.join(pyqt_path, 'plugins')
|
||||
|
||||
if is_macos_app_bundle:
|
||||
# Special handling for macOS .app bundles. To satisfy codesign requirements, we are forced to split `qml`
|
||||
# directory into two parts; one that keeps only binaries (rooted in `Contents/Frameworks`) and one that keeps
|
||||
# only data files (rooted in `Contents/Resources), with files from one directory tree being symlinked to the
|
||||
# other to maintain illusion of a single mixed-content directory. As Qt seems to compute the identifier of its
|
||||
# QML components based on location of the `qmldir` file w.r.t. the registered QML import paths, we need to
|
||||
# register both paths, because the `qmldir` file for a component could be reached via either directory tree.
|
||||
pyqt_path_res = os.path.normpath(
|
||||
os.path.join(sys._MEIPASS, '..', 'Resources', os.path.relpath(pyqt_path, sys._MEIPASS))
|
||||
)
|
||||
os.environ['QML2_IMPORT_PATH'] = os.pathsep.join([
|
||||
os.path.join(pyqt_path_res, 'qml'),
|
||||
os.path.join(pyqt_path, 'qml'),
|
||||
])
|
||||
else:
|
||||
os.environ['QML2_IMPORT_PATH'] = os.path.join(pyqt_path, 'qml')
|
||||
|
||||
# Add `sys._MEIPASS` to `PATH` in order to ensure that `QtNetwork` can discover OpenSSL DLLs that might have been
|
||||
# collected there (i.e., when they were not shipped with the package, and were collected from an external location).
|
||||
if sys.platform.startswith('win'):
|
||||
prepend_path_to_environment_variable(sys._MEIPASS, 'PATH')
|
||||
|
||||
# Qt bindings package installed via PyPI wheels typically ensures that its bundled Qt is relocatable, by creating
|
||||
# embedded `qt.conf` file during its initialization. This run-time generated qt.conf dynamically sets the Qt prefix
|
||||
# path to the package's Qt directory. For bindings packages that do not create embedded `qt.conf` during their
|
||||
# initialization (for example, conda-installed packages), try to perform this step ourselves.
|
||||
qt_rth_utils.create_embedded_qt_conf("PySide2", pyqt_path)
|
||||
|
||||
|
||||
_pyi_rthook()
|
||||
del _pyi_rthook
|
||||
@@ -0,0 +1,69 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2021-2023, PyInstaller Development Team.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# The path to Qt's components may not default to the wheel layout for self-compiled PySide6 installations. Mandate the
|
||||
# wheel layout. See ``utils/hooks/qt.py`` for more details.
|
||||
|
||||
|
||||
def _pyi_rthook():
|
||||
import os
|
||||
import sys
|
||||
|
||||
from _pyi_rth_utils import is_macos_app_bundle, prepend_path_to_environment_variable
|
||||
from _pyi_rth_utils import qt as qt_rth_utils
|
||||
|
||||
# Ensure this is the only Qt bindings package in the application.
|
||||
qt_rth_utils.ensure_single_qt_bindings_package("PySide6")
|
||||
|
||||
if sys.platform.startswith('win'):
|
||||
pyqt_path = os.path.join(sys._MEIPASS, 'PySide6')
|
||||
else:
|
||||
pyqt_path = os.path.join(sys._MEIPASS, 'PySide6', 'Qt')
|
||||
|
||||
os.environ['QT_PLUGIN_PATH'] = os.path.join(pyqt_path, 'plugins')
|
||||
|
||||
if is_macos_app_bundle:
|
||||
# Special handling for macOS .app bundles. To satisfy codesign requirements, we are forced to split `qml`
|
||||
# directory into two parts; one that keeps only binaries (rooted in `Contents/Frameworks`) and one that keeps
|
||||
# only data files (rooted in `Contents/Resources), with files from one directory tree being symlinked to the
|
||||
# other to maintain illusion of a single mixed-content directory. As Qt seems to compute the identifier of its
|
||||
# QML components based on location of the `qmldir` file w.r.t. the registered QML import paths, we need to
|
||||
# register both paths, because the `qmldir` file for a component could be reached via either directory tree.
|
||||
pyqt_path_res = os.path.normpath(
|
||||
os.path.join(sys._MEIPASS, '..', 'Resources', os.path.relpath(pyqt_path, sys._MEIPASS))
|
||||
)
|
||||
os.environ['QML2_IMPORT_PATH'] = os.pathsep.join([
|
||||
os.path.join(pyqt_path_res, 'qml'),
|
||||
os.path.join(pyqt_path, 'qml'),
|
||||
])
|
||||
else:
|
||||
os.environ['QML2_IMPORT_PATH'] = os.path.join(pyqt_path, 'qml')
|
||||
|
||||
# Add `sys._MEIPASS` to `PATH` in order to ensure that `QtNetwork` can discover OpenSSL DLLs that might have been
|
||||
# collected there (i.e., when they were not shipped with the package, and were collected from an external location).
|
||||
if sys.platform.startswith('win'):
|
||||
prepend_path_to_environment_variable(sys._MEIPASS, 'PATH')
|
||||
|
||||
# For macOS POSIX builds, we need to add `sys._MEIPASS` to `DYLD_LIBRARY_PATH` so that QtNetwork can discover
|
||||
# OpenSSL dynamic libraries for its `openssl` TLS backend. This also prevents fallback to external locations, such
|
||||
# as Homebrew. For .app bundles, this is unnecessary because `QtNetwork` explicitly searches `Contents/Frameworks`.
|
||||
if sys.platform == 'darwin' and not is_macos_app_bundle:
|
||||
prepend_path_to_environment_variable(sys._MEIPASS, 'DYLD_LIBRARY_PATH')
|
||||
|
||||
# Qt bindings package installed via PyPI wheels typically ensures that its bundled Qt is relocatable, by creating
|
||||
# embedded `qt.conf` file during its initialization. This run-time generated qt.conf dynamically sets the Qt prefix
|
||||
# path to the package's Qt directory. For bindings packages that do not create embedded `qt.conf` during their
|
||||
# initialization (for example, conda-installed packages), try to perform this step ourselves.
|
||||
qt_rth_utils.create_embedded_qt_conf("PySide6", pyqt_path)
|
||||
|
||||
|
||||
_pyi_rthook()
|
||||
del _pyi_rthook
|
||||
@@ -0,0 +1,37 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2022-2023, PyInstaller Development Team.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# This runtime hook performs the equivalent of the distutils-precedence.pth from the setuptools package;
|
||||
# it registers a special meta finder that diverts import of distutils to setuptools._distutils, if available.
|
||||
|
||||
|
||||
def _pyi_rthook():
|
||||
def _install_setuptools_distutils_hack():
|
||||
import os
|
||||
import setuptools
|
||||
|
||||
# We need to query setuptools version at runtime, because the default value for SETUPTOOLS_USE_DISTUTILS
|
||||
# has changed at version 60.0 from "stdlib" to "local", and we want to mimic that behavior.
|
||||
setuptools_major = int(setuptools.__version__.split('.')[0])
|
||||
default_value = "stdlib" if setuptools_major < 60 else "local"
|
||||
|
||||
if os.environ.get("SETUPTOOLS_USE_DISTUTILS", default_value) == "local":
|
||||
import _distutils_hack
|
||||
_distutils_hack.add_shim()
|
||||
|
||||
try:
|
||||
_install_setuptools_distutils_hack()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
_pyi_rthook()
|
||||
del _pyi_rthook
|
||||
Reference in New Issue
Block a user