Remove hardcoded libpython binaries and add debug step
All checks were successful
build / build-linux (push) Successful in 16s
All checks were successful
build / build-linux (push) Successful in 16s
This commit is contained in:
140
venv/lib/python3.12/site-packages/PyInstaller/loader/pyimod01_archive.py
Executable file
140
venv/lib/python3.12/site-packages/PyInstaller/loader/pyimod01_archive.py
Executable file
@@ -0,0 +1,140 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 2005-2023, PyInstaller Development Team.
|
||||
#
|
||||
# Distributed under the terms of the GNU General Public License (version 2
|
||||
# or later) with exception for distributing the bootloader.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#
|
||||
# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# **NOTE** This module is used during bootstrap.
|
||||
# Import *ONLY* builtin modules or modules that are collected into the base_library.zip archive.
|
||||
# List of built-in modules: sys.builtin_module_names
|
||||
# List of modules collected into base_library.zip: PyInstaller.compat.PY3_BASE_MODULES
|
||||
|
||||
import os
|
||||
import struct
|
||||
import marshal
|
||||
import zlib
|
||||
|
||||
# In Python3, the MAGIC_NUMBER value is available in the importlib module. However, in the bootstrap phase we cannot use
|
||||
# importlib directly, but rather its frozen variant.
|
||||
import _frozen_importlib
|
||||
|
||||
PYTHON_MAGIC_NUMBER = _frozen_importlib._bootstrap_external.MAGIC_NUMBER
|
||||
|
||||
# Type codes for PYZ PYZ entries
|
||||
PYZ_ITEM_MODULE = 0
|
||||
PYZ_ITEM_PKG = 1
|
||||
PYZ_ITEM_DATA = 2 # deprecated; PYZ does not contain any data entries anymore
|
||||
PYZ_ITEM_NSPKG = 3 # PEP-420 namespace package
|
||||
|
||||
|
||||
class ArchiveReadError(RuntimeError):
|
||||
pass
|
||||
|
||||
|
||||
class ZlibArchiveReader:
|
||||
"""
|
||||
Reader for PyInstaller's PYZ (ZlibArchive) archive. The archive is used to store collected byte-compiled Python
|
||||
modules, as individually-compressed entries.
|
||||
"""
|
||||
_PYZ_MAGIC_PATTERN = b'PYZ\0'
|
||||
|
||||
def __init__(self, filename, start_offset=None, check_pymagic=False):
|
||||
self._filename = filename
|
||||
self._start_offset = start_offset
|
||||
|
||||
self.toc = {}
|
||||
|
||||
# If no offset is given, try inferring it from filename
|
||||
if start_offset is None:
|
||||
self._filename, self._start_offset = self._parse_offset_from_filename(filename)
|
||||
|
||||
# Parse header and load TOC. Standard header contains 12 bytes: PYZ magic pattern, python bytecode magic
|
||||
# pattern, and offset to TOC (32-bit integer). It might be followed by additional fields, depending on
|
||||
# implementation version.
|
||||
with open(self._filename, "rb") as fp:
|
||||
# Read PYZ magic pattern, located at the start of the file
|
||||
fp.seek(self._start_offset, os.SEEK_SET)
|
||||
|
||||
magic = fp.read(len(self._PYZ_MAGIC_PATTERN))
|
||||
if magic != self._PYZ_MAGIC_PATTERN:
|
||||
raise ArchiveReadError("PYZ magic pattern mismatch!")
|
||||
|
||||
# Read python magic/version number
|
||||
pymagic = fp.read(len(PYTHON_MAGIC_NUMBER))
|
||||
if check_pymagic and pymagic != PYTHON_MAGIC_NUMBER:
|
||||
raise ArchiveReadError("Python magic pattern mismatch!")
|
||||
|
||||
# Read TOC offset
|
||||
toc_offset, *_ = struct.unpack('!i', fp.read(4))
|
||||
|
||||
# Load TOC
|
||||
fp.seek(self._start_offset + toc_offset, os.SEEK_SET)
|
||||
self.toc = dict(marshal.load(fp))
|
||||
|
||||
@staticmethod
|
||||
def _parse_offset_from_filename(filename):
|
||||
"""
|
||||
Parse the numeric offset from filename, stored as: `/path/to/file?offset`.
|
||||
"""
|
||||
offset = 0
|
||||
|
||||
idx = filename.rfind('?')
|
||||
if idx == -1:
|
||||
return filename, offset
|
||||
|
||||
try:
|
||||
offset = int(filename[idx + 1:])
|
||||
filename = filename[:idx] # Remove the offset from filename
|
||||
except ValueError:
|
||||
# Ignore spurious "?" in the path (for example, like in Windows UNC \\?\<path>).
|
||||
pass
|
||||
|
||||
return filename, offset
|
||||
|
||||
def extract(self, name, raw=False):
|
||||
"""
|
||||
Extract data from entry with the given name.
|
||||
|
||||
If the entry belongs to a module or a package, the data is loaded (unmarshaled) into code object. To retrieve
|
||||
raw data, set `raw` flag to True.
|
||||
"""
|
||||
# Look up entry
|
||||
entry = self.toc.get(name)
|
||||
if entry is None:
|
||||
raise KeyError(f"No entry named {name!r} found in the archive!")
|
||||
|
||||
typecode, entry_offset, entry_length = entry
|
||||
|
||||
# PEP-420 namespace package does not have a data blob.
|
||||
if typecode == PYZ_ITEM_NSPKG:
|
||||
return None
|
||||
|
||||
# Read data blob
|
||||
try:
|
||||
with open(self._filename, "rb") as fp:
|
||||
fp.seek(self._start_offset + entry_offset)
|
||||
obj = fp.read(entry_length)
|
||||
except FileNotFoundError:
|
||||
# We open the archive file each time we need to read from it, to avoid locking the file by keeping it open.
|
||||
# This allows executable to be deleted or moved (renamed) while it is running, which is useful in certain
|
||||
# scenarios (e.g., automatic update that replaces the executable). The caveat is that once the executable is
|
||||
# renamed, we cannot read from its embedded PYZ archive anymore. In such case, exit with informative
|
||||
# message.
|
||||
raise SystemExit(
|
||||
f"ERROR: {self._filename} appears to have been moved or deleted since this application was launched. "
|
||||
"Continouation from this state is impossible. Exiting now."
|
||||
)
|
||||
|
||||
try:
|
||||
obj = zlib.decompress(obj)
|
||||
if typecode in (PYZ_ITEM_MODULE, PYZ_ITEM_PKG) and not raw:
|
||||
obj = marshal.loads(obj)
|
||||
except EOFError as e:
|
||||
raise ImportError(f"Failed to unmarshal PYZ entry {name!r}!") from e
|
||||
|
||||
return obj
|
||||
Reference in New Issue
Block a user