diff --git a/.gitignore b/.gitignore index 08a5b84..bc9bb7d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ -/downloads \ No newline at end of file +/downloads +/build +/dist \ No newline at end of file diff --git a/run.py b/run.py index 7a8b2e4..fd831cb 100644 --- a/run.py +++ b/run.py @@ -10,6 +10,8 @@ debug_html = join(sys.path[0],"debug.html") debug_html_ch = join(sys.path[0],"debug_ch.html") +start_time = time.time() + #https://stackoverflow.com/questions/14587728/what-does-this-error-in-beautiful-soup-means user_agent_list = [ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36", @@ -61,7 +63,7 @@ def onechapter(web, headers, output_dir): time.sleep(1) print("Xong.") -def allchapters(web, headers, domain): +def allchapters(web, headers, domain, parts_only=False, part_start = int(), part_end = int()): res = requests.get(web,headers=headers) html_content = res.text soup = BeautifulSoup(html_content, 'html.parser') @@ -81,8 +83,13 @@ def allchapters(web, headers, domain): title = re.sub(r'\s+', ' ', h1_tag.text).strip() print(title) output_dir = join(sys.path[0],"downloads",title) - for link in chapters: - onechapter(link, headers, output_dir) + if parts_only: + for x in range(part_start, part_end): + link = chapters[x-1] + onechapter(link, headers, output_dir) + else: + for link in chapters: + onechapter(link, headers, output_dir) web = str(input("Nhập đường link của truyện: ")) print("**!** Tool còn nhiều hạn chế, và mình sẽ luôn cố gắng cập nhật để bắt kịp với trang web.") @@ -107,5 +114,28 @@ def allchapters(web, headers, domain): output_dir = '' onechapter(web, headers, output_dir) else: - print("Có vẻ như đây là đường link của cả một truyện. Tiến hành tải tất cả chương mà truyện hiện có...") - allchapters(web, headers, domain) \ No newline at end of file + print("Có vẻ như đây là đường link của cả một truyện.") + print("Bạn muốn tải tất cả các chương truyện hiện có hay chỉ một phần?") + choose = input("(T) Toàn Bộ - (M) Một Phần: ") + if choose == "T": + print("Bạn đã chọn tải toàn bộ các chương truyện.") + print("Tiến hành tải tất cả chương mà truyện hiện có...") + allchapters(web, headers, domain) + elif choose == "M": + print("Bạn đã chọn tải một phần của truyện.") + print("Xin hãy nhập phần các chương bạn muốn tải:") + print("""Ví dụ: + Đầu: 60 + Cuối: 100 + Vậy chương trình sẽ tiến hành tải các chương từ 60 đến 100. + """) + part_start = int(input("Đầu: ")) + part_end = int(input("Cuối: ")) + print("Tiến hành tải tất cả chương trong phần được chỉ định...") + allchapters(web, headers, domain,parts_only=True,part_start=part_start,part_end=part_end) + +end_time = time.time() +elapsed_time = end_time - start_time +print(f"Thời gian chạy: {elapsed_time} giây") +print("Tất cả đã hoàn thành!") +input("Nhấn Enter để tiếp tục...") \ No newline at end of file diff --git a/run.spec b/run.spec new file mode 100644 index 0000000..e8fe9ce --- /dev/null +++ b/run.spec @@ -0,0 +1,38 @@ +# -*- mode: python ; coding: utf-8 -*- + + +a = Analysis( + ['run.py'], + pathex=[], + binaries=[], + datas=[], + hiddenimports=[], + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + noarchive=False, + optimize=0, +) +pyz = PYZ(a.pure) + +exe = EXE( + pyz, + a.scripts, + a.binaries, + a.datas, + [], + name='run', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + upx_exclude=[], + runtime_tmpdir=None, + console=True, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, + codesign_identity=None, + entitlements_file=None, +) diff --git a/venv/Lib/site-packages/PyInstaller/__init__.py b/venv/Lib/site-packages/PyInstaller/__init__.py new file mode 100644 index 0000000..13ce621 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/__init__.py @@ -0,0 +1,44 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +__all__ = ('HOMEPATH', 'PLATFORM', '__version__', 'DEFAULT_DISTPATH', 'DEFAULT_SPECPATH', 'DEFAULT_WORKPATH') + +import os + +from PyInstaller import compat + +# Note: Keep this variable as plain string so it could be updated automatically when doing a release. +__version__ = '6.11.1' + +# Absolute path of this package's directory. Save this early so all submodules can use the absolute path. This is +# required for example if the current directory changes prior to loading the hooks. +PACKAGEPATH = os.path.abspath(os.path.dirname(__file__)) + +HOMEPATH = os.path.dirname(PACKAGEPATH) + +# Default values of paths where to put files created by PyInstaller. If changing these, do not forget to update the +# help text for corresponding command-line options, defined in build_main. + +# Where to put created .spec file. +DEFAULT_SPECPATH = os.getcwd() +# Where to put the final frozen application. +DEFAULT_DISTPATH = os.path.join(os.getcwd(), 'dist') +# Where to put all the temporary files; .log, .pyz, etc. +DEFAULT_WORKPATH = os.path.join(os.getcwd(), 'build') + +PLATFORM = compat.system + '-' + compat.architecture +# Include machine name in path to bootloader for some machines (e.g., 'arm'). Explicitly avoid doing this on macOS, +# where we keep universal2 bootloaders in Darwin-64bit folder regardless of whether we are on x86_64 or arm64. +if compat.machine and not compat.is_darwin: + PLATFORM += '-' + compat.machine +# Similarly, disambiguate musl Linux from glibc Linux. +if compat.is_musl: + PLATFORM += '-musl' diff --git a/venv/Lib/site-packages/PyInstaller/__main__.py b/venv/Lib/site-packages/PyInstaller/__main__.py new file mode 100644 index 0000000..9814748 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/__main__.py @@ -0,0 +1,321 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- +""" +Main command-line interface to PyInstaller. +""" +from __future__ import annotations + +import argparse +import os +import platform +import sys +import pathlib +from collections import defaultdict + +from PyInstaller import __version__ +from PyInstaller import log as logging +# Note: do not import anything else until compat.check_requirements function is run! +from PyInstaller import compat + +try: + from argcomplete import autocomplete +except ImportError: + + def autocomplete(parser): + return None + + +logger = logging.getLogger(__name__) + +# Taken from https://stackoverflow.com/a/22157136 to format args more flexibly: any help text which beings with ``R|`` +# will have all newlines preserved; the help text will be line wrapped. See +# https://docs.python.org/3/library/argparse.html#formatter-class. + + +# This is used by the ``--debug`` option. +class _SmartFormatter(argparse.HelpFormatter): + def _split_lines(self, text, width): + if text.startswith('R|'): + # The underlying implementation of ``RawTextHelpFormatter._split_lines`` invokes this; mimic it. + return text[2:].splitlines() + else: + # Invoke the usual formatter. + return super()._split_lines(text, width) + + +def run_makespec(filenames, **opts): + # Split pathex by using the path separator + temppaths = opts['pathex'][:] + pathex = opts['pathex'] = [] + for p in temppaths: + pathex.extend(p.split(os.pathsep)) + + import PyInstaller.building.makespec + + spec_file = PyInstaller.building.makespec.main(filenames, **opts) + logger.info('wrote %s' % spec_file) + return spec_file + + +def run_build(pyi_config, spec_file, **kwargs): + import PyInstaller.building.build_main + PyInstaller.building.build_main.main(pyi_config, spec_file, **kwargs) + + +def __add_options(parser): + parser.add_argument( + '-v', + '--version', + action='version', + version=__version__, + help='Show program version info and exit.', + ) + + +class _PyiArgumentParser(argparse.ArgumentParser): + def __init__(self, *args, **kwargs): + self._pyi_action_groups = defaultdict(list) + super().__init__(*args, **kwargs) + + def _add_options(self, __add_options: callable, name: str = ""): + """ + Mutate self with the given callable, storing any new actions added in a named group + """ + n_actions_before = len(getattr(self, "_actions", [])) + __add_options(self) # preserves old behavior + new_actions = getattr(self, "_actions", [])[n_actions_before:] + self._pyi_action_groups[name].extend(new_actions) + + def _option_name(self, action): + """ + Get the option name(s) associated with an action + + For options that define both short and long names, this function will + return the long names joined by "/" + """ + longnames = [name for name in action.option_strings if name.startswith("--")] + if longnames: + name = "/".join(longnames) + else: + name = action.option_strings[0] + return name + + def _forbid_options(self, args: argparse.Namespace, group: str, errmsg: str = ""): + """Forbid options from a named action group""" + options = defaultdict(str) + for action in self._pyi_action_groups[group]: + dest = action.dest + name = self._option_name(action) + if getattr(args, dest) is not self.get_default(dest): + if dest in options: + options[dest] += "/" + options[dest] += name + + # if any options from the forbidden group are not the default values, + # the user must have passed them in, so issue an error report + if options: + sep = "\n " + bad = sep.join(options.values()) + if errmsg: + errmsg = "\n" + errmsg + raise SystemExit(f"option(s) not allowed:{sep}{bad}{errmsg}") + + +def generate_parser() -> _PyiArgumentParser: + """ + Build an argparse parser for PyInstaller's main CLI. + """ + + import PyInstaller.building.build_main + import PyInstaller.building.makespec + import PyInstaller.log + + parser = _PyiArgumentParser(formatter_class=_SmartFormatter) + parser.prog = "pyinstaller" + + parser._add_options(__add_options) + parser._add_options(PyInstaller.building.makespec.__add_options, name="makespec") + parser._add_options(PyInstaller.building.build_main.__add_options, name="build_main") + parser._add_options(PyInstaller.log.__add_options, name="log") + + parser.add_argument( + 'filenames', + metavar='scriptname', + nargs='+', + help="Name of scriptfiles to be processed or exactly one .spec file. If a .spec file is specified, most " + "options are unnecessary and are ignored.", + ) + + return parser + + +def run(pyi_args: list | None = None, pyi_config: dict | None = None): + """ + pyi_args allows running PyInstaller programmatically without a subprocess + pyi_config allows checking configuration once when running multiple tests + """ + compat.check_requirements() + check_unsafe_privileges() + + import PyInstaller.log + + old_sys_argv = sys.argv + try: + parser = generate_parser() + autocomplete(parser) + if pyi_args is None: + pyi_args = sys.argv[1:] + try: + index = pyi_args.index("--") + except ValueError: + index = len(pyi_args) + args = parser.parse_args(pyi_args[:index]) + spec_args = pyi_args[index + 1:] + PyInstaller.log.__process_options(parser, args) + + # Print PyInstaller version, Python version, and platform as the first line to stdout. This helps us identify + # PyInstaller, Python, and platform version when users report issues. + try: + from _pyinstaller_hooks_contrib import __version__ as contrib_hooks_version + except Exception: + contrib_hooks_version = 'unknown' + + logger.info('PyInstaller: %s, contrib hooks: %s', __version__, contrib_hooks_version) + logger.info('Python: %s%s', platform.python_version(), " (conda)" if compat.is_conda else "") + logger.info('Platform: %s', platform.platform()) + logger.info('Python environment: %s', sys.prefix) + + # Skip creating .spec when .spec file is supplied. + if args.filenames[0].endswith('.spec'): + parser._forbid_options( + args, group="makespec", errmsg="makespec options not valid when a .spec file is given" + ) + spec_file = args.filenames[0] + else: + # Ensure that the given script files exist, before trying to generate the .spec file. + # This prevents us from overwriting an existing (and customized) .spec file if user makes a typo in the + # .spec file's suffix when trying to build it, for example, `pyinstaller program.cpes` (see #8276). + # It also prevents creation of a .spec file when `pyinstaller program.py` is accidentally ran from a + # directory that does not contain the script (for example, due to failing to change the directory prior + # to running the command). + for filename in args.filenames: + if not os.path.isfile(filename): + raise SystemExit(f"Script file {filename!r} does not exist.") + spec_file = run_makespec(**vars(args)) + + sys.argv = [spec_file, *spec_args] + run_build(pyi_config, spec_file, **vars(args)) + + except KeyboardInterrupt: + raise SystemExit("Aborted by user request.") + except RecursionError: + from PyInstaller import _recursion_too_deep_message + _recursion_too_deep_message.raise_with_msg() + finally: + sys.argv = old_sys_argv + + +def _console_script_run(): + # Python prepends the main script's parent directory to sys.path. When PyInstaller is ran via the usual + # `pyinstaller` CLI entry point, this directory is $pythonprefix/bin which should not be in sys.path. + if os.path.basename(sys.path[0]) in ("bin", "Scripts"): + sys.path.pop(0) + run() + + +def check_unsafe_privileges(): + """ + Forbid dangerous usage of PyInstaller with escalated privileges + """ + if compat.is_win and not compat.is_win_wine: + # Discourage (with the intention to eventually block) people using *run as admin* with PyInstaller. + # There are 4 cases, block case 3 but be careful not to also block case 2. + # 1. User has no admin access: TokenElevationTypeDefault + # 2. User is an admin/UAC disabled (common on CI/VMs): TokenElevationTypeDefault + # 3. User has used *run as administrator* to elevate: TokenElevationTypeFull + # 4. User can escalate but hasn't: TokenElevationTypeLimited + # https://techcommunity.microsoft.com/t5/windows-blog-archive/how-to-determine-if-a-user-is-a-member-of-the-administrators/ba-p/228476 + import ctypes + + advapi32 = ctypes.CDLL("Advapi32.dll") + kernel32 = ctypes.CDLL("kernel32.dll") + + kernel32.GetCurrentProcess.restype = ctypes.c_void_p + process = kernel32.GetCurrentProcess() + + token = ctypes.c_void_p() + try: + TOKEN_QUERY = 8 + assert advapi32.OpenProcessToken(ctypes.c_void_p(process), TOKEN_QUERY, ctypes.byref(token)) + + elevation_type = ctypes.c_int() + TokenElevationType = 18 + assert advapi32.GetTokenInformation( + token, TokenElevationType, ctypes.byref(elevation_type), ctypes.sizeof(elevation_type), + ctypes.byref(ctypes.c_int()) + ) + finally: + kernel32.CloseHandle(token) + + if elevation_type.value == 2: # TokenElevationTypeFull + logger.log( + logging.DEPRECATION, + "Running PyInstaller as admin is not necessary nor sensible. Run PyInstaller from a non-administrator " + "terminal. PyInstaller 7.0 will block this." + ) + + elif compat.is_darwin or compat.is_linux: + # Discourage (with the intention to eventually block) people using *sudo* with PyInstaller. + # Again there are 4 cases, block only case 4. + # 1. Non-root: os.getuid() != 0 + # 2. Logged in as root (usually a VM): os.getlogin() == "root", os.getuid() == 0 + # 3. No named users (e.g. most Docker containers): os.getlogin() fails + # 4. Regular user using escalation: os.getlogin() != "root", os.getuid() == 0 + try: + user = os.getlogin() + except OSError: + user = "" + if os.getuid() == 0 and user and user != "root": + logger.log( + logging.DEPRECATION, + "Running PyInstaller as root is not necessary nor sensible. Do not use PyInstaller with sudo. " + "PyInstaller 7.0 will block this." + ) + + if compat.is_win: + # Do not let people run PyInstaller from admin cmd's default working directory (C:\Windows\system32) + cwd = pathlib.Path.cwd() + + try: + win_dir = compat.win32api.GetWindowsDirectory() + except Exception: + win_dir = None + win_dir = None if win_dir is None else pathlib.Path(win_dir).resolve() + + inside_win_dir = cwd == win_dir or win_dir in cwd.parents + + # The only exception to the above is if user's home directory is also located under %WINDIR%, which happens + # when PyInstaller is ran under SYSTEM user. + if inside_win_dir: + home_dir = pathlib.Path.home().resolve() + if cwd == home_dir or home_dir in cwd.parents: + inside_win_dir = False + + if inside_win_dir: + raise SystemExit( + f"Error: Do not run pyinstaller from {cwd}. cd to where your code is and run pyinstaller from there. " + "Hint: You can open a terminal where your code is by going to the parent folder in Windows file " + "explorer and typing cmd into the address bar." + ) + + +if __name__ == '__main__': + run() diff --git a/venv/Lib/site-packages/PyInstaller/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..d0ee534 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/__pycache__/__main__.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/__pycache__/__main__.cpython-311.pyc new file mode 100644 index 0000000..29c9dc4 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/__pycache__/__main__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/__pycache__/_recursion_too_deep_message.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/__pycache__/_recursion_too_deep_message.cpython-311.pyc new file mode 100644 index 0000000..59b72e9 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/__pycache__/_recursion_too_deep_message.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/__pycache__/_shared_with_waf.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/__pycache__/_shared_with_waf.cpython-311.pyc new file mode 100644 index 0000000..e3ec9af Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/__pycache__/_shared_with_waf.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/__pycache__/compat.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/__pycache__/compat.cpython-311.pyc new file mode 100644 index 0000000..2d08872 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/__pycache__/compat.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/__pycache__/config.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/__pycache__/config.cpython-311.pyc new file mode 100644 index 0000000..09408c2 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/__pycache__/config.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/__pycache__/configure.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/__pycache__/configure.cpython-311.pyc new file mode 100644 index 0000000..b258286 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/__pycache__/configure.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/__pycache__/exceptions.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/__pycache__/exceptions.cpython-311.pyc new file mode 100644 index 0000000..745ae8a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/__pycache__/exceptions.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/__pycache__/log.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/__pycache__/log.cpython-311.pyc new file mode 100644 index 0000000..ff8988f Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/__pycache__/log.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/_recursion_too_deep_message.py b/venv/Lib/site-packages/PyInstaller/_recursion_too_deep_message.py new file mode 100644 index 0000000..e62c20d --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/_recursion_too_deep_message.py @@ -0,0 +1,45 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +msg = """ +============================================================= +A RecursionError (maximum recursion depth exceeded) occurred. +For working around please follow these instructions +============================================================= + +1. In your program's .spec file add this line near the top:: + + import sys ; sys.setrecursionlimit(sys.getrecursionlimit() * 5) + +2. Build your program by running PyInstaller with the .spec file as + argument:: + + pyinstaller myprog.spec + +3. If this fails, you most probably hit an endless recursion in + PyInstaller. Please try to track this down as far as possible, + create a minimal example so we can reproduce and open an issue at + https://github.com/pyinstaller/pyinstaller/issues following the + instructions in the issue template. Many thanks. + +Explanation: Python's stack-limit is a safety-belt against endless recursion, +eating up memory. PyInstaller imports modules recursively. If the structure +how modules are imported within your program is awkward, this leads to the +nesting being too deep and hitting Python's stack-limit. + +With the default recursion limit (1000), the recursion error occurs at about +115 nested imported, with limit 2000 at about 240, with limit 5000 at about +660. +""" + + +def raise_with_msg(): + raise SystemExit(msg) diff --git a/venv/Lib/site-packages/PyInstaller/_shared_with_waf.py b/venv/Lib/site-packages/PyInstaller/_shared_with_waf.py new file mode 100644 index 0000000..c3d52ad --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/_shared_with_waf.py @@ -0,0 +1,86 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- +""" +Code to be shared by PyInstaller and the bootloader/wscript file. + +This code must not assume that either PyInstaller or any of its dependencies installed. I.e., the only imports allowed +in here are standard library ones. Within reason, it is preferable that this file should still run under Python 2.7 as +many compiler docker images still have only Python 2 installed. +""" + +import platform +import re + + +def _pyi_machine(machine, system): + # type: (str, str) -> str + """ + Choose an intentionally simplified architecture identifier to be used in the bootloader's directory name. + + Args: + machine: + The output of ``platform.machine()`` or any known architecture alias or shorthand that may be used by a + C compiler. + system: + The output of ``platform.system()`` on the target machine. + Returns: + Either a string tag or, on platforms that don't need an architecture tag, ``None``. + + Ideally, we would just use ``platform.machine()`` directly, but that makes cross-compiling the bootloader almost + impossible, because you need to know at compile time exactly what ``platform.machine()`` will be at run time, based + only on the machine name alias or shorthand reported by the C compiler at the build time. Rather, use a loose + differentiation, and trust that anyone mixing armv6l with armv6h knows what they are doing. + """ + # See the corresponding tests in tests/unit/test_compat.py for examples. + + if platform.machine() == "sw_64" or platform.machine() == "loongarch64": + # This explicitly inhibits cross compiling the bootloader for or on SunWay and LoongArch machine. + return platform.machine() + + if system == "Windows": + if machine.lower().startswith("arm"): + return "arm" + else: + return "intel" + + if system != "Linux": + # No architecture specifier for anything par Linux. + # - macOS is on two 64 bit architectures, but they are merged into one "universal2" bootloader. + # - BSD supports a wide range of architectures, but according to PyPI's download statistics, every one of our + # BSD users are on x86_64. This may change in the distant future. + return + + if machine.startswith(("arm", "aarch")): + # ARM has a huge number of similar and aliased sub-versions, such as armv5, armv6l armv8h, aarch64. + return "arm" + if machine in ("thumb"): + # Reported by waf/gcc when Thumb instruction set is enabled on 32-bit ARM. The platform.machine() returns "arm" + # regardless of the instruction set. + return "arm" + if machine in ("x86_64", "x64", "x86"): + return "intel" + if re.fullmatch("i[1-6]86", machine): + return "intel" + if machine.startswith(("ppc", "powerpc")): + # PowerPC comes in 64 vs 32 bit and little vs big endian variants. + return "ppc" + if machine in ("mips64", "mips"): + return "mips" + if machine.startswith("riscv"): + return "riscv" + # Machines with no known aliases :) + if machine in ("s390x",): + return machine + + # Unknown architectures are allowed by default, but will all be placed under one directory. In theory, trying to + # have multiple unknown architectures in one copy of PyInstaller will not work, but that should be sufficiently + # unlikely to ever happen. + return "unknown" diff --git a/venv/Lib/site-packages/PyInstaller/archive/__init__.py b/venv/Lib/site-packages/PyInstaller/archive/__init__.py new file mode 100644 index 0000000..a7501ae --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/archive/__init__.py @@ -0,0 +1 @@ +__author__ = 'martin' diff --git a/venv/Lib/site-packages/PyInstaller/archive/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/archive/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..ec8850a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/archive/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/archive/__pycache__/pyz_crypto.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/archive/__pycache__/pyz_crypto.cpython-311.pyc new file mode 100644 index 0000000..08e8031 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/archive/__pycache__/pyz_crypto.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/archive/__pycache__/readers.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/archive/__pycache__/readers.cpython-311.pyc new file mode 100644 index 0000000..5759e14 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/archive/__pycache__/readers.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/archive/__pycache__/writers.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/archive/__pycache__/writers.cpython-311.pyc new file mode 100644 index 0000000..e3e38ac Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/archive/__pycache__/writers.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/archive/pyz_crypto.py b/venv/Lib/site-packages/PyInstaller/archive/pyz_crypto.py new file mode 100644 index 0000000..a16905f --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/archive/pyz_crypto.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +class PyiBlockCipher: + def __init__(self, key=None): + from PyInstaller.exceptions import RemovedCipherFeatureError + raise RemovedCipherFeatureError("Please remove cipher and block_cipher parameters from your spec file.") diff --git a/venv/Lib/site-packages/PyInstaller/archive/readers.py b/venv/Lib/site-packages/PyInstaller/archive/readers.py new file mode 100644 index 0000000..6e4a297 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/archive/readers.py @@ -0,0 +1,227 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- +""" +Python-based CArchive (PKG) reader implementation. Used only in the archive_viewer utility. +""" + +import os +import struct + +from PyInstaller.loader.pyimod01_archive import ZlibArchiveReader, ArchiveReadError + + +class NotAnArchiveError(TypeError): + pass + + +# Type codes for CArchive TOC entries +PKG_ITEM_BINARY = 'b' # binary +PKG_ITEM_DEPENDENCY = 'd' # runtime option +PKG_ITEM_PYZ = 'z' # zlib (pyz) - frozen Python code +PKG_ITEM_ZIPFILE = 'Z' # zlib (pyz) - frozen Python code +PKG_ITEM_PYPACKAGE = 'M' # Python package (__init__.py) +PKG_ITEM_PYMODULE = 'm' # Python module +PKG_ITEM_PYSOURCE = 's' # Python script (v3) +PKG_ITEM_DATA = 'x' # data +PKG_ITEM_RUNTIME_OPTION = 'o' # runtime option +PKG_ITEM_SPLASH = 'l' # splash resources + + +class CArchiveReader: + """ + Reader for PyInstaller's CArchive (PKG) archive. + """ + + # Cookie - holds some information for the bootloader. C struct format definition. '!' at the beginning means network + # byte order. C struct looks like: + # + # typedef struct _archive_cookie + # { + # char magic[8]; + # uint32_t pkg_length; + # uint32_t toc_offset; + # uint32_t toc_length; + # uint32_t python_version; + # char python_libname[64]; + # } ARCHIVE_COOKIE; + # + _COOKIE_MAGIC_PATTERN = b'MEI\014\013\012\013\016' + + _COOKIE_FORMAT = '!8sIIII64s' + _COOKIE_LENGTH = struct.calcsize(_COOKIE_FORMAT) + + # TOC entry: + # + # typedef struct _toc_entry + # { + # uint32_t entry_length; + # uint32_t offset; + # uint32_t length; + # uint32_t uncompressed_length; + # unsigned char compression_flag; + # char typecode; + # char name[1]; /* Variable-length name, padded to multiple of 16 */ + # } TOC_ENTRY; + # + _TOC_ENTRY_FORMAT = '!IIIIBc' + _TOC_ENTRY_LENGTH = struct.calcsize(_TOC_ENTRY_FORMAT) + + def __init__(self, filename): + self._filename = filename + self._start_offset = 0 + self._toc_offset = 0 + self._toc_length = 0 + + self.toc = {} + self.options = [] + + # Load TOC + with open(self._filename, "rb") as fp: + # Find cookie MAGIC pattern + cookie_start_offset = self._find_magic_pattern(fp, self._COOKIE_MAGIC_PATTERN) + if cookie_start_offset == -1: + raise ArchiveReadError("Could not find COOKIE magic pattern!") + + # Read the whole cookie + fp.seek(cookie_start_offset, os.SEEK_SET) + cookie_data = fp.read(self._COOKIE_LENGTH) + + magic, archive_length, toc_offset, toc_length, pyvers, pylib_name = \ + struct.unpack(self._COOKIE_FORMAT, cookie_data) + + # Compute start of the the archive + self._start_offset = (cookie_start_offset + self._COOKIE_LENGTH) - archive_length + + # Verify that Python shared library name is set + if not pylib_name: + raise ArchiveReadError("Python shared library name not set in the archive!") + + # Read whole toc + fp.seek(self._start_offset + toc_offset) + toc_data = fp.read(toc_length) + + self.toc, self.options = self._parse_toc(toc_data) + + @staticmethod + def _find_magic_pattern(fp, magic_pattern): + # Start at the end of file, and scan back-to-start + fp.seek(0, os.SEEK_END) + end_pos = fp.tell() + + # Scan from back + SEARCH_CHUNK_SIZE = 8192 + magic_offset = -1 + while end_pos >= len(magic_pattern): + start_pos = max(end_pos - SEARCH_CHUNK_SIZE, 0) + chunk_size = end_pos - start_pos + # Is the remaining chunk large enough to hold the pattern? + if chunk_size < len(magic_pattern): + break + # Read and scan the chunk + fp.seek(start_pos, os.SEEK_SET) + buf = fp.read(chunk_size) + pos = buf.rfind(magic_pattern) + if pos != -1: + magic_offset = start_pos + pos + break + # Adjust search location for next chunk; ensure proper overlap + end_pos = start_pos + len(magic_pattern) - 1 + + return magic_offset + + @classmethod + def _parse_toc(cls, data): + options = [] + toc = {} + cur_pos = 0 + while cur_pos < len(data): + # Read and parse the fixed-size TOC entry header + entry_length, entry_offset, data_length, uncompressed_length, compression_flag, typecode = \ + struct.unpack(cls._TOC_ENTRY_FORMAT, data[cur_pos:(cur_pos + cls._TOC_ENTRY_LENGTH)]) + cur_pos += cls._TOC_ENTRY_LENGTH + # Read variable-length name + name_length = entry_length - cls._TOC_ENTRY_LENGTH + name, *_ = struct.unpack(f'{name_length}s', data[cur_pos:(cur_pos + name_length)]) + cur_pos += name_length + # Name string may contain up to 15 bytes of padding + name = name.rstrip(b'\0').decode('utf-8') + + typecode = typecode.decode('ascii') + + # The TOC should not contain duplicates, except for OPTION entries. Therefore, keep those + # in a separate list. With options, the rest of the entries do not make sense, anyway. + if typecode == 'o': + options.append(name) + else: + toc[name] = (entry_offset, data_length, uncompressed_length, compression_flag, typecode) + + return toc, options + + def extract(self, name): + """ + Extract data for the given entry name. + """ + + entry = self.toc.get(name) + if entry is None: + raise KeyError(f"No entry named {name} found in the archive!") + + entry_offset, data_length, uncompressed_length, compression_flag, typecode = entry + with open(self._filename, "rb") as fp: + fp.seek(self._start_offset + entry_offset, os.SEEK_SET) + data = fp.read(data_length) + + if compression_flag: + import zlib + data = zlib.decompress(data) + + return data + + def open_embedded_archive(self, name): + """ + Open new archive reader for the embedded archive. + """ + + entry = self.toc.get(name) + if entry is None: + raise KeyError(f"No entry named {name} found in the archive!") + + entry_offset, data_length, uncompressed_length, compression_flag, typecode = entry + + if typecode == PKG_ITEM_PYZ: + # Open as embedded archive, without extraction. + return ZlibArchiveReader(self._filename, self._start_offset + entry_offset) + elif typecode == PKG_ITEM_ZIPFILE: + raise NotAnArchiveError("Zipfile archives not supported yet!") + else: + raise NotAnArchiveError(f"Entry {name} is not a supported embedded archive!") + + +def pkg_archive_contents(filename, recursive=True): + """ + List the contents of the PKG / CArchive. If `recursive` flag is set (the default), the contents of the embedded PYZ + archive is included as well. + + Used by the tests. + """ + + contents = [] + + pkg_archive = CArchiveReader(filename) + for name, toc_entry in pkg_archive.toc.items(): + *_, typecode = toc_entry + contents.append(name) + if typecode == PKG_ITEM_PYZ and recursive: + pyz_archive = pkg_archive.open_embedded_archive(name) + for name in pyz_archive.toc.keys(): + contents.append(name) + + return contents diff --git a/venv/Lib/site-packages/PyInstaller/archive/writers.py b/venv/Lib/site-packages/PyInstaller/archive/writers.py new file mode 100644 index 0000000..ee0a29f --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/archive/writers.py @@ -0,0 +1,423 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- +""" +Utilities to create data structures for embedding Python modules and additional files into the executable. +""" + +import marshal +import os +import shutil +import struct +import sys +import zlib + +from PyInstaller.building.utils import get_code_object, strip_paths_in_code +from PyInstaller.compat import BYTECODE_MAGIC, is_win, strict_collect_mode +from PyInstaller.loader.pyimod01_archive import PYZ_ITEM_MODULE, PYZ_ITEM_NSPKG, PYZ_ITEM_PKG + + +class ZlibArchiveWriter: + """ + Writer 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' + _HEADER_LENGTH = 12 + 5 + _COMPRESSION_LEVEL = 6 # zlib compression level + + def __init__(self, filename, entries, code_dict=None): + """ + filename + Target filename of the archive. + entries + An iterable containing entries in the form of tuples: (name, src_path, typecode), where `name` is the name + under which the resource is stored (e.g., python module name, without suffix), `src_path` is name of the + file from which the resource is read, and `typecode` is the Analysis-level TOC typecode (`PYMODULE`). + code_dict + Optional code dictionary containing code objects for analyzed/collected python modules. + """ + code_dict = code_dict or {} + + with open(filename, "wb") as fp: + # Reserve space for the header. + fp.write(b'\0' * self._HEADER_LENGTH) + + # Write entries' data and collect TOC entries + toc = [] + for entry in entries: + toc_entry = self._write_entry(fp, entry, code_dict) + toc.append(toc_entry) + + # Write TOC + toc_offset = fp.tell() + toc_data = marshal.dumps(toc) + fp.write(toc_data) + + # Write header: + # - PYZ magic pattern (4 bytes) + # - python bytecode magic pattern (4 bytes) + # - TOC offset (32-bit int, 4 bytes) + # - 4 unused bytes + fp.seek(0, os.SEEK_SET) + + fp.write(self._PYZ_MAGIC_PATTERN) + fp.write(BYTECODE_MAGIC) + fp.write(struct.pack('!i', toc_offset)) + + @classmethod + def _write_entry(cls, fp, entry, code_dict): + name, src_path, typecode = entry + assert typecode in {'PYMODULE', 'PYMODULE-1', 'PYMODULE-2'} + + typecode = PYZ_ITEM_MODULE + if src_path in ('-', None): + # This is a NamespacePackage, modulegraph marks them by using the filename '-'. (But wants to use None, + # so check for None, too, to be forward-compatible.) + typecode = PYZ_ITEM_NSPKG + else: + src_basename, _ = os.path.splitext(os.path.basename(src_path)) + if src_basename == '__init__': + typecode = PYZ_ITEM_PKG + data = marshal.dumps(code_dict[name]) + + # First compress, then encrypt. + obj = zlib.compress(data, cls._COMPRESSION_LEVEL) + + # Create TOC entry + toc_entry = (name, (typecode, fp.tell(), len(obj))) + + # Write data blob + fp.write(obj) + + return toc_entry + + +class CArchiveWriter: + """ + Writer for PyInstaller's CArchive (PKG) archive. + + This archive contains all files that are bundled within an executable; a PYZ (ZlibArchive), DLLs, Python C + extensions, and other data files that are bundled in onefile mode. + + The archive can be read from either C (bootloader code at application's run-time) or Python (for debug purposes). + """ + _COOKIE_MAGIC_PATTERN = b'MEI\014\013\012\013\016' + + # For cookie and TOC entry structure, see `PyInstaller.archive.readers.CArchiveReader`. + _COOKIE_FORMAT = '!8sIIII64s' + _COOKIE_LENGTH = struct.calcsize(_COOKIE_FORMAT) + + _TOC_ENTRY_FORMAT = '!IIIIBc' + _TOC_ENTRY_LENGTH = struct.calcsize(_TOC_ENTRY_FORMAT) + + _COMPRESSION_LEVEL = 9 # zlib compression level + + def __init__(self, filename, entries, pylib_name): + """ + filename + Target filename of the archive. + entries + An iterable containing entries in the form of tuples: (dest_name, src_name, compress, typecode), where + `dest_name` is the name under which the resource is stored in the archive (and name under which it is + extracted at runtime), `src_name` is name of the file from which the resouce is read, `compress` is a + boolean compression flag, and `typecode` is the Analysis-level TOC typecode. + pylib_name + Name of the python shared library. + """ + self._collected_names = set() # Track collected names for strict package mode. + + with open(filename, "wb") as fp: + # Write entries' data and collect TOC entries + toc = [] + for entry in entries: + toc_entry = self._write_entry(fp, entry) + toc.append(toc_entry) + + # Write TOC + toc_offset = fp.tell() + toc_data = self._serialize_toc(toc) + toc_length = len(toc_data) + + fp.write(toc_data) + + # Write cookie + archive_length = toc_offset + toc_length + self._COOKIE_LENGTH + pyvers = sys.version_info[0] * 100 + sys.version_info[1] + cookie_data = struct.pack( + self._COOKIE_FORMAT, + self._COOKIE_MAGIC_PATTERN, + archive_length, + toc_offset, + toc_length, + pyvers, + pylib_name.encode('ascii'), + ) + + fp.write(cookie_data) + + def _write_entry(self, fp, entry): + dest_name, src_name, compress, typecode = entry + + # Write OPTION entries as-is, without normalizing them. This also exempts them from duplication check, + # allowing them to be specified multiple times. + if typecode == 'o': + return self._write_blob(fp, b"", dest_name, typecode) + + # Ensure forward slashes in paths are on Windows converted to back slashes '\\', as on Windows the bootloader + # works only with back slashes. + dest_name = os.path.normpath(dest_name) + if is_win and os.path.sep == '/': + # When building under MSYS, the above path normalization uses Unix-style separators, so replace them + # manually. + dest_name = dest_name.replace(os.path.sep, '\\') + + # For symbolic link entries, also ensure that the symlink target path (stored in src_name) is using + # Windows-style back slash separators. + if typecode == 'n': + src_name = src_name.replace(os.path.sep, '\\') + + # Strict pack/collect mode: keep track of the destination names, and raise an error if we try to add a duplicate + # (a file with same destination name, subject to OS case normalization rules). + if strict_collect_mode: + normalized_dest = None + if typecode in {'s', 's1', 's2', 'm', 'M'}: + # Exempt python source scripts and modules from the check. + pass + else: + # Everything else; normalize the case + normalized_dest = os.path.normcase(dest_name) + # Check for existing entry, if applicable + if normalized_dest: + if normalized_dest in self._collected_names: + raise ValueError( + f"Attempting to collect a duplicated file into CArchive: {normalized_dest} (type: {typecode})" + ) + self._collected_names.add(normalized_dest) + + if typecode == 'd': + # Dependency; merge src_name (= reference path prefix) and dest_name (= name) into single-string format that + # is parsed by bootloader. + return self._write_blob(fp, b"", f"{src_name}:{dest_name}", typecode) + elif typecode in {'s', 's1', 's2'}: + # If it is a source code file, compile it to a code object and marshal the object, so it can be unmarshalled + # by the bootloader. For that, we need to know target optimization level, which is stored in typecode. + optim_level = {'s': 0, 's1': 1, 's2': 2}[typecode] + code = get_code_object(dest_name, src_name, optimize=optim_level) + code = strip_paths_in_code(code) + return self._write_blob(fp, marshal.dumps(code), dest_name, 's', compress=compress) + elif typecode in ('m', 'M'): + # Read the PYC file. We do not perform compilation here (in contrast to script files in the above branch), + # so typecode does not contain optimization level information. + with open(src_name, "rb") as in_fp: + data = in_fp.read() + assert data[:4] == BYTECODE_MAGIC + # Skip the PYC header, load the code object. + code = marshal.loads(data[16:]) + code = strip_paths_in_code(code) + # These module entries are loaded and executed within the bootloader, which requires only the code + # object, without the PYC header. + return self._write_blob(fp, marshal.dumps(code), dest_name, typecode, compress=compress) + elif typecode == 'n': + # Symbolic link; store target name (as NULL-terminated string) + data = src_name.encode('utf-8') + b'\x00' + return self._write_blob(fp, data, dest_name, typecode, compress=compress) + else: + return self._write_file(fp, src_name, dest_name, typecode, compress=compress) + + def _write_blob(self, out_fp, blob: bytes, dest_name, typecode, compress=False): + """ + Write the binary contents (**blob**) of a small file to the archive and return the corresponding CArchive TOC + entry. + """ + data_offset = out_fp.tell() + data_length = len(blob) + if compress: + blob = zlib.compress(blob, level=self._COMPRESSION_LEVEL) + out_fp.write(blob) + + return (data_offset, len(blob), data_length, int(compress), typecode, dest_name) + + def _write_file(self, out_fp, src_name, dest_name, typecode, compress=False): + """ + Stream copy a large file into the archive and return the corresponding CArchive TOC entry. + """ + data_offset = out_fp.tell() + data_length = os.stat(src_name).st_size + with open(src_name, 'rb') as in_fp: + if compress: + tmp_buffer = bytearray(16 * 1024) + compressor = zlib.compressobj(self._COMPRESSION_LEVEL) + while True: + num_read = in_fp.readinto(tmp_buffer) + if not num_read: + break + out_fp.write(compressor.compress(tmp_buffer[:num_read])) + out_fp.write(compressor.flush()) + else: + shutil.copyfileobj(in_fp, out_fp) + + return (data_offset, out_fp.tell() - data_offset, data_length, int(compress), typecode, dest_name) + + @classmethod + def _serialize_toc(cls, toc): + serialized_toc = [] + for toc_entry in toc: + data_offset, compressed_length, data_length, compress, typecode, name = toc_entry + + # Encode names as UTF-8. This should be safe as standard python modules only contain ASCII-characters (and + # standard shared libraries should have the same), and thus the C-code still can handle this correctly. + name = name.encode('utf-8') + name_length = len(name) + 1 # Add 1 for string-terminating zero byte. + + # Ensure TOC entries are aligned on 16-byte boundary, so they can be read by bootloader (C code) on + # platforms with strict data alignment requirements (for example linux on `armhf`/`armv7`, such as 32-bit + # Debian Buster on Raspberry Pi). + entry_length = cls._TOC_ENTRY_LENGTH + name_length + if entry_length % 16 != 0: + padding_length = 16 - (entry_length % 16) + name_length += padding_length + + # Serialize + serialized_entry = struct.pack( + cls._TOC_ENTRY_FORMAT + f"{name_length}s", # "Ns" format automatically pads the string with zero bytes. + cls._TOC_ENTRY_LENGTH + name_length, + data_offset, + compressed_length, + data_length, + compress, + typecode.encode('ascii'), + name, + ) + serialized_toc.append(serialized_entry) + + return b''.join(serialized_toc) + + +class SplashWriter: + """ + Writer for the splash screen resources archive. + + The resulting archive is added as an entry into the CArchive with the typecode PKG_ITEM_SPLASH. + """ + # This struct describes the splash resources as it will be in an buffer inside the bootloader. All necessary parts + # are bundled, the *_len and *_offset fields describe the data beyond this header definition. + # Whereas script and image fields are binary data, the requirements fields describe an array of strings. Each string + # is null-terminated in order to easily iterate over this list from within C. + # + # typedef struct _splash_data_header + # { + # char tcl_libname[16]; + # char tk_libname[16]; + # char tk_lib[16]; + # + # uint32_t script_len; + # uint32_t script_offset; + # + # uint32_t image_len; + # uint32_t image_offset; + # + # uint32_t requirements_len; + # uint32_t requirements_offset; + # } SPLASH_DATA_HEADER; + # + _HEADER_FORMAT = '!16s 16s 16s II II II' + _HEADER_LENGTH = struct.calcsize(_HEADER_FORMAT) + + # The created archive is compressed by the CArchive, so no need to compress the data here. + + def __init__(self, filename, name_list, tcl_libname, tk_libname, tklib, image, script): + """ + Writer for splash screen resources that are bundled into the CArchive as a single archive/entry. + + :param filename: The filename of the archive to create + :param name_list: List of filenames for the requirements array + :param str tcl_libname: Name of the tcl shared library file + :param str tk_libname: Name of the tk shared library file + :param str tklib: Root of tk library (e.g. tk/) + :param Union[str, bytes] image: Image like object + :param str script: The tcl/tk script to execute to create the screen. + """ + + # Ensure forward slashes in dependency names are on Windows converted to back slashes '\\', as on Windows the + # bootloader works only with back slashes. + def _normalize_filename(filename): + filename = os.path.normpath(filename) + if is_win and os.path.sep == '/': + # When building under MSYS, the above path normalization uses Unix-style separators, so replace them + # manually. + filename = filename.replace(os.path.sep, '\\') + return filename + + name_list = [_normalize_filename(name) for name in name_list] + + with open(filename, "wb") as fp: + # Reserve space for the header. + fp.write(b'\0' * self._HEADER_LENGTH) + + # Serialize the requirements list. This list (more an array) contains the names of all files the bootloader + # needs to extract before the splash screen can be started. The implementation terminates every name with a + # null-byte, that keeps the list short memory wise and makes it iterable from C. + requirements_len = 0 + requirements_offset = fp.tell() + for name in name_list: + name = name.encode('utf-8') + b'\0' + fp.write(name) + requirements_len += len(name) + + # Write splash script + script_offset = fp.tell() + script_len = len(script) + fp.write(script.encode("utf-8")) + + # Write splash image. If image is a bytes buffer, it is written directly into the archive. Otherwise, it + # is assumed to be a path and the file is copied into the archive. + image_offset = fp.tell() + if isinstance(image, bytes): + # Image was converted by PIL/Pillow and is already in buffer + image_len = len(image) + fp.write(image) + else: + # Read image into buffer + with open(image, 'rb') as image_fp: + image_data = image_fp.read() + image_len = len(image_data) + fp.write(image_data) + del image_data + + # The following strings are written to 16-character fields with zero-padding, which means that we need to + # ensure that their length is strictly below 16 characters (if it were exactly 16, the field would have no + # terminating NULL character!). + def _encode_str(value, field_name, limit): + enc_value = value.encode("utf-8") + if len(enc_value) >= limit: + raise ValueError( + f"Length of the encoded field {field_name!r} is greater or equal to the limit of {limit} " + "characters!" + ) + + return enc_value + + # Write header + header_data = struct.pack( + self._HEADER_FORMAT, + _encode_str(tcl_libname, 'tcl_libname', 16), + _encode_str(tk_libname, 'tk_libname', 16), + _encode_str(tklib, 'tklib', 16), + script_len, + script_offset, + image_len, + image_offset, + requirements_len, + requirements_offset, + ) + + fp.seek(0, os.SEEK_SET) + fp.write(header_data) diff --git a/venv/Lib/site-packages/PyInstaller/bootloader/Windows-64bit-intel/run.exe b/venv/Lib/site-packages/PyInstaller/bootloader/Windows-64bit-intel/run.exe new file mode 100644 index 0000000..e5a3313 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/bootloader/Windows-64bit-intel/run.exe differ diff --git a/venv/Lib/site-packages/PyInstaller/bootloader/Windows-64bit-intel/run_d.exe b/venv/Lib/site-packages/PyInstaller/bootloader/Windows-64bit-intel/run_d.exe new file mode 100644 index 0000000..5be27cf Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/bootloader/Windows-64bit-intel/run_d.exe differ diff --git a/venv/Lib/site-packages/PyInstaller/bootloader/Windows-64bit-intel/runw.exe b/venv/Lib/site-packages/PyInstaller/bootloader/Windows-64bit-intel/runw.exe new file mode 100644 index 0000000..4a7ac96 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/bootloader/Windows-64bit-intel/runw.exe differ diff --git a/venv/Lib/site-packages/PyInstaller/bootloader/Windows-64bit-intel/runw_d.exe b/venv/Lib/site-packages/PyInstaller/bootloader/Windows-64bit-intel/runw_d.exe new file mode 100644 index 0000000..aef4a8d Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/bootloader/Windows-64bit-intel/runw_d.exe differ diff --git a/venv/Lib/site-packages/PyInstaller/bootloader/images/icon-console.ico b/venv/Lib/site-packages/PyInstaller/bootloader/images/icon-console.ico new file mode 100644 index 0000000..4d63d0f Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/bootloader/images/icon-console.ico differ diff --git a/venv/Lib/site-packages/PyInstaller/bootloader/images/icon-windowed.ico b/venv/Lib/site-packages/PyInstaller/bootloader/images/icon-windowed.ico new file mode 100644 index 0000000..cc9903d Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/bootloader/images/icon-windowed.ico differ diff --git a/venv/Lib/site-packages/PyInstaller/building/__init__.py b/venv/Lib/site-packages/PyInstaller/building/__init__.py new file mode 100644 index 0000000..792d600 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/building/__init__.py @@ -0,0 +1 @@ +# diff --git a/venv/Lib/site-packages/PyInstaller/building/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/building/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..fa5f875 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/building/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/building/__pycache__/api.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/building/__pycache__/api.cpython-311.pyc new file mode 100644 index 0000000..221dc89 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/building/__pycache__/api.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/building/__pycache__/build_main.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/building/__pycache__/build_main.cpython-311.pyc new file mode 100644 index 0000000..a0a6d90 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/building/__pycache__/build_main.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/building/__pycache__/datastruct.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/building/__pycache__/datastruct.cpython-311.pyc new file mode 100644 index 0000000..1cc5f1c Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/building/__pycache__/datastruct.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/building/__pycache__/icon.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/building/__pycache__/icon.cpython-311.pyc new file mode 100644 index 0000000..4a93709 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/building/__pycache__/icon.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/building/__pycache__/makespec.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/building/__pycache__/makespec.cpython-311.pyc new file mode 100644 index 0000000..5cfdf55 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/building/__pycache__/makespec.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/building/__pycache__/osx.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/building/__pycache__/osx.cpython-311.pyc new file mode 100644 index 0000000..c47b53d Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/building/__pycache__/osx.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/building/__pycache__/splash.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/building/__pycache__/splash.cpython-311.pyc new file mode 100644 index 0000000..10eb93e Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/building/__pycache__/splash.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/building/__pycache__/splash_templates.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/building/__pycache__/splash_templates.cpython-311.pyc new file mode 100644 index 0000000..83c6336 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/building/__pycache__/splash_templates.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/building/__pycache__/templates.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/building/__pycache__/templates.cpython-311.pyc new file mode 100644 index 0000000..54dfc99 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/building/__pycache__/templates.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/building/__pycache__/utils.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/building/__pycache__/utils.cpython-311.pyc new file mode 100644 index 0000000..153e2a6 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/building/__pycache__/utils.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/building/api.py b/venv/Lib/site-packages/PyInstaller/building/api.py new file mode 100644 index 0000000..8276925 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/building/api.py @@ -0,0 +1,1309 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- +""" +This module contains classes that are available for the .spec files. + +Spec file is generated by PyInstaller. The generated code from .spec file +is a way how PyInstaller does the dependency analysis and creates executable. +""" + +import os +import subprocess +import time +import pathlib +import shutil +from operator import itemgetter + +from PyInstaller import HOMEPATH, PLATFORM +from PyInstaller import log as logging +from PyInstaller.archive.writers import CArchiveWriter, ZlibArchiveWriter +from PyInstaller.building.datastruct import Target, _check_guts_eq, normalize_pyz_toc, normalize_toc +from PyInstaller.building.utils import ( + _check_guts_toc, _make_clean_directory, _rmtree, process_collected_binary, get_code_object, strip_paths_in_code, + compile_pymodule +) +from PyInstaller.building.splash import Splash # argument type validation in EXE +from PyInstaller.compat import is_cygwin, is_darwin, is_linux, is_win, strict_collect_mode, is_nogil +from PyInstaller.depend import bindepend +from PyInstaller.depend.analysis import get_bootstrap_modules +import PyInstaller.utils.misc as miscutils + +logger = logging.getLogger(__name__) + +if is_win: + from PyInstaller.utils.win32 import (icon, versioninfo, winmanifest, winresource, winutils) + +if is_darwin: + import PyInstaller.utils.osx as osxutils + + +class PYZ(Target): + """ + Creates a zlib-based PYZ archive that contains byte-compiled pure Python modules. + """ + def __init__(self, *tocs, **kwargs): + """ + tocs + One or more TOC (Table of Contents) lists, usually an `Analysis.pure`. + + kwargs + Possible keyword arguments: + + name + A filename for the .pyz. Normally not needed, as the generated name will do fine. + """ + if kwargs.get("cipher"): + from PyInstaller.exceptions import RemovedCipherFeatureError + raise RemovedCipherFeatureError( + "Please remove the 'cipher' arguments to PYZ() and Analysis() in your spec file." + ) + + from PyInstaller.config import CONF + + super().__init__() + + name = kwargs.get('name', None) + + self.name = name + if name is None: + self.name = os.path.splitext(self.tocfilename)[0] + '.pyz' + + # PyInstaller bootstrapping modules. + bootstrap_dependencies = get_bootstrap_modules() + + # Compile the python modules that are part of bootstrap dependencies, so that they can be collected into the + # CArchive/PKG and imported by the bootstrap script. + self.dependencies = [] + workpath = os.path.join(CONF['workpath'], 'localpycs') + for name, src_path, typecode in bootstrap_dependencies: + if typecode == 'PYMODULE': + # Compile pymodule and include the compiled .pyc file. + pyc_path = compile_pymodule( + name, + src_path, + workpath, + # Never optimize bootstrap dependencies! + optimize=0, + code_cache=None, + ) + self.dependencies.append((name, pyc_path, typecode)) + else: + # Include as is (extensions). + self.dependencies.append((name, src_path, typecode)) + + # Merge input TOC(s) and their code object dictionaries (if available). Skip the bootstrap modules, which will + # be passed on to CArchive/PKG. + bootstrap_module_names = set(name for name, _, typecode in self.dependencies if typecode == 'PYMODULE') + self.toc = [] + self.code_dict = {} + for toc in tocs: + # Check if code cache association exists for the given TOC list + code_cache = CONF['code_cache'].get(id(toc)) + if code_cache is not None: + self.code_dict.update(code_cache) + + for entry in toc: + name, _, typecode = entry + # PYZ expects only PYMODULE entries (python code objects). + assert typecode in {'PYMODULE', 'PYMODULE-1', 'PYMODULE-2'}, f"Invalid entry passed to PYZ: {entry}!" + # Module required during bootstrap; skip to avoid collecting a duplicate. + if name in bootstrap_module_names: + continue + self.toc.append(entry) + + # Normalize TOC + self.toc = normalize_pyz_toc(self.toc) + + # Alphabetically sort the TOC to enable reproducible builds. + self.toc.sort() + + self.__postinit__() + + _GUTS = ( + # input parameters + ('name', _check_guts_eq), + ('toc', _check_guts_toc), + # no calculated/analysed values + ) + + def assemble(self): + logger.info("Building PYZ (ZlibArchive) %s", self.name) + + # Ensure code objects are available for all modules we are about to collect. + # NOTE: `self.toc` is already sorted by names. + archive_toc = [] + for entry in self.toc: + name, src_path, typecode = entry + if name not in self.code_dict: + # The code object is not available from the ModuleGraph's cache; re-create it. + optim_level = {'PYMODULE': 0, 'PYMODULE-1': 1, 'PYMODULE-2': 2}[typecode] + try: + self.code_dict[name] = get_code_object(name, src_path, optimize=optim_level) + except SyntaxError: + # The module was likely written for different Python version; exclude it + continue + archive_toc.append(entry) + + # Remove leading parts of paths in code objects. + self.code_dict = {name: strip_paths_in_code(code) for name, code in self.code_dict.items()} + + # Create the archive + ZlibArchiveWriter(self.name, archive_toc, code_dict=self.code_dict) + logger.info("Building PYZ (ZlibArchive) %s completed successfully.", self.name) + + +class PKG(Target): + """ + Creates a CArchive. CArchive is the data structure that is embedded into the executable. This data structure allows + to include various read-only data in a single-file deployment. + """ + xformdict = { + # PYMODULE entries are already byte-compiled, so we do not need to encode optimization level in the low-level + # typecodes. PYSOURCE entries are byte-compiled by the underlying writer, so we need to pass the optimization + # level via low-level typecodes. + 'PYMODULE': 'm', + 'PYMODULE-1': 'm', + 'PYMODULE-2': 'm', + 'PYSOURCE': 's', + 'PYSOURCE-1': 's1', + 'PYSOURCE-2': 's2', + 'EXTENSION': 'b', + 'PYZ': 'z', + 'PKG': 'a', + 'DATA': 'x', + 'BINARY': 'b', + 'ZIPFILE': 'Z', + 'EXECUTABLE': 'b', + 'DEPENDENCY': 'd', + 'SPLASH': 'l', + 'SYMLINK': 'n', + } + + def __init__( + self, + toc, + python_lib_name, + name=None, + cdict=None, + exclude_binaries=False, + strip_binaries=False, + upx_binaries=False, + upx_exclude=None, + target_arch=None, + codesign_identity=None, + entitlements_file=None + ): + """ + toc + A TOC (Table of Contents) list. + python_lib_name + Name of the python shared library to store in PKG. Required by bootloader. + name + An optional filename for the PKG. + cdict + Dictionary that specifies compression by typecode. For Example, PYZ is left uncompressed so that it + can be accessed inside the PKG. The default uses sensible values. If zlib is not available, no + compression is used. + exclude_binaries + If True, EXTENSIONs and BINARYs will be left out of the PKG, and forwarded to its container (usually + a COLLECT). + strip_binaries + If True, use 'strip' command to reduce the size of binary files. + upx_binaries + """ + super().__init__() + + self.toc = normalize_toc(toc) # Ensure guts contain normalized TOC + self.python_lib_name = python_lib_name + self.cdict = cdict + self.name = name + if name is None: + self.name = os.path.splitext(self.tocfilename)[0] + '.pkg' + self.exclude_binaries = exclude_binaries + self.strip_binaries = strip_binaries + self.upx_binaries = upx_binaries + self.upx_exclude = upx_exclude or [] + self.target_arch = target_arch + self.codesign_identity = codesign_identity + self.entitlements_file = entitlements_file + + # This dict tells PyInstaller what items embedded in the executable should be compressed. + if self.cdict is None: + self.cdict = { + 'EXTENSION': COMPRESSED, + 'DATA': COMPRESSED, + 'BINARY': COMPRESSED, + 'EXECUTABLE': COMPRESSED, + 'PYSOURCE': COMPRESSED, + 'PYMODULE': COMPRESSED, + 'SPLASH': COMPRESSED, + # Do not compress PYZ as a whole, as it contains individually-compressed modules. + 'PYZ': UNCOMPRESSED, + # Do not compress target names in symbolic links. + 'SYMLINK': UNCOMPRESSED, + } + + self.__postinit__() + + _GUTS = ( # input parameters + ('name', _check_guts_eq), + ('cdict', _check_guts_eq), + ('toc', _check_guts_toc), # list unchanged and no newer files + ('python_lib_name', _check_guts_eq), + ('exclude_binaries', _check_guts_eq), + ('strip_binaries', _check_guts_eq), + ('upx_binaries', _check_guts_eq), + ('upx_exclude', _check_guts_eq), + ('target_arch', _check_guts_eq), + ('codesign_identity', _check_guts_eq), + ('entitlements_file', _check_guts_eq), + # no calculated/analysed values + ) + + def assemble(self): + logger.info("Building PKG (CArchive) %s", os.path.basename(self.name)) + + pkg_file = pathlib.Path(self.name).resolve() # Used to detect attempts at PKG feeding itself + + bootstrap_toc = [] # TOC containing bootstrap scripts and modules, which must not be sorted. + archive_toc = [] # TOC containing all other elements. Sorted to enable reproducible builds. + + for dest_name, src_name, typecode in self.toc: + # Ensure that the source file exists, if necessary. Skip the check for OPTION entries, where 'src_name' is + # None. Also skip DEPENDENCY entries due to special contents of 'dest_name' and/or 'src_name'. Same for the + # SYMLINK entries, where 'src_name' is relative target name for symbolic link. + if typecode not in {'OPTION', 'DEPENDENCY', 'SYMLINK'}: + if not os.path.exists(src_name): + if strict_collect_mode: + raise ValueError(f"Non-existent resource {src_name}, meant to be collected as {dest_name}!") + else: + logger.warning( + "Ignoring non-existent resource %s, meant to be collected as %s", src_name, dest_name + ) + continue + + # Detect attempt at collecting PKG into itself, as it results in and endless feeding loop and exhaustion + # of all available storage space. + if pathlib.Path(src_name).resolve() == pkg_file: + raise ValueError(f"Trying to collect PKG file {src_name} into itself!") + + if typecode in ('BINARY', 'EXTENSION'): + if self.exclude_binaries: + # This is onedir-specific codepath - the EXE and consequently PKG should not be passed the Analysis' + # `datas` and `binaries` TOCs (unless the user messes up the .spec file). However, EXTENSION entries + # might still slip in via `PYZ.dependencies`, which are merged by EXE into its TOC and passed on to + # PKG here. Such entries need to be passed to the parent container (the COLLECT) via + # `PKG.dependencies`. + # + # This codepath formerly performed such pass-through only for EXTENSION entries, but in order to + # keep code simple, we now also do it for BINARY entries. In a sane world, we do not expect to + # encounter them here; but if they do happen to pass through here and we pass them on, the + # container's TOC de-duplication should take care of them (same as with EXTENSION ones, really). + self.dependencies.append((dest_name, src_name, typecode)) + else: + # This is onefile-specific codepath. The binaries (both EXTENSION and BINARY entries) need to be + # processed using `process_collected_binary` helper. + src_name = process_collected_binary( + src_name, + dest_name, + use_strip=self.strip_binaries, + use_upx=self.upx_binaries, + upx_exclude=self.upx_exclude, + target_arch=self.target_arch, + codesign_identity=self.codesign_identity, + entitlements_file=self.entitlements_file, + strict_arch_validation=(typecode == 'EXTENSION'), + ) + archive_toc.append((dest_name, src_name, self.cdict.get(typecode, False), self.xformdict[typecode])) + elif typecode in ('DATA', 'ZIPFILE'): + # Same logic as above for BINARY and EXTENSION; if `exclude_binaries` is set, we are in onedir mode; + # we should exclude DATA (and ZIPFILE) entries and instead pass them on via PKG's `dependencies`. This + # prevents a onedir application from becoming a broken onefile one if user accidentally passes datas + # and binaries TOCs to EXE instead of COLLECT. + if self.exclude_binaries: + self.dependencies.append((dest_name, src_name, typecode)) + else: + if typecode == 'DATA' and os.access(src_name, os.X_OK): + # DATA with executable bit set (e.g., shell script); turn into binary so that executable bit is + # restored on the extracted file. + carchive_typecode = 'b' + else: + carchive_typecode = self.xformdict[typecode] + archive_toc.append((dest_name, src_name, self.cdict.get(typecode, False), carchive_typecode)) + elif typecode == 'OPTION': + archive_toc.append((dest_name, '', False, 'o')) + elif typecode in {'PYSOURCE', 'PYSOURCE-1', 'PYSOURCE-2', 'PYMODULE', 'PYMODULE-1', 'PYMODULE-2'}: + # Collect python script and modules in a TOC that will not be sorted. + bootstrap_toc.append((dest_name, src_name, self.cdict.get(typecode, False), self.xformdict[typecode])) + else: + # PYZ, PKG, DEPENDENCY, SPLASH, SYMLINK + archive_toc.append((dest_name, src_name, self.cdict.get(typecode, False), self.xformdict[typecode])) + + # Sort content alphabetically by type and name to enable reproducible builds. + archive_toc.sort(key=itemgetter(3, 0)) + # Do *not* sort modules and scripts, as their order is important. + # TODO: Think about having all modules first and then all scripts. + CArchiveWriter(self.name, bootstrap_toc + archive_toc, pylib_name=self.python_lib_name) + + logger.info("Building PKG (CArchive) %s completed successfully.", os.path.basename(self.name)) + + +class EXE(Target): + """ + Creates the final executable of the frozen app. This bundles all necessary files together. + """ + def __init__(self, *args, **kwargs): + """ + args + One or more arguments that are either an instance of `Target` or an iterable representing TOC list. + kwargs + Possible keyword arguments: + + bootloader_ignore_signals + Non-Windows only. If True, the bootloader process will ignore all ignorable signals. If False (default), + it will forward all signals to the child process. Useful in situations where for example a supervisor + process signals both the bootloader and the child (e.g., via a process group) to avoid signalling the + child twice. + console + On Windows or Mac OS governs whether to use the console executable or the windowed executable. Always + True on Linux/Unix (always console executable - it does not matter there). + hide_console + Windows only. In console-enabled executable, hide or minimize the console window if the program owns the + console window (i.e., was not launched from existing console window). Depending on the setting, the + console is hidden/mininized either early in the bootloader execution ('hide-early', 'minimize-early') or + late in the bootloader execution ('hide-late', 'minimize-late'). The early option takes place as soon as + the PKG archive is found. In onefile builds, the late option takes place after application has unpacked + itself and before it launches the child process. In onedir builds, the late option takes place before + starting the embedded python interpreter. + disable_windowed_traceback + Disable traceback dump of unhandled exception in windowed (noconsole) mode (Windows and macOS only), + and instead display a message that this feature is disabled. + debug + Setting to True gives you progress messages from the executable (for console=False there will be + annoying MessageBoxes on Windows). + name + The filename for the executable. On Windows suffix '.exe' is appended. + exclude_binaries + Forwarded to the PKG the EXE builds. + icon + Windows and Mac OS only. icon='myicon.ico' to use an icon file or icon='notepad.exe,0' to grab an icon + resource. Defaults to use PyInstaller's console or windowed icon. Use icon=`NONE` to not add any icon. + version + Windows only. version='myversion.txt'. Use grab_version.py to get a version resource from an executable + and then edit the output to create your own. (The syntax of version resources is so arcane that I would + not attempt to write one from scratch). + uac_admin + Windows only. Setting to True creates a Manifest with will request elevation upon application start. + uac_uiaccess + Windows only. Setting to True allows an elevated application to work with Remote Desktop. + argv_emulation + macOS only. Enables argv emulation in macOS .app bundles (i.e., windowed bootloader). If enabled, the + initial open document/URL Apple Events are intercepted by bootloader and converted into sys.argv. + target_arch + macOS only. Used to explicitly specify the target architecture; either single-arch ('x86_64' or 'arm64') + or 'universal2'. Used in checks that the collected binaries contain the requires arch slice(s) and/or + to convert fat binaries into thin ones as necessary. If not specified (default), a single-arch build + corresponding to running architecture is assumed. + codesign_identity + macOS only. Use the provided identity to sign collected binaries and the generated executable. If + signing identity is not provided, ad-hoc signing is performed. + entitlements_file + macOS only. Optional path to entitlements file to use with code signing of collected binaries + (--entitlements option to codesign utility). + contents_directory + Onedir mode only. Specifies the name of the directory where all files par the executable will be placed. + Setting the name to '.' (or '' or None) re-enables old onedir layout without contents directory. + """ + from PyInstaller.config import CONF + + super().__init__() + + # Available options for EXE in .spec files. + self.exclude_binaries = kwargs.get('exclude_binaries', False) + self.bootloader_ignore_signals = kwargs.get('bootloader_ignore_signals', False) + self.console = kwargs.get('console', True) + self.hide_console = kwargs.get('hide_console', None) + self.disable_windowed_traceback = kwargs.get('disable_windowed_traceback', False) + self.debug = kwargs.get('debug', False) + self.name = kwargs.get('name', None) + self.icon = kwargs.get('icon', None) + self.versrsrc = kwargs.get('version', None) + self.manifest = kwargs.get('manifest', None) + self.resources = kwargs.get('resources', []) + self.strip = kwargs.get('strip', False) + self.upx_exclude = kwargs.get("upx_exclude", []) + self.runtime_tmpdir = kwargs.get('runtime_tmpdir', None) + self.contents_directory = kwargs.get("contents_directory", "_internal") + # If ``append_pkg`` is false, the archive will not be appended to the exe, but copied beside it. + self.append_pkg = kwargs.get('append_pkg', True) + + # On Windows allows the exe to request admin privileges. + self.uac_admin = kwargs.get('uac_admin', False) + self.uac_uiaccess = kwargs.get('uac_uiaccess', False) + + # macOS argv emulation + self.argv_emulation = kwargs.get('argv_emulation', False) + + # Target architecture (macOS only) + self.target_arch = kwargs.get('target_arch', None) + if is_darwin: + if self.target_arch is None: + import platform + self.target_arch = platform.machine() + else: + assert self.target_arch in {'x86_64', 'arm64', 'universal2'}, \ + f"Unsupported target arch: {self.target_arch}" + logger.info("EXE target arch: %s", self.target_arch) + else: + self.target_arch = None # explicitly disable + + # Code signing identity (macOS only) + self.codesign_identity = kwargs.get('codesign_identity', None) + if is_darwin: + logger.info("Code signing identity: %s", self.codesign_identity) + else: + self.codesign_identity = None # explicitly disable + # Code signing entitlements + self.entitlements_file = kwargs.get('entitlements_file', None) + + # UPX needs to be both available and enabled for the target. + self.upx = CONF['upx_available'] and kwargs.get('upx', False) + + # Catch and clear options that are unsupported on specific platforms. + if self.versrsrc and not is_win: + logger.warning('Ignoring version information; supported only on Windows!') + self.versrsrc = None + if self.manifest and not is_win: + logger.warning('Ignoring manifest; supported only on Windows!') + self.manifest = None + if self.resources and not is_win: + logger.warning('Ignoring resources; supported only on Windows!') + self.resources = [] + if self.icon and not (is_win or is_darwin): + logger.warning('Ignoring icon; supported only on Windows and macOS!') + self.icon = None + if self.hide_console and not is_win: + logger.warning('Ignoring hide_console; supported only on Windows!') + self.hide_console = None + + if self.contents_directory in ("", "."): + self.contents_directory = None # Re-enable old onedir layout without contents directory. + elif self.contents_directory == ".." or "/" in self.contents_directory or "\\" in self.contents_directory: + raise SystemExit( + f'Invalid value "{self.contents_directory}" passed to `--contents-directory` or `contents_directory`. ' + 'Exactly one directory level is required (or just "." to disable the contents directory).' + ) + + if not kwargs.get('embed_manifest', True): + from PyInstaller.exceptions import RemovedExternalManifestError + raise RemovedExternalManifestError( + "Please remove the 'embed_manifest' argument to EXE() in your spec file." + ) + + # Old .spec format included in 'name' the path where to put created app. New format includes only exename. + # + # Ignore fullpath in the 'name' and prepend DISTPATH or WORKPATH. + # DISTPATH - onefile + # WORKPATH - onedir + if self.exclude_binaries: + # onedir mode - create executable in WORKPATH. + self.name = os.path.join(CONF['workpath'], os.path.basename(self.name)) + else: + # onefile mode - create executable in DISTPATH. + self.name = os.path.join(CONF['distpath'], os.path.basename(self.name)) + + # Old .spec format included on Windows in 'name' .exe suffix. + if is_win or is_cygwin: + # Append .exe suffix if it is not already there. + if not self.name.endswith('.exe'): + self.name += '.exe' + base_name = os.path.splitext(os.path.basename(self.name))[0] + else: + base_name = os.path.basename(self.name) + # Create the CArchive PKG in WORKPATH. When instancing PKG(), set name so that guts check can test whether the + # file already exists. + self.pkgname = os.path.join(CONF['workpath'], base_name + '.pkg') + + self.toc = [] + + for arg in args: + # Valid arguments: PYZ object, Splash object, and TOC-list iterables + if isinstance(arg, (PYZ, Splash)): + # Add object as an entry to the TOC, and merge its dependencies TOC + if isinstance(arg, PYZ): + self.toc.append((os.path.basename(arg.name), arg.name, "PYZ")) + else: + self.toc.append((os.path.basename(arg.name), arg.name, "SPLASH")) + self.toc.extend(arg.dependencies) + elif miscutils.is_iterable(arg): + # TOC-like iterable + self.toc.extend(arg) + else: + raise TypeError(f"Invalid argument type for EXE: {type(arg)!r}") + + if is_nogil: + # Signal to bootloader that python was built with Py_GIL_DISABLED, in order to select correct `PyConfig` + # structure layout at run-time. + self.toc.append(("pyi-python-flag Py_GIL_DISABLED", "", "OPTION")) + + if self.runtime_tmpdir is not None: + self.toc.append(("pyi-runtime-tmpdir " + self.runtime_tmpdir, "", "OPTION")) + + if self.bootloader_ignore_signals: + # no value; presence means "true" + self.toc.append(("pyi-bootloader-ignore-signals", "", "OPTION")) + + if self.disable_windowed_traceback: + # no value; presence means "true" + self.toc.append(("pyi-disable-windowed-traceback", "", "OPTION")) + + if self.argv_emulation: + # no value; presence means "true" + self.toc.append(("pyi-macos-argv-emulation", "", "OPTION")) + + if self.contents_directory: + self.toc.append(("pyi-contents-directory " + self.contents_directory, "", "OPTION")) + + if self.hide_console: + # Validate the value + _HIDE_CONSOLE_VALUES = {'hide-early', 'minimize-early', 'hide-late', 'minimize-late'} + self.hide_console = self.hide_console.lower() + if self.hide_console not in _HIDE_CONSOLE_VALUES: + raise ValueError( + f"Invalid hide_console value: {self.hide_console}! Allowed values: {_HIDE_CONSOLE_VALUES}" + ) + self.toc.append((f"pyi-hide-console {self.hide_console}", "", "OPTION")) + + # If the icon path is relative, make it relative to the .spec file. + if self.icon and self.icon != "NONE": + if isinstance(self.icon, list): + self.icon = [self._makeabs(ic) for ic in self.icon] + else: + self.icon = [self._makeabs(self.icon)] + + if is_win: + if not self.icon: + # --icon not specified; use default from bootloader folder + if self.console: + ico = 'icon-console.ico' + else: + ico = 'icon-windowed.ico' + self.icon = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'bootloader', 'images', ico) + + # Prepare manifest for the executable by creating minimal manifest or modifying the supplied one. + if self.manifest: + # Determine if we were given a filename or an XML string. + if "<" in self.manifest: + self.manifest = self.manifest.encode("utf-8") + else: + self.manifest = self._makeabs(self.manifest) + with open(self.manifest, "rb") as fp: + self.manifest = fp.read() + self.manifest = winmanifest.create_application_manifest(self.manifest, self.uac_admin, self.uac_uiaccess) + + if self.versrsrc: + if isinstance(self.versrsrc, versioninfo.VSVersionInfo): + # We were passed a valid versioninfo.VSVersionInfo structure + pass + elif isinstance(self.versrsrc, (str, bytes, os.PathLike)): + # File path; either absolute, or relative to the spec file + self.versrsrc = self._makeabs(self.versrsrc) + logger.debug("Loading version info from file: %r", self.versrsrc) + self.versrsrc = versioninfo.load_version_info_from_text_file(self.versrsrc) + else: + raise TypeError(f"Unsupported type for version info argument: {type(self.versrsrc)!r}") + + # Identify python shared library. This is needed both for PKG (where we need to store the name so that + # bootloader can look it up), and for macOS-specific processing of the generated executable (adjusting the SDK + # version). + # + # NOTE: we already performed an equivalent search (using the same `get_python_library_path` helper) during the + # analysis stage to ensure that the python shared library is collected. Unfortunately, with the way data passing + # works in onedir builds, we cannot look up the value in the TOC at this stage, and we need to search again. + self.python_lib = bindepend.get_python_library_path() + if self.python_lib is None: + from PyInstaller.exceptions import PythonLibraryNotFoundError + raise PythonLibraryNotFoundError() + + # Normalize TOC + self.toc = normalize_toc(self.toc) + + self.pkg = PKG( + toc=self.toc, + python_lib_name=os.path.basename(self.python_lib), + name=self.pkgname, + cdict=kwargs.get('cdict', None), + exclude_binaries=self.exclude_binaries, + strip_binaries=self.strip, + upx_binaries=self.upx, + upx_exclude=self.upx_exclude, + target_arch=self.target_arch, + codesign_identity=self.codesign_identity, + entitlements_file=self.entitlements_file + ) + self.dependencies = self.pkg.dependencies + + # Get the path of the bootloader and store it in a TOC, so it can be checked for being changed. + exe = self._bootloader_file('run', '.exe' if is_win or is_cygwin else '') + self.exefiles = [(os.path.basename(exe), exe, 'EXECUTABLE')] + + self.__postinit__() + + _GUTS = ( + # input parameters + ('name', _check_guts_eq), + ('console', _check_guts_eq), + ('debug', _check_guts_eq), + ('exclude_binaries', _check_guts_eq), + ('icon', _check_guts_eq), + ('versrsrc', _check_guts_eq), + ('uac_admin', _check_guts_eq), + ('uac_uiaccess', _check_guts_eq), + ('manifest', _check_guts_eq), + ('append_pkg', _check_guts_eq), + ('argv_emulation', _check_guts_eq), + ('target_arch', _check_guts_eq), + ('codesign_identity', _check_guts_eq), + ('entitlements_file', _check_guts_eq), + # for the case the directory is shared between platforms: + ('pkgname', _check_guts_eq), + ('toc', _check_guts_eq), + ('resources', _check_guts_eq), + ('strip', _check_guts_eq), + ('upx', _check_guts_eq), + ('mtm', None), # checked below + # derived values + ('exefiles', _check_guts_toc), + ('python_lib', _check_guts_eq), + ) + + def _check_guts(self, data, last_build): + if not os.path.exists(self.name): + logger.info("Rebuilding %s because %s missing", self.tocbasename, os.path.basename(self.name)) + return True + if not self.append_pkg and not os.path.exists(self.pkgname): + logger.info("Rebuilding because %s missing", os.path.basename(self.pkgname)) + return True + + if Target._check_guts(self, data, last_build): + return True + + mtm = data['mtm'] + if mtm != miscutils.mtime(self.name): + logger.info("Rebuilding %s because mtimes don't match", self.tocbasename) + return True + if mtm < miscutils.mtime(self.pkg.tocfilename): + logger.info("Rebuilding %s because pkg is more recent", self.tocbasename) + return True + + return False + + @staticmethod + def _makeabs(path): + """ + Helper for anchoring relative paths to spec file location. + """ + from PyInstaller.config import CONF + if os.path.isabs(path): + return path + else: + return os.path.join(CONF['specpath'], path) + + def _bootloader_file(self, exe, extension=None): + """ + Pick up the right bootloader file - debug, console, windowed. + """ + # Having console/windowed bootloader makes sense only on Windows and Mac OS. + if is_win or is_darwin: + if not self.console: + exe = exe + 'w' + # There are two types of bootloaders: + # run - release, no verbose messages in console. + # run_d - contains verbose messages in console. + if self.debug: + exe = exe + '_d' + if extension: + exe = exe + extension + bootloader_file = os.path.join(HOMEPATH, 'PyInstaller', 'bootloader', PLATFORM, exe) + logger.info('Bootloader %s' % bootloader_file) + return bootloader_file + + def assemble(self): + # On Windows, we used to append .notanexecutable to the intermediate/temporary file name to (attempt to) + # prevent interference from anti-virus programs with the build process (see #6467). This is now disabled + # as we wrap all processing steps that modify the executable in the `_retry_operation` helper; however, + # we keep around the `build_name` variable instead of directly using `self.name`, just in case we need + # to re-enable it... + build_name = self.name + + logger.info("Building EXE from %s", self.tocbasename) + if os.path.exists(self.name): + if os.path.isdir(self.name): + _rmtree(self.name) # will prompt for confirmation if --noconfirm is not given + else: + os.remove(self.name) + if not os.path.exists(os.path.dirname(self.name)): + os.makedirs(os.path.dirname(self.name)) + bootloader_exe = self.exefiles[0][1] # pathname of bootloader + if not os.path.exists(bootloader_exe): + raise SystemExit(_MISSING_BOOTLOADER_ERRORMSG) + + # Step 1: copy the bootloader file, and perform any operations that need to be done prior to appending the PKG. + logger.info("Copying bootloader EXE to %s", build_name) + self._retry_operation(shutil.copyfile, bootloader_exe, build_name) + self._retry_operation(os.chmod, build_name, 0o755) + + if is_win: + # First, remove all resources from the file. This ensures that no manifest is embedded, even if bootloader + # was compiled with a toolchain that forcibly embeds a default manifest (e.g., mingw toolchain from msys2). + self._retry_operation(winresource.remove_all_resources, build_name) + # Embed icon. + if self.icon != "NONE": + logger.info("Copying icon to EXE") + self._retry_operation(icon.CopyIcons, build_name, self.icon) + # Embed version info. + if self.versrsrc: + logger.info("Copying version information to EXE") + self._retry_operation(versioninfo.write_version_info_to_executable, build_name, self.versrsrc) + # Embed/copy other resources. + logger.info("Copying %d resources to EXE", len(self.resources)) + for resource in self.resources: + self._retry_operation(self._copy_windows_resource, build_name, resource) + # Embed the manifest into the executable. + logger.info("Embedding manifest in EXE") + self._retry_operation(winmanifest.write_manifest_to_executable, build_name, self.manifest) + elif is_darwin: + # Convert bootloader to the target arch + logger.info("Converting EXE to target arch (%s)", self.target_arch) + osxutils.binary_to_target_arch(build_name, self.target_arch, display_name='Bootloader EXE') + + # Step 2: append the PKG, if necessary + if self.append_pkg: + append_file = self.pkg.name # Append PKG + append_type = 'PKG archive' # For debug messages + else: + # In onefile mode, copy the stand-alone PKG next to the executable. In onedir, this will be done by the + # COLLECT() target. + if not self.exclude_binaries: + pkg_dst = os.path.join(os.path.dirname(build_name), os.path.basename(self.pkgname)) + logger.info("Copying stand-alone PKG archive from %s to %s", self.pkg.name, pkg_dst) + shutil.copyfile(self.pkg.name, pkg_dst) + else: + logger.info("Stand-alone PKG archive will be handled by COLLECT") + + # The bootloader requires package side-loading to be explicitly enabled, which is done by embedding custom + # signature to the executable. This extra signature ensures that the sideload-enabled executable is at least + # slightly different from the stock bootloader executables, which should prevent antivirus programs from + # flagging our stock bootloaders due to sideload-enabled applications in the wild. + + # Write to temporary file + pkgsig_file = self.pkg.name + '.sig' + with open(pkgsig_file, "wb") as f: + # 8-byte MAGIC; slightly changed PKG MAGIC pattern + f.write(b'MEI\015\013\012\013\016') + + append_file = pkgsig_file # Append PKG-SIG + append_type = 'PKG sideload signature' # For debug messages + + if is_linux: + # Linux: append data into custom ELF section using objcopy. + logger.info("Appending %s to custom ELF section in EXE", append_type) + cmd = ['objcopy', '--add-section', f'pydata={append_file}', build_name] + p = subprocess.run(cmd, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, encoding='utf-8') + if p.returncode: + raise SystemError(f"objcopy Failure: {p.returncode} {p.stdout}") + + elif is_darwin: + # macOS: remove signature, append data, and fix-up headers so that the appended data appears to be part of + # the executable (which is required by strict validation during code-signing). + + # Strip signatures from all arch slices. Strictly speaking, we need to remove signature (if present) from + # the last slice, because we will be appending data to it. When building universal2 bootloaders natively on + # macOS, only arm64 slices have a (dummy) signature. However, when cross-compiling with osxcross, we seem to + # get dummy signatures on both x86_64 and arm64 slices. While the former should not have any impact, it does + # seem to cause issues with further binary signing using real identity. Therefore, we remove all signatures + # and re-sign the binary using dummy signature once the data is appended. + logger.info("Removing signature(s) from EXE") + osxutils.remove_signature_from_binary(build_name) + + # Append the data + logger.info("Appending %s to EXE", append_type) + self._append_data_to_exe(build_name, append_file) + + # Fix Mach-O headers + logger.info("Fixing EXE headers for code signing") + osxutils.fix_exe_for_code_signing(build_name) + else: + # Fall back to just appending data at the end of the file + logger.info("Appending %s to EXE", append_type) + self._retry_operation(self._append_data_to_exe, build_name, append_file) + + # Step 3: post-processing + if is_win: + # Set checksum to appease antiviral software. Also set build timestamp to current time to increase entropy + # (but honor SOURCE_DATE_EPOCH environment variable for reproducible builds). + logger.info("Fixing EXE headers") + build_timestamp = int(os.environ.get('SOURCE_DATE_EPOCH', time.time())) + self._retry_operation(winutils.set_exe_build_timestamp, build_name, build_timestamp) + self._retry_operation(winutils.update_exe_pe_checksum, build_name) + elif is_darwin: + # If the version of macOS SDK used to build bootloader exceeds that of macOS SDK used to built Python + # library (and, by extension, bundled Tcl/Tk libraries), force the version declared by the frozen executable + # to match that of the Python library. + # Having macOS attempt to enable new features (based on SDK version) for frozen application has no benefit + # if the Python library does not support them as well. + # On the other hand, there seem to be UI issues in tkinter due to failed or partial enablement of dark mode + # (i.e., the bootloader executable being built against SDK 10.14 or later, which causes macOS to enable dark + # mode, and Tk libraries being built against an earlier SDK version that does not support the dark mode). + # With python.org Intel macOS installers, this manifests as black Tk windows and UI elements (see issue + # #5827), while in Anaconda python, it may result in white text on bright background. + pylib_version = osxutils.get_macos_sdk_version(self.python_lib) + exe_version = osxutils.get_macos_sdk_version(build_name) + if pylib_version < exe_version: + logger.info( + "Rewriting the executable's macOS SDK version (%d.%d.%d) to match the SDK version of the Python " + "library (%d.%d.%d) in order to avoid inconsistent behavior and potential UI issues in the " + "frozen application.", *exe_version, *pylib_version + ) + osxutils.set_macos_sdk_version(build_name, *pylib_version) + + # Re-sign the binary (either ad-hoc or using real identity, if provided). + logger.info("Re-signing the EXE") + osxutils.sign_binary(build_name, self.codesign_identity, self.entitlements_file) + + # Ensure executable flag is set + self._retry_operation(os.chmod, build_name, 0o755) + # Get mtime for storing into the guts + self.mtm = self._retry_operation(miscutils.mtime, build_name) + if build_name != self.name: + self._retry_operation(os.rename, build_name, self.name) + logger.info("Building EXE from %s completed successfully.", self.tocbasename) + + def _copy_windows_resource(self, build_name, resource_spec): + import pefile + + # Helper for optionally converting integer strings to values; resource types and IDs/names can be specified as + # either numeric values or custom strings... + def _to_int(value): + try: + return int(value) + except Exception: + return value + + logger.debug("Processing resource: %r", resource_spec) + resource = resource_spec.split(",") # filename,[type],[name],[language] + + if len(resource) < 1 or len(resource) > 4: + raise ValueError( + f"Invalid Windows resource specifier {resource_spec!r}! " + f"Must be in format 'filename,[type],[name],[language]'!" + ) + + # Anchor resource file to spec file location, if necessary. + src_filename = self._makeabs(resource[0]) + + # Ensure file exists. + if not os.path.isfile(src_filename): + raise ValueError(f"Resource file {src_filename!r} does not exist!") + + # Check if src_filename points to a PE file or an arbitrary (data) file. + try: + with pefile.PE(src_filename, fast_load=True): + is_pe_file = True + except Exception: + is_pe_file = False + + if is_pe_file: + # If resource file is PE file, copy all resources from it, subject to specified type, name, and language. + logger.debug("Resource file %r is a PE file...", src_filename) + + # Resource type, name, and language serve as filters. If not specified, use "*". + resource_type = _to_int(resource[1]) if len(resource) >= 2 else "*" + resource_name = _to_int(resource[2]) if len(resource) >= 3 else "*" + resource_lang = _to_int(resource[3]) if len(resource) >= 4 else "*" + + try: + winresource.copy_resources_from_pe_file( + build_name, + src_filename, + [resource_type], + [resource_name], + [resource_lang], + ) + except Exception as e: + raise IOError(f"Failed to copy resources from PE file {src_filename!r}") from e + else: + logger.debug("Resource file %r is an arbitrary data file...", src_filename) + + # For arbitrary data file, resource type and name need to be provided. + if len(resource) < 3: + raise ValueError( + f"Invalid Windows resource specifier {resource_spec!r}! " + f"For arbitrary data file, the format is 'filename,type,name,[language]'!" + ) + + resource_type = _to_int(resource[1]) + resource_name = _to_int(resource[2]) + resource_lang = _to_int(resource[3]) if len(resource) >= 4 else 0 # LANG_NEUTRAL + + # Prohibit wildcards for resource type and name. + if resource_type == "*": + raise ValueError( + f"Invalid Windows resource specifier {resource_spec!r}! " + f"For arbitrary data file, resource type cannot be a wildcard (*)!" + ) + if resource_name == "*": + raise ValueError( + f"Invalid Windows resource specifier {resource_spec!r}! " + f"For arbitrary data file, resource ma,e cannot be a wildcard (*)!" + ) + + try: + with open(src_filename, 'rb') as fp: + data = fp.read() + + winresource.add_or_update_resource( + build_name, + data, + resource_type, + [resource_name], + [resource_lang], + ) + except Exception as e: + raise IOError(f"Failed to embed data file {src_filename!r} as Windows resource") from e + + def _append_data_to_exe(self, build_name, append_file): + with open(build_name, 'ab') as outf: + with open(append_file, 'rb') as inf: + shutil.copyfileobj(inf, outf, length=64 * 1024) + + @staticmethod + def _retry_operation(func, *args, max_attempts=20): + """ + Attempt to execute the given function `max_attempts` number of times while catching exceptions that are usually + associated with Windows anti-virus programs temporarily locking the access to the executable. + """ + def _is_allowed_exception(e): + """ + Helper to determine whether the given exception is eligible for retry or not. + """ + if isinstance(e, PermissionError): + # Always retry on all instances of PermissionError + return True + elif is_win: + from PyInstaller.compat import pywintypes + + # Windows-specific errno and winerror codes. + # https://learn.microsoft.com/en-us/cpp/c-runtime-library/errno-constants + _ALLOWED_ERRNO = { + 13, # EACCES (would typically be a PermissionError instead) + 22, # EINVAL (reported to be caused by Crowdstrike; see #7840) + } + # https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499- + _ALLOWED_WINERROR = { + 5, # ERROR_ACCESS_DENIED (reported in #7825) + 32, # ERROR_SHARING_VIOLATION (exclusive lock via `CreateFileW` flags, or via `_locked`). + 110, # ERROR_OPEN_FAILED (reported in #8138) + } + if isinstance(e, OSError): + # For OSError exceptions other than PermissionError, validate errno. + if e.errno in _ALLOWED_ERRNO: + return True + # OSError typically translates `winerror` into `errno` equivalent; but try to match the original + # values as a fall back, just in case. `OSError.winerror` attribute exists only on Windows. + if e.winerror in _ALLOWED_WINERROR: + return True + elif isinstance(e, pywintypes.error): + # pywintypes.error is raised by helper functions that use win32 C API bound via pywin32-ctypes. + if e.winerror in _ALLOWED_WINERROR: + return True + return False + + func_name = func.__name__ + for attempt in range(max_attempts): + try: + return func(*args) + except Exception as e: + # Check if exception is eligible for retry; if not, also check its immediate cause (in case the + # exception was thrown from an eligible exception). + if not _is_allowed_exception(e) and not _is_allowed_exception(e.__context__): + raise + + # Retry after sleep (unless this was our last attempt) + if attempt < max_attempts - 1: + sleep_duration = 1 / (max_attempts - 1 - attempt) + logger.warning( + f"Execution of {func_name!r} failed on attempt #{attempt + 1} / {max_attempts}: {e!r}. " + f"Retrying in {sleep_duration:.2f} second(s)..." + ) + time.sleep(sleep_duration) + else: + logger.warning( + f"Execution of {func_name!r} failed on attempt #{attempt + 1} / {max_attempts}: {e!r}." + ) + raise RuntimeError(f"Execution of {func_name!r} failed - no more attempts left!") from e + + +class COLLECT(Target): + """ + In one-dir mode creates the output folder with all necessary files. + """ + def __init__(self, *args, **kwargs): + """ + args + One or more arguments that are either an instance of `Target` or an iterable representing TOC list. + kwargs + Possible keyword arguments: + + name + The name of the directory to be built. + """ + from PyInstaller.config import CONF + + super().__init__() + + self.strip_binaries = kwargs.get('strip', False) + self.upx_exclude = kwargs.get("upx_exclude", []) + self.console = True + self.target_arch = None + self.codesign_identity = None + self.entitlements_file = None + + # UPX needs to be both available and enabled for the taget. + self.upx_binaries = CONF['upx_available'] and kwargs.get('upx', False) + + # The `name` should be the output directory name, without the parent path (the directory is created in the + # DISTPATH). Old .spec formats included parent path, so strip it away. + self.name = os.path.join(CONF['distpath'], os.path.basename(kwargs.get('name'))) + + for arg in args: + if isinstance(arg, EXE): + self.contents_directory = arg.contents_directory + break + else: + raise ValueError("No EXE() instance was passed to COLLECT()") + + self.toc = [] + for arg in args: + # Valid arguments: EXE object and TOC-like iterables + if isinstance(arg, EXE): + # Add EXE as an entry to the TOC, and merge its dependencies TOC + self.toc.append((os.path.basename(arg.name), arg.name, 'EXECUTABLE')) + self.toc.extend(arg.dependencies) + # Inherit settings + self.console = arg.console + self.target_arch = arg.target_arch + self.codesign_identity = arg.codesign_identity + self.entitlements_file = arg.entitlements_file + # Search for the executable's external manifest, and collect it if available + for dest_name, src_name, typecode in arg.toc: + if dest_name == os.path.basename(arg.name) + ".manifest": + self.toc.append((dest_name, src_name, typecode)) + # If PKG is not appended to the executable, we need to collect it. + if not arg.append_pkg: + self.toc.append((os.path.basename(arg.pkgname), arg.pkgname, 'PKG')) + elif miscutils.is_iterable(arg): + # TOC-like iterable + self.toc.extend(arg) + else: + raise TypeError(f"Invalid argument type for COLLECT: {type(arg)!r}") + + # Normalize TOC + self.toc = normalize_toc(self.toc) + + self.__postinit__() + + _GUTS = ( + # COLLECT always builds, we just want the TOC to be written out. + ('toc', None), + ) + + def _check_guts(self, data, last_build): + # COLLECT always needs to be executed, in order to clean the output directory. + return True + + def assemble(self): + _make_clean_directory(self.name) + logger.info("Building COLLECT %s", self.tocbasename) + for dest_name, src_name, typecode in self.toc: + # Ensure that the source file exists, if necessary. Skip the check for DEPENDENCY entries due to special + # contents of 'dest_name' and/or 'src_name'. Same for the SYMLINK entries, where 'src_name' is relative + # target name for symbolic link. + if typecode not in {'DEPENDENCY', 'SYMLINK'} and not os.path.exists(src_name): + # If file is contained within python egg, it will be added with the egg. + if strict_collect_mode: + raise ValueError(f"Non-existent resource {src_name}, meant to be collected as {dest_name}!") + else: + logger.warning( + "Ignoring non-existent resource %s, meant to be collected as %s", src_name, dest_name + ) + continue + # Disallow collection outside of the dist directory. + if os.pardir in os.path.normpath(dest_name).split(os.sep) or os.path.isabs(dest_name): + raise SystemExit( + 'Security-Alert: attempting to store file outside of the dist directory: %r. Aborting.' % dest_name + ) + # Create parent directory structure, if necessary + if typecode in ("EXECUTABLE", "PKG"): + dest_path = os.path.join(self.name, dest_name) + else: + dest_path = os.path.join(self.name, self.contents_directory or "", dest_name) + dest_dir = os.path.dirname(dest_path) + try: + os.makedirs(dest_dir, exist_ok=True) + except FileExistsError: + raise SystemExit( + f"Pyinstaller needs to create a directory at {dest_dir!r}, " + "but there already exists a file at that path!" + ) + if typecode in ('EXTENSION', 'BINARY'): + src_name = process_collected_binary( + src_name, + dest_name, + use_strip=self.strip_binaries, + use_upx=self.upx_binaries, + upx_exclude=self.upx_exclude, + target_arch=self.target_arch, + codesign_identity=self.codesign_identity, + entitlements_file=self.entitlements_file, + strict_arch_validation=(typecode == 'EXTENSION'), + ) + if typecode == 'SYMLINK': + # On Windows, ensure that symlink target path (stored in src_name) is using Windows-style back slash + # separators. + if is_win and os.path.sep == '/': + src_name = src_name.replace(os.path.sep, '\\') + + os.symlink(src_name, dest_path) # Create link at dest_path, pointing at (relative) src_name + elif typecode != 'DEPENDENCY': + # At this point, `src_name` should be a valid file. + if not os.path.isfile(src_name): + raise ValueError(f"Resource {src_name!r} is not a valid file!") + # If strict collection mode is enabled, the destination should not exist yet. + if strict_collect_mode and os.path.exists(dest_path): + raise ValueError( + f"Attempting to collect a duplicated file into COLLECT: {dest_name} (type: {typecode})" + ) + # Use `shutil.copyfile` to copy file with default permissions. We do not attempt to preserve original + # permissions nor metadata, as they might be too restrictive and cause issues either during subsequent + # re-build attempts or when trying to move the application bundle. For binaries (and data files with + # executable bit set), we manually set the executable bits after copying the file. + shutil.copyfile(src_name, dest_path) + if ( + typecode in ('EXTENSION', 'BINARY', 'EXECUTABLE') + or (typecode == 'DATA' and os.access(src_name, os.X_OK)) + ): + os.chmod(dest_path, 0o755) + logger.info("Building COLLECT %s completed successfully.", self.tocbasename) + + +class MERGE: + """ + Given Analysis objects for multiple executables, replace occurrences of data and binary files with references to the + first executable in which they occur. The actual data and binary files are then collected only once, thereby + reducing the disk space used by multiple executables. Every executable (even onedir ones!) obtained from a + MERGE-processed Analysis gains onefile semantics, because it needs to extract its referenced dependencies from other + executables into temporary directory before they can run. + """ + def __init__(self, *args): + """ + args + Dependencies as a list of (analysis, identifier, path_to_exe) tuples. `analysis` is an instance of + `Analysis`, `identifier` is the basename of the entry-point script (without .py suffix), and `path_to_exe` + is path to the corresponding executable, relative to the `dist` directory (without .exe suffix in the + filename component). For onefile executables, `path_to_exe` is usually just executable's base name + (e.g., `myexecutable`). For onedir executables, `path_to_exe` usually comprises both the application's + directory name and executable name (e.g., `myapp/myexecutable`). + """ + self._dependencies = {} + self._symlinks = set() + + # Process all given (analysis, identifier, path_to_exe) tuples + for analysis, identifier, path_to_exe in args: + # Process analysis.binaries and analysis.datas TOCs. self._process_toc() call returns two TOCs; the first + # contains entries that remain within this analysis, while the second contains entries that reference + # an entry in another executable. + binaries, binaries_refs = self._process_toc(analysis.binaries, path_to_exe) + datas, datas_refs = self._process_toc(analysis.datas, path_to_exe) + # Update `analysis.binaries`, `analysis.datas`, and `analysis.dependencies`. + # The entries that are found in preceding executable(s) are removed from `binaries` and `datas`, and their + # DEPENDENCY entry counterparts are added to `dependencies`. We cannot simply update the entries in + # `binaries` and `datas`, because at least in theory, we need to support both onefile and onedir mode. And + # while in onefile, `a.datas`, `a.binaries`, and `a.dependencies` are passed to `EXE` (and its `PKG`), with + # onedir, `a.datas` and `a.binaries` need to be passed to `COLLECT` (as they were before the MERGE), while + # `a.dependencies` needs to be passed to `EXE`. This split requires DEPENDENCY entries to be in a separate + # TOC. + analysis.binaries = normalize_toc(binaries) + analysis.datas = normalize_toc(datas) + analysis.dependencies += binaries_refs + datas_refs + + def _process_toc(self, toc, path_to_exe): + # NOTE: unfortunately, these need to keep two separate lists. See the comment in the calling code on why this + # is so. + toc_keep = [] + toc_refs = [] + for entry in toc: + dest_name, src_name, typecode = entry + + # Special handling and bookkeeping for symbolic links. We need to account both for dest_name and src_name, + # because src_name might be the same in different contexts. For example, when collecting Qt .framework + # bundles on macOS, there are multiple relative symbolic links `Current -> A` (one in each .framework). + if typecode == 'SYMLINK': + key = dest_name, src_name + if key not in self._symlinks: + # First occurrence; keep the entry in "for-keep" TOC, same as we would for binaries and datas. + logger.debug("Keeping symbolic link %r entry in original TOC.", entry) + self._symlinks.add(key) + toc_keep.append(entry) + else: + # Subsequent occurrence; keep the SYMLINK entry intact, but add it to the references TOC instead of + # "for-keep" TOC, so it ends up in `a.dependencies`. + logger.debug("Moving symbolic link %r entry to references TOC.", entry) + toc_refs.append(entry) + del key # Block-local variable + continue + + # In fact, we need to accout for both dest_name and src_name with regular entries as well; previous + # approach that considered only src_name ended tripped up when same file was collected in different + # locations (i.e., same src_name but different dest_names). + key = dest_name, src_name + if key not in self._dependencies: + logger.debug("Adding dependency %r located in %s", key, path_to_exe) + self._dependencies[key] = path_to_exe + # Add entry to list of kept TOC entries + toc_keep.append(entry) + else: + # Construct relative dependency path; i.e., the relative path from this executable (or rather, its + # parent directory) to the executable that contains the dependency. + dep_path = os.path.relpath(self._dependencies[key], os.path.dirname(path_to_exe)) + # Ignore references that point to the origin package. This can happen if the same resource is listed + # multiple times in TOCs (e.g., once as binary and once as data). + if dep_path.endswith(path_to_exe): + logger.debug( + "Ignoring self-reference of %r for %s, located in %s - duplicated TOC entry?", key, path_to_exe, + dep_path + ) + # The entry is a duplicate, and should be ignored (i.e., do not add it to either of output TOCs). + continue + logger.debug("Referencing %r to be a dependency for %s, located in %s", key, path_to_exe, dep_path) + # Create new DEPENDENCY entry; under destination path (first element), we store the original destination + # path, while source path contains the relative reference path. + toc_refs.append((dest_name, dep_path, "DEPENDENCY")) + + return toc_keep, toc_refs + + +UNCOMPRESSED = False +COMPRESSED = True + +_MISSING_BOOTLOADER_ERRORMSG = """Fatal error: PyInstaller does not include a pre-compiled bootloader for your +platform. For more details and instructions how to build the bootloader see +""" diff --git a/venv/Lib/site-packages/PyInstaller/building/build_main.py b/venv/Lib/site-packages/PyInstaller/building/build_main.py new file mode 100644 index 0000000..b15271e --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/building/build_main.py @@ -0,0 +1,1252 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- +""" +Build packages using spec files. + +NOTE: All global variables, classes and imported modules create API for .spec files. +""" + +import glob +import os +import pathlib +import pprint +import shutil +import enum +import re +import sys + +from PyInstaller import DEFAULT_DISTPATH, DEFAULT_WORKPATH, HOMEPATH, compat +from PyInstaller import log as logging +from PyInstaller.building.api import COLLECT, EXE, MERGE, PYZ +from PyInstaller.building.datastruct import ( + TOC, Target, Tree, _check_guts_eq, normalize_toc, normalize_pyz_toc, toc_process_symbolic_links +) +from PyInstaller.building.osx import BUNDLE +from PyInstaller.building.splash import Splash +from PyInstaller.building.utils import ( + _check_guts_toc, _check_guts_toc_mtime, _should_include_system_binary, format_binaries_and_datas, compile_pymodule, + add_suffix_to_extension, postprocess_binaries_toc_pywin32, postprocess_binaries_toc_pywin32_anaconda +) +from PyInstaller.compat import is_win, is_conda, is_darwin, is_linux +from PyInstaller.depend import bindepend +from PyInstaller.depend.analysis import initialize_modgraph, HOOK_PRIORITY_USER_HOOKS +from PyInstaller.depend.utils import create_py3_base_library, scan_code_for_ctypes +from PyInstaller import isolated +from PyInstaller.utils.misc import absnormpath, get_path_to_toplevel_modules, mtime +from PyInstaller.utils.hooks import get_package_paths +from PyInstaller.utils.hooks.gi import compile_glib_schema_files + +if is_darwin: + from PyInstaller.utils import osx as osxutils + +logger = logging.getLogger(__name__) + +STRINGTYPE = type('') +TUPLETYPE = type((None,)) + +rthooks = {} + +# Place where the loader modules and initialization scripts live. +_init_code_path = os.path.join(HOMEPATH, 'PyInstaller', 'loader') + +IMPORT_TYPES = [ + 'top-level', 'conditional', 'delayed', 'delayed, conditional', 'optional', 'conditional, optional', + 'delayed, optional', 'delayed, conditional, optional' +] + +WARNFILE_HEADER = """\ + +This file lists modules PyInstaller was not able to find. This does not +necessarily mean this module is required for running your program. Python and +Python 3rd-party packages include a lot of conditional or optional modules. For +example the module 'ntpath' only exists on Windows, whereas the module +'posixpath' only exists on Posix systems. + +Types if import: +* top-level: imported at the top-level - look at these first +* conditional: imported within an if-statement +* delayed: imported within a function +* optional: imported within a try-except-statement + +IMPORTANT: Do NOT post this list to the issue-tracker. Use it as a basis for + tracking down the missing module yourself. Thanks! + +""" + + +@isolated.decorate +def discover_hook_directories(): + """ + Discover hook directories via pyinstaller40 entry points. Perform the discovery in an isolated subprocess + to avoid importing the package(s) in the main process. + + :return: list of discovered hook directories. + """ + + from traceback import format_exception_only + from PyInstaller.log import logger + from PyInstaller.compat import importlib_metadata + from PyInstaller.depend.analysis import HOOK_PRIORITY_CONTRIBUTED_HOOKS, HOOK_PRIORITY_UPSTREAM_HOOKS + + # The “selectable” entry points (via group and name keyword args) were introduced in importlib_metadata 4.6 and + # Python 3.10. The compat module ensures we are using a compatible version. + entry_points = importlib_metadata.entry_points(group='pyinstaller40', name='hook-dirs') + + # Ensure that pyinstaller_hooks_contrib comes last so that hooks from packages providing their own take priority. + # In pyinstaller-hooks-contrib >= 2024.8, the entry-point module is `_pyinstaller_hooks_contrib`; in earlier + # versions, it was `_pyinstaller_hooks_contrib.hooks`. + entry_points = sorted(entry_points, key=lambda x: x.module.startswith("_pyinstaller_hooks_contrib")) + + hook_directories = [] + for entry_point in entry_points: + # Query hook directory location(s) from entry point + try: + hook_directory_entries = entry_point.load()() + except Exception as e: + msg = "".join(format_exception_only(type(e), e)).strip() + logger.warning("discover_hook_directories: Failed to process hook entry point '%s': %s", entry_point, msg) + continue + + # Determine location-based priority: upstream hooks vs. hooks from contributed hooks package. + location_priority = ( + HOOK_PRIORITY_CONTRIBUTED_HOOKS + if entry_point.module.startswith("_pyinstaller_hooks_contrib") else HOOK_PRIORITY_UPSTREAM_HOOKS + ) + + # Append entries + hook_directories.extend([(hook_directory_entry, location_priority) + for hook_directory_entry in hook_directory_entries]) + + logger.debug("discover_hook_directories: Hook directories: %s", hook_directories) + + return hook_directories + + +def find_binary_dependencies(binaries, import_packages, symlink_suppression_patterns): + """ + Find dynamic dependencies (linked shared libraries) for the provided list of binaries. + + On Windows, this function performs additional pre-processing in an isolated environment in an attempt to handle + dynamic library search path modifications made by packages during their import. The packages from the given list + of collected packages are imported one by one, while keeping track of modifications made by `os.add_dll_directory` + calls and additions to the `PATH` environment variable. The recorded additional search paths are then passed to + the binary dependency analysis step. + + binaries + List of binaries to scan for dynamic dependencies. + import_packages + List of packages to import prior to scanning binaries. + symlink_suppression_patterns + Set of paths and/or path patterns for which binary dependency analysis should not create symbolic links + to the top-level application directory (when the discovered shared library's parent directory structure + is preserved). When binary dependency analysis discovers a shared library, it matches its *source path* + against all symlink suppression patterns (using `pathlib.PurePath.match`) to determine whether to create + a symbolic link to top-level application directory or not. + + :return: expanded list of binaries and then dependencies. + """ + + # Extra library search paths (used on Windows to resolve DLL paths). + extra_libdirs = [] + if compat.is_win: + # Always search `sys.base_prefix`, and search it first. This ensures that we resolve the correct version of + # `python3X.dll` and `python3.dll` (a PEP-0384 stable ABI stub that forwards symbols to the fully versioned + # `python3X.dll`), regardless of other python installations that might be present in the PATH. + extra_libdirs.append(compat.base_prefix) + + # When using python built from source, `sys.base_prefix` does not point to the directory that contains python + # executable, `python3X.dll`, and `python3.dll`. To accommodate such case, also add the directory in which + # python executable is located to the extra search paths. On the off-chance that this is a combination of venv + # and python built from source, prefer `sys._base_executable` over `sys.executable`. + extra_libdirs.append(os.path.dirname(getattr(sys, '_base_executable', sys.executable))) + + # If `pywin32` is installed, resolve the path to the `pywin32_system32` directory. Most `pywin32` extensions + # reference the `pywintypes3X.dll` in there. Based on resolved `pywin32_system32` directory, also add other + # `pywin32` directory, in case extensions in different directories reference each other (the ones in the same + # directory should already be resolvable due to binary dependency analysis passing the analyzed binary's + # location to the `get_imports` function). This allows us to avoid searching all paths in `sys.path`, which + # may lead to other corner-case issues (e.g., #5560). + pywin32_system32_dir = None + try: + # Look up the directory by treating it as a namespace package. + _, pywin32_system32_dir = get_package_paths('pywin32_system32') + except Exception: + pass + + if pywin32_system32_dir: + pywin32_base_dir = os.path.dirname(pywin32_system32_dir) + extra_libdirs += [ + pywin32_system32_dir, # .../pywin32_system32 + # based on pywin32.pth + os.path.join(pywin32_base_dir, 'win32'), # .../win32 + os.path.join(pywin32_base_dir, 'win32', 'lib'), # .../win32/lib + os.path.join(pywin32_base_dir, 'Pythonwin'), # .../Pythonwin + ] + + # On Windows, packages' initialization code might register additional DLL search paths, either by modifying the + # `PATH` environment variable, or by calling `os.add_dll_directory`. Therefore, we import all collected packages, + # and track changes made to the environment. + if compat.is_win: + # Helper functions to be executed in isolated environment. + def setup(suppressed_imports): + """ + Prepare environment for change tracking + """ + import os + import sys + + os._added_dll_directories = [] + os._original_path_env = os.environ.get('PATH', '') + + _original_add_dll_directory = os.add_dll_directory + + def _pyi_add_dll_directory(path): + os._added_dll_directories.append(path) + return _original_add_dll_directory(path) + + os.add_dll_directory = _pyi_add_dll_directory + + # Suppress import of specified packages + for name in suppressed_imports: + sys.modules[name] = None + + def import_library(package): + """ + Import collected package to set up environment. + """ + try: + __import__(package) + except Exception: + pass + + def process_search_paths(): + """ + Obtain lists of added search paths. + """ + import os + + # `os.add_dll_directory` might be called with a `pathlib.Path`, which cannot be marhsalled out of the helper + # process. So explicitly convert all entries to strings. + dll_directories = [str(path) for path in os._added_dll_directories] + + orig_path = set(os._original_path_env.split(os.pathsep)) + modified_path = os.environ.get('PATH', '').split(os.pathsep) + path_additions = [path for path in modified_path if path and path not in orig_path] + + return dll_directories, path_additions + + # Pre-process the list of packages to import. + # Check for Qt bindings packages, and put them at the front of the packages list. This ensures that they are + # always imported first, which should prevent packages that support multiple bindings (`qtypy`, `pyqtgraph`, + # `matplotlib`, etc.) from trying to auto-select bindings. + _QT_BINDINGS = ('PySide2', 'PyQt5', 'PySide6', 'PyQt6') + + qt_packages = [] + other_packages = [] + for package in import_packages: + if package.startswith(_QT_BINDINGS): + qt_packages.append(package) + else: + other_packages.append(package) + import_packages = qt_packages + other_packages + + # Just in case, explicitly suppress imports of Qt bindings that we are *not* collecting - if multiple bindings + # are available and some were excluded from our analysis, a package imported here might still try to import an + # excluded bindings package (and succeed at doing so). + suppressed_imports = [package for package in _QT_BINDINGS if package not in qt_packages] + + # If we suppressed PySide2 or PySide6, we must also suppress their corresponding shiboken package + if "PySide2" in suppressed_imports: + suppressed_imports += ["shiboken2"] + if "PySide6" in suppressed_imports: + suppressed_imports += ["shiboken6"] + + # Suppress import of `pyqtgraph.canvas`, which is known to crash python interpreter. See #7452 and #8322, as + # well as https://github.com/pyqtgraph/pyqtgraph/issues/2838. + suppressed_imports += ['pyqtgraph.canvas'] + + # PySimpleGUI 5.x displays a "first-run" dialog when imported for the first time, which blocks the loop below. + # This is a problem for building on CI, where the dialog cannot be closed, and where PySimpleGUI runs "for the + # first time" every time. See #8396. + suppressed_imports += ['PySimpleGUI'] + + # Processing in isolated environment. + with isolated.Python() as child: + child.call(setup, suppressed_imports) + for package in import_packages: + try: + child.call(import_library, package) + except isolated.SubprocessDiedError as e: + # Re-raise as `isolated.SubprocessDiedError` again, to trigger error-handling codepath in + # `isolated.Python.__exit__()`. + raise isolated.SubprocessDiedError( + f"Isolated subprocess crashed while importing package {package!r}! " + f"Package import list: {import_packages!r}" + ) from e + added_dll_directories, added_path_directories = child.call(process_search_paths) + + # Process extra search paths... + logger.info("Extra DLL search directories (AddDllDirectory): %r", added_dll_directories) + extra_libdirs += added_dll_directories + + logger.info("Extra DLL search directories (PATH): %r", added_path_directories) + extra_libdirs += added_path_directories + + # Deduplicate search paths + # NOTE: `list(set(extra_libdirs))` does not preserve the order of search paths (which matters here), so we need to + # de-duplicate using `list(dict.fromkeys(extra_libdirs).keys())` instead. + extra_libdirs = list(dict.fromkeys(extra_libdirs).keys()) + + # Search for dependencies of the given binaries + return bindepend.binary_dependency_analysis( + binaries, + search_paths=extra_libdirs, + symlink_suppression_patterns=symlink_suppression_patterns, + ) + + +class _ModuleCollectionMode(enum.IntFlag): + """ + Module collection mode flags. + """ + PYZ = enum.auto() # Collect byte-compiled .pyc into PYZ archive + PYC = enum.auto() # Collect byte-compiled .pyc as external data file + PY = enum.auto() # Collect source .py file as external data file + + +_MODULE_COLLECTION_MODES = { + "pyz": _ModuleCollectionMode.PYZ, + "pyc": _ModuleCollectionMode.PYC, + "py": _ModuleCollectionMode.PY, + "pyz+py": _ModuleCollectionMode.PYZ | _ModuleCollectionMode.PY, + "py+pyz": _ModuleCollectionMode.PYZ | _ModuleCollectionMode.PY, +} + + +def _get_module_collection_mode(mode_dict, name, noarchive=False): + """ + Determine the module/package collection mode for the given module name, based on the provided collection + mode settings dictionary. + """ + # Default mode: collect into PYZ, unless noarchive is enabled. In that case, collect as pyc. + mode_flags = _ModuleCollectionMode.PYC if noarchive else _ModuleCollectionMode.PYZ + + # If we have no collection mode settings, end here and now. + if not mode_dict: + return mode_flags + + # Search the parent modules/packages in top-down fashion, and take the last given setting. This ensures that + # a setting given for the top-level package is recursively propagated to all its subpackages and submodules, + # but also allows individual sub-modules to override the setting again. + mode = 'pyz' + + name_parts = name.split('.') + for i in range(len(name_parts)): + modlevel = ".".join(name_parts[:i + 1]) + modlevel_mode = mode_dict.get(modlevel, None) + if modlevel_mode is not None: + mode = modlevel_mode + + # Convert mode string to _ModuleCollectionMode flags + try: + mode_flags = _MODULE_COLLECTION_MODES[mode] + except KeyError: + raise ValueError(f"Unknown module collection mode for {name!r}: {mode!r}!") + + # noarchive flag being set means that we need to change _ModuleCollectionMode.PYZ into _ModuleCollectionMode.PYC + if noarchive and _ModuleCollectionMode.PYZ in mode_flags: + mode_flags ^= _ModuleCollectionMode.PYZ + mode_flags |= _ModuleCollectionMode.PYC + + return mode_flags + + +class Analysis(Target): + """ + Class that performs analysis of the user's main Python scripts. + + An Analysis contains multiple TOC (Table of Contents) lists, accessed as attributes of the analysis object. + + scripts + The scripts you gave Analysis as input, with any runtime hook scripts prepended. + pure + The pure Python modules. + binaries + The extension modules and their dependencies. + datas + Data files collected from packages. + zipfiles + Deprecated - always empty. + zipped_data + Deprecated - always empty. + """ + _old_scripts = { + absnormpath(os.path.join(HOMEPATH, "support", "_mountzlib.py")), + absnormpath(os.path.join(HOMEPATH, "support", "useUnicode.py")), + absnormpath(os.path.join(HOMEPATH, "support", "useTK.py")), + absnormpath(os.path.join(HOMEPATH, "support", "unpackTK.py")), + absnormpath(os.path.join(HOMEPATH, "support", "removeTK.py")) + } + + def __init__( + self, + scripts, + pathex=None, + binaries=None, + datas=None, + hiddenimports=None, + hookspath=None, + hooksconfig=None, + excludes=None, + runtime_hooks=None, + cipher=None, + win_no_prefer_redirects=False, + win_private_assemblies=False, + noarchive=False, + module_collection_mode=None, + optimize=-1, + **_kwargs, + ): + """ + scripts + A list of scripts specified as file names. + pathex + An optional list of paths to be searched before sys.path. + binaries + An optional list of additional binaries (dlls, etc.) to include. + datas + An optional list of additional data files to include. + hiddenimport + An optional list of additional (hidden) modules to include. + hookspath + An optional list of additional paths to search for hooks. (hook-modules). + hooksconfig + An optional dict of config settings for hooks. (hook-modules). + excludes + An optional list of module or package names (their Python names, not path names) that will be + ignored (as though they were not found). + runtime_hooks + An optional list of scripts to use as users' runtime hooks. Specified as file names. + cipher + Deprecated. Raises an error if not None. + win_no_prefer_redirects + Deprecated. Raises an error if not False. + win_private_assemblies + Deprecated. Raises an error if not False. + noarchive + If True, do not place source files in a archive, but keep them as individual files. + module_collection_mode + An optional dict of package/module names and collection mode strings. Valid collection mode strings: + 'pyz' (default), 'pyc', 'py', 'pyz+py' (or 'py+pyz') + optimize + Optimization level for collected bytecode. If not specified or set to -1, it is set to the value of + `sys.flags.optimize` of the running build process. + """ + if cipher is not None: + from PyInstaller.exceptions import RemovedCipherFeatureError + raise RemovedCipherFeatureError( + "Please remove the 'cipher' arguments to PYZ() and Analysis() in your spec file." + ) + if win_no_prefer_redirects: + from PyInstaller.exceptions import RemovedWinSideBySideSupportError + raise RemovedWinSideBySideSupportError( + "Please remove the 'win_no_prefer_redirects' argument to Analysis() in your spec file." + ) + if win_private_assemblies: + from PyInstaller.exceptions import RemovedWinSideBySideSupportError + raise RemovedWinSideBySideSupportError( + "Please remove the 'win_private_assemblies' argument to Analysis() in your spec file." + ) + super().__init__() + from PyInstaller.config import CONF + + self.inputs = [] + spec_dir = os.path.dirname(CONF['spec']) + for script in scripts: + # If path is relative, it is relative to the location of .spec file. + if not os.path.isabs(script): + script = os.path.join(spec_dir, script) + if absnormpath(script) in self._old_scripts: + logger.warning('Ignoring obsolete auto-added script %s', script) + continue + # Normalize script path. + script = os.path.normpath(script) + if not os.path.exists(script): + raise SystemExit("script '%s' not found" % script) + self.inputs.append(script) + + # Django hook requires this variable to find the script manage.py. + CONF['main_script'] = self.inputs[0] + + site_packages_pathex = [] + for path in (pathex or []): + if pathlib.Path(path).name == "site-packages": + site_packages_pathex.append(str(path)) + if site_packages_pathex: + logger.log( + logging.DEPRECATION, "Foreign Python environment's site-packages paths added to --paths/pathex:\n%s\n" + "This is ALWAYS the wrong thing to do. If your environment's site-packages is not in PyInstaller's " + "module search path then you are running PyInstaller from a different environment to the one your " + "packages are in. Run print(sys.prefix) without PyInstaller to get the environment you should be using " + "then install and run PyInstaller from that environment instead of this one. This warning will become " + "an error in PyInstaller 7.0.", pprint.pformat(site_packages_pathex) + ) + + self.pathex = self._extend_pathex(pathex, self.inputs) + # Set global config variable 'pathex' to make it available for PyInstaller.utils.hooks and import hooks. Path + # extensions for module search. + CONF['pathex'] = self.pathex + # Extend sys.path so PyInstaller could find all necessary modules. + sys.path.extend(self.pathex) + logger.info('Module search paths (PYTHONPATH):\n' + pprint.pformat(sys.path)) + + self.hiddenimports = hiddenimports or [] + # Include hidden imports passed via CONF['hiddenimports']; these might be populated if user has a wrapper script + # that calls `build_main.main()` with custom `pyi_config` dictionary that contains `hiddenimports`. + self.hiddenimports.extend(CONF.get('hiddenimports', [])) + + for modnm in self.hiddenimports: + if re.search(r"[\\/]", modnm): + raise SystemExit( + f"Error: Invalid hiddenimport '{modnm}'. Hidden imports should be importable module names – not " + "file paths. i.e. use --hiddenimport=foo.bar instead of --hiddenimport=.../site-packages/foo/bar.py" + ) + + self.hookspath = [] + # Prepend directories in `hookspath` (`--additional-hooks-dir`) to take precedence over those from the entry + # points. Expand starting tilde into user's home directory, as a work-around for tilde not being expanded by + # shell when using ˙--additional-hooks-dir=~/path/abc` instead of ˙--additional-hooks-dir ~/path/abc` (or when + # the path argument is quoted). + if hookspath: + self.hookspath.extend([(os.path.expanduser(path), HOOK_PRIORITY_USER_HOOKS) for path in hookspath]) + + # Add hook directories from PyInstaller entry points. + self.hookspath += discover_hook_directories() + + self.hooksconfig = {} + if hooksconfig: + self.hooksconfig.update(hooksconfig) + + # Custom runtime hook files that should be included and started before any existing PyInstaller runtime hooks. + self.custom_runtime_hooks = runtime_hooks or [] + + self._input_binaries = [] + self._input_datas = [] + + self.excludes = excludes or [] + self.scripts = [] + self.pure = [] + self.binaries = [] + self.zipfiles = [] + self.zipped_data = [] + self.datas = [] + self.dependencies = [] + self._python_version = sys.version + self.noarchive = noarchive + self.module_collection_mode = module_collection_mode or {} + self.optimize = sys.flags.optimize if optimize in {-1, None} else optimize + + # Validate the optimization level to avoid errors later on... + if self.optimize not in {0, 1, 2}: + raise ValueError(f"Unsupported bytecode optimization level: {self.optimize!r}") + + # Expand the `binaries` and `datas` lists specified in the .spec file, and ensure that the lists are normalized + # and sorted before guts comparison. + # + # While we use these lists to initialize `Analysis.binaries` and `Analysis.datas`, at this point, we need to + # store them in separate variables, which undergo *full* guts comparison (`_check_guts_toc`) as opposed to + # just mtime-based comparison (`_check_guts_toc_mtime`). Changes to these initial list *must* trigger a rebuild + # (and due to the way things work, a re-analysis), otherwise user might end up with a cached build that fails to + # reflect the changes. + if binaries: + logger.info("Appending 'binaries' from .spec") + self._input_binaries = [(dest_name, src_name, 'BINARY') + for dest_name, src_name in format_binaries_and_datas(binaries, workingdir=spec_dir)] + self._input_binaries = sorted(normalize_toc(self._input_binaries)) + + if datas: + logger.info("Appending 'datas' from .spec") + self._input_datas = [(dest_name, src_name, 'DATA') + for dest_name, src_name in format_binaries_and_datas(datas, workingdir=spec_dir)] + self._input_datas = sorted(normalize_toc(self._input_datas)) + + self.__postinit__() + + _GUTS = ( # input parameters + ('inputs', _check_guts_eq), # parameter `scripts` + ('pathex', _check_guts_eq), + ('hiddenimports', _check_guts_eq), + ('hookspath', _check_guts_eq), + ('hooksconfig', _check_guts_eq), + ('excludes', _check_guts_eq), + ('custom_runtime_hooks', _check_guts_eq), + ('noarchive', _check_guts_eq), + ('module_collection_mode', _check_guts_eq), + ('optimize', _check_guts_eq), + + ('_input_binaries', _check_guts_toc), + ('_input_datas', _check_guts_toc), + + # calculated/analysed values + ('_python_version', _check_guts_eq), + ('scripts', _check_guts_toc_mtime), + ('pure', _check_guts_toc_mtime), + ('binaries', _check_guts_toc_mtime), + ('zipfiles', _check_guts_toc_mtime), + ('zipped_data', None), # TODO check this, too + ('datas', _check_guts_toc_mtime), + # TODO: Need to add "dependencies"? + ) + + def _extend_pathex(self, spec_pathex, scripts): + """ + Normalize additional paths where PyInstaller will look for modules and add paths with scripts to the list of + paths. + + :param spec_pathex: Additional paths defined defined in .spec file. + :param scripts: Scripts to create executable from. + :return: list of updated paths + """ + # Based on main supplied script - add top-level modules directory to PYTHONPATH. + # Sometimes the main app script is not top-level module but submodule like 'mymodule.mainscript.py'. + # In that case PyInstaller will not be able find modules in the directory containing 'mymodule'. + # Add this directory to PYTHONPATH so PyInstaller could find it. + pathex = [] + # Add scripts paths first. + for script in scripts: + logger.debug('script: %s' % script) + script_toplevel_dir = get_path_to_toplevel_modules(script) + if script_toplevel_dir: + pathex.append(script_toplevel_dir) + # Append paths from .spec. + if spec_pathex is not None: + pathex.extend(spec_pathex) + # Normalize paths in pathex and make them absolute. + return [absnormpath(p) for p in pathex] + + def _check_guts(self, data, last_build): + if Target._check_guts(self, data, last_build): + return True + for filename in self.inputs: + if mtime(filename) > last_build: + logger.info("Building because %s changed", filename) + return True + # Now we know that none of the input parameters and none of the input files has changed. So take the values + # that were calculated / analyzed in the last run and store them in `self`. These TOC lists should already + # be normalized. + self.scripts = data['scripts'] + self.pure = data['pure'] + self.binaries = data['binaries'] + self.zipfiles = data['zipfiles'] + self.zipped_data = data['zipped_data'] + self.datas = data['datas'] + + return False + + def assemble(self): + """ + This method is the MAIN method for finding all necessary files to be bundled. + """ + from PyInstaller.config import CONF + + logger.info("Running Analysis %s", self.tocbasename) + logger.info("Target bytecode optimization level: %d", self.optimize) + + for m in self.excludes: + logger.debug("Excluding module '%s'" % m) + self.graph = initialize_modgraph(excludes=self.excludes, user_hook_dirs=self.hookspath) + + # Initialize `binaries` and `datas` with `_input_binaries` and `_input_datas`. Make sure to copy the lists + # to prevent modifications of original lists, which we need to store in original form for guts comparison. + self.datas = [entry for entry in self._input_datas] + self.binaries = [entry for entry in self._input_binaries] + + # TODO: find a better place where to put 'base_library.zip' and when to created it. + # For Python 3 it is necessary to create file 'base_library.zip' containing core Python modules. In Python 3 + # some built-in modules are written in pure Python. base_library.zip is a way how to have those modules as + # "built-in". + libzip_filename = os.path.join(CONF['workpath'], 'base_library.zip') + create_py3_base_library(libzip_filename, graph=self.graph) + # Bundle base_library.zip as data file. + # Data format of TOC item: ('relative_path_in_dist_dir', 'absolute_path_on_disk', 'DATA') + self.datas.append((os.path.basename(libzip_filename), libzip_filename, 'DATA')) + + # Expand sys.path of module graph. The attribute is the set of paths to use for imports: sys.path, plus our + # loader, plus other paths from e.g. --path option). + self.graph.path = self.pathex + self.graph.path + + # Scan for legacy namespace packages. + self.graph.scan_legacy_namespace_packages() + + # Search for python shared library, which we need to collect into frozen application. + logger.info('Looking for Python shared library...') + python_lib = bindepend.get_python_library_path() + if python_lib is None: + from PyInstaller.exceptions import PythonLibraryNotFoundError + raise PythonLibraryNotFoundError() + logger.info('Using Python shared library: %s', python_lib) + if is_darwin and osxutils.is_framework_bundle_lib(python_lib): + # If python library is located in macOS .framework bundle, collect the bundle, and create symbolic link to + # top-level directory. + src_path = pathlib.PurePath(python_lib) + dst_path = pathlib.PurePath(src_path.relative_to(src_path.parent.parent.parent.parent)) + self.binaries.append((str(dst_path), str(src_path), 'BINARY')) + self.binaries.append((os.path.basename(python_lib), str(dst_path), 'SYMLINK')) + else: + self.binaries.append((os.path.basename(python_lib), python_lib, 'BINARY')) + + # -- Module graph. -- + # + # Construct the module graph of import relationships between modules required by this user's application. For + # each entry point (top-level user-defined Python script), all imports originating from this entry point are + # recursively parsed into a subgraph of the module graph. This subgraph is then connected to this graph's root + # node, ensuring imported module nodes will be reachable from the root node -- which is is (arbitrarily) chosen + # to be the first entry point's node. + + # List of graph nodes corresponding to program scripts. + program_scripts = [] + + # Assume that if the script does not exist, Modulegraph will raise error. Save the graph nodes of each in + # sequence. + for script in self.inputs: + logger.info("Analyzing %s", script) + program_scripts.append(self.graph.add_script(script)) + + # Analyze the script's hidden imports (named on the command line) + self.graph.add_hiddenimports(self.hiddenimports) + + # -- Post-graph hooks. -- + self.graph.process_post_graph_hooks(self) + + # Update 'binaries' and 'datas' TOC lists with entries collected from hooks. + self.binaries += self.graph.make_hook_binaries_toc() + self.datas += self.graph.make_hook_datas_toc() + + # We do not support zipped eggs anymore (PyInstaller v6.0), so `zipped_data` and `zipfiles` are always empty. + self.zipped_data = [] + self.zipfiles = [] + + # -- Automatic binary vs. data reclassification. -- + # + # At this point, `binaries` and `datas` contain TOC entries supplied by user via input arguments, and by hooks + # that were ran during the analysis. Neither source can be fully trusted regarding the DATA vs BINARY + # classification (no thanks to our hookutils not being 100% reliable, either!). Therefore, inspect the files and + # automatically reclassify them as necessary. + # + # The proper classification is important especially for collected binaries - to ensure that they undergo binary + # dependency analysis and platform-specific binary processing. On macOS, the .app bundle generation code also + # depends on files to be properly classified. + # + # For entries added to `binaries` and `datas` after this point, we trust their typecodes due to the nature of + # their origin. + combined_toc = normalize_toc(self.datas + self.binaries) + + logger.info('Performing binary vs. data reclassification (%d entries)', len(combined_toc)) + + self.datas = [] + self.binaries = [] + + for dest_name, src_name, typecode in combined_toc: + # Returns 'BINARY' or 'DATA', or None if file cannot be classified. + detected_typecode = bindepend.classify_binary_vs_data(src_name) + if detected_typecode is not None: + if detected_typecode != typecode: + logger.debug( + "Reclassifying collected file %r from %s to %s...", src_name, typecode, detected_typecode + ) + typecode = detected_typecode + + # Put back into corresponding TOC list. + if typecode in {'BINARY', 'EXTENSION'}: + self.binaries.append((dest_name, src_name, typecode)) + else: + self.datas.append((dest_name, src_name, typecode)) + + # -- Look for dlls that are imported by Python 'ctypes' module. -- + # First get code objects of all modules that import 'ctypes'. + logger.info('Looking for ctypes DLLs') + # dict like: {'module1': code_obj, 'module2': code_obj} + ctypes_code_objs = self.graph.get_code_using("ctypes") + + for name, co in ctypes_code_objs.items(): + # Get dlls that might be needed by ctypes. + logger.debug('Scanning %s for ctypes-based references to shared libraries', name) + try: + ctypes_binaries = scan_code_for_ctypes(co) + # As this scan happens after automatic binary-vs-data classification, we need to validate the binaries + # ourselves, just in case. + for dest_name, src_name, typecode in set(ctypes_binaries): + # Allow for `None` in case re-classification is not supported on the given platform. + if bindepend.classify_binary_vs_data(src_name) not in (None, 'BINARY'): + logger.warning("Ignoring %s found via ctypes - not a valid binary!", src_name) + continue + self.binaries.append((dest_name, src_name, typecode)) + except Exception as ex: + raise RuntimeError(f"Failed to scan the module '{name}'. This is a bug. Please report it.") from ex + + self.datas.extend((dest, source, "DATA") + for (dest, source) in format_binaries_and_datas(self.graph.metadata_required())) + + # Analyze run-time hooks. + rhtook_scripts = self.graph.analyze_runtime_hooks(self.custom_runtime_hooks) + + # -- Extract the nodes of the graph as TOCs for further processing. -- + + # Initialize the scripts list: run-time hooks (custom ones, followed by regular ones), followed by program + # script(s). + + # We do not optimize bytecode of run-time hooks. + rthook_toc = self.graph.nodes_to_toc(rhtook_scripts) + + # Override the typecode of program script(s) to include bytecode optimization level. + program_toc = self.graph.nodes_to_toc(program_scripts) + optim_typecode = {0: 'PYSOURCE', 1: 'PYSOURCE-1', 2: 'PYSOURCE-2'}[self.optimize] + program_toc = [(name, src_path, optim_typecode) for name, src_path, typecode in program_toc] + + self.scripts = rthook_toc + program_toc + self.scripts = normalize_toc(self.scripts) # Should not really contain duplicates, but just in case... + + # Extend the binaries list with all the Extensions modulegraph has found. + self.binaries += self.graph.make_binaries_toc() + + # Convert extension module names into full filenames, and append suffix. Ensure that extensions that come from + # the lib-dynload are collected into _MEIPASS/lib-dynload instead of directly into _MEIPASS. + for idx, (dest, source, typecode) in enumerate(self.binaries): + if typecode != 'EXTENSION': + continue + + # Convert to full filename and append suffix + dest, source, typecode = add_suffix_to_extension(dest, source, typecode) + + # Divert into lib-dyload, if necessary (i.e., if file comes from lib-dynload directory) and its destination + # path does not already have a directory prefix. + src_parent = os.path.basename(os.path.dirname(source)) + if src_parent == 'lib-dynload' and not os.path.dirname(os.path.normpath(dest)): + dest = os.path.join('lib-dynload', dest) + + # Update + self.binaries[idx] = (dest, source, typecode) + + # Perform initial normalization of `datas` and `binaries` + self.datas = normalize_toc(self.datas) + self.binaries = normalize_toc(self.binaries) + + # Post-process GLib schemas + self.datas = compile_glib_schema_files(self.datas, os.path.join(CONF['workpath'], "_pyi_gschema_compilation")) + self.datas = normalize_toc(self.datas) + + # Process the pure-python modules list. Depending on the collection mode, these entries end up either in "pure" + # list for collection into the PYZ archive, or in the "datas" list for collection as external data files. + assert len(self.pure) == 0 + pure_pymodules_toc = self.graph.make_pure_toc() + + # Merge package collection mode settings from .spec file. These are applied last, so they override the + # settings previously applied by hooks. + self.graph._module_collection_mode.update(self.module_collection_mode) + logger.debug("Module collection settings: %r", self.graph._module_collection_mode) + + # If target bytecode optimization level matches the run-time bytecode optimization level (i.e., of the running + # build process), we can re-use the modulegraph's code-object cache. + if self.optimize == sys.flags.optimize: + logger.debug( + "Target optimization level %d matches run-time optimization level %d - using modulegraph's code-object " + "cache.", + self.optimize, + sys.flags.optimize, + ) + code_cache = self.graph.get_code_objects() + else: + logger.debug( + "Target optimization level %d differs from run-time optimization level %d - ignoring modulegraph's " + "code-object cache.", + self.optimize, + sys.flags.optimize, + ) + code_cache = None + + pycs_dir = os.path.join(CONF['workpath'], 'localpycs') + optim_level = self.optimize # We could extend this with per-module settings, similar to `collect_mode`. + for name, src_path, typecode in pure_pymodules_toc: + assert typecode == 'PYMODULE' + collect_mode = _get_module_collection_mode(self.graph._module_collection_mode, name, self.noarchive) + + # Collect byte-compiled .pyc into PYZ archive. Embed optimization level into typecode. + if _ModuleCollectionMode.PYZ in collect_mode: + optim_typecode = {0: 'PYMODULE', 1: 'PYMODULE-1', 2: 'PYMODULE-2'}[optim_level] + self.pure.append((name, src_path, optim_typecode)) + + # Pure namespace packages have no source path, and cannot be collected as external data file. + if src_path in (None, '-'): + continue + + # Collect source .py file as external data file + if _ModuleCollectionMode.PY in collect_mode: + dest_path = name.replace('.', os.sep) + # Special case: packages have an implied `__init__` filename that needs to be added. + basename, ext = os.path.splitext(os.path.basename(src_path)) + if basename == '__init__': + dest_path += os.sep + '__init__' + ext + else: + dest_path += ext + self.datas.append((dest_path, src_path, "DATA")) + + # Collect byte-compiled .pyc file as external data file + if _ModuleCollectionMode.PYC in collect_mode: + dest_path = name.replace('.', os.sep) + # Special case: packages have an implied `__init__` filename that needs to be added. + basename, ext = os.path.splitext(os.path.basename(src_path)) + if basename == '__init__': + dest_path += os.sep + '__init__' + # Append the extension for the compiled result. In python 3.5 (PEP-488) .pyo files were replaced by + # .opt-1.pyc and .opt-2.pyc. However, it seems that for bytecode-only module distribution, we always + # need to use the .pyc extension. + dest_path += '.pyc' + + # Compile - use optimization-level-specific sub-directory in local working directory. + obj_path = compile_pymodule( + name, + src_path, + workpath=os.path.join(pycs_dir, str(optim_level)), + optimize=optim_level, + code_cache=code_cache, + ) + + self.datas.append((dest_path, obj_path, "DATA")) + + # Normalize list of pure-python modules (these will end up in PYZ archive, so use specific normalization). + self.pure = normalize_pyz_toc(self.pure) + + # Associate the `pure` TOC list instance with code cache in the global `CONF`; this is used by `PYZ` writer + # to obtain modules' code from cache instead + # + # (NOTE: back when `pure` was an instance of `TOC` class, the code object was passed by adding an attribute + # to the `pure` itself; now that `pure` is plain `list`, we cannot do that anymore. But the association via + # object ID should have the same semantics as the added attribute). + from PyInstaller.config import CONF + global_code_cache_map = CONF['code_cache'] + global_code_cache_map[id(self.pure)] = code_cache + + # Add remaining binary dependencies - analyze Python C-extensions and what DLLs they depend on. + # + # Up until this point, we did very best not to import the packages into the main process. However, a package + # may set up additional library search paths during its import (e.g., by modifying PATH or calling the + # add_dll_directory() function on Windows, or modifying LD_LIBRARY_PATH on Linux). In order to reliably + # discover dynamic libraries, we therefore require an environment with all packages imported. We achieve that + # by gathering list of all collected packages, and spawn an isolated process, in which we first import all + # the packages from the list, and then perform search for dynamic libraries. + logger.info('Looking for dynamic libraries') + + collected_packages = self.graph.get_collected_packages() + self.binaries.extend( + find_binary_dependencies(self.binaries, collected_packages, self.graph._bindepend_symlink_suppression) + ) + + # Apply work-around for (potential) binaries collected from `pywin32` package... + if is_win: + self.binaries = postprocess_binaries_toc_pywin32(self.binaries) + # With anaconda, we need additional work-around... + if is_conda: + self.binaries = postprocess_binaries_toc_pywin32_anaconda(self.binaries) + + # On linux, check for HMAC files accompanying shared library files and, if available, collect them. + # These are present on Fedora and RHEL, and are used in FIPS-enabled configurations to ensure shared + # library's file integrity. + if is_linux: + for dest_name, src_name, typecode in self.binaries: + if typecode not in {'BINARY', 'EXTENSION'}: + continue # Skip symbolic links + + src_lib_path = pathlib.Path(src_name) + + # Check for .name.hmac file next to the shared library. + src_hmac_path = src_lib_path.with_name(f".{src_lib_path.name}.hmac") + if src_hmac_path.is_file(): + dest_hmac_path = pathlib.PurePath(dest_name).with_name(src_hmac_path.name) + self.datas.append((str(dest_hmac_path), str(src_hmac_path), 'DATA')) + + # Alternatively, check the fipscheck directory: fipscheck/name.hmac + src_hmac_path = src_lib_path.parent / "fipscheck" / f"{src_lib_path.name}.hmac" + if src_hmac_path.is_file(): + dest_hmac_path = pathlib.PurePath("fipscheck") / src_hmac_path.name + self.datas.append((str(dest_hmac_path), str(src_hmac_path), 'DATA')) + + # Similarly, look for .chk files that are used by NSS libraries. + src_chk_path = src_lib_path.with_suffix(".chk") + if src_chk_path.is_file(): + dest_chk_path = pathlib.PurePath(dest_name).with_name(src_chk_path.name) + self.datas.append((str(dest_chk_path), str(src_chk_path), 'DATA')) + + # Final normalization of `datas` and `binaries`: + # - normalize both TOCs together (to avoid having duplicates across the lists) + # - process the combined normalized TOC for symlinks + # - split back into `binaries` (BINARY, EXTENSION) and `datas` (everything else) + combined_toc = normalize_toc(self.datas + self.binaries) + combined_toc = toc_process_symbolic_links(combined_toc) + + # On macOS, look for binaries collected from .framework bundles, and collect their Info.plist files. + if is_darwin: + combined_toc += osxutils.collect_files_from_framework_bundles(combined_toc) + + self.datas = [] + self.binaries = [] + for entry in combined_toc: + dest_name, src_name, typecode = entry + if typecode in {'BINARY', 'EXTENSION'}: + self.binaries.append(entry) + else: + self.datas.append(entry) + + # On macOS, the Finder app seems to litter visited directories with `.DS_Store` files. These cause issues with + # codesigning when placed in mixed-content directories, where our .app bundle generator cross-links data files + # from `Resources` to `Frameworks` tree, and the `codesign` utility explicitly forbids a `.DS_Store` file to be + # a symbolic link. + # But there is no reason for `.DS_Store` files to be collected in the first place, so filter them out. + if is_darwin: + self.datas = [(dest_name, src_name, typecode) for dest_name, src_name, typecode in self.datas + if os.path.basename(src_name) != '.DS_Store'] + + # Write warnings about missing modules. + self._write_warnings() + # Write debug information about the graph + self._write_graph_debug() + + # On macOS, check the SDK version of the binaries to be collected, and warn when the SDK version is either + # invalid or too low. Such binaries will likely refuse to be loaded when hardened runtime is enabled and + # while we cannot do anything about it, we can at least warn the user about it. + # See: https://developer.apple.com/forums/thread/132526 + if is_darwin: + binaries_with_invalid_sdk = [] + for dest_name, src_name, typecode in self.binaries: + try: + sdk_version = osxutils.get_macos_sdk_version(src_name) + except Exception: + logger.warning("Failed to query macOS SDK version of %r!", src_name, exc_info=True) + binaries_with_invalid_sdk.append((dest_name, src_name, "unavailable")) + continue + + if sdk_version < (10, 9, 0): + binaries_with_invalid_sdk.append((dest_name, src_name, sdk_version)) + if binaries_with_invalid_sdk: + logger.warning("Found one or more binaries with invalid or incompatible macOS SDK version:") + for dest_name, src_name, sdk_version in binaries_with_invalid_sdk: + logger.warning(" * %r, collected as %r; version: %r", src_name, dest_name, sdk_version) + logger.warning("These binaries will likely cause issues with code-signing and hardened runtime!") + + def _write_warnings(self): + """ + Write warnings about missing modules. Get them from the graph and use the graph to figure out who tried to + import them. + """ + def dependency_description(name, dep_info): + if not dep_info or dep_info == 'direct': + imptype = 0 + else: + imptype = (dep_info.conditional + 2 * dep_info.function + 4 * dep_info.tryexcept) + return '%s (%s)' % (name, IMPORT_TYPES[imptype]) + + from PyInstaller.config import CONF + miss_toc = self.graph.make_missing_toc() + with open(CONF['warnfile'], 'w', encoding='utf-8') as wf: + wf.write(WARNFILE_HEADER) + for (n, p, status) in miss_toc: + importers = self.graph.get_importers(n) + print( + status, + 'module named', + n, + '- imported by', + ', '.join(dependency_description(name, data) for name, data in importers), + file=wf + ) + logger.info("Warnings written to %s", CONF['warnfile']) + + def _write_graph_debug(self): + """ + Write a xref (in html) and with `--log-level DEBUG` a dot-drawing of the graph. + """ + from PyInstaller.config import CONF + with open(CONF['xref-file'], 'w', encoding='utf-8') as fh: + self.graph.create_xref(fh) + logger.info("Graph cross-reference written to %s", CONF['xref-file']) + if logger.getEffectiveLevel() > logging.DEBUG: + return + # The `DOT language's `_ default character encoding (see the end + # of the linked page) is UTF-8. + with open(CONF['dot-file'], 'w', encoding='utf-8') as fh: + self.graph.graphreport(fh) + logger.info("Graph drawing written to %s", CONF['dot-file']) + + def exclude_system_libraries(self, list_of_exceptions=None): + """ + This method may be optionally called from the spec file to exclude any system libraries from the list of + binaries other than those containing the shell-style wildcards in list_of_exceptions. Those that match + '*python*' or are stored under 'lib-dynload' are always treated as exceptions and not excluded. + """ + + self.binaries = [ + entry for entry in self.binaries if _should_include_system_binary(entry, list_of_exceptions or []) + ] + + +class ExecutableBuilder: + """ + Class that constructs the executable. + """ + # TODO wrap the 'main' and 'build' function into this class. + + +def build(spec, distpath, workpath, clean_build): + """ + Build the executable according to the created SPEC file. + """ + from PyInstaller.config import CONF + + # Ensure starting tilde in distpath / workpath is expanded into user's home directory. This is to work around for + # tilde not being expanded when using ˙--workpath=~/path/abc` instead of ˙--workpath ~/path/abc` (or when the path + # argument is quoted). See https://github.com/pyinstaller/pyinstaller/issues/696 + distpath = os.path.abspath(os.path.expanduser(distpath)) + workpath = os.path.abspath(os.path.expanduser(workpath)) + + CONF['spec'] = os.path.abspath(spec) + CONF['specpath'], CONF['specnm'] = os.path.split(CONF['spec']) + CONF['specnm'] = os.path.splitext(CONF['specnm'])[0] + + # Add 'specname' to workpath and distpath if they point to PyInstaller homepath. + if os.path.dirname(distpath) == HOMEPATH: + distpath = os.path.join(HOMEPATH, CONF['specnm'], os.path.basename(distpath)) + CONF['distpath'] = distpath + if os.path.dirname(workpath) == HOMEPATH: + workpath = os.path.join(HOMEPATH, CONF['specnm'], os.path.basename(workpath), CONF['specnm']) + else: + workpath = os.path.join(workpath, CONF['specnm']) + CONF['workpath'] = workpath + + CONF['warnfile'] = os.path.join(workpath, 'warn-%s.txt' % CONF['specnm']) + CONF['dot-file'] = os.path.join(workpath, 'graph-%s.dot' % CONF['specnm']) + CONF['xref-file'] = os.path.join(workpath, 'xref-%s.html' % CONF['specnm']) + + CONF['code_cache'] = dict() + + # Clean PyInstaller cache (CONF['cachedir']) and temporary files (workpath) to be able start a clean build. + if clean_build: + logger.info('Removing temporary files and cleaning cache in %s', CONF['cachedir']) + for pth in (CONF['cachedir'], workpath): + if os.path.exists(pth): + # Remove all files in 'pth'. + for f in glob.glob(pth + '/*'): + # Remove dirs recursively. + if os.path.isdir(f): + shutil.rmtree(f) + else: + os.remove(f) + + # Create DISTPATH and workpath if they does not exist. + for pth in (CONF['distpath'], CONF['workpath']): + os.makedirs(pth, exist_ok=True) + + # Construct NAMESPACE for running the Python code from .SPEC file. + # NOTE: Passing NAMESPACE allows to avoid having global variables in this module and makes isolated environment for + # running tests. + # NOTE: Defining NAMESPACE allows to map any class to a apecific name for .SPEC. + # FIXME: Some symbols might be missing. Add them if there are some failures. + # TODO: What from this .spec API is deprecated and could be removed? + spec_namespace = { + # Set of global variables that can be used while processing .spec file. Some of them act as configuration + # options. + 'DISTPATH': CONF['distpath'], + 'HOMEPATH': HOMEPATH, + 'SPEC': CONF['spec'], + 'specnm': CONF['specnm'], + 'SPECPATH': CONF['specpath'], + 'WARNFILE': CONF['warnfile'], + 'workpath': CONF['workpath'], + # PyInstaller classes for .spec. + 'TOC': TOC, # Kept for backward compatibility even though `TOC` class is deprecated. + 'Analysis': Analysis, + 'BUNDLE': BUNDLE, + 'COLLECT': COLLECT, + 'EXE': EXE, + 'MERGE': MERGE, + 'PYZ': PYZ, + 'Tree': Tree, + 'Splash': Splash, + # Python modules available for .spec. + 'os': os, + } + + # Execute the specfile. Read it as a binary file... + try: + with open(spec, 'rb') as f: + # ... then let Python determine the encoding, since ``compile`` accepts byte strings. + code = compile(f.read(), spec, 'exec') + except FileNotFoundError: + raise SystemExit(f'Spec file "{spec}" not found!') + exec(code, spec_namespace) + + +def __add_options(parser): + parser.add_argument( + "--distpath", + metavar="DIR", + default=DEFAULT_DISTPATH, + help="Where to put the bundled app (default: ./dist)", + ) + parser.add_argument( + '--workpath', + default=DEFAULT_WORKPATH, + help="Where to put all the temporary work files, .log, .pyz and etc. (default: ./build)", + ) + parser.add_argument( + '-y', + '--noconfirm', + action="store_true", + default=False, + help="Replace output directory (default: %s) without asking for confirmation" % + os.path.join('SPECPATH', 'dist', 'SPECNAME'), + ) + parser.add_argument( + '--upx-dir', + default=None, + help="Path to UPX utility (default: search the execution path)", + ) + parser.add_argument( + '--clean', + dest='clean_build', + action='store_true', + default=False, + help="Clean PyInstaller cache and remove temporary files before building.", + ) + + +def main( + pyi_config, + specfile, + noconfirm=False, + distpath=DEFAULT_DISTPATH, + workpath=DEFAULT_WORKPATH, + upx_dir=None, + clean_build=False, + **kw +): + from PyInstaller.config import CONF + CONF['noconfirm'] = noconfirm + + # If configuration dict is supplied - skip configuration step. + if pyi_config is None: + import PyInstaller.configure as configure + CONF.update(configure.get_config(upx_dir=upx_dir)) + else: + CONF.update(pyi_config) + + CONF['ui_admin'] = kw.get('ui_admin', False) + CONF['ui_access'] = kw.get('ui_uiaccess', False) + + build(specfile, distpath, workpath, clean_build) diff --git a/venv/Lib/site-packages/PyInstaller/building/datastruct.py b/venv/Lib/site-packages/PyInstaller/building/datastruct.py new file mode 100644 index 0000000..ca16286 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/building/datastruct.py @@ -0,0 +1,459 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +import os +import pathlib +import warnings + +from PyInstaller import log as logging +from PyInstaller.building.utils import _check_guts_eq +from PyInstaller.utils import misc + +logger = logging.getLogger(__name__) + + +def unique_name(entry): + """ + Return the filename used to enforce uniqueness for the given TOC entry. + + Parameters + ---------- + entry : tuple + + Returns + ------- + unique_name: str + """ + name, path, typecode = entry + if typecode in ('BINARY', 'DATA', 'EXTENSION', 'DEPENDENCY'): + name = os.path.normcase(name) + + return name + + +# This class is deprecated and has been replaced by plain lists with explicit normalization (de-duplication) via +# `normalize_toc` and `normalize_pyz_toc` helper functions. +class TOC(list): + """ + TOC (Table of Contents) class is a list of tuples of the form (name, path, typecode). + + typecode name path description + -------------------------------------------------------------------------------------- + EXTENSION Python internal name. Full path name in build. Extension module. + PYSOURCE Python internal name. Full path name in build. Script. + PYMODULE Python internal name. Full path name in build. Pure Python module (including __init__ modules). + PYZ Runtime name. Full path name in build. A .pyz archive (ZlibArchive data structure). + PKG Runtime name. Full path name in build. A .pkg archive (Carchive data structure). + BINARY Runtime name. Full path name in build. Shared library. + DATA Runtime name. Full path name in build. Arbitrary files. + OPTION The option. Unused. Python runtime option (frozen into executable). + + A TOC contains various types of files. A TOC contains no duplicates and preserves order. + PyInstaller uses TOC data type to collect necessary files bundle them into an executable. + """ + def __init__(self, initlist=None): + super().__init__() + + # Deprecation warning + warnings.warn( + "TOC class is deprecated. Use a plain list of 3-element tuples instead.", + DeprecationWarning, + stacklevel=2, + ) + + self.filenames = set() + if initlist: + for entry in initlist: + self.append(entry) + + def append(self, entry): + if not isinstance(entry, tuple): + logger.info("TOC found a %s, not a tuple", entry) + raise TypeError("Expected tuple, not %s." % type(entry).__name__) + + unique = unique_name(entry) + + if unique not in self.filenames: + self.filenames.add(unique) + super().append(entry) + + def insert(self, pos, entry): + if not isinstance(entry, tuple): + logger.info("TOC found a %s, not a tuple", entry) + raise TypeError("Expected tuple, not %s." % type(entry).__name__) + unique = unique_name(entry) + + if unique not in self.filenames: + self.filenames.add(unique) + super().insert(pos, entry) + + def __add__(self, other): + result = TOC(self) + result.extend(other) + return result + + def __radd__(self, other): + result = TOC(other) + result.extend(self) + return result + + def __iadd__(self, other): + for entry in other: + self.append(entry) + return self + + def extend(self, other): + # TODO: look if this can be done more efficient with out the loop, e.g. by not using a list as base at all. + for entry in other: + self.append(entry) + + def __sub__(self, other): + # Construct new TOC with entries not contained in the other TOC + other = TOC(other) + return TOC([entry for entry in self if unique_name(entry) not in other.filenames]) + + def __rsub__(self, other): + result = TOC(other) + return result.__sub__(self) + + def __setitem__(self, key, value): + if isinstance(key, slice): + if key == slice(None, None, None): + # special case: set the entire list + self.filenames = set() + self.clear() + self.extend(value) + return + else: + raise KeyError("TOC.__setitem__ doesn't handle slices") + + else: + old_value = self[key] + old_name = unique_name(old_value) + self.filenames.remove(old_name) + + new_name = unique_name(value) + if new_name not in self.filenames: + self.filenames.add(new_name) + super(TOC, self).__setitem__(key, value) + + +class Target: + invcnum = 0 + + def __init__(self): + from PyInstaller.config import CONF + + # Get a (per class) unique number to avoid conflicts between toc objects + self.invcnum = self.__class__.invcnum + self.__class__.invcnum += 1 + self.tocfilename = os.path.join(CONF['workpath'], '%s-%02d.toc' % (self.__class__.__name__, self.invcnum)) + self.tocbasename = os.path.basename(self.tocfilename) + self.dependencies = [] + + def __postinit__(self): + """ + Check if the target need to be rebuild and if so, re-assemble. + + `__postinit__` is to be called at the end of `__init__` of every subclass of Target. `__init__` is meant to + setup the parameters and `__postinit__` is checking if rebuild is required and in case calls `assemble()` + """ + logger.info("checking %s", self.__class__.__name__) + data = None + last_build = misc.mtime(self.tocfilename) + if last_build == 0: + logger.info("Building %s because %s is non existent", self.__class__.__name__, self.tocbasename) + else: + try: + data = misc.load_py_data_struct(self.tocfilename) + except Exception: + logger.info("Building because %s is bad", self.tocbasename) + else: + # create a dict for easier access + data = dict(zip((g[0] for g in self._GUTS), data)) + # assemble if previous data was not found or is outdated + if not data or self._check_guts(data, last_build): + self.assemble() + self._save_guts() + + _GUTS = [] + + def _check_guts(self, data, last_build): + """ + Returns True if rebuild/assemble is required. + """ + if len(data) != len(self._GUTS): + logger.info("Building because %s is bad", self.tocbasename) + return True + for attr, func in self._GUTS: + if func is None: + # no check for this value + continue + if func(attr, data[attr], getattr(self, attr), last_build): + return True + return False + + def _save_guts(self): + """ + Save the input parameters and the work-product of this run to maybe avoid regenerating it later. + """ + data = tuple(getattr(self, g[0]) for g in self._GUTS) + misc.save_py_data_struct(self.tocfilename, data) + + +class Tree(Target, list): + """ + This class is a way of creating a TOC (Table of Contents) list that describes some or all of the files within a + directory. + """ + def __init__(self, root=None, prefix=None, excludes=None, typecode='DATA'): + """ + root + The root of the tree (on the build system). + prefix + Optional prefix to the names of the target system. + excludes + A list of names to exclude. Two forms are allowed: + + name + Files with this basename will be excluded (do not include the path). + *.ext + Any file with the given extension will be excluded. + typecode + The typecode to be used for all files found in this tree. See the TOC class for for information about + the typcodes. + """ + Target.__init__(self) + list.__init__(self) + self.root = root + self.prefix = prefix + self.excludes = excludes + self.typecode = typecode + if excludes is None: + self.excludes = [] + self.__postinit__() + + _GUTS = ( # input parameters + ('root', _check_guts_eq), + ('prefix', _check_guts_eq), + ('excludes', _check_guts_eq), + ('typecode', _check_guts_eq), + ('data', None), # tested below + # no calculated/analysed values + ) + + def _check_guts(self, data, last_build): + if Target._check_guts(self, data, last_build): + return True + # Walk the collected directories as check if they have been changed - which means files have been added or + # removed. There is no need to check for the files, since `Tree` is only about the directory contents (which is + # the list of files). + stack = [data['root']] + while stack: + d = stack.pop() + if misc.mtime(d) > last_build: + logger.info("Building %s because directory %s changed", self.tocbasename, d) + return True + for nm in os.listdir(d): + path = os.path.join(d, nm) + if os.path.isdir(path): + stack.append(path) + self[:] = data['data'] # collected files + return False + + def _save_guts(self): + # Use the attribute `data` to save the list + self.data = self + super()._save_guts() + del self.data + + def assemble(self): + logger.info("Building Tree %s", self.tocbasename) + stack = [(self.root, self.prefix)] + excludes = set() + xexcludes = set() + for name in self.excludes: + if name.startswith('*'): + xexcludes.add(name[1:]) + else: + excludes.add(name) + result = [] + while stack: + dir, prefix = stack.pop() + for filename in os.listdir(dir): + if filename in excludes: + continue + ext = os.path.splitext(filename)[1] + if ext in xexcludes: + continue + fullfilename = os.path.join(dir, filename) + if prefix: + resfilename = os.path.join(prefix, filename) + else: + resfilename = filename + if os.path.isdir(fullfilename): + stack.append((fullfilename, resfilename)) + else: + result.append((resfilename, fullfilename, self.typecode)) + self[:] = result + + +def normalize_toc(toc): + # Default priority: 0 + _TOC_TYPE_PRIORITIES = { + # DEPENDENCY entries need to replace original entries, so they need the highest priority. + 'DEPENDENCY': 3, + # SYMLINK entries have higher priority than other regular entries + 'SYMLINK': 2, + # BINARY/EXTENSION entries undergo additional processing, so give them precedence over DATA and other entries. + 'BINARY': 1, + 'EXTENSION': 1, + } + + def _type_case_normalization_fcn(typecode): + # Case-normalize all entries except OPTION. + return typecode not in { + "OPTION", + } + + return _normalize_toc(toc, _TOC_TYPE_PRIORITIES, _type_case_normalization_fcn) + + +def normalize_pyz_toc(toc): + # Default priority: 0 + _TOC_TYPE_PRIORITIES = { + # Ensure that entries with higher optimization level take precedence. + 'PYMODULE-2': 2, + 'PYMODULE-1': 1, + 'PYMODULE': 0, + } + + return _normalize_toc(toc, _TOC_TYPE_PRIORITIES) + + +def _normalize_toc(toc, toc_type_priorities, type_case_normalization_fcn=lambda typecode: False): + options_toc = [] + tmp_toc = dict() + for dest_name, src_name, typecode in toc: + # Exempt OPTION entries from de-duplication processing. Some options might allow being specified multiple times. + if typecode == 'OPTION': + options_toc.append(((dest_name, src_name, typecode))) + continue + + # Always sanitize the dest_name with `os.path.normpath` to remove any local loops with parent directory path + # components. `pathlib` does not seem to offer equivalent functionality. + dest_name = os.path.normpath(dest_name) + + # Normalize the destination name for uniqueness. Use `pathlib.PurePath` to ensure that keys are both + # case-normalized (on OSes where applicable) and directory-separator normalized (just in case). + if type_case_normalization_fcn(typecode): + entry_key = pathlib.PurePath(dest_name) + else: + entry_key = dest_name + + existing_entry = tmp_toc.get(entry_key) + if existing_entry is None: + # Entry does not exist - insert + tmp_toc[entry_key] = (dest_name, src_name, typecode) + else: + # Entry already exists - replace if its typecode has higher priority + _, _, existing_typecode = existing_entry + if toc_type_priorities.get(typecode, 0) > toc_type_priorities.get(existing_typecode, 0): + tmp_toc[entry_key] = (dest_name, src_name, typecode) + + # Return the items as list. The order matches the original order due to python dict maintaining the insertion order. + # The exception are OPTION entries, which are now placed at the beginning of the TOC. + return options_toc + list(tmp_toc.values()) + + +def toc_process_symbolic_links(toc): + """ + Process TOC entries and replace entries whose files are symbolic links with SYMLINK entries (provided original file + is also being collected). + """ + # Dictionary of all destination names, for a fast look-up. + all_dest_files = set([dest_name for dest_name, src_name, typecode in toc]) + + # Process the TOC to create SYMLINK entries + new_toc = [] + for entry in toc: + dest_name, src_name, typecode = entry + + # Skip entries that are already symbolic links + if typecode == 'SYMLINK': + new_toc.append(entry) + continue + + # Skip entries without valid source name (e.g., OPTION) + if not src_name: + new_toc.append(entry) + continue + + # Source path is not a symbolic link (i.e., it is a regular file or directory) + if not os.path.islink(src_name): + new_toc.append(entry) + continue + + # Try preserving the symbolic link, under strict relative-relationship-preservation check + symlink_entry = _try_preserving_symbolic_link(dest_name, src_name, all_dest_files) + + if symlink_entry: + new_toc.append(symlink_entry) + else: + new_toc.append(entry) + + return new_toc + + +def _try_preserving_symbolic_link(dest_name, src_name, all_dest_files): + seen_src_files = set() + + # Set initial values for the loop + ref_src_file = src_name + ref_dest_file = dest_name + + while True: + # Guard against cyclic links... + if ref_src_file in seen_src_files: + break + seen_src_files.add(ref_src_file) + + # Stop when referenced source file is not a symbolic link anymore. + if not os.path.islink(ref_src_file): + break + + # Read the symbolic link's target, but do not fully resolve it using os.path.realpath(), because there might be + # other symbolic links involved as well (for example, /lib64 -> /usr/lib64 whereas we are processing + # /lib64/liba.so -> /lib64/liba.so.1) + symlink_target = os.readlink(ref_src_file) + if os.path.isabs(symlink_target): + break # We support only relative symbolic links. + + ref_dest_file = os.path.join(os.path.dirname(ref_dest_file), symlink_target) + ref_dest_file = os.path.normpath(ref_dest_file) # remove any '..' + + ref_src_file = os.path.join(os.path.dirname(ref_src_file), symlink_target) + ref_src_file = os.path.normpath(ref_src_file) # remove any '..' + + # Check if referenced destination file is valid (i.e., we are collecting a file under referenced name). + if ref_dest_file in all_dest_files: + # Sanity check: original source name and current referenced source name must, after complete resolution, + # point to the same file. + if os.path.realpath(src_name) == os.path.realpath(ref_src_file): + # Compute relative link for the destination file (might be modified, if we went over non-collected + # intermediate links). + rel_link = os.path.relpath(ref_dest_file, os.path.dirname(dest_name)) + return dest_name, rel_link, 'SYMLINK' + + # If referenced destination is not valid, do another iteration in case we are dealing with chained links and we + # are not collecting an intermediate link... + + return None diff --git a/venv/Lib/site-packages/PyInstaller/building/icon.py b/venv/Lib/site-packages/PyInstaller/building/icon.py new file mode 100644 index 0000000..de298f2 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/building/icon.py @@ -0,0 +1,90 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2022-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) +#----------------------------------------------------------------------------- + +from typing import Tuple + +import os +import hashlib + + +def normalize_icon_type(icon_path: str, allowed_types: Tuple[str], convert_type: str, workpath: str) -> str: + """ + Returns a valid icon path or raises an Exception on error. + Ensures that the icon exists, and, if necessary, attempts to convert it to correct OS-specific format using Pillow. + + Takes: + icon_path - the icon given by the user + allowed_types - a tuple of icon formats that should be allowed through + EX: ("ico", "exe") + convert_type - the type to attempt conversion too if necessary + EX: "icns" + workpath - the temp directory to save any newly generated image files + """ + + # explicitly error if file not found + if not os.path.exists(icon_path): + raise FileNotFoundError(f"Icon input file {icon_path} not found") + + _, extension = os.path.splitext(icon_path) + extension = extension[1:] # get rid of the "." in ".whatever" + + # if the file is already in the right format, pass it back unchanged + if extension in allowed_types: + # Check both the suffix and the header of the file to guard against the user confusing image types. + signatures = hex_signatures[extension] + with open(icon_path, "rb") as f: + header = f.read(max(len(s) for s in signatures)) + if any(list(header)[:len(s)] == s for s in signatures): + return icon_path + + # The icon type is wrong! Let's try and import PIL + try: + from PIL import Image as PILImage + import PIL + + except ImportError: + raise ValueError( + f"Received icon image '{icon_path}' which exists but is not in the correct format. On this platform, " + f"only {allowed_types} images may be used as icons. If Pillow is installed, automatic conversion will " + f"be attempted. Please install Pillow or convert your '{extension}' file to one of {allowed_types} " + f"and try again." + ) + + # Let's try to use PIL to convert the icon file type + try: + _generated_name = f"generated-{hashlib.sha256(icon_path.encode()).hexdigest()}.{convert_type}" + generated_icon = os.path.join(workpath, _generated_name) + with PILImage.open(icon_path) as im: + # If an image uses a custom palette + transparency, convert it to RGBA for a better alpha mask depth. + if im.mode == "P" and im.info.get("transparency", None) is not None: + # The bit depth of the alpha channel will be higher, and the images will look better when eventually + # scaled to multiple sizes (16,24,32,..) for the ICO format for example. + im = im.convert("RGBA") + im.save(generated_icon) + icon_path = generated_icon + except PIL.UnidentifiedImageError: + raise ValueError( + f"Something went wrong converting icon image '{icon_path}' to '.{convert_type}' with Pillow, " + f"perhaps the image format is unsupported. Try again with a different file or use a file that can " + f"be used without conversion on this platform: {allowed_types}" + ) + + return icon_path + + +# Possible initial bytes of icon types PyInstaller needs to be able to recognise. +# Taken from: https://en.wikipedia.org/wiki/List_of_file_signatures +hex_signatures = { + "png": [[0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]], + "exe": [[0x4D, 0x5A], [0x5A, 0x4D]], + "ico": [[0x00, 0x00, 0x01, 0x00]], + "icns": [[0x69, 0x63, 0x6e, 0x73]], +} diff --git a/venv/Lib/site-packages/PyInstaller/building/makespec.py b/venv/Lib/site-packages/PyInstaller/building/makespec.py new file mode 100644 index 0000000..98dac8b --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/building/makespec.py @@ -0,0 +1,905 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- +""" +Automatically build spec files containing a description of the project. +""" + +import argparse +import os +import re +import sys + +from PyInstaller import DEFAULT_SPECPATH, HOMEPATH +from PyInstaller import log as logging +from PyInstaller.building.templates import bundleexetmplt, bundletmplt, onedirtmplt, onefiletmplt, splashtmpl +from PyInstaller.compat import is_darwin, is_win + +logger = logging.getLogger(__name__) + +# This list gives valid choices for the ``--debug`` command-line option, except for the ``all`` choice. +DEBUG_ARGUMENT_CHOICES = ['imports', 'bootloader', 'noarchive'] +# This is the ``all`` choice. +DEBUG_ALL_CHOICE = ['all'] + + +def escape_win_filepath(path): + # escape all \ with another \ after using normpath to clean up the path + return os.path.normpath(path).replace('\\', '\\\\') + + +def make_path_spec_relative(filename, spec_dir): + """ + Make the filename relative to the directory containing .spec file if filename is relative and not absolute. + Otherwise keep filename untouched. + """ + if os.path.isabs(filename): + return filename + else: + filename = os.path.abspath(filename) + # Make it relative. + filename = os.path.relpath(filename, start=spec_dir) + return filename + + +# Support for trying to avoid hard-coded paths in the .spec files. Eg, all files rooted in the Installer directory tree +# will be written using "HOMEPATH", thus allowing this spec file to be used with any Installer installation. Same thing +# could be done for other paths too. +path_conversions = ((HOMEPATH, "HOMEPATH"),) + + +class SourceDestAction(argparse.Action): + """ + A command line option which takes multiple source:dest pairs. + """ + def __init__(self, *args, default=None, metavar=None, **kwargs): + super().__init__(*args, default=[], metavar='SOURCE:DEST', **kwargs) + + def __call__(self, parser, namespace, value, option_string=None): + try: + # Find the only separator that isn't a Windows drive. + separator, = (m for m in re.finditer(rf"(^\w:[/\\])|[:{os.pathsep}]", value) if not m[1]) + except ValueError: + # Split into SRC and DEST failed, wrong syntax + raise argparse.ArgumentError(self, f'Wrong syntax, should be {self.option_strings[0]}=SOURCE:DEST') + src = value[:separator.start()] + dest = value[separator.end():] + if not src or not dest: + # Syntax was correct, but one or both of SRC and DEST was not given + raise argparse.ArgumentError(self, "You have to specify both SOURCE and DEST") + + # argparse is not particularly smart with copy by reference typed defaults. If the current list is the default, + # replace it before modifying it to avoid changing the default. + if getattr(namespace, self.dest) is self.default: + setattr(namespace, self.dest, []) + getattr(namespace, self.dest).append((src, dest)) + + +def make_variable_path(filename, conversions=path_conversions): + if not os.path.isabs(filename): + # os.path.commonpath can not compare relative and absolute paths, and if filename is not absolute, none of the + # paths in conversions will match anyway. + return None, filename + for (from_path, to_name) in conversions: + assert os.path.abspath(from_path) == from_path, ("path '%s' should already be absolute" % from_path) + try: + common_path = os.path.commonpath([filename, from_path]) + except ValueError: + # Per https://docs.python.org/3/library/os.path.html#os.path.commonpath, this raises ValueError in several + # cases which prevent computing a common path. + common_path = None + if common_path == from_path: + rest = filename[len(from_path):] + if rest.startswith(('\\', '/')): + rest = rest[1:] + return to_name, rest + return None, filename + + +def removed_key_option(x): + from PyInstaller.exceptions import RemovedCipherFeatureError + raise RemovedCipherFeatureError("Please remove your --key=xxx argument.") + + +class _RemovedFlagAction(argparse.Action): + def __init__(self, *args, **kwargs): + kwargs["help"] = argparse.SUPPRESS + kwargs["nargs"] = 0 + super().__init__(*args, **kwargs) + + +class _RemovedNoEmbedManifestAction(_RemovedFlagAction): + def __call__(self, *args, **kwargs): + from PyInstaller.exceptions import RemovedExternalManifestError + raise RemovedExternalManifestError("Please remove your --no-embed-manifest argument.") + + +class _RemovedWinPrivateAssembliesAction(_RemovedFlagAction): + def __call__(self, *args, **kwargs): + from PyInstaller.exceptions import RemovedWinSideBySideSupportError + raise RemovedWinSideBySideSupportError("Please remove your --win-private-assemblies argument.") + + +class _RemovedWinNoPreferRedirectsAction(_RemovedFlagAction): + def __call__(self, *args, **kwargs): + from PyInstaller.exceptions import RemovedWinSideBySideSupportError + raise RemovedWinSideBySideSupportError("Please remove your --win-no-prefer-redirects argument.") + + +# An object used in place of a "path string", which knows how to repr() itself using variable names instead of +# hard-coded paths. +class Path: + def __init__(self, *parts): + self.path = os.path.join(*parts) + self.variable_prefix = self.filename_suffix = None + + def __repr__(self): + if self.filename_suffix is None: + self.variable_prefix, self.filename_suffix = make_variable_path(self.path) + if self.variable_prefix is None: + return repr(self.path) + return "os.path.join(" + self.variable_prefix + "," + repr(self.filename_suffix) + ")" + + +# An object used to construct extra preamble for the spec file, in order to accommodate extra collect_*() calls from the +# command-line +class Preamble: + def __init__( + self, datas, binaries, hiddenimports, collect_data, collect_binaries, collect_submodules, collect_all, + copy_metadata, recursive_copy_metadata + ): + # Initialize with literal values - will be switched to preamble variable name later, if necessary + self.binaries = binaries or [] + self.hiddenimports = hiddenimports or [] + self.datas = datas or [] + # Preamble content + self.content = [] + + # Import statements + if collect_data: + self._add_hookutil_import('collect_data_files') + if collect_binaries: + self._add_hookutil_import('collect_dynamic_libs') + if collect_submodules: + self._add_hookutil_import('collect_submodules') + if collect_all: + self._add_hookutil_import('collect_all') + if copy_metadata or recursive_copy_metadata: + self._add_hookutil_import('copy_metadata') + if self.content: + self.content += [''] # empty line to separate the section + # Variables + if collect_data or copy_metadata or collect_all or recursive_copy_metadata: + self._add_var('datas', self.datas) + self.datas = 'datas' # switch to variable + if collect_binaries or collect_all: + self._add_var('binaries', self.binaries) + self.binaries = 'binaries' # switch to variable + if collect_submodules or collect_all: + self._add_var('hiddenimports', self.hiddenimports) + self.hiddenimports = 'hiddenimports' # switch to variable + # Content - collect_data_files + for entry in collect_data: + self._add_collect_data(entry) + # Content - copy_metadata + for entry in copy_metadata: + self._add_copy_metadata(entry) + # Content - copy_metadata(..., recursive=True) + for entry in recursive_copy_metadata: + self._add_recursive_copy_metadata(entry) + # Content - collect_binaries + for entry in collect_binaries: + self._add_collect_binaries(entry) + # Content - collect_submodules + for entry in collect_submodules: + self._add_collect_submodules(entry) + # Content - collect_all + for entry in collect_all: + self._add_collect_all(entry) + # Merge + if self.content and self.content[-1] != '': + self.content += [''] # empty line + self.content = '\n'.join(self.content) + + def _add_hookutil_import(self, name): + self.content += ['from PyInstaller.utils.hooks import {0}'.format(name)] + + def _add_var(self, name, initial_value): + self.content += ['{0} = {1}'.format(name, initial_value)] + + def _add_collect_data(self, name): + self.content += ['datas += collect_data_files(\'{0}\')'.format(name)] + + def _add_copy_metadata(self, name): + self.content += ['datas += copy_metadata(\'{0}\')'.format(name)] + + def _add_recursive_copy_metadata(self, name): + self.content += ['datas += copy_metadata(\'{0}\', recursive=True)'.format(name)] + + def _add_collect_binaries(self, name): + self.content += ['binaries += collect_dynamic_libs(\'{0}\')'.format(name)] + + def _add_collect_submodules(self, name): + self.content += ['hiddenimports += collect_submodules(\'{0}\')'.format(name)] + + def _add_collect_all(self, name): + self.content += [ + 'tmp_ret = collect_all(\'{0}\')'.format(name), + 'datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]' + ] + + +def __add_options(parser): + """ + Add the `Makespec` options to a option-parser instance or a option group. + """ + g = parser.add_argument_group('What to generate') + g.add_argument( + "-D", + "--onedir", + dest="onefile", + action="store_false", + default=None, + help="Create a one-folder bundle containing an executable (default)", + ) + g.add_argument( + "-F", + "--onefile", + dest="onefile", + action="store_true", + default=None, + help="Create a one-file bundled executable.", + ) + g.add_argument( + "--specpath", + metavar="DIR", + help="Folder to store the generated spec file (default: current directory)", + ) + g.add_argument( + "-n", + "--name", + help="Name to assign to the bundled app and spec file (default: first script's basename)", + ) + g.add_argument( + "--contents-directory", + help="For onedir builds only, specify the name of the directory in which all supporting files (i.e. everything " + "except the executable itself) will be placed in. Use \".\" to re-enable old onedir layout without contents " + "directory.", + ) + + g = parser.add_argument_group('What to bundle, where to search') + g.add_argument( + '--add-data', + action=SourceDestAction, + dest='datas', + help="Additional data files or directories containing data files to be added to the application. The argument " + 'value should be in form of "source:dest_dir", where source is the path to file (or directory) to be ' + "collected, dest_dir is the destination directory relative to the top-level application directory, and both " + "paths are separated by a colon (:). To put a file in the top-level application directory, use . as a " + "dest_dir. This option can be used multiple times." + ) + g.add_argument( + '--add-binary', + action=SourceDestAction, + dest="binaries", + help='Additional binary files to be added to the executable. See the ``--add-data`` option for the format. ' + 'This option can be used multiple times.', + ) + g.add_argument( + "-p", + "--paths", + dest="pathex", + metavar="DIR", + action="append", + default=[], + help="A path to search for imports (like using PYTHONPATH). Multiple paths are allowed, separated by ``%s``, " + "or use this option multiple times. Equivalent to supplying the ``pathex`` argument in the spec file." % + repr(os.pathsep), + ) + g.add_argument( + '--hidden-import', + '--hiddenimport', + action='append', + default=[], + metavar="MODULENAME", + dest='hiddenimports', + help='Name an import not visible in the code of the script(s). This option can be used multiple times.', + ) + g.add_argument( + '--collect-submodules', + action="append", + default=[], + metavar="MODULENAME", + dest='collect_submodules', + help='Collect all submodules from the specified package or module. This option can be used multiple times.', + ) + g.add_argument( + '--collect-data', + '--collect-datas', + action="append", + default=[], + metavar="MODULENAME", + dest='collect_data', + help='Collect all data from the specified package or module. This option can be used multiple times.', + ) + g.add_argument( + '--collect-binaries', + action="append", + default=[], + metavar="MODULENAME", + dest='collect_binaries', + help='Collect all binaries from the specified package or module. This option can be used multiple times.', + ) + g.add_argument( + '--collect-all', + action="append", + default=[], + metavar="MODULENAME", + dest='collect_all', + help='Collect all submodules, data files, and binaries from the specified package or module. This option can ' + 'be used multiple times.', + ) + g.add_argument( + '--copy-metadata', + action="append", + default=[], + metavar="PACKAGENAME", + dest='copy_metadata', + help='Copy metadata for the specified package. This option can be used multiple times.', + ) + g.add_argument( + '--recursive-copy-metadata', + action="append", + default=[], + metavar="PACKAGENAME", + dest='recursive_copy_metadata', + help='Copy metadata for the specified package and all its dependencies. This option can be used multiple ' + 'times.', + ) + g.add_argument( + "--additional-hooks-dir", + action="append", + dest="hookspath", + default=[], + help="An additional path to search for hooks. This option can be used multiple times.", + ) + g.add_argument( + '--runtime-hook', + action='append', + dest='runtime_hooks', + default=[], + help='Path to a custom runtime hook file. A runtime hook is code that is bundled with the executable and is ' + 'executed before any other code or module to set up special features of the runtime environment. This option ' + 'can be used multiple times.', + ) + g.add_argument( + '--exclude-module', + dest='excludes', + action='append', + default=[], + help='Optional module or package (the Python name, not the path name) that will be ignored (as though it was ' + 'not found). This option can be used multiple times.', + ) + g.add_argument( + '--key', + dest='key', + help=argparse.SUPPRESS, + type=removed_key_option, + ) + g.add_argument( + '--splash', + dest='splash', + metavar="IMAGE_FILE", + help="(EXPERIMENTAL) Add an splash screen with the image IMAGE_FILE to the application. The splash screen can " + "display progress updates while unpacking.", + ) + + g = parser.add_argument_group('How to generate') + g.add_argument( + "-d", + "--debug", + # If this option is not specified, then its default value is an empty list (no debug options selected). + default=[], + # Note that ``nargs`` is omitted. This produces a single item not stored in a list, as opposed to a list + # containing one item, as per `nargs `_. + nargs=None, + # The options specified must come from this list. + choices=DEBUG_ALL_CHOICE + DEBUG_ARGUMENT_CHOICES, + # Append choice, rather than storing them (which would overwrite any previous selections). + action='append', + # Allow newlines in the help text; see the ``_SmartFormatter`` in ``__main__.py``. + help=( + "R|Provide assistance with debugging a frozen\n" + "application. This argument may be provided multiple\n" + "times to select several of the following options.\n" + "\n" + "- all: All three of the following options.\n" + "\n" + "- imports: specify the -v option to the underlying\n" + " Python interpreter, causing it to print a message\n" + " each time a module is initialized, showing the\n" + " place (filename or built-in module) from which it\n" + " is loaded. See\n" + " https://docs.python.org/3/using/cmdline.html#id4.\n" + "\n" + "- bootloader: tell the bootloader to issue progress\n" + " messages while initializing and starting the\n" + " bundled app. Used to diagnose problems with\n" + " missing imports.\n" + "\n" + "- noarchive: instead of storing all frozen Python\n" + " source files as an archive inside the resulting\n" + " executable, store them as files in the resulting\n" + " output directory.\n" + "\n" + ), + ) + g.add_argument( + '--optimize', + dest='optimize', + metavar='LEVEL', + type=int, + choices={-1, 0, 1, 2}, + default=None, + help='Bytecode optimization level used for collected python modules and scripts. For details, see the section ' + '“Bytecode Optimization Level” in PyInstaller manual.', + ) + g.add_argument( + '--python-option', + dest='python_options', + metavar='PYTHON_OPTION', + action='append', + default=[], + help='Specify a command-line option to pass to the Python interpreter at runtime. Currently supports ' + '"v" (equivalent to "--debug imports"), "u", "W ", "X ", and "hash_seed=". ' + 'For details, see the section "Specifying Python Interpreter Options" in PyInstaller manual.', + ) + g.add_argument( + "-s", + "--strip", + action="store_true", + help="Apply a symbol-table strip to the executable and shared libs (not recommended for Windows)", + ) + g.add_argument( + "--noupx", + action="store_true", + default=False, + help="Do not use UPX even if it is available (works differently between Windows and *nix)", + ) + g.add_argument( + "--upx-exclude", + dest="upx_exclude", + metavar="FILE", + action="append", + help="Prevent a binary from being compressed when using upx. This is typically used if upx corrupts certain " + "binaries during compression. FILE is the filename of the binary without path. This option can be used " + "multiple times.", + ) + + g = parser.add_argument_group('Windows and Mac OS X specific options') + g.add_argument( + "-c", + "--console", + "--nowindowed", + dest="console", + action="store_true", + default=None, + help="Open a console window for standard i/o (default). On Windows this option has no effect if the first " + "script is a '.pyw' file.", + ) + g.add_argument( + "-w", + "--windowed", + "--noconsole", + dest="console", + action="store_false", + default=None, + help="Windows and Mac OS X: do not provide a console window for standard i/o. On Mac OS this also triggers " + "building a Mac OS .app bundle. On Windows this option is automatically set if the first script is a '.pyw' " + "file. This option is ignored on *NIX systems.", + ) + g.add_argument( + "--hide-console", + type=str, + choices={'hide-early', 'hide-late', 'minimize-early', 'minimize-late'}, + default=None, + help="Windows only: in console-enabled executable, have bootloader automatically hide or minimize the console " + "window if the program owns the console window (i.e., was not launched from an existing console window).", + ) + g.add_argument( + "-i", + "--icon", + action='append', + dest="icon_file", + metavar='', + help="FILE.ico: apply the icon to a Windows executable. FILE.exe,ID: extract the icon with ID from an exe. " + "FILE.icns: apply the icon to the .app bundle on Mac OS. If an image file is entered that isn't in the " + "platform format (ico on Windows, icns on Mac), PyInstaller tries to use Pillow to translate the icon into " + "the correct format (if Pillow is installed). Use \"NONE\" to not apply any icon, thereby making the OS show " + "some default (default: apply PyInstaller's icon). This option can be used multiple times.", + ) + g.add_argument( + "--disable-windowed-traceback", + dest="disable_windowed_traceback", + action="store_true", + default=False, + help="Disable traceback dump of unhandled exception in windowed (noconsole) mode (Windows and macOS only), " + "and instead display a message that this feature is disabled.", + ) + + g = parser.add_argument_group('Windows specific options') + g.add_argument( + "--version-file", + dest="version_file", + metavar="FILE", + help="Add a version resource from FILE to the exe.", + ) + g.add_argument( + "--manifest", + metavar="", + help="Add manifest FILE or XML to the exe.", + ) + g.add_argument( + "-m", + dest="shorthand_manifest", + metavar="", + help="Deprecated shorthand for --manifest.", + ) + g.add_argument( + "--no-embed-manifest", + action=_RemovedNoEmbedManifestAction, + ) + g.add_argument( + "-r", + "--resource", + dest="resources", + metavar="RESOURCE", + action="append", + default=[], + help="Add or update a resource to a Windows executable. The RESOURCE is one to four items, " + "FILE[,TYPE[,NAME[,LANGUAGE]]]. FILE can be a data file or an exe/dll. For data files, at least TYPE and NAME " + "must be specified. LANGUAGE defaults to 0 or may be specified as wildcard * to update all resources of the " + "given TYPE and NAME. For exe/dll files, all resources from FILE will be added/updated to the final executable " + "if TYPE, NAME and LANGUAGE are omitted or specified as wildcard *. This option can be used multiple times.", + ) + g.add_argument( + '--uac-admin', + dest='uac_admin', + action="store_true", + default=False, + help="Using this option creates a Manifest that will request elevation upon application start.", + ) + g.add_argument( + '--uac-uiaccess', + dest='uac_uiaccess', + action="store_true", + default=False, + help="Using this option allows an elevated application to work with Remote Desktop.", + ) + + g = parser.add_argument_group('Windows Side-by-side Assembly searching options (advanced)') + g.add_argument( + "--win-private-assemblies", + action=_RemovedWinPrivateAssembliesAction, + ) + g.add_argument( + "--win-no-prefer-redirects", + action=_RemovedWinNoPreferRedirectsAction, + ) + + g = parser.add_argument_group('Mac OS specific options') + g.add_argument( + "--argv-emulation", + dest="argv_emulation", + action="store_true", + default=False, + help="Enable argv emulation for macOS app bundles. If enabled, the initial open document/URL event is " + "processed by the bootloader and the passed file paths or URLs are appended to sys.argv.", + ) + + g.add_argument( + '--osx-bundle-identifier', + dest='bundle_identifier', + help="Mac OS .app bundle identifier is used as the default unique program name for code signing purposes. " + "The usual form is a hierarchical name in reverse DNS notation. For example: com.mycompany.department.appname " + "(default: first script's basename)", + ) + + g.add_argument( + '--target-architecture', + '--target-arch', + dest='target_arch', + metavar='ARCH', + default=None, + help="Target architecture (macOS only; valid values: x86_64, arm64, universal2). Enables switching between " + "universal2 and single-arch version of frozen application (provided python installation supports the target " + "architecture). If not target architecture is not specified, the current running architecture is targeted.", + ) + + g.add_argument( + '--codesign-identity', + dest='codesign_identity', + metavar='IDENTITY', + default=None, + help="Code signing identity (macOS only). Use the provided identity to sign collected binaries and generated " + "executable. If signing identity is not provided, ad-hoc signing is performed instead.", + ) + + g.add_argument( + '--osx-entitlements-file', + dest='entitlements_file', + metavar='FILENAME', + default=None, + help="Entitlements file to use when code-signing the collected binaries (macOS only).", + ) + + g = parser.add_argument_group('Rarely used special options') + g.add_argument( + "--runtime-tmpdir", + dest="runtime_tmpdir", + metavar="PATH", + help="Where to extract libraries and support files in `onefile` mode. If this option is given, the bootloader " + "will ignore any temp-folder location defined by the run-time OS. The ``_MEIxxxxxx``-folder will be created " + "here. Please use this option only if you know what you are doing. Note that on POSIX systems, PyInstaller's " + "bootloader does NOT perform shell-style environment variable expansion on the given path string. Therefore, " + "using environment variables (e.g., ``~`` or ``$HOME``) in path will NOT work.", + ) + g.add_argument( + "--bootloader-ignore-signals", + action="store_true", + default=False, + help="Tell the bootloader to ignore signals rather than forwarding them to the child process. Useful in " + "situations where for example a supervisor process signals both the bootloader and the child (e.g., via a " + "process group) to avoid signalling the child twice.", + ) + + +def main( + scripts, + name=None, + onefile=False, + console=True, + debug=[], + python_options=[], + strip=False, + noupx=False, + upx_exclude=None, + runtime_tmpdir=None, + contents_directory=None, + pathex=[], + version_file=None, + specpath=None, + bootloader_ignore_signals=False, + disable_windowed_traceback=False, + datas=[], + binaries=[], + icon_file=None, + manifest=None, + resources=[], + bundle_identifier=None, + hiddenimports=[], + hookspath=[], + runtime_hooks=[], + excludes=[], + uac_admin=False, + uac_uiaccess=False, + collect_submodules=[], + collect_binaries=[], + collect_data=[], + collect_all=[], + copy_metadata=[], + splash=None, + recursive_copy_metadata=[], + target_arch=None, + codesign_identity=None, + entitlements_file=None, + argv_emulation=False, + hide_console=None, + optimize=None, + **_kwargs +): + # Default values for onefile and console when not explicitly specified on command-line (indicated by None) + if onefile is None: + onefile = False + + if console is None: + console = True + + # If appname is not specified - use the basename of the main script as name. + if name is None: + name = os.path.splitext(os.path.basename(scripts[0]))[0] + + # If specpath not specified - use default value - current working directory. + if specpath is None: + specpath = DEFAULT_SPECPATH + else: + # Expand starting tilde into user's home directory, as a work-around for tilde not being expanded by shell when + # using ˙--specpath=~/path/abc` instead of ˙--specpath ~/path/abc` (or when the path argument is quoted). + specpath = os.path.expanduser(specpath) + # If cwd is the root directory of PyInstaller, generate the .spec file in ./appname/ subdirectory. + if specpath == HOMEPATH: + specpath = os.path.join(HOMEPATH, name) + # Create directory tree if missing. + if not os.path.exists(specpath): + os.makedirs(specpath) + + # Handle additional EXE options. + exe_options = '' + if version_file: + exe_options += "\n version='%s'," % escape_win_filepath(version_file) + if uac_admin: + exe_options += "\n uac_admin=True," + if uac_uiaccess: + exe_options += "\n uac_uiaccess=True," + if icon_file: + # Icon file for Windows. + # On Windows, the default icon is embedded in the bootloader executable. + if icon_file[0] == 'NONE': + exe_options += "\n icon='NONE'," + else: + exe_options += "\n icon=[%s]," % ','.join("'%s'" % escape_win_filepath(ic) for ic in icon_file) + # Icon file for Mac OS. + # We need to encapsulate it into apostrofes. + icon_file = "'%s'" % icon_file[0] + else: + # On Mac OS, the default icon has to be copied into the .app bundle. + # The the text value 'None' means - use default icon. + icon_file = 'None' + if contents_directory: + exe_options += "\n contents_directory='%s'," % (contents_directory or "_internal") + if hide_console: + exe_options += "\n hide_console='%s'," % hide_console + + if bundle_identifier: + # We need to encapsulate it into apostrofes. + bundle_identifier = "'%s'" % bundle_identifier + + if _kwargs["shorthand_manifest"]: + manifest = _kwargs["shorthand_manifest"] + logger.log( + logging.DEPRECATION, "PyInstaller v7 will remove the -m shorthand flag. Please use --manifest=%s instead", + manifest + ) + if manifest: + if "<" in manifest: + # Assume XML string + exe_options += "\n manifest='%s'," % manifest.replace("'", "\\'") + else: + # Assume filename + exe_options += "\n manifest='%s'," % escape_win_filepath(manifest) + if resources: + resources = list(map(escape_win_filepath, resources)) + exe_options += "\n resources=%s," % repr(resources) + + hiddenimports = hiddenimports or [] + upx_exclude = upx_exclude or [] + + # If file extension of the first script is '.pyw', force --windowed option. + if is_win and os.path.splitext(scripts[0])[-1] == '.pyw': + console = False + + # If script paths are relative, make them relative to the directory containing .spec file. + scripts = [make_path_spec_relative(x, specpath) for x in scripts] + # With absolute paths replace prefix with variable HOMEPATH. + scripts = list(map(Path, scripts)) + + # Translate the default of ``debug=None`` to an empty list. + if debug is None: + debug = [] + # Translate the ``all`` option. + if DEBUG_ALL_CHOICE[0] in debug: + debug = DEBUG_ARGUMENT_CHOICES + + # Create preamble (for collect_*() calls) + preamble = Preamble( + datas, binaries, hiddenimports, collect_data, collect_binaries, collect_submodules, collect_all, copy_metadata, + recursive_copy_metadata + ) + + if splash: + splash_init = splashtmpl % {'splash_image': splash} + splash_binaries = "\n splash.binaries," + splash_target = "\n splash," + else: + splash_init = splash_binaries = splash_target = "" + + # Infer byte-code optimization level. + opt_level = sum([opt == 'O' for opt in python_options]) + if opt_level > 2: + logger.warning( + "The switch '--python-option O' has been specified %d times - it should be specified at most twice!", + opt_level, + ) + opt_level = 2 + + if optimize is None: + if opt_level == 0: + # Infer from running python process + optimize = sys.flags.optimize + else: + # Infer from `--python-option O` switch(es). + optimize = opt_level + elif optimize != opt_level and opt_level != 0: + logger.warning( + "Mismatch between optimization level passed via --optimize switch (%d) and number of '--python-option O' " + "switches (%d)!", + optimize, + opt_level, + ) + + if optimize >= 0: + # Ensure OPTIONs passed to bootloader match the optimization settings. + python_options += max(0, optimize - opt_level) * ['O'] + + # Create OPTIONs array + if 'imports' in debug and 'v' not in python_options: + python_options.append('v') + python_options_array = [(opt, None, 'OPTION') for opt in python_options] + + d = { + 'scripts': scripts, + 'pathex': pathex or [], + 'binaries': preamble.binaries, + 'datas': preamble.datas, + 'hiddenimports': preamble.hiddenimports, + 'preamble': preamble.content, + 'name': name, + 'noarchive': 'noarchive' in debug, + 'optimize': optimize, + 'options': python_options_array, + 'debug_bootloader': 'bootloader' in debug, + 'bootloader_ignore_signals': bootloader_ignore_signals, + 'strip': strip, + 'upx': not noupx, + 'upx_exclude': upx_exclude, + 'runtime_tmpdir': runtime_tmpdir, + 'exe_options': exe_options, + # Directory with additional custom import hooks. + 'hookspath': hookspath, + # List with custom runtime hook files. + 'runtime_hooks': runtime_hooks or [], + # List of modules/packages to ignore. + 'excludes': excludes or [], + # only Windows and Mac OS distinguish windowed and console apps + 'console': console, + 'disable_windowed_traceback': disable_windowed_traceback, + # Icon filename. Only Mac OS uses this item. + 'icon': icon_file, + # .app bundle identifier. Only OSX uses this item. + 'bundle_identifier': bundle_identifier, + # argv emulation (macOS only) + 'argv_emulation': argv_emulation, + # Target architecture (macOS only) + 'target_arch': target_arch, + # Code signing identity (macOS only) + 'codesign_identity': codesign_identity, + # Entitlements file (macOS only) + 'entitlements_file': entitlements_file, + # splash screen + 'splash_init': splash_init, + 'splash_target': splash_target, + 'splash_binaries': splash_binaries, + } + + # Write down .spec file to filesystem. + specfnm = os.path.join(specpath, name + '.spec') + with open(specfnm, 'w', encoding='utf-8') as specfile: + if onefile: + specfile.write(onefiletmplt % d) + # For Mac OS create .app bundle. + if is_darwin and not console: + specfile.write(bundleexetmplt % d) + else: + specfile.write(onedirtmplt % d) + # For Mac OS create .app bundle. + if is_darwin and not console: + specfile.write(bundletmplt % d) + + return specfnm diff --git a/venv/Lib/site-packages/PyInstaller/building/osx.py b/venv/Lib/site-packages/PyInstaller/building/osx.py new file mode 100644 index 0000000..1d5e0ff --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/building/osx.py @@ -0,0 +1,723 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +import os +import pathlib +import plistlib +import shutil +import subprocess + +from PyInstaller.building.api import COLLECT, EXE +from PyInstaller.building.datastruct import Target, logger, normalize_toc +from PyInstaller.building.utils import _check_path_overlap, _rmtree, process_collected_binary +from PyInstaller.compat import is_darwin, strict_collect_mode +from PyInstaller.building.icon import normalize_icon_type +import PyInstaller.utils.misc as miscutils + +if is_darwin: + import PyInstaller.utils.osx as osxutils + +# Character sequence used to replace dot (`.`) in names of directories that are created in `Contents/MacOS` or +# `Contents/Frameworks`, where only .framework bundle directories are allowed to have dot in name. +DOT_REPLACEMENT = '__dot__' + + +class BUNDLE(Target): + def __init__(self, *args, **kwargs): + from PyInstaller.config import CONF + + # BUNDLE only has a sense under Mac OS, it's a noop on other platforms + if not is_darwin: + return + + # Get a path to a .icns icon for the app bundle. + self.icon = kwargs.get('icon') + if not self.icon: + # --icon not specified; use the default in the pyinstaller folder + self.icon = os.path.join( + os.path.dirname(os.path.dirname(__file__)), 'bootloader', 'images', 'icon-windowed.icns' + ) + else: + # User gave an --icon=path. If it is relative, make it relative to the spec file location. + if not os.path.isabs(self.icon): + self.icon = os.path.join(CONF['specpath'], self.icon) + + super().__init__() + + # .app bundle is created in DISTPATH. + self.name = kwargs.get('name', None) + base_name = os.path.basename(self.name) + self.name = os.path.join(CONF['distpath'], base_name) + + self.appname = os.path.splitext(base_name)[0] + # Ensure version is a string, even if user accidentally passed an int or a float. + # Having a `CFBundleShortVersionString` entry of non-string type in `Info.plist` causes the .app bundle to + # crash at start (#4466). + self.version = str(kwargs.get("version", "0.0.0")) + self.toc = [] + self.strip = False + self.upx = False + self.console = True + self.target_arch = None + self.codesign_identity = None + self.entitlements_file = None + + # .app bundle identifier for Code Signing + self.bundle_identifier = kwargs.get('bundle_identifier') + if not self.bundle_identifier: + # Fallback to appname. + self.bundle_identifier = self.appname + + self.info_plist = kwargs.get('info_plist', None) + + for arg in args: + # Valid arguments: EXE object, COLLECT object, and TOC-like iterables + if isinstance(arg, EXE): + # Add EXE as an entry to the TOC, and merge its dependencies TOC + self.toc.append((os.path.basename(arg.name), arg.name, 'EXECUTABLE')) + self.toc.extend(arg.dependencies) + # Inherit settings + self.strip = arg.strip + self.upx = arg.upx + self.upx_exclude = arg.upx_exclude + self.console = arg.console + self.target_arch = arg.target_arch + self.codesign_identity = arg.codesign_identity + self.entitlements_file = arg.entitlements_file + elif isinstance(arg, COLLECT): + # Merge the TOC + self.toc.extend(arg.toc) + # Inherit settings + self.strip = arg.strip_binaries + self.upx = arg.upx_binaries + self.upx_exclude = arg.upx_exclude + self.console = arg.console + self.target_arch = arg.target_arch + self.codesign_identity = arg.codesign_identity + self.entitlements_file = arg.entitlements_file + elif miscutils.is_iterable(arg): + # TOC-like iterable + self.toc.extend(arg) + else: + raise TypeError(f"Invalid argument type for BUNDLE: {type(arg)!r}") + + # Infer the executable name from the first EXECUTABLE entry in the TOC; it might have come from the COLLECT + # (as opposed to the stand-alone EXE). + for dest_name, src_name, typecode in self.toc: + if typecode == "EXECUTABLE": + self.exename = src_name + break + else: + raise ValueError("No EXECUTABLE entry found in the TOC!") + + # Normalize TOC + self.toc = normalize_toc(self.toc) + + self.__postinit__() + + _GUTS = ( + # BUNDLE always builds, just want the toc to be written out + ('toc', None), + ) + + def _check_guts(self, data, last_build): + # BUNDLE always needs to be executed, in order to clean the output directory. + return True + + # Helper for determining whether the given file belongs to a .framework bundle or not. If it does, it returns + # the path to the top-level .framework bundle directory; otherwise, returns None. + @staticmethod + def _is_framework_file(dest_path): + for parent in dest_path.parents: + if parent.name.endswith('.framework'): + return parent + return None + + # Helper that computes relative cross-link path between link's location and target, assuming they are both + # rooted in the `Contents` directory of a macOS .app bundle. + @staticmethod + def _compute_relative_crosslink(crosslink_location, crosslink_target): + # We could take symlink_location and symlink_target as they are (relative to parent of the `Contents` + # directory), but that would introduce an unnecessary `../Contents` part. So instead, we take both paths + # relative to the `Contents` directory. + return os.path.join( + *['..' for level in pathlib.PurePath(crosslink_location).relative_to('Contents').parent.parts], + pathlib.PurePath(crosslink_target).relative_to('Contents'), + ) + + # This method takes the original (input) TOC and processes it into final TOC, based on which the `assemble` method + # performs its file collection. The TOC processing here represents the core of our efforts to generate an .app + # bundle that is compatible with Apple's code-signing requirements. + # + # For in-depth details on the code-signing, see Apple's `Technical Note TN2206: macOS Code Signing In Depth` at + # https://developer.apple.com/library/archive/technotes/tn2206/_index.html + # + # The requirements, framed from PyInstaller's perspective, can be summarized as follows: + # + # 1. The `Contents/MacOS` directory is expected to contain only the program executable and (binary) code (= dylibs + # and nested .framework bundles). Alternatively, the dylibs and .framework bundles can be also placed into + # `Contents/Frameworks` directory (where same rules apply as for `Contents/MacOS`, so the remainder of this + # text refers to the two inter-changeably, unless explicitly noted otherwise). The code in `Contents/MacOS` + # is expected to be signed, and the `codesign` utility will recursively sign all found code when using `--deep` + # option to sign the .app bundle. + # + # 2. All non-code files should be be placed in `Contents/Resources`, so they become sealed (data) resources; + # i.e., their signature data is recorded in `Contents/_CodeSignature/CodeResources`. (As a side note, + # it seems that signature information for data/resources in `Contents/Resources` is kept nder `file` key in + # the `CodeResources` file, while the information for contents in `Contents/MacOS` is kept under `file2` key). + # + # 3. The directories in `Contents/MacOS` may not contain dots (`.`) in their names, except for the nested + # .framework bundle directories. The directories in `Contents/Resources` have no such restrictions. + # + # 4. There may not be any content in the top level of a bundle. In other words, if a bundle has a `Contents` + # or a `Versions` directory at its top level, there may be no other files or directories alongside them. The + # sole exception is that alongside ˙Versions˙, there may be symlinks to files and directories in + # `Versions/Current`. This rule is important for nested .framework bundles that we collect from python packages. + # + # Next, let us consider the consequences of violating each of the above requirements: + # + # 1. Code signing machinery can directly store signature only in Mach-O binaries and nested .framework bundles; if + # a data file is placed in `Contents/MacOS`, the signature is stored in the file's extended attributes. If the + # extended attributes are lost, the program's signature will be broken. Many file transfer techniques (e.g., a + # zip file) do not preserve extended attributes, nor are they preserved when uploading to the Mac App Store. + # + # 2. Putting code (a dylib or a .framework bundle) into `Contents/Resources` causes it to be treated as a resource; + # the outer signature (i.e., of the whole .app bundle) does not know that this nested content is actually a code. + # Consequently, signing the bundle with ˙codesign --deep` will NOT sign binaries placed in the + # `Contents/Resources`, which may result in missing signatures when .app bundle is verified for notarization. + # This might be worked around by signing each binary separately, and then signing the whole bundle (without the + # `--deep˙ option), but requires the user to keep track of the offending binaries. + # + # 3. If a directory in `Contents/MacOS` contains a dot in the name, code-signing the bundle fails with + # ˙bundle format unrecognized, invalid, or unsuitable` due to code signing machinery treating directory as a + # nested .framework bundle directory. + # + # 4. If nested .framework bundle is malformed, the signing of the .app bundle might succeed, but subsequent + # verification will fail, for example with `embedded framework contains modified or invalid version` (as observed + # with .framework bundles shipped by contemporary PyQt/PySide PyPI wheels). + # + # The above requirements are unfortunately often at odds with the structure of python packages: + # + # * In general, python packages are mixed-content directories, where binaries and data files may be expected to + # be found next to each other. + # + # For example, `opencv-python` provides a custom loader script that requires the package to be collected in the + # source-only form by PyInstaller (i.e., the python modules and scripts collected as source .py files). At the + # same time, it expects the .py loader script to be able to find the binary extension next to itself. + # + # Another example of mixed-mode directories are Qt QML components' sub-directories, which contain both the + # component's plugin (a binary) and associated meta files (data files). + # + # * In python world, the directories often contain dots in their names. + # + # Dots are often used for private directories containing binaries that are shipped with a package. For example, + # `numpy/.dylibs`, `scipy/.dylibs`, etc. + # + # Qt QML components may also contain a dot in their name; couple of examples from `PySide2` package: + # `PySide2/Qt/qml/QtQuick.2`, ˙PySide2/Qt/qml/QtQuick/Controls.2˙, ˙PySide2/Qt/qml/QtQuick/Particles.2˙, etc. + # + # The packages' metadata directories also invariably contain dots in the name due to version (for example, + # `numpy-1.24.3.dist-info`). + # + # In the light of all above, PyInstaller attempts to strictly place all files to their mandated location + # (`Contents/MacOS` or `Contents/Frameworks` vs `Contents/Resources`). To preserve the illusion of mixed-content + # directories, the content is cross-linked from one directory to the other. Specifically: + # + # * All entries with DATA typecode are assumed to be data files, and are always placed in corresponding directory + # structure rooted in `Contents/Resources`. + # + # * All entries with BINARY or EXTENSION typecode are always placed in corresponding directory structure rooted in + # `Contents/Frameworks`. + # + # * All entries with EXECUTABLE are placed in `Contents/MacOS` directory. + # + # * For the purposes of relocation, nested .framework bundles are treated as a single BINARY entity; i.e., the + # whole .bundle directory is placed in corresponding directory structure rooted in `Contents/Frameworks` (even + # though some of its contents, such as `Info.plist` file, are actually data files). + # + # * Top-level data files and binaries are always cross-linked to the other directory. For example, given a data file + # `data_file.txt` that was collected into `Contents/Resources`, we create a symbolic link called + # `Contents/MacOS/data_file.txt` that points to `../Resources/data_file.txt`. + # + # * The executable itself, while placed in `Contents/MacOS`, are cross-linked into both `Contents/Framworks` and + # `Contents/Resources`. + # + # * The stand-alone PKG entries (used with onefile builds that side-load the PKG archive) are treated as data files + # and collected into `Contents/Resources`, but cross-linked only into `Contents/MacOS` directory (because they + # must appear to be next to the program executable). This is the only entry type that is cross-linked into the + # `Contents/MacOS` directory and also the only data-like entry type that is not cross-linked into the + # `Contents/Frameworks` directory. + # + # * For files in sub-directories, the cross-linking behavior depends on the type of directory: + # + # * A data-only directory is created in directory structure rooted in `Contents/Resources`, and cross-linked + # into directory structure rooted in `Contents/Frameworks` at directory level (i.e., we link the whole + # directory instead of individual files). + # + # This largely saves us from having to deal with dots in the names of collected metadata directories, which + # are examples of data-only directories. + # + # * A binary-only directory is created in directory structure rooted in `Contents/Frameworks`, and cross-linked + # into `Contents/Resources` at directory level. + # + # * A mixed-content directory is created in both directory structures. Files are placed into corresponding + # directory structure based on their type, and cross-linked into other directory structure at file level. + # + # * This rule is applied recursively; for example, a data-only sub-directory in a mixed-content directory is + # cross-linked at directory level, while adjacent binary and data files are cross-linked at file level. + # + # * To work around the issue with dots in the names of directories in `Contents/Frameworks` (applicable to + # binary-only or mixed-content directories), such directories are created with modified name (the dot replaced + # with a pre-defined pattern). Next to the modified directory, a symbolic link with original name is created, + # pointing to the directory with modified name. With mixed-content directories, this modification is performed + # only on the `Contents/Frameworks` side; the corresponding directory in `Contents/Resources` can be created + # directly, without name modification and symbolic link. + # + # * If a symbolic link needs to be created in a mixed-content directory due to a SYMLINK entry from the original + # TOC (i.e., a "collected" symlink originating from analysis, as opposed to the cross-linking mechanism described + # above), the link is created in both directory structures, each pointing to the resource in its corresponding + # directory structure (with one such resource being an actual file, and the other being a cross-link to the file). + # + # Final remarks: + # + # NOTE: the relocation mechanism is codified by tests in `tests/functional/test_macos_bundle_structure.py`. + # + # NOTE: by placing binaries and nested .framework entries into `Contents/Frameworks` instead of `Contents/MacOS`, + # we have effectively relocated the `sys._MEIPASS` directory from the `Contents/MacOS` (= the parent directory of + # the program executable) into `Contents/Frameworks`. This requires the PyInstaller's bootloader to detect that it + # is running in the app-bundle mode (e.g., by checking if program executable's parent directory is `Contents/NacOS`) + # and adjust the path accordingly. + # + # NOTE: the implemented relocation mechanism depends on the input TOC containing properly classified entries + # w.r.t. BINARY vs DATA. So hooks and .spec files triggering collection of binaries as datas (and vice versa) will + # result in incorrect placement of those files in the generated .app bundle. However, this is *not* the proper place + # to address such issues; if necessary, automatic (re)classification should be added to analysis process, to ensure + # that BUNDLE (as well as other build targets) receive correctly classified TOC. + # + # NOTE: similar to the previous note, the relocation mechanism is also not the proper place to enforce compliant + # structure of the nested .framework bundles. Instead, this is handled by the analysis process, using the + # `PyInstaller.utils.osx.collect_files_from_framework_bundles` helper function. So the input TOC that BUNDLE + # receives should already contain entries that reconstruct compliant nested .framework bundles. + def _process_bundle_toc(self, toc): + bundle_toc = [] + + # Step 1: inspect the directory layout and classify the directories according to their contents. + directory_types = dict() + + _MIXED_DIR_TYPE = 'MIXED-DIR' + _DATA_DIR_TYPE = 'DATA-DIR' + _BINARY_DIR_TYPE = 'BINARY-DIR' + _FRAMEWORK_DIR_TYPE = 'FRAMEWORK-DIR' + + _TOP_LEVEL_DIR = pathlib.PurePath('.') + + for dest_name, src_name, typecode in toc: + dest_path = pathlib.PurePath(dest_name) + + framework_dir = self._is_framework_file(dest_path) + if framework_dir: + # Mark the framework directory as FRAMEWORK-DIR. + directory_types[framework_dir] = _FRAMEWORK_DIR_TYPE + # Treat the framework directory as BINARY file when classifying parent directories. + typecode = 'BINARY' + parent_dirs = framework_dir.parents + else: + parent_dirs = dest_path.parents + # Treat BINARY and EXTENSION as BINARY to simplify further processing. + if typecode == 'EXTENSION': + typecode = 'BINARY' + + # (Re)classify parent directories + for parent_dir in parent_dirs: + # Skip the top-level `.` dir. This is also the only directory that can contain EXECUTABLE and PKG + # entries, so we do not have to worry about. + if parent_dir == _TOP_LEVEL_DIR: + continue + + directory_type = _BINARY_DIR_TYPE if typecode == 'BINARY' else _DATA_DIR_TYPE # default + directory_type = directory_types.get(parent_dir, directory_type) + + if directory_type == _DATA_DIR_TYPE and typecode == 'BINARY': + directory_type = _MIXED_DIR_TYPE + if directory_type == _BINARY_DIR_TYPE and typecode == 'DATA': + directory_type = _MIXED_DIR_TYPE + + directory_types[parent_dir] = directory_type + + logger.debug("Directory classification: %r", directory_types) + + # Step 2: process the obtained directory structure and create symlink entries for directories that need to be + # cross-linked. Such directories are data-only and binary-only directories (and framework directories) that are + # located either in the top-level directory (have no parent) or in a mixed-content directory. + for directory_path, directory_type in directory_types.items(): + # Cross-linking at directory level applies only to data-only and binary-only directories (as well as + # framework directories). + if directory_type == _MIXED_DIR_TYPE: + continue + + # The parent needs to be either top-level directory or a mixed-content directory. Otherwise, the parent + # (or one of its ancestors) will get cross-linked, and we do not need the link here. + parent_dir = directory_path.parent + requires_crosslink = parent_dir == _TOP_LEVEL_DIR or directory_types.get(parent_dir) == _MIXED_DIR_TYPE + if not requires_crosslink: + continue + + logger.debug("Cross-linking directory %r of type %r", directory_path, directory_type) + + # Data-only directories are created in `Contents/Resources`, needs to be cross-linked into `Contents/MacOS`. + # Vice versa for binary-only or framework directories. The directory creation is handled implicitly, when we + # create parent directory structure for collected files. + if directory_type == _DATA_DIR_TYPE: + symlink_src = os.path.join('Contents/Resources', directory_path) + symlink_dest = os.path.join('Contents/Frameworks', directory_path) + else: + symlink_src = os.path.join('Contents/Frameworks', directory_path) + symlink_dest = os.path.join('Contents/Resources', directory_path) + symlink_ref = self._compute_relative_crosslink(symlink_dest, symlink_src) + + bundle_toc.append((symlink_dest, symlink_ref, 'SYMLINK')) + + # Step 3: first part of the work-around for directories that are located in `Contents/Frameworks` but contain a + # dot in their name. As per `codesign` rules, the only directories in `Contents/Frameworks` that are allowed to + # contain a dot in their name are .framework bundle directories. So we replace the dot with a custom character + # sequence (stored in global `DOT_REPLACEMENT` variable), and create a symbolic with original name pointing to + # the modified name. This is the best we can do with code-sign requirements vs. python community showing their + # packages' dylibs into `.dylib` subdirectories, or Qt storing their Qml components in directories named + # `QtQuick.2`, `QtQuick/Controls.2`, `QtQuick/Particles.2`, `QtQuick/Templates.2`, etc. + # + # In this step, we only prepare symlink entries that link the original directory name (with dot) to the modified + # one (with dot replaced). The parent paths for collected files are modified in later step(s). + for directory_path, directory_type in directory_types.items(): + # .framework bundle directories contain a dot in the name, but are allowed that. + if directory_type == _FRAMEWORK_DIR_TYPE: + continue + + # Data-only directories are fully located in `Contents/Resources` and cross-linked to `Contents/Frameworks` + # at directory level, so they are also allowed a dot in their name. + if directory_type == _DATA_DIR_TYPE: + continue + + # Apply the work-around, if necessary... + if '.' not in directory_path.name: + continue + + logger.debug( + "Creating symlink to work around the dot in the name of directory %r (%s)...", str(directory_path), + directory_type + ) + + # Create a SYMLINK entry, but only for this level. In case of nested directories with dots in names, the + # symlinks for ancestors will be created by corresponding loop iteration. + bundle_toc.append(( + os.path.join('Contents/Frameworks', directory_path), + directory_path.name.replace('.', DOT_REPLACEMENT), + 'SYMLINK', + )) + + # Step 4: process the entries for collected files, and decide whether they should be placed into + # `Contents/MacOS`, `Contents/Frameworks`, or `Contents/Resources`, and whether they should be cross-linked into + # other directories. + for orig_dest_name, src_name, typecode in toc: + orig_dest_path = pathlib.PurePath(orig_dest_name) + + # Special handling for EXECUTABLE and PKG entries + if typecode == 'EXECUTABLE': + # Place into `Contents/MacOS`, ... + file_dest = os.path.join('Contents/MacOS', orig_dest_name) + bundle_toc.append((file_dest, src_name, typecode)) + # ... and do nothing else. We explicitly avoid cross-linking the executable to `Contents/Frameworks` and + # `Contents/Resources`, because it should be not necessary (the executable's location should be + # discovered via `sys.executable`) and to prevent issues when executable name collides with name of a + # package from which we collect either binaries or data files (or both); see #7314. + continue + elif typecode == 'PKG': + # Place into `Contents/Resources` ... + file_dest = os.path.join('Contents/Resources', orig_dest_name) + bundle_toc.append((file_dest, src_name, typecode)) + # ... and cross-link only into `Contents/MacOS`. + # This is used only in `onefile` mode, where there is actually no other content to distribute among the + # `Contents/Resources` and `Contents/Frameworks` directories, so cross-linking into the latter makes + # little sense. + symlink_dest = os.path.join('Contents/MacOS', orig_dest_name) + symlink_ref = self._compute_relative_crosslink(symlink_dest, file_dest) + bundle_toc.append((symlink_dest, symlink_ref, 'SYMLINK')) + continue + + # Standard data vs binary processing... + + # Determine file location based on its type. + if self._is_framework_file(orig_dest_path): + # File from a framework bundle; put into `Contents/Frameworks`, but never cross-link the file itself. + # The whole .framework bundle directory will be linked as necessary by the directory cross-linking + # mechanism. + file_base_dir = 'Contents/Frameworks' + crosslink_base_dir = None + elif typecode == 'DATA': + # Data file; relocate to `Contents/Resources` and cross-link it back into `Contents/Frameworks`. + file_base_dir = 'Contents/Resources' + crosslink_base_dir = 'Contents/Frameworks' + else: + # Binary; put into `Contents/Frameworks` and cross-link it into `Contents/Resources`. + file_base_dir = 'Contents/Frameworks' + crosslink_base_dir = 'Contents/Resources' + + # Determine if we need to cross-link the file. We need to do this for top-level files (the ones without + # parent directories), and for files whose parent directories are mixed-content directories. + requires_crosslink = False + if crosslink_base_dir is not None: + parent_dir = orig_dest_path.parent + requires_crosslink = parent_dir == _TOP_LEVEL_DIR or directory_types.get(parent_dir) == _MIXED_DIR_TYPE + + # Special handling for SYMLINK entries in original TOC; if we need to cross-link a symlink entry, we create + # it in both locations, and have each point to the (relative) resource in the same directory (so one of the + # targets will likely be a file, and the other will be a symlink due to cross-linking). + if typecode == 'SYMLINK' and requires_crosslink: + bundle_toc.append((os.path.join(file_base_dir, orig_dest_name), src_name, typecode)) + bundle_toc.append((os.path.join(crosslink_base_dir, orig_dest_name), src_name, typecode)) + continue + + # The file itself. + file_dest = os.path.join(file_base_dir, orig_dest_name) + bundle_toc.append((file_dest, src_name, typecode)) + + # Symlink for cross-linking + if requires_crosslink: + symlink_dest = os.path.join(crosslink_base_dir, orig_dest_name) + symlink_ref = self._compute_relative_crosslink(symlink_dest, file_dest) + bundle_toc.append((symlink_dest, symlink_ref, 'SYMLINK')) + + # Step 5: sanitize all destination paths in the new TOC, to ensure that paths that are rooted in + # `Contents/Frameworks` do not contain directories with dots in their names. Doing this as a post-processing + # step keeps code simple and clean and ensures that this step is applied to files, symlinks that originate from + # cross-linking files, and symlinks that originate from cross-linking directories. This in turn ensures that + # all directory hierarchies created during the actual file collection have sanitized names, and that collection + # outcome does not depend on the order of entries in the TOC. + sanitized_toc = [] + for dest_name, src_name, typecode in bundle_toc: + dest_path = pathlib.PurePath(dest_name) + + # Paths rooted in Contents/Resources do not require sanitizing. + if dest_path.parts[0] == 'Contents' and dest_path.parts[1] == 'Resources': + sanitized_toc.append((dest_name, src_name, typecode)) + continue + + # Special handling for files from .framework bundle directories; sanitize only parent path of the .framework + # directory. + framework_path = self._is_framework_file(dest_path) + if framework_path: + parent_path = framework_path.parent + remaining_path = dest_path.relative_to(parent_path) + else: + parent_path = dest_path.parent + remaining_path = dest_path.name + + sanitized_dest_path = pathlib.PurePath( + *parent_path.parts[:2], # Contents/Frameworks + *[part.replace('.', DOT_REPLACEMENT) for part in parent_path.parts[2:]], + remaining_path, + ) + sanitized_dest_name = str(sanitized_dest_path) + + if sanitized_dest_path != dest_path: + logger.debug("Sanitizing dest path: %r -> %r", dest_name, sanitized_dest_name) + + sanitized_toc.append((sanitized_dest_name, src_name, typecode)) + + bundle_toc = sanitized_toc + + # Normalize and sort the TOC for easier inspection + bundle_toc = sorted(normalize_toc(bundle_toc)) + + return bundle_toc + + def assemble(self): + from PyInstaller.config import CONF + + if _check_path_overlap(self.name) and os.path.isdir(self.name): + _rmtree(self.name) + + logger.info("Building BUNDLE %s", self.tocbasename) + + # Create a minimal Mac bundle structure. + os.makedirs(os.path.join(self.name, "Contents", "MacOS")) + os.makedirs(os.path.join(self.name, "Contents", "Resources")) + os.makedirs(os.path.join(self.name, "Contents", "Frameworks")) + + # Makes sure the icon exists and attempts to convert to the proper format if applicable + self.icon = normalize_icon_type(self.icon, ("icns",), "icns", CONF["workpath"]) + + # Ensure icon path is absolute + self.icon = os.path.abspath(self.icon) + + # Copy icns icon to Resources directory. + shutil.copyfile(self.icon, os.path.join(self.name, 'Contents', 'Resources', os.path.basename(self.icon))) + + # Key/values for a minimal Info.plist file + info_plist_dict = { + "CFBundleDisplayName": self.appname, + "CFBundleName": self.appname, + + # Required by 'codesign' utility. + # The value for CFBundleIdentifier is used as the default unique name of your program for Code Signing + # purposes. It even identifies the APP for access to restricted OS X areas like Keychain. + # + # The identifier used for signing must be globally unique. The usual form for this identifier is a + # hierarchical name in reverse DNS notation, starting with the toplevel domain, followed by the company + # name, followed by the department within the company, and ending with the product name. Usually in the + # form: com.mycompany.department.appname + # CLI option --osx-bundle-identifier sets this value. + "CFBundleIdentifier": self.bundle_identifier, + "CFBundleExecutable": os.path.basename(self.exename), + "CFBundleIconFile": os.path.basename(self.icon), + "CFBundleInfoDictionaryVersion": "6.0", + "CFBundlePackageType": "APPL", + "CFBundleShortVersionString": self.version, + } + + # Set some default values. But they still can be overwritten by the user. + if self.console: + # Setting EXE console=True implies LSBackgroundOnly=True. + info_plist_dict['LSBackgroundOnly'] = True + else: + # Let's use high resolution by default. + info_plist_dict['NSHighResolutionCapable'] = True + + # Merge info_plist settings from spec file + if isinstance(self.info_plist, dict) and self.info_plist: + info_plist_dict.update(self.info_plist) + + plist_filename = os.path.join(self.name, "Contents", "Info.plist") + with open(plist_filename, "wb") as plist_fh: + plistlib.dump(info_plist_dict, plist_fh) + + # Pre-process the TOC into its final BUNDLE-compatible form. + bundle_toc = self._process_bundle_toc(self.toc) + + # Perform the actual collection. + CONTENTS_FRAMEWORKS_PATH = pathlib.PurePath('Contents/Frameworks') + for dest_name, src_name, typecode in bundle_toc: + # Create parent directory structure, if necessary + dest_path = os.path.join(self.name, dest_name) # Absolute destination path + dest_dir = os.path.dirname(dest_path) + try: + os.makedirs(dest_dir, exist_ok=True) + except FileExistsError: + raise SystemExit( + f"Pyinstaller needs to create a directory at {dest_dir!r}, " + "but there already exists a file at that path!" + ) + # Copy extensions and binaries from cache. This ensures that these files undergo additional binary + # processing - have paths to linked libraries rewritten (relative to `@rpath`) and have rpath set to the + # top-level directory (relative to `@loader_path`, i.e., the file's location). The "top-level" directory + # in this case corresponds to `Contents/MacOS` (where `sys._MEIPASS` also points), so we need to pass + # the cache retrieval function the *original* destination path (which is without preceding + # `Contents/MacOS`). + if typecode in ('EXTENSION', 'BINARY'): + orig_dest_name = str(pathlib.PurePath(dest_name).relative_to(CONTENTS_FRAMEWORKS_PATH)) + src_name = process_collected_binary( + src_name, + orig_dest_name, + use_strip=self.strip, + use_upx=self.upx, + upx_exclude=self.upx_exclude, + target_arch=self.target_arch, + codesign_identity=self.codesign_identity, + entitlements_file=self.entitlements_file, + strict_arch_validation=(typecode == 'EXTENSION'), + ) + if typecode == 'SYMLINK': + os.symlink(src_name, dest_path) # Create link at dest_path, pointing at (relative) src_name + else: + # BUNDLE does not support MERGE-based multipackage + assert typecode != 'DEPENDENCY', "MERGE DEPENDENCY entries are not supported in BUNDLE!" + + # At this point, `src_name` should be a valid file. + if not os.path.isfile(src_name): + raise ValueError(f"Resource {src_name!r} is not a valid file!") + # If strict collection mode is enabled, the destination should not exist yet. + if strict_collect_mode and os.path.exists(dest_path): + raise ValueError( + f"Attempting to collect a duplicated file into BUNDLE: {dest_name} (type: {typecode})" + ) + # Use `shutil.copyfile` to copy file with default permissions. We do not attempt to preserve original + # permissions nor metadata, as they might be too restrictive and cause issues either during subsequent + # re-build attempts or when trying to move the application bundle. For binaries (and data files with + # executable bit set), we manually set the executable bits after copying the file. + shutil.copyfile(src_name, dest_path) + if ( + typecode in ('EXTENSION', 'BINARY', 'EXECUTABLE') + or (typecode == 'DATA' and os.access(src_name, os.X_OK)) + ): + os.chmod(dest_path, 0o755) + + # Sign the bundle + logger.info('Signing the BUNDLE...') + try: + osxutils.sign_binary(self.name, self.codesign_identity, self.entitlements_file, deep=True) + except Exception as e: + # Display a warning or re-raise the error, depending on the environment-variable setting. + if os.environ.get("PYINSTALLER_STRICT_BUNDLE_CODESIGN_ERROR", "0") == "0": + logger.warning("Error while signing the bundle: %s", e) + logger.warning("You will need to sign the bundle manually!") + else: + raise RuntimeError("Failed to codesign the bundle!") from e + + logger.info("Building BUNDLE %s completed successfully.", self.tocbasename) + + # Optionally verify bundle's signature. This is primarily intended for our CI. + if os.environ.get("PYINSTALLER_VERIFY_BUNDLE_SIGNATURE", "0") != "0": + logger.info("Verifying signature for BUNDLE %s...", self.name) + self.verify_bundle_signature(self.name) + logger.info("BUNDLE verification complete!") + + @staticmethod + def verify_bundle_signature(bundle_dir): + # First, verify the bundle signature using codesign. + cmd_args = ['/usr/bin/codesign', '--verify', '--all-architectures', '--deep', '--strict', bundle_dir] + p = subprocess.run(cmd_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding='utf8') + if p.returncode: + raise SystemError( + f"codesign command ({cmd_args}) failed with error code {p.returncode}!\noutput: {p.stdout}" + ) + + # Ensure that code-signing information is *NOT* embedded in the files' extended attributes. + # + # This happens when files other than binaries are present in `Contents/MacOS` or `Contents/Frameworks` + # directory; as the signature cannot be embedded within the file itself (contrary to binaries with + # `LC_CODE_SIGNATURE` section in their header), it ends up stores in the file's extended attributes. However, + # if such bundle is transferred using a method that does not support extended attributes (for example, a zip + # file), the signatures on these files are lost, and the signature of the bundle as a whole becomes invalid. + # This is the primary reason why we need to relocate non-binaries into `Contents/Resources` - the signatures + # for files in that directory end up stored in `Contents/_CodeSignature/CodeResources` file. + # + # This check therefore aims to ensure that all files have been properly relocated to their corresponding + # locations w.r.t. the code-signing requirements. + + try: + import xattr + except ModuleNotFoundError: + logger.info("xattr package not available; skipping verification of extended attributes!") + return + + CODESIGN_ATTRS = ( + "com.apple.cs.CodeDirectory", + "com.apple.cs.CodeRequirements", + "com.apple.cs.CodeRequirements-1", + "com.apple.cs.CodeSignature", + ) + + for entry in pathlib.Path(bundle_dir).rglob("*"): + if not entry.is_file(): + continue + + file_attrs = xattr.listxattr(entry) + if any([codesign_attr in file_attrs for codesign_attr in CODESIGN_ATTRS]): + raise ValueError(f"Code-sign attributes found in extended attributes of {str(entry)!r}!") diff --git a/venv/Lib/site-packages/PyInstaller/building/splash.py b/venv/Lib/site-packages/PyInstaller/building/splash.py new file mode 100644 index 0000000..1f1371b --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/building/splash.py @@ -0,0 +1,442 @@ +# ----------------------------------------------------------------------------- +# 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) +# ----------------------------------------------------------------------------- +import io +import os +import re +import struct +import pathlib + +from PyInstaller import log as logging +from PyInstaller.archive.writers import SplashWriter +from PyInstaller.building import splash_templates +from PyInstaller.building.datastruct import Target +from PyInstaller.building.utils import _check_guts_eq, _check_guts_toc, misc +from PyInstaller.compat import is_darwin +from PyInstaller.depend import bindepend +from PyInstaller.utils.hooks.tcl_tk import tcltk_info + +try: + from PIL import Image as PILImage +except ImportError: + PILImage = None + +logger = logging.getLogger(__name__) + +# These requirement files are checked against the current splash screen script. If you wish to modify the splash screen +# and run into tcl errors/bad behavior, this is a good place to start and add components your implementation of the +# splash screen might use. +# NOTE: these paths use the *destination* layout for Tcl/Tk scripts, which uses unversioned tcl and tk directories +# (see `PyInstaller.utils.hooks.tcl_tk.collect_tcl_tk_files`). +splash_requirements = [ + # prepended tcl/tk binaries + os.path.join(tcltk_info.TK_ROOTNAME, "license.terms"), + os.path.join(tcltk_info.TK_ROOTNAME, "text.tcl"), + os.path.join(tcltk_info.TK_ROOTNAME, "tk.tcl"), + # Used for customizable font + os.path.join(tcltk_info.TK_ROOTNAME, "ttk", "ttk.tcl"), + os.path.join(tcltk_info.TK_ROOTNAME, "ttk", "fonts.tcl"), + os.path.join(tcltk_info.TK_ROOTNAME, "ttk", "cursors.tcl"), + os.path.join(tcltk_info.TK_ROOTNAME, "ttk", "utils.tcl"), +] + + +class Splash(Target): + """ + Bundles the required resources for the splash screen into a file, which will be included in the CArchive. + + A Splash has two outputs, one is itself and one is stored in splash.binaries. Both need to be passed to other + build targets in order to enable the splash screen. + """ + def __init__(self, image_file, binaries, datas, **kwargs): + """ + :param str image_file: + A path-like object to the image to be used. Only the PNG file format is supported. + + .. note:: If a different file format is supplied and PIL (Pillow) is installed, the file will be converted + automatically. + + .. note:: *Windows*: The color ``'magenta'`` / ``'#ff00ff'`` must not be used in the image or text, as it is + used by splash screen to indicate transparent areas. Use a similar color (e.g., ``'#ff00fe'``) instead. + + .. note:: If PIL (Pillow) is installed and the image is bigger than max_img_size, the image will be resized + to fit into the specified area. + :param list binaries: + The TOC list of binaries the Analysis build target found. This TOC includes all extension modules and their + binary dependencies. This is required to determine whether the user's program uses `tkinter`. + :param list datas: + The TOC list of data the Analysis build target found. This TOC includes all data-file dependencies of the + modules. This is required to check if all splash screen requirements can be bundled. + + :keyword text_pos: + An optional two-integer tuple that represents the origin of the text on the splash screen image. The + origin of the text is its lower left corner. A unit in the respective coordinate system is a pixel of the + image, its origin lies in the top left corner of the image. This parameter also acts like a switch for + the text feature. If omitted, no text will be displayed on the splash screen. This text will be used to + show textual progress in onefile mode. + :type text_pos: Tuple[int, int] + :keyword text_size: + The desired size of the font. If the size argument is a positive number, it is interpreted as a size in + points. If size is a negative number, its absolute value is interpreted as a size in pixels. Default: ``12`` + :type text_size: int + :keyword text_font: + An optional name of a font for the text. This font must be installed on the user system, otherwise the + system default font is used. If this parameter is omitted, the default font is also used. + :keyword text_color: + An optional color for the text. HTML color codes (``'#40e0d0'``) and color names (``'turquoise'``) are + supported. Default: ``'black'`` + (Windows: the color ``'magenta'`` / ``'#ff00ff'`` is used to indicate transparency, and should not be used) + :type text_color: str + :keyword text_default: + The default text which will be displayed before the extraction starts. Default: ``"Initializing"`` + :type text_default: str + :keyword full_tk: + By default Splash bundles only the necessary files for the splash screen (some tk components). This + options enables adding full tk and making it a requirement, meaning all tk files will be unpacked before + the splash screen can be started. This is useful during development of the splash screen script. + Default: ``False`` + :type full_tk: bool + :keyword minify_script: + The splash screen is created by executing an Tcl/Tk script. This option enables minimizing the script, + meaning removing all non essential parts from the script. Default: ``True`` + :keyword name: + An optional alternative filename for the .res file. If not specified, a name is generated. + :type name: str + :keyword script_name: + An optional alternative filename for the Tcl script, that will be generated. If not specified, a name is + generated. + :type script_name: str + :keyword max_img_size: + Maximum size of the splash screen image as a tuple. If the supplied image exceeds this limit, it will be + resized to fit the maximum width (to keep the original aspect ratio). This option can be disabled by + setting it to None. Default: ``(760, 480)`` + :type max_img_size: Tuple[int, int] + :keyword always_on_top: + Force the splashscreen to be always on top of other windows. If disabled, other windows (e.g., from other + applications) can cover the splash screen by user bringing them to front. This might be useful for + frozen applications with long startup times. Default: ``True`` + :type always_on_top: bool + """ + from ..config import CONF + Target.__init__(self) + + # Splash screen is not supported on macOS. It operates in a secondary thread and macOS disallows UI operations + # in any thread other than main. + if is_darwin: + raise SystemExit("Splash screen is not supported on macOS.") + + # Ensure tkinter (and thus Tcl/Tk) is available. + if not tcltk_info.available: + raise SystemExit( + "Your platform does not support the splash screen feature, since tkinter is not installed. Please " + "install tkinter and try again." + ) + + # Check if the Tcl/Tk version is supported. + self._check_tcl_tk_compatibility() + + # Make image path relative to .spec file + if not os.path.isabs(image_file): + image_file = os.path.join(CONF['specpath'], image_file) + image_file = os.path.normpath(image_file) + if not os.path.exists(image_file): + raise ValueError("Image file '%s' not found" % image_file) + + # Copy all arguments + self.image_file = image_file + self.full_tk = kwargs.get("full_tk", False) + self.name = kwargs.get("name", None) + self.script_name = kwargs.get("script_name", None) + self.minify_script = kwargs.get("minify_script", True) + self.max_img_size = kwargs.get("max_img_size", (760, 480)) + + # text options + self.text_pos = kwargs.get("text_pos", None) + self.text_size = kwargs.get("text_size", 12) + self.text_font = kwargs.get("text_font", "TkDefaultFont") + self.text_color = kwargs.get("text_color", "black") + self.text_default = kwargs.get("text_default", "Initializing") + + # always-on-top behavior + self.always_on_top = kwargs.get("always_on_top", True) + + # Save the generated file separately so that it is not necessary to generate the data again and again + root = os.path.splitext(self.tocfilename)[0] + if self.name is None: + self.name = root + '.res' + if self.script_name is None: + self.script_name = root + '_script.tcl' + + # Internal variables + # Store path to _tkinter extension module, so that guts check can detect if the path changed for some reason. + self._tkinter_file = tcltk_info.tkinter_extension_file + + # Calculated / analysed values + self.uses_tkinter = self._uses_tkinter(self._tkinter_file, binaries) + logger.debug("Program uses tkinter: %r", self.uses_tkinter) + self.script = self.generate_script() + self.tcl_lib = tcltk_info.tcl_shared_library # full path to shared library + self.tk_lib = tcltk_info.tk_shared_library + + assert self.tcl_lib is not None + assert self.tk_lib is not None + + logger.debug("Using Tcl shared library: %r", self.tcl_lib) + logger.debug("Using Tk shared library: %r", self.tk_lib) + + self.splash_requirements = set([ + # NOTE: the implicit assumption here is that Tcl and Tk shared library are collected into top-level + # application directory, which, at tme moment, is true in practically all cases. + os.path.basename(self.tcl_lib), + os.path.basename(self.tk_lib), + *splash_requirements, + ]) + + logger.info("Collect Tcl/Tk data files for the splash screen") + tcltk_tree = tcltk_info.data_files # 3-element tuple TOC + if self.full_tk: + # The user wants a full copy of Tk, so make all Tk files a requirement. + self.splash_requirements.update(entry[0] for entry in tcltk_tree) + + # Scan for binary dependencies of the Tcl/Tk shared libraries, and add them to `binaries` TOC list (which + # should really be called `dependencies` as it is not limited to binaries. But it is too late now, and + # existing spec files depend on this naming). We specify these binary dependencies (which include the + # Tcl and Tk shared libaries themselves) even if the user's program uses tkinter and they would be collected + # anyway; let the collection mechanism deal with potential duplicates. + tcltk_libs = [(os.path.basename(src_name), src_name, 'BINARY') for src_name in (self.tcl_lib, self.tk_lib)] + self.binaries = bindepend.binary_dependency_analysis(tcltk_libs) + + # Put all shared library dependencies in `splash_requirements`, so they are made available in onefile mode. + self.splash_requirements.update(entry[0] for entry in self.binaries) + + # If the user's program does not use tkinter, add resources from Tcl/Tk tree to the dependencies list. + # Do so only for the resources that are part of splash requirements. + if not self.uses_tkinter: + self.binaries.extend(entry for entry in tcltk_tree if entry[0] in self.splash_requirements) + + # Check if all requirements were found. + collected_files = set(entry[0] for entry in (binaries + datas + self.binaries)) + + def _filter_requirement(filename): + if filename not in collected_files: + # Item is not bundled, so warn the user about it. This actually may happen on some tkinter installations + # that are missing the license.terms file. + logger.warning( + "The local Tcl/Tk installation is missing the file %s. The behavior of the splash screen is " + "therefore undefined and may be unsupported.", filename + ) + return False + return True + + # Remove all files which were not found. + self.splash_requirements = set(filter(_filter_requirement, self.splash_requirements)) + + logger.debug("Splash Requirements: %s", self.splash_requirements) + + self.__postinit__() + + _GUTS = ( + # input parameters + ('image_file', _check_guts_eq), + ('name', _check_guts_eq), + ('script_name', _check_guts_eq), + ('text_pos', _check_guts_eq), + ('text_size', _check_guts_eq), + ('text_font', _check_guts_eq), + ('text_color', _check_guts_eq), + ('text_default', _check_guts_eq), + ('always_on_top', _check_guts_eq), + ('full_tk', _check_guts_eq), + ('minify_script', _check_guts_eq), + ('max_img_size', _check_guts_eq), + # calculated/analysed values + ('uses_tkinter', _check_guts_eq), + ('script', _check_guts_eq), + ('tcl_lib', _check_guts_eq), + ('tk_lib', _check_guts_eq), + ('splash_requirements', _check_guts_eq), + ('binaries', _check_guts_toc), + # internal value + # Check if the tkinter installation changed. This is theoretically possible if someone uses two different python + # installations of the same version. + ('_tkinter_file', _check_guts_eq), + ) + + def _check_guts(self, data, last_build): + if Target._check_guts(self, data, last_build): + return True + + # Check if the image has been modified. + if misc.mtime(self.image_file) > last_build: + logger.info("Building %s because file %s changed", self.tocbasename, self.image_file) + return True + + return False + + def assemble(self): + logger.info("Building Splash %s", self.name) + + # Function to resize a given image to fit into the area defined by max_img_size. + def _resize_image(_image, _orig_size): + if PILImage: + _w, _h = _orig_size + _ratio_w = self.max_img_size[0] / _w + if _ratio_w < 1: + # Image width exceeds limit + _h = int(_h * _ratio_w) + _w = self.max_img_size[0] + + _ratio_h = self.max_img_size[1] / _h + if _ratio_h < 1: + # Image height exceeds limit + _w = int(_w * _ratio_h) + _h = self.max_img_size[1] + + # If a file is given it will be open + if isinstance(_image, PILImage.Image): + _img = _image + else: + _img = PILImage.open(_image) + _img_resized = _img.resize((_w, _h)) + + # Save image into a stream + _image_stream = io.BytesIO() + _img_resized.save(_image_stream, format='PNG') + _img.close() + _img_resized.close() + _image_data = _image_stream.getvalue() + logger.info("Resized image %s from dimensions %r to (%d, %d)", self.image_file, _orig_size, _w, _h) + return _image_data + else: + raise ValueError( + "The splash image dimensions (w: %d, h: %d) exceed max_img_size (w: %d, h:%d), but the image " + "cannot be resized due to missing PIL.Image! Either install the Pillow package, adjust the " + "max_img_size, or use an image of compatible dimensions." % + (_orig_size[0], _orig_size[1], self.max_img_size[0], self.max_img_size[1]) + ) + + # Open image file + image_file = open(self.image_file, 'rb') + + # Check header of the file to identify it + if image_file.read(8) == b'\x89PNG\r\n\x1a\n': + # self.image_file is a PNG file + image_file.seek(16) + img_size = (struct.unpack("!I", image_file.read(4))[0], struct.unpack("!I", image_file.read(4))[0]) + + if img_size > self.max_img_size: + # The image exceeds the maximum image size, so resize it + image = _resize_image(self.image_file, img_size) + else: + image = os.path.abspath(self.image_file) + elif PILImage: + # Pillow is installed, meaning the image can be converted automatically + img = PILImage.open(self.image_file, mode='r') + + if img.size > self.max_img_size: + image = _resize_image(img, img.size) + else: + image_data = io.BytesIO() + img.save(image_data, format='PNG') + img.close() + image = image_data.getvalue() + logger.info("Converted image %s to PNG format", self.image_file) + else: + raise ValueError( + "The image %s needs to be converted to a PNG file, but PIL.Image is not available! Either install the " + "Pillow package, or use a PNG image for you splash screen." % (self.image_file,) + ) + + image_file.close() + + SplashWriter( + self.name, + self.splash_requirements, + os.path.basename(self.tcl_lib), # tcl86t.dll + os.path.basename(self.tk_lib), # tk86t.dll + tcltk_info.TK_ROOTNAME, + image, + self.script + ) + + @staticmethod + def _check_tcl_tk_compatibility(): + tcl_version = tcltk_info.tcl_version # (major, minor) tuple + tk_version = tcltk_info.tk_version + + if is_darwin and tcltk_info.is_macos_system_framework: + # Outdated Tcl/Tk 8.5 system framework is not supported. + raise SystemExit("The splash screen feature does not support macOS system framework version of Tcl/Tk.") + + # Test if tcl/tk version is supported + if tcl_version < (8, 6) or tk_version < (8, 6): + logger.warning( + "The installed Tcl/Tk (%d.%d / %d.%d) version might not work with the splash screen feature of the " + "bootloader, which was tested against Tcl/Tk 8.6", *tcl_version, *tk_version + ) + + # This should be impossible, since tcl/tk is released together with the same version number, but just in case + if tcl_version != tk_version: + logger.warning( + "The installed version of Tcl (%d.%d) and Tk (%d.%d) do not match. PyInstaller is tested against " + "matching versions", *tcl_version, *tk_version + ) + + # Ensure that Tcl is built with multi-threading support. + if not tcltk_info.tcl_threaded: + # This is a feature breaking problem, so exit. + raise SystemExit( + "The installed Tcl version is not threaded. PyInstaller only supports the splash screen " + "using threaded Tcl." + ) + + def generate_script(self): + """ + Generate the script for the splash screen. + + If minify_script is True, all unnecessary parts will be removed. + """ + d = {} + if self.text_pos is not None: + logger.debug("Add text support to splash screen") + d.update({ + 'pad_x': self.text_pos[0], + 'pad_y': self.text_pos[1], + 'color': self.text_color, + 'font': self.text_font, + 'font_size': self.text_size, + 'default_text': self.text_default, + }) + script = splash_templates.build_script(text_options=d, always_on_top=self.always_on_top) + + if self.minify_script: + # Remove any documentation, empty lines and unnecessary spaces + script = '\n'.join( + line for line in map(lambda line: line.strip(), script.splitlines()) + if not line.startswith('#') # documentation + and line # empty lines + ) + # Remove unnecessary spaces + script = re.sub(' +', ' ', script) + + # Write script to disk, so that it is transparent to the user what script is executed. + with open(self.script_name, "w", encoding="utf-8") as script_file: + script_file.write(script) + return script + + @staticmethod + def _uses_tkinter(tkinter_file, binaries): + # Test for _tkinter extension instead of tkinter module, because user might use a different wrapping library for + # Tk. Use `pathlib.PurePath˙ in comparisons to account for case normalization and separator normalization. + tkinter_file = pathlib.PurePath(tkinter_file) + for dest_name, src_name, typecode in binaries: + if pathlib.PurePath(src_name) == tkinter_file: + return True + return False diff --git a/venv/Lib/site-packages/PyInstaller/building/splash_templates.py b/venv/Lib/site-packages/PyInstaller/building/splash_templates.py new file mode 100644 index 0000000..e93c696 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/building/splash_templates.py @@ -0,0 +1,229 @@ +# ----------------------------------------------------------------------------- +# 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) +# ----------------------------------------------------------------------------- +""" +Templates for the splash screen tcl script. +""" +from PyInstaller.compat import is_cygwin, is_darwin, is_win + +ipc_script = r""" +proc _ipc_server {channel clientaddr clientport} { + # This function is called if a new client connects to + # the server. This creates a channel, which calls + # _ipc_caller if data was send through the connection + set client_name [format <%s:%d> $clientaddr $clientport] + + chan configure $channel \ + -buffering none \ + -encoding utf-8 \ + -eofchar \x04 \ + -translation cr + chan event $channel readable [list _ipc_caller $channel $client_name] +} + +proc _ipc_caller {channel client_name} { + # This function is called if a command was sent through + # the tcp connection. The current implementation supports + # two commands: update_text and exit, although exit + # is implemented to be called if the connection gets + # closed (from python) or the character 0x04 was received + chan gets $channel cmd + + if {[chan eof $channel]} { + # This is entered if either the connection was closed + # or the char 0x04 was send + chan close $channel + exit + + } elseif {![chan blocked $channel]} { + # RPC methods + + # update_text command + if {[string match "update_text*" $cmd]} { + global status_text + set first [expr {[string first "(" $cmd] + 1}] + set last [expr {[string last ")" $cmd] - 1}] + + set status_text [string range $cmd $first $last] + } + # Implement other procedures here + } +} + +# By setting the port to 0 the os will assign a free port +set server_socket [socket -server _ipc_server -myaddr localhost 0] +set server_port [fconfigure $server_socket -sockname] + +# This environment variable is shared between the python and the tcl +# interpreter and publishes the port the tcp server socket is available +set env(_PYI_SPLASH_IPC) [lindex $server_port 2] +""" + +image_script = r""" +# The variable $_image_data, which holds the data for the splash +# image is created by the bootloader. +image create photo splash_image +splash_image put $_image_data +# delete the variable, because the image now holds the data +unset _image_data + +proc canvas_text_update {canvas tag _var - -} { + # This function is rigged to be called if the a variable + # status_text gets changed. This updates the text on + # the canvas + upvar $_var var + $canvas itemconfigure $tag -text $var +} +""" + +splash_canvas_setup = r""" +package require Tk + +set image_width [image width splash_image] +set image_height [image height splash_image] +set display_width [winfo screenwidth .] +set display_height [winfo screenheight .] + +set x_position [expr {int(0.5*($display_width - $image_width))}] +set y_position [expr {int(0.5*($display_height - $image_height))}] + +# Toplevel frame in which all widgets should be positioned +frame .root + +# Configure the canvas on which the splash +# screen will be drawn +canvas .root.canvas \ + -width $image_width \ + -height $image_height \ + -borderwidth 0 \ + -highlightthickness 0 + +# Draw the image into the canvas, filling it. +.root.canvas create image \ + [expr {$image_width / 2}] \ + [expr {$image_height / 2}] \ + -image splash_image +""" + +splash_canvas_text = r""" +# Create a text on the canvas, which tracks the local +# variable status_text. status_text is changed via C to +# update the progress on the splash screen. +# We cannot use the default label, because it has a +# default background, which cannot be turned transparent +.root.canvas create text \ + %(pad_x)d \ + %(pad_y)d \ + -fill %(color)s \ + -justify center \ + -font myFont \ + -tag vartext \ + -anchor sw +trace variable status_text w \ + [list canvas_text_update .root.canvas vartext] +set status_text "%(default_text)s" +""" + +splash_canvas_default_font = r""" +font create myFont {*}[font actual TkDefaultFont] +font configure myFont -size %(font_size)d +""" + +splash_canvas_custom_font = r""" +font create myFont -family %(font)s -size %(font_size)d +""" + +if is_win or is_cygwin: + transparent_setup = r""" +# If the image is transparent, the background will be filled +# with magenta. The magenta background is later replaced with transparency. +# Here is the limitation of this implementation, that only +# sharp transparent image corners are possible +wm attributes . -transparentcolor magenta +.root.canvas configure -background magenta +""" + +elif is_darwin: + # This is untested, but should work following: https://stackoverflow.com/a/44296157/5869139 + transparent_setup = r""" +wm attributes . -transparent 1 +. configure -background systemTransparent +.root.canvas configure -background systemTransparent +""" + +else: + # For Linux there is no common way to create a transparent window + transparent_setup = r"" + +pack_widgets = r""" +# Position all widgets in the window +pack .root +grid .root.canvas -column 0 -row 0 -columnspan 1 -rowspan 2 +""" + +# Enable always-on-top behavior, by setting overrideredirect and the topmost attribute. +position_window_on_top = r""" +# Set position and mode of the window - always-on-top behavior +wm overrideredirect . 1 +wm geometry . +${x_position}+${y_position} +wm attributes . -topmost 1 +""" + +# Disable always-on-top behavior +if is_win or is_cygwin or is_darwin: + # On Windows, we disable the always-on-top behavior while still setting overrideredirect + # (to disable window decorations), but set topmost attribute to 0. + position_window = r""" +# Set position and mode of the window +wm overrideredirect . 1 +wm geometry . +${x_position}+${y_position} +wm attributes . -topmost 0 +""" +else: + # On Linux, we must not use overrideredirect; instead, we set X11-specific type attribute to splash, + # which lets the window manager to properly handle the splash screen (without window decorations + # but allowing other windows to be brought to front). + position_window = r""" +# Set position and mode of the window +wm geometry . +${x_position}+${y_position} +wm attributes . -type splash +""" + +raise_window = r""" +raise . +""" + + +def build_script(text_options=None, always_on_top=False): + """ + This function builds the tcl script for the splash screen. + """ + # Order is important! + script = [ + ipc_script, + image_script, + splash_canvas_setup, + ] + + if text_options: + # If the default font is used we need a different syntax + if text_options['font'] == "TkDefaultFont": + script.append(splash_canvas_default_font % text_options) + else: + script.append(splash_canvas_custom_font % text_options) + script.append(splash_canvas_text % text_options) + + script.append(transparent_setup) + + script.append(pack_widgets) + script.append(position_window_on_top if always_on_top else position_window) + script.append(raise_window) + + return '\n'.join(script) diff --git a/venv/Lib/site-packages/PyInstaller/building/templates.py b/venv/Lib/site-packages/PyInstaller/building/templates.py new file mode 100644 index 0000000..24e5080 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/building/templates.py @@ -0,0 +1,126 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- +""" +Templates to generate .spec files. +""" + +onefiletmplt = """# -*- mode: python ; coding: utf-8 -*- +%(preamble)s + +a = Analysis( + %(scripts)s, + pathex=%(pathex)s, + binaries=%(binaries)s, + datas=%(datas)s, + hiddenimports=%(hiddenimports)s, + hookspath=%(hookspath)r, + hooksconfig={}, + runtime_hooks=%(runtime_hooks)r, + excludes=%(excludes)s, + noarchive=%(noarchive)s, + optimize=%(optimize)r, +) +pyz = PYZ(a.pure) +%(splash_init)s +exe = EXE( + pyz, + a.scripts, + a.binaries, + a.datas,%(splash_target)s%(splash_binaries)s + %(options)s, + name='%(name)s', + debug=%(debug_bootloader)s, + bootloader_ignore_signals=%(bootloader_ignore_signals)s, + strip=%(strip)s, + upx=%(upx)s, + upx_exclude=%(upx_exclude)s, + runtime_tmpdir=%(runtime_tmpdir)r, + console=%(console)s, + disable_windowed_traceback=%(disable_windowed_traceback)s, + argv_emulation=%(argv_emulation)r, + target_arch=%(target_arch)r, + codesign_identity=%(codesign_identity)r, + entitlements_file=%(entitlements_file)r,%(exe_options)s +) +""" + +onedirtmplt = """# -*- mode: python ; coding: utf-8 -*- +%(preamble)s + +a = Analysis( + %(scripts)s, + pathex=%(pathex)s, + binaries=%(binaries)s, + datas=%(datas)s, + hiddenimports=%(hiddenimports)s, + hookspath=%(hookspath)r, + hooksconfig={}, + runtime_hooks=%(runtime_hooks)r, + excludes=%(excludes)s, + noarchive=%(noarchive)s, + optimize=%(optimize)r, +) +pyz = PYZ(a.pure) +%(splash_init)s +exe = EXE( + pyz, + a.scripts,%(splash_target)s + %(options)s, + exclude_binaries=True, + name='%(name)s', + debug=%(debug_bootloader)s, + bootloader_ignore_signals=%(bootloader_ignore_signals)s, + strip=%(strip)s, + upx=%(upx)s, + console=%(console)s, + disable_windowed_traceback=%(disable_windowed_traceback)s, + argv_emulation=%(argv_emulation)r, + target_arch=%(target_arch)r, + codesign_identity=%(codesign_identity)r, + entitlements_file=%(entitlements_file)r,%(exe_options)s +) +coll = COLLECT( + exe, + a.binaries, + a.datas,%(splash_binaries)s + strip=%(strip)s, + upx=%(upx)s, + upx_exclude=%(upx_exclude)s, + name='%(name)s', +) +""" + +bundleexetmplt = """app = BUNDLE( + exe, + name='%(name)s.app', + icon=%(icon)s, + bundle_identifier=%(bundle_identifier)s, +) +""" + +bundletmplt = """app = BUNDLE( + coll, + name='%(name)s.app', + icon=%(icon)s, + bundle_identifier=%(bundle_identifier)s, +) +""" + +splashtmpl = """splash = Splash( + %(splash_image)r, + binaries=a.binaries, + datas=a.datas, + text_pos=None, + text_size=12, + minify_script=True, + always_on_top=True, +) +""" diff --git a/venv/Lib/site-packages/PyInstaller/building/utils.py b/venv/Lib/site-packages/PyInstaller/building/utils.py new file mode 100644 index 0000000..f32c069 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/building/utils.py @@ -0,0 +1,805 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +import fnmatch +import glob +import hashlib +import marshal +import os +import pathlib +import platform +import py_compile +import shutil +import struct +import subprocess +import sys +import zipfile + +from PyInstaller import compat +from PyInstaller import log as logging +from PyInstaller.compat import EXTENSION_SUFFIXES, is_darwin, is_win, is_linux +from PyInstaller.config import CONF +from PyInstaller.exceptions import InvalidSrcDestTupleError +from PyInstaller.utils import misc + +if is_win: + from PyInstaller.utils.win32 import versioninfo + +if is_darwin: + import PyInstaller.utils.osx as osxutils + +logger = logging.getLogger(__name__) + +# -- Helpers for checking guts. +# +# NOTE: by _GUTS it is meant intermediate files and data structures that PyInstaller creates for bundling files and +# creating final executable. + + +def _check_guts_eq(attr_name, old_value, new_value, last_build): + """ + Rebuild is required if values differ. + """ + if old_value != new_value: + logger.info("Building because %s changed", attr_name) + return True + return False + + +def _check_guts_toc_mtime(attr_name, old_toc, new_toc, last_build): + """ + Rebuild is required if mtimes of files listed in old TOC are newer than last_build. + + Use this for calculated/analysed values read from cache. + """ + for dest_name, src_name, typecode in old_toc: + if misc.mtime(src_name) > last_build: + logger.info("Building because %s changed", src_name) + return True + return False + + +def _check_guts_toc(attr_name, old_toc, new_toc, last_build): + """ + Rebuild is required if either TOC content changed or mtimes of files listed in old TOC are newer than last_build. + + Use this for input parameters. + """ + return _check_guts_eq(attr_name, old_toc, new_toc, last_build) or \ + _check_guts_toc_mtime(attr_name, old_toc, new_toc, last_build) + + +def add_suffix_to_extension(dest_name, src_name, typecode): + """ + Take a TOC entry (dest_name, src_name, typecode) and adjust the dest_name for EXTENSION to include the full library + suffix. + """ + # No-op for non-extension + if typecode != 'EXTENSION': + return dest_name, src_name, typecode + + # If dest_name completely fits into end of the src_name, it has already been processed. + if src_name.endswith(dest_name): + return dest_name, src_name, typecode + + # Change the dotted name into a relative path. This places C extensions in the Python-standard location. + dest_name = dest_name.replace('.', os.sep) + # In some rare cases extension might already contain a suffix. Skip it in this case. + if os.path.splitext(dest_name)[1] not in EXTENSION_SUFFIXES: + # Determine the base name of the file. + base_name = os.path.basename(dest_name) + assert '.' not in base_name + # Use this file's existing extension. For extensions such as ``libzmq.cp36-win_amd64.pyd``, we cannot use + # ``os.path.splitext``, which would give only the ```.pyd`` part of the extension. + dest_name = dest_name + os.path.basename(src_name)[len(base_name):] + + return dest_name, src_name, typecode + + +def process_collected_binary( + src_name, + dest_name, + use_strip=False, + use_upx=False, + upx_exclude=None, + target_arch=None, + codesign_identity=None, + entitlements_file=None, + strict_arch_validation=False +): + """ + Process the collected binary using strip or UPX (or both), and apply any platform-specific processing. On macOS, + this rewrites the library paths in the headers, and (re-)signs the binary. On-disk cache is used to avoid processing + the same binary with same options over and over. + + In addition to given arguments, this function also uses CONF['cachedir'] and CONF['upx_dir']. + """ + from PyInstaller.config import CONF + + # We need to use cache in the following scenarios: + # * extra binary processing due to use of `strip` or `upx` + # * building on macOS, where we need to rewrite library paths in binaries' headers and (re-)sign the binaries. + if not use_strip and not use_upx and not is_darwin: + return src_name + + # Match against provided UPX exclude patterns. + upx_exclude = upx_exclude or [] + if use_upx: + src_path = pathlib.PurePath(src_name) + for upx_exclude_entry in upx_exclude: + # pathlib.PurePath.match() matches from right to left, and supports * wildcard, but does not support the + # "**" syntax for directory recursion. Case sensitivity follows the OS default. + if src_path.match(upx_exclude_entry): + logger.info("Disabling UPX for %s due to match in exclude pattern: %s", src_name, upx_exclude_entry) + use_upx = False + break + + # Additional automatic disablement rules for UPX and strip. + + # On Windows, avoid using UPX with binaries that have control flow guard (CFG) enabled. + if use_upx and is_win and versioninfo.pefile_check_control_flow_guard(src_name): + logger.info('Disabling UPX for %s due to CFG!', src_name) + use_upx = False + + # Avoid using UPX with Qt plugins, as it strips the data required by the Qt plugin loader. + if use_upx and misc.is_file_qt_plugin(src_name): + logger.info('Disabling UPX for %s due to it being a Qt plugin!', src_name) + use_upx = False + + # On linux, if a binary has an accompanying HMAC or CHK file, avoid modifying it in any way. + if (use_upx or use_strip) and is_linux: + src_path = pathlib.Path(src_name) + hmac_path = src_path.with_name(f".{src_path.name}.hmac") + chk_path = src_path.with_suffix(".chk") + if hmac_path.is_file(): + logger.info('Disabling UPX and/or strip for %s due to accompanying .hmac file!', src_name) + use_upx = use_strip = False + elif chk_path.is_file(): + logger.info('Disabling UPX and/or strip for %s due to accompanying .chk file!', src_name) + use_upx = use_strip = False + del src_path, hmac_path, chk_path + + # Exit early if no processing is required after above rules are applied. + if not use_strip and not use_upx and not is_darwin: + return src_name + + # Prepare cache directory path. Cache is tied to python major/minor version, but also to various processing options. + pyver = f'py{sys.version_info[0]}{sys.version_info[1]}' + arch = platform.architecture()[0] + cache_dir = os.path.join( + CONF['cachedir'], + f'bincache{use_strip:d}{use_upx:d}{pyver}{arch}', + ) + if target_arch: + cache_dir = os.path.join(cache_dir, target_arch) + if is_darwin: + # Separate by codesign identity + if codesign_identity: + # Compute hex digest of codesign identity string to prevent issues with invalid characters. + csi_hash = hashlib.sha256(codesign_identity.encode('utf-8')) + cache_dir = os.path.join(cache_dir, csi_hash.hexdigest()) + else: + cache_dir = os.path.join(cache_dir, 'adhoc') # ad-hoc signing + # Separate by entitlements + if entitlements_file: + # Compute hex digest of entitlements file contents + with open(entitlements_file, 'rb') as fp: + ef_hash = hashlib.sha256(fp.read()) + cache_dir = os.path.join(cache_dir, ef_hash.hexdigest()) + else: + cache_dir = os.path.join(cache_dir, 'no-entitlements') + os.makedirs(cache_dir, exist_ok=True) + + # Load cache index, if available + cache_index_file = os.path.join(cache_dir, "index.dat") + try: + cache_index = misc.load_py_data_struct(cache_index_file) + except FileNotFoundError: + cache_index = {} + except Exception: + # Tell the user they may want to fix their cache... However, do not delete it for them; if it keeps getting + # corrupted, we will never find out. + logger.warning("PyInstaller bincache may be corrupted; use pyinstaller --clean to fix it.") + raise + + # Look up the file in cache; use case-normalized destination name as identifier. + cached_id = os.path.normcase(dest_name) + cached_name = os.path.join(cache_dir, dest_name) + src_digest = _compute_file_digest(src_name) + + if cached_id in cache_index: + # If digest matches to the cached digest, return the cached file... + if src_digest == cache_index[cached_id]: + return cached_name + + # ... otherwise remove it. + os.remove(cached_name) + + # Ensure parent path exists + os.makedirs(os.path.dirname(cached_name), exist_ok=True) + + # Use `shutil.copyfile` to copy the file with default permissions bits, then manually set executable + # bits. This way, we avoid copying permission bits and metadata from the original file, which might be too + # restrictive for further processing (read-only permissions, immutable flag on FreeBSD, and so on). + shutil.copyfile(src_name, cached_name) + os.chmod(cached_name, 0o755) + + # Apply strip + if use_strip: + strip_options = [] + if is_darwin: + # The default strip behavior breaks some shared libraries under macOS. + strip_options = ["-S"] # -S = strip only debug symbols. + + cmd = ["strip", *strip_options, cached_name] + logger.info("Executing: %s", " ".join(cmd)) + try: + p = subprocess.run( + cmd, + stdin=subprocess.DEVNULL, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + check=True, + errors='ignore', + encoding='utf-8', + ) + logger.debug("Output from strip command:\n%s", p.stdout) + except subprocess.CalledProcessError as e: + logger.warning("Failed to run strip on %r!", cached_name, exc_info=True) + logger.warning("Output from strip command:\n%s", e.stdout) + except Exception: + logger.warning("Failed to run strip on %r!", cached_name, exc_info=True) + + # Apply UPX + if use_upx: + upx_exe = 'upx' + upx_dir = CONF['upx_dir'] + if upx_dir: + upx_exe = os.path.join(upx_dir, upx_exe) + + upx_options = [ + # Do not compress icons, so that they can still be accessed externally. + '--compress-icons=0', + # Use LZMA compression. + '--lzma', + # Quiet mode. + '-q', + ] + if is_win: + # Binaries built with Visual Studio 7.1 require --strip-loadconf or they will not compress. + upx_options.append('--strip-loadconf') + + cmd = [upx_exe, *upx_options, cached_name] + logger.info("Executing: %s", " ".join(cmd)) + try: + p = subprocess.run( + cmd, + stdin=subprocess.DEVNULL, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + check=True, + errors='ignore', + encoding='utf-8', + ) + logger.debug("Output from upx command:\n%s", p.stdout) + except subprocess.CalledProcessError as e: + logger.warning("Failed to upx strip on %r!", cached_name, exc_info=True) + logger.warning("Output from upx command:\n%s", e.stdout) + except Exception: + logger.warning("Failed to run upx on %r!", cached_name, exc_info=True) + + # On macOS, we need to modify the given binary's paths to the dependent libraries, in order to ensure they are + # relocatable and always refer to location within the frozen application. Specifically, we make all dependent + # library paths relative to @rpath, and set @rpath to point to the top-level application directory, relative to + # the binary's location (i.e., @loader_path). + # + # While modifying the headers invalidates existing signatures, we avoid removing them in order to speed things up + # (and to avoid potential bugs in the codesign utility, like the one reported on Mac OS 10.13 in #6167). + # The forced re-signing at the end should take care of the invalidated signatures. + if is_darwin: + try: + osxutils.binary_to_target_arch(cached_name, target_arch, display_name=src_name) + #osxutils.remove_signature_from_binary(cached_name) # Disabled as per comment above. + target_rpath = str( + pathlib.PurePath('@loader_path', *['..' for level in pathlib.PurePath(dest_name).parent.parts]) + ) + osxutils.set_dylib_dependency_paths(cached_name, target_rpath) + osxutils.sign_binary(cached_name, codesign_identity, entitlements_file) + except osxutils.InvalidBinaryError: + # Raised by osxutils.binary_to_target_arch when the given file is not a valid macOS binary (for example, + # a linux .so file; see issue #6327). The error prevents any further processing, so just ignore it. + pass + except osxutils.IncompatibleBinaryArchError: + # Raised by osxutils.binary_to_target_arch when the given file does not contain (all) required arch slices. + # Depending on the strict validation mode, re-raise or swallow the error. + # + # Strict validation should be enabled only for binaries where the architecture *must* match the target one, + # i.e., the extension modules. Everything else is pretty much a gray area, for example: + # * a universal2 extension may have its x86_64 and arm64 slices linked against distinct single-arch/thin + # shared libraries + # * a collected executable that is launched by python code via a subprocess can be x86_64-only, even though + # the actual python code is running on M1 in native arm64 mode. + if strict_arch_validation: + raise + logger.debug("File %s failed optional architecture validation - collecting as-is!", src_name) + except Exception as e: + raise SystemError(f"Failed to process binary {cached_name!r}!") from e + + # Update cache index + cache_index[cached_id] = src_digest + misc.save_py_data_struct(cache_index_file, cache_index) + + return cached_name + + +def _compute_file_digest(filename): + hasher = hashlib.sha1() + with open(filename, "rb") as fp: + for chunk in iter(lambda: fp.read(16 * 1024), b""): + hasher.update(chunk) + return bytearray(hasher.digest()) + + +def _check_path_overlap(path): + """ + Check that path does not overlap with WORKPATH or SPECPATH (i.e., WORKPATH and SPECPATH may not start with path, + which could be caused by a faulty hand-edited specfile). + + Raise SystemExit if there is overlap, return True otherwise + """ + from PyInstaller.config import CONF + specerr = 0 + if CONF['workpath'].startswith(path): + logger.error('Specfile error: The output path "%s" contains WORKPATH (%s)', path, CONF['workpath']) + specerr += 1 + if CONF['specpath'].startswith(path): + logger.error('Specfile error: The output path "%s" contains SPECPATH (%s)', path, CONF['specpath']) + specerr += 1 + if specerr: + raise SystemExit( + 'Error: Please edit/recreate the specfile (%s) and set a different output name (e.g. "dist").' % + CONF['spec'] + ) + return True + + +def _make_clean_directory(path): + """ + Create a clean directory from the given directory name. + """ + if _check_path_overlap(path): + if os.path.isdir(path) or os.path.isfile(path): + try: + os.remove(path) + except OSError: + _rmtree(path) + + os.makedirs(path, exist_ok=True) + + +def _rmtree(path): + """ + Remove directory and all its contents, but only after user confirmation, or if the -y option is set. + """ + from PyInstaller.config import CONF + if CONF['noconfirm']: + choice = 'y' + elif sys.stdout.isatty(): + choice = input( + 'WARNING: The output directory "%s" and ALL ITS CONTENTS will be REMOVED! Continue? (y/N)' % path + ) + else: + raise SystemExit( + 'Error: The output directory "%s" is not empty. Please remove all its contents or use the -y option (remove' + ' output directory without confirmation).' % path + ) + if choice.strip().lower() == 'y': + if not CONF['noconfirm']: + print("On your own risk, you can use the option `--noconfirm` to get rid of this question.") + logger.info('Removing dir %s', path) + shutil.rmtree(path) + else: + raise SystemExit('User aborted') + + +# TODO Refactor to prohibit empty target directories. As the docstring below documents, this function currently permits +# the second item of each 2-tuple in "hook.datas" to be the empty string, in which case the target directory defaults to +# the source directory's basename. However, this functionality is very fragile and hence bad. Instead: +# +# * An exception should be raised if such item is empty. +# * All hooks currently passing the empty string for such item (e.g., +# "hooks/hook-babel.py", "hooks/hook-matplotlib.py") should be refactored +# to instead pass such basename. +def format_binaries_and_datas(binaries_or_datas, workingdir=None): + """ + Convert the passed list of hook-style 2-tuples into a returned set of `TOC`-style 2-tuples. + + Elements of the passed list are 2-tuples `(source_dir_or_glob, target_dir)`. + Elements of the returned set are 2-tuples `(target_file, source_file)`. + For backwards compatibility, the order of elements in the former tuples are the reverse of the order of elements in + the latter tuples! + + Parameters + ---------- + binaries_or_datas : list + List of hook-style 2-tuples (e.g., the top-level `binaries` and `datas` attributes defined by hooks) whose: + * The first element is either: + * A glob matching only the absolute or relative paths of source non-Python data files. + * The absolute or relative path of a source directory containing only source non-Python data files. + * The second element is the relative path of the target directory into which these source files will be + recursively copied. + + If the optional `workingdir` parameter is passed, source paths may be either absolute or relative; else, source + paths _must_ be absolute. + workingdir : str + Optional absolute path of the directory to which all relative source paths in the `binaries_or_datas` + parameter will be prepended by (and hence converted into absolute paths) _or_ `None` if these paths are to be + preserved as relative. Defaults to `None`. + + Returns + ---------- + set + Set of `TOC`-style 2-tuples whose: + * First element is the absolute or relative path of a target file. + * Second element is the absolute or relative path of the corresponding source file to be copied to this target + file. + """ + toc_datas = set() + + for src_root_path_or_glob, trg_root_dir in binaries_or_datas: + # Disallow empty source path. Those are typically result of errors, and result in implicit collection of the + # whole current working directory, which is never a good idea. + if not src_root_path_or_glob: + raise InvalidSrcDestTupleError( + (src_root_path_or_glob, trg_root_dir), + "Empty SRC is not allowed when adding binary and data files, as it would result in collection of the " + "whole current working directory." + ) + if not trg_root_dir: + raise InvalidSrcDestTupleError( + (src_root_path_or_glob, trg_root_dir), + "Empty DEST_DIR is not allowed - to collect files into application's top-level directory, use " + f"{os.curdir!r}." + ) + # Disallow absolute target paths, as well as target paths that would end up pointing outside of the + # application's top-level directory. + if os.path.isabs(trg_root_dir): + raise InvalidSrcDestTupleError((src_root_path_or_glob, trg_root_dir), "DEST_DIR must be a relative path!") + if os.path.normpath(trg_root_dir).startswith('..'): + raise InvalidSrcDestTupleError( + (src_root_path_or_glob, trg_root_dir), + "DEST_DIR must not point outside of application's top-level directory!", + ) + + # Convert relative to absolute paths if required. + if workingdir and not os.path.isabs(src_root_path_or_glob): + src_root_path_or_glob = os.path.join(workingdir, src_root_path_or_glob) + + # Normalize paths. + src_root_path_or_glob = os.path.normpath(src_root_path_or_glob) + if os.path.isfile(src_root_path_or_glob): + src_root_paths = [src_root_path_or_glob] + else: + # List of the absolute paths of all source paths matching the current glob. + src_root_paths = glob.glob(src_root_path_or_glob) + + if not src_root_paths: + raise SystemExit(f'Unable to find {src_root_path_or_glob!r} when adding binary and data files.') + + for src_root_path in src_root_paths: + if os.path.isfile(src_root_path): + # Normalizing the result to remove redundant relative paths (e.g., removing "./" from "trg/./file"). + toc_datas.add(( + os.path.normpath(os.path.join(trg_root_dir, os.path.basename(src_root_path))), + os.path.normpath(src_root_path), + )) + elif os.path.isdir(src_root_path): + for src_dir, src_subdir_basenames, src_file_basenames in os.walk(src_root_path): + # Ensure the current source directory is a subdirectory of the passed top-level source directory. + # Since os.walk() does *NOT* follow symlinks by default, this should be the case. (But let's make + # sure.) + assert src_dir.startswith(src_root_path) + + # Relative path of the current target directory, obtained by: + # + # * Stripping the top-level source directory from the current source directory (e.g., removing + # "/top" from "/top/dir"). + # * Normalizing the result to remove redundant relative paths (e.g., removing "./" from + # "trg/./file"). + trg_dir = os.path.normpath(os.path.join(trg_root_dir, os.path.relpath(src_dir, src_root_path))) + + for src_file_basename in src_file_basenames: + src_file = os.path.join(src_dir, src_file_basename) + if os.path.isfile(src_file): + # Normalize the result to remove redundant relative paths (e.g., removing "./" from + # "trg/./file"). + toc_datas.add(( + os.path.normpath(os.path.join(trg_dir, src_file_basename)), os.path.normpath(src_file) + )) + + return toc_datas + + +def get_code_object(modname, filename, optimize): + """ + Get the code-object for a module. + + This is a simplifed non-performant version which circumvents __pycache__. + """ + + if filename in ('-', None): + # This is a NamespacePackage, modulegraph marks them by using the filename '-'. (But wants to use None, so + # check for None, too, to be forward-compatible.) + logger.debug('Compiling namespace package %s', modname) + txt = '#\n' + code_object = compile(txt, filename, 'exec', optimize=optimize) + else: + _, ext = os.path.splitext(filename) + ext = ext.lower() + + if ext == '.pyc': + # The module is available in binary-only form. Read the contents of .pyc file using helper function, which + # supports reading from either stand-alone or archive-embedded .pyc files. + logger.debug('Reading code object from .pyc file %s', filename) + pyc_data = _read_pyc_data(filename) + code_object = marshal.loads(pyc_data[16:]) + else: + # Assume this is a source .py file, but allow an arbitrary extension (other than .pyc, which is taken in + # the above branch). This allows entry-point scripts to have an arbitrary (or no) extension, as tested by + # the `test_arbitrary_ext` in `test_basic.py`. + logger.debug('Compiling python script/module file %s', filename) + + with open(filename, 'rb') as f: + source = f.read() + + # If entry-point script has no suffix, append .py when compiling the source. In POSIX builds, the executable + # has no suffix either; this causes issues with `traceback` module, as it tries to read the executable file + # when trying to look up the code for the entry-point script (when current working directory contains the + # executable). + _, ext = os.path.splitext(filename) + if not ext: + logger.debug("Appending .py to compiled entry-point name...") + filename += '.py' + + try: + code_object = compile(source, filename, 'exec', optimize=optimize) + except SyntaxError: + logger.warning("Sytnax error while compiling %s", filename) + raise + + return code_object + + +def strip_paths_in_code(co, new_filename=None): + # Paths to remove from filenames embedded in code objects + replace_paths = sys.path + CONF['pathex'] + # Make sure paths end with os.sep and the longest paths are first + replace_paths = sorted((os.path.join(f, '') for f in replace_paths), key=len, reverse=True) + + if new_filename is None: + original_filename = os.path.normpath(co.co_filename) + for f in replace_paths: + if original_filename.startswith(f): + new_filename = original_filename[len(f):] + break + + else: + return co + + code_func = type(co) + + consts = tuple( + strip_paths_in_code(const_co, new_filename) if isinstance(const_co, code_func) else const_co + for const_co in co.co_consts + ) + + return co.replace(co_consts=consts, co_filename=new_filename) + + +def _should_include_system_binary(binary_tuple, exceptions): + """ + Return True if the given binary_tuple describes a system binary that should be included. + + Exclude all system library binaries other than those with "lib-dynload" in the destination or "python" in the + source, except for those matching the patterns in the exceptions list. Intended to be used from the Analysis + exclude_system_libraries method. + """ + dest = binary_tuple[0] + if dest.startswith('lib-dynload'): + return True + src = binary_tuple[1] + if fnmatch.fnmatch(src, '*python*'): + return True + if not src.startswith('/lib') and not src.startswith('/usr/lib'): + return True + for exception in exceptions: + if fnmatch.fnmatch(dest, exception): + return True + return False + + +def compile_pymodule(name, src_path, workpath, optimize, code_cache=None): + """ + Given the name and source file for a pure-python module, compile the module in the specified working directory, + and return the name of resulting .pyc file. The paths in the resulting .pyc module are anonymized by having their + absolute prefix removed. + + If a .pyc file with matching name already exists in the target working directory, it is re-used (provided it has + compatible bytecode magic in the header, and that its modification time is newer than that of the source file). + + If the specified module is available in binary-only form, the input .pyc file is copied to the target working + directory and post-processed. If the specified module is available in source form, it is compiled only if + corresponding code object is not available in the optional code-object cache; otherwise, it is copied from cache + and post-processed. When compiling the module, the specified byte-code optimization level is used. + + It is up to caller to ensure that the optional code-object cache contains only code-objects of target optimization + level, and that if the specified working directory already contains .pyc files, that they were created with target + optimization level. + """ + + # Construct the target .pyc filename in the workpath + split_name = name.split(".") + if "__init__" in src_path: + # __init__ module; use "__init__" as module name, and construct parent path using all components of the + # fully-qualified name + parent_dirs = split_name + mod_basename = "__init__" + else: + # Regular module; use last component of the fully-qualified name as module name, and the rest as the parent + # path. + parent_dirs = split_name[:-1] + mod_basename = split_name[-1] + pyc_path = os.path.join(workpath, *parent_dirs, mod_basename + '.pyc') + + # If .pyc file already exists in our workpath, check if we can re-use it. For that: + # - its modification timestamp must be newer than that of the source file + # - it must be compiled for compatible python version + if os.path.exists(pyc_path): + can_reuse = False + if misc.mtime(pyc_path) > misc.mtime(src_path): + with open(pyc_path, 'rb') as fh: + can_reuse = fh.read(4) == compat.BYTECODE_MAGIC + + if can_reuse: + return pyc_path + + # Ensure the existence of parent directories for the target pyc path + os.makedirs(os.path.dirname(pyc_path), exist_ok=True) + + # Check if optional cache contains module entry + code_object = code_cache.get(name, None) if code_cache else None + + if code_object is None: + _, ext = os.path.splitext(src_path) + ext = ext.lower() + + if ext == '.py': + # Source py file; compile... + py_compile.compile(src_path, pyc_path, optimize=optimize) + # ... and read the contents + with open(pyc_path, 'rb') as fp: + pyc_data = fp.read() + elif ext == '.pyc': + # The module is available in binary-only form. Read the contents of .pyc file using helper function, which + # supports reading from either stand-alone or archive-embedded .pyc files. + pyc_data = _read_pyc_data(src_path) + else: + raise ValueError(f"Invalid python module file {src_path}; unhandled extension {ext}!") + + # Unmarshal code object; this is necessary if we want to strip paths from it + code_object = marshal.loads(pyc_data[16:]) + + # Strip code paths from the code object + code_object = strip_paths_in_code(code_object) + + # Write module file + with open(pyc_path, 'wb') as fh: + fh.write(compat.BYTECODE_MAGIC) + fh.write(struct.pack('= 3.10 stdlib, or equivalent importlib-metadata >= 4.6. +if _setup_py_mode: + importlib_metadata = None +else: + if sys.version_info >= (3, 10): + import importlib.metadata as importlib_metadata + else: + try: + import importlib_metadata + except ImportError as e: + from PyInstaller.exceptions import ImportlibMetadataError + raise ImportlibMetadataError() from e + + import packaging.version # For importlib_metadata version check + + # Validate the version + if packaging.version.parse(importlib_metadata.version("importlib-metadata")) < packaging.version.parse("4.6"): + from PyInstaller.exceptions import ImportlibMetadataError + raise ImportlibMetadataError() + +# Strict collect mode, which raises error when trying to collect duplicate files into PKG/CArchive or COLLECT. +strict_collect_mode = os.environ.get("PYINSTALLER_STRICT_COLLECT_MODE", "0") != "0" + +# Copied from https://docs.python.org/3/library/platform.html#cross-platform. +is_64bits: bool = sys.maxsize > 2**32 + +# Distinguish specific code for various Python versions. Variables 'is_pyXY' mean that Python X.Y and up is supported. +# Keep even unsupported versions here to keep 3rd-party hooks working. +is_py35 = sys.version_info >= (3, 5) +is_py36 = sys.version_info >= (3, 6) +is_py37 = sys.version_info >= (3, 7) +is_py38 = sys.version_info >= (3, 8) +is_py39 = sys.version_info >= (3, 9) +is_py310 = sys.version_info >= (3, 10) +is_py311 = sys.version_info >= (3, 11) +is_py312 = sys.version_info >= (3, 12) +is_py313 = sys.version_info >= (3, 13) + +is_win = sys.platform.startswith('win') +is_win_10 = is_win and (platform.win32_ver()[0] == '10') +is_win_11 = is_win and (platform.win32_ver()[0] == '11') +is_win_wine = False # Running under Wine; determined later on. +is_cygwin = sys.platform == 'cygwin' +is_darwin = sys.platform == 'darwin' # Mac OS X + +# Unix platforms +is_linux = sys.platform.startswith('linux') +is_solar = sys.platform.startswith('sun') # Solaris +is_aix = sys.platform.startswith('aix') +is_freebsd = sys.platform.startswith('freebsd') +is_openbsd = sys.platform.startswith('openbsd') +is_hpux = sys.platform.startswith('hp-ux') + +# Some code parts are similar to several unix platforms (e.g. Linux, Solaris, AIX). +# Mac OS is not considered as unix since there are many platform-specific details for Mac in PyInstaller. +is_unix = is_linux or is_solar or is_aix or is_freebsd or is_hpux or is_openbsd + +# Linux distributions such as Alpine or OpenWRT use musl as their libc implementation and resultantly need specially +# compiled bootloaders. On musl systems, ldd with no arguments prints 'musl' and its version. +is_musl = is_linux and "musl" in subprocess.run(["ldd"], capture_output=True, encoding="utf-8").stderr + +# macOS version +_macos_ver = tuple(int(x) for x in platform.mac_ver()[0].split('.')) if is_darwin else None + +# macOS 11 (Big Sur): if python is not compiled with Big Sur support, it ends up in compatibility mode by default, which +# is indicated by platform.mac_ver() returning '10.16'. The lack of proper Big Sur support breaks find_library() +# function from ctypes.util module, as starting with Big Sur, shared libraries are not visible on disk anymore. Support +# for the new library search mechanism was added in python 3.9 when compiled with Big Sur support. In such cases, +# platform.mac_ver() reports version as '11.x'. The behavior can be further modified via SYSTEM_VERSION_COMPAT +# environment variable; which allows explicitly enabling or disabling the compatibility mode. However, note that +# disabling the compatibility mode and using python that does not properly support Big Sur still leaves find_library() +# broken (which is a scenario that we ignore at the moment). +# The same logic applies to macOS 12 (Monterey). +is_macos_11_compat = bool(_macos_ver) and _macos_ver[0:2] == (10, 16) # Big Sur or newer in compat mode +is_macos_11_native = bool(_macos_ver) and _macos_ver[0:2] >= (11, 0) # Big Sur or newer in native mode +is_macos_11 = is_macos_11_compat or is_macos_11_native # Big Sur or newer + +# Check if python >= 3.13 was built with Py_GIL_DISABLED / free-threading (PEP703). +# +# This affects the shared library name, which has the "t" ABI suffix, as per: +# https://github.com/python/steering-council/issues/221#issuecomment-1841593283 +# +# It also affects the layout of PyConfig structure used by bootloader; consequently +# a) we need to inform bootloader what kind of build it is dealing with +# b) we must not mix up shared libraries, in case multiple builds are present on the system. Thus, strictly enforce the +# "t" ABI suffix in the PYDYLIB_NAMES, if applicable. +is_nogil = bool(sysconfig.get_config_var('Py_GIL_DISABLED')) + +_py_suffix = "t" if is_nogil else "" + +# On different platforms is different file for dynamic python library. +_py_major, _py_minor = sys.version_info[:2] +if is_win or is_cygwin: + PYDYLIB_NAMES = { + f'python{_py_major}{_py_minor}{_py_suffix}.dll', + f'libpython{_py_major}{_py_minor}{_py_suffix}.dll', + f'libpython{_py_major}.{_py_minor}{_py_suffix}.dll', + } # For MSYS2 environment +elif is_darwin: + # The suffix in .framework library name is capitalized, e.g., PythonT for freethreading-enabled build. + # The `libpython%d.%d%s.dylib` is there primarily for Anaconda installations, but it also serves as a fallback in + # .framework builds, where `/Library/Frameworks/Python.framework/Versions/3.X/lib/libpython3.13.dylib` is a symbolic + # link that points to `../Python`. + PYDYLIB_NAMES = { + f'Python{_py_suffix.upper()}', + f'.Python{_py_suffix.upper()}', + f'Python{_py_major}{_py_suffix.upper()}', + f'libpython{_py_major}.{_py_minor}{_py_suffix}.dylib', + } +elif is_aix: + # Shared libs on AIX may be archives with shared object members, hence the ".a" suffix. However, starting with + # python 2.7.11 libpython?.?.so and Python3 libpython?.?m.so files are produced. + PYDYLIB_NAMES = { + f'libpython{_py_major}.{_py_minor}{_py_suffix}.a', + f'libpython{_py_major}.{_py_minor}{_py_suffix}.so', + } +elif is_freebsd: + PYDYLIB_NAMES = { + f'libpython{_py_major}.{_py_minor}{_py_suffix}.so.1', + f'libpython{_py_major}.{_py_minor}{_py_suffix}.so.1.0', + } +elif is_openbsd: + PYDYLIB_NAMES = { + f'libpython{_py_major}.{_py_minor}{_py_suffix}.so.0.0', + } +elif is_hpux: + PYDYLIB_NAMES = { + f'libpython{_py_major}.{_py_minor}{_py_suffix}.so', + } +elif is_unix: + # Other *nix platforms. + # Python 2 .so library on Linux is: libpython2.7.so.1.0 + # Python 3 .so library on Linux is: libpython3.3.so.1.0 + PYDYLIB_NAMES = { + f'libpython{_py_major}.{_py_minor}{_py_suffix}.so.1.0', + f'libpython{_py_major}.{_py_minor}{_py_suffix}.so', + } +else: + raise SystemExit('Your platform is not yet supported. Please define constant PYDYLIB_NAMES for your platform.') + +del _py_major, _py_minor, _py_suffix + +# In a virtual environment created by virtualenv (github.com/pypa/virtualenv) there exists sys.real_prefix with the path +# to the base Python installation from which the virtual environment was created. This is true regardless of the version +# of Python used to execute the virtualenv command. +# +# In a virtual environment created by the venv module available in the Python standard lib, there exists sys.base_prefix +# with the path to the base implementation. This does not exist in a virtual environment created by virtualenv. +# +# The following code creates compat.is_venv and is.virtualenv that are True when running a virtual environment, and also +# compat.base_prefix with the path to the base Python installation. + +base_prefix: str = os.path.abspath(getattr(sys, 'real_prefix', getattr(sys, 'base_prefix', sys.prefix))) +# Ensure `base_prefix` is not containing any relative parts. +is_venv = is_virtualenv = base_prefix != os.path.abspath(sys.prefix) + +# Conda environments sometimes have different paths or apply patches to packages that can affect how a hook or package +# should access resources. Method for determining conda taken from https://stackoverflow.com/questions/47610844#47610844 +is_conda = os.path.isdir(os.path.join(base_prefix, 'conda-meta')) + +# Similar to ``is_conda`` but is ``False`` using another ``venv``-like manager on top. In this case, no packages +# encountered will be conda packages meaning that the default non-conda behaviour is generally desired from PyInstaller. +is_pure_conda = os.path.isdir(os.path.join(sys.prefix, 'conda-meta')) + +# Full path to python interpreter. +python_executable = getattr(sys, '_base_executable', sys.executable) + +# Is this Python from Microsoft App Store (Windows only)? Python from Microsoft App Store has executable pointing at +# empty shims. +is_ms_app_store = is_win and os.path.getsize(python_executable) == 0 + +if is_ms_app_store: + # Locate the actual executable inside base_prefix. + python_executable = os.path.join(base_prefix, os.path.basename(python_executable)) + if not os.path.exists(python_executable): + raise SystemExit( + 'PyInstaller cannot locate real python executable belonging to Python from Microsoft App Store!' + ) + +# Bytecode magic value +BYTECODE_MAGIC = importlib.util.MAGIC_NUMBER + +# List of suffixes for Python C extension modules. +EXTENSION_SUFFIXES = importlib.machinery.EXTENSION_SUFFIXES +ALL_SUFFIXES = importlib.machinery.all_suffixes() + +# On Windows we require pywin32-ctypes. +# -> all pyinstaller modules should use win32api from PyInstaller.compat to +# ensure that it can work on MSYS2 (which requires pywin32-ctypes) +if is_win: + if _setup_py_mode: + pywintypes = None + win32api = None + else: + try: + # Hide the `cffi` package from win32-ctypes by temporarily blocking its import. This ensures that `ctypes` + # backend is always used, even if `cffi` is available. The `cffi` backend uses `pycparser`, which is + # incompatible with -OO mode (2nd optimization level) due to its removal of docstrings. + # See https://github.com/pyinstaller/pyinstaller/issues/6345 + # On the off chance that `cffi` has already been imported, store the `sys.modules` entry so we can restore + # it after importing `pywin32-ctypes` modules. + orig_cffi = sys.modules.get('cffi') + sys.modules['cffi'] = None + + from win32ctypes.pywin32 import pywintypes # noqa: F401, E402 + from win32ctypes.pywin32 import win32api # noqa: F401, E402 + except ImportError as e: + raise SystemExit( + 'Could not import `pywintypes` or `win32api` from `win32ctypes.pywin32`.\n' + 'Please make sure that `pywin32-ctypes` is installed and importable, for example:\n\n' + 'pip install pywin32-ctypes\n' + ) from e + finally: + # Unblock `cffi`. + if orig_cffi is not None: + sys.modules['cffi'] = orig_cffi + else: + del sys.modules['cffi'] + del orig_cffi + +# macOS's platform.architecture() can be buggy, so we do this manually here. Based off the python documentation: +# https://docs.python.org/3/library/platform.html#platform.architecture +if is_darwin: + architecture = '64bit' if sys.maxsize > 2**32 else '32bit' +else: + architecture = platform.architecture()[0] + +# Cygwin needs special handling, because platform.system() contains identifiers such as MSYS_NT-10.0-19042 and +# CYGWIN_NT-10.0-19042 that do not fit PyInstaller's OS naming scheme. Explicitly set `system` to 'Cygwin'. +system = 'Cygwin' if is_cygwin else platform.system() + +# Machine suffix for bootloader. +if is_win: + # On Windows ARM64 using an x64 Python environment, platform.machine() returns ARM64 but + # we really want the bootloader that matches the Python environment instead of the OS. + machine = _pyi_machine(os.environ.get("PROCESSOR_ARCHITECTURE", platform.machine()), platform.system()) +else: + machine = _pyi_machine(platform.machine(), platform.system()) + + +# Wine detection and support +def is_wine_dll(filename: str | os.PathLike): + """ + Check if the given PE file is a Wine DLL (PE-converted built-in, or fake/placeholder one). + + Returns True if the given file is a Wine DLL, False if not (or if file cannot be analyzed or does not exist). + """ + _WINE_SIGNATURES = ( + b'Wine builtin DLL', # PE-converted Wine DLL + b'Wine placeholder DLL', # Fake/placeholder Wine DLL + ) + _MAX_LEN = max([len(sig) for sig in _WINE_SIGNATURES]) + + # Wine places their DLL signature in the padding area between the IMAGE_DOS_HEADER and IMAGE_NT_HEADERS. So we need + # to compare the bytes that come right after IMAGE_DOS_HEADER, i.e., after initial 64 bytes. We can read the file + # directly and avoid using the pefile library to avoid performance penalty associated with full header parsing. + try: + with open(filename, 'rb') as fp: + fp.seek(64) + signature = fp.read(_MAX_LEN) + return signature.startswith(_WINE_SIGNATURES) + except Exception: + pass + return False + + +if is_win: + try: + import ctypes.util # noqa: E402 + is_win_wine = is_wine_dll(ctypes.util.find_library('kernel32')) + except Exception: + pass + +# Set and get environment variables does not handle unicode strings correctly on Windows. + +# Acting on os.environ instead of using getenv()/setenv()/unsetenv(), as suggested in +# : "Calling putenv() directly does not change os.environ, so it is +# better to modify os.environ." (Same for unsetenv.) + + +def getenv(name: str, default: str | None = None): + """ + Returns unicode string containing value of environment variable 'name'. + """ + return os.environ.get(name, default) + + +def setenv(name: str, value: str): + """ + Accepts unicode string and set it as environment variable 'name' containing value 'value'. + """ + os.environ[name] = value + + +def unsetenv(name: str): + """ + Delete the environment variable 'name'. + """ + # Some platforms (e.g., AIX) do not support `os.unsetenv()` and thus `del os.environ[name]` has no effect on the + # real environment. For this case, we set the value to the empty string. + os.environ[name] = "" + del os.environ[name] + + +# Exec commands in subprocesses. + + +def exec_command( + *cmdargs: str, encoding: str | None = None, raise_enoent: bool | None = None, **kwargs: int | bool | list | None +): + """ + Run the command specified by the passed positional arguments, optionally configured by the passed keyword arguments. + + .. DANGER:: + **Ignore this function's return value** -- unless this command's standard output contains _only_ pathnames, in + which case this function returns the correct filesystem-encoded string expected by PyInstaller. In all other + cases, this function's return value is _not_ safely usable. + + For backward compatibility, this function's return value non-portably depends on the current Python version and + passed keyword arguments: + + * Under Python 3.x, this value is a **decoded `str` string**. However, even this value is _not_ necessarily + safely usable: + * If the `encoding` parameter is passed, this value is guaranteed to be safely usable. + * Else, this value _cannot_ be safely used for any purpose (e.g., string manipulation or parsing), except to be + passed directly to another non-Python command. Why? Because this value has been decoded with the encoding + specified by `sys.getfilesystemencoding()`, the encoding used by `os.fsencode()` and `os.fsdecode()` to + convert from platform-agnostic to platform-specific pathnames. This is _not_ necessarily the encoding with + which this command's standard output was encoded. Cue edge-case decoding exceptions. + + Parameters + ---------- + cmdargs : + Variadic list whose: + 1. Mandatory first element is the absolute path, relative path, or basename in the current `${PATH}` of the + command to run. + 2. Optional remaining elements are arguments to pass to this command. + encoding : str, optional + Optional keyword argument specifying the encoding with which to decode this command's standard output under + Python 3. As this function's return value should be ignored, this argument should _never_ be passed. + raise_enoent : boolean, optional + Optional keyword argument to simply raise the exception if the executing the command fails since to the command + is not found. This is useful to checking id a command exists. + + All remaining keyword arguments are passed as is to the `subprocess.Popen()` constructor. + + Returns + ---------- + str + Ignore this value. See discussion above. + """ + + proc = subprocess.Popen(cmdargs, stdout=subprocess.PIPE, **kwargs) + try: + out = proc.communicate(timeout=60)[0] + except OSError as e: + if raise_enoent and e.errno == errno.ENOENT: + raise + print('--' * 20, file=sys.stderr) + print("Error running '%s':" % " ".join(cmdargs), file=sys.stderr) + print(e, file=sys.stderr) + print('--' * 20, file=sys.stderr) + raise ExecCommandFailed("Error: Executing command failed!") from e + except subprocess.TimeoutExpired: + proc.kill() + raise + + # stdout/stderr are returned as a byte array NOT as string, so we need to convert that to proper encoding. + try: + if encoding: + out = out.decode(encoding) + else: + # If no encoding is given, assume we are reading filenames from stdout only because it is the common case. + out = os.fsdecode(out) + except UnicodeDecodeError as e: + # The sub-process used a different encoding; provide more information to ease debugging. + print('--' * 20, file=sys.stderr) + print(str(e), file=sys.stderr) + print('These are the bytes around the offending byte:', file=sys.stderr) + print('--' * 20, file=sys.stderr) + raise + return out + + +def exec_command_rc(*cmdargs: str, **kwargs: float | bool | list | None): + """ + Return the exit code of the command specified by the passed positional arguments, optionally configured by the + passed keyword arguments. + + Parameters + ---------- + cmdargs : list + Variadic list whose: + 1. Mandatory first element is the absolute path, relative path, or basename in the current `${PATH}` of the + command to run. + 2. Optional remaining elements are arguments to pass to this command. + + All keyword arguments are passed as is to the `subprocess.call()` function. + + Returns + ---------- + int + This command's exit code as an unsigned byte in the range `[0, 255]`, where 0 signifies success and all other + values signal a failure. + """ + + # 'encoding' keyword is not supported for 'subprocess.call'; remove it from kwargs. + if 'encoding' in kwargs: + kwargs.pop('encoding') + return subprocess.call(cmdargs, **kwargs) + + +def exec_command_all(*cmdargs: str, encoding: str | None = None, **kwargs: int | bool | list | None): + """ + Run the command specified by the passed positional arguments, optionally configured by the passed keyword arguments. + + .. DANGER:: + **Ignore this function's return value.** If this command's standard output consists solely of pathnames, consider + calling `exec_command()` + + Parameters + ---------- + cmdargs : str + Variadic list whose: + 1. Mandatory first element is the absolute path, relative path, or basename in the current `${PATH}` of the + command to run. + 2. Optional remaining elements are arguments to pass to this command. + encoding : str, optional + Optional keyword argument specifying the encoding with which to decode this command's standard output. As this + function's return value should be ignored, this argument should _never_ be passed. + + All remaining keyword arguments are passed as is to the `subprocess.Popen()` constructor. + + Returns + ---------- + (int, str, str) + Ignore this 3-element tuple `(exit_code, stdout, stderr)`. See the `exec_command()` function for discussion. + """ + proc = subprocess.Popen( + cmdargs, + bufsize=-1, # Default OS buffer size. + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + **kwargs + ) + # Waits for subprocess to complete. + try: + out, err = proc.communicate(timeout=60) + except subprocess.TimeoutExpired: + proc.kill() + raise + # stdout/stderr are returned as a byte array NOT as string. Thus we need to convert that to proper encoding. + try: + if encoding: + out = out.decode(encoding) + err = err.decode(encoding) + else: + # If no encoding is given, assume we're reading filenames from stdout only because it's the common case. + out = os.fsdecode(out) + err = os.fsdecode(err) + except UnicodeDecodeError as e: + # The sub-process used a different encoding, provide more information to ease debugging. + print('--' * 20, file=sys.stderr) + print(str(e), file=sys.stderr) + print('These are the bytes around the offending byte:', file=sys.stderr) + print('--' * 20, file=sys.stderr) + raise + + return proc.returncode, out, err + + +def __wrap_python(args, kwargs): + cmdargs = [sys.executable] + + # Mac OS X supports universal binaries (binary for multiple architectures. We need to ensure that subprocess + # binaries are running for the same architecture as python executable. It is necessary to run binaries with 'arch' + # command. + if is_darwin: + if architecture == '64bit': + if platform.machine() == 'arm64': + py_prefix = ['arch', '-arm64'] # Apple M1 + else: + py_prefix = ['arch', '-x86_64'] # Intel + elif architecture == '32bit': + py_prefix = ['arch', '-i386'] + else: + py_prefix = [] + # Since Mac OS 10.11, the environment variable DYLD_LIBRARY_PATH is no more inherited by child processes, so we + # proactively propagate the current value using the `-e` option of the `arch` command. + if 'DYLD_LIBRARY_PATH' in os.environ: + path = os.environ['DYLD_LIBRARY_PATH'] + py_prefix += ['-e', 'DYLD_LIBRARY_PATH=%s' % path] + cmdargs = py_prefix + cmdargs + + if not __debug__: + cmdargs.append('-O') + + cmdargs.extend(args) + + env = kwargs.get('env') + if env is None: + env = dict(**os.environ) + + # Ensure python 3 subprocess writes 'str' as utf-8 + env['PYTHONIOENCODING'] = 'UTF-8' + # ... and ensure we read output as utf-8 + kwargs['encoding'] = 'UTF-8' + + return cmdargs, kwargs + + +def exec_python(*args: str, **kwargs: str | None): + """ + Wrap running python script in a subprocess. + + Return stdout of the invoked command. + """ + cmdargs, kwargs = __wrap_python(args, kwargs) + return exec_command(*cmdargs, **kwargs) + + +def exec_python_rc(*args: str, **kwargs: str | None): + """ + Wrap running python script in a subprocess. + + Return exit code of the invoked command. + """ + cmdargs, kwargs = __wrap_python(args, kwargs) + return exec_command_rc(*cmdargs, **kwargs) + + +# Path handling. + + +# Site-packages functions - use native function if available. +def getsitepackages(prefixes: list | None = None): + """ + Returns a list containing all global site-packages directories. + + For each directory present in ``prefixes`` (or the global ``PREFIXES``), this function finds its `site-packages` + subdirectory depending on the system environment, and returns a list of full paths. + """ + # This implementation was copied from the ``site`` module, python 3.7.3. + sitepackages = [] + seen = set() + + if prefixes is None: + prefixes = [sys.prefix, sys.exec_prefix] + + for prefix in prefixes: + if not prefix or prefix in seen: + continue + seen.add(prefix) + + if os.sep == '/': + sitepackages.append(os.path.join(prefix, "lib", "python%d.%d" % sys.version_info[:2], "site-packages")) + else: + sitepackages.append(prefix) + sitepackages.append(os.path.join(prefix, "lib", "site-packages")) + return sitepackages + + +# Backported for virtualenv. Module 'site' in virtualenv might not have this attribute. +getsitepackages = getattr(site, 'getsitepackages', getsitepackages) + + +# Wrapper to load a module from a Python source file. This function loads import hooks when processing them. +def importlib_load_source(name: str, pathname: str): + # Import module from a file. + mod_loader = importlib.machinery.SourceFileLoader(name, pathname) + mod = types.ModuleType(mod_loader.name) + mod.__file__ = mod_loader.get_filename() # Some hooks require __file__ attribute in their namespace + mod_loader.exec_module(mod) + return mod + + +# Patterns of module names that should be bundled into the base_library.zip to be available during bootstrap. +# These modules include direct or indirect dependencies of encodings.* modules. The encodings modules must be +# recursively included to set the I/O encoding during python startup. Similarly, this list should include +# modules used by PyInstaller's bootstrap scripts and modules (loader/pyi*.py) + +PY3_BASE_MODULES = { + '_collections_abc', + '_weakrefset', + 'abc', + 'codecs', + 'collections', + 'copyreg', + 'encodings', + 'enum', + 'functools', + 'genericpath', # dependency of os.path + 'io', + 'heapq', + 'keyword', + 'linecache', + 'locale', + 'ntpath', # dependency of os.path + 'operator', + 'os', + 'posixpath', # dependency of os.path + 're', + 'reprlib', + 'sre_compile', + 'sre_constants', + 'sre_parse', + 'stat', # dependency of os.path + 'traceback', # for startup errors + 'types', + 'weakref', + 'warnings', +} + +if not is_py310: + PY3_BASE_MODULES.add('_bootlocale') + +# Object types of Pure Python modules in modulegraph dependency graph. +# Pure Python modules have code object (attribute co_code). +PURE_PYTHON_MODULE_TYPES = { + 'SourceModule', + 'CompiledModule', + 'Package', + 'NamespacePackage', + # Deprecated. + # TODO Could these module types be removed? + 'FlatPackage', + 'ArchiveModule', +} +# Object types of special Python modules (built-in, run-time, namespace package) in modulegraph dependency graph that do +# not have code object. +SPECIAL_MODULE_TYPES = { + # Omit AliasNode from here (and consequently from VALID_MODULE_TYPES), in order to prevent PyiModuleGraph from + # running standard hooks for aliased modules. + #'AliasNode', + 'BuiltinModule', + 'RuntimeModule', + 'RuntimePackage', + + # PyInstaller handles scripts differently and not as standard Python modules. + 'Script', +} +# Object types of Binary Python modules (extensions, etc) in modulegraph dependency graph. +BINARY_MODULE_TYPES = { + 'Extension', + 'ExtensionPackage', +} +# Object types of valid Python modules in modulegraph dependency graph. +VALID_MODULE_TYPES = PURE_PYTHON_MODULE_TYPES | SPECIAL_MODULE_TYPES | BINARY_MODULE_TYPES +# Object types of bad/missing/invalid Python modules in modulegraph dependency graph. +# TODO: should be 'Invalid' module types also in the 'MISSING' set? +BAD_MODULE_TYPES = { + 'BadModule', + 'ExcludedModule', + 'InvalidSourceModule', + 'InvalidCompiledModule', + 'MissingModule', + + # Runtime modules and packages are technically valid rather than bad, but exist only in-memory rather than on-disk + # (typically due to pre_safe_import_module() hooks), and hence cannot be physically frozen. For simplicity, these + # nodes are categorized as bad rather than valid. + 'RuntimeModule', + 'RuntimePackage', +} +ALL_MODULE_TYPES = VALID_MODULE_TYPES | BAD_MODULE_TYPES +# TODO: review this mapping to TOC, remove useless entries. +# Dictionary to map ModuleGraph node types to TOC typecodes. +MODULE_TYPES_TO_TOC_DICT = { + # Pure modules. + 'AliasNode': 'PYMODULE', + 'Script': 'PYSOURCE', + 'SourceModule': 'PYMODULE', + 'CompiledModule': 'PYMODULE', + 'Package': 'PYMODULE', + 'FlatPackage': 'PYMODULE', + 'ArchiveModule': 'PYMODULE', + # Binary modules. + 'Extension': 'EXTENSION', + 'ExtensionPackage': 'EXTENSION', + # Special valid modules. + 'BuiltinModule': 'BUILTIN', + 'NamespacePackage': 'PYMODULE', + # Bad modules. + 'BadModule': 'bad', + 'ExcludedModule': 'excluded', + 'InvalidSourceModule': 'invalid', + 'InvalidCompiledModule': 'invalid', + 'MissingModule': 'missing', + 'RuntimeModule': 'runtime', + 'RuntimePackage': 'runtime', + # Other. + 'does not occur': 'BINARY', +} + + +def check_requirements(): + """ + Verify that all requirements to run PyInstaller are met. + + Fail hard if any requirement is not met. + """ + # Fail hard if Python does not have minimum required version + if sys.version_info < (3, 8): + raise EnvironmentError('PyInstaller requires Python 3.8 or newer.') + + # There are some old packages which used to be backports of libraries which are now part of the standard library. + # These backports are now unmaintained and contain only an older subset of features leading to obscure errors like + # "enum has not attribute IntFlag" if installed. + from importlib.metadata import distribution, PackageNotFoundError + + for name in ["enum34", "typing", "pathlib"]: + try: + dist = distribution(name) + except PackageNotFoundError: + continue + remove = "conda remove" if is_conda else f'"{sys.executable}" -m pip uninstall {name}' + raise SystemExit( + f"The '{name}' package is an obsolete backport of a standard library package and is incompatible with " + f"PyInstaller. Please remove this package (located in {dist.locate_file('')}) using\n {remove}\n" + "then try again." + ) + + # Bail out if binutils is not installed. + if is_linux and shutil.which("objdump") is None: + raise SystemExit( + "On Linux, objdump is required. It is typically provided by the 'binutils' package " + "installable via your Linux distribution's package manager." + ) diff --git a/venv/Lib/site-packages/PyInstaller/config.py b/venv/Lib/site-packages/PyInstaller/config.py new file mode 100644 index 0000000..e6cb695 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/config.py @@ -0,0 +1,56 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- +""" +This module holds run-time PyInstaller configuration. + +Variable CONF is a dict() with all configuration options that are necessary for the build phase. Build phase is done by +passing .spec file to exec() function. CONF variable is the only way how to pass arguments to exec() and how to avoid +using 'global' variables. + +NOTE: Having 'global' variables does not play well with the test suite because it does not provide isolated environments +for tests. Some tests might fail in this case. + +NOTE: The 'CONF' dict() is cleaned after building phase to not interfere with any other possible test. + +To pass any arguments to build phase, just do: + + from PyInstaller.config import CONF + CONF['my_var_name'] = my_value + +And to use this variable in the build phase: + + from PyInstaller.config import CONF + foo = CONF['my_var_name'] + + +This is the list of known variables. (Please update it if necessary.) + +cachedir +hiddenimports +noconfirm +pathex +ui_admin +ui_access +upx_available +upx_dir +workpath + +tests_modgraph - cached PyiModuleGraph object to speed up tests + +code_cache - dictionary associating `Analysis.pure` list instances with code cache dictionaries. Used by PYZ writer. +""" + +# NOTE: Do not import other PyInstaller modules here. Just define constants here. + +CONF = { + # Unit tests require this key to exist. + 'pathex': [], +} diff --git a/venv/Lib/site-packages/PyInstaller/configure.py b/venv/Lib/site-packages/PyInstaller/configure.py new file mode 100644 index 0000000..46234b8 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/configure.py @@ -0,0 +1,107 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- +""" +Configure PyInstaller for the current Python installation. +""" + +import os +import subprocess + +from PyInstaller import compat +from PyInstaller import log as logging + +logger = logging.getLogger(__name__) + + +def _check_upx_availability(upx_dir): + logger.debug('Testing UPX availability ...') + + upx_exe = "upx" + if upx_dir: + upx_exe = os.path.normpath(os.path.join(upx_dir, upx_exe)) + + # Check if we can call `upx -V`. + try: + output = subprocess.check_output( + [upx_exe, '-V'], + stdin=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + encoding='utf-8', + ) + except Exception: + logger.debug('UPX is not available.') + return False + + # Read the first line to display version string + try: + version_string = output.splitlines()[0] + except IndexError: + version_string = 'version string unavailable' + + logger.debug('UPX is available: %s', version_string) + return True + + +def _get_pyinstaller_cache_dir(): + old_cache_dir = None + if compat.getenv('PYINSTALLER_CONFIG_DIR'): + cache_dir = compat.getenv('PYINSTALLER_CONFIG_DIR') + elif compat.is_win: + cache_dir = compat.getenv('LOCALAPPDATA') + if not cache_dir: + cache_dir = os.path.expanduser('~\\Application Data') + elif compat.is_darwin: + cache_dir = os.path.expanduser('~/Library/Application Support') + else: + # According to XDG specification: http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html + old_cache_dir = compat.getenv('XDG_DATA_HOME') + if not old_cache_dir: + old_cache_dir = os.path.expanduser('~/.local/share') + cache_dir = compat.getenv('XDG_CACHE_HOME') + if not cache_dir: + cache_dir = os.path.expanduser('~/.cache') + cache_dir = os.path.join(cache_dir, 'pyinstaller') + # Move old cache-dir, if any, to new location. + if old_cache_dir and not os.path.exists(cache_dir): + old_cache_dir = os.path.join(old_cache_dir, 'pyinstaller') + if os.path.exists(old_cache_dir): + parent_dir = os.path.dirname(cache_dir) + if not os.path.exists(parent_dir): + os.makedirs(parent_dir) + os.rename(old_cache_dir, cache_dir) + return cache_dir + + +def get_config(upx_dir=None): + config = {} + + config['cachedir'] = _get_pyinstaller_cache_dir() + config['upx_dir'] = upx_dir + + # Disable UPX on non-Windows. Using UPX (3.96) on modern Linux shared libraries (for example, the python3.x.so + # shared library) seems to result in segmentation fault when they are dlopen'd. This happens in recent versions + # of Fedora and Ubuntu linux, as well as in Alpine containers. On macOS, UPX (3.96) fails with + # UnknownExecutableFormatException on most .dylibs (and interferes with code signature on other occasions). And + # even when it would succeed, compressed libraries cannot be (re)signed due to failed strict validation. + upx_available = _check_upx_availability(upx_dir) + if upx_available: + if compat.is_win or compat.is_cygwin: + logger.info("UPX is available and will be used if enabled on build targets.") + elif os.environ.get("PYINSTALLER_FORCE_UPX", "0") != "0": + logger.warning( + "UPX is available and force-enabled on platform with known compatibility problems - use at own risk!" + ) + else: + upx_available = False + logger.info("UPX is available but is disabled on non-Windows due to known compatibility problems.") + config['upx_available'] = upx_available + + return config diff --git a/venv/Lib/site-packages/PyInstaller/depend/__init__.py b/venv/Lib/site-packages/PyInstaller/depend/__init__.py new file mode 100644 index 0000000..792d600 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/depend/__init__.py @@ -0,0 +1 @@ +# diff --git a/venv/Lib/site-packages/PyInstaller/depend/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/depend/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..6106225 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/depend/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/depend/__pycache__/analysis.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/depend/__pycache__/analysis.cpython-311.pyc new file mode 100644 index 0000000..2fde1f3 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/depend/__pycache__/analysis.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/depend/__pycache__/bindepend.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/depend/__pycache__/bindepend.cpython-311.pyc new file mode 100644 index 0000000..3a0bd9f Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/depend/__pycache__/bindepend.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/depend/__pycache__/bytecode.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/depend/__pycache__/bytecode.cpython-311.pyc new file mode 100644 index 0000000..9df9235 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/depend/__pycache__/bytecode.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/depend/__pycache__/dylib.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/depend/__pycache__/dylib.cpython-311.pyc new file mode 100644 index 0000000..39b1426 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/depend/__pycache__/dylib.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/depend/__pycache__/imphook.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/depend/__pycache__/imphook.cpython-311.pyc new file mode 100644 index 0000000..09418b3 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/depend/__pycache__/imphook.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/depend/__pycache__/imphookapi.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/depend/__pycache__/imphookapi.cpython-311.pyc new file mode 100644 index 0000000..de5c4ca Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/depend/__pycache__/imphookapi.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/depend/__pycache__/utils.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/depend/__pycache__/utils.cpython-311.pyc new file mode 100644 index 0000000..c24b4c2 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/depend/__pycache__/utils.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/depend/analysis.py b/venv/Lib/site-packages/PyInstaller/depend/analysis.py new file mode 100644 index 0000000..f4f28f2 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/depend/analysis.py @@ -0,0 +1,1014 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- +""" +Define a modified ModuleGraph that can return its contents as a TOC and in other ways act like the old ImpTracker. +TODO: This class, along with TOC and Tree, should be in a separate module. + +For reference, the ModuleGraph node types and their contents: + + nodetype identifier filename + + Script full path to .py full path to .py + SourceModule basename full path to .py + BuiltinModule basename None + CompiledModule basename full path to .pyc + Extension basename full path to .so + MissingModule basename None + Package basename full path to __init__.py + packagepath is ['path to package'] + globalnames is set of global names __init__.py defines + ExtensionPackage basename full path to __init__.{so,dll} + packagepath is ['path to package'] + +The main extension here over ModuleGraph is a method to extract nodes from the flattened graph and return them as a +TOC, or added to a TOC. Other added methods look up nodes by identifier and return facts about them, replacing what +the old ImpTracker list could do. +""" + +import ast +import os +import re +import sys +import traceback +from collections import defaultdict +from copy import deepcopy + +from PyInstaller import HOMEPATH, PACKAGEPATH +from PyInstaller import log as logging +from PyInstaller.building.utils import add_suffix_to_extension +from PyInstaller.compat import ( + BAD_MODULE_TYPES, BINARY_MODULE_TYPES, MODULE_TYPES_TO_TOC_DICT, PURE_PYTHON_MODULE_TYPES, PY3_BASE_MODULES, + VALID_MODULE_TYPES, importlib_load_source, is_win +) +from PyInstaller.depend import bytecode +from PyInstaller.depend.imphook import AdditionalFilesCache, ModuleHookCache +from PyInstaller.depend.imphookapi import (PreFindModulePathAPI, PreSafeImportModuleAPI) +from PyInstaller.lib.modulegraph.find_modules import get_implies +from PyInstaller.lib.modulegraph.modulegraph import ModuleGraph, DEFAULT_IMPORT_LEVEL, ABSOLUTE_IMPORT_LEVEL, Package +from PyInstaller.log import DEBUG, INFO, TRACE +from PyInstaller.utils.hooks import collect_submodules, is_package + +logger = logging.getLogger(__name__) + +# Location-based hook priority constants +HOOK_PRIORITY_BUILTIN_HOOKS = -2000 # Built-in hooks. Lowest priority. +HOOK_PRIORITY_CONTRIBUTED_HOOKS = -1000 # Hooks from pyinstaller-hooks-contrib package. +HOOK_PRIORITY_UPSTREAM_HOOKS = 0 # Hooks provided by packages themselves, via entry-points. +HOOK_PRIORITY_USER_HOOKS = 1000 # User-supplied hooks (command-line / spec file). Highest priority. + + +class PyiModuleGraph(ModuleGraph): + """ + Directed graph whose nodes represent modules and edges represent dependencies between these modules. + + This high-level subclass wraps the lower-level `ModuleGraph` class with support for graph and runtime hooks. + While each instance of `ModuleGraph` represents a set of disconnected trees, each instance of this class *only* + represents a single connected tree whose root node is the Python script originally passed by the user on the + command line. For that reason, while there may (and typically do) exist more than one `ModuleGraph` instance, + there typically exists only a singleton instance of this class. + + Attributes + ---------- + _hooks : ModuleHookCache + Dictionary mapping the fully-qualified names of all modules with normal (post-graph) hooks to the absolute paths + of such hooks. See the the `_find_module_path()` method for details. + _hooks_pre_find_module_path : ModuleHookCache + Dictionary mapping the fully-qualified names of all modules with pre-find module path hooks to the absolute + paths of such hooks. See the the `_find_module_path()` method for details. + _hooks_pre_safe_import_module : ModuleHookCache + Dictionary mapping the fully-qualified names of all modules with pre-safe import module hooks to the absolute + paths of such hooks. See the `_safe_import_module()` method for details. + _user_hook_dirs : list + List of the absolute paths of all directories containing user-defined hooks for the current application. + _excludes : list + List of module names to be excluded when searching for dependencies. + _additional_files_cache : AdditionalFilesCache + Cache of all external dependencies (e.g., binaries, datas) listed in hook scripts for imported modules. + _module_collection_mode : dict + A dictionary of module/package collection mode settings set by hook scripts for their modules. + _bindepend_symlink_suppression : set + A set of paths or path patterns corresponding to shared libraries for which binary dependency analysis should + not create symbolic links into top-level application directory. + _base_modules: list + Dependencies for `base_library.zip` (which remain the same for every executable). + """ + + # Note: these levels are completely arbitrary and may be adjusted if needed. + LOG_LEVEL_MAPPING = {0: INFO, 1: DEBUG, 2: TRACE, 3: TRACE, 4: TRACE} + + def __init__(self, pyi_homepath, user_hook_dirs=(), excludes=(), **kwargs): + super().__init__(excludes=excludes, **kwargs) + # Homepath to the place where is PyInstaller located. + self._homepath = pyi_homepath + # modulegraph Node for the main python script that is analyzed by PyInstaller. + self._top_script_node = None + + # Absolute paths of all user-defined hook directories. + self._excludes = excludes + self._reset(user_hook_dirs) + self._analyze_base_modules() + + def _reset(self, user_hook_dirs): + """ + Reset for another set of scripts. This is primary required for running the test-suite. + """ + self._top_script_node = None + self._additional_files_cache = AdditionalFilesCache() + self._module_collection_mode = dict() + self._bindepend_symlink_suppression = set() + # Hook sources: user-supplied (command-line / spec file), entry-point (upstream hooks, contributed hooks), and + # built-in hooks. The order does not really matter anymore, because each entry is now a (location, priority) + # tuple, and order is determined from assigned priority (which may also be overridden by hooks themselves). + self._user_hook_dirs = [ + *user_hook_dirs, + (os.path.join(PACKAGEPATH, 'hooks'), HOOK_PRIORITY_BUILTIN_HOOKS), + ] + # Hook-specific lookup tables. These need to reset when reusing cached PyiModuleGraph to avoid hooks to refer to + # files or data from another test-case. + logger.info('Initializing module graph hook caches...') + self._hooks = self._cache_hooks("") + self._hooks_pre_safe_import_module = self._cache_hooks('pre_safe_import_module') + self._hooks_pre_find_module_path = self._cache_hooks('pre_find_module_path') + + # Search for run-time hooks in all hook directories. + self._available_rthooks = defaultdict(list) + for uhd, _ in self._user_hook_dirs: + uhd_path = os.path.abspath(os.path.join(uhd, 'rthooks.dat')) + try: + with open(uhd_path, 'r', encoding='utf-8') as f: + rthooks = ast.literal_eval(f.read()) + except FileNotFoundError: + # Ignore if this hook path doesn't have run-time hooks. + continue + except Exception as e: + logger.error('Unable to read run-time hooks from %r: %s' % (uhd_path, e)) + continue + + self._merge_rthooks(rthooks, uhd, uhd_path) + + # Convert back to a standard dict. + self._available_rthooks = dict(self._available_rthooks) + + def _merge_rthooks(self, rthooks, uhd, uhd_path): + """ + The expected data structure for a run-time hook file is a Python dictionary of type ``Dict[str, List[str]]``, + where the dictionary keys are module names and the sequence strings are Python file names. + + Check then merge this data structure, updating the file names to be absolute. + """ + # Check that the root element is a dict. + assert isinstance(rthooks, dict), 'The root element in %s must be a dict.' % uhd_path + for module_name, python_file_name_list in rthooks.items(): + # Ensure the key is a string. + assert isinstance(module_name, str), \ + '%s must be a dict whose keys are strings; %s is not a string.' % (uhd_path, module_name) + # Ensure the value is a list. + assert isinstance(python_file_name_list, list), \ + 'The value of %s key %s must be a list.' % (uhd_path, module_name) + if module_name in self._available_rthooks: + logger.warning( + 'Runtime hooks for %s have already been defined. Skipping the runtime hooks for %s that are ' + 'defined in %s.', module_name, module_name, os.path.join(uhd, 'rthooks') + ) + # Skip this module + continue + # Merge this with existing run-time hooks. + for python_file_name in python_file_name_list: + # Ensure each item in the list is a string. + assert isinstance(python_file_name, str), \ + '%s key %s, item %r must be a string.' % (uhd_path, module_name, python_file_name) + # Transform it into an absolute path. + abs_path = os.path.join(uhd, 'rthooks', python_file_name) + # Make sure this file exists. + assert os.path.exists(abs_path), \ + 'In %s, key %s, the file %r expected to be located at %r does not exist.' % \ + (uhd_path, module_name, python_file_name, abs_path) + # Merge it. + self._available_rthooks[module_name].append(abs_path) + + @staticmethod + def _findCaller(*args, **kwargs): + # Used to add an additional stack-frame above logger.findCaller. findCaller expects the caller to be three + # stack-frames above itself. + return logger.findCaller(*args, **kwargs) + + def msg(self, level, s, *args): + """ + Print a debug message with the given level. + + 1. Map the msg log level to a logger log level. + 2. Generate the message format (the same format as ModuleGraph) + 3. Find the caller, which findCaller expects three stack-frames above itself: + [3] caller -> [2] msg (here) -> [1] _findCaller -> [0] logger.findCaller + 4. Create a logRecord with the caller's information. + 5. Handle the logRecord. + """ + try: + level = self.LOG_LEVEL_MAPPING[level] + except KeyError: + return + if not logger.isEnabledFor(level): + return + + msg = "%s %s" % (s, ' '.join(map(repr, args))) + + try: + fn, lno, func, sinfo = self._findCaller() + except ValueError: # pragma: no cover + fn, lno, func, sinfo = "(unknown file)", 0, "(unknown function)", None + record = logger.makeRecord(logger.name, level, fn, lno, msg, [], None, func, None, sinfo) + + logger.handle(record) + + # Set logging methods so that the stack is correctly detected. + msgin = msg + msgout = msg + + def _cache_hooks(self, hook_type): + """ + Create a cache of all hooks of the specified type. + + The cache will include all official hooks defined by the PyInstaller codebase _and_ all unofficial hooks + defined for the current application. + + Parameters + ---------- + hook_type : str + Type of hooks to be cached, equivalent to the basename of the subpackage of the `PyInstaller.hooks` + package containing such hooks (e.g., empty string for standard hooks, `pre_safe_import_module` for + pre-safe-import-module hooks, `pre_find_module_path` for pre-find-module-path hooks). + """ + # Cache of this type of hooks. + hook_dirs = [] + for user_hook_dir, priority in self._user_hook_dirs: + # Absolute path of the user-defined subdirectory of this hook type. If this directory exists, add it to the + # list to be cached. + user_hook_type_dir = os.path.join(user_hook_dir, hook_type) + if os.path.isdir(user_hook_type_dir): + hook_dirs.append((user_hook_type_dir, priority)) + + return ModuleHookCache(self, hook_dirs) + + def _analyze_base_modules(self): + """ + Analyze dependencies of the the modules in base_library.zip. + """ + logger.info('Analyzing base_library.zip ...') + required_mods = [] + # Collect submodules from required modules in base_library.zip. + for m in PY3_BASE_MODULES: + if is_package(m): + required_mods += collect_submodules(m) + else: + required_mods.append(m) + # Initialize ModuleGraph. + self._base_modules = [mod for req in required_mods for mod in self.import_hook(req)] + + def add_script(self, pathname, caller=None): + """ + Wrap the parent's 'run_script' method and create graph from the first script in the analysis, and save its + node to use as the "caller" node for all others. This gives a connected graph rather than a collection of + unrelated trees. + """ + if self._top_script_node is None: + # Remember the node for the first script. + try: + self._top_script_node = super().add_script(pathname) + except SyntaxError: + print("\nSyntax error in", pathname, file=sys.stderr) + formatted_lines = traceback.format_exc().splitlines(True) + print(*formatted_lines[-4:], file=sys.stderr) + sys.exit(1) + # Create references from the top script to the base_modules in graph. + for node in self._base_modules: + self.add_edge(self._top_script_node, node) + # Return top-level script node. + return self._top_script_node + else: + if not caller: + # Defaults to as any additional script is called from the top-level script. + caller = self._top_script_node + return super().add_script(pathname, caller=caller) + + def process_post_graph_hooks(self, analysis): + """ + For each imported module, run this module's post-graph hooks if any. + + Parameters + ---------- + analysis: build_main.Analysis + The Analysis that calls the hooks + + """ + # For each iteration of the infinite "while" loop below: + # + # 1. All hook() functions defined in cached hooks for imported modules are called. This may result in new + # modules being imported (e.g., as hidden imports) that were ignored earlier in the current iteration: if + # this is the case, all hook() functions defined in cached hooks for these modules will be called by the next + # iteration. + # 2. All cached hooks whose hook() functions were called are removed from this cache. If this cache is empty, no + # hook() functions will be called by the next iteration and this loop will be terminated. + # 3. If no hook() functions were called, this loop is terminated. + logger.info('Processing module hooks (post-graph stage)...') + while True: + # Set of the names of all imported modules whose post-graph hooks are run by this iteration, preventing the + # next iteration from re- running these hooks. If still empty at the end of this iteration, no post-graph + # hooks were run; thus, this loop will be terminated. + hooked_module_names = set() + + # For each remaining hookable module and corresponding hooks... + for module_name, module_hook in self._hooks.items(): + # Graph node for this module if imported or "None" otherwise. + module_node = self.find_node(module_name, create_nspkg=False) + + # If this module has not been imported, temporarily ignore it. This module is retained in the cache, as + # a subsequently run post-graph hook could import this module as a hidden import. + if module_node is None: + continue + + # If this module is unimportable, permanently ignore it. + if type(module_node).__name__ not in VALID_MODULE_TYPES: + hooked_module_names.add(module_name) + continue + + # Run this script's post-graph hook. + module_hook.post_graph(analysis) + + # Cache all external dependencies listed by this script after running this hook, which could add + # dependencies. + self._additional_files_cache.add(module_name, module_hook.binaries, module_hook.datas) + + # Update package collection mode settings. + self._module_collection_mode.update(module_hook.module_collection_mode) + + # Update symbolic link suppression patterns for binary dependency analysis. + self._bindepend_symlink_suppression.update(module_hook.bindepend_symlink_suppression) + + # Prevent this module's hooks from being run again. + hooked_module_names.add(module_name) + + # Prevent all post-graph hooks run above from being run again by the next iteration. + self._hooks.remove_modules(*hooked_module_names) + + # If no post-graph hooks were run, terminate iteration. + if not hooked_module_names: + break + + def _find_all_excluded_imports(self, module_name): + """ + Collect excludedimports from the hooks of the specified module and all its parents. + """ + excluded_imports = set() + while module_name: + # Gather excluded imports from hook belonging to the module. + module_hook = self._hooks.get(module_name, None) + if module_hook: + excluded_imports.update(module_hook.excludedimports) + # Change module name to the module's parent name + module_name = module_name.rpartition('.')[0] + return excluded_imports + + def _safe_import_hook( + self, target_module_partname, source_module, target_attr_names, level=DEFAULT_IMPORT_LEVEL, edge_attr=None + ): + if source_module is not None: + # Gather all excluded imports for the referring modules, as well as its parents. + # For example, we want the excluded imports specified by hook for PIL to be also applied when the referring + # module is its submodule, PIL.Image. + excluded_imports = self._find_all_excluded_imports(source_module.identifier) + + # Apply extra processing only if we have any excluded-imports rules + if excluded_imports: + # Resolve the base module name. Level can be ABSOLUTE_IMPORT_LEVEL (= 0) for absolute imports, or an + # integer indicating the relative level. We do not use equality comparison just in case we ever happen + # to get ABSOLUTE_OR_RELATIVE_IMPORT_LEVEL (-1), which is a remnant of python2 days. + if level > ABSOLUTE_IMPORT_LEVEL: + if isinstance(source_module, Package): + # Package + base_module_name = source_module.identifier + else: + # Module in a package; base name must be the parent package name! + base_module_name = '.'.join(source_module.identifier.split('.')[:-1]) + + if target_module_partname: + base_module_name += '.' + target_module_partname + + # Adjust the base module name based on level + if level > 1: + base_module_name = '.'.join(base_module_name.split('.')[:-(level - 1)]) + else: + base_module_name = target_module_partname + + def _exclude_module(module_name, excluded_imports): + """ + Helper for checking whether given module should be excluded. + Returns the name of exclusion rule if module should be excluded, None otherwise. + """ + module_name_parts = module_name.split('.') + for excluded_import in excluded_imports: + excluded_import_parts = excluded_import.split('.') + match = module_name_parts[:len(excluded_import_parts)] == excluded_import_parts + if match: + return excluded_import + return None + + # First, check if base module name is to be excluded. + # This covers both basic `import a` and `import a.b.c`, as well as `from d import e, f` where base + # module `d` is excluded. + excluded_import_rule = _exclude_module(base_module_name, excluded_imports) + if excluded_import_rule: + logger.debug( + "Suppressing import of %r from module %r due to excluded import %r specified in a hook for %r " + "(or its parent package(s)).", base_module_name, source_module.identifier, excluded_import_rule, + source_module.identifier + ) + return [] + + # If we have target attribute names, check each of them, and remove excluded ones from the + # `target_attr_names` list. + if target_attr_names: + filtered_target_attr_names = [] + for target_attr_name in target_attr_names: + submodule_name = base_module_name + '.' + target_attr_name + excluded_import_rule = _exclude_module(submodule_name, excluded_imports) + if excluded_import_rule: + logger.debug( + "Suppressing import of %r from module %r due to excluded import %r specified in a hook " + "for %r (or its parent package(s)).", submodule_name, source_module.identifier, + excluded_import_rule, source_module.identifier + ) + else: + filtered_target_attr_names.append(target_attr_name) + + # Swap with filtered target attribute names list; if no elements remain after the filtering, pass + # None... + target_attr_names = filtered_target_attr_names or None + + ret_modules = super()._safe_import_hook( + target_module_partname, source_module, target_attr_names, level, edge_attr + ) + + # Ensure that hooks are pre-loaded for returned module(s), in an attempt to ensure that hooks are called in the + # order of imports. The hooks are cached, so there should be no downsides to pre-loading hooks early (as opposed + # to loading them in post-graph analysis). When modules are imported from other modules, the hooks for those + # referring (source) modules and their parent package(s) are loaded by the exclusion mechanism that takes place + # before the above `super()._safe_import_hook` call. The code below attempts to complement that, but for the + # referred (target) modules and their parent package(s). + for ret_module in ret_modules: + if type(ret_module).__name__ not in VALID_MODULE_TYPES: + continue + # (Ab)use the `_find_all_excluded_imports` helper to load all hooks for the given module and its parent + # package(s). + self._find_all_excluded_imports(ret_module.identifier) + + return ret_modules + + def _safe_import_module(self, module_basename, module_name, parent_package): + """ + Create a new graph node for the module with the passed name under the parent package signified by the passed + graph node. + + This method wraps the superclass method with support for pre-import module hooks. If such a hook exists for + this module (e.g., a script `PyInstaller.hooks.hook-{module_name}` containing a function + `pre_safe_import_module()`), that hook will be run _before_ the superclass method is called. + + Pre-Safe-Import-Hooks are performed just *prior* to importing the module. When running the hook, the modules + parent package has already been imported and ti's `__path__` is set up. But the module is just about to be + imported. + + See the superclass method for description of parameters and return value. + """ + # If this module has a pre-safe import module hook, run it. Make sure to remove it first, to prevent subsequent + # calls from running it again. + hook = self._hooks_pre_safe_import_module.pop(module_name, None) + if hook is not None: + # Dynamically import this hook as a fabricated module. + hook_path, hook_basename = os.path.split(hook.hook_filename) + logger.info('Processing pre-safe-import-module hook %r from %r', hook_basename, hook_path) + hook_module_name = 'PyInstaller_hooks_pre_safe_import_module_' + module_name.replace('.', '_') + hook_module = importlib_load_source(hook_module_name, hook.hook_filename) + + # Object communicating changes made by this hook back to us. + hook_api = PreSafeImportModuleAPI( + module_graph=self, + module_basename=module_basename, + module_name=module_name, + parent_package=parent_package, + ) + + # Run this hook, passed this object. + if not hasattr(hook_module, 'pre_safe_import_module'): + raise NameError('pre_safe_import_module() function not defined by hook %r.' % hook_module) + hook_module.pre_safe_import_module(hook_api) + + # Respect method call changes requested by this hook. + module_basename = hook_api.module_basename + module_name = hook_api.module_name + + # Call the superclass method. + return super()._safe_import_module(module_basename, module_name, parent_package) + + def _find_module_path(self, fullname, module_name, search_dirs): + """ + Get a 3-tuple detailing the physical location of the module with the passed name if that module exists _or_ + raise `ImportError` otherwise. + + This method wraps the superclass method with support for pre-find module path hooks. If such a hook exists + for this module (e.g., a script `PyInstaller.hooks.hook-{module_name}` containing a function + `pre_find_module_path()`), that hook will be run _before_ the superclass method is called. + + See superclass method for parameter and return value descriptions. + """ + # If this module has a pre-find module path hook, run it. Make sure to remove it first, to prevent subsequent + # calls from running it again. + hook = self._hooks_pre_find_module_path.pop(fullname, None) + if hook is not None: + # Dynamically import this hook as a fabricated module. + hook_path, hook_basename = os.path.split(hook.hook_filename) + logger.info('Processing pre-find-module-path hook %r from %r', hook_basename, hook_path) + hook_fullname = 'PyInstaller_hooks_pre_find_module_path_' + fullname.replace('.', '_') + hook_module = importlib_load_source(hook_fullname, hook.hook_filename) + + # Object communicating changes made by this hook back to us. + hook_api = PreFindModulePathAPI( + module_graph=self, + module_name=fullname, + search_dirs=search_dirs, + ) + + # Run this hook, passed this object. + if not hasattr(hook_module, 'pre_find_module_path'): + raise NameError('pre_find_module_path() function not defined by hook %r.' % hook_module) + hook_module.pre_find_module_path(hook_api) + + # Respect search-directory changes requested by this hook. + search_dirs = hook_api.search_dirs + + # Call the superclass method. + return super()._find_module_path(fullname, module_name, search_dirs) + + def get_code_objects(self): + """ + Get code objects from ModuleGraph for pure Python modules. This allows to avoid writing .pyc/pyo files to hdd + at later stage. + + :return: Dict with module name and code object. + """ + code_dict = {} + mod_types = PURE_PYTHON_MODULE_TYPES + for node in self.iter_graph(start=self._top_script_node): + # TODO This is terrible. To allow subclassing, types should never be directly compared. Use isinstance() + # instead, which is safer, simpler, and accepts sets. Most other calls to type() in the codebase should also + # be refactored to call isinstance() instead. + + # get node type e.g. Script + mg_type = type(node).__name__ + if mg_type in mod_types: + if node.code: + code_dict[node.identifier] = node.code + return code_dict + + def _make_toc(self, typecode=None): + """ + Return the name, path and type of selected nodes as a TOC. The selection is determined by the given list + of PyInstaller TOC typecodes. If that list is empty we return the complete flattened graph as a TOC with the + ModuleGraph note types in place of typecodes -- meant for debugging only. Normally we return ModuleGraph + nodes whose types map to the requested PyInstaller typecode(s) as indicated in the MODULE_TYPES_TO_TOC_DICT. + + We use the ModuleGraph (really, ObjectGraph) flatten() method to scan all the nodes. This is patterned after + ModuleGraph.report(). + """ + # Construct regular expression for matching modules that should be excluded because they are bundled in + # base_library.zip. + # + # This expression matches the base module name, optionally followed by a period and then any number of + # characters. This matches the module name and the fully qualified names of any of its submodules. + regex_str = '(' + '|'.join(PY3_BASE_MODULES) + r')(\.|$)' + module_filter = re.compile(regex_str) + + toc = list() + for node in self.iter_graph(start=self._top_script_node): + # Skip modules that are in base_library.zip. + if module_filter.match(node.identifier): + continue + entry = self._node_to_toc(node, typecode) + # Append the entry. We do not check for duplicates here; the TOC normalization is left to caller. + # However, as entries are obtained from modulegraph, there should not be any duplicates at this stage. + if entry is not None: + toc.append(entry) + return toc + + def make_pure_toc(self): + """ + Return all pure Python modules formatted as TOC. + """ + # PyInstaller should handle special module types without code object. + return self._make_toc(PURE_PYTHON_MODULE_TYPES) + + def make_binaries_toc(self): + """ + Return all binary Python modules formatted as TOC. + """ + return self._make_toc(BINARY_MODULE_TYPES) + + def make_missing_toc(self): + """ + Return all MISSING Python modules formatted as TOC. + """ + return self._make_toc(BAD_MODULE_TYPES) + + @staticmethod + def _node_to_toc(node, typecode=None): + # TODO This is terrible. Everything in Python has a type. It is nonsensical to even speak of "nodes [that] are + # not typed." How would that even occur? After all, even "None" has a type! (It is "NoneType", for the curious.) + # Remove this, please. + + # Get node type, e.g., Script + mg_type = type(node).__name__ + assert mg_type is not None + + if typecode and mg_type not in typecode: + # Type is not a to be selected one, skip this one + return None + # Extract the identifier and a path if any. + if mg_type == 'Script': + # for Script nodes only, identifier is a whole path + (name, ext) = os.path.splitext(node.filename) + name = os.path.basename(name) + elif mg_type == 'ExtensionPackage': + # Package with __init__ module being an extension module. This needs to end up as e.g. 'mypkg/__init__.so'. + # Convert the packages name ('mypkg') into the module name ('mypkg.__init__') *here* to keep special cases + # away elsewhere (where the module name is converted to a filename). + name = node.identifier + ".__init__" + else: + name = node.identifier + path = node.filename if node.filename is not None else '' + # Ensure name is really 'str'. Module graph might return object type 'modulegraph.Alias' which inherits fromm + # 'str'. But 'marshal.dumps()' function is able to marshal only 'str'. Otherwise on Windows PyInstaller might + # fail with message like: + # ValueError: unmarshallable object + name = str(name) + # Translate to the corresponding TOC typecode. + toc_type = MODULE_TYPES_TO_TOC_DICT[mg_type] + return name, path, toc_type + + def nodes_to_toc(self, nodes): + """ + Given a list of nodes, create a TOC representing those nodes. This is mainly used to initialize a TOC of + scripts with the ones that are runtime hooks. The process is almost the same as _make_toc(), but the caller + guarantees the nodes are valid, so minimal checking. + """ + return [self._node_to_toc(node) for node in nodes] + + # Return true if the named item is in the graph as a BuiltinModule node. The passed name is a basename. + def is_a_builtin(self, name): + node = self.find_node(name) + if node is None: + return False + return type(node).__name__ == 'BuiltinModule' + + def get_importers(self, name): + """ + List all modules importing the module with the passed name. + + Returns a list of (identifier, DependencyIinfo)-tuples. If the names module has not yet been imported, this + method returns an empty list. + + Parameters + ---------- + name : str + Fully-qualified name of the module to be examined. + + Returns + ---------- + list + List of (fully-qualified names, DependencyIinfo)-tuples of all modules importing the module with the passed + fully-qualified name. + + """ + def get_importer_edge_data(importer): + edge = self.graph.edge_by_node(importer, name) + # edge might be None in case an AliasModule was added. + if edge is not None: + return self.graph.edge_data(edge) + + node = self.find_node(name) + if node is None: + return [] + _, importers = self.get_edges(node) + importers = (importer.identifier for importer in importers if importer is not None) + return [(importer, get_importer_edge_data(importer)) for importer in importers] + + # TODO: create a class from this function. + def analyze_runtime_hooks(self, custom_runhooks): + """ + Analyze custom run-time hooks and run-time hooks implied by found modules. + + :return : list of Graph nodes. + """ + rthooks_nodes = [] + logger.info('Analyzing run-time hooks ...') + # Process custom runtime hooks (from --runtime-hook options). The runtime hooks are order dependent. First hooks + # in the list are executed first. Put their graph nodes at the head of the priority_scripts list Pyinstaller + # defined rthooks and thus they are executed first. + if custom_runhooks: + for hook_file in custom_runhooks: + logger.info("Including custom run-time hook %r", hook_file) + hook_file = os.path.abspath(hook_file) + # Not using "try" here because the path is supposed to exist, if it does not, the raised error will + # explain. + rthooks_nodes.append(self.add_script(hook_file)) + + # Find runtime hooks that are implied by packages already imported. Get a temporary TOC listing all the scripts + # and packages graphed so far. Assuming that runtime hooks apply only to modules and packages. + temp_toc = self._make_toc(VALID_MODULE_TYPES) + for (mod_name, path, typecode) in temp_toc: + # Look if there is any run-time hook for given module. + if mod_name in self._available_rthooks: + # There could be several run-time hooks for a module. + for abs_path in self._available_rthooks[mod_name]: + hook_path, hook_basename = os.path.split(abs_path) + logger.info("Including run-time hook %r from %r", hook_basename, hook_path) + rthooks_nodes.append(self.add_script(abs_path)) + + return rthooks_nodes + + def add_hiddenimports(self, module_list): + """ + Add hidden imports that are either supplied as CLI option --hidden-import=MODULENAME or as dependencies from + some PyInstaller features when enabled (e.g., crypto feature). + """ + assert self._top_script_node is not None + # Analyze the script's hidden imports (named on the command line). + for modnm in module_list: + node = self.find_node(modnm) + if node is not None: + logger.debug('Hidden import %r already found', modnm) + else: + logger.info("Analyzing hidden import %r", modnm) + # ModuleGraph throws ImportError if import not found. + try: + nodes = self.import_hook(modnm) + assert len(nodes) == 1 + node = nodes[0] + except ImportError: + logger.error("Hidden import %r not found", modnm) + continue + # Create references from the top script to the hidden import, even if found otherwise. Do not waste time + # checking whether it is actually added by this (test-) script. + self.add_edge(self._top_script_node, node) + + def get_code_using(self, module: str) -> dict: + """ + Find modules that import a given **module**. + """ + co_dict = {} + pure_python_module_types = PURE_PYTHON_MODULE_TYPES | { + 'Script', + } + node = self.find_node(module) + if node: + referrers = self.incoming(node) + for r in referrers: + # Under python 3.7 and earlier, if `module` is added to hidden imports, one of referrers ends up being + # None, causing #3825. Work around it. + if r is None: + continue + # Ensure that modulegraph objects have 'code' attribute. + if type(r).__name__ not in pure_python_module_types: + continue + identifier = r.identifier + if identifier == module or identifier.startswith(module + '.'): + # Skip self references or references from `modules`'s own submodules. + continue + # The code object may be None if referrer ends up shadowed by eponymous directory that ends up treated + # as a namespace package. See #6873 for an example. + if r.code is None: + continue + co_dict[r.identifier] = r.code + return co_dict + + def metadata_required(self) -> set: + """ + Collect metadata for all packages that appear to need it. + """ + + # List every function that we can think of which is known to require metadata. + out = set() + + out |= self._metadata_from( + "pkg_resources", + ["get_distribution"], # Requires metadata for one distribution. + ["require"], # Requires metadata for all dependencies. + ) + + # importlib.metadata is often `import ... as` aliased to importlib_metadata for compatibility with < py38. + # Assume both are valid. + for importlib_metadata in ["importlib.metadata", "importlib_metadata"]: + out |= self._metadata_from( + importlib_metadata, + ["metadata", "distribution", "version", "files", "requires"], + [], + ) + + return out + + def _metadata_from(self, package, methods=(), recursive_methods=()) -> set: + """ + Collect metadata whose requirements are implied by given function names. + + Args: + package: + The module name that must be imported in a source file to trigger the search. + methods: + Function names from **package** which take a distribution name as an argument and imply that metadata + is required for that distribution. + recursive_methods: + Like **methods** but also implies that a distribution's dependencies' metadata must be collected too. + Returns: + Required metadata in hook data ``(source, dest)`` format as returned by + :func:`PyInstaller.utils.hooks.copy_metadata()`. + + Scan all source code to be included for usage of particular *key* functions which imply that that code will + require metadata for some distribution (which may not be its own) at runtime. In the case of a match, + collect the required metadata. + """ + from PyInstaller.utils.hooks import copy_metadata + from PyInstaller.compat import importlib_metadata + + # Generate sets of possible function names to search for. + need_metadata = set() + need_recursive_metadata = set() + for method in methods: + need_metadata.update(bytecode.any_alias(package + "." + method)) + for method in recursive_methods: + need_recursive_metadata.update(bytecode.any_alias(package + "." + method)) + + out = set() + + for name, code in self.get_code_using(package).items(): + for calls in bytecode.recursive_function_calls(code).values(): + for function_name, args in calls: + # Only consider function calls taking one argument. + if len(args) != 1: + continue + package = args[0] + try: + if function_name in need_metadata: + out.update(copy_metadata(package)) + elif function_name in need_recursive_metadata: + out.update(copy_metadata(package, recursive=True)) + + except importlib_metadata.PackageNotFoundError: + # Currently, we opt to silently skip over missing metadata. + continue + + return out + + def get_collected_packages(self) -> list: + """ + Return the list of collected python packages. + """ + # `node.identifier` might be an instance of `modulegraph.Alias`, hence explicit conversion to `str`. + return [ + str(node.identifier) for node in self.iter_graph(start=self._top_script_node) + if type(node).__name__ == 'Package' + ] + + def make_hook_binaries_toc(self) -> list: + """ + Return the TOC list of binaries collected by hooks." + """ + toc = [] + for node in self.iter_graph(start=self._top_script_node): + module_name = str(node.identifier) + for dest_name, src_name in self._additional_files_cache.binaries(module_name): + toc.append((dest_name, src_name, 'BINARY')) + + return toc + + def make_hook_datas_toc(self) -> list: + """ + Return the TOC list of data files collected by hooks." + """ + toc = [] + for node in self.iter_graph(start=self._top_script_node): + module_name = str(node.identifier) + for dest_name, src_name in self._additional_files_cache.datas(module_name): + toc.append((dest_name, src_name, 'DATA')) + + return toc + + +_cached_module_graph_ = None + + +def initialize_modgraph(excludes=(), user_hook_dirs=()): + """ + Create the cached module graph. + + This function might appear weird but is necessary for speeding up test runtime because it allows caching basic + ModuleGraph object that gets created for 'base_library.zip'. + + Parameters + ---------- + excludes : list + List of the fully-qualified names of all modules to be "excluded" and hence _not_ frozen into the executable. + user_hook_dirs : list + List of the absolute paths of all directories containing user-defined hooks for the current application or + `None` if no such directories were specified. + + Returns + ---------- + PyiModuleGraph + Module graph with core dependencies. + """ + # Normalize parameters to ensure tuples and make comparison work. + user_hook_dirs = user_hook_dirs or () + excludes = excludes or () + + # Ensure that __main__ is always excluded from the modulegraph, to prevent accidentally pulling PyInstaller itself + # into the modulegraph. This seems to happen on Windows, because modulegraph is able to resolve `__main__` as + # `.../PyInstaller.exe/__main__.py` and analyze it. The `__main__` has a different meaning during analysis compared + # to the program run-time, when it refers to the program's entry-point (which would always be part of the + # modulegraph anyway, by virtue of being the starting point of the analysis). + if "__main__" not in excludes: + excludes += ("__main__",) + + # If there is a graph cached with the same excludes, reuse it. See ``PyiModulegraph._reset()`` for what is + # reset. This cache is used primarily to speed up the test-suite. Fixture `pyi_modgraph` calls this function with + # empty excludes, creating a graph suitable for the huge majority of tests. + global _cached_module_graph_ + if _cached_module_graph_ and _cached_module_graph_._excludes == excludes: + logger.info('Reusing cached module dependency graph...') + graph = deepcopy(_cached_module_graph_) + graph._reset(user_hook_dirs) + return graph + + logger.info('Initializing module dependency graph...') + + # Construct the initial module graph by analyzing all import statements. + graph = PyiModuleGraph( + HOMEPATH, + excludes=excludes, + # get_implies() are hidden imports known by modulgraph. + implies=get_implies(), + user_hook_dirs=user_hook_dirs, + ) + + if not _cached_module_graph_: + # Only cache the first graph, see above for explanation. + logger.info('Caching module dependency graph...') + # cache a deep copy of the graph + _cached_module_graph_ = deepcopy(graph) + # Clear data which does not need to be copied from the cached graph since it will be reset by + # ``PyiModulegraph._reset()`` anyway. + _cached_module_graph_._hooks = None + _cached_module_graph_._hooks_pre_safe_import_module = None + _cached_module_graph_._hooks_pre_find_module_path = None + + return graph + + +def get_bootstrap_modules(): + """ + Get TOC with the bootstrapping modules and their dependencies. + :return: TOC with modules + """ + # Import 'struct' modules to get real paths to module file names. + mod_struct = __import__('struct') + # Basic modules necessary for the bootstrap process. + loader_mods = list() + loaderpath = os.path.join(HOMEPATH, 'PyInstaller', 'loader') + # On some platforms (Windows, Debian/Ubuntu) '_struct' and zlib modules are built-in modules (linked statically) + # and thus does not have attribute __file__. 'struct' module is required for reading Python bytecode from + # executable. 'zlib' is required to decompress this bytecode. + for mod_name in ['_struct', 'zlib']: + mod = __import__(mod_name) # C extension. + if hasattr(mod, '__file__'): + mod_file = os.path.abspath(mod.__file__) + if os.path.basename(os.path.dirname(mod_file)) == 'lib-dynload': + # Divert extensions originating from python's lib-dynload directory, to match behavior of #5604. + mod_name = os.path.join('lib-dynload', mod_name) + loader_mods.append(add_suffix_to_extension(mod_name, mod_file, 'EXTENSION')) + loader_mods.append(('struct', os.path.abspath(mod_struct.__file__), 'PYMODULE')) + # Loader/bootstrap modules. + # NOTE: These modules should be kept simple without any complicated dependencies. + loader_mods += [ + ('pyimod01_archive', os.path.join(loaderpath, 'pyimod01_archive.py'), 'PYMODULE'), + ('pyimod02_importers', os.path.join(loaderpath, 'pyimod02_importers.py'), 'PYMODULE'), + ('pyimod03_ctypes', os.path.join(loaderpath, 'pyimod03_ctypes.py'), 'PYMODULE'), + ] + if is_win: + loader_mods.append(('pyimod04_pywin32', os.path.join(loaderpath, 'pyimod04_pywin32.py'), 'PYMODULE')) + # The bootstrap script + loader_mods.append(('pyiboot01_bootstrap', os.path.join(loaderpath, 'pyiboot01_bootstrap.py'), 'PYSOURCE')) + return loader_mods diff --git a/venv/Lib/site-packages/PyInstaller/depend/bindepend.py b/venv/Lib/site-packages/PyInstaller/depend/bindepend.py new file mode 100644 index 0000000..cfb448f --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/depend/bindepend.py @@ -0,0 +1,946 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- +""" +Find external dependencies of binary libraries. +""" + +import ctypes.util +import os +import pathlib +import re +import sys +import sysconfig +import subprocess + +from PyInstaller import compat +from PyInstaller import log as logging +from PyInstaller.depend import dylib, utils +from PyInstaller.utils.win32 import winutils + +if compat.is_darwin: + import PyInstaller.utils.osx as osxutils + +logger = logging.getLogger(__name__) + +_exe_machine_type = None +if compat.is_win: + _exe_machine_type = winutils.get_pe_file_machine_type(compat.python_executable) + +#- High-level binary dependency analysis + + +def _get_paths_for_parent_directory_preservation(): + """ + Return list of paths that serve as prefixes for parent-directory preservation of collected binaries and/or + shared libraries. If a binary is collected from a location that starts with a path from this list, the relative + directory structure is preserved within the frozen application bundle; otherwise, the binary is collected to the + frozen application's top-level directory. + """ + + # Use only site-packages paths. We have no control over contents of `sys.path`, so using all paths from that may + # lead to unintended behavior in corner cases. For example, if `sys.path` contained the drive root (see #7028), + # all paths that do not match some other sub-path rooted in that drive will end up recognized as relative to the + # drive root. In such case, any DLL collected from `c:\Windows\system32` will be collected into `Windows\system32` + # sub-directory; ucrt DLLs collected from MSVC or Windows SDK installed in `c:\Program Files\...` will end up + # collected into `Program Files\...` subdirectory; etc. + # + # On the other hand, the DLL parent directory preservation is primarily aimed at packages installed via PyPI + # wheels, which are typically installed into site-packages. Therefore, limiting the directory preservation for + # shared libraries collected from site-packages should do the trick, and should be reasonably safe. + import site + + orig_paths = site.getsitepackages() + orig_paths.append(site.getusersitepackages()) + + # Explicitly excluded paths. `site.getsitepackages` seems to include `sys.prefix`, which we need to exclude, to + # avoid issue swith DLLs in its sub-directories. We need both resolved and unresolved variant to handle cases + # where `base_prefix` itself is a symbolic link (e.g., `scoop`-installed python on Windows, see #8023). + excluded_paths = { + pathlib.Path(sys.base_prefix), + pathlib.Path(sys.base_prefix).resolve(), + pathlib.Path(sys.prefix), + pathlib.Path(sys.prefix).resolve(), + } + + # For each path in orig_paths, append a resolved variant. This helps with linux venv where we need to consider + # both `venv/lib/python3.11/site-packages` and `venv/lib/python3.11/site-packages` and `lib64` is a symlink + # to `lib`. + orig_paths += [pathlib.Path(path).resolve() for path in orig_paths] + + paths = set() + for path in orig_paths: + if not path: + continue + path = pathlib.Path(path) + # Filter out non-directories (e.g., /path/to/python3x.zip) or non-existent paths + if not path.is_dir(): + continue + # Filter out explicitly excluded paths + if path in excluded_paths: + continue + paths.add(path) + + # Sort by length (in term of path components) to ensure match against the longest common prefix (for example, match + # /path/to/venv/lib/site-packages instead of /path/to/venv when both paths are in site paths). + paths = sorted(paths, key=lambda x: len(x.parents), reverse=True) + + return paths + + +def _select_destination_directory(src_filename, parent_dir_preservation_paths): + # Check parent directory preservation paths + for parent_dir_preservation_path in parent_dir_preservation_paths: + if parent_dir_preservation_path in src_filename.parents: + # Collect into corresponding sub-directory. + return src_filename.relative_to(parent_dir_preservation_path) + + # Collect into top-level directory. + return src_filename.name + + +def binary_dependency_analysis(binaries, search_paths=None, symlink_suppression_patterns=None): + """ + Perform binary dependency analysis on the given TOC list of collected binaries, by recursively scanning each binary + for linked dependencies (shared library imports). Returns new TOC list that contains both original entries and their + binary dependencies. + + Additional search paths for dependencies' full path resolution may be supplied via optional argument. + """ + + # Get all path prefixes for binaries' parent-directory preservation. For binaries collected from packages in (for + # example) site-packages directory, we should try to preserve the parent directory structure. + parent_dir_preservation_paths = _get_paths_for_parent_directory_preservation() + + # Keep track of processed binaries and processed dependencies. + processed_binaries = set() + processed_dependencies = set() + + # Keep track of unresolved dependencies, in order to defer the missing-library warnings until after everything has + # been processed. This allows us to suppress warnings for dependencies that end up being collected anyway; for + # details, see the end of this function. + missing_dependencies = [] + + # Populate output TOC with input binaries - this also serves as TODO list, as we iterate over it while appending + # new entries at the end. + output_toc = binaries[:] + for dest_name, src_name, typecode in output_toc: + # Do not process symbolic links (already present in input TOC list, or added during analysis below). + if typecode == 'SYMLINK': + continue + + # Keep track of processed binaries, to avoid unnecessarily repeating analysis of the same file. Use pathlib.Path + # to avoid having to worry about case normalization. + src_path = pathlib.Path(src_name) + if src_path in processed_binaries: + continue + processed_binaries.add(src_path) + + logger.debug("Analyzing binary %r", src_name) + + # Analyze imports (linked dependencies) + for dep_name, dep_src_path in get_imports(src_name, search_paths): + logger.debug("Processing dependency, name: %r, resolved path: %r", dep_name, dep_src_path) + + # Skip unresolved dependencies. Defer the missing-library warnings until after binary dependency analysis + # is complete. + if not dep_src_path: + missing_dependencies.append((dep_name, src_name)) + continue + + # Compare resolved dependency against global inclusion/exclusion rules. + if not dylib.include_library(dep_src_path): + logger.debug("Skipping dependency %r due to global exclusion rules.", dep_src_path) + continue + + dep_src_path = pathlib.Path(dep_src_path) # Turn into pathlib.Path for subsequent processing + + # Avoid processing this dependency if we have already processed it. + if dep_src_path in processed_dependencies: + logger.debug("Skipping dependency %r due to prior processing.", str(dep_src_path)) + continue + processed_dependencies.add(dep_src_path) + + # Try to preserve parent directory structure, if applicable. + # NOTE: do not resolve the source path, because on macOS and linux, it may be a versioned .so (e.g., + # libsomething.so.1, pointing at libsomething.so.1.2.3), and we need to collect it under original name! + dep_dest_path = _select_destination_directory(dep_src_path, parent_dir_preservation_paths) + dep_dest_path = pathlib.PurePath(dep_dest_path) # Might be a str() if it is just a basename... + + # If we are collecting library into top-level directory on macOS, check whether it comes from a + # .framework bundle. If it does, re-create the .framework bundle in the top-level directory + # instead. + if compat.is_darwin and dep_dest_path.parent == pathlib.PurePath('.'): + if osxutils.is_framework_bundle_lib(dep_src_path): + # dst_src_path is parent_path/Name.framework/Versions/Current/Name + framework_parent_path = dep_src_path.parent.parent.parent.parent + dep_dest_path = pathlib.PurePath(dep_src_path.relative_to(framework_parent_path)) + + logger.debug("Collecting dependency %r as %r.", str(dep_src_path), str(dep_dest_path)) + output_toc.append((str(dep_dest_path), str(dep_src_path), 'BINARY')) + + # On non-Windows, if we are not collecting the binary into application's top-level directory ('.'), + # add a symbolic link from top-level directory to the actual location. This is to accommodate + # LD_LIBRARY_PATH being set to the top-level application directory on linux (although library search + # should be mostly done via rpaths, so this might be redundant) and to accommodate library path + # rewriting on macOS, which assumes that the library was collected into top-level directory. + if compat.is_win: + # We do not use symlinks on Windows. + pass + elif dep_dest_path.parent == pathlib.PurePath('.'): + # The shared library itself is being collected into top-level application directory. + pass + elif any(dep_src_path.match(pattern) for pattern in symlink_suppression_patterns): + # Honor symlink suppression patterns specified by hooks. + logger.debug( + "Skipping symbolic link from %r to top-level application directory due to source path matching one " + "of symlink suppression path patterns.", str(dep_dest_path) + ) + else: + logger.debug("Adding symbolic link from %r to top-level application directory.", str(dep_dest_path)) + output_toc.append((str(dep_dest_path.name), str(dep_dest_path), 'SYMLINK')) + + # Display warnings about missing dependencies + seen_binaries = set([ + os.path.normcase(os.path.basename(src_name)) for dest_name, src_name, typecode in output_toc + if typecode != 'SYMLINK' + ]) + for dependency_name, referring_binary in missing_dependencies: + # Ignore libraries that we would not collect in the first place. + if not dylib.include_library(dependency_name): + continue + # Apply global warning suppression rules. + if not dylib.warn_missing_lib(dependency_name): + continue + # If the binary with a matching basename happens to be among the discovered binaries, suppress the message as + # well. This might happen either because the library was collected by some other mechanism (for example, via + # hook, or supplied by the user), or because it was discovered during the analysis of another binary (which, + # for example, had properly set run-paths on Linux/macOS or was located next to that other analyzed binary on + # Windows). + if os.path.normcase(os.path.basename(dependency_name)) in seen_binaries: + continue + logger.warning("Library not found: could not resolve %r, dependency of %r.", dependency_name, referring_binary) + + return output_toc + + +#- Low-level import analysis + + +def get_imports(filename, search_paths=None): + """ + Analyze the given binary file (shared library or executable), and obtain the list of shared libraries it imports + (i.e., link-time dependencies). + + Returns set of tuples (name, fullpath). The name component is the referenced name, and on macOS, may not be just + a base name. If the library's full path cannot be resolved, fullpath element is None. + + Additional list of search paths may be specified via `search_paths`, to be used as a fall-back when the + platform-specific resolution mechanism fails to resolve a library fullpath. + """ + if compat.is_win: + if str(filename).lower().endswith(".manifest"): + return [] + return _get_imports_pefile(filename, search_paths) + elif compat.is_darwin: + return _get_imports_macholib(filename, search_paths) + else: + return _get_imports_ldd(filename, search_paths) + + +def _get_imports_pefile(filename, search_paths): + """ + Windows-specific helper for `get_imports`, which uses the `pefile` library to walk through PE header. + """ + import pefile + + output = set() + + # By default, pefile library parses all PE information. We are only interested in the list of dependent dlls. + # Performance is improved by reading only needed information. https://code.google.com/p/pefile/wiki/UsageExamples + pe = pefile.PE(filename, fast_load=True) + pe.parse_data_directories( + directories=[ + pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_IMPORT'], + pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_EXPORT'], + ], + forwarded_exports_only=True, + import_dllnames_only=True, + ) + + # If a library has no binary dependencies, pe.DIRECTORY_ENTRY_IMPORT does not exist. + for entry in getattr(pe, 'DIRECTORY_ENTRY_IMPORT', []): + dll_str = entry.dll.decode('utf-8') + output.add(dll_str) + + # We must also read the exports table to find forwarded symbols: + # http://blogs.msdn.com/b/oldnewthing/archive/2006/07/19/671238.aspx + exported_symbols = getattr(pe, 'DIRECTORY_ENTRY_EXPORT', None) + if exported_symbols: + for symbol in exported_symbols.symbols: + if symbol.forwarder is not None: + # symbol.forwarder is a bytes object. Convert it to a string. + forwarder = symbol.forwarder.decode('utf-8') + # symbol.forwarder is for example 'KERNEL32.EnterCriticalSection' + dll = forwarder.split('.')[0] + output.add(dll + ".dll") + + pe.close() + + # Attempt to resolve full paths to referenced DLLs. Always add the input binary's parent directory to the search + # paths. + search_paths = [os.path.dirname(filename)] + (search_paths or []) + output = {(lib, resolve_library_path(lib, search_paths)) for lib in output} + + return output + + +def _get_imports_ldd(filename, search_paths): + """ + Helper for `get_imports`, which uses `ldd` to analyze shared libraries. Used on Linux and other POSIX-like platforms + (with exception of macOS). + """ + + output = set() + + # Output of ldd varies between platforms... + if compat.is_aix: + # Match libs of the form + # 'archivelib.a(objectmember.so/.o)' + # or + # 'sharedlib.so' + # Will not match the fake lib '/unix' + LDD_PATTERN = re.compile(r"^\s*(((?P(.*\.a))(?P\(.*\)))|((?P(.*\.so))))$") + elif compat.is_hpux: + # Match libs of the form + # 'sharedlib.so => full-path-to-lib + # e.g. + # 'libpython2.7.so => /usr/local/lib/hpux32/libpython2.7.so' + LDD_PATTERN = re.compile(r"^\s+(.*)\s+=>\s+(.*)$") + elif compat.is_solar: + # Match libs of the form + # 'sharedlib.so => full-path-to-lib + # e.g. + # 'libpython2.7.so.1.0 => /usr/local/lib/libpython2.7.so.1.0' + # Will not match the platform specific libs starting with '/platform' + LDD_PATTERN = re.compile(r"^\s+(.*)\s+=>\s+(.*)$") + elif compat.is_linux: + # Match libs of the form + # libpython3.13.so.1.0 => /home/brenainn/.pyenv/versions/3.13.0/lib/libpython3.13.so.1.0 (0x00007a9e15800000) + # or + # /tmp/python/install/bin/../lib/libpython3.13.so.1.0 (0x00007b9489c82000) + LDD_PATTERN = re.compile(r"^\s*(?:(.*?)\s+=>\s+)?(.*?)\s+\(.*\)") + else: + LDD_PATTERN = re.compile(r"\s*(.*?)\s+=>\s+(.*?)\s+\(.*\)") + + # Resolve symlinks since GNU ldd contains a bug in processing a symlink to a binary + # using $ORIGIN: https://sourceware.org/bugzilla/show_bug.cgi?id=25263 + p = subprocess.run( + ['ldd', os.path.realpath(filename)], + stdin=subprocess.DEVNULL, + stderr=subprocess.PIPE, + stdout=subprocess.PIPE, + encoding='utf-8', + ) + + ldd_warnings = [] + for line in p.stderr.splitlines(): + if not line: + continue + # Python extensions (including stdlib ones) are not linked against python.so but rely on Python's symbols having + # already been loaded into symbol space at runtime. musl's ldd issues a series of harmless warnings to stderr + # telling us that those symbols are unfindable. These should be suppressed. + elif line.startswith("Error relocating ") and line.endswith(" symbol not found"): + continue + # Shared libraries should have the executable bits set; however, this is not the case for shared libraries + # shipped in PyPI wheels, which cause ldd to emit `ldd: warning: you do not have execution permission for ...` + # warnings. Suppress these. + elif line.startswith("ldd: warning: you do not have execution permission for "): + continue + # When `ldd` is ran against a file that is not a dynamic binary (i.e., is not a binary at all, or is a static + # binary), it emits a "not a dynamic executable" warning. Suppress it. + elif "not a dynamic executable" in line: + continue + # Propagate any other warnings it might have. + ldd_warnings.append(line) + if ldd_warnings: + logger.warning("ldd warnings for %r:\n%s", filename, "\n".join(ldd_warnings)) + + for line in p.stdout.splitlines(): + name = None # Referenced name + lib = None # Resolved library path + + m = LDD_PATTERN.search(line) + if m: + if compat.is_aix: + libarchive = m.group('libarchive') + if libarchive: + # We matched an archive lib with a request for a particular embedded shared object. + # 'archivelib.a(objectmember.so/.o)' + lib = libarchive + name = os.path.basename(lib) + m.group('objectmember') + else: + # We matched a stand-alone shared library. + # 'sharedlib.so' + lib = m.group('libshared') + name = os.path.basename(lib) + elif compat.is_hpux: + name, lib = m.group(1), m.group(2) + else: + name, lib = m.group(1), m.group(2) + name = name or os.path.basename(lib) + if compat.is_linux: + # Skip all ld variants listed https://sourceware.org/glibc/wiki/ABIList + # plus musl's ld-musl-*.so.*. + if re.fullmatch(r"ld(64)?(-linux|-musl)?(-.+)?\.so(\..+)?", os.path.basename(lib)): + continue + if name[:10] in ('linux-gate', 'linux-vdso'): + # linux-gate is a fake library which does not exist and should be ignored. See also: + # http://www.trilithium.com/johan/2005/08/linux-gate/ + continue + + if compat.is_cygwin: + # exclude Windows system library + if lib.lower().startswith('/cygdrive/c/windows/system'): + continue + + # Reset library path if it does not exist + if not os.path.exists(lib): + lib = None + elif line.endswith("not found"): + # On glibc-based linux distributions, missing libraries are marked with name.so => not found + tokens = line.split('=>') + if len(tokens) != 2: + continue + name = tokens[0].strip() + lib = None + else: + # TODO: should we warn about unprocessed lines? + continue + + # Fall back to searching the supplied search paths, if any. + if not lib: + lib = _resolve_library_path_in_search_paths( + os.path.basename(name), # Search for basename of the referenced name. + search_paths, + ) + + # Normalize the resolved path, to remove any extraneous "../" elements. + if lib: + lib = os.path.normpath(lib) + + # Return referenced name as-is instead of computing a basename, to provide additional context when library + # cannot be resolved. + output.add((name, lib)) + + return output + + +def _get_imports_macholib(filename, search_paths): + """ + macOS-specific helper for `get_imports`, which uses `macholib` to analyze library load commands in Mach-O headers. + """ + from macholib.dyld import dyld_find + from macholib.mach_o import LC_RPATH + from macholib.MachO import MachO + + try: + from macholib.dyld import _dyld_shared_cache_contains_path + except ImportError: + _dyld_shared_cache_contains_path = None + + output = set() + referenced_libs = set() # Libraries referenced in Mach-O headers. + + # Parent directory of the input binary and parent directory of python executable, used to substitute @loader_path + # and @executable_path. The MacOS dylib loader (dyld) fully resolves the symbolic links when using @loader_path + # and @executable_path references, so we need to do the same using `os.path.realpath`. + bin_path = os.path.dirname(os.path.realpath(filename)) + python_bin_path = os.path.dirname(os.path.realpath(sys.executable)) + + # Walk through Mach-O headers, and collect all referenced libraries. + m = MachO(filename) + for header in m.headers: + for idx, name, lib in header.walkRelocatables(): + referenced_libs.add(lib) + + # Find LC_RPATH commands to collect rpaths. macholib does not handle @rpath, so we need to handle run paths + # ourselves. + run_paths = set() + for header in m.headers: + for command in header.commands: + # A command is a tuple like: + # (, + # , + # '../lib\x00\x00') + cmd_type = command[0].cmd + if cmd_type == LC_RPATH: + rpath = command[2].decode('utf-8') + # Remove trailing '\x00' characters. E.g., '../lib\x00\x00' + rpath = rpath.rstrip('\x00') + # If run path starts with @, ensure it starts with either @loader_path or @executable_path. We cannot + # process anything else. + if rpath.startswith("@") and not rpath.startswith(("@executable_path", "@loader_path")): + logger.warning("Unsupported rpath format %r found in binary %r - ignoring...", rpath, filename) + continue + run_paths.add(rpath) + + # For distributions like Anaconda, all of the dylibs are stored in the lib directory of the Python distribution, not + # alongside of the .so's in each module's subdirectory. Usually, libraries using @rpath to reference their + # dependencies also set up their run-paths via LC_RPATH commands. However, they are not strictly required to do so, + # because run-paths are inherited from the process within which the libraries are loaded. Therefore, if the python + # executable uses an LC_RPATH command to set up run-path that resolves the shared lib directory (for example, + # `@loader_path/../lib` in case of the Anaconda python), all libraries loaded within the python process are able + # to resolve the shared libraries within the environment's shared lib directory without using LC_RPATH commands + # themselves. + # + # Our analysis does not account for inherited run-paths, and we attempt to work around this limitation by + # registering the following fall-back run-path. + run_paths.add(os.path.join(compat.base_prefix, 'lib')) + + def _resolve_using_loader_path(lib, bin_path, python_bin_path): + # macholib does not support @loader_path, so replace it with @executable_path. Strictly speaking, @loader_path + # should be anchored to parent directory of analyzed binary (`bin_path`), while @executable_path should be + # anchored to the parent directory of the process' executable. Typically, this would be python executable + # (`python_bin_path`), unless we are analyzing a collected 3rd party executable. In that case, `bin_path` + # is correct option. So we first try resolving using `bin_path`, and then fall back to `python_bin_path`. + # This does not account for transitive run paths of higher-order dependencies, but there is only so much we + # can do here... + if lib.startswith('@loader_path'): + lib = lib.replace('@loader_path', '@executable_path') + + try: + # Try resolving with binary's path first... + return dyld_find(lib, executable_path=bin_path) + except ValueError: + # ... and fall-back to resolving with python executable's path + try: + return dyld_find(lib, executable_path=python_bin_path) + except ValueError: + return None + + def _resolve_using_path(lib): + # Absolute paths should not be resolved; we should just check whether the library exists or not. This used to + # be done using macholib's dyld_find() as well (as it properly handles system libraries that are hidden on + # Big Sur and later), but it turns out that even if given an absolute path, it gives precedence to search paths + # from DYLD_LIBRARY_PATH. This leads to confusing errors when directory in DYLD_LIBRARY_PATH contains a file + # (shared library or data file) that happens to have the same name as a library from a system framework. + if os.path.isabs(lib): + if _dyld_shared_cache_contains_path is not None and _dyld_shared_cache_contains_path(lib): + return lib + if os.path.isfile(lib): + return lib + return None + + try: + return dyld_find(lib) + except ValueError: + return None + + # Try to resolve full path of the referenced libraries. + for referenced_lib in referenced_libs: + resolved_lib = None + + # If path starts with @rpath, we have to handle it ourselves. + if referenced_lib.startswith('@rpath'): + lib = os.path.join(*referenced_lib.split(os.sep)[1:]) # Remove the @rpath/ prefix + + # Try all run paths. + for run_path in run_paths: + # Join the path. + lib_path = os.path.join(run_path, lib) + + if lib_path.startswith(("@executable_path", "@loader_path")): + # Run path starts with @executable_path or @loader_path. + lib_path = _resolve_using_loader_path(lib_path, bin_path, python_bin_path) + else: + # If run path was relative, anchor it to binary's location. + if not os.path.isabs(lib_path): + os.path.join(bin_path, lib_path) + lib_path = _resolve_using_path(lib_path) + + if lib_path and os.path.exists(lib_path): + resolved_lib = lib_path + break + else: + if referenced_lib.startswith(("@executable_path", "@loader_path")): + resolved_lib = _resolve_using_loader_path(referenced_lib, bin_path, python_bin_path) + else: + resolved_lib = _resolve_using_path(referenced_lib) + + # Fall back to searching the supplied search paths, if any. + if not resolved_lib: + resolved_lib = _resolve_library_path_in_search_paths( + os.path.basename(referenced_lib), # Search for basename of the referenced name. + search_paths, + ) + + # Normalize the resolved path, to remove any extraneous "../" elements. + if resolved_lib: + resolved_lib = os.path.normpath(resolved_lib) + + # Return referenced library name as-is instead of computing a basename. Full referenced name carries additional + # information that might be useful for the caller to determine how to deal with unresolved library (e.g., ignore + # unresolved libraries that are supposed to be located in system-wide directories). + output.add((referenced_lib, resolved_lib)) + + return output + + +#- Library full path resolution + + +def resolve_library_path(name, search_paths=None): + """ + Given a library name, attempt to resolve full path to that library. The search for library is done via + platform-specific mechanism and fall back to optionally-provided list of search paths. Returns None if library + cannot be resolved. If give library name is already an absolute path, the given path is returned without any + processing. + """ + # No-op if path is already absolute. + if os.path.isabs(name): + return name + + if compat.is_unix: + # Use platform-specific helper. + fullpath = _resolve_library_path_unix(name) + if fullpath: + return fullpath + # Fall back to searching the supplied search paths, if any + return _resolve_library_path_in_search_paths(name, search_paths) + elif compat.is_win: + # Try the caller-supplied search paths, if any. + fullpath = _resolve_library_path_in_search_paths(name, search_paths) + if fullpath: + return fullpath + + # Fall back to default Windows search paths, using the PATH environment variable (which should also include + # the system paths, such as c:\windows and c:\windows\system32) + win_search_paths = [path for path in compat.getenv('PATH', '').split(os.pathsep) if path] + return _resolve_library_path_in_search_paths(name, win_search_paths) + else: + return ctypes.util.find_library(name) + + return None + + +# Compatibility aliases for hooks from contributed hooks repository. All of these now point to the high-level +# `resolve_library_path`. +findLibrary = resolve_library_path +findSystemLibrary = resolve_library_path + + +def _resolve_library_path_in_search_paths(name, search_paths=None): + """ + Low-level helper for resolving given library name to full path in given list of search paths. + """ + for search_path in search_paths or []: + fullpath = os.path.join(search_path, name) + if not os.path.isfile(fullpath): + continue + + # On Windows, ensure that architecture matches that of running python interpreter. + if compat.is_win: + try: + dll_machine_type = winutils.get_pe_file_machine_type(fullpath) + except Exception: + # A search path might contain a DLL that we cannot analyze; for example, a stub file. Skip over. + continue + if dll_machine_type != _exe_machine_type: + continue + + return os.path.normpath(fullpath) + + return None + + +def _resolve_library_path_unix(name): + """ + UNIX-specific helper for resolving library path. + + Emulates the algorithm used by dlopen. `name` must include the prefix, e.g., ``libpython2.4.so``. + """ + assert compat.is_unix, "Current implementation for Unix only (Linux, Solaris, AIX, FreeBSD)" + + if name.endswith('.so') or '.so.' in name: + # We have been given full library name that includes suffix. Use `_resolve_library_path_in_search_paths` to find + # the exact match. + lib_search_func = _resolve_library_path_in_search_paths + else: + # We have been given a library name without suffix. Use `_which_library` as search function, which will try to + # find library with matching basename. + lib_search_func = _which_library + + # Look in the LD_LIBRARY_PATH according to platform. + if compat.is_aix: + lp = compat.getenv('LIBPATH', '') + elif compat.is_darwin: + lp = compat.getenv('DYLD_LIBRARY_PATH', '') + else: + lp = compat.getenv('LD_LIBRARY_PATH', '') + lib = lib_search_func(name, filter(None, lp.split(os.pathsep))) + + # Look in /etc/ld.so.cache + # Solaris does not have /sbin/ldconfig. Just check if this file exists. + if lib is None: + utils.load_ldconfig_cache() + lib = utils.LDCONFIG_CACHE.get(name) + if lib: + assert os.path.isfile(lib) + + # Look in the known safe paths. + if lib is None: + # Architecture independent locations. + paths = ['/lib', '/usr/lib'] + # Architecture dependent locations. + if compat.architecture == '32bit': + paths.extend(['/lib32', '/usr/lib32']) + else: + paths.extend(['/lib64', '/usr/lib64']) + # Machine dependent locations. + if compat.machine == 'intel': + if compat.architecture == '32bit': + paths.extend(['/usr/lib/i386-linux-gnu']) + else: + paths.extend(['/usr/lib/x86_64-linux-gnu']) + + # On Debian/Ubuntu /usr/bin/python is linked statically with libpython. Newer Debian/Ubuntu with multiarch + # support puts the libpythonX.Y.so in paths like /usr/lib/i386-linux-gnu/. Try to query the arch-specific + # sub-directory, if available. + arch_subdir = sysconfig.get_config_var('multiarchsubdir') + if arch_subdir: + arch_subdir = os.path.basename(arch_subdir) + paths.append(os.path.join('/usr/lib', arch_subdir)) + else: + logger.debug('Multiarch directory not detected.') + + # Termux (a Ubuntu like subsystem for Android) has an additional libraries directory. + if os.path.isdir('/data/data/com.termux/files/usr/lib'): + paths.append('/data/data/com.termux/files/usr/lib') + + if compat.is_aix: + paths.append('/opt/freeware/lib') + elif compat.is_hpux: + if compat.architecture == '32bit': + paths.append('/usr/local/lib/hpux32') + else: + paths.append('/usr/local/lib/hpux64') + elif compat.is_freebsd or compat.is_openbsd: + paths.append('/usr/local/lib') + lib = lib_search_func(name, paths) + + return lib + + +def _which_library(name, dirs): + """ + Search for a shared library in a list of directories. + + Args: + name: + The library name including the `lib` prefix but excluding any `.so` suffix. + dirs: + An iterable of folders to search in. + Returns: + The path to the library if found or None otherwise. + + """ + matcher = _library_matcher(name) + for path in filter(os.path.exists, dirs): + for _path in os.listdir(path): + if matcher(_path): + return os.path.join(path, _path) + + +def _library_matcher(name): + """ + Create a callable that matches libraries if **name** is a valid library prefix for input library full names. + """ + return re.compile(name + r"[0-9]*\.").match + + +#- Python shared library search + + +def get_python_library_path(): + """ + Find Python shared library that belongs to the current interpreter. + + Return full path to Python dynamic library or None when not found. + + PyInstaller needs to collect the Python shared library, so that bootloader can load it, import Python C API + symbols, and use them to set up the embedded Python interpreter. + + The name of the shared library is typically fixed (`python3.X.dll` on Windows, libpython3.X.so on Unix systems, + and `libpython3.X.dylib` on macOS for shared library builds and `Python.framework/Python` for framework build). + Its location can usually be inferred from the Python interpreter executable, when the latter is dynamically + linked against the shared library. + + However, some situations require extra handling due to various quirks; for example, debian-based some linux + distributions statically link the Python interpreter executable against the Python library, while also providing + a shared library variant for external users. + """ + def _find_lib_in_libdirs(*libdirs): + for libdir in libdirs: + for name in compat.PYDYLIB_NAMES: + full_path = os.path.join(libdir, name) + if not os.path.exists(full_path): + continue + # Resolve potential symbolic links to achieve consistent results with linker-based search; e.g., on + # POSIX systems, linker resolves unversioned library names (python3.X.so) to versioned ones + # (libpython3.X.so.1.0) due to former being symbolic linkes to the latter. See #6831. + full_path = os.path.realpath(full_path) + if not os.path.exists(full_path): + continue + return full_path + return None + + # If this is Microsoft App Store Python, check the compat.base_path first. While compat.python_executable resolves + # to actual python.exe file, the latter contains a relative library reference that we fail to properly resolve. + if compat.is_ms_app_store: + python_libname = _find_lib_in_libdirs(compat.base_prefix) + if python_libname: + return python_libname + + # Try to get Python library name from the Python executable. It assumes that Python library is not statically + # linked. + imported_libraries = get_imports(compat.python_executable) # (name, fullpath) tuples + for _, lib_path in imported_libraries: + if lib_path is None: + continue # Skip unresolved imports + for name in compat.PYDYLIB_NAMES: + if os.path.normcase(os.path.basename(lib_path)) == name: + # Python library found. Return absolute path to it. + return lib_path + + # Work around for Python venv having VERSION.dll rather than pythonXY.dll + if compat.is_win and any([os.path.normcase(lib_name) == 'version.dll' for lib_name, _ in imported_libraries]): + pydll = 'python%d%d.dll' % sys.version_info[:2] + return resolve_library_path(pydll, [os.path.dirname(compat.python_executable)]) + + # Search the `sys.base_prefix` and `lib` directory in `sys.base_prefix`. + # This covers various Python installations in case we fail to infer the shared library location for whatever reason; + # Anaconda Python, `uv` and `rye` Python, etc. + python_libname = _find_lib_in_libdirs( + compat.base_prefix, + os.path.join(compat.base_prefix, 'lib'), + ) + if python_libname: + return python_libname + + # On Unix-like systems, perform search in the configured library search locations. This should be done after + # exhausting all other options; it primarily caters to debian-packaged Python, but we need to make sure that we do + # not collect shared library from system-installed Python when the current interpreter is in fact some other Python + # build (for example, `uv` or `rye` Python of the same version as system-installed Python). + if compat.is_unix: + for name in compat.PYDYLIB_NAMES: + python_libname = resolve_library_path(name) + if python_libname: + return python_libname + + # Python library NOT found. Return None and let the caller deal with this. + return None + + +#- Binary vs data (re)classification + + +def classify_binary_vs_data(filename): + """ + Classify the given file as either BINARY or a DATA, using appropriate platform-specific method. Returns 'BINARY' + or 'DATA' string depending on the determined file type, or None if classification cannot be performed (non-existing + file, missing tool, and other errors during classification). + """ + + # We cannot classify non-existent files. + if not os.path.isfile(filename): + return None + + # Use platform-specific implementation. + return _classify_binary_vs_data(filename) + + +if compat.is_linux: + + def _classify_binary_vs_data(filename): + # First check for ELF signature, in order to avoid calling `objdump` on every data file, which can be costly. + try: + with open(filename, 'rb') as fp: + sig = fp.read(4) + except Exception: + return None + + if sig != b"\x7FELF": + return "DATA" + + # Verify the binary by checking if `objdump` recognizes the file. The preceding ELF signature check should + # ensure that this is an ELF file, while this check should ensure that it is a valid ELF file. In the future, + # we could try checking that the architecture matches the running platform. + cmd_args = ['objdump', '-a', filename] + try: + p = subprocess.run( + cmd_args, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + stdin=subprocess.DEVNULL, + encoding='utf8', + ) + except Exception: + return None # Failed to run `objdump` or `objdump` unavailable. + + return 'BINARY' if p.returncode == 0 else 'DATA' + +elif compat.is_win: + + def _classify_binary_vs_data(filename): + import pefile + + # First check for MZ signature, which should allow us to quickly classify the majority of data files. + try: + with open(filename, 'rb') as fp: + sig = fp.read(2) + except Exception: + return None + + if sig != b"MZ": + return "DATA" + + # Check if the file can be opened using `pefile`. + try: + with pefile.PE(filename, fast_load=True) as pe: # noqa: F841 + pass + return 'BINARY' + except pefile.PEFormatError: + return 'DATA' + except Exception: + pass + + return None + +elif compat.is_darwin: + + def _classify_binary_vs_data(filename): + # See if the file can be opened using `macholib`. + import macholib.MachO + + try: + macho = macholib.MachO.MachO(filename) # noqa: F841 + return 'BINARY' + except Exception: + # TODO: catch only `ValueError`? + pass + + return 'DATA' + +else: + + def _classify_binary_vs_data(filename): + # Classification not implemented for the platform. + return None diff --git a/venv/Lib/site-packages/PyInstaller/depend/bytecode.py b/venv/Lib/site-packages/PyInstaller/depend/bytecode.py new file mode 100644 index 0000000..bd633ef --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/depend/bytecode.py @@ -0,0 +1,337 @@ +# -*- coding: utf-8 -*- +""" +Tools for searching bytecode for key statements that indicate the need for additional resources, such as data files +and package metadata. + +By *bytecode* I mean the ``code`` object given by ``compile()``, accessible from the ``__code__`` attribute of any +non-builtin function or, in PyInstallerLand, the ``PyiModuleGraph.node("some.module").code`` attribute. The best +guide for bytecode format I have found is the disassembler reference: https://docs.python.org/3/library/dis.html + +This parser implementation aims to combine the flexibility and speed of regex with the clarity of the output of +``dis.dis(code)``. It has not achieved the 2nd, but C'est la vie... + +The biggest clarity killer here is the ``EXTENDED_ARG`` opcode which can appear almost anywhere and therefore needs +to be tiptoed around at every step. If this code needs to expand significantly, I would recommend an upgrade to a +regex-based grammar parsing library such as Reparse. This way, little steps like unpacking ``EXTENDED_ARGS`` can be +defined once then simply referenced forming a nice hierarchy rather than copied everywhere its needed. +""" + +import dis +import re +from types import CodeType +from typing import Pattern + +from PyInstaller import compat + +# opcode name -> opcode map +# Python 3.11 introduced specialized opcodes that are not covered by opcode.opmap (and equivalent dis.opmap), but dis +# has a private map of all opcodes called _all_opmap. So use the latter, if available. +opmap = getattr(dis, '_all_opmap', dis.opmap) + + +def _instruction_to_regex(x: str): + """ + Get a regex-escaped opcode byte from its human readable name. + """ + return re.escape(bytes([opmap[x]])) + + +def bytecode_regex(pattern: bytes, flags=re.VERBOSE | re.DOTALL): + """ + A regex-powered Python bytecode matcher. + + ``bytecode_regex`` provides a very thin wrapper around :func:`re.compile`. + + * Any opcode names wrapped in backticks are substituted for their corresponding opcode bytes. + * Patterns are compiled in VERBOSE mode by default so that whitespace and comments may be used. + + This aims to mirror the output of :func:`dis.dis`, which is far more readable than looking at raw byte strings. + """ + assert isinstance(pattern, bytes) + + # Replace anything wrapped in backticks with regex-escaped opcodes. + pattern = re.sub( + rb"`(\w+)`", + lambda m: _instruction_to_regex(m[1].decode()), + pattern, + ) + return re.compile(pattern, flags=flags) + + +def finditer(pattern: Pattern, string: bytes): + """ + Call ``pattern.finditer(string)``, but remove any matches beginning on an odd byte (i.e., matches where + match.start() is not a multiple of 2). + + This should be used to avoid false positive matches where a bytecode pair's argument is mistaken for an opcode. + """ + assert isinstance(string, bytes) + string = _cleanup_bytecode_string(string) + matches = pattern.finditer(string) + while True: + for match in matches: + if match.start() % 2 == 0: + # All is good. This match starts on an OPCODE. + yield match + else: + # This match has started on an odd byte, meaning that it is a false positive and should be skipped. + # There is a very slim chance that a genuine match overlaps this one and, because re.finditer() does not + # allow overlapping matches, it would be lost. To avoid that, restart the regex scan, starting at the + # next even byte. + matches = pattern.finditer(string, match.start() + 1) + break + else: + break + + +# Opcodes involved in function calls with constant arguments. The differences between python versions are handled by +# variables below, which are then used to construct the _call_function_bytecode regex. +# NOTE1: the _OPCODES_* entries are typically used in (non-capturing) groups that match the opcode plus an arbitrary +# argument. But because the entries themselves may contain more than on opcode (with OR operator between them), they +# themselves need to be enclosed in another (non-capturing) group. E.g., "(?:(?:_OPCODES_FUNCTION_GLOBAL).)". +# NOTE2: _OPCODES_EXTENDED_ARG2 is an exception, as it is used as a list of opcodes to exclude, i.e., +# "[^_OPCODES_EXTENDED_ARG2]". Therefore, multiple opcodes are not separated by the OR operator. +if not compat.is_py311: + # Python 3.7 introduced two new function-related opcodes, LOAD_METHOD and CALL_METHOD + _OPCODES_EXTENDED_ARG = rb"`EXTENDED_ARG`" + _OPCODES_EXTENDED_ARG2 = _OPCODES_EXTENDED_ARG + _OPCODES_FUNCTION_GLOBAL = rb"`LOAD_NAME`|`LOAD_GLOBAL`|`LOAD_FAST`" + _OPCODES_FUNCTION_LOAD = rb"`LOAD_ATTR`|`LOAD_METHOD`" + _OPCODES_FUNCTION_ARGS = rb"`LOAD_CONST`" + _OPCODES_FUNCTION_CALL = rb"`CALL_FUNCTION`|`CALL_METHOD`|`CALL_FUNCTION_EX`" + + def _cleanup_bytecode_string(bytecode): + return bytecode # Nothing to do here +elif not compat.is_py312: + # Python 3.11 removed CALL_FUNCTION and CALL_METHOD, and replaced them with PRECALL + CALL instruction sequence. + # As both PRECALL and CALL have the same parameter (the argument count), we need to match only up to the PRECALL. + # The CALL_FUNCTION_EX is still present. + # From Python 3.11b1 on, there is an EXTENDED_ARG_QUICK specialization opcode present. + _OPCODES_EXTENDED_ARG = rb"`EXTENDED_ARG`|`EXTENDED_ARG_QUICK`" + _OPCODES_EXTENDED_ARG2 = rb"`EXTENDED_ARG``EXTENDED_ARG_QUICK`" # Special case; see note above the if/else block! + _OPCODES_FUNCTION_GLOBAL = rb"`LOAD_NAME`|`LOAD_GLOBAL`|`LOAD_FAST`" + _OPCODES_FUNCTION_LOAD = rb"`LOAD_ATTR`|`LOAD_METHOD`" + _OPCODES_FUNCTION_ARGS = rb"`LOAD_CONST`" + _OPCODES_FUNCTION_CALL = rb"`PRECALL`|`CALL_FUNCTION_EX`" + + # Starting with python 3.11, the bytecode is peppered with CACHE instructions (which dis module conveniently hides + # unless show_caches=True is used). Dealing with these CACHE instructions in regex rules is going to render them + # unreadable, so instead we pre-process the bytecode and filter the offending opcodes out. + _cache_instruction_filter = bytecode_regex(rb"(`CACHE`.)|(..)") + + def _cleanup_bytecode_string(bytecode): + return _cache_instruction_filter.sub(rb"\2", bytecode) +else: + # Python 3.12 merged EXTENDED_ARG_QUICK back in to EXTENDED_ARG, and LOAD_METHOD in to LOAD_ATTR + # PRECALL is no longer a valid key + _OPCODES_EXTENDED_ARG = rb"`EXTENDED_ARG`" + _OPCODES_EXTENDED_ARG2 = _OPCODES_EXTENDED_ARG + _OPCODES_FUNCTION_GLOBAL = rb"`LOAD_NAME`|`LOAD_GLOBAL`|`LOAD_FAST`" + _OPCODES_FUNCTION_LOAD = rb"`LOAD_ATTR`" + _OPCODES_FUNCTION_ARGS = rb"`LOAD_CONST`" + _OPCODES_FUNCTION_CALL = rb"`CALL`|`CALL_FUNCTION_EX`" + + # In Python 3.13, PUSH_NULL opcode is emitted after the LOAD_NAME (and after LOAD_ATTR opcode(s), if applicable). + # In python 3.11 and 3.12, it was emitted before the LOAD_NAME, and thus fell outside of our regex matching; now, + # we have to deal with it. But, instead of trying to add it to matching rules and adjusting the post-processing + # to deal with it, we opt to filter them out (at the same time as we filter out CACHE opcodes), and leave the rest + # of processing untouched. + if compat.is_py313: + _cache_instruction_filter = bytecode_regex(rb"(`CACHE`.)|(`PUSH_NULL`.)|(..)") + + def _cleanup_bytecode_string(bytecode): + return _cache_instruction_filter.sub(rb"\3", bytecode) + else: + _cache_instruction_filter = bytecode_regex(rb"(`CACHE`.)|(..)") + + def _cleanup_bytecode_string(bytecode): + return _cache_instruction_filter.sub(rb"\2", bytecode) + + +# language=PythonVerboseRegExp +_call_function_bytecode = bytecode_regex( + rb""" + # Matches `global_function('some', 'constant', 'arguments')`. + + # Load the global function. In code with >256 of names, this may require extended name references. + ( + (?:(?:""" + _OPCODES_EXTENDED_ARG + rb""").)* + (?:(?:""" + _OPCODES_FUNCTION_GLOBAL + rb""").) + ) + + # For foo.bar.whizz(), the above is the 'foo', below is the 'bar.whizz' (one opcode per name component, each + # possibly preceded by name reference extension). + ( + (?: + (?:(?:""" + _OPCODES_EXTENDED_ARG + rb""").)* + (?:""" + _OPCODES_FUNCTION_LOAD + rb"""). + )* + ) + + # Load however many arguments it takes. These (for now) must all be constants. + # Again, code with >256 constants may need extended enumeration. + ( + (?: + (?:(?:""" + _OPCODES_EXTENDED_ARG + rb""").)* + (?:""" + _OPCODES_FUNCTION_ARGS + rb"""). + )* + ) + + # Call the function. If opcode is CALL_FUNCTION_EX, the parameter are flags. For other opcodes, the parameter + # is the argument count (which may be > 256). + ( + (?:(?:""" + _OPCODES_EXTENDED_ARG + rb""").)* + (?:""" + _OPCODES_FUNCTION_CALL + rb"""). + ) +""" +) + +# language=PythonVerboseRegExp +_extended_arg_bytecode = bytecode_regex( + rb"""( + # Arbitrary number of EXTENDED_ARG pairs. + (?:(?:""" + _OPCODES_EXTENDED_ARG + rb""").)* + + # Followed by some other instruction (usually a LOAD). + [^""" + _OPCODES_EXTENDED_ARG2 + rb"""]. +)""" +) + + +def extended_arguments(extended_args: bytes): + """ + Unpack the (extended) integer used to reference names or constants. + + The input should be a bytecode snippet of the following form:: + + EXTENDED_ARG ? # Repeated 0-4 times. + LOAD_xxx ? # Any of LOAD_NAME/LOAD_CONST/LOAD_METHOD/... + + Each ? byte combined together gives the number we want. + """ + return int.from_bytes(extended_args[1::2], "big") + + +def load(raw: bytes, code: CodeType) -> str: + """ + Parse an (extended) LOAD_xxx instruction. + """ + # Get the enumeration. + index = extended_arguments(raw) + + # Work out what that enumeration was for (constant/local var/global var). + + # If the last instruction byte is a LOAD_FAST: + if raw[-2] == opmap["LOAD_FAST"]: + # Then this is a local variable. + return code.co_varnames[index] + # Or if it is a LOAD_CONST: + if raw[-2] == opmap["LOAD_CONST"]: + # Then this is a literal. + return code.co_consts[index] + # Otherwise, it is a global name. + if compat.is_py311 and raw[-2] == opmap["LOAD_GLOBAL"]: + # In python 3.11, namei>>1 is pushed on stack... + return code.co_names[index >> 1] + if compat.is_py312 and raw[-2] == opmap["LOAD_ATTR"]: + # In python 3.12, namei>>1 is pushed on stack... + return code.co_names[index >> 1] + + return code.co_names[index] + + +def loads(raw: bytes, code: CodeType) -> list: + """ + Parse multiple consecutive LOAD_xxx instructions. Or load() in a for loop. + + May be used to unpack a function's parameters or nested attributes ``(foo.bar.pop.whack)``. + """ + return [load(i, code) for i in _extended_arg_bytecode.findall(raw)] + + +def function_calls(code: CodeType) -> list: + """ + Scan a code object for all function calls on constant arguments. + """ + match: re.Match + out = [] + + for match in finditer(_call_function_bytecode, code.co_code): + function_root, methods, args, function_call = match.groups() + + # For foo(): + # `function_root` contains 'foo' and `methods` is empty. + # For foo.bar.whizz(): + # `function_root` contains 'foo' and `methods` contains the rest. + function_root = load(function_root, code) + methods = loads(methods, code) + function = ".".join([function_root] + methods) + + args = loads(args, code) + if function_call[0] == opmap['CALL_FUNCTION_EX']: + flags = extended_arguments(function_call) + if flags != 0: + # Keyword arguments present. Unhandled at the moment. + continue + # In calls with const arguments, args contains a single + # tuple with all values. + if len(args) != 1 or not isinstance(args[0], tuple): + continue + args = list(args[0]) + else: + arg_count = extended_arguments(function_call) + + if arg_count != len(args): + # This happens if there are variable or keyword arguments. Bail out in either case. + continue + + out.append((function, args)) + + return out + + +def search_recursively(search: callable, code: CodeType, _memo=None) -> dict: + """ + Apply a search function to a code object, recursing into child code objects (function definitions). + """ + if _memo is None: + _memo = {} + if code not in _memo: + _memo[code] = search(code) + for const in code.co_consts: + if isinstance(const, CodeType): + search_recursively(search, const, _memo) + return _memo + + +def recursive_function_calls(code: CodeType) -> dict: + """ + Scan a code object for function calls on constant arguments, recursing into function definitions and bodies of + comprehension loops. + """ + return search_recursively(function_calls, code) + + +def any_alias(full_name: str): + """List possible aliases of a fully qualified Python name. + + >>> list(any_alias("foo.bar.wizz")) + ['foo.bar.wizz', 'bar.wizz', 'wizz'] + + This crudely allows us to capture uses of wizz() under any of + :: + import foo + foo.bar.wizz() + :: + from foo import bar + bar.wizz() + :: + from foo.bar import wizz + wizz() + + However, it will fail for any form of aliases and quite likely find false matches. + """ + parts = full_name.split('.') + while parts: + yield ".".join(parts) + parts = parts[1:] diff --git a/venv/Lib/site-packages/PyInstaller/depend/dylib.py b/venv/Lib/site-packages/PyInstaller/depend/dylib.py new file mode 100644 index 0000000..32cbd28 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/depend/dylib.py @@ -0,0 +1,361 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- +""" +Manipulating with dynamic libraries. +""" + +import os +import pathlib +import re + +from PyInstaller import compat +import PyInstaller.log as logging + +logger = logging.getLogger(__name__) + +# Ignoring some system libraries speeds up packaging process +_excludes = { + # Ignore annoying warnings with Windows system DLLs. + # + # 'W: library kernel32.dll required via ctypes not found' + # 'W: library coredll.dll required via ctypes not found' + # + # These these dlls has to be ignored for all operating systems because they might be resolved when scanning code for + # ctypes dependencies. + r'advapi32\.dll', + r'ws2_32\.dll', + r'gdi32\.dll', + r'oleaut32\.dll', + r'shell32\.dll', + r'ole32\.dll', + r'coredll\.dll', + r'crypt32\.dll', + r'kernel32', + r'kernel32\.dll', + r'msvcrt\.dll', + r'rpcrt4\.dll', + r'user32\.dll', + # Some modules tries to import the Python library. e.g. pyreadline.console.console + r'python\%s\%s', +} + +# Regex includes - overrides excludes. Include list is used only to override specific libraries from exclude list. +_includes = set() + +_win_includes = { + # We need to allow collection of Visual Studio C++ (VC) runtime DLLs from system directories in order to avoid + # missing DLL errors when the frozen application is run on a system that does not have the corresponding VC + # runtime installed. The VC runtime DLLs may be dependencies of python shared library itself or of extension + # modules provided by 3rd party packages. + + # Visual Studio 2010 (VC10) runtime + # http://msdn.microsoft.com/en-us/library/8kche8ah(v=vs.100).aspx + r'atl100\.dll', + r'msvcr100\.dll', + r'msvcp100\.dll', + r'mfc100\.dll', + r'mfc100u\.dll', + r'mfcmifc80\.dll', + r'mfcm100\.dll', + r'mfcm100u\.dll', + + # Visual Studio 2012 (VC11) runtime + # https://docs.microsoft.com/en-us/visualstudio/releases/2013/2012-redistribution-vs + # + # VC110.ATL + r'atl110\.dll', + # VC110.CRT + r'msvcp110\.dll', + r'msvcr110\.dll', + r'vccorlib110\.dll', + # VC110.CXXAMP + r'vcamp110\.dll', + # VC110.MFC + r'mfc110\.dll', + r'mfc110u\.dll', + r'mfcm110\.dll', + r'mfcm110u\.dll', + # VC110.MFCLOC + r'mfc110chs\.dll', + r'mfc110cht\.dll', + r'mfc110enu\.dll', + r'mfc110esn\.dll', + r'mfc110deu\.dll', + r'mfc110fra\.dll', + r'mfc110ita\.dll', + r'mfc110jpn\.dll', + r'mfc110kor\.dll', + r'mfc110rus\.dll', + # VC110.OpenMP + r'vcomp110\.dll', + # DIA SDK + r'msdia110\.dll', + + # Visual Studio 2013 (VC12) runtime + # https://docs.microsoft.com/en-us/visualstudio/releases/2013/2013-redistribution-vs + # + # VC120.CRT + r'msvcp120\.dll', + r'msvcr120\.dll', + r'vccorlib120\.dll', + # VC120.CXXAMP + r'vcamp120\.dll', + # VC120.MFC + r'mfc120\.dll', + r'mfc120u\.dll', + r'mfcm120\.dll', + r'mfcm120u\.dll', + # VC120.MFCLOC + r'mfc120chs\.dll', + r'mfc120cht\.dll', + r'mfc120deu\.dll', + r'mfc120enu\.dll', + r'mfc120esn\.dll', + r'mfc120fra\.dll', + r'mfc120ita\.dll', + r'mfc120jpn\.dll', + r'mfc120kor\.dll', + r'mfc120rus\.dll', + # VC120.OPENMP + r'vcomp120\.dll', + # DIA SDK + r'msdia120\.dll', + # Cpp REST Windows SDK + r'casablanca120.winrt\.dll', + # Mobile Services Cpp Client + r'zumosdk120.winrt\.dll', + # Cpp REST SDK + r'casablanca120\.dll', + + # Universal C Runtime Library (since Visual Studio 2015) + # + # NOTE: these should be put under a switch, as they need not to be bundled if deployment target is Windows 10 + # and later, as "UCRT is now a system component in Windows 10 and later, managed by Windows Update". + # (https://docs.microsoft.com/en-us/cpp/windows/determining-which-dlls-to-redistribute?view=msvc-170) + # And as discovered in #6326, Windows prefers system-installed version over the bundled one, anyway + # (see https://docs.microsoft.com/en-us/cpp/windows/universal-crt-deployment?view=msvc-170#local-deployment). + r'api-ms-win-core.*', + r'api-ms-win-crt.*', + r'ucrtbase\.dll', + + # Visual Studio 2015/2017/2019/2022 (VC14) runtime + # https://docs.microsoft.com/en-us/visualstudio/releases/2022/redistribution + # + # VC141.CRT/VC142.CRT/VC143.CRT + r'concrt140\.dll', + r'msvcp140\.dll', + r'msvcp140_1\.dll', + r'msvcp140_2\.dll', + r'msvcp140_atomic_wait\.dll', + r'msvcp140_codecvt_ids\.dll', + r'vccorlib140\.dll', + r'vcruntime140\.dll', + r'vcruntime140_1\.dll', + # VC141.CXXAMP/VC142.CXXAMP/VC143.CXXAMP + r'vcamp140\.dll', + # VC141.OpenMP/VC142.OpenMP/VC143.OpenMP + r'vcomp140\.dll', + # DIA SDK + r'msdia140\.dll', + + # Allow pythonNN.dll, pythoncomNN.dll, pywintypesNN.dll + r'py(?:thon(?:com(?:loader)?)?|wintypes)\d+\.dll', +} + +_win_excludes = { + # On Windows, only .dll files can be loaded. + r'.*\.so', + r'.*\.dylib', + + # MS assembly excludes + r'Microsoft\.Windows\.Common-Controls', +} + +_unix_excludes = { + r'libc\.so(\..*)?', + r'libdl\.so(\..*)?', + r'libm\.so(\..*)?', + r'libpthread\.so(\..*)?', + r'librt\.so(\..*)?', + r'libthread_db\.so(\..*)?', + # glibc regex excludes. + r'ld-linux\.so(\..*)?', + r'libBrokenLocale\.so(\..*)?', + r'libanl\.so(\..*)?', + r'libcidn\.so(\..*)?', + r'libcrypt\.so(\..*)?', + r'libnsl\.so(\..*)?', + r'libnss_compat.*\.so(\..*)?', + r'libnss_dns.*\.so(\..*)?', + r'libnss_files.*\.so(\..*)?', + r'libnss_hesiod.*\.so(\..*)?', + r'libnss_nis.*\.so(\..*)?', + r'libnss_nisplus.*\.so(\..*)?', + r'libresolv\.so(\..*)?', + r'libutil\.so(\..*)?', + # graphical interface libraries come with graphical stack (see libglvnd) + r'libE?(Open)?GLX?(ESv1_CM|ESv2)?(dispatch)?\.so(\..*)?', + r'libdrm\.so(\..*)?', + # a subset of libraries included as part of the Nvidia Linux Graphics Driver as of 520.56.06: + # https://download.nvidia.com/XFree86/Linux-x86_64/520.56.06/README/installedcomponents.html + r'nvidia_drv\.so', + r'libglxserver_nvidia\.so(\..*)?', + r'libnvidia-egl-(gbm|wayland)\.so(\..*)?', + r'libnvidia-(cfg|compiler|e?glcore|glsi|glvkspirv|rtcore|allocator|tls|ml)\.so(\..*)?', + r'lib(EGL|GLX)_nvidia\.so(\..*)?', + # libcuda.so, libcuda.so.1, and libcuda.so.{version} are run-time part of NVIDIA driver, and should not be + # collected, as they need to match the rest of driver components on the target system. + r'libcuda\.so(\..*)?', + r'libcudadebugger\.so(\..*)?', + # libxcb-dri changes ABI frequently (e.g.: between Ubuntu LTS releases) and is usually installed as dependency of + # the graphics stack anyway. No need to bundle it. + r'libxcb\.so(\..*)?', + r'libxcb-dri.*\.so(\..*)?', +} + +_aix_excludes = { + r'libbz2\.a', + r'libc\.a', + r'libC\.a', + r'libcrypt\.a', + r'libdl\.a', + r'libintl\.a', + r'libpthreads\.a', + r'librt\\.a', + r'librtl\.a', + r'libz\.a', +} + +if compat.is_win: + _includes |= _win_includes + _excludes |= _win_excludes +elif compat.is_aix: + # The exclude list for AIX differs from other *nix platforms. + _excludes |= _aix_excludes +elif compat.is_unix: + # Common excludes for *nix platforms -- except AIX. + _excludes |= _unix_excludes + + +class MatchList: + def __init__(self, entries): + self._regex = re.compile('|'.join(entries), re.I) if entries else None + + def check_library(self, libname): + if self._regex: + return self._regex.match(os.path.basename(libname)) + return False + + +if compat.is_darwin: + import macholib.util + + class MacExcludeList(MatchList): + def __init__(self, entries): + super().__init__(entries) + + def check_library(self, libname): + # Try the global exclude list. + result = super().check_library(libname) + if result: + return result + + # Exclude libraries in standard system locations. + return macholib.util.in_system_path(libname) + + exclude_list = MacExcludeList(_excludes) + include_list = MatchList(_includes) + +elif compat.is_win: + from PyInstaller.utils.win32 import winutils + + class WinExcludeList(MatchList): + def __init__(self, entries): + super().__init__(entries) + + self._windows_dir = pathlib.Path(winutils.get_windows_dir()).resolve() + + # When running as SYSTEM user, the home directory is `%WINDIR%\system32\config\systemprofile`. + self._home_dir = pathlib.Path.home().resolve() + self._system_home = self._windows_dir in self._home_dir.parents + + def check_library(self, libname): + # Try the global exclude list. The global exclude list contains lower-cased names, so lower-case the input + # for case-normalized comparison. + result = super().check_library(libname.lower()) + if result: + return result + + # Exclude everything from the Windows directory by default; but allow contents of user's gome directory if + # that happens to be rooted under Windows directory (e.g., when running PyInstaller as SYSTEM user). + lib_fullpath = pathlib.Path(libname).resolve() + exclude = self._windows_dir in lib_fullpath.parents + if exclude and self._system_home and self._home_dir in lib_fullpath.parents: + exclude = False + return exclude + + exclude_list = WinExcludeList(_excludes) + include_list = MatchList(_includes) +else: + exclude_list = MatchList(_excludes) + include_list = MatchList(_includes) + +_seen_wine_dlls = set() # Used for warning tracking in include_library() + + +def include_library(libname): + """ + Check if the dynamic library should be included with application or not. + """ + if exclude_list.check_library(libname) and not include_list.check_library(libname): + # Library is excluded and is not overridden by include list. It should be excluded. + return False + + # If we are running under Wine and the library is a Wine built-in DLL, ensure that it is always excluded. Typically, + # excluding a DLL leads to an incomplete bundle and run-time errors when the said DLL is not installed on the target + # system. However, having Wine built-in DLLs collected is even more detrimental, as they usually provide Wine's + # implementation of low-level functionality, and therefore cannot be used on actual Windows (i.e., system libraries + # from the C:\Windows\system32 directory that might end up collected due to ``_win_includes`` list; a prominent + # example are VC runtime DLLs, for which Wine provides their own implementation, unless user explicitly installs + # Microsoft's VC redistributable package in their Wine environment). Therefore, excluding the Wine built-in DLLs + # actually improves the chances of the bundle running on Windows, or at least makes the issue easier to debug by + # turning it into the "standard" missing DLL problem. Exclusion should not affect the bundle's ability to run under + # Wine itself, as the excluded DLLs are available there. + if compat.is_win_wine and compat.is_wine_dll(libname): + # Display warning message only once per DLL. Note that it is also displayed only if the DLL were to be included + # in the first place. + if libname not in _seen_wine_dlls: + logger.warning("Excluding Wine built-in DLL: %s", libname) + _seen_wine_dlls.add(libname) + return False + + return True + + +# Patterns for suppressing warnings about missing dynamically linked libraries +_warning_suppressions = [] + +# On some systems (e.g., openwrt), libc.so might point to ldd. Suppress warnings about it. +if compat.is_linux: + _warning_suppressions.append(r'ldd') + +# Suppress warnings about unresolvable UCRT DLLs (see issue #1566) on Windows 10 and 11. +if compat.is_win_10 or compat.is_win_11: + _warning_suppressions.append(r'api-ms-win-.*\.dll') + +missing_lib_warning_suppression_list = MatchList(_warning_suppressions) + + +def warn_missing_lib(libname): + """ + Check if a missing-library warning should be displayed for the given library name (or full path). + """ + return not missing_lib_warning_suppression_list.check_library(libname) diff --git a/venv/Lib/site-packages/PyInstaller/depend/imphook.py b/venv/Lib/site-packages/PyInstaller/depend/imphook.py new file mode 100644 index 0000000..b4f184a --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/depend/imphook.py @@ -0,0 +1,582 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- +""" +Code related to processing of import hooks. +""" + +import glob +import os.path +import sys +import weakref +import re + +from PyInstaller import log as logging +from PyInstaller.building.utils import format_binaries_and_datas +from PyInstaller.compat import importlib_load_source +from PyInstaller.depend.imphookapi import PostGraphAPI +from PyInstaller.exceptions import ImportErrorWhenRunningHook + +logger = logging.getLogger(__name__) + + +class ModuleHookCache(dict): + """ + Cache of lazily loadable hook script objects. + + This cache is implemented as a `dict` subclass mapping from the fully-qualified names of all modules with at + least one hook script to lists of `ModuleHook` instances encapsulating these scripts. As a `dict` subclass, + all cached module names and hook scripts are accessible via standard dictionary operations. + + Attributes + ---------- + module_graph : ModuleGraph + Current module graph. + _hook_module_name_prefix : str + String prefixing the names of all in-memory modules lazily loaded from cached hook scripts. See also the + `hook_module_name_prefix` parameter passed to the `ModuleHook.__init__()` method. + """ + + _cache_id_next = 0 + """ + 0-based identifier unique to the next `ModuleHookCache` to be instantiated. + + This identifier is incremented on each instantiation of a new `ModuleHookCache` to isolate in-memory modules of + lazily loaded hook scripts in that cache to the same cache-specific namespace, preventing edge-case collisions + with existing in-memory modules in other caches. + + """ + def __init__(self, module_graph, hook_dirs): + """ + Cache all hook scripts in the passed directories. + + **Order of caching is significant** with respect to hooks for the same module, as the values of this + dictionary are lists. Hooks for the same module will be run in the order in which they are cached. Previously + cached hooks are always preserved rather than overridden. + + By default, official hooks are cached _before_ user-defined hooks. For modules with both official and + user-defined hooks, this implies that the former take priority over and hence will be loaded _before_ the + latter. + + Parameters + ---------- + module_graph : ModuleGraph + Current module graph. + hook_dirs : list + List of the absolute or relative paths of all directories containing **hook scripts** (i.e., + Python scripts with filenames matching `hook-{module_name}.py`, where `{module_name}` is the module + hooked by that script) to be cached. + """ + super().__init__() + + # To avoid circular references and hence increased memory consumption, a weak rather than strong reference is + # stored to the passed graph. Since this graph is guaranteed to live longer than this cache, + # this is guaranteed to be safe. + self.module_graph = weakref.proxy(module_graph) + + # String unique to this cache prefixing the names of all in-memory modules lazily loaded from cached hook + # scripts, privatized for safety. + self._hook_module_name_prefix = '__PyInstaller_hooks_{}_'.format(ModuleHookCache._cache_id_next) + ModuleHookCache._cache_id_next += 1 + + # Cache all hook scripts in the passed directories. + self._cache_hook_dirs(hook_dirs) + + def _cache_hook_dirs(self, hook_dirs): + """ + Cache all hook scripts in the passed directories. + + Parameters + ---------- + hook_dirs : list + List of the absolute or relative paths of all directories containing hook scripts to be cached. + """ + + for hook_dir, default_priority in hook_dirs: + # Canonicalize this directory's path and validate its existence. + hook_dir = os.path.abspath(hook_dir) + if not os.path.isdir(hook_dir): + raise FileNotFoundError('Hook directory "{}" not found.'.format(hook_dir)) + + # For each hook script in this directory... + hook_filenames = glob.glob(os.path.join(hook_dir, 'hook-*.py')) + for hook_filename in hook_filenames: + # Fully-qualified name of this hook's corresponding module, constructed by removing the "hook-" prefix + # and ".py" suffix. + module_name = os.path.basename(hook_filename)[5:-3] + + # Lazily loadable hook object. + module_hook = ModuleHook( + module_graph=self.module_graph, + module_name=module_name, + hook_filename=hook_filename, + hook_module_name_prefix=self._hook_module_name_prefix, + default_priority=default_priority, + ) + + # Add this hook to this module's list of hooks. + module_hooks = self.setdefault(module_name, []) + module_hooks.append(module_hook) + + # Post-processing: we allow only one instance of hook per module. Currently, the priority order is defined + # implicitly, via order of hook directories, so the first hook in the list has the highest priority. + for module_name in self.keys(): + hooks = self[module_name] + if len(hooks) == 1: + self[module_name] = hooks[0] + else: + # Order by priority value, in descending order. + sorted_hooks = sorted(hooks, key=lambda hook: hook.priority, reverse=True) + self[module_name] = sorted_hooks[0] + + def remove_modules(self, *module_names): + """ + Remove the passed modules and all hook scripts cached for these modules from this cache. + + Parameters + ---------- + module_names : list + List of all fully-qualified module names to be removed. + """ + + for module_name in module_names: + # Unload this module's hook script modules from memory. Since these are top-level pure-Python modules cached + # only in the "sys.modules" dictionary, popping these modules from this dictionary suffices to garbage + # collect them. + module_hook = self.pop(module_name, None) # Remove our reference, if available. + if module_hook is not None: + sys.modules.pop(module_hook.hook_module_name, None) + + +def _module_collection_mode_sanitizer(value): + if isinstance(value, dict): + # Hook set a dictionary; use it as-is + return value + elif isinstance(value, str): + # Hook set a mode string; convert to a dictionary and assign the string to `None` (= the hooked module). + return {None: value} + + raise ValueError(f"Invalid module collection mode setting value: {value!r}") + + +def _bindepend_symlink_suppression_sanitizer(value): + if isinstance(value, (list, set)): + # Hook set a list or a set; use it as-is + return set(value) + elif isinstance(value, str): + # Hook set a string; create a set with single element. + return set([value]) + + raise ValueError(f"Invalid value for bindepend_symlink_suppression: {value!r}") + + +# Dictionary mapping the names of magic attributes required by the "ModuleHook" class to 2-tuples "(default_type, +# sanitizer_func)", where: +# +# * "default_type" is the type to which that attribute will be initialized when that hook is lazily loaded. +# * "sanitizer_func" is the callable sanitizing the original value of that attribute defined by that hook into a +# safer value consumable by "ModuleHook" callers if any or "None" if the original value requires no sanitization. +# +# To avoid subtleties in the ModuleHook.__getattr__() method, this dictionary is declared as a module rather than a +# class attribute. If declared as a class attribute and then undefined (...for whatever reason), attempting to access +# this attribute from that method would produce infinite recursion. +_MAGIC_MODULE_HOOK_ATTRS = { + # Collections in which order is insignificant. This includes: + # + # * "datas", sanitized from hook-style 2-tuple lists defined by hooks into TOC-style 2-tuple sets consumable by + # "ModuleHook" callers. + # * "binaries", sanitized in the same way. + 'datas': (set, format_binaries_and_datas), + 'binaries': (set, format_binaries_and_datas), + 'excludedimports': (set, None), + + # Collections in which order is significant. This includes: + # + # * "hiddenimports", as order of importation is significant. On module importation, hook scripts are loaded and hook + # functions declared by these scripts are called. As these scripts and functions can have side effects dependent + # on module importation order, module importation itself can have side effects dependent on this order! + 'hiddenimports': (list, None), + + # Flags + 'warn_on_missing_hiddenimports': (lambda: True, bool), + + # Package/module collection mode dictionary. + 'module_collection_mode': (dict, _module_collection_mode_sanitizer), + + # Path patterns for suppression of symbolic links created by binary dependency analysis. + 'bindepend_symlink_suppression': (set, _bindepend_symlink_suppression_sanitizer), +} + + +class ModuleHook: + """ + Cached object encapsulating a lazy loadable hook script. + + This object exposes public attributes (e.g., `datas`) of the underlying hook script as attributes of the same + name of this object. On the first access of any such attribute, this hook script is lazily loaded into an + in-memory private module reused on subsequent accesses. These dynamic attributes are referred to as "magic." All + other static attributes of this object (e.g., `hook_module_name`) are referred to as "non-magic." + + Attributes (Magic) + ---------- + datas : set + Set of `TOC`-style 2-tuples `(target_file, source_file)` for all external non-executable files required by + the module being hooked, converted from the `datas` list of hook-style 2-tuples `(source_dir_or_glob, + target_dir)` defined by this hook script. + binaries : set + Set of `TOC`-style 2-tuples `(target_file, source_file)` for all external executable files required by the + module being hooked, converted from the `binaries` list of hook-style 2-tuples `(source_dir_or_glob, + target_dir)` defined by this hook script. + excludedimports : set + Set of the fully-qualified names of all modules imported by the module being hooked to be ignored rather than + imported from that module, converted from the `excludedimports` list defined by this hook script. These + modules will only be "locally" rather than "globally" ignored. These modules will remain importable from all + modules other than the module being hooked. + hiddenimports : set + Set of the fully-qualified names of all modules imported by the module being hooked that are _not_ + automatically detectable by PyInstaller (usually due to being dynamically imported in that module), + converted from the `hiddenimports` list defined by this hook script. + warn_on_missing_hiddenimports : bool + Boolean flag indicating whether missing hidden imports from the hook should generate warnings or not. This + behavior is enabled by default, but individual hooks can opt out of it. + module_collection_mode : dict + A dictionary of package/module names and their corresponding collection mode strings ('pyz', 'pyc', 'py', + 'pyz+py', 'py+pyz'). + bindepend_symlink_suppression : set + A set of paths or path patterns corresponding to shared libraries for which binary dependency analysis should + not create symbolic links into top-level application directory. + + Attributes (Non-magic) + ---------- + module_graph : ModuleGraph + Current module graph. + module_name : str + Name of the module hooked by this hook script. + hook_filename : str + Absolute or relative path of this hook script. + hook_module_name : str + Name of the in-memory module of this hook script's interpreted contents. + _hook_module : module + In-memory module of this hook script's interpreted contents, lazily loaded on the first call to the + `_load_hook_module()` method _or_ `None` if this method has yet to be accessed. + _default_priority : int + Default (location-based) priority for this hook. + priority : int + Actual priority for this hook. Might be different from `_default_priority` if hook file specifies the hook + priority override. + """ + + #-- Magic -- + + def __init__(self, module_graph, module_name, hook_filename, hook_module_name_prefix, default_priority): + """ + Initialize this metadata. + + Parameters + ---------- + module_graph : ModuleGraph + Current module graph. + module_name : str + Name of the module hooked by this hook script. + hook_filename : str + Absolute or relative path of this hook script. + hook_module_name_prefix : str + String prefixing the name of the in-memory module for this hook script. To avoid namespace clashes with + similar modules created by other `ModuleHook` objects in other `ModuleHookCache` containers, this string + _must_ be unique to the `ModuleHookCache` container containing this `ModuleHook` object. If this string + is non-unique, an existing in-memory module will be erroneously reused when lazily loading this hook + script, thus erroneously resanitizing previously sanitized hook script attributes (e.g., `datas`) with + the `format_binaries_and_datas()` helper. + default_priority : int + Default, location-based priority for this hook. Used to select active hook when multiple hooks are defined + for the same module. + """ + # Note that the passed module graph is already a weak reference, avoiding circular reference issues. See + # ModuleHookCache.__init__(). TODO: Add a failure message + assert isinstance(module_graph, weakref.ProxyTypes) + self.module_graph = module_graph + self.module_name = module_name + self.hook_filename = hook_filename + + # Default priority; used as fall-back for dynamic `hook_priority` attribute. + self._default_priority = default_priority + + # Name of the in-memory module fabricated to refer to this hook script. + self.hook_module_name = hook_module_name_prefix + self.module_name.replace('.', '_') + + # Attributes subsequently defined by the _load_hook_module() method. + self._loaded = False + self._has_hook_function = False + self._hook_module = None + + def __getattr__(self, attr_name): + """ + Get the magic attribute with the passed name (e.g., `datas`) from this lazily loaded hook script if any _or_ + raise `AttributeError` otherwise. + + This special method is called only for attributes _not_ already defined by this object. This includes + undefined attributes and the first attempt to access magic attributes. + + This special method is _not_ called for subsequent attempts to access magic attributes. The first attempt to + access magic attributes defines corresponding instance variables accessible via the `self.__dict__` instance + dictionary (e.g., as `self.datas`) without calling this method. This approach also allows magic attributes to + be deleted from this object _without_ defining the `__delattr__()` special method. + + See Also + ---------- + Class docstring for supported magic attributes. + """ + + if attr_name == 'priority': + # If attribute is part of hook metadata, read metadata from hook script and return the attribute value. + self._load_hook_metadata() + return getattr(self, attr_name) + if attr_name in _MAGIC_MODULE_HOOK_ATTRS and not self._loaded: + # If attribute is hook's magic attribute, load and run the hook script, and return the attribute value. + self._load_hook_module() + return getattr(self, attr_name) + else: + # This is an undefined attribute. Raise an exception. + raise AttributeError(attr_name) + + def __setattr__(self, attr_name, attr_value): + """ + Set the attribute with the passed name to the passed value. + + If this is a magic attribute, this hook script will be lazily loaded before setting this attribute. Unlike + `__getattr__()`, this special method is called to set _any_ attribute -- including magic, non-magic, + and undefined attributes. + + See Also + ---------- + Class docstring for supported magic attributes. + """ + + # If this is a magic attribute, initialize this attribute by lazy loading this hook script before overwriting + # this attribute. + if attr_name in _MAGIC_MODULE_HOOK_ATTRS: + self._load_hook_module() + + # Set this attribute to the passed value. To avoid recursion, the superclass method rather than setattr() is + # called. + return super().__setattr__(attr_name, attr_value) + + #-- Loading -- + + def _load_hook_metadata(self): + """ + Load hook metadata from its source file. + """ + self.priority = self._default_priority + + # Priority override pattern: `# $PyInstaller-Hook-Priority: ` + priority_pattern = re.compile(r"^\s*#\s*\$PyInstaller-Hook-Priority:\s*(?P[\S]+)") + + with open(self.hook_filename, "r", encoding="utf-8") as f: + for line in f: + # Attempt to match and parse hook priority directive + m = priority_pattern.match(line) + if m is not None: + try: + self.priority = int(m.group('value')) + except Exception: + logger.warning( + "Failed to parse hook priority value string: %r!", m.group('value'), exc_info=True + ) + # Currently, this is our only line of interest, so we can stop the search here. + return + + def _load_hook_module(self, keep_module_ref=False): + """ + Lazily load this hook script into an in-memory private module. + + This method (and, indeed, this class) preserves all attributes and functions defined by this hook script as + is, ensuring sane behaviour in hook functions _not_ expecting unplanned external modification. Instead, + this method copies public attributes defined by this hook script (e.g., `binaries`) into private attributes + of this object, which the special `__getattr__()` and `__setattr__()` methods safely expose to external + callers. For public attributes _not_ defined by this hook script, the corresponding private attributes will + be assigned sane defaults. For some public attributes defined by this hook script, the corresponding private + attributes will be transformed into objects more readily and safely consumed elsewhere by external callers. + + See Also + ---------- + Class docstring for supported attributes. + """ + + # If this hook script module has already been loaded, noop. + if self._loaded and (self._hook_module is not None or not keep_module_ref): + return + + # Load and execute the hook script. Even if mechanisms from the import machinery are used, this does not import + # the hook as the module. + hook_path, hook_basename = os.path.split(self.hook_filename) + logger.info('Processing standard module hook %r from %r', hook_basename, hook_path) + try: + self._hook_module = importlib_load_source(self.hook_module_name, self.hook_filename) + except ImportError: + logger.debug("Hook failed with:", exc_info=True) + raise ImportErrorWhenRunningHook(self.hook_module_name, self.hook_filename) + + # Mark as loaded + self._loaded = True + + # Check if module has hook() function. + self._has_hook_function = hasattr(self._hook_module, 'hook') + + # Copy hook script attributes into magic attributes exposed as instance variables of the current "ModuleHook" + # instance. + for attr_name, (default_type, sanitizer_func) in _MAGIC_MODULE_HOOK_ATTRS.items(): + # Unsanitized value of this attribute. + attr_value = getattr(self._hook_module, attr_name, None) + + # If this attribute is undefined, expose a sane default instead. + if attr_value is None: + attr_value = default_type() + # Else if this attribute requires sanitization, do so. + elif sanitizer_func is not None: + attr_value = sanitizer_func(attr_value) + # Else, expose the unsanitized value of this attribute. + + # Expose this attribute as an instance variable of the same name. + setattr(self, attr_name, attr_value) + + # If module_collection_mode has an entry with None key, reassign it to the hooked module's name. + setattr( + self, 'module_collection_mode', { + key if key is not None else self.module_name: value + for key, value in getattr(self, 'module_collection_mode').items() + } + ) + + # Release the module if we do not need the reference. This is the case when hook is loaded during the analysis + # rather as part of the post-graph operations. + if not keep_module_ref: + self._hook_module = None + + #-- Hooks -- + + def post_graph(self, analysis): + """ + Call the **post-graph hook** (i.e., `hook()` function) defined by this hook script, if any. + + Parameters + ---------- + analysis: build_main.Analysis + Analysis that calls the hook + + This method is intended to be called _after_ the module graph for this application is constructed. + """ + + # Lazily load this hook script into an in-memory module. + # The script might have been loaded before during modulegraph analysis; in that case, it needs to be reloaded + # only if it provides a hook() function. + if not self._loaded or self._has_hook_function: + # Keep module reference when loading the hook, so we can call its hook function! + self._load_hook_module(keep_module_ref=True) + + # Call this hook script's hook() function, which modifies attributes accessed by subsequent methods and + # hence must be called first. + self._process_hook_func(analysis) + + # Order is insignificant here. + self._process_hidden_imports() + + def _process_hook_func(self, analysis): + """ + Call this hook's `hook()` function if defined. + + Parameters + ---------- + analysis: build_main.Analysis + Analysis that calls the hook + """ + + # If this hook script defines no hook() function, noop. + if not hasattr(self._hook_module, 'hook'): + return + + # Call this hook() function. + hook_api = PostGraphAPI(module_name=self.module_name, module_graph=self.module_graph, analysis=analysis) + try: + self._hook_module.hook(hook_api) + except ImportError: + logger.debug("Hook failed with:", exc_info=True) + raise ImportErrorWhenRunningHook(self.hook_module_name, self.hook_filename) + + # Update all magic attributes modified by the prior call. + self.datas.update(set(hook_api._added_datas)) + self.binaries.update(set(hook_api._added_binaries)) + self.hiddenimports.extend(hook_api._added_imports) + self.module_collection_mode.update(hook_api._module_collection_mode) + self.bindepend_symlink_suppression.update(hook_api._bindepend_symlink_suppression) + + # FIXME: `hook_api._deleted_imports` should be appended to `self.excludedimports` and used to suppress module + # import during the modulegraph construction rather than handled here. However, for that to work, the `hook()` + # function needs to be ran during modulegraph construction instead of in post-processing (and this in turn + # requires additional code refactoring in order to be able to pass `analysis` to `PostGraphAPI` object at + # that point). So once the modulegraph rewrite is complete, remove the code block below. + for deleted_module_name in hook_api._deleted_imports: + # Remove the graph link between the hooked module and item. This removes the 'item' node from the graph if + # no other links go to it (no other modules import it) + self.module_graph.removeReference(hook_api.node, deleted_module_name) + + def _process_hidden_imports(self): + """ + Add all imports listed in this hook script's `hiddenimports` attribute to the module graph as if directly + imported by this hooked module. + + These imports are typically _not_ implicitly detectable by PyInstaller and hence must be explicitly defined + by hook scripts. + """ + + # For each hidden import required by the module being hooked... + for import_module_name in self.hiddenimports: + try: + # Graph node for this module. Do not implicitly create namespace packages for non-existent packages. + caller = self.module_graph.find_node(self.module_name, create_nspkg=False) + + # Manually import this hidden import from this module. + self.module_graph.import_hook(import_module_name, caller) + # If this hidden import is unimportable, print a non-fatal warning. Hidden imports often become + # desynchronized from upstream packages and hence are only "soft" recommendations. + except ImportError: + if self.warn_on_missing_hiddenimports: + logger.warning('Hidden import "%s" not found!', import_module_name) + + +class AdditionalFilesCache: + """ + Cache for storing what binaries and datas were pushed by what modules when import hooks were processed. + """ + def __init__(self): + self._binaries = {} + self._datas = {} + + def add(self, modname, binaries, datas): + + self._binaries.setdefault(modname, []) + self._binaries[modname].extend(binaries or []) + self._datas.setdefault(modname, []) + self._datas[modname].extend(datas or []) + + def __contains__(self, name): + return name in self._binaries or name in self._datas + + def binaries(self, modname): + """ + Return list of binaries for given module name. + """ + return self._binaries.get(modname, []) + + def datas(self, modname): + """ + Return list of datas for given module name. + """ + return self._datas.get(modname, []) diff --git a/venv/Lib/site-packages/PyInstaller/depend/imphookapi.py b/venv/Lib/site-packages/PyInstaller/depend/imphookapi.py new file mode 100644 index 0000000..c51830b --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/depend/imphookapi.py @@ -0,0 +1,486 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- +""" +Classes facilitating communication between PyInstaller and import hooks. + +PyInstaller passes instances of classes defined by this module to corresponding functions defined by external import +hooks, which commonly modify the contents of these instances before returning. PyInstaller then detects and converts +these modifications into appropriate operations on the current `PyiModuleGraph` instance, thus modifying which +modules will be frozen into the executable. +""" + +from PyInstaller.building.utils import format_binaries_and_datas +from PyInstaller.lib.modulegraph.modulegraph import (RuntimeModule, RuntimePackage) + + +class PreSafeImportModuleAPI: + """ + Metadata communicating changes made by the current **pre-safe import module hook** (i.e., hook run immediately + _before_ a call to `ModuleGraph._safe_import_module()` recursively adding the hooked module, package, + or C extension and all transitive imports thereof to the module graph) back to PyInstaller. + + Pre-safe import module hooks _must_ define a `pre_safe_import_module()` function accepting an instance of this + class, whose attributes describe the subsequent `ModuleGraph._safe_import_module()` call creating the hooked + module's graph node. + + Each pre-safe import module hook is run _only_ on the first attempt to create the hooked module's graph node and + then subsequently ignored. If this hook successfully creates that graph node, the subsequent + `ModuleGraph._safe_import_module()` call will observe this fact and silently return without attempting to + recreate that graph node. + + Pre-safe import module hooks are typically used to create graph nodes for **runtime modules** (i.e., + modules dynamically defined at runtime). Most modules are physically defined in external `.py`-suffixed scripts. + Some modules, however, are dynamically defined at runtime (e.g., `six.moves`, dynamically defined by the + physically defined `six.py` module). However, `ModuleGraph` only parses `import` statements residing in external + scripts. `ModuleGraph` is _not_ a full-fledged, Turing-complete Python interpreter and hence has no means of + parsing `import` statements performed by runtime modules existing only in-memory. + + 'With great power comes great responsibility.' + + + Attributes (Immutable) + ---------------------------- + The following attributes are **immutable** (i.e., read-only). For safety, any attempts to change these attributes + _will_ result in a raised exception: + + module_graph : PyiModuleGraph + Current module graph. + parent_package : Package + Graph node for the package providing this module _or_ `None` if this module is a top-level module. + + Attributes (Mutable) + ----------------------------- + The following attributes are editable. + + module_basename : str + Unqualified name of the module to be imported (e.g., `text`). + module_name : str + Fully-qualified name of this module (e.g., `email.mime.text`). + """ + def __init__(self, module_graph, module_basename, module_name, parent_package): + self._module_graph = module_graph + self.module_basename = module_basename + self.module_name = module_name + self._parent_package = parent_package + + # Immutable properties. No corresponding setters are defined. + @property + def module_graph(self): + """ + Current module graph. + """ + return self._module_graph + + @property + def parent_package(self): + """ + Parent Package of this node. + """ + return self._parent_package + + def add_runtime_module(self, module_name): + """ + Add a graph node representing a non-package Python module with the passed name dynamically defined at runtime. + + Most modules are statically defined on-disk as standard Python files. Some modules, however, are dynamically + defined in-memory at runtime (e.g., `gi.repository.Gst`, dynamically defined by the statically defined + `gi.repository.__init__` module). + + This method adds a graph node representing such a runtime module. Since this module is _not_ a package, + all attempts to import submodules from this module in `from`-style import statements (e.g., the `queue` + submodule in `from six.moves import queue`) will be silently ignored. To circumvent this, simply call + `add_runtime_package()` instead. + + Parameters + ---------- + module_name : str + Fully-qualified name of this module (e.g., `gi.repository.Gst`). + + Examples + ---------- + This method is typically called by `pre_safe_import_module()` hooks, e.g.: + + def pre_safe_import_module(api): + api.add_runtime_module(api.module_name) + """ + + self._module_graph.add_module(RuntimeModule(module_name)) + + def add_runtime_package(self, package_name): + """ + Add a graph node representing a non-namespace Python package with the passed name dynamically defined at + runtime. + + Most packages are statically defined on-disk as standard subdirectories containing `__init__.py` files. Some + packages, however, are dynamically defined in-memory at runtime (e.g., `six.moves`, dynamically defined by + the statically defined `six` module). + + This method adds a graph node representing such a runtime package. All attributes imported from this package + in `from`-style import statements that are submodules of this package (e.g., the `queue` submodule in `from + six.moves import queue`) will be imported rather than ignored. + + Parameters + ---------- + package_name : str + Fully-qualified name of this package (e.g., `six.moves`). + + Examples + ---------- + This method is typically called by `pre_safe_import_module()` hooks, e.g.: + + def pre_safe_import_module(api): + api.add_runtime_package(api.module_name) + """ + + self._module_graph.add_module(RuntimePackage(package_name)) + + def add_alias_module(self, real_module_name, alias_module_name): + """ + Alias the source module to the target module with the passed names. + + This method ensures that the next call to findNode() given the target module name will resolve this alias. + This includes importing and adding a graph node for the source module if needed as well as adding a reference + from the target to the source module. + + Parameters + ---------- + real_module_name : str + Fully-qualified name of the **existing module** (i.e., the module being aliased). + alias_module_name : str + Fully-qualified name of the **non-existent module** (i.e., the alias to be created). + """ + + self._module_graph.alias_module(real_module_name, alias_module_name) + + def append_package_path(self, directory): + """ + Modulegraph does a good job at simulating Python's, but it cannot handle packagepath `__path__` modifications + packages make at runtime. + + Therefore there is a mechanism whereby you can register extra paths in this map for a package, and it will be + honored. + + Parameters + ---------- + directory : str + Absolute or relative path of the directory to be appended to this package's `__path__` attribute. + """ + + self._module_graph.append_package_path(self.module_name, directory) + + +class PreFindModulePathAPI: + """ + Metadata communicating changes made by the current **pre-find module path hook** (i.e., hook run immediately + _before_ a call to `ModuleGraph._find_module_path()` finding the hooked module's absolute path) back to PyInstaller. + + Pre-find module path hooks _must_ define a `pre_find_module_path()` function accepting an instance of this class, + whose attributes describe the subsequent `ModuleGraph._find_module_path()` call to be performed. + + Pre-find module path hooks are typically used to change the absolute path from which a module will be + subsequently imported and thus frozen into the executable. To do so, hooks may overwrite the default + `search_dirs` list of the absolute paths of all directories to be searched for that module: e.g., + + def pre_find_module_path(api): + api.search_dirs = ['/the/one/true/package/providing/this/module'] + + Each pre-find module path hook is run _only_ on the first call to `ModuleGraph._find_module_path()` for the + corresponding module. + + Attributes + ---------- + The following attributes are **mutable** (i.e., modifiable). All changes to these attributes will be immediately + respected by PyInstaller: + + search_dirs : list + List of the absolute paths of all directories to be searched for this module (in order). Searching will halt + at the first directory containing this module. + + Attributes (Immutable) + ---------- + The following attributes are **immutable** (i.e., read-only). For safety, any attempts to change these attributes + _will_ result in a raised exception: + + module_name : str + Fully-qualified name of this module. + module_graph : PyiModuleGraph + Current module graph. For efficiency, this attribute is technically mutable. To preserve graph integrity, + this attribute should nonetheless _never_ be modified. While read-only `PyiModuleGraph` methods (e.g., + `findNode()`) are safely callable from within pre-find module path hooks, methods modifying the graph are + _not_. If graph modifications are required, consider an alternative type of hook (e.g., pre-import module + hooks). + """ + def __init__( + self, + module_graph, + module_name, + search_dirs, + ): + # Mutable attributes. + self.search_dirs = search_dirs + + # Immutable attributes. + self._module_graph = module_graph + self._module_name = module_name + + # Immutable properties. No corresponding setters are defined. + @property + def module_graph(self): + """ + Current module graph. + """ + return self._module_graph + + @property + def module_name(self): + """ + Fully-qualified name of this module. + """ + return self._module_name + + +class PostGraphAPI: + """ + Metadata communicating changes made by the current **post-graph hook** (i.e., hook run for a specific module + transitively imported by the current application _after_ the module graph of all `import` statements performed by + this application has been constructed) back to PyInstaller. + + Post-graph hooks may optionally define a `post_graph()` function accepting an instance of this class, + whose attributes describe the current state of the module graph and the hooked module's graph node. + + Attributes (Mutable) + ---------- + The following attributes are **mutable** (i.e., modifiable). All changes to these attributes will be immediately + respected by PyInstaller: + + module_graph : PyiModuleGraph + Current module graph. + module : Node + Graph node for the currently hooked module. + + 'With great power comes great responsibility.' + + Attributes (Immutable) + ---------- + The following attributes are **immutable** (i.e., read-only). For safety, any attempts to change these attributes + _will_ result in a raised exception: + + __name__ : str + Fully-qualified name of this module (e.g., `six.moves.tkinter`). + __file__ : str + Absolute path of this module. If this module is: + * A standard (rather than namespace) package, this is the absolute path of this package's directory. + * A namespace (rather than standard) package, this is the abstract placeholder `-`. (Don't ask. Don't tell.) + * A non-package module or C extension, this is the absolute path of the corresponding file. + __path__ : list + List of the absolute paths of all directories comprising this package if this module is a package _or_ `None` + otherwise. If this module is a standard (rather than namespace) package, this list contains only the absolute + path of this package's directory. + co : code + Code object compiled from the contents of `__file__` (e.g., via the `compile()` builtin). + analysis: build_main.Analysis + The Analysis that load the hook. + + Attributes (Private) + ---------- + The following attributes are technically mutable but private, and hence should _never_ be externally accessed or + modified by hooks. Call the corresponding public methods instead: + + _added_datas : list + List of the `(name, path)` 2-tuples or TOC objects of all external data files required by the current hook, + defaulting to the empty list. This is equivalent to the global `datas` hook attribute. + _added_imports : list + List of the fully-qualified names of all modules imported by the current hook, defaulting to the empty list. + This is equivalent to the global `hiddenimports` hook attribute. + _added_binaries : list + List of the `(name, path)` 2-tuples or TOC objects of all external C extensions imported by the current hook, + defaulting to the empty list. This is equivalent to the global `binaries` hook attribute. + _module_collection_mode : dict + Dictionary of package/module names and their corresponding collection mode strings. This is equivalent to the + global `module_collection_mode` hook attribute. + _bindepend_symlink_suppression : set + A set of paths or path patterns corresponding to shared libraries for which binary dependency analysis should + not generate symbolic links into top-level application directory. + """ + def __init__(self, module_name, module_graph, analysis): + # Mutable attributes. + self.module_graph = module_graph + self.module = module_graph.find_node(module_name) + assert self.module is not None # should not occur + + # Immutable attributes. + self.___name__ = module_name + self.___file__ = self.module.filename + self._co = self.module.code + self._analysis = analysis + + # To enforce immutability, convert this module's package path if any into an immutable tuple. + self.___path__ = tuple(self.module.packagepath) \ + if self.module.packagepath is not None else None + + #FIXME: Refactor "_added_datas", "_added_binaries", and "_deleted_imports" into sets. Since order of + #import is important, "_added_imports" must remain a list. + + # Private attributes. + self._added_binaries = [] + self._added_datas = [] + self._added_imports = [] + self._deleted_imports = [] + self._module_collection_mode = {} + self._bindepend_symlink_suppression = set() + + # Immutable properties. No corresponding setters are defined. + @property + def __file__(self): + """ + Absolute path of this module's file. + """ + return self.___file__ + + @property + def __path__(self): + """ + List of the absolute paths of all directories comprising this package if this module is a package _or_ `None` + otherwise. If this module is a standard (rather than namespace) package, this list contains only the absolute + path of this package's directory. + """ + return self.___path__ + + @property + def __name__(self): + """ + Fully-qualified name of this module (e.g., `six.moves.tkinter`). + """ + return self.___name__ + + @property + def co(self): + """ + Code object compiled from the contents of `__file__` (e.g., via the `compile()` builtin). + """ + return self._co + + @property + def analysis(self): + """ + build_main.Analysis that calls the hook. + """ + return self._analysis + + # Obsolete immutable properties provided to preserve backward compatibility. + @property + def name(self): + """ + Fully-qualified name of this module (e.g., `six.moves.tkinter`). + + **This property has been deprecated by the `__name__` property.** + """ + return self.___name__ + + @property + def graph(self): + """ + Current module graph. + + **This property has been deprecated by the `module_graph` property.** + """ + return self.module_graph + + @property + def node(self): + """ + Graph node for the currently hooked module. + + **This property has been deprecated by the `module` property.** + """ + return self.module + + # TODO: This incorrectly returns the list of the graph nodes of all modules *TRANSITIVELY* (rather than directly) + # imported by this module. Unfortunately, this implies that most uses of this property are currently broken + # (e.g., "hook-PIL.SpiderImagePlugin.py"). We only require this for the aforementioned hook, so contemplate + # alternative approaches. + @property + def imports(self): + """ + List of the graph nodes of all modules directly imported by this module. + """ + return self.module_graph.iter_graph(start=self.module) + + def add_imports(self, *module_names): + """ + Add all Python modules whose fully-qualified names are in the passed list as "hidden imports" upon which the + current module depends. + + This is equivalent to appending such names to the hook-specific `hiddenimports` attribute. + """ + # Append such names to the current list of all such names. + self._added_imports.extend(module_names) + + def del_imports(self, *module_names): + """ + Remove the named fully-qualified modules from the set of imports (either hidden or visible) upon which the + current module depends. + + This is equivalent to appending such names to the hook-specific `excludedimports` attribute. + """ + self._deleted_imports.extend(module_names) + + def add_binaries(self, binaries): + """ + Add all external dynamic libraries in the passed list of `(src_name, dest_name)` 2-tuples as dependencies of the + current module. This is equivalent to adding to the global `binaries` hook attribute. + + For convenience, the `binaries` may also be a list of TOC-style 3-tuples `(dest_name, src_name, typecode)`. + """ + + # Detect TOC 3-tuple list by checking the length of the first entry + if binaries and len(binaries[0]) == 3: + self._added_binaries.extend(entry[:2] for entry in binaries) + else: + # NOTE: `format_binaries_and_datas` changes tuples from input format `(src_name, dest_name)` to output + # format `(dest_name, src_name)`. + self._added_binaries.extend(format_binaries_and_datas(binaries)) + + def add_datas(self, datas): + """ + Add all external data files in the passed list of `(src_name, dest_name)` 2-tuples as dependencies of the + current module. This is equivalent to adding to the global `datas` hook attribute. + + For convenience, the `datas` may also be a list of TOC-style 3-tuples `(dest_name, src_name, typecode)`. + """ + + # Detect TOC 3-tuple list by checking the length of the first entry + if datas and len(datas[0]) == 3: + self._added_datas.extend(entry[:2] for entry in datas) + else: + # NOTE: `format_binaries_and_datas` changes tuples from input format `(src_name, dest_name)` to output + # format `(dest_name, src_name)`. + self._added_datas.extend(format_binaries_and_datas(datas)) + + def set_module_collection_mode(self, name, mode): + """" + Set the package/module collection mode for the specified module name. If `name` is `None`, the hooked + module/package name is used. `mode` can be one of valid mode strings (`'pyz'`, `'pyc'`, ˙'py'˙, `'pyz+py'`, + ˙'py+pyz'`) or `None`, which clears the setting for the module/package - but only within this hook's context! + """ + if name is None: + name = self.__name__ + if mode is None: + self._module_collection_mode.pop(name) + else: + self._module_collection_mode[name] = mode + + def add_bindepend_symlink_suppression_pattern(self, pattern): + """ + Add the given path or path pattern to the set of patterns that prevent binary dependency analysis from creating + a symbolic link to the top-level application directory. + """ + self._bindepend_symlink_suppression.add(pattern) diff --git a/venv/Lib/site-packages/PyInstaller/depend/utils.py b/venv/Lib/site-packages/PyInstaller/depend/utils.py new file mode 100644 index 0000000..d74360a --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/depend/utils.py @@ -0,0 +1,401 @@ +# -*- coding: utf-8 -*- +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- +""" +Utility functions related to analyzing/bundling dependencies. +""" + +import ctypes.util +import io +import os +import re +import shutil +import struct +import zipfile +from types import CodeType + +import marshal + +from PyInstaller import compat +from PyInstaller import log as logging +from PyInstaller.depend import bytecode +from PyInstaller.depend.dylib import include_library +from PyInstaller.exceptions import ExecCommandFailed +from PyInstaller.lib.modulegraph import modulegraph + +logger = logging.getLogger(__name__) + + +# TODO find out if modules from base_library.zip could be somehow bundled into the .exe file. +def create_py3_base_library(libzip_filename, graph): + """ + Package basic Python modules into .zip file. The .zip file with basic modules is necessary to have on PYTHONPATH + for initializing libpython3 in order to run the frozen executable with Python 3. + """ + # Import strip_paths_in_code locally to avoid cyclic import between building.utils and depend.utils (this module); + # building.utils imports depend.bindepend, which in turn imports depend.utils. + from PyInstaller.building.utils import strip_paths_in_code + + # Construct regular expression for matching modules that should be bundled into base_library.zip. Excluded are plain + # 'modules' or 'submodules.ANY_NAME'. The match has to be exact - start and end of string not substring. + regex_modules = '|'.join([rf'(^{x}$)' for x in compat.PY3_BASE_MODULES]) + regex_submod = '|'.join([rf'(^{x}\..*$)' for x in compat.PY3_BASE_MODULES]) + regex_str = regex_modules + '|' + regex_submod + module_filter = re.compile(regex_str) + + try: + # Remove .zip from previous run. + if os.path.exists(libzip_filename): + os.remove(libzip_filename) + logger.debug('Adding python files to base_library.zip') + # Class zipfile.PyZipFile is not suitable for PyInstaller needs. + with zipfile.ZipFile(libzip_filename, mode='w') as zf: + zf.debug = 3 + # Sort the graph nodes by identifier to ensure repeatable builds + graph_nodes = list(graph.iter_graph()) + graph_nodes.sort(key=lambda item: item.identifier) + for mod in graph_nodes: + if type(mod) in (modulegraph.SourceModule, modulegraph.Package, modulegraph.CompiledModule): + # Bundling just required modules. + if module_filter.match(mod.identifier): + # Name inside the archive. The ZIP format specification requires forward slashes as directory + # separator. + if type(mod) is modulegraph.Package: + new_name = mod.identifier.replace('.', '/') + '/__init__.pyc' + else: + new_name = mod.identifier.replace('.', '/') + '.pyc' + + # Write code to a file. This code is similar to py_compile.compile(). + with io.BytesIO() as fc: + fc.write(compat.BYTECODE_MAGIC) + fc.write(struct.pack('>> _resolveCtypesImports(['libgs.so']) + [(libgs.so', ''/usr/lib/libgs.so', 'BINARY')] + """ + from ctypes.util import find_library + + from PyInstaller.config import CONF + + if compat.is_unix: + envvar = "LD_LIBRARY_PATH" + elif compat.is_darwin: + envvar = "DYLD_LIBRARY_PATH" + else: + envvar = "PATH" + + def _setPaths(): + path = os.pathsep.join(CONF['pathex']) + old = compat.getenv(envvar) + if old is not None: + path = os.pathsep.join((path, old)) + compat.setenv(envvar, path) + return old + + def _restorePaths(old): + if old is None: + compat.unsetenv(envvar) + else: + compat.setenv(envvar, old) + + ret = [] + + # Try to locate the shared library on the disk. This is done by calling ctypes.util.find_library with + # ImportTracker's local paths temporarily prepended to the library search paths (and restored after the call). + old = _setPaths() + for cbin in cbinaries: + try: + # There is an issue with find_library() where it can run into errors trying to locate the library. See + # #5734. + cpath = find_library(os.path.splitext(cbin)[0]) + except FileNotFoundError: + # In these cases, find_library() should return None. + cpath = None + if compat.is_unix: + # CAVEAT: find_library() is not the correct function. ctype's documentation says that it is meant to resolve + # only the filename (as a *compiler* does) not the full path. Anyway, it works well enough on Windows and + # Mac OS. On Linux, we need to implement more code to find out the full path. + if cpath is None: + cpath = cbin + # "man ld.so" says that we should first search LD_LIBRARY_PATH and then the ldcache. + for d in compat.getenv(envvar, '').split(os.pathsep): + if os.path.isfile(os.path.join(d, cpath)): + cpath = os.path.join(d, cpath) + break + else: + if LDCONFIG_CACHE is None: + load_ldconfig_cache() + if cpath in LDCONFIG_CACHE: + cpath = LDCONFIG_CACHE[cpath] + assert os.path.isfile(cpath) + else: + cpath = None + if cpath is None: + # Skip warning message if cbin (basename of library) is ignored. This prevents messages like: + # 'W: library kernel32.dll required via ctypes not found' + if not include_library(cbin): + continue + # On non-Windows, automatically ignore all ctypes-based referenes to DLL files. This complements the above + # check, which might not match potential case variations (e.g., `KERNEL32.dll`, instead of `kernel32.dll`) + # due to case-sensitivity of the matching that is in effect on non-Windows platforms. + if not compat.is_win and cbin.lower().endswith('.dll'): + continue + logger.warning("Library %s required via ctypes not found", cbin) + else: + if not include_library(cpath): + continue + ret.append((cbin, cpath, "BINARY")) + _restorePaths(old) + return ret + + +LDCONFIG_CACHE = None # cache the output of `/sbin/ldconfig -p` + + +def load_ldconfig_cache(): + """ + Create a cache of the `ldconfig`-output to call it only once. + It contains thousands of libraries and running it on every dylib is expensive. + """ + global LDCONFIG_CACHE + + if LDCONFIG_CACHE is not None: + return + + if compat.is_musl: + # Musl deliberately doesn't use ldconfig. The ldconfig executable either doesn't exist or it's a functionless + # executable which, on calling with any arguments, simply tells you that those arguments are invalid. + LDCONFIG_CACHE = {} + return + + ldconfig = shutil.which('ldconfig') + if ldconfig is None: + # If `ldconfig` is not found in $PATH, search for it in some fixed directories. Simply use a second call instead + # of fiddling around with checks for empty env-vars and string-concat. + ldconfig = shutil.which('ldconfig', path='/usr/sbin:/sbin:/usr/bin:/bin') + + # If we still could not find the 'ldconfig' command... + if ldconfig is None: + LDCONFIG_CACHE = {} + return + + if compat.is_freebsd or compat.is_openbsd: + # This has a quite different format than other Unixes: + # [vagrant@freebsd-10 ~]$ ldconfig -r + # /var/run/ld-elf.so.hints: + # search directories: /lib:/usr/lib:/usr/lib/compat:... + # 0:-lgeom.5 => /lib/libgeom.so.5 + # 184:-lpython2.7.1 => /usr/local/lib/libpython2.7.so.1 + ldconfig_arg = '-r' + splitlines_count = 2 + pattern = re.compile(r'^\s+\d+:-l(\S+)(\s.*)? => (\S+)') + else: + # Skip first line of the library list because it is just an informative line and might contain localized + # characters. Example of first line with locale set to cs_CZ.UTF-8: + #$ /sbin/ldconfig -p + #V keši „/etc/ld.so.cache“ nalezeno knihoven: 2799 + # libzvbi.so.0 (libc6,x86-64) => /lib64/libzvbi.so.0 + # libzvbi-chains.so.0 (libc6,x86-64) => /lib64/libzvbi-chains.so.0 + ldconfig_arg = '-p' + splitlines_count = 1 + pattern = re.compile(r'^\s+(\S+)(\s.*)? => (\S+)') + + try: + text = compat.exec_command(ldconfig, ldconfig_arg) + except ExecCommandFailed: + logger.warning("Failed to execute ldconfig. Disabling LD cache.") + LDCONFIG_CACHE = {} + return + + text = text.strip().splitlines()[splitlines_count:] + + LDCONFIG_CACHE = {} + for line in text: + # :fixme: this assumes library names do not contain whitespace + m = pattern.match(line) + + # Sanitize away any abnormal lines of output. + if m is None: + # Warn about it then skip the rest of this iteration. + if re.search("Cache generated by:", line): + # See #5540. This particular line is harmless. + pass + else: + logger.warning("Unrecognised line of output %r from ldconfig", line) + continue + + path = m.groups()[-1] + if compat.is_freebsd or compat.is_openbsd: + # Insert `.so` at the end of the lib's basename. soname and filename may have (different) trailing versions. + # We assume the `.so` in the filename to mark the end of the lib's basename. + bname = os.path.basename(path).split('.so', 1)[0] + name = 'lib' + m.group(1) + assert name.startswith(bname) + name = bname + '.so' + name[len(bname):] + else: + name = m.group(1) + # ldconfig may know about several versions of the same lib, e.g., different arch, different libc, etc. + # Use the first entry. + if name not in LDCONFIG_CACHE: + LDCONFIG_CACHE[name] = path diff --git a/venv/Lib/site-packages/PyInstaller/exceptions.py b/venv/Lib/site-packages/PyInstaller/exceptions.py new file mode 100644 index 0000000..3562c0d --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/exceptions.py @@ -0,0 +1,82 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller import compat + + +class ExecCommandFailed(SystemExit): + pass + + +class HookError(Exception): + """ + Base class for hook related errors. + """ + pass + + +class ImportErrorWhenRunningHook(HookError): + def __str__(self): + return ( + "Failed to import module {0} required by hook for module {1}. Please check whether module {0} actually " + "exists and whether the hook is compatible with your version of {1}: You might want to read more about " + "hooks in the manual and provide a pull-request to improve PyInstaller.".format(self.args[0], self.args[1]) + ) + + +class RemovedCipherFeatureError(SystemExit): + def __init__(self, message): + super().__init__( + f"Bytecode encryption was removed in PyInstaller v6.0. {message}" + " For the rationale and alternatives see https://github.com/pyinstaller/pyinstaller/pull/6999" + ) + + +class RemovedExternalManifestError(SystemExit): + def __init__(self, message): + super().__init__(f"Support for external executable manifest was removed in PyInstaller v6.0. {message}") + + +class RemovedWinSideBySideSupportError(SystemExit): + def __init__(self, message): + super().__init__( + f"Support for collecting and processing WinSxS assemblies was removed in PyInstaller v6.0. {message}" + ) + + +_MISSING_PYTHON_LIB_MSG = \ +"""Python library not found: {0} + This means your Python installation does not come with proper shared library files. + This usually happens due to missing development package, or unsuitable build parameters of the Python installation. + + * On Debian/Ubuntu, you need to install Python development packages: + * apt-get install python3-dev + * apt-get install python-dev + * If you are building Python by yourself, rebuild with `--enable-shared` (or, `--enable-framework` on macOS). +""" # noqa: E122 + + +class PythonLibraryNotFoundError(IOError): + def __init__(self): + super().__init__(_MISSING_PYTHON_LIB_MSG.format(", ".join(compat.PYDYLIB_NAMES),)) + + +class InvalidSrcDestTupleError(SystemExit): + def __init__(self, src_dest, message): + super().__init__(f"Invalid (SRC, DEST_DIR) tuple: {src_dest!r}. {message}") + + +class ImportlibMetadataError(SystemExit): + def __init__(self): + super().__init__( + "PyInstaller requires importlib.metadata from python >= 3.10 stdlib or importlib_metadata from " + "importlib-metadata >= 4.6" + ) diff --git a/venv/Lib/site-packages/PyInstaller/fake-modules/__pycache__/pyi_splash.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/fake-modules/__pycache__/pyi_splash.cpython-311.pyc new file mode 100644 index 0000000..e9d6752 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/fake-modules/__pycache__/pyi_splash.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/fake-modules/_pyi_rth_utils/__init__.py b/venv/Lib/site-packages/PyInstaller/fake-modules/_pyi_rth_utils/__init__.py new file mode 100644 index 0000000..e006337 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/fake-modules/_pyi_rth_utils/__init__.py @@ -0,0 +1,36 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 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 +# ----------------------------------------------------------------------------- + +import sys +import os + +# A boolean indicating whether the frozen application is a macOS .app bundle. +is_macos_app_bundle = sys.platform == 'darwin' and sys._MEIPASS.endswith("Contents/Frameworks") + + +def prepend_path_to_environment_variable(path, variable_name): + """ + Prepend the given path to the list of paths stored in the given environment variable (separated by `os.pathsep`). + If the given path is already specified in the environment variable, no changes are made. If the environment variable + is not set or is empty, it is set/overwritten with the given path. + """ + stored_paths = os.environ.get(variable_name) + if stored_paths: + # If path is already included, make this a no-op. NOTE: we need to split the string and search in the list of + # substrings to find an exact match; searching in the original string might erroneously match a prefix of a + # longer (i.e., sub-directory) path when such entry already happens to be in PATH (see #8857). + if path in stored_paths.split(os.pathsep): + return + # Otherwise, prepend the path + stored_paths = path + os.pathsep + stored_paths + else: + stored_paths = path + os.environ[variable_name] = stored_paths diff --git a/venv/Lib/site-packages/PyInstaller/fake-modules/_pyi_rth_utils/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/fake-modules/_pyi_rth_utils/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..1744acb Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/fake-modules/_pyi_rth_utils/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/fake-modules/_pyi_rth_utils/__pycache__/_win32.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/fake-modules/_pyi_rth_utils/__pycache__/_win32.cpython-311.pyc new file mode 100644 index 0000000..b726cf6 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/fake-modules/_pyi_rth_utils/__pycache__/_win32.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/fake-modules/_pyi_rth_utils/__pycache__/qt.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/fake-modules/_pyi_rth_utils/__pycache__/qt.cpython-311.pyc new file mode 100644 index 0000000..21a5a47 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/fake-modules/_pyi_rth_utils/__pycache__/qt.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/fake-modules/_pyi_rth_utils/__pycache__/tempfile.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/fake-modules/_pyi_rth_utils/__pycache__/tempfile.cpython-311.pyc new file mode 100644 index 0000000..7e4f5c1 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/fake-modules/_pyi_rth_utils/__pycache__/tempfile.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/fake-modules/_pyi_rth_utils/_win32.py b/venv/Lib/site-packages/PyInstaller/fake-modules/_pyi_rth_utils/_win32.py new file mode 100644 index 0000000..80e30ec --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/fake-modules/_pyi_rth_utils/_win32.py @@ -0,0 +1,333 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 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 +# ----------------------------------------------------------------------------- + +import ctypes +import ctypes.wintypes + +# Constants from win32 headers +TOKEN_QUERY = 0x0008 + +TokenUser = 1 # from TOKEN_INFORMATION_CLASS enum +TokenAppContainerSid = 31 # from TOKEN_INFORMATION_CLASS enum + +ERROR_INSUFFICIENT_BUFFER = 122 + +INVALID_HANDLE = -1 + +FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100 +FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000 + +SDDL_REVISION1 = 1 + +# Structures for ConvertSidToStringSidW +PSID = ctypes.wintypes.LPVOID + + +class SID_AND_ATTRIBUTES(ctypes.Structure): + _fields_ = [ + ("Sid", PSID), + ("Attributes", ctypes.wintypes.DWORD), + ] + + +class TOKEN_USER(ctypes.Structure): + _fields_ = [ + ("User", SID_AND_ATTRIBUTES), + ] + + +PTOKEN_USER = ctypes.POINTER(TOKEN_USER) + + +class TOKEN_APPCONTAINER_INFORMATION(ctypes.Structure): + _fields_ = [ + ("TokenAppContainer", PSID), + ] + + +PTOKEN_APPCONTAINER_INFORMATION = ctypes.POINTER(TOKEN_APPCONTAINER_INFORMATION) + +# SECURITY_ATTRIBUTES structure for CreateDirectoryW +PSECURITY_DESCRIPTOR = ctypes.wintypes.LPVOID + + +class SECURITY_ATTRIBUTES(ctypes.Structure): + _fields_ = [ + ("nLength", ctypes.wintypes.DWORD), + ("lpSecurityDescriptor", PSECURITY_DESCRIPTOR), + ("bInheritHandle", ctypes.wintypes.BOOL), + ] + + +# win32 API functions, bound via ctypes. +# NOTE: we do not use ctypes.windll. to avoid modifying its (global) function prototypes, which might affect +# user's code. +advapi32 = ctypes.WinDLL("advapi32") +kernel32 = ctypes.WinDLL("kernel32") + +advapi32.ConvertSidToStringSidW.restype = ctypes.wintypes.BOOL +advapi32.ConvertSidToStringSidW.argtypes = ( + PSID, # [in] PSID Sid + ctypes.POINTER(ctypes.wintypes.LPWSTR), # [out] LPWSTR *StringSid +) + +advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW.restype = ctypes.wintypes.BOOL +advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW.argtypes = ( + ctypes.wintypes.LPCWSTR, # [in] LPCWSTR StringSecurityDescriptor + ctypes.wintypes.DWORD, # [in] DWORD StringSDRevision + ctypes.POINTER(PSECURITY_DESCRIPTOR), # [out] PSECURITY_DESCRIPTOR *SecurityDescriptor + ctypes.wintypes.PULONG, # [out] PULONG SecurityDescriptorSize +) + +advapi32.GetTokenInformation.restype = ctypes.wintypes.BOOL +advapi32.GetTokenInformation.argtypes = ( + ctypes.wintypes.HANDLE, # [in] HANDLE TokenHandle + ctypes.c_int, # [in] TOKEN_INFORMATION_CLASS TokenInformationClass + ctypes.wintypes.LPVOID, # [out, optional] LPVOID TokenInformation + ctypes.wintypes.DWORD, # [in] DWORD TokenInformationLength + ctypes.wintypes.PDWORD, # [out] PDWORD ReturnLength +) + +kernel32.CloseHandle.restype = ctypes.wintypes.BOOL +kernel32.CloseHandle.argtypes = ( + ctypes.wintypes.HANDLE, # [in] HANDLE hObject +) + +kernel32.CreateDirectoryW.restype = ctypes.wintypes.BOOL +kernel32.CreateDirectoryW.argtypes = ( + ctypes.wintypes.LPCWSTR, # [in] LPCWSTR lpPathName + ctypes.POINTER(SECURITY_ATTRIBUTES), # [in, optional] LPSECURITY_ATTRIBUTES lpSecurityAttributes +) + +kernel32.FormatMessageW.restype = ctypes.wintypes.DWORD +kernel32.FormatMessageW.argtypes = ( + ctypes.wintypes.DWORD, # [in] DWORD dwFlags + ctypes.wintypes.LPCVOID, # [in, optional] LPCVOID lpSource + ctypes.wintypes.DWORD, # [in] DWORD dwMessageId + ctypes.wintypes.DWORD, # [in] DWORD dwLanguageId + ctypes.wintypes.LPWSTR, # [out] LPWSTR lpBuffer + ctypes.wintypes.DWORD, # [in] DWORD nSize + ctypes.wintypes.LPVOID, # [in, optional] va_list *Arguments +) + +kernel32.GetCurrentProcess.restype = ctypes.wintypes.HANDLE +# kernel32.GetCurrentProcess has no arguments + +kernel32.GetLastError.restype = ctypes.wintypes.DWORD +# kernel32.GetLastError has no arguments + +kernel32.LocalFree.restype = ctypes.wintypes.BOOL +kernel32.LocalFree.argtypes = ( + ctypes.wintypes.HLOCAL, # [in] _Frees_ptr_opt_ HLOCAL hMem +) + +kernel32.OpenProcessToken.restype = ctypes.wintypes.BOOL +kernel32.OpenProcessToken.argtypes = ( + ctypes.wintypes.HANDLE, # [in] HANDLE ProcessHandle + ctypes.wintypes.DWORD, # [in] DWORD DesiredAccess + ctypes.wintypes.PHANDLE, # [out] PHANDLE TokenHandle +) + + +def _win_error_to_message(error_code): + """ + Convert win32 error code to message. + """ + message_wstr = ctypes.wintypes.LPWSTR(None) + ret = kernel32.FormatMessageW( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + None, # lpSource + error_code, # dwMessageId + 0x400, # dwLanguageId = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT) + ctypes.cast( + ctypes.byref(message_wstr), + ctypes.wintypes.LPWSTR, + ), # pointer to LPWSTR due to FORMAT_MESSAGE_ALLOCATE_BUFFER; needs to be cast to LPWSTR + 64, # due to FORMAT_MESSAGE_ALLOCATE_BUFFER, this is minimum number of characters to allocate + None, + ) + if ret == 0: + return None + + message = message_wstr.value + kernel32.LocalFree(message_wstr) + + # Strip trailing CR/LF. + if message: + message = message.strip() + return message + + +def _get_process_sid(token_information_class): + """ + Obtain the SID from the current process by the given token information class. + + Args: + token_information_class: Token information class identifying the SID that we're + interested in. Only TokenUser and TokenAppContainerSid are supported. + + Returns: SID (if it could be fetched) or None if not available or on error. + """ + process_token = ctypes.wintypes.HANDLE(INVALID_HANDLE) + + try: + # Get access token for the current process + ret = kernel32.OpenProcessToken( + kernel32.GetCurrentProcess(), + TOKEN_QUERY, + ctypes.pointer(process_token), + ) + if ret == 0: + error_code = kernel32.GetLastError() + raise RuntimeError(f"Failed to open process token! Error code: 0x{error_code:X}") + + # Query buffer size for sid + token_info_size = ctypes.wintypes.DWORD(0) + + ret = advapi32.GetTokenInformation( + process_token, + token_information_class, + None, + 0, + ctypes.byref(token_info_size), + ) + + # We expect this call to fail with ERROR_INSUFFICIENT_BUFFER + if ret == 0: + error_code = kernel32.GetLastError() + if error_code != ERROR_INSUFFICIENT_BUFFER: + raise RuntimeError(f"Failed to query token information buffer size! Error code: 0x{error_code:X}") + else: + raise RuntimeError("Unexpected return value from GetTokenInformation!") + + # Allocate buffer + token_info = ctypes.create_string_buffer(token_info_size.value) + ret = advapi32.GetTokenInformation( + process_token, + token_information_class, + token_info, + token_info_size, + ctypes.byref(token_info_size), + ) + if ret == 0: + error_code = kernel32.GetLastError() + raise RuntimeError(f"Failed to query token information! Error code: 0x{error_code:X}") + + # Convert SID to string + # Technically, when UserToken is used, we need to pass user_info->User.Sid, + # but as they are at the beginning of the buffer, just pass the buffer instead... + sid_wstr = ctypes.wintypes.LPWSTR(None) + + if token_information_class == TokenUser: + sid = ctypes.cast(token_info, PTOKEN_USER).contents.User.Sid + elif token_information_class == TokenAppContainerSid: + sid = ctypes.cast(token_info, PTOKEN_APPCONTAINER_INFORMATION).contents.TokenAppContainer + else: + raise ValueError(f"Unexpected token information class: {token_information_class}") + + ret = advapi32.ConvertSidToStringSidW(sid, ctypes.pointer(sid_wstr)) + if ret == 0: + error_code = kernel32.GetLastError() + raise RuntimeError(f"Failed to convert SID to string! Error code: 0x{error_code:X}") + sid = sid_wstr.value + kernel32.LocalFree(sid_wstr) + except Exception: + sid = None + finally: + # Close the process token + if process_token.value != INVALID_HANDLE: + kernel32.CloseHandle(process_token) + + return sid + + +# Get and cache current user's SID +_user_sid = _get_process_sid(TokenUser) + +# Get and cache current app container's SID (if any) +_app_container_sid = _get_process_sid(TokenAppContainerSid) + + +def secure_mkdir(dir_name): + """ + Replacement for mkdir that limits the access to created directory to current user. + """ + + # Create security descriptor + # Prefer actual user SID over SID S-1-3-4 (current owner), because at the time of writing, Wine does not properly + # support the latter. + user_sid = _user_sid or "S-1-3-4" + + # DACL descriptor (D): + # ace_type;ace_flags;rights;object_guid;inherit_object_guid;account_sid;(resource_attribute) + # - ace_type = SDDL_ACCESS_ALLOWED (A) + # - rights = SDDL_FILE_ALL (FA) + # - account_sid = current user (queried SID) + security_desc_str = f"D:(A;;FA;;;{user_sid})" + + # If the app is running within an AppContainer, the app container SID has to be added to the DACL. + # Otherwise our process will not have access to the temp dir. + # + # Quoting https://learn.microsoft.com/en-us/windows/win32/secauthz/implementing-an-appcontainer: + # "The AppContainer SID is a persistent unique identifier for the appcontainer. ... + # To allow a single AppContainer to access a resource, add its AppContainerSID to the ACL for that resource." + if _app_container_sid: + security_desc_str += f"(A;;FA;;;{_app_container_sid})" + security_desc = ctypes.wintypes.LPVOID(None) + + ret = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW( + security_desc_str, + SDDL_REVISION1, + ctypes.byref(security_desc), + None, + ) + if ret == 0: + error_code = kernel32.GetLastError() + raise RuntimeError( + f"Failed to create security descriptor! Error code: 0x{error_code:X}, " + f"message: {_win_error_to_message(error_code)}" + ) + + security_attr = SECURITY_ATTRIBUTES() + security_attr.nLength = ctypes.sizeof(SECURITY_ATTRIBUTES) + security_attr.lpSecurityDescriptor = security_desc + security_attr.bInheritHandle = False + + # Create directory + ret = kernel32.CreateDirectoryW( + dir_name, + security_attr, + ) + if ret == 0: + # Call failed; store error code immediately, to avoid it being overwritten in cleanup below. + error_code = kernel32.GetLastError() + + # Free security descriptor + kernel32.LocalFree(security_desc) + + # Exit on succeess + if ret != 0: + return + + # Construct OSError from win error code + error_message = _win_error_to_message(error_code) + + # Strip trailing dot to match error message from os.mkdir(). + if error_message and error_message[-1] == '.': + error_message = error_message[:-1] + + raise OSError( + None, # errno + error_message, # strerror + dir_name, # filename + error_code, # winerror + None, # filename2 + ) diff --git a/venv/Lib/site-packages/PyInstaller/fake-modules/_pyi_rth_utils/qt.py b/venv/Lib/site-packages/PyInstaller/fake-modules/_pyi_rth_utils/qt.py new file mode 100644 index 0000000..b406677 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/fake-modules/_pyi_rth_utils/qt.py @@ -0,0 +1,118 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2024, 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 +# ----------------------------------------------------------------------------- + +import os +import importlib +import atexit + +# Helper for ensuring that only one Qt bindings package is registered at run-time via run-time hooks. +_registered_qt_bindings = None + + +def ensure_single_qt_bindings_package(qt_bindings): + global _registered_qt_bindings + if _registered_qt_bindings is not None: + raise RuntimeError( + f"Cannot execute run-time hook for {qt_bindings!r} because run-time hook for {_registered_qt_bindings!r} " + "has been run before, and PyInstaller-frozen applications do not support multiple Qt bindings in the same " + "application!" + ) + _registered_qt_bindings = qt_bindings + + +# Helper for relocating Qt prefix via embedded qt.conf file. +_QT_CONF_FILENAME = ":/qt/etc/qt.conf" + +_QT_CONF_RESOURCE_NAME = ( + # qt + b"\x00\x02" + b"\x00\x00\x07\x84" + b"\x00\x71" + b"\x00\x74" + # etc + b"\x00\x03" + b"\x00\x00\x6c\xa3" + b"\x00\x65" + b"\x00\x74\x00\x63" + # qt.conf + b"\x00\x07" + b"\x08\x74\xa6\xa6" + b"\x00\x71" + b"\x00\x74\x00\x2e\x00\x63\x00\x6f\x00\x6e\x00\x66" +) + +_QT_CONF_RESOURCE_STRUCT = ( + # : + b"\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01" + # :/qt + b"\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02" + # :/qt/etc + b"\x00\x00\x00\x0a\x00\x02\x00\x00\x00\x01\x00\x00\x00\x03" + # :/qt/etc/qt.conf + b"\x00\x00\x00\x16\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00" +) + + +def create_embedded_qt_conf(qt_bindings, prefix_path): + # The QtCore module might be unavailable if we collected just the top-level binding package (e.g., PyQt5) without + # any of its submodules. Since this helper is called from run-time hook for the binding package, we need to handle + # that scenario here. + try: + QtCore = importlib.import_module(qt_bindings + ".QtCore") + except ImportError: + return + + # No-op if embedded qt.conf already exists + if QtCore.QFile.exists(_QT_CONF_FILENAME): + return + + # Create qt.conf file that relocates Qt prefix. + # NOTE: paths should use POSIX-style forward slashes as separator, even on Windows. + if os.sep == '\\': + prefix_path = prefix_path.replace(os.sep, '/') + + qt_conf = f"[Paths]\nPrefix = {prefix_path}\n" + if os.name == 'nt' and qt_bindings in {"PySide2", "PySide6"}: + # PySide PyPI wheels on Windows set LibraryExecutablesPath to PrefixPath + qt_conf += f"LibraryExecutables = {prefix_path}" + + # Encode the contents; in Qt5, QSettings uses Latin1 encoding, in Qt6, it uses UTF8. + if qt_bindings in {"PySide2", "PyQt5"}: + qt_conf = qt_conf.encode("latin1") + else: + qt_conf = qt_conf.encode("utf-8") + + # Prepend data size (32-bit integer, big endian) + qt_conf_size = len(qt_conf) + qt_resource_data = qt_conf_size.to_bytes(4, 'big') + qt_conf + + # Register + succeeded = QtCore.qRegisterResourceData( + 0x01, + _QT_CONF_RESOURCE_STRUCT, + _QT_CONF_RESOURCE_NAME, + qt_resource_data, + ) + if not succeeded: + return # Tough luck + + # Unregister the resource at exit, to ensure that the registered resource on Qt/C++ side does not outlive the + # `_qt_resource_data` python variable and its data buffer. This also adds a reference to the `_qt_resource_data`, + # which conveniently ensures that the data is not garbage collected before we perform the cleanup (otherwise garbage + # collector might kick in at any time after we exit this helper function, and `qRegisterResourceData` does not seem + # to make a copy of the data!). + atexit.register( + QtCore.qUnregisterResourceData, + 0x01, + _QT_CONF_RESOURCE_STRUCT, + _QT_CONF_RESOURCE_NAME, + qt_resource_data, + ) diff --git a/venv/Lib/site-packages/PyInstaller/fake-modules/_pyi_rth_utils/tempfile.py b/venv/Lib/site-packages/PyInstaller/fake-modules/_pyi_rth_utils/tempfile.py new file mode 100644 index 0000000..da2307b --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/fake-modules/_pyi_rth_utils/tempfile.py @@ -0,0 +1,56 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 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 +# ----------------------------------------------------------------------------- + +import os +import sys +import errno +import tempfile + +# Helper for creating temporary directories with access restricted to the user running the process. +# On POSIX systems, this is already achieved by `tempfile.mkdtemp`, which uses 0o700 permissions mask. +# On Windows, however, the POSIX permissions semantics have no effect, and we need to provide our own implementation +# that restricts the access by passing appropriate security attributes to the `CreateDirectory` function. + +if os.name == 'nt': + from . import _win32 + + def secure_mkdtemp(suffix=None, prefix=None, dir=None): + """ + Windows-specific replacement for `tempfile.mkdtemp` that restricts access to the user running the process. + Based on `mkdtemp` implementation from python 3.11 stdlib. + """ + + prefix, suffix, dir, output_type = tempfile._sanitize_params(prefix, suffix, dir) + + names = tempfile._get_candidate_names() + if output_type is bytes: + names = map(os.fsencode, names) + + for seq in range(tempfile.TMP_MAX): + name = next(names) + file = os.path.join(dir, prefix + name + suffix) + sys.audit("tempfile.mkdtemp", file) + try: + _win32.secure_mkdir(file) + except FileExistsError: + continue # try again + except PermissionError: + # This exception is thrown when a directory with the chosen name already exists on windows. + if (os.name == 'nt' and os.path.isdir(dir) and os.access(dir, os.W_OK)): + continue + else: + raise + return file + + raise FileExistsError(errno.EEXIST, "No usable temporary directory name found") + +else: + secure_mkdtemp = tempfile.mkdtemp diff --git a/venv/Lib/site-packages/PyInstaller/fake-modules/pyi_splash.py b/venv/Lib/site-packages/PyInstaller/fake-modules/pyi_splash.py new file mode 100644 index 0000000..934d288 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/fake-modules/pyi_splash.py @@ -0,0 +1,211 @@ +# ----------------------------------------------------------------------------- +# 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 module is not a "fake module" in the classical sense, but a real module that can be imported. It acts as an RPC +# interface for the functions of the bootloader. +""" +This module connects to the bootloader to send messages to the splash screen. + +It is intended to act as a RPC interface for the functions provided by the bootloader, such as displaying text or +closing. This makes the users python program independent of how the communication with the bootloader is implemented, +since a consistent API is provided. + +To connect to the bootloader, it connects to a local tcp socket whose port is passed through the environment variable +'_PYI_SPLASH_IPC'. The bootloader creates a server socket and accepts every connection request. Since the os-module, +which is needed to request the environment variable, is not available at boot time, the module does not establish the +connection until initialization. + +The protocol by which the Python interpreter communicates with the bootloader is implemented in this module. + +This module does not support reloads while the splash screen is displayed, i.e. it cannot be reloaded (such as by +importlib.reload), because the splash screen closes automatically when the connection to this instance of the module +is lost. +""" + +import atexit +import os + +# Import the _socket module instead of the socket module. All used functions to connect to the ipc system are +# provided by the C module and the users program does not necessarily need to include the socket module and all +# required modules it uses. +import _socket + +__all__ = ["CLOSE_CONNECTION", "FLUSH_CHARACTER", "is_alive", "close", "update_text"] + +try: + # The user might have excluded logging from imports. + import logging as _logging +except ImportError: + _logging = None + +try: + # The user might have excluded functools from imports. + from functools import update_wrapper +except ImportError: + update_wrapper = None + + +# Utility +def _log(level, msg, *args, **kwargs): + """ + Conditional wrapper around logging module. If the user excluded logging from the imports or it was not imported, + this function should handle it and avoid using the logger. + """ + if _logging: + logger = _logging.getLogger(__name__) + logger.log(level, msg, *args, **kwargs) + + +# These constants define single characters which are needed to send commands to the bootloader. Those constants are +# also set in the tcl script. +CLOSE_CONNECTION = b'\x04' # ASCII End-of-Transmission character +FLUSH_CHARACTER = b'\x0D' # ASCII Carriage Return character + +# Module internal variables +_initialized = False +# Keep these variables always synchronized +_ipc_socket_closed = True +_ipc_socket = _socket.socket(_socket.AF_INET, _socket.SOCK_STREAM) + + +def _initialize(): + """ + Initialize this module + + :return: + """ + global _initialized, _ipc_socket, _ipc_socket_closed + + # If _ipc_port is zero, the splash screen is intentionally suppressed (for example, we are in sub-process spawned + # via sys.executable). Mark the splash screen as initialized, but do not attempt to connect. + if _ipc_port == 0: + _initialized = True + return + + # Attempt to connect to the splash screen process. + try: + _ipc_socket.connect(("127.0.0.1", _ipc_port)) + _ipc_socket_closed = False + + _initialized = True + _log(10, "IPC connection to the splash screen was successfully established.") # log-level: debug + except OSError as err: + raise ConnectionError(f"Could not connect to TCP port {_ipc_port}.") from err + + +# We expect a splash screen from the bootloader, but if _PYI_SPLASH_IPC is not set, the module cannot connect to it. +# _PYI_SPLASH_IPC being set to zero indicates that splash screen should be (gracefully) suppressed; i.e., the calls +# in this module should become no-op without generating warning messages. +try: + _ipc_port = int(os.environ['_PYI_SPLASH_IPC']) + del os.environ['_PYI_SPLASH_IPC'] + # Initialize the connection upon importing this module. This will establish a connection to the bootloader's TCP + # server socket. + _initialize() +except (KeyError, ValueError): + # log-level: warning + _log( + 30, + "The environment does not allow connecting to the splash screen. Did bootloader fail to initialize it?", + exc_info=True, + ) +except ConnectionError: + # log-level: error + _log(40, "Failed to connect to the bootloader's IPC server!", exc_info=True) + + +def _check_connection(func): + """ + Utility decorator for checking whether the function should be executed. + + The wrapped function may raise a ConnectionError if the module was not initialized correctly. + """ + def wrapper(*args, **kwargs): + """ + Executes the wrapped function if the environment allows it. + + That is, if the connection to to bootloader has not been closed and the module is initialized. + + :raises RuntimeError: if the module was not initialized correctly. + """ + if _initialized and _ipc_socket_closed: + if _ipc_port != 0: + _log(10, "Connection to splash screen has already been closed.") # log-level: debug + return + elif not _initialized: + raise RuntimeError("This module is not initialized; did it fail to load?") + + return func(*args, **kwargs) + + if update_wrapper: + # For runtime introspection + update_wrapper(wrapper, func) + + return wrapper + + +@_check_connection +def _send_command(cmd, args=None): + """ + Send the command followed by args to the splash screen. + + :param str cmd: The command to send. All command have to be defined as procedures in the tcl splash screen script. + :param list[str] args: All arguments to send to the receiving function + """ + if args is None: + args = [] + + full_cmd = "%s(%s)" % (cmd, " ".join(args)) + try: + _ipc_socket.sendall(full_cmd.encode("utf-8") + FLUSH_CHARACTER) + except OSError as err: + raise ConnectionError(f"Unable to send command {full_cmd!r} to the bootloader") from err + + +def is_alive(): + """ + Indicates whether the module can be used. + + Returns False if the module is either not initialized or was disabled by closing the splash screen. Otherwise, + the module should be usable. + """ + return _initialized and not _ipc_socket_closed + + +@_check_connection +def update_text(msg: str): + """ + Updates the text on the splash screen window. + + :param str msg: the text to be displayed + :raises ConnectionError: If the OS fails to write to the socket. + :raises RuntimeError: If the module is not initialized. + """ + _send_command("update_text", [msg]) + + +def close(): + """ + Close the connection to the ipc tcp server socket. + + This will close the splash screen and renders this module unusable. After this function is called, no connection + can be opened to the splash screen again and all functions in this module become unusable. + """ + global _ipc_socket_closed + if _initialized and not _ipc_socket_closed: + _ipc_socket.sendall(CLOSE_CONNECTION) + _ipc_socket.close() + _ipc_socket_closed = True + + +@atexit.register +def _exit(): + close() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__init__.py b/venv/Lib/site-packages/PyInstaller/hooks/__init__.py new file mode 100644 index 0000000..792d600 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/__init__.py @@ -0,0 +1 @@ +# diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..50a7235 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PIL.Image.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PIL.Image.cpython-311.pyc new file mode 100644 index 0000000..37dac9b Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PIL.Image.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PIL.ImageFilter.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PIL.ImageFilter.cpython-311.pyc new file mode 100644 index 0000000..e8a82a4 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PIL.ImageFilter.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PIL.SpiderImagePlugin.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PIL.SpiderImagePlugin.cpython-311.pyc new file mode 100644 index 0000000..732b5d5 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PIL.SpiderImagePlugin.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PIL.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PIL.cpython-311.pyc new file mode 100644 index 0000000..fec7115 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PIL.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QAxContainer.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QAxContainer.cpython-311.pyc new file mode 100644 index 0000000..6b0c701 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QAxContainer.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.Qsci.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.Qsci.cpython-311.pyc new file mode 100644 index 0000000..9fcb58e Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.Qsci.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.Qt.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.Qt.cpython-311.pyc new file mode 100644 index 0000000..0bc9dde Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.Qt.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.Qt3DAnimation.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.Qt3DAnimation.cpython-311.pyc new file mode 100644 index 0000000..457bdd2 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.Qt3DAnimation.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.Qt3DCore.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.Qt3DCore.cpython-311.pyc new file mode 100644 index 0000000..0a1d581 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.Qt3DCore.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.Qt3DExtras.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.Qt3DExtras.cpython-311.pyc new file mode 100644 index 0000000..3755615 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.Qt3DExtras.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.Qt3DInput.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.Qt3DInput.cpython-311.pyc new file mode 100644 index 0000000..219a91b Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.Qt3DInput.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.Qt3DLogic.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.Qt3DLogic.cpython-311.pyc new file mode 100644 index 0000000..7ede779 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.Qt3DLogic.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.Qt3DRender.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.Qt3DRender.cpython-311.pyc new file mode 100644 index 0000000..6d74123 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.Qt3DRender.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtBluetooth.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtBluetooth.cpython-311.pyc new file mode 100644 index 0000000..16e0894 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtBluetooth.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtChart.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtChart.cpython-311.pyc new file mode 100644 index 0000000..3b0891f Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtChart.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtCore.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtCore.cpython-311.pyc new file mode 100644 index 0000000..488bd4f Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtCore.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtDBus.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtDBus.cpython-311.pyc new file mode 100644 index 0000000..3ca0920 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtDBus.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtDataVisualization.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtDataVisualization.cpython-311.pyc new file mode 100644 index 0000000..50b6aef Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtDataVisualization.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtDesigner.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtDesigner.cpython-311.pyc new file mode 100644 index 0000000..76ac332 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtDesigner.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtGui.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtGui.cpython-311.pyc new file mode 100644 index 0000000..704619b Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtGui.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtHelp.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtHelp.cpython-311.pyc new file mode 100644 index 0000000..fc44e66 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtHelp.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtLocation.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtLocation.cpython-311.pyc new file mode 100644 index 0000000..c16a482 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtLocation.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtMacExtras.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtMacExtras.cpython-311.pyc new file mode 100644 index 0000000..4d501f1 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtMacExtras.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtMultimedia.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtMultimedia.cpython-311.pyc new file mode 100644 index 0000000..818c478 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtMultimedia.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtMultimediaWidgets.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtMultimediaWidgets.cpython-311.pyc new file mode 100644 index 0000000..e82caca Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtMultimediaWidgets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtNetwork.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtNetwork.cpython-311.pyc new file mode 100644 index 0000000..df8cee7 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtNetwork.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtNetworkAuth.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtNetworkAuth.cpython-311.pyc new file mode 100644 index 0000000..99504c9 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtNetworkAuth.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtNfc.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtNfc.cpython-311.pyc new file mode 100644 index 0000000..8668094 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtNfc.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtOpenGL.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtOpenGL.cpython-311.pyc new file mode 100644 index 0000000..a6f5bc0 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtOpenGL.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtPositioning.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtPositioning.cpython-311.pyc new file mode 100644 index 0000000..25f072a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtPositioning.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtPrintSupport.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtPrintSupport.cpython-311.pyc new file mode 100644 index 0000000..3ec91f3 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtPrintSupport.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtPurchasing.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtPurchasing.cpython-311.pyc new file mode 100644 index 0000000..1571bb6 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtPurchasing.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtQml.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtQml.cpython-311.pyc new file mode 100644 index 0000000..09527fc Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtQml.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtQuick.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtQuick.cpython-311.pyc new file mode 100644 index 0000000..968c180 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtQuick.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtQuick3D.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtQuick3D.cpython-311.pyc new file mode 100644 index 0000000..4f078c3 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtQuick3D.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtQuickWidgets.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtQuickWidgets.cpython-311.pyc new file mode 100644 index 0000000..22b11f7 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtQuickWidgets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtRemoteObjects.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtRemoteObjects.cpython-311.pyc new file mode 100644 index 0000000..72aa8ec Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtRemoteObjects.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtScript.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtScript.cpython-311.pyc new file mode 100644 index 0000000..ec09f78 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtScript.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtSensors.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtSensors.cpython-311.pyc new file mode 100644 index 0000000..f4937bb Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtSensors.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtSerialPort.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtSerialPort.cpython-311.pyc new file mode 100644 index 0000000..7462783 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtSerialPort.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtSql.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtSql.cpython-311.pyc new file mode 100644 index 0000000..a9bf471 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtSql.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtSvg.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtSvg.cpython-311.pyc new file mode 100644 index 0000000..5c0b927 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtSvg.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtTest.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtTest.cpython-311.pyc new file mode 100644 index 0000000..72880b9 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtTest.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtTextToSpeech.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtTextToSpeech.cpython-311.pyc new file mode 100644 index 0000000..06c5ade Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtTextToSpeech.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtWebChannel.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtWebChannel.cpython-311.pyc new file mode 100644 index 0000000..5b15b84 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtWebChannel.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtWebEngine.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtWebEngine.cpython-311.pyc new file mode 100644 index 0000000..5dd1433 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtWebEngine.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtWebEngineCore.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtWebEngineCore.cpython-311.pyc new file mode 100644 index 0000000..8f89208 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtWebEngineCore.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtWebEngineWidgets.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtWebEngineWidgets.cpython-311.pyc new file mode 100644 index 0000000..2b5164a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtWebEngineWidgets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtWebKit.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtWebKit.cpython-311.pyc new file mode 100644 index 0000000..6200fc6 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtWebKit.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtWebKitWidgets.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtWebKitWidgets.cpython-311.pyc new file mode 100644 index 0000000..fb0f5ec Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtWebKitWidgets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtWebSockets.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtWebSockets.cpython-311.pyc new file mode 100644 index 0000000..4c4a74a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtWebSockets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtWidgets.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtWidgets.cpython-311.pyc new file mode 100644 index 0000000..ec34332 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtWidgets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtWinExtras.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtWinExtras.cpython-311.pyc new file mode 100644 index 0000000..7c7e69f Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtWinExtras.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtX11Extras.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtX11Extras.cpython-311.pyc new file mode 100644 index 0000000..354fe0b Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtX11Extras.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtXml.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtXml.cpython-311.pyc new file mode 100644 index 0000000..3dc0cb0 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtXml.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtXmlPatterns.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtXmlPatterns.cpython-311.pyc new file mode 100644 index 0000000..27aaec2 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.QtXmlPatterns.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.cpython-311.pyc new file mode 100644 index 0000000..559e2b3 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.uic.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.uic.cpython-311.pyc new file mode 100644 index 0000000..57b60e2 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt5.uic.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QAxContainer.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QAxContainer.cpython-311.pyc new file mode 100644 index 0000000..f6c24d5 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QAxContainer.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.Qsci.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.Qsci.cpython-311.pyc new file mode 100644 index 0000000..b2ca1be Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.Qsci.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.Qt3DAnimation.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.Qt3DAnimation.cpython-311.pyc new file mode 100644 index 0000000..da434b6 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.Qt3DAnimation.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.Qt3DCore.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.Qt3DCore.cpython-311.pyc new file mode 100644 index 0000000..3adc2d9 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.Qt3DCore.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.Qt3DExtras.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.Qt3DExtras.cpython-311.pyc new file mode 100644 index 0000000..fc1b16a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.Qt3DExtras.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.Qt3DInput.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.Qt3DInput.cpython-311.pyc new file mode 100644 index 0000000..75ba881 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.Qt3DInput.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.Qt3DLogic.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.Qt3DLogic.cpython-311.pyc new file mode 100644 index 0000000..30bad9f Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.Qt3DLogic.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.Qt3DRender.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.Qt3DRender.cpython-311.pyc new file mode 100644 index 0000000..47a3a9c Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.Qt3DRender.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtBluetooth.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtBluetooth.cpython-311.pyc new file mode 100644 index 0000000..9e03cb4 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtBluetooth.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtCharts.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtCharts.cpython-311.pyc new file mode 100644 index 0000000..f7d492a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtCharts.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtCore.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtCore.cpython-311.pyc new file mode 100644 index 0000000..ca06f5e Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtCore.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtDBus.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtDBus.cpython-311.pyc new file mode 100644 index 0000000..1c70d74 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtDBus.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtDataVisualization.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtDataVisualization.cpython-311.pyc new file mode 100644 index 0000000..c23e501 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtDataVisualization.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtDesigner.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtDesigner.cpython-311.pyc new file mode 100644 index 0000000..322ddf0 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtDesigner.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtGui.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtGui.cpython-311.pyc new file mode 100644 index 0000000..1100bef Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtGui.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtHelp.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtHelp.cpython-311.pyc new file mode 100644 index 0000000..a436ceb Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtHelp.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtMultimedia.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtMultimedia.cpython-311.pyc new file mode 100644 index 0000000..e74a7a3 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtMultimedia.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtMultimediaWidgets.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtMultimediaWidgets.cpython-311.pyc new file mode 100644 index 0000000..968b1d9 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtMultimediaWidgets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtNetwork.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtNetwork.cpython-311.pyc new file mode 100644 index 0000000..44307c7 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtNetwork.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtNetworkAuth.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtNetworkAuth.cpython-311.pyc new file mode 100644 index 0000000..425b3b8 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtNetworkAuth.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtNfc.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtNfc.cpython-311.pyc new file mode 100644 index 0000000..910b309 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtNfc.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtOpenGL.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtOpenGL.cpython-311.pyc new file mode 100644 index 0000000..0f0ee1c Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtOpenGL.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtOpenGLWidgets.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtOpenGLWidgets.cpython-311.pyc new file mode 100644 index 0000000..1edc508 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtOpenGLWidgets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtPdf.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtPdf.cpython-311.pyc new file mode 100644 index 0000000..5af5ef8 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtPdf.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtPdfWidgets.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtPdfWidgets.cpython-311.pyc new file mode 100644 index 0000000..4726fca Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtPdfWidgets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtPositioning.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtPositioning.cpython-311.pyc new file mode 100644 index 0000000..38833b9 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtPositioning.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtPrintSupport.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtPrintSupport.cpython-311.pyc new file mode 100644 index 0000000..31c1e1f Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtPrintSupport.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtQml.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtQml.cpython-311.pyc new file mode 100644 index 0000000..562fdb8 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtQml.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtQuick.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtQuick.cpython-311.pyc new file mode 100644 index 0000000..70761f8 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtQuick.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtQuick3D.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtQuick3D.cpython-311.pyc new file mode 100644 index 0000000..88cf7ad Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtQuick3D.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtQuickWidgets.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtQuickWidgets.cpython-311.pyc new file mode 100644 index 0000000..8b45057 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtQuickWidgets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtRemoteObjects.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtRemoteObjects.cpython-311.pyc new file mode 100644 index 0000000..de20bcb Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtRemoteObjects.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtSensors.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtSensors.cpython-311.pyc new file mode 100644 index 0000000..6ea6451 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtSensors.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtSerialPort.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtSerialPort.cpython-311.pyc new file mode 100644 index 0000000..713acba Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtSerialPort.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtSpatialAudio.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtSpatialAudio.cpython-311.pyc new file mode 100644 index 0000000..bc9d3ee Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtSpatialAudio.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtSql.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtSql.cpython-311.pyc new file mode 100644 index 0000000..756dc6a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtSql.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtSvg.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtSvg.cpython-311.pyc new file mode 100644 index 0000000..96152ca Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtSvg.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtSvgWidgets.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtSvgWidgets.cpython-311.pyc new file mode 100644 index 0000000..a640870 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtSvgWidgets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtTest.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtTest.cpython-311.pyc new file mode 100644 index 0000000..3c69001 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtTest.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtTextToSpeech.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtTextToSpeech.cpython-311.pyc new file mode 100644 index 0000000..df634d2 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtTextToSpeech.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtWebChannel.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtWebChannel.cpython-311.pyc new file mode 100644 index 0000000..406b3af Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtWebChannel.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtWebEngineCore.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtWebEngineCore.cpython-311.pyc new file mode 100644 index 0000000..d28c584 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtWebEngineCore.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtWebEngineQuick.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtWebEngineQuick.cpython-311.pyc new file mode 100644 index 0000000..581740a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtWebEngineQuick.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtWebEngineWidgets.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtWebEngineWidgets.cpython-311.pyc new file mode 100644 index 0000000..a9acf76 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtWebEngineWidgets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtWebSockets.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtWebSockets.cpython-311.pyc new file mode 100644 index 0000000..372f799 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtWebSockets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtWidgets.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtWidgets.cpython-311.pyc new file mode 100644 index 0000000..d2b3853 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtWidgets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtXml.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtXml.cpython-311.pyc new file mode 100644 index 0000000..2f46afd Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.QtXml.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.cpython-311.pyc new file mode 100644 index 0000000..6ca321c Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.uic.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.uic.cpython-311.pyc new file mode 100644 index 0000000..eb56386 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PyQt6.uic.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.Qt3DAnimation.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.Qt3DAnimation.cpython-311.pyc new file mode 100644 index 0000000..d7720cc Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.Qt3DAnimation.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.Qt3DCore.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.Qt3DCore.cpython-311.pyc new file mode 100644 index 0000000..b7c9b09 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.Qt3DCore.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.Qt3DExtras.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.Qt3DExtras.cpython-311.pyc new file mode 100644 index 0000000..d08a358 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.Qt3DExtras.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.Qt3DInput.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.Qt3DInput.cpython-311.pyc new file mode 100644 index 0000000..9ee27e6 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.Qt3DInput.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.Qt3DLogic.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.Qt3DLogic.cpython-311.pyc new file mode 100644 index 0000000..8adc214 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.Qt3DLogic.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.Qt3DRender.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.Qt3DRender.cpython-311.pyc new file mode 100644 index 0000000..e39fb60 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.Qt3DRender.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtAxContainer.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtAxContainer.cpython-311.pyc new file mode 100644 index 0000000..56b078f Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtAxContainer.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtCharts.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtCharts.cpython-311.pyc new file mode 100644 index 0000000..2bb7bcc Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtCharts.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtConcurrent.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtConcurrent.cpython-311.pyc new file mode 100644 index 0000000..914048d Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtConcurrent.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtCore.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtCore.cpython-311.pyc new file mode 100644 index 0000000..0c8cdcf Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtCore.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtDataVisualization.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtDataVisualization.cpython-311.pyc new file mode 100644 index 0000000..6f6ec05 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtDataVisualization.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtGui.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtGui.cpython-311.pyc new file mode 100644 index 0000000..05d4dd3 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtGui.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtHelp.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtHelp.cpython-311.pyc new file mode 100644 index 0000000..b5118d0 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtHelp.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtLocation.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtLocation.cpython-311.pyc new file mode 100644 index 0000000..83aeb09 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtLocation.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtMacExtras.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtMacExtras.cpython-311.pyc new file mode 100644 index 0000000..664665e Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtMacExtras.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtMultimedia.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtMultimedia.cpython-311.pyc new file mode 100644 index 0000000..19a5508 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtMultimedia.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtMultimediaWidgets.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtMultimediaWidgets.cpython-311.pyc new file mode 100644 index 0000000..a9cb807 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtMultimediaWidgets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtNetwork.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtNetwork.cpython-311.pyc new file mode 100644 index 0000000..b7ff9aa Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtNetwork.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtOpenGL.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtOpenGL.cpython-311.pyc new file mode 100644 index 0000000..a60e960 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtOpenGL.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtOpenGLFunctions.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtOpenGLFunctions.cpython-311.pyc new file mode 100644 index 0000000..0037fe5 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtOpenGLFunctions.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtPositioning.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtPositioning.cpython-311.pyc new file mode 100644 index 0000000..8520860 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtPositioning.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtPrintSupport.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtPrintSupport.cpython-311.pyc new file mode 100644 index 0000000..7c1b822 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtPrintSupport.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtQml.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtQml.cpython-311.pyc new file mode 100644 index 0000000..ed15bbe Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtQml.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtQuick.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtQuick.cpython-311.pyc new file mode 100644 index 0000000..95848aa Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtQuick.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtQuickControls2.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtQuickControls2.cpython-311.pyc new file mode 100644 index 0000000..2cbe445 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtQuickControls2.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtQuickWidgets.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtQuickWidgets.cpython-311.pyc new file mode 100644 index 0000000..4f7346e Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtQuickWidgets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtRemoteObjects.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtRemoteObjects.cpython-311.pyc new file mode 100644 index 0000000..8bbd0de Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtRemoteObjects.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtScript.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtScript.cpython-311.pyc new file mode 100644 index 0000000..659f9bb Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtScript.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtScriptTools.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtScriptTools.cpython-311.pyc new file mode 100644 index 0000000..297639d Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtScriptTools.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtScxml.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtScxml.cpython-311.pyc new file mode 100644 index 0000000..91c480e Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtScxml.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtSensors.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtSensors.cpython-311.pyc new file mode 100644 index 0000000..2dbee68 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtSensors.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtSerialPort.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtSerialPort.cpython-311.pyc new file mode 100644 index 0000000..9ccc787 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtSerialPort.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtSql.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtSql.cpython-311.pyc new file mode 100644 index 0000000..0e30487 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtSql.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtSvg.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtSvg.cpython-311.pyc new file mode 100644 index 0000000..f4b04b6 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtSvg.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtTest.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtTest.cpython-311.pyc new file mode 100644 index 0000000..f253b03 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtTest.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtTextToSpeech.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtTextToSpeech.cpython-311.pyc new file mode 100644 index 0000000..06e2669 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtTextToSpeech.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtUiTools.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtUiTools.cpython-311.pyc new file mode 100644 index 0000000..9786156 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtUiTools.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtWebChannel.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtWebChannel.cpython-311.pyc new file mode 100644 index 0000000..59e486a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtWebChannel.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtWebEngine.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtWebEngine.cpython-311.pyc new file mode 100644 index 0000000..e9cb677 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtWebEngine.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtWebEngineCore.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtWebEngineCore.cpython-311.pyc new file mode 100644 index 0000000..cd622b3 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtWebEngineCore.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtWebEngineWidgets.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtWebEngineWidgets.cpython-311.pyc new file mode 100644 index 0000000..7859817 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtWebEngineWidgets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtWebKit.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtWebKit.cpython-311.pyc new file mode 100644 index 0000000..2c97583 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtWebKit.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtWebKitWidgets.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtWebKitWidgets.cpython-311.pyc new file mode 100644 index 0000000..0085e0c Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtWebKitWidgets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtWebSockets.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtWebSockets.cpython-311.pyc new file mode 100644 index 0000000..a7d5a9a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtWebSockets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtWidgets.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtWidgets.cpython-311.pyc new file mode 100644 index 0000000..7930a1d Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtWidgets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtWinExtras.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtWinExtras.cpython-311.pyc new file mode 100644 index 0000000..47f62dc Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtWinExtras.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtX11Extras.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtX11Extras.cpython-311.pyc new file mode 100644 index 0000000..9c52161 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtX11Extras.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtXml.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtXml.cpython-311.pyc new file mode 100644 index 0000000..77230cd Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtXml.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtXmlPatterns.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtXmlPatterns.cpython-311.pyc new file mode 100644 index 0000000..3e707d5 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.QtXmlPatterns.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.Qwt5.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.Qwt5.cpython-311.pyc new file mode 100644 index 0000000..142f176 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.Qwt5.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.cpython-311.pyc new file mode 100644 index 0000000..8319e46 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide2.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.Qt3DAnimation.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.Qt3DAnimation.cpython-311.pyc new file mode 100644 index 0000000..1159919 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.Qt3DAnimation.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.Qt3DCore.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.Qt3DCore.cpython-311.pyc new file mode 100644 index 0000000..a33fe29 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.Qt3DCore.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.Qt3DExtras.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.Qt3DExtras.cpython-311.pyc new file mode 100644 index 0000000..b196bce Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.Qt3DExtras.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.Qt3DInput.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.Qt3DInput.cpython-311.pyc new file mode 100644 index 0000000..0395e41 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.Qt3DInput.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.Qt3DLogic.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.Qt3DLogic.cpython-311.pyc new file mode 100644 index 0000000..eec7d06 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.Qt3DLogic.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.Qt3DRender.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.Qt3DRender.cpython-311.pyc new file mode 100644 index 0000000..69c191d Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.Qt3DRender.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtAxContainer.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtAxContainer.cpython-311.pyc new file mode 100644 index 0000000..cbc61b6 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtAxContainer.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtBluetooth.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtBluetooth.cpython-311.pyc new file mode 100644 index 0000000..31dd320 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtBluetooth.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtCharts.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtCharts.cpython-311.pyc new file mode 100644 index 0000000..7f22b3b Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtCharts.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtConcurrent.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtConcurrent.cpython-311.pyc new file mode 100644 index 0000000..5b27451 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtConcurrent.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtCore.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtCore.cpython-311.pyc new file mode 100644 index 0000000..7f80038 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtCore.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtDBus.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtDBus.cpython-311.pyc new file mode 100644 index 0000000..f844a1b Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtDBus.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtDataVisualization.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtDataVisualization.cpython-311.pyc new file mode 100644 index 0000000..90b0dda Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtDataVisualization.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtDesigner.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtDesigner.cpython-311.pyc new file mode 100644 index 0000000..9daa9f4 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtDesigner.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtGraphs.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtGraphs.cpython-311.pyc new file mode 100644 index 0000000..b88e00a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtGraphs.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtGraphsWidgets.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtGraphsWidgets.cpython-311.pyc new file mode 100644 index 0000000..21e30fc Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtGraphsWidgets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtGui.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtGui.cpython-311.pyc new file mode 100644 index 0000000..8d6dea1 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtGui.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtHelp.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtHelp.cpython-311.pyc new file mode 100644 index 0000000..55e417a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtHelp.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtHttpServer.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtHttpServer.cpython-311.pyc new file mode 100644 index 0000000..ee6e8b2 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtHttpServer.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtLocation.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtLocation.cpython-311.pyc new file mode 100644 index 0000000..8afbb5b Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtLocation.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtMultimedia.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtMultimedia.cpython-311.pyc new file mode 100644 index 0000000..b766d22 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtMultimedia.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtMultimediaWidgets.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtMultimediaWidgets.cpython-311.pyc new file mode 100644 index 0000000..5213a3a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtMultimediaWidgets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtNetwork.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtNetwork.cpython-311.pyc new file mode 100644 index 0000000..2be42d9 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtNetwork.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtNetworkAuth.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtNetworkAuth.cpython-311.pyc new file mode 100644 index 0000000..4a9dc80 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtNetworkAuth.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtNfc.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtNfc.cpython-311.pyc new file mode 100644 index 0000000..ac65e70 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtNfc.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtOpenGL.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtOpenGL.cpython-311.pyc new file mode 100644 index 0000000..dbfe058 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtOpenGL.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtOpenGLWidgets.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtOpenGLWidgets.cpython-311.pyc new file mode 100644 index 0000000..97a8cf2 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtOpenGLWidgets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtPdf.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtPdf.cpython-311.pyc new file mode 100644 index 0000000..99e0269 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtPdf.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtPdfWidgets.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtPdfWidgets.cpython-311.pyc new file mode 100644 index 0000000..e962a44 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtPdfWidgets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtPositioning.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtPositioning.cpython-311.pyc new file mode 100644 index 0000000..8fbcaad Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtPositioning.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtPrintSupport.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtPrintSupport.cpython-311.pyc new file mode 100644 index 0000000..fd627f7 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtPrintSupport.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtQml.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtQml.cpython-311.pyc new file mode 100644 index 0000000..fdeeece Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtQml.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtQuick.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtQuick.cpython-311.pyc new file mode 100644 index 0000000..8b1718c Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtQuick.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtQuick3D.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtQuick3D.cpython-311.pyc new file mode 100644 index 0000000..021e1b2 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtQuick3D.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtQuickControls2.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtQuickControls2.cpython-311.pyc new file mode 100644 index 0000000..f759fd6 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtQuickControls2.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtQuickWidgets.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtQuickWidgets.cpython-311.pyc new file mode 100644 index 0000000..047a2b7 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtQuickWidgets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtRemoteObjects.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtRemoteObjects.cpython-311.pyc new file mode 100644 index 0000000..a1851ea Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtRemoteObjects.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtScxml.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtScxml.cpython-311.pyc new file mode 100644 index 0000000..e7828a0 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtScxml.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtSensors.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtSensors.cpython-311.pyc new file mode 100644 index 0000000..935720f Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtSensors.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtSerialBus.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtSerialBus.cpython-311.pyc new file mode 100644 index 0000000..42be6b7 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtSerialBus.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtSerialPort.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtSerialPort.cpython-311.pyc new file mode 100644 index 0000000..938f9f0 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtSerialPort.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtSpatialAudio.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtSpatialAudio.cpython-311.pyc new file mode 100644 index 0000000..a2a276e Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtSpatialAudio.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtSql.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtSql.cpython-311.pyc new file mode 100644 index 0000000..d3b0a0c Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtSql.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtStateMachine.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtStateMachine.cpython-311.pyc new file mode 100644 index 0000000..93f7198 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtStateMachine.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtSvg.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtSvg.cpython-311.pyc new file mode 100644 index 0000000..a3c6bae Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtSvg.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtSvgWidgets.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtSvgWidgets.cpython-311.pyc new file mode 100644 index 0000000..40cc0b4 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtSvgWidgets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtTest.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtTest.cpython-311.pyc new file mode 100644 index 0000000..75023b8 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtTest.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtTextToSpeech.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtTextToSpeech.cpython-311.pyc new file mode 100644 index 0000000..3b006fe Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtTextToSpeech.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtUiTools.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtUiTools.cpython-311.pyc new file mode 100644 index 0000000..c939222 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtUiTools.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtWebChannel.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtWebChannel.cpython-311.pyc new file mode 100644 index 0000000..29d1751 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtWebChannel.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtWebEngineCore.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtWebEngineCore.cpython-311.pyc new file mode 100644 index 0000000..e87cbb4 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtWebEngineCore.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtWebEngineQuick.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtWebEngineQuick.cpython-311.pyc new file mode 100644 index 0000000..4c3ac53 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtWebEngineQuick.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtWebEngineWidgets.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtWebEngineWidgets.cpython-311.pyc new file mode 100644 index 0000000..74ad8ca Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtWebEngineWidgets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtWebSockets.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtWebSockets.cpython-311.pyc new file mode 100644 index 0000000..41ed1a5 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtWebSockets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtWidgets.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtWidgets.cpython-311.pyc new file mode 100644 index 0000000..80d4ab8 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtWidgets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtXml.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtXml.cpython-311.pyc new file mode 100644 index 0000000..be89fee Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.QtXml.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.cpython-311.pyc new file mode 100644 index 0000000..9449e9e Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-PySide6.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-_pyi_rth_utils.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-_pyi_rth_utils.cpython-311.pyc new file mode 100644 index 0000000..b3ce140 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-_pyi_rth_utils.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-_tkinter.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-_tkinter.cpython-311.pyc new file mode 100644 index 0000000..226ea3e Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-_tkinter.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-babel.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-babel.cpython-311.pyc new file mode 100644 index 0000000..50fcb62 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-babel.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-difflib.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-difflib.cpython-311.pyc new file mode 100644 index 0000000..09ba0c4 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-difflib.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-distutils.command.check.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-distutils.command.check.cpython-311.pyc new file mode 100644 index 0000000..1ed3cb1 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-distutils.command.check.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-distutils.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-distutils.cpython-311.pyc new file mode 100644 index 0000000..f0f9cc9 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-distutils.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-distutils.util.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-distutils.util.cpython-311.pyc new file mode 100644 index 0000000..0f38e26 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-distutils.util.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-django.contrib.sessions.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-django.contrib.sessions.cpython-311.pyc new file mode 100644 index 0000000..801b167 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-django.contrib.sessions.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-django.core.cache.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-django.core.cache.cpython-311.pyc new file mode 100644 index 0000000..9114085 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-django.core.cache.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-django.core.mail.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-django.core.mail.cpython-311.pyc new file mode 100644 index 0000000..273b78c Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-django.core.mail.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-django.core.management.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-django.core.management.cpython-311.pyc new file mode 100644 index 0000000..9fcacb3 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-django.core.management.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-django.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-django.cpython-311.pyc new file mode 100644 index 0000000..a241fb0 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-django.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-django.db.backends.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-django.db.backends.cpython-311.pyc new file mode 100644 index 0000000..5e60618 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-django.db.backends.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-django.db.backends.mysql.base.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-django.db.backends.mysql.base.cpython-311.pyc new file mode 100644 index 0000000..7f65246 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-django.db.backends.mysql.base.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-django.db.backends.oracle.base.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-django.db.backends.oracle.base.cpython-311.pyc new file mode 100644 index 0000000..ed63367 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-django.db.backends.oracle.base.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-django.template.loaders.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-django.template.loaders.cpython-311.pyc new file mode 100644 index 0000000..1efc117 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-django.template.loaders.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-encodings.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-encodings.cpython-311.pyc new file mode 100644 index 0000000..b4612c2 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-encodings.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gevent.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gevent.cpython-311.pyc new file mode 100644 index 0000000..af6050c Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gevent.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.cpython-311.pyc new file mode 100644 index 0000000..79a83eb Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Adw.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Adw.cpython-311.pyc new file mode 100644 index 0000000..7e2c505 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Adw.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.AppIndicator3.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.AppIndicator3.cpython-311.pyc new file mode 100644 index 0000000..60afa9b Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.AppIndicator3.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Atk.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Atk.cpython-311.pyc new file mode 100644 index 0000000..2007ae5 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Atk.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.AyatanaAppIndicator3.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.AyatanaAppIndicator3.cpython-311.pyc new file mode 100644 index 0000000..b5984e3 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.AyatanaAppIndicator3.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Champlain.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Champlain.cpython-311.pyc new file mode 100644 index 0000000..f464bec Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Champlain.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Clutter.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Clutter.cpython-311.pyc new file mode 100644 index 0000000..cec1022 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Clutter.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.DBus.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.DBus.cpython-311.pyc new file mode 100644 index 0000000..f6f95ab Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.DBus.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GIRepository.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GIRepository.cpython-311.pyc new file mode 100644 index 0000000..dfbdd70 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GIRepository.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GLib.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GLib.cpython-311.pyc new file mode 100644 index 0000000..3cbc7fb Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GLib.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GModule.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GModule.cpython-311.pyc new file mode 100644 index 0000000..0bf789a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GModule.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GObject.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GObject.cpython-311.pyc new file mode 100644 index 0000000..15c136f Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GObject.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Gdk.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Gdk.cpython-311.pyc new file mode 100644 index 0000000..661b82c Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Gdk.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GdkPixbuf.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GdkPixbuf.cpython-311.pyc new file mode 100644 index 0000000..710cb04 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GdkPixbuf.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Gio.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Gio.cpython-311.pyc new file mode 100644 index 0000000..2ad12ac Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Gio.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Graphene.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Graphene.cpython-311.pyc new file mode 100644 index 0000000..50a644b Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Graphene.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Gsk.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Gsk.cpython-311.pyc new file mode 100644 index 0000000..7b461f3 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Gsk.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Gst.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Gst.cpython-311.pyc new file mode 100644 index 0000000..ac6ec9a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Gst.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstAllocators.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstAllocators.cpython-311.pyc new file mode 100644 index 0000000..83a89ca Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstAllocators.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstApp.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstApp.cpython-311.pyc new file mode 100644 index 0000000..a36fff1 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstApp.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstAudio.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstAudio.cpython-311.pyc new file mode 100644 index 0000000..433d29a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstAudio.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstBadAudio.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstBadAudio.cpython-311.pyc new file mode 100644 index 0000000..7e2c3a8 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstBadAudio.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstBase.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstBase.cpython-311.pyc new file mode 100644 index 0000000..260228f Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstBase.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstCheck.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstCheck.cpython-311.pyc new file mode 100644 index 0000000..50709e9 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstCheck.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstCodecs.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstCodecs.cpython-311.pyc new file mode 100644 index 0000000..0a0db6b Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstCodecs.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstController.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstController.cpython-311.pyc new file mode 100644 index 0000000..6e4b2ce Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstController.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstGL.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstGL.cpython-311.pyc new file mode 100644 index 0000000..e6ac2ec Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstGL.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstGLEGL.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstGLEGL.cpython-311.pyc new file mode 100644 index 0000000..0417118 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstGLEGL.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstGLWayland.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstGLWayland.cpython-311.pyc new file mode 100644 index 0000000..f8c9d2e Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstGLWayland.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstGLX11.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstGLX11.cpython-311.pyc new file mode 100644 index 0000000..d906df5 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstGLX11.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstInsertBin.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstInsertBin.cpython-311.pyc new file mode 100644 index 0000000..826c470 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstInsertBin.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstMpegts.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstMpegts.cpython-311.pyc new file mode 100644 index 0000000..bb94722 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstMpegts.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstNet.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstNet.cpython-311.pyc new file mode 100644 index 0000000..d438e06 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstNet.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstPbutils.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstPbutils.cpython-311.pyc new file mode 100644 index 0000000..f9ad115 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstPbutils.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstPlay.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstPlay.cpython-311.pyc new file mode 100644 index 0000000..7b807fd Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstPlay.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstPlayer.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstPlayer.cpython-311.pyc new file mode 100644 index 0000000..c146040 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstPlayer.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstRtp.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstRtp.cpython-311.pyc new file mode 100644 index 0000000..0f5affe Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstRtp.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstRtsp.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstRtsp.cpython-311.pyc new file mode 100644 index 0000000..eb7c478 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstRtsp.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstRtspServer.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstRtspServer.cpython-311.pyc new file mode 100644 index 0000000..3d88940 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstRtspServer.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstSdp.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstSdp.cpython-311.pyc new file mode 100644 index 0000000..eed30cf Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstSdp.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstTag.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstTag.cpython-311.pyc new file mode 100644 index 0000000..86692c7 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstTag.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstTranscoder.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstTranscoder.cpython-311.pyc new file mode 100644 index 0000000..e1334c8 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstTranscoder.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstVideo.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstVideo.cpython-311.pyc new file mode 100644 index 0000000..82efa38 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstVideo.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstVulkan.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstVulkan.cpython-311.pyc new file mode 100644 index 0000000..947686a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstVulkan.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstVulkanWayland.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstVulkanWayland.cpython-311.pyc new file mode 100644 index 0000000..4c9d6f2 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstVulkanWayland.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstVulkanXCB.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstVulkanXCB.cpython-311.pyc new file mode 100644 index 0000000..af90d5a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstVulkanXCB.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstWebRTC.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstWebRTC.cpython-311.pyc new file mode 100644 index 0000000..417ff9c Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GstWebRTC.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Gtk.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Gtk.cpython-311.pyc new file mode 100644 index 0000000..d93bf5c Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Gtk.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GtkChamplain.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GtkChamplain.cpython-311.pyc new file mode 100644 index 0000000..a074e91 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GtkChamplain.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GtkClutter.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GtkClutter.cpython-311.pyc new file mode 100644 index 0000000..5e6acff Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GtkClutter.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GtkSource.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GtkSource.cpython-311.pyc new file mode 100644 index 0000000..9b9089a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GtkSource.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GtkosxApplication.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GtkosxApplication.cpython-311.pyc new file mode 100644 index 0000000..54561e3 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.GtkosxApplication.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.HarfBuzz.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.HarfBuzz.cpython-311.pyc new file mode 100644 index 0000000..b07c90b Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.HarfBuzz.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Pango.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Pango.cpython-311.pyc new file mode 100644 index 0000000..5efa6f4 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.Pango.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.PangoCairo.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.PangoCairo.cpython-311.pyc new file mode 100644 index 0000000..8c6674d Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.PangoCairo.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.cairo.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.cairo.cpython-311.pyc new file mode 100644 index 0000000..649add2 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.cairo.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.freetype2.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.freetype2.cpython-311.pyc new file mode 100644 index 0000000..efbd539 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.freetype2.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.xlib.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.xlib.cpython-311.pyc new file mode 100644 index 0000000..fc719b4 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-gi.repository.xlib.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-heapq.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-heapq.cpython-311.pyc new file mode 100644 index 0000000..13fe51e Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-heapq.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-idlelib.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-idlelib.cpython-311.pyc new file mode 100644 index 0000000..3e1e1ed Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-idlelib.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-importlib_metadata.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-importlib_metadata.cpython-311.pyc new file mode 100644 index 0000000..281dbc5 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-importlib_metadata.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-importlib_resources.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-importlib_resources.cpython-311.pyc new file mode 100644 index 0000000..0a4dc7a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-importlib_resources.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-keyring.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-keyring.cpython-311.pyc new file mode 100644 index 0000000..bd7684d Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-keyring.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-kivy.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-kivy.cpython-311.pyc new file mode 100644 index 0000000..3c4bf2c Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-kivy.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-lib2to3.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-lib2to3.cpython-311.pyc new file mode 100644 index 0000000..ae5f818 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-lib2to3.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-matplotlib.backend_bases.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-matplotlib.backend_bases.cpython-311.pyc new file mode 100644 index 0000000..0839670 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-matplotlib.backend_bases.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-matplotlib.backends.backend_qtagg.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-matplotlib.backends.backend_qtagg.cpython-311.pyc new file mode 100644 index 0000000..9cf74d5 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-matplotlib.backends.backend_qtagg.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-matplotlib.backends.backend_qtcairo.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-matplotlib.backends.backend_qtcairo.cpython-311.pyc new file mode 100644 index 0000000..1fe63b1 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-matplotlib.backends.backend_qtcairo.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-matplotlib.backends.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-matplotlib.backends.cpython-311.pyc new file mode 100644 index 0000000..856f1ba Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-matplotlib.backends.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-matplotlib.backends.qt_compat.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-matplotlib.backends.qt_compat.cpython-311.pyc new file mode 100644 index 0000000..b059eab Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-matplotlib.backends.qt_compat.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-matplotlib.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-matplotlib.cpython-311.pyc new file mode 100644 index 0000000..310f3bd Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-matplotlib.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-matplotlib.numerix.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-matplotlib.numerix.cpython-311.pyc new file mode 100644 index 0000000..9bdd81b Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-matplotlib.numerix.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-matplotlib.pyplot.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-matplotlib.pyplot.cpython-311.pyc new file mode 100644 index 0000000..8a00a5d Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-matplotlib.pyplot.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-multiprocessing.util.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-multiprocessing.util.cpython-311.pyc new file mode 100644 index 0000000..b39874a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-multiprocessing.util.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-numpy.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-numpy.cpython-311.pyc new file mode 100644 index 0000000..0bbeb43 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-numpy.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-packaging.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-packaging.cpython-311.pyc new file mode 100644 index 0000000..e43eafa Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-packaging.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-pandas.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-pandas.cpython-311.pyc new file mode 100644 index 0000000..f9565dd Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-pandas.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-pandas.io.clipboard.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-pandas.io.clipboard.cpython-311.pyc new file mode 100644 index 0000000..7a2f767 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-pandas.io.clipboard.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-pandas.io.formats.style.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-pandas.io.formats.style.cpython-311.pyc new file mode 100644 index 0000000..11e21e5 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-pandas.io.formats.style.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-pandas.plotting.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-pandas.plotting.cpython-311.pyc new file mode 100644 index 0000000..5b43b1a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-pandas.plotting.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-pickle.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-pickle.cpython-311.pyc new file mode 100644 index 0000000..1b47d84 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-pickle.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-pkg_resources.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-pkg_resources.cpython-311.pyc new file mode 100644 index 0000000..0397660 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-pkg_resources.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-platform.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-platform.cpython-311.pyc new file mode 100644 index 0000000..de73437 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-platform.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-pygments.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-pygments.cpython-311.pyc new file mode 100644 index 0000000..b4bdcc8 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-pygments.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-pytz.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-pytz.cpython-311.pyc new file mode 100644 index 0000000..d281de6 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-pytz.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-pytzdata.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-pytzdata.cpython-311.pyc new file mode 100644 index 0000000..07af03d Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-pytzdata.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-qtawesome.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-qtawesome.cpython-311.pyc new file mode 100644 index 0000000..97e375c Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-qtawesome.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-qtpy.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-qtpy.cpython-311.pyc new file mode 100644 index 0000000..a931af8 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-qtpy.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-scapy.layers.all.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-scapy.layers.all.cpython-311.pyc new file mode 100644 index 0000000..8c4829d Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-scapy.layers.all.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-scipy.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-scipy.cpython-311.pyc new file mode 100644 index 0000000..1e03f62 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-scipy.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-scipy.io.matlab.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-scipy.io.matlab.cpython-311.pyc new file mode 100644 index 0000000..8b4e267 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-scipy.io.matlab.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-scipy.linalg.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-scipy.linalg.cpython-311.pyc new file mode 100644 index 0000000..5d40aad Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-scipy.linalg.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-scipy.sparse.csgraph.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-scipy.sparse.csgraph.cpython-311.pyc new file mode 100644 index 0000000..34e2c6b Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-scipy.sparse.csgraph.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-scipy.spatial.transform.rotation.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-scipy.spatial.transform.rotation.cpython-311.pyc new file mode 100644 index 0000000..39e1c00 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-scipy.spatial.transform.rotation.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-scipy.special._ellip_harm_2.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-scipy.special._ellip_harm_2.cpython-311.pyc new file mode 100644 index 0000000..6ce3348 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-scipy.special._ellip_harm_2.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-scipy.special._ufuncs.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-scipy.special._ufuncs.cpython-311.pyc new file mode 100644 index 0000000..f83b261 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-scipy.special._ufuncs.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-scipy.stats._stats.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-scipy.stats._stats.cpython-311.pyc new file mode 100644 index 0000000..423eb5b Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-scipy.stats._stats.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-scrapy.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-scrapy.cpython-311.pyc new file mode 100644 index 0000000..817e029 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-scrapy.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-setuptools._vendor.importlib_metadata.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-setuptools._vendor.importlib_metadata.cpython-311.pyc new file mode 100644 index 0000000..2a3fbf6 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-setuptools._vendor.importlib_metadata.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-setuptools._vendor.jaraco.text.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-setuptools._vendor.jaraco.text.cpython-311.pyc new file mode 100644 index 0000000..86a2beb Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-setuptools._vendor.jaraco.text.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-setuptools.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-setuptools.cpython-311.pyc new file mode 100644 index 0000000..b35be70 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-setuptools.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-shelve.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-shelve.cpython-311.pyc new file mode 100644 index 0000000..63203a9 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-shelve.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-shiboken6.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-shiboken6.cpython-311.pyc new file mode 100644 index 0000000..43a1f57 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-shiboken6.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-sphinx.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-sphinx.cpython-311.pyc new file mode 100644 index 0000000..8e527de Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-sphinx.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-sqlalchemy.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-sqlalchemy.cpython-311.pyc new file mode 100644 index 0000000..fd098f5 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-sqlalchemy.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-sqlite3.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-sqlite3.cpython-311.pyc new file mode 100644 index 0000000..dd436ee Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-sqlite3.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-sysconfig.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-sysconfig.cpython-311.pyc new file mode 100644 index 0000000..bc7907d Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-sysconfig.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-wcwidth.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-wcwidth.cpython-311.pyc new file mode 100644 index 0000000..86d157c Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-wcwidth.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-win32ctypes.core.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-win32ctypes.core.cpython-311.pyc new file mode 100644 index 0000000..ee07b74 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-win32ctypes.core.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-xml.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-xml.cpython-311.pyc new file mode 100644 index 0000000..f1d1c51 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-xml.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-xml.dom.domreg.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-xml.dom.domreg.cpython-311.pyc new file mode 100644 index 0000000..c1601fc Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-xml.dom.domreg.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-xml.etree.cElementTree.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-xml.etree.cElementTree.cpython-311.pyc new file mode 100644 index 0000000..dec96f6 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-xml.etree.cElementTree.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-zope.interface.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-zope.interface.cpython-311.pyc new file mode 100644 index 0000000..37e60c8 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/__pycache__/hook-zope.interface.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PIL.Image.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PIL.Image.py new file mode 100644 index 0000000..1d9e029 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PIL.Image.py @@ -0,0 +1,17 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +# This hook was tested with Pillow 2.9.0 (Maintained fork of PIL): https://pypi.python.org/pypi/Pillow + +from PyInstaller.utils.hooks import collect_submodules + +# Include all PIL image plugins - module names containing 'ImagePlugin'. e.g. PIL.JpegImagePlugin +hiddenimports = collect_submodules('PIL', lambda name: 'ImagePlugin' in name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PIL.ImageFilter.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PIL.ImageFilter.py new file mode 100644 index 0000000..528694b --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PIL.ImageFilter.py @@ -0,0 +1,13 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +# Only used if installed, not mean to pull in numpy. +excludedimports = ["numpy"] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PIL.SpiderImagePlugin.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PIL.SpiderImagePlugin.py new file mode 100644 index 0000000..1b6466f --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PIL.SpiderImagePlugin.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +# PIL's SpiderImagePlugin features a tkPhotoImage() method, which imports ImageTk (and thus brings in the whole Tcl/Tk +# library). Assume that if people are really using tkinter in their application, they will also import it directly. +excludedimports = ['tkinter'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PIL.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PIL.py new file mode 100644 index 0000000..b7a6849 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PIL.py @@ -0,0 +1,21 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +# This hook was tested with Pillow 2.9.0 (Maintained fork of PIL): +# https://pypi.python.org/pypi/Pillow + +# Ignore tkinter to prevent inclusion of Tcl/Tk library and other GUI libraries. Assume that if people are really using +# tkinter in their application, they will also import it directly and thus PyInstaller bundles the right GUI library. +excludedimports = ['tkinter', 'PyQt5', 'PySide2', 'PyQt6', 'PySide6'] + +# Similarly, prevent inclusion of IPython, which in turn ends up pulling in whole matplotlib, along with its optional +# GUI library dependencies. +excludedimports += ['IPython'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QAxContainer.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QAxContainer.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QAxContainer.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.Qsci.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.Qsci.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.Qsci.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.Qt.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.Qt.py new file mode 100644 index 0000000..3520f3c --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.Qt.py @@ -0,0 +1,29 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +# When PyQt5.Qt is imported it implies the import of all PyQt5 modules. See +# http://pyqt.sourceforge.net/Docs/PyQt5/Qt.html. +import os + +from PyInstaller.utils.hooks import get_module_file_attribute + +# Only do this if PyQt5 is found. +mfi = get_module_file_attribute('PyQt5') +if mfi: + # Determine the name of all these modules by looking in the PyQt5 directory. + hiddenimports = [] + for f in os.listdir(os.path.dirname(mfi)): + root, ext = os.path.splitext(os.path.basename(f)) + if root.startswith('Qt') and root != 'Qt': + # On Linux and OS X, PyQt 5.14.1 has a ``.abi3`` suffix on all library names. Remove it. + if root.endswith('.abi3'): + root = root[:-5] + hiddenimports.append('PyQt5.' + root) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.Qt3DAnimation.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.Qt3DAnimation.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.Qt3DAnimation.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.Qt3DCore.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.Qt3DCore.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.Qt3DCore.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.Qt3DExtras.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.Qt3DExtras.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.Qt3DExtras.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.Qt3DInput.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.Qt3DInput.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.Qt3DInput.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.Qt3DLogic.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.Qt3DLogic.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.Qt3DLogic.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.Qt3DRender.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.Qt3DRender.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.Qt3DRender.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtBluetooth.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtBluetooth.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtBluetooth.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtChart.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtChart.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtChart.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtCore.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtCore.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtCore.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtDBus.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtDBus.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtDBus.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtDataVisualization.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtDataVisualization.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtDataVisualization.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtDesigner.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtDesigner.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtDesigner.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtGui.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtGui.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtGui.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtHelp.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtHelp.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtHelp.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtLocation.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtLocation.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtLocation.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtMacExtras.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtMacExtras.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtMacExtras.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtMultimedia.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtMultimedia.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtMultimedia.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtMultimediaWidgets.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtMultimediaWidgets.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtMultimediaWidgets.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtNetwork.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtNetwork.py new file mode 100644 index 0000000..1c8cc67 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtNetwork.py @@ -0,0 +1,15 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies, pyqt5_library_info + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) +binaries += pyqt5_library_info.collect_qtnetwork_files() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtNetworkAuth.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtNetworkAuth.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtNetworkAuth.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtNfc.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtNfc.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtNfc.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtOpenGL.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtOpenGL.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtOpenGL.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtPositioning.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtPositioning.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtPositioning.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtPrintSupport.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtPrintSupport.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtPrintSupport.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtPurchasing.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtPurchasing.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtPurchasing.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtQml.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtQml.py new file mode 100644 index 0000000..718d323 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtQml.py @@ -0,0 +1,17 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies, pyqt5_library_info + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) +qml_binaries, qml_datas = pyqt5_library_info.collect_qtqml_files() +binaries += qml_binaries +datas += qml_datas diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtQuick.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtQuick.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtQuick.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtQuick3D.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtQuick3D.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtQuick3D.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtQuickWidgets.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtQuickWidgets.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtQuickWidgets.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtRemoteObjects.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtRemoteObjects.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtRemoteObjects.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtScript.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtScript.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtScript.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtSensors.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtSensors.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtSensors.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtSerialPort.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtSerialPort.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtSerialPort.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtSql.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtSql.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtSql.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtSvg.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtSvg.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtSvg.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtTest.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtTest.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtTest.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtTextToSpeech.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtTextToSpeech.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtTextToSpeech.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtWebChannel.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtWebChannel.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtWebChannel.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtWebEngine.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtWebEngine.py new file mode 100644 index 0000000..7b67e1b --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtWebEngine.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2014-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtWebEngineCore.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtWebEngineCore.py new file mode 100644 index 0000000..f575e0d --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtWebEngineCore.py @@ -0,0 +1,22 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2014-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import \ + add_qt5_dependencies, pyqt5_library_info + +# Ensure PyQt5 is importable before adding info depending on it. +if pyqt5_library_info.version is not None: + hiddenimports, binaries, datas = add_qt5_dependencies(__file__) + + # Include helper process executable, translations, and resources. + webengine_binaries, webengine_datas = pyqt5_library_info.collect_qtwebengine_files() + binaries += webengine_binaries + datas += webengine_datas diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtWebEngineWidgets.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtWebEngineWidgets.py new file mode 100644 index 0000000..7b67e1b --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtWebEngineWidgets.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2014-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtWebKit.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtWebKit.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtWebKit.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtWebKitWidgets.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtWebKitWidgets.py new file mode 100644 index 0000000..7b67e1b --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtWebKitWidgets.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2014-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtWebSockets.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtWebSockets.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtWebSockets.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtWidgets.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtWidgets.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtWidgets.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtWinExtras.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtWinExtras.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtWinExtras.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtX11Extras.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtX11Extras.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtX11Extras.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtXml.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtXml.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtXml.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtXmlPatterns.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtXmlPatterns.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.QtXmlPatterns.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.py new file mode 100644 index 0000000..2325577 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.py @@ -0,0 +1,29 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import pyqt5_library_info, ensure_single_qt_bindings_package + +# Allow only one Qt bindings package to be collected in frozen application. +ensure_single_qt_bindings_package("PyQt5") + +# Only proceed if PyQt5 can be imported. +if pyqt5_library_info.version is not None: + hiddenimports = [ + # PyQt5.10 and earlier uses sip in an separate package; + 'sip', + # PyQt5.11 and later provides SIP in a private package. Support both. + 'PyQt5.sip', + # Imported via __import__ in PyQt5/__init__.py + 'pkgutil', + ] + + # Collect required Qt binaries. + binaries = pyqt5_library_info.collect_extra_binaries() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.uic.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.uic.py new file mode 100644 index 0000000..e4474dd --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt5.uic.py @@ -0,0 +1,17 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks import collect_data_files + +# We need to include modules in PyQt5.uic.widget-plugins, so they can be dynamically loaded by uic. They should be +# included as separate (data-like) files, so they can be found by os.listdir and friends. However, as this directory +# is not a package, refer to it using the package (PyQt5.uic) followed by the subdirectory name (``widget-plugins/``). +datas = collect_data_files('PyQt5.uic', True, 'widget-plugins') diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QAxContainer.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QAxContainer.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QAxContainer.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.Qsci.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.Qsci.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.Qsci.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.Qt3DAnimation.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.Qt3DAnimation.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.Qt3DAnimation.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.Qt3DCore.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.Qt3DCore.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.Qt3DCore.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.Qt3DExtras.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.Qt3DExtras.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.Qt3DExtras.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.Qt3DInput.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.Qt3DInput.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.Qt3DInput.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.Qt3DLogic.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.Qt3DLogic.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.Qt3DLogic.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.Qt3DRender.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.Qt3DRender.py new file mode 100644 index 0000000..58ac06d --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.Qt3DRender.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) + +hiddenimports += ["PyQt6.QtOpenGL"] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtBluetooth.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtBluetooth.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtBluetooth.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtCharts.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtCharts.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtCharts.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtCore.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtCore.py new file mode 100644 index 0000000..edd5cd1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtCore.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtDBus.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtDBus.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtDBus.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtDataVisualization.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtDataVisualization.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtDataVisualization.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtDesigner.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtDesigner.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtDesigner.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtGui.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtGui.py new file mode 100644 index 0000000..edd5cd1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtGui.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtHelp.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtHelp.py new file mode 100644 index 0000000..edd5cd1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtHelp.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtMultimedia.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtMultimedia.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtMultimedia.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtMultimediaWidgets.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtMultimediaWidgets.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtMultimediaWidgets.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtNetwork.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtNetwork.py new file mode 100644 index 0000000..c780c7c --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtNetwork.py @@ -0,0 +1,15 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies, pyqt6_library_info + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) +binaries += pyqt6_library_info.collect_qtnetwork_files() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtNetworkAuth.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtNetworkAuth.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtNetworkAuth.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtNfc.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtNfc.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtNfc.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtOpenGL.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtOpenGL.py new file mode 100644 index 0000000..edd5cd1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtOpenGL.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtOpenGLWidgets.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtOpenGLWidgets.py new file mode 100644 index 0000000..edd5cd1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtOpenGLWidgets.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtPdf.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtPdf.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtPdf.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtPdfWidgets.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtPdfWidgets.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtPdfWidgets.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtPositioning.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtPositioning.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtPositioning.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtPrintSupport.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtPrintSupport.py new file mode 100644 index 0000000..edd5cd1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtPrintSupport.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtQml.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtQml.py new file mode 100644 index 0000000..024696a --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtQml.py @@ -0,0 +1,17 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies, pyqt6_library_info + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) +qml_binaries, qml_datas = pyqt6_library_info.collect_qtqml_files() +binaries += qml_binaries +datas += qml_datas diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtQuick.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtQuick.py new file mode 100644 index 0000000..edd5cd1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtQuick.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtQuick3D.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtQuick3D.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtQuick3D.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtQuickWidgets.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtQuickWidgets.py new file mode 100644 index 0000000..edd5cd1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtQuickWidgets.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtRemoteObjects.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtRemoteObjects.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtRemoteObjects.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtSensors.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtSensors.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtSensors.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtSerialPort.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtSerialPort.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtSerialPort.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtSpatialAudio.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtSpatialAudio.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtSpatialAudio.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtSql.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtSql.py new file mode 100644 index 0000000..edd5cd1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtSql.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtSvg.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtSvg.py new file mode 100644 index 0000000..edd5cd1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtSvg.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtSvgWidgets.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtSvgWidgets.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtSvgWidgets.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtTest.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtTest.py new file mode 100644 index 0000000..edd5cd1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtTest.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtTextToSpeech.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtTextToSpeech.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtTextToSpeech.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtWebChannel.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtWebChannel.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtWebChannel.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtWebEngineCore.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtWebEngineCore.py new file mode 100644 index 0000000..a749a7c --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtWebEngineCore.py @@ -0,0 +1,27 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2014-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import \ + add_qt6_dependencies, pyqt6_library_info + +# Ensure PyQt6 is importable before adding info depending on it. +if pyqt6_library_info.version is not None: + # Qt6 prior to 6.2.2 contains a bug that makes it incompatible with the way PyInstaller collects + # QtWebEngine shared libraries and resources. So exit here and now instead of producing a defunct build. + if pyqt6_library_info.version < [6, 2, 2]: + raise SystemExit("Error: PyInstaller's QtWebEngine support requires Qt6 6.2.2 or later!") + + hiddenimports, binaries, datas = add_qt6_dependencies(__file__) + + # Include helper process executable, translations, and resources. + webengine_binaries, webengine_datas = pyqt6_library_info.collect_qtwebengine_files() + binaries += webengine_binaries + datas += webengine_datas diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtWebEngineQuick.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtWebEngineQuick.py new file mode 100644 index 0000000..19083de --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtWebEngineQuick.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2014-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtWebEngineWidgets.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtWebEngineWidgets.py new file mode 100644 index 0000000..19083de --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtWebEngineWidgets.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2014-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtWebSockets.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtWebSockets.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtWebSockets.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtWidgets.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtWidgets.py new file mode 100644 index 0000000..edd5cd1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtWidgets.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtXml.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtXml.py new file mode 100644 index 0000000..edd5cd1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.QtXml.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.py new file mode 100644 index 0000000..b9e2f51 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.py @@ -0,0 +1,26 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import pyqt6_library_info, ensure_single_qt_bindings_package + +# Allow only one Qt bindings package to be collected in frozen application. +ensure_single_qt_bindings_package("PyQt6") + +# Only proceed if PyQt6 can be imported. +if pyqt6_library_info.version is not None: + hiddenimports = [ + 'PyQt6.sip', + # Imported via __import__ in PyQt6/__init__.py + 'pkgutil', + ] + + # Collect required Qt binaries. + binaries = pyqt6_library_info.collect_extra_binaries() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.uic.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.uic.py new file mode 100644 index 0000000..7744cbc --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PyQt6.uic.py @@ -0,0 +1,17 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks import collect_data_files + +# We need to include modules in PyQt6.uic.widget-plugins, so they can be dynamically loaded by uic. They should be +# included as separate (data-like) files, so they can be found by os.listdir and friends. However, as this directory +# is not a package, refer to it using the package (PyQt6.uic) followed by the subdirectory name (``widget-plugins/``). +datas = collect_data_files('PyQt6.uic', True, 'widget-plugins') diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.Qt3DAnimation.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.Qt3DAnimation.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.Qt3DAnimation.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.Qt3DCore.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.Qt3DCore.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.Qt3DCore.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.Qt3DExtras.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.Qt3DExtras.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.Qt3DExtras.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.Qt3DInput.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.Qt3DInput.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.Qt3DInput.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.Qt3DLogic.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.Qt3DLogic.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.Qt3DLogic.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.Qt3DRender.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.Qt3DRender.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.Qt3DRender.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtAxContainer.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtAxContainer.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtAxContainer.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtCharts.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtCharts.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtCharts.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtConcurrent.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtConcurrent.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtConcurrent.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtCore.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtCore.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtCore.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtDataVisualization.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtDataVisualization.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtDataVisualization.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtGui.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtGui.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtGui.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtHelp.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtHelp.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtHelp.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtLocation.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtLocation.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtLocation.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtMacExtras.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtMacExtras.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtMacExtras.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtMultimedia.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtMultimedia.py new file mode 100644 index 0000000..1f3f908 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtMultimedia.py @@ -0,0 +1,19 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) + +# Using PySide2 true_properties ("from __feature__ import true_properties") causes a hidden dependency on +# QtMultimediaWidgets python module: +# https://github.com/qtproject/pyside-pyside-setup/blob/5.15.2/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/mapping.py#L577-L586 +hiddenimports += ['PySide2.QtMultimediaWidgets'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtMultimediaWidgets.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtMultimediaWidgets.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtMultimediaWidgets.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtNetwork.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtNetwork.py new file mode 100644 index 0000000..4e62091 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtNetwork.py @@ -0,0 +1,15 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies, pyside2_library_info + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) +binaries += pyside2_library_info.collect_qtnetwork_files() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtOpenGL.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtOpenGL.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtOpenGL.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtOpenGLFunctions.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtOpenGLFunctions.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtOpenGLFunctions.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtPositioning.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtPositioning.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtPositioning.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtPrintSupport.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtPrintSupport.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtPrintSupport.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtQml.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtQml.py new file mode 100644 index 0000000..a9f7162 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtQml.py @@ -0,0 +1,19 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies, pyside2_library_info + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) +qml_binaries, qml_datas = pyside2_library_info.collect_qtqml_files() +binaries += qml_binaries +datas += qml_datas + +hiddenimports += ["PySide2.QtGui"] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtQuick.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtQuick.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtQuick.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtQuickControls2.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtQuickControls2.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtQuickControls2.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtQuickWidgets.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtQuickWidgets.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtQuickWidgets.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtRemoteObjects.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtRemoteObjects.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtRemoteObjects.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtScript.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtScript.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtScript.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtScriptTools.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtScriptTools.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtScriptTools.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtScxml.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtScxml.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtScxml.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtSensors.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtSensors.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtSensors.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtSerialPort.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtSerialPort.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtSerialPort.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtSql.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtSql.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtSql.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtSvg.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtSvg.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtSvg.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtTest.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtTest.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtTest.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtTextToSpeech.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtTextToSpeech.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtTextToSpeech.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtUiTools.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtUiTools.py new file mode 100644 index 0000000..9f47776 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtUiTools.py @@ -0,0 +1,15 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) +hiddenimports += ['PySide2.QtXml'] # Not inferred from dynamic lib analysis diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtWebChannel.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtWebChannel.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtWebChannel.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtWebEngine.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtWebEngine.py new file mode 100644 index 0000000..7b67e1b --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtWebEngine.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2014-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtWebEngineCore.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtWebEngineCore.py new file mode 100644 index 0000000..afb578e --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtWebEngineCore.py @@ -0,0 +1,22 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2014-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import \ + add_qt5_dependencies, pyside2_library_info + +# Ensure PySide2 is importable before adding info depending on it. +if pyside2_library_info.version is not None: + hiddenimports, binaries, datas = add_qt5_dependencies(__file__) + + # Include helper process executable, translations, and resources. + webengine_binaries, webengine_datas = pyside2_library_info.collect_qtwebengine_files() + binaries += webengine_binaries + datas += webengine_datas diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtWebEngineWidgets.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtWebEngineWidgets.py new file mode 100644 index 0000000..7b67e1b --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtWebEngineWidgets.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2014-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtWebKit.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtWebKit.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtWebKit.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtWebKitWidgets.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtWebKitWidgets.py new file mode 100644 index 0000000..7b67e1b --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtWebKitWidgets.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2014-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtWebSockets.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtWebSockets.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtWebSockets.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtWidgets.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtWidgets.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtWidgets.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtWinExtras.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtWinExtras.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtWinExtras.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtX11Extras.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtX11Extras.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtX11Extras.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtXml.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtXml.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtXml.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtXmlPatterns.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtXmlPatterns.py new file mode 100644 index 0000000..51258b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.QtXmlPatterns.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt5_dependencies + +hiddenimports, binaries, datas = add_qt5_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.Qwt5.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.Qwt5.py new file mode 100644 index 0000000..57f3c22 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.Qwt5.py @@ -0,0 +1,31 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller import isolated + +hiddenimports = ['PySide2.QtCore', 'PySide2.QtWidgets', 'PySide2.QtGui', 'PySide2.QtSvg'] + + +@isolated.decorate +def conditional_imports(): + from PySide2 import Qwt5 + + out = [] + if hasattr(Qwt5, "toNumpy"): + out.append("numpy") + if hasattr(Qwt5, "toNumeric"): + out.append("numeric") + if hasattr(Qwt5, "toNumarray"): + out.append("numarray") + return out + + +hiddenimports += conditional_imports() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.py new file mode 100644 index 0000000..aa7a714 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide2.py @@ -0,0 +1,25 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import pyside2_library_info, ensure_single_qt_bindings_package + +# Allow only one Qt bindings package to be collected in frozen application. +ensure_single_qt_bindings_package("PySide2") + +# Only proceed if PySide2 can be imported. +if pyside2_library_info.version is not None: + hiddenimports = ['shiboken2', 'inspect'] + if pyside2_library_info.version < [5, 15]: + # The shiboken2 bootstrap in earlier releases requires __future__ in addition to inspect + hiddenimports += ['__future__'] + + # Collect required Qt binaries. + binaries = pyside2_library_info.collect_extra_binaries() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.Qt3DAnimation.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.Qt3DAnimation.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.Qt3DAnimation.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.Qt3DCore.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.Qt3DCore.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.Qt3DCore.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.Qt3DExtras.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.Qt3DExtras.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.Qt3DExtras.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.Qt3DInput.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.Qt3DInput.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.Qt3DInput.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.Qt3DLogic.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.Qt3DLogic.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.Qt3DLogic.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.Qt3DRender.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.Qt3DRender.py new file mode 100644 index 0000000..2bb9b83 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.Qt3DRender.py @@ -0,0 +1,20 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies, pyside6_library_info + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) + +# In PySide 6.7.0, Qt3DRender module added a reference to QtOpenGL type system. The hidden import is required on +# Windows, while on macOS and Linux we seem to pick it up automatically due to the corresponding Qt shared library +# appearing among binary dependencies. Keep it around on all OSes, though - just in case this ever changes. +if pyside6_library_info.version is not None and pyside6_library_info.version >= [6, 7]: + hiddenimports += ['PySide6.QtOpenGL'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtAxContainer.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtAxContainer.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtAxContainer.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtBluetooth.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtBluetooth.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtBluetooth.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtCharts.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtCharts.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtCharts.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtConcurrent.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtConcurrent.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtConcurrent.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtCore.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtCore.py new file mode 100644 index 0000000..edd5cd1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtCore.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtDBus.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtDBus.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtDBus.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtDataVisualization.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtDataVisualization.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtDataVisualization.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtDesigner.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtDesigner.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtDesigner.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtGraphs.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtGraphs.py new file mode 100644 index 0000000..00941c0 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtGraphs.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtGraphsWidgets.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtGraphsWidgets.py new file mode 100644 index 0000000..91ae027 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtGraphsWidgets.py @@ -0,0 +1,17 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2024, 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) + +# These dependencies cannot seem to be inferred from linked libraries. +hiddenimports += ['PySide6.QtQuickWidgets', 'PySide6.QtGraphs'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtGui.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtGui.py new file mode 100644 index 0000000..edd5cd1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtGui.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtHelp.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtHelp.py new file mode 100644 index 0000000..edd5cd1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtHelp.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtHttpServer.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtHttpServer.py new file mode 100644 index 0000000..790cb11 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtHttpServer.py @@ -0,0 +1,18 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) + +# This seems to be necessary on Windows; on other OSes, it is inferred automatically because the extension is linked +# against the Qt6Concurrent shared library. +hiddenimports += ['PySide6.QtConcurrent'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtLocation.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtLocation.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtLocation.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtMultimedia.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtMultimedia.py new file mode 100644 index 0000000..0c2d31b --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtMultimedia.py @@ -0,0 +1,19 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) + +# Using PySide6 true_properties ("from __feature__ import true_properties") causes a hidden dependency on +# QtMultimediaWidgets python module: +# https://github.com/qtproject/pyside-pyside-setup/blob/v6.2.2.1/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py#L614-L627 +hiddenimports += ['PySide6.QtMultimediaWidgets'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtMultimediaWidgets.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtMultimediaWidgets.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtMultimediaWidgets.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtNetwork.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtNetwork.py new file mode 100644 index 0000000..a216ecd --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtNetwork.py @@ -0,0 +1,15 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies, pyside6_library_info + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) +binaries += pyside6_library_info.collect_qtnetwork_files() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtNetworkAuth.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtNetworkAuth.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtNetworkAuth.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtNfc.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtNfc.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtNfc.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtOpenGL.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtOpenGL.py new file mode 100644 index 0000000..edd5cd1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtOpenGL.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtOpenGLWidgets.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtOpenGLWidgets.py new file mode 100644 index 0000000..edd5cd1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtOpenGLWidgets.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtPdf.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtPdf.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtPdf.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtPdfWidgets.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtPdfWidgets.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtPdfWidgets.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtPositioning.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtPositioning.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtPositioning.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtPrintSupport.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtPrintSupport.py new file mode 100644 index 0000000..edd5cd1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtPrintSupport.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtQml.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtQml.py new file mode 100644 index 0000000..8b6837d --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtQml.py @@ -0,0 +1,17 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies, pyside6_library_info + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) +qml_binaries, qml_datas = pyside6_library_info.collect_qtqml_files() +binaries += qml_binaries +datas += qml_datas diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtQuick.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtQuick.py new file mode 100644 index 0000000..edd5cd1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtQuick.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtQuick3D.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtQuick3D.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtQuick3D.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtQuickControls2.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtQuickControls2.py new file mode 100644 index 0000000..b405fc6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtQuickControls2.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) + +hiddenimports += ['PySide6.QtQuick'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtQuickWidgets.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtQuickWidgets.py new file mode 100644 index 0000000..edd5cd1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtQuickWidgets.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtRemoteObjects.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtRemoteObjects.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtRemoteObjects.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtScxml.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtScxml.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtScxml.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtSensors.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtSensors.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtSensors.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtSerialBus.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtSerialBus.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtSerialBus.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtSerialPort.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtSerialPort.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtSerialPort.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtSpatialAudio.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtSpatialAudio.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtSpatialAudio.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtSql.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtSql.py new file mode 100644 index 0000000..edd5cd1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtSql.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtStateMachine.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtStateMachine.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtStateMachine.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtSvg.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtSvg.py new file mode 100644 index 0000000..edd5cd1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtSvg.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtSvgWidgets.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtSvgWidgets.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtSvgWidgets.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtTest.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtTest.py new file mode 100644 index 0000000..edd5cd1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtTest.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtTextToSpeech.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtTextToSpeech.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtTextToSpeech.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtUiTools.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtUiTools.py new file mode 100644 index 0000000..edd5cd1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtUiTools.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtWebChannel.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtWebChannel.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtWebChannel.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtWebEngineCore.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtWebEngineCore.py new file mode 100644 index 0000000..1889c0c --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtWebEngineCore.py @@ -0,0 +1,29 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2014-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import \ + add_qt6_dependencies, pyside6_library_info + +# Ensure PySide6 is importable before adding info depending on it. +if pyside6_library_info.version is not None: + # Qt6 prior to 6.2.2 contains a bug that makes it incompatible with the way PyInstaller collects + # QtWebEngine shared libraries and resources. So exit here and now instead of producing a defunct build. + if pyside6_library_info.version < [6, 2, 2]: + raise SystemExit("Error: PyInstaller's QtWebEngine support requires Qt6 6.2.2 or later!") + + hiddenimports, binaries, datas = add_qt6_dependencies(__file__) + + # Include helper process executable, translations, and resources. + webengine_binaries, webengine_datas = pyside6_library_info.collect_qtwebengine_files() + binaries += webengine_binaries + datas += webengine_datas + + hiddenimports += ['PySide6.QtPrintSupport'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtWebEngineQuick.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtWebEngineQuick.py new file mode 100644 index 0000000..19083de --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtWebEngineQuick.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2014-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtWebEngineWidgets.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtWebEngineWidgets.py new file mode 100644 index 0000000..19083de --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtWebEngineWidgets.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2014-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtWebSockets.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtWebSockets.py new file mode 100644 index 0000000..49d27d6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtWebSockets.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtWidgets.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtWidgets.py new file mode 100644 index 0000000..edd5cd1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtWidgets.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtXml.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtXml.py new file mode 100644 index 0000000..edd5cd1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.QtXml.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.qt import add_qt6_dependencies + +hiddenimports, binaries, datas = add_qt6_dependencies(__file__) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.py new file mode 100644 index 0000000..30e2ee6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-PySide6.py @@ -0,0 +1,28 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks import check_requirement +from PyInstaller.utils.hooks.qt import pyside6_library_info, ensure_single_qt_bindings_package + +# Allow only one Qt bindings package to be collected in frozen application. +ensure_single_qt_bindings_package("PySide6") + +# Only proceed if PySide6 can be imported. +if pyside6_library_info.version is not None: + hiddenimports = ['shiboken6', 'inspect'] + + # Starting with PySide6 6.4.0, we need to collect PySide6.support.deprecated for | and & operators to work with + # Qt key and key modifiers enums. See #7249. + if check_requirement("PySide6 >= 6.4.0"): + hiddenimports += ['PySide6.support.deprecated'] + + # Collect required Qt binaries. + binaries = pyside6_library_info.collect_extra_binaries() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-_pyi_rth_utils.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-_pyi_rth_utils.py new file mode 100644 index 0000000..cbd93aa --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-_pyi_rth_utils.py @@ -0,0 +1,17 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 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) +#----------------------------------------------------------------------------- + +from PyInstaller import compat + +# Exclude submodules specific to non-applicable OSes +excludedimports = [] +if not compat.is_win: + excludedimports += ['_pyi_rth_utils._win32'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-_tkinter.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-_tkinter.py new file mode 100644 index 0000000..7f21b49 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-_tkinter.py @@ -0,0 +1,22 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.tcl_tk import tcltk_info + + +def hook(hook_api): + # Add all Tcl/Tk data files, based on the `TclTkInfo.data_files`. If Tcl/Tk is unavailable, the list is empty. + # + # NOTE: the list contains 3-element TOC tuples with full destination filenames (because other parts of code, + # specifically splash-screen writer, currently require this format). Therefore, we need to use + # `PostGraphAPI.add_datas` (which supports 3-element TOC tuples); if this was 2-element "hook-style" TOC list, + # we could just assign `datas` global hook variable, without implementing the post-graph `hook()` function. + hook_api.add_datas(tcltk_info.data_files) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-babel.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-babel.py new file mode 100644 index 0000000..5f03a97 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-babel.py @@ -0,0 +1,24 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks import collect_data_files + +# Ensure that .dat files from locale-data sub-directory are collected. +datas = collect_data_files('babel') + +# Unpickling of locale-data/root.dat currently (babel v2.16.0) requires classes from following modules, so ensure that +# they are always collected: +hiddenimports = [ + "babel.dates", + "babel.localedata", + "babel.plural", + "babel.numbers", +] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-difflib.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-difflib.py new file mode 100644 index 0000000..2416758 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-difflib.py @@ -0,0 +1,13 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2015-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) +#----------------------------------------------------------------------------- + +# only required when run as `__main__` +excludedimports = ["doctest"] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-distutils.command.check.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-distutils.command.check.py new file mode 100644 index 0000000..50a17d4 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-distutils.command.check.py @@ -0,0 +1,13 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 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) +#----------------------------------------------------------------------------- + +# Conditionally imported in this module; should not trigger collection. +excludedimports = ['docutils'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-distutils.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-distutils.py new file mode 100644 index 0000000..c9cd63b --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-distutils.py @@ -0,0 +1,33 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.setuptools import setuptools_info + +hiddenimports = [] + +# From Python 3.6 and later ``distutils.sysconfig`` takes on the same behaviour as regular ``sysconfig`` of moving the +# config vars to a module (see hook-sysconfig.py). It doesn't use a nice `get module name` function like ``sysconfig`` +# does to help us locate it but the module is the same file that ``sysconfig`` uses so we can use the +# ``_get_sysconfigdata_name()`` from regular ``sysconfig``. +try: + import sysconfig + hiddenimports += [sysconfig._get_sysconfigdata_name()] +except AttributeError: + # Either sysconfig has no attribute _get_sysconfigdata_name (i.e., the function does not exist), or this is Windows + # and the _get_sysconfigdata_name() call failed due to missing sys.abiflags attribute. + pass + +# Starting with setuptools 60.0, the vendored distutils overrides the stdlib one (which will be removed in python 3.12 +# anyway), so check if we are using that version. While the distutils override behavior can be controleld via the +# ``SETUPTOOLS_USE_DISTUTILS`` environment variable, the latter may have a different value during the build and at the +# runtime, and so we need to ensure that both stdlib and setuptools variant of distutils are collected. +if setuptools_info.available and setuptools_info.version >= (60, 0): + hiddenimports += ['setuptools._distutils'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-distutils.util.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-distutils.util.py new file mode 100644 index 0000000..021d459 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-distutils.util.py @@ -0,0 +1,13 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +# distutils.util.run_2to3() imports lib2to3. Exclude it as chances are low that it is used by the frozen package. +excludedimports = ['lib2to3.refactor'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-django.contrib.sessions.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-django.contrib.sessions.py new file mode 100644 index 0000000..5d86e6c --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-django.contrib.sessions.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks import collect_submodules + +hiddenimports = collect_submodules('django.contrib.sessions.backends') diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-django.core.cache.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-django.core.cache.py new file mode 100644 index 0000000..eb319c7 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-django.core.cache.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks import collect_submodules + +hiddenimports = collect_submodules('django.core.cache.backends') diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-django.core.mail.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-django.core.mail.py new file mode 100644 index 0000000..1cee61c --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-django.core.mail.py @@ -0,0 +1,25 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- +""" +django.core.mail uses part of the email package. +The problem is: when using runserver with autoreload mode, the thread that checks for changed files triggers further +imports within the email package, because of the LazyImporter in email (used in 2.5 for backward compatibility). +We then need to name those modules as hidden imports, otherwise at runtime the autoreload thread will complain +with a traceback. +""" + +hiddenimports = [ + 'email.mime.message', + 'email.mime.image', + 'email.mime.text', + 'email.mime.multipart', + 'email.mime.audio', +] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-django.core.management.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-django.core.management.py new file mode 100644 index 0000000..a8566e0 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-django.core.management.py @@ -0,0 +1,19 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks import collect_submodules + +# Module django.core.management.commands.shell imports IPython, but it introduces many other dependencies that are not +# necessary for a simple django project; ignore the IPython module. +excludedimports = ['IPython', 'matplotlib', 'tkinter'] + +# Django requires management modules for the script 'manage.py'. +hiddenimports = collect_submodules('django.core.management.commands') diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-django.db.backends.mysql.base.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-django.db.backends.mysql.base.py new file mode 100644 index 0000000..951899e --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-django.db.backends.mysql.base.py @@ -0,0 +1,13 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +# Compiler module (see class DatabaseOperations) +hiddenimports = ["django.db.backends.mysql.compiler"] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-django.db.backends.oracle.base.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-django.db.backends.oracle.base.py new file mode 100644 index 0000000..d50eb97 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-django.db.backends.oracle.base.py @@ -0,0 +1,12 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +hiddenimports = ["django.db.backends.oracle.compiler"] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-django.db.backends.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-django.db.backends.py new file mode 100644 index 0000000..e829fe7 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-django.db.backends.py @@ -0,0 +1,25 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +import glob +import os + +from PyInstaller.utils.hooks import get_module_file_attribute + +# Compiler (see class BaseDatabaseOperations) +hiddenimports = ['django.db.models.sql.compiler'] + +# Include all available Django backends. +modpath = os.path.dirname(get_module_file_attribute('django.db.backends')) +for fn in glob.glob(os.path.join(modpath, '*')): + if os.path.isdir(fn): + fn = os.path.basename(fn) + hiddenimports.append('django.db.backends.' + fn + '.base') diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-django.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-django.py new file mode 100644 index 0000000..4a8ee04 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-django.py @@ -0,0 +1,92 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +# Tested with django 2.2 + +import glob +import os + +from PyInstaller import log as logging +from PyInstaller.utils import hooks +from PyInstaller.utils.hooks import django + +logger = logging.getLogger(__name__) + +# Collect everything. Some submodules of django are not importable without considerable external setup. Ignore the +# errors they raise. +datas, binaries, hiddenimports = hooks.collect_all('django', on_error="ignore") + +root_dir = django.django_find_root_dir() +if root_dir: + logger.info('Django root directory %s', root_dir) + # Include imports from the mysite.settings.py module. + settings_py_imports = django.django_dottedstring_imports(root_dir) + # Include all submodules of all imports detected in mysite.settings.py. + for submod in settings_py_imports: + hiddenimports.append(submod) + hiddenimports += hooks.collect_submodules(submod) + # Include main django modules - settings.py, urls.py, wsgi.py. Without them the django server won't run. + package_name = os.path.basename(root_dir) + default_settings_module = f'{package_name}.settings' + settings_module = os.environ.get('DJANGO_SETTINGS_MODULE', default_settings_module) + hiddenimports += [ + # TODO: consider including 'mysite.settings.py' in source code as a data files, + # since users might need to edit this file. + settings_module, + package_name + '.urls', + package_name + '.wsgi', + ] + # Django hiddenimports from the standard Python library. + hiddenimports += [ + 'http.cookies', + 'html.parser', + ] + + # Bundle django DB schema migration scripts as data files. They are necessary for some commands. + logger.info('Collecting Django migration scripts.') + migration_modules = [ + 'django.conf.app_template.migrations', + 'django.contrib.admin.migrations', + 'django.contrib.auth.migrations', + 'django.contrib.contenttypes.migrations', + 'django.contrib.flatpages.migrations', + 'django.contrib.redirects.migrations', + 'django.contrib.sessions.migrations', + 'django.contrib.sites.migrations', + ] + # Include migration scripts of Django-based apps too. + installed_apps = hooks.get_module_attribute(settings_module, 'INSTALLED_APPS') + migration_modules.extend(set(app + '.migrations' for app in installed_apps)) + # Copy migration files. + for mod in migration_modules: + mod_name, bundle_name = mod.split('.', 1) + mod_dir = os.path.dirname(hooks.get_module_file_attribute(mod_name)) + bundle_dir = bundle_name.replace('.', os.sep) + pattern = os.path.join(mod_dir, bundle_dir, '*.py') + files = glob.glob(pattern) + for f in files: + datas.append((f, os.path.join(mod_name, bundle_dir))) + + # Include data files from your Django project found in your django root package. + datas += hooks.collect_data_files(package_name) + + # Include database file if using sqlite. The sqlite database is usually next to the manage.py script. + root_dir_parent = os.path.dirname(root_dir) + # TODO Add more patterns if necessary. + _patterns = ['*.db', 'db.*'] + for p in _patterns: + files = glob.glob(os.path.join(root_dir_parent, p)) + for f in files: + # Place those files next to the executable. + datas.append((f, '.')) + +else: + logger.warning('No django root directory could be found!') diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-django.template.loaders.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-django.template.loaders.py new file mode 100644 index 0000000..18b1374 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-django.template.loaders.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks import collect_submodules + +hiddenimports = collect_submodules('django.template.loaders') diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-encodings.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-encodings.py new file mode 100644 index 0000000..a4082e1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-encodings.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks import collect_submodules + +hiddenimports = collect_submodules('encodings') diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gevent.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gevent.py new file mode 100644 index 0000000..40ad953 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gevent.py @@ -0,0 +1,24 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2015-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks import collect_all, copy_metadata + +excludedimports = ["gevent.testing", "gevent.tests"] + +datas, binaries, hiddenimports = collect_all( + 'gevent', + filter_submodules=lambda name: ("gevent.testing" not in name or "gevent.tests" not in name), + include_py_files=False, + exclude_datas=["**/tests"] +) + +# Gevent uses ``pkg_resources.require("...")``, which means that all its dependencies must also have their metadata. +datas += copy_metadata('gevent', recursive=True) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.py new file mode 100644 index 0000000..f6b2261 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.py @@ -0,0 +1,12 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +hiddenimports = ['gi._error', 'gi._option'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Adw.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Adw.py new file mode 100644 index 0000000..3327e21 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Adw.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('Adw', '1') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.AppIndicator3.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.AppIndicator3.py new file mode 100644 index 0000000..4b9c894 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.AppIndicator3.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('AppIndicator3', '0.1') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Atk.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Atk.py new file mode 100644 index 0000000..b57ee3f --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Atk.py @@ -0,0 +1,29 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks import get_hook_config +from PyInstaller.utils.hooks.gi import GiModuleInfo, collect_glib_translations + + +def hook(hook_api): + module_info = GiModuleInfo('Atk', '1.0') + if not module_info.available: + return + + binaries, datas, hiddenimports = module_info.collect_typelib_data() + + # Collect translations + lang_list = get_hook_config(hook_api, "gi", "languages") + datas += collect_glib_translations('atk10', lang_list) + + hook_api.add_datas(datas) + hook_api.add_binaries(binaries) + hook_api.add_imports(*hiddenimports) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.AyatanaAppIndicator3.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.AyatanaAppIndicator3.py new file mode 100644 index 0000000..36b178a --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.AyatanaAppIndicator3.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('AyatanaAppIndicator3', '0.1') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Champlain.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Champlain.py new file mode 100644 index 0000000..d48def3 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Champlain.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('Champlain', '0.12') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Clutter.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Clutter.py new file mode 100644 index 0000000..9ad56a6 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Clutter.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('Clutter', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.DBus.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.DBus.py new file mode 100644 index 0000000..0580fcb --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.DBus.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('DBus', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GIRepository.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GIRepository.py new file mode 100644 index 0000000..5c6961a --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GIRepository.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GIRepository', '2.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GLib.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GLib.py new file mode 100644 index 0000000..6aa236c --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GLib.py @@ -0,0 +1,42 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +import glob +import os + +from PyInstaller.compat import is_win +from PyInstaller.utils.hooks import get_hook_config +from PyInstaller.utils.hooks.gi import GiModuleInfo, collect_glib_share_files, collect_glib_translations + + +def hook(hook_api): + module_info = GiModuleInfo('GLib', '2.0') + if not module_info.available: + return + + binaries, datas, hiddenimports = module_info.collect_typelib_data() + + # Collect translations + lang_list = get_hook_config(hook_api, "gi", "languages") + datas += collect_glib_translations('glib20', lang_list) + + # Collect schemas + datas += collect_glib_share_files('glib-2.0', 'schemas') + + # On Windows, glib needs a spawn helper for g_spawn* API + if is_win: + pattern = os.path.join(module_info.get_libdir(), 'gspawn-*-helper*.exe') + for f in glob.glob(pattern): + binaries.append((f, '.')) + + hook_api.add_datas(datas) + hook_api.add_binaries(binaries) + hook_api.add_imports(*hiddenimports) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GModule.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GModule.py new file mode 100644 index 0000000..0ccaaaf --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GModule.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GModule', '2.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GObject.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GObject.py new file mode 100644 index 0000000..2171165 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GObject.py @@ -0,0 +1,19 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- +from PyInstaller.utils.hooks import check_requirement +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GObject', '2.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() + # gi._gobject removed from PyGObject in version 3.25.1 + if check_requirement('PyGObject < 3.25.1'): + hiddenimports += ['gi._gobject'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Gdk.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Gdk.py new file mode 100644 index 0000000..99fbd08 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Gdk.py @@ -0,0 +1,36 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo +from PyInstaller.utils.hooks import get_hook_config + + +def hook(hook_api): + # Use the Gdk version from hook config, if available. If not, try using Gtk version from hook config, so that we + # collect Gdk and Gtk of the same version. + module_versions = get_hook_config(hook_api, 'gi', 'module-versions') + if module_versions: + version = module_versions.get('Gdk') + if not version: + version = module_versions.get('Gtk', '3.0') + else: + version = '3.0' + + module_info = GiModuleInfo('Gdk', version) + if not module_info.available: + return + + binaries, datas, hiddenimports = module_info.collect_typelib_data() + hiddenimports += ['gi._gi_cairo', 'gi.repository.cairo'] + + hook_api.add_datas(datas) + hook_api.add_binaries(binaries) + hook_api.add_imports(*hiddenimports) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GdkPixbuf.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GdkPixbuf.py new file mode 100644 index 0000000..6c6b7c0 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GdkPixbuf.py @@ -0,0 +1,150 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +import glob +import os +import shutil +import subprocess + +from PyInstaller import compat +from PyInstaller.config import CONF # workpath +from PyInstaller.utils.hooks import get_hook_config, logger +from PyInstaller.utils.hooks.gi import GiModuleInfo, collect_glib_translations + +LOADERS_PATH = os.path.join('gdk-pixbuf-2.0', '2.10.0', 'loaders') +LOADER_MODULE_DEST_PATH = "lib/gdk-pixbuf/loaders" +LOADER_CACHE_DEST_PATH = "lib/gdk-pixbuf" # NOTE: some search & replace code depends on / being used on all platforms. + + +def _find_gdk_pixbuf_query_loaders_executable(libdir): + # Distributions either package gdk-pixbuf-query-loaders in the GI libs directory (not on the path), or on the path + # with or without a -x64 suffix, depending on the architecture. + cmds = [ + os.path.join(libdir, 'gdk-pixbuf-2.0', 'gdk-pixbuf-query-loaders'), + 'gdk-pixbuf-query-loaders-64', + 'gdk-pixbuf-query-loaders', + ] + + for cmd in cmds: + cmd_fullpath = shutil.which(cmd) + if cmd_fullpath is not None: + return cmd_fullpath + + return None + + +def _collect_loaders(libdir): + # Assume loader plugins have .so library suffix on all non-Windows platforms + lib_ext = "*.dll" if compat.is_win else "*.so" + + # Find all loaders + loader_libs = [] + pattern = os.path.join(libdir, LOADERS_PATH, lib_ext) + for f in glob.glob(pattern): + loader_libs.append(f) + + # Sometimes the loaders are stored in a different directory from the library (msys2) + if not loader_libs: + pattern = os.path.abspath(os.path.join(libdir, '..', 'lib', LOADERS_PATH, lib_ext)) + for f in glob.glob(pattern): + loader_libs.append(f) + + return loader_libs + + +def _generate_loader_cache(gdk_pixbuf_query_loaders, libdir, loader_libs): + # Run the "gdk-pixbuf-query-loaders" command and capture its standard output providing an updated loader + # cache; then write this output to the loader cache bundled with this frozen application. On all platforms, + # we also move the package structure to point to lib/gdk-pixbuf instead of lib/gdk-pixbuf-2.0/2.10.0 in + # order to make compatible for OSX application signing. + # + # On Mac OS we use @executable_path to specify a path relative to the generated bundle. However, on + # non-Windows, we need to rewrite the loader cache because it is not relocatable by default. See + # https://bugzilla.gnome.org/show_bug.cgi?id=737523 + # + # To make it easier to rewrite, we just always write @executable_path, since its significantly easier to + # find/replace at runtime. :) + # + # To permit string munging, decode the encoded bytes output by this command (i.e., enable the + # "universal_newlines" option). + # + # On Fedora, the default loaders cache is /usr/lib64, but the libdir is actually /lib64. To get around this, + # we pass the path to the loader command, and it will create a cache with the right path. + # + # On Windows, the loaders lib directory is relative, starts with 'lib', and uses \\ as path separators + # (escaped \). + cachedata = subprocess.run([gdk_pixbuf_query_loaders, *loader_libs], + check=True, + stdout=subprocess.PIPE, + encoding='utf-8').stdout + + output_lines = [] + prefix = '"' + os.path.join(libdir, 'gdk-pixbuf-2.0', '2.10.0') + plen = len(prefix) + + win_prefix = '"' + '\\\\'.join(['lib', 'gdk-pixbuf-2.0', '2.10.0']) + win_plen = len(win_prefix) + + msys2_prefix = '"' + os.path.abspath(os.path.join(libdir, '..', 'lib', 'gdk-pixbuf-2.0', '2.10.0')) + msys2_plen = len(msys2_prefix) + + # For each line in the updated loader cache... + for line in cachedata.splitlines(): + if line.startswith('#'): + continue + if line.startswith(prefix): + line = '"@executable_path/' + LOADER_CACHE_DEST_PATH + line[plen:] + elif line.startswith(win_prefix): + line = '"' + LOADER_CACHE_DEST_PATH.replace('/', '\\\\') + line[win_plen:] + elif line.startswith(msys2_prefix): + line = ('"' + LOADER_CACHE_DEST_PATH + line[msys2_plen:]).replace('/', '\\\\') + output_lines.append(line) + + return '\n'.join(output_lines) + + +def hook(hook_api): + module_info = GiModuleInfo('GdkPixbuf', '2.0') + if not module_info.available: + return + + binaries, datas, hiddenimports = module_info.collect_typelib_data() + + libdir = module_info.get_libdir() + + # Collect GdkPixbuf loaders and generate loader cache file + gdk_pixbuf_query_loaders = _find_gdk_pixbuf_query_loaders_executable(libdir) + logger.debug("gdk-pixbuf-query-loaders executable: %s", gdk_pixbuf_query_loaders) + if not gdk_pixbuf_query_loaders: + logger.warning("gdk-pixbuf-query-loaders executable not found in GI library directory or in PATH!") + else: + # Find all GdkPixbuf loader modules + loader_libs = _collect_loaders(libdir) + + # Collect discovered loaders + for lib in loader_libs: + binaries.append((lib, LOADER_MODULE_DEST_PATH)) + + # Generate loader cache; we need to store it to CONF['workpath'] so we can collect it as a data file. + cachedata = _generate_loader_cache(gdk_pixbuf_query_loaders, libdir, loader_libs) + cachefile = os.path.join(CONF['workpath'], 'loaders.cache') + with open(cachefile, 'w', encoding='utf-8') as fp: + fp.write(cachedata) + datas.append((cachefile, LOADER_CACHE_DEST_PATH)) + + # Collect translations + lang_list = get_hook_config(hook_api, "gi", "languages") + if gdk_pixbuf_query_loaders: + datas += collect_glib_translations('gdk-pixbuf', lang_list) + + hook_api.add_datas(datas) + hook_api.add_binaries(binaries) + hook_api.add_imports(*hiddenimports) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Gio.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Gio.py new file mode 100644 index 0000000..46a4351 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Gio.py @@ -0,0 +1,63 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +import glob +import os + +from PyInstaller import compat +import PyInstaller.log as logging +from PyInstaller.utils.hooks.gi import GiModuleInfo + +logger = logging.getLogger(__name__) + +module_info = GiModuleInfo('Gio', '2.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() + + # Find Gio modules + libdir = module_info.get_libdir() + modules_pattern = None + + if compat.is_win: + modules_pattern = os.path.join(libdir, 'gio', 'modules', '*.dll') + else: + gio_libdir = os.path.join(libdir, 'gio', 'modules') + if not os.path.exists(gio_libdir): + # homebrew installs the files elsewhere... + gio_libdir = os.path.join(os.path.commonprefix([compat.base_prefix, gio_libdir]), 'lib', 'gio', 'modules') + + if os.path.exists(gio_libdir): + modules_pattern = os.path.join(gio_libdir, '*.so') + else: + logger.warning('Could not determine Gio modules path!') + + if modules_pattern: + for f in glob.glob(modules_pattern): + binaries.append((f, 'gio_modules')) + else: + # To add a new platform add a new elif above with the proper is_ and proper pattern for finding the + # Gio modules on your platform. + logger.warning('Bundling Gio modules is not supported on your platform.') + + # Bundle the mime cache -- might not be needed on Windows + # -> this is used for content type detection (also used by GdkPixbuf) + # -> gio/xdgmime/xdgmime.c looks for mime/mime.cache in the users home directory, followed by XDG_DATA_DIRS if + # specified in the environment, otherwise it searches /usr/local/share/ and /usr/share/ + if not compat.is_win: + _mime_searchdirs = ['/usr/local/share', '/usr/share'] + if 'XDG_DATA_DIRS' in os.environ: + _mime_searchdirs.insert(0, os.environ['XDG_DATA_DIRS']) + + for sd in _mime_searchdirs: + spath = os.path.join(sd, 'mime', 'mime.cache') + if os.path.exists(spath): + datas.append((spath, 'share/mime')) + break diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Graphene.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Graphene.py new file mode 100644 index 0000000..bfa4d30 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Graphene.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('Graphene', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Gsk.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Gsk.py new file mode 100644 index 0000000..9229252 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Gsk.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('Gsk', '4.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Gst.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Gst.py new file mode 100644 index 0000000..939a37b --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Gst.py @@ -0,0 +1,93 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +# GStreamer contains a lot of plugins. We need to collect them and bundle them with the exe file. We also need to +# resolve binary dependencies of these GStreamer plugins. + +import pathlib + +from PyInstaller.utils.hooks import get_hook_config, include_or_exclude_file +import PyInstaller.log as logging +from PyInstaller import isolated +from PyInstaller.utils.hooks.gi import GiModuleInfo, collect_glib_share_files, collect_glib_translations + +logger = logging.getLogger(__name__) + + +@isolated.decorate +def _get_gst_plugin_path(): + import os + import gi + gi.require_version('Gst', '1.0') + from gi.repository import Gst + Gst.init(None) + reg = Gst.Registry.get() + plug = reg.find_plugin('coreelements') + path = plug.get_filename() + return os.path.dirname(path) + + +def _format_plugin_pattern(plugin_name): + return f"**/*gst{plugin_name}.*" + + +def hook(hook_api): + module_info = GiModuleInfo('Gst', '1.0') + if not module_info.available: + return + + binaries, datas, hiddenimports = module_info.collect_typelib_data() + hiddenimports += ["gi.repository.Gio"] + + # Collect data files + datas += collect_glib_share_files('gstreamer-1.0') + + # Translations + lang_list = get_hook_config(hook_api, "gi", "languages") + for prog in [ + 'gst-plugins-bad-1.0', + 'gst-plugins-base-1.0', + 'gst-plugins-good-1.0', + 'gst-plugins-ugly-1.0', + 'gstreamer-1.0', + ]: + datas += collect_glib_translations(prog, lang_list) + + # Plugins + try: + plugin_path = _get_gst_plugin_path() + except Exception as e: + logger.warning("Failed to determine gstreamer plugin path: %s", e) + plugin_path = None + + if plugin_path: + plugin_path = pathlib.Path(plugin_path) + + # Obtain optional include/exclude list from hook config + include_list = get_hook_config(hook_api, "gstreamer", "include_plugins") + exclude_list = get_hook_config(hook_api, "gstreamer", "exclude_plugins") + + # Format plugin basenames into filename patterns for matching + if include_list is not None: + include_list = [_format_plugin_pattern(name) for name in include_list] + if exclude_list is not None: + exclude_list = [_format_plugin_pattern(name) for name in exclude_list] + + # The names of GStreamer plugins typically start with libgst (or just gst, depending on the toolchain). We also + # need to account for different extensions that might be used on a particular OS (for example, on macOS, the + # extension may be either .so or .dylib). + for lib_pattern in ['*gst*.dll', '*gst*.dylib', '*gst*.so']: + binaries += [(str(filename), 'gst_plugins') for filename in plugin_path.glob(lib_pattern) + if include_or_exclude_file(filename, include_list, exclude_list)] + + hook_api.add_datas(datas) + hook_api.add_binaries(binaries) + hook_api.add_imports(*hiddenimports) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstAllocators.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstAllocators.py new file mode 100644 index 0000000..119401a --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstAllocators.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GstAllocators', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstApp.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstApp.py new file mode 100644 index 0000000..7c25a44 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstApp.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GstApp', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstAudio.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstAudio.py new file mode 100644 index 0000000..cf18078 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstAudio.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GstAudio', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstBadAudio.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstBadAudio.py new file mode 100644 index 0000000..0f345b9 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstBadAudio.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GstBadAudio', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstBase.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstBase.py new file mode 100644 index 0000000..ea6187b --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstBase.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GstBase', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstCheck.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstCheck.py new file mode 100644 index 0000000..e631995 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstCheck.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GstCheck', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstCodecs.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstCodecs.py new file mode 100644 index 0000000..ffa643e --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstCodecs.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GstCodecs', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstController.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstController.py new file mode 100644 index 0000000..c928843 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstController.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GstController', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstGL.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstGL.py new file mode 100644 index 0000000..0075eb0 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstGL.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GstGL', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstGLEGL.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstGLEGL.py new file mode 100644 index 0000000..a3f557d --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstGLEGL.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GstGLEGL', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstGLWayland.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstGLWayland.py new file mode 100644 index 0000000..6ef146d --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstGLWayland.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GstGLWayland', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstGLX11.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstGLX11.py new file mode 100644 index 0000000..dd68570 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstGLX11.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GstGLX11', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstInsertBin.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstInsertBin.py new file mode 100644 index 0000000..c7980bc --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstInsertBin.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GstInsertBin', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstMpegts.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstMpegts.py new file mode 100644 index 0000000..b690192 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstMpegts.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GstMpegts', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstNet.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstNet.py new file mode 100644 index 0000000..0c268af --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstNet.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GstNet', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstPbutils.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstPbutils.py new file mode 100644 index 0000000..173b695 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstPbutils.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GstPbutils', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstPlay.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstPlay.py new file mode 100644 index 0000000..edb6020 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstPlay.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GstPlay', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstPlayer.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstPlayer.py new file mode 100644 index 0000000..80cb93f --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstPlayer.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GstPlayer', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstRtp.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstRtp.py new file mode 100644 index 0000000..d18e58d --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstRtp.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GstRtp', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstRtsp.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstRtsp.py new file mode 100644 index 0000000..09382dd --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstRtsp.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GstRtsp', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstRtspServer.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstRtspServer.py new file mode 100644 index 0000000..d023c3f --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstRtspServer.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GstRtspServer', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstSdp.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstSdp.py new file mode 100644 index 0000000..2a78e2b --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstSdp.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GstSdp', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstTag.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstTag.py new file mode 100644 index 0000000..dbac756 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstTag.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GstTag', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstTranscoder.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstTranscoder.py new file mode 100644 index 0000000..3cc1dcf --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstTranscoder.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GstTranscoder', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstVideo.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstVideo.py new file mode 100644 index 0000000..398b503 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstVideo.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GstVideo', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstVulkan.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstVulkan.py new file mode 100644 index 0000000..588c073 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstVulkan.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GstVulkan', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstVulkanWayland.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstVulkanWayland.py new file mode 100644 index 0000000..aaef939 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstVulkanWayland.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GstVulkanWayland', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstVulkanXCB.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstVulkanXCB.py new file mode 100644 index 0000000..2351a13 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstVulkanXCB.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GstVulkanXCB', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstWebRTC.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstWebRTC.py new file mode 100644 index 0000000..9fcac06 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GstWebRTC.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GstWebRTC', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Gtk.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Gtk.py new file mode 100644 index 0000000..2495b1d --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Gtk.py @@ -0,0 +1,59 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +import os +import os.path + +from PyInstaller.compat import is_win +from PyInstaller.utils.hooks import get_hook_config +from PyInstaller.utils.hooks.gi import GiModuleInfo, collect_glib_etc_files, collect_glib_share_files, \ + collect_glib_translations + + +def hook(hook_api): + module_info = GiModuleInfo('Gtk', '3.0', hook_api=hook_api) # Pass hook_api to read version from hook config + if not module_info.available: + return + + binaries, datas, hiddenimports = module_info.collect_typelib_data() + + # Collect fontconfig data + datas += collect_glib_share_files('fontconfig') + + # Icons, themes, translations + icon_list = get_hook_config(hook_api, "gi", "icons") + if icon_list is not None: + for icon in icon_list: + datas += collect_glib_share_files(os.path.join('icons', icon)) + else: + datas += collect_glib_share_files('icons') + + # Themes + theme_list = get_hook_config(hook_api, "gi", "themes") + if theme_list is not None: + for theme in theme_list: + datas += collect_glib_share_files(os.path.join('themes', theme)) + else: + datas += collect_glib_share_files('themes') + + # Translations + lang_list = get_hook_config(hook_api, "gi", "languages") + datas += collect_glib_translations(f'gtk{module_info.version[0]}0', lang_list) + + # These only seem to be required on Windows + if is_win: + datas += collect_glib_etc_files('fonts') + datas += collect_glib_etc_files('pango') + datas += collect_glib_share_files('fonts') + + hook_api.add_datas(datas) + hook_api.add_binaries(binaries) + hook_api.add_imports(*hiddenimports) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GtkChamplain.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GtkChamplain.py new file mode 100644 index 0000000..777b620 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GtkChamplain.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GtkChamplain', '0.12') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GtkClutter.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GtkClutter.py new file mode 100644 index 0000000..cc4fcd7 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GtkClutter.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('GtkClutter', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GtkSource.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GtkSource.py new file mode 100644 index 0000000..5e7efa7 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GtkSource.py @@ -0,0 +1,31 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo, collect_glib_share_files + + +def hook(hook_api): + module_info = GiModuleInfo('GtkSource', '3.0', hook_api=hook_api) # Pass hook_api to read version from hook config + if not module_info.available: + return + + binaries, datas, hiddenimports = module_info.collect_typelib_data() + + # Collect data files + # The data directory name contains verbatim version, e.g.: + # * GtkSourceView-3.0 -> /usr/share/gtksourceview-3.0 + # * GtkSourceView-4 -> /usr/share/gtksourceview-4 + # * GtkSourceView-5 -> /usr/share/gtksourceview-5 + datas += collect_glib_share_files(f'gtksourceview-{module_info.version}') + + hook_api.add_datas(datas) + hook_api.add_binaries(binaries) + hook_api.add_imports(*hiddenimports) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GtkosxApplication.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GtkosxApplication.py new file mode 100644 index 0000000..3437edf --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.GtkosxApplication.py @@ -0,0 +1,18 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.compat import is_darwin +from PyInstaller.utils.hooks.gi import GiModuleInfo + +if is_darwin: + module_info = GiModuleInfo('GtkosxApplication', '1.0') + if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.HarfBuzz.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.HarfBuzz.py new file mode 100644 index 0000000..41cef14 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.HarfBuzz.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('HarfBuzz', '0.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Pango.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Pango.py new file mode 100644 index 0000000..3d8b865 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.Pango.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('Pango', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.PangoCairo.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.PangoCairo.py new file mode 100644 index 0000000..7c058fd --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.PangoCairo.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('PangoCairo', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.cairo.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.cairo.py new file mode 100644 index 0000000..71fed30 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.cairo.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('cairo', '1.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.freetype2.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.freetype2.py new file mode 100644 index 0000000..ffea7a1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.freetype2.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('freetype2', '2.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.xlib.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.xlib.py new file mode 100644 index 0000000..1c2bde3 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-gi.repository.xlib.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks.gi import GiModuleInfo + +module_info = GiModuleInfo('xlib', '2.0') +if module_info.available: + binaries, datas, hiddenimports = module_info.collect_typelib_data() diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-heapq.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-heapq.py new file mode 100644 index 0000000..373025f --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-heapq.py @@ -0,0 +1,13 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2015-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) +#----------------------------------------------------------------------------- + +# Only required when run as `__main__`. +excludedimports = ["doctest"] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-idlelib.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-idlelib.py new file mode 100644 index 0000000..505378d --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-idlelib.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('idlelib') diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-importlib_metadata.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-importlib_metadata.py new file mode 100644 index 0000000..7abf511 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-importlib_metadata.py @@ -0,0 +1,24 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2019-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) +#----------------------------------------------------------------------------- +""" +importlib_metadata is a library to access the metadata for a Python package. This functionality intends to replace most +uses of pkg_resources entry point API and metadata API. +""" + +from PyInstaller.utils.hooks import copy_metadata + +# Normally, we should never need to use copy_metadata() in a hook since metadata requirements detection is now +# automatic. However, that detection first uses `PyiModuleGraph.get_code_using("importlib_metadata")` to find +# files which `import importlib_metadata` and `get_code_using()` intentionally excludes internal imports. This +# means that importlib_metadata is not scanned for usages of importlib_metadata and therefore when +# importlib_metadata uses its own API to get its version, this goes undetected. Therefore, we must collect its +# metadata manually. +datas = copy_metadata('importlib_metadata') diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-importlib_resources.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-importlib_resources.py new file mode 100644 index 0000000..b43b19b --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-importlib_resources.py @@ -0,0 +1,22 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2019-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) +#----------------------------------------------------------------------------- +""" +`importlib_resources` is a backport of the 3.9+ module `importlib.resources` +""" + +from PyInstaller.utils.hooks import check_requirement, collect_data_files + +# Prior to v1.2.0, a `version.txt` file is used to set __version__. Later versions use `importlib.metadata`. +if check_requirement("importlib_resources < 1.2.0"): + datas = collect_data_files("importlib_resources", includes=["version.txt"]) + +if check_requirement("importlib_resources >= 1.3.1"): + hiddenimports = ['importlib_resources.trees'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-keyring.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-keyring.py new file mode 100644 index 0000000..acbd5ff --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-keyring.py @@ -0,0 +1,19 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2014-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks import collect_submodules, copy_metadata + +# Collect backends +hiddenimports = collect_submodules('keyring.backends') + +# Keyring performs backend plugin discovery using setuptools entry points, which are listed in the metadata. Therefore, +# we need to copy the metadata, otherwise no backends will be found at run-time. +datas = copy_metadata('keyring') diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-kivy.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-kivy.py new file mode 100644 index 0000000..fd01f06 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-kivy.py @@ -0,0 +1,25 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2015-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) +#----------------------------------------------------------------------------- + +from PyInstaller import log as logging +from PyInstaller.utils.hooks import check_requirement + +if check_requirement('kivy >= 1.9.1'): + from kivy.tools.packaging.pyinstaller_hooks import (add_dep_paths, get_deps_all, get_factory_modules, kivy_modules) + from kivy.tools.packaging.pyinstaller_hooks import excludedimports, datas # noqa: F401 + + add_dep_paths() + + hiddenimports = get_deps_all()['hiddenimports'] + hiddenimports = list(set(get_factory_modules() + kivy_modules + hiddenimports)) +else: + logger = logging.getLogger(__name__) + logger.warning('Hook disabled because of Kivy version < 1.9.1') diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-lib2to3.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-lib2to3.py new file mode 100644 index 0000000..83b0f08 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-lib2to3.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +# This is needed to bundle lib2to3 Grammars files + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('lib2to3') diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-matplotlib.backend_bases.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-matplotlib.backend_bases.py new file mode 100644 index 0000000..f65344c --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-matplotlib.backend_bases.py @@ -0,0 +1,12 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2024, 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) +#----------------------------------------------------------------------------- + +excludedimports = ['IPython'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-matplotlib.backends.backend_qtagg.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-matplotlib.backends.backend_qtagg.py new file mode 100644 index 0000000..b3067db --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-matplotlib.backends.backend_qtagg.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2024, 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) +#----------------------------------------------------------------------------- + +# This module conditionally imports PyQt6: +# https://github.com/matplotlib/matplotlib/blob/9e18a343fb58a2978a8e27df03190ed21c61c343/lib/matplotlib/backends/backend_qtagg.py#L52-L53 +# Suppress this import to prevent PyQt6 from being accidentally pulled in; the actually relevant Qt bindings are +# determined by our hook for `matplotlib.backends.qt_compat` module. +excludedimports = ['PyQt6'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-matplotlib.backends.backend_qtcairo.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-matplotlib.backends.backend_qtcairo.py new file mode 100644 index 0000000..0b9174b --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-matplotlib.backends.backend_qtcairo.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2024, 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) +#----------------------------------------------------------------------------- + +# This module conditionally imports PyQt6: +# https://github.com/matplotlib/matplotlib/blob/9e18a343fb58a2978a8e27df03190ed21c61c343/lib/matplotlib/backends/backend_qtcairo.py#L24-L25 +# Suppress this import to prevent PyQt6 from being accidentally pulled in; the actually relevant Qt bindings are +# determined by our hook for `matplotlib.backends.qt_compat` module. +excludedimports = ['PyQt6'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-matplotlib.backends.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-matplotlib.backends.py new file mode 100644 index 0000000..318f82e --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-matplotlib.backends.py @@ -0,0 +1,226 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.compat import is_darwin +from PyInstaller.utils.hooks import logger, get_hook_config +from PyInstaller import isolated + + +@isolated.decorate +def _get_configured_default_backend(): + """ + Return the configured default matplotlib backend name, if available as matplotlib.rcParams['backend'] (or overridden + by MPLBACKEND environment variable. If the value of matplotlib.rcParams['backend'] corresponds to the auto-sentinel + object, returns None + """ + import matplotlib + # matplotlib.rcParams overrides the __getitem__ implementation and attempts to determine and load the default + # backend using pyplot.switch_backend(). Therefore, use dict.__getitem__(). + val = dict.__getitem__(matplotlib.rcParams, 'backend') + if isinstance(val, str): + return val + return None + + +@isolated.decorate +def _list_available_mpl_backends(): + """ + Returns the names of all available matplotlib backends. + """ + import matplotlib + return matplotlib.rcsetup.all_backends + + +@isolated.decorate +def _check_mpl_backend_importable(module_name): + """ + Attempts to import the given module name (matplotlib backend module). + + Exceptions are propagated to caller. + """ + __import__(module_name) + + +# Bytecode scanning +def _recursive_scan_code_objects_for_mpl_use(co): + """ + Recursively scan the bytecode for occurrences of matplotlib.use() or mpl.use() calls with const arguments, and + collect those arguments into list of used matplotlib backend names. + """ + + from PyInstaller.depend.bytecode import any_alias, recursive_function_calls + + mpl_use_names = { + *any_alias("matplotlib.use"), + *any_alias("mpl.use"), # matplotlib is commonly aliased as mpl + } + + backends = [] + for calls in recursive_function_calls(co).values(): + for name, args in calls: + # matplotlib.use(backend) or matplotlib.use(backend, force) + # We support only literal arguments. Similarly, kwargs are + # not supported. + if len(args) not in {1, 2} or not isinstance(args[0], str): + continue + if name in mpl_use_names: + backends.append(args[0]) + + return backends + + +def _backend_module_name(name): + """ + Converts matplotlib backend name to its corresponding module name. + + Equivalent to matplotlib.cbook._backend_module_name(). + """ + if name.startswith("module://"): + return name[9:] + return f"matplotlib.backends.backend_{name.lower()}" + + +def _autodetect_used_backends(hook_api): + """ + Returns a list of automatically-discovered matplotlib backends in use, or the name of the default matplotlib + backend. Implements the 'auto' backend selection method. + """ + # Scan the code for matplotlib.use() + modulegraph = hook_api.analysis.graph + mpl_code_objs = modulegraph.get_code_using("matplotlib") + used_backends = [] + for name, co in mpl_code_objs.items(): + co_backends = _recursive_scan_code_objects_for_mpl_use(co) + if co_backends: + logger.info( + "Discovered Matplotlib backend(s) via `matplotlib.use()` call in module %r: %r", name, co_backends + ) + used_backends += co_backends + + # Deduplicate and sort the list of used backends before displaying it. + used_backends = sorted(set(used_backends)) + + if used_backends: + HOOK_CONFIG_DOCS = 'https://pyinstaller.org/en/stable/hooks-config.html#matplotlib-hooks' + logger.info( + "The following Matplotlib backends were discovered by scanning for `matplotlib.use()` calls: %r. If your " + "backend of choice is not in this list, either add a `matplotlib.use()` call to your code, or configure " + "the backend collection via hook options (see: %s).", used_backends, HOOK_CONFIG_DOCS + ) + return used_backends + + # Determine the default matplotlib backend. + # + # Ideally, this would be done by calling ``matplotlib.get_backend()``. However, that function tries to switch to the + # default backend (calling ``matplotlib.pyplot.switch_backend()``), which seems to occasionally fail on our linux CI + # with an error and, on other occasions, returns the headless Agg backend instead of the GUI one (even with display + # server running). Furthermore, using ``matplotlib.get_backend()`` returns headless 'Agg' when display server is + # unavailable, which is not ideal for automated builds. + # + # Therefore, we try to emulate ``matplotlib.get_backend()`` ourselves. First, we try to obtain the configured + # default backend from settings (rcparams and/or MPLBACKEND environment variable). If that is unavailable, we try to + # find the first importable GUI-based backend, using the same list as matplotlib.pyplot.switch_backend() uses for + # automatic backend selection. The difference is that we only test whether the backend module is importable, without + # trying to switch to it. + default_backend = _get_configured_default_backend() # isolated sub-process + if default_backend: + logger.info("Found configured default matplotlib backend: %s", default_backend) + return [default_backend] + + # `QtAgg` supersedes `Qt5Agg`; however, we keep `Qt5Agg` in the candidate list to support older versions of + # matplotlib that do not have `QtAgg`. + candidates = ["QtAgg", "Qt5Agg", "Gtk4Agg", "Gtk3Agg", "TkAgg", "WxAgg"] + if is_darwin: + candidates = ["MacOSX"] + candidates + logger.info("Trying determine the default backend as first importable candidate from the list: %r", candidates) + + for candidate in candidates: + try: + module_name = _backend_module_name(candidate) + _check_mpl_backend_importable(module_name) # NOTE: uses an isolated sub-process. + except Exception: + continue + return [candidate] + + # Fall back to headless Agg backend + logger.info("None of the backend candidates could be imported; falling back to headless Agg!") + return ['Agg'] + + +def _collect_all_importable_backends(hook_api): + """ + Returns a list of all importable matplotlib backends. Implements the 'all' backend selection method. + """ + # List of the human-readable names of all available backends. + backend_names = _list_available_mpl_backends() # NOTE: retrieved in an isolated sub-process. + logger.info("All available matplotlib backends: %r", backend_names) + + # Try to import the module(s). + importable_backends = [] + + # List of backends to exclude; Qt4 is not supported by PyInstaller anymore. + exclude_backends = {'Qt4Agg', 'Qt4Cairo'} + + # Ignore "CocoaAgg" on OSes other than Mac OS; attempting to import it on other OSes halts the current + # (sub)process without printing output or raising exceptions, preventing reliable detection. Apply the + # same logic for the (newer) "MacOSX" backend. + if not is_darwin: + exclude_backends |= {'CocoaAgg', 'MacOSX'} + + # For safety, attempt to import each backend in an isolated sub-process. + for backend_name in backend_names: + if backend_name in exclude_backends: + logger.info(' Matplotlib backend %r: excluded', backend_name) + continue + + try: + module_name = _backend_module_name(backend_name) + _check_mpl_backend_importable(module_name) # NOTE: uses an isolated sub-process. + except Exception: + # Backend is not importable, for whatever reason. + logger.info(' Matplotlib backend %r: ignored due to import error', backend_name) + continue + + logger.info(' Matplotlib backend %r: added', backend_name) + importable_backends.append(backend_name) + + return importable_backends + + +def hook(hook_api): + # Backend collection setting + backends_method = get_hook_config(hook_api, 'matplotlib', 'backends') + if backends_method is None: + backends_method = 'auto' # default method + + # Select backend(s) + if backends_method == 'auto': + logger.info("Matplotlib backend selection method: automatic discovery of used backends") + backend_names = _autodetect_used_backends(hook_api) + elif backends_method == 'all': + logger.info("Matplotlib backend selection method: collection of all importable backends") + backend_names = _collect_all_importable_backends(hook_api) + else: + logger.info("Matplotlib backend selection method: user-provided name(s)") + if isinstance(backends_method, str): + backend_names = [backends_method] + else: + assert isinstance(backends_method, list), "User-provided backend name(s) must be either a string or a list!" + backend_names = backends_method + + # Deduplicate and sort the list of selected backends before displaying it. + backend_names = sorted(set(backend_names)) + + logger.info("Selected matplotlib backends: %r", backend_names) + + # Set module names as hiddenimports + module_names = [_backend_module_name(backend) for backend in backend_names] # backend name -> module name + hook_api.add_imports(*module_names) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-matplotlib.backends.qt_compat.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-matplotlib.backends.qt_compat.py new file mode 100644 index 0000000..4e12fff --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-matplotlib.backends.qt_compat.py @@ -0,0 +1,26 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2024, 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks import qt as qtutils + +# This module conditionally imports all Qt bindings. Prevent all available bindings from being pulled in by trying to +# select the most applicable one. +# +# The preference order for this module appears to be: PyQt6, PySide6, PyQt5, PySide2 (or just PyQt5, PySide2 if Qt5 +# bindings are forced). See: +# https://github.com/matplotlib/matplotlib/blob/9e18a343fb58a2978a8e27df03190ed21c61c343/lib/matplotlib/backends/qt_compat.py#L113-L125 +# +# We, however, use the default preference order of the helper function, in order to keep it consistent across multiple +# hooks that use the same helper. +excludedimports = qtutils.exclude_extraneous_qt_bindings( + hook_name="hook-matplotlib.backends.qt_compat", + qt_bindings_order=None, +) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-matplotlib.numerix.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-matplotlib.numerix.py new file mode 100644 index 0000000..924b400 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-matplotlib.numerix.py @@ -0,0 +1,21 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- +""" +The matplotlib.numerix package sneaks these imports in under the radar. +""" + +hiddenimports = [ + 'fft', + 'linear_algebra', + 'random_array', + 'ma', + 'mlab', +] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-matplotlib.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-matplotlib.py new file mode 100644 index 0000000..e628e9b --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-matplotlib.py @@ -0,0 +1,38 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller import isolated +from PyInstaller import compat +from PyInstaller.utils import hooks as hookutils + + +@isolated.decorate +def mpl_data_dir(): + import matplotlib + return matplotlib.get_data_path() + + +datas = [ + (mpl_data_dir(), "matplotlib/mpl-data"), +] + +binaries = [] + +# Windows PyPI wheels for `matplotlib` >= 3.7.0 use `delvewheel`. +# In addition to DLLs from `matplotlib.libs` directory, which should be picked up automatically by dependency analysis +# in contemporary PyInstaller versions, we also need to collect the load-order file. This used to be required for +# python <= 3.7 (that lacked `os.add_dll_directory`), but is also needed for Anaconda python 3.8 and 3.9, where +# `delvewheel` falls back to load-order file codepath due to Anaconda breaking `os.add_dll_directory` implementation. +if compat.is_win and hookutils.check_requirement('matplotlib >= 3.7.0'): + delvewheel_datas, delvewheel_binaries = hookutils.collect_delvewheel_libs_directory('matplotlib') + + datas += delvewheel_datas + binaries += delvewheel_binaries diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-matplotlib.pyplot.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-matplotlib.pyplot.py new file mode 100644 index 0000000..2f78597 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-matplotlib.pyplot.py @@ -0,0 +1,12 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2024, 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) +#----------------------------------------------------------------------------- + +excludedimports = ['IPython', "IPython.core.pylabtools"] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-multiprocessing.util.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-multiprocessing.util.py new file mode 100644 index 0000000..b9363ba --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-multiprocessing.util.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +# In Python 3.8 mutliprocess.utils has _cleanup_tests() to cleanup multiprocessing resources when multiprocessing tests +# completed. This function import `tests` which is the complete Python test-suite, pulling in many more dependencies, +# e.g., tkinter. + +excludedimports = ['test'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-numpy.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-numpy.py new file mode 100644 index 0000000..bbdfa29 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-numpy.py @@ -0,0 +1,116 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-2024, PyInstaller Development Team. +# +# Distributed under the terms of the GNU General Public License (version 2 +# or later) with exception for distributing the bootloader. Additional +# +# The full license is in the file COPYING.txt, distributed with this software. +# +# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception) +#----------------------------------------------------------------------------- + +# --- Copyright Disclaimer --- +# +# An earlier copy of this hook has been submitted to the NumPy project, where it was integrated in v1.23.0rc1 +# (https://github.com/numpy/numpy/pull/20745), under terms and conditions outlined in their repository [1]. +# +# A special provision is hereby granted to the NumPy project that allows the NumPy copy of the hook to incorporate the +# changes made to this (PyInstaller's) copy of the hook, subject to their licensing terms as opposed to PyInstaller's +# (stricter) licensing terms. +# +# .. refs: +# +# [1] NumPy's license: https://github.com/numpy/numpy/blob/master/LICENSE.txt + +# NOTE: when comparing the contents of this hook and the NumPy version of the hook (for example, to port changes), keep +# in mind that this copy is PyInstaller-centric - it caters to the version of PyInstaller it is bundled with, but needs +# to account for different behavior of different NumPy versions. In contrast, the NumPy copy of the hook caters to the +# version of NumPy it is bundled with, but should account for behavior differences in different PyInstaller versions. + +# Override the default hook priority so that our copy of hook is used instead of NumPy's one (which has priority 0, +# the default for upstream hooks). +# $PyInstaller-Hook-Priority: 1 + +from PyInstaller import compat +from PyInstaller.utils.hooks import ( + get_installer, + collect_dynamic_libs, +) + +from packaging.version import Version + +numpy_version = Version(compat.importlib_metadata.version("numpy")).release +numpy_installer = get_installer('numpy') + +hiddenimports = [] +datas = [] +binaries = [] + +# Collect shared libraries that are bundled inside the numpy's package directory. With PyInstaller 6.x, the directory +# layout of collected shared libraries should be preserved (to match behavior of the binary dependency analysis). In +# earlier versions of PyInstaller, it was necessary to collect the shared libraries into application's top-level +# directory (because that was also what binary dependency analysis in PyInstaller < 6.0 did). +binaries += collect_dynamic_libs("numpy") + +# Check if we are using Anaconda-packaged numpy +if numpy_installer == 'conda': + # Collect DLLs for NumPy and its dependencies (MKL, OpenBlas, OpenMP, etc.) from the communal Conda bin directory. + from PyInstaller.utils.hooks import conda_support + datas += conda_support.collect_dynamic_libs("numpy", dependencies=True) + +# NumPy 1.26 started using `delvewheel` for its Windows PyPI wheels. While contemporary PyInstaller versions +# automatically pick up DLLs from external `numpy.libs` directory, this does not work on Anaconda python 3.8 and 3.9 +# due to defunct `os.add_dll_directory`, which forces `delvewheel` to use the old load-order file approach. So we need +# to explicitly ensure that load-order file as well as DLLs are collected. +if compat.is_win and numpy_version >= (1, 26) and numpy_installer == 'pip': + from PyInstaller.utils.hooks import collect_delvewheel_libs_directory + datas, binaries = collect_delvewheel_libs_directory("numpy", datas=datas, binaries=binaries) + +# Submodules PyInstaller cannot detect (probably because they are only imported by extension modules, which PyInstaller +# cannot read). +if numpy_version >= (2, 0): + # In v2.0.0, `numpy.core` was renamed to `numpy._core`. + # See https://github.com/numpy/numpy/commit/47b70cbffd672849a5d3b9b6fa6e515700460fd0 + hiddenimports += ['numpy._core._dtype_ctypes', 'numpy._core._multiarray_tests'] +else: + hiddenimports += ['numpy.core._dtype_ctypes'] + + # See https://github.com/numpy/numpy/commit/99104bd2d0557078d7ea9a590129c87dd63df623 + if numpy_version >= (1, 25): + hiddenimports += ['numpy.core._multiarray_tests'] + +# This hidden import was removed from NumPy hook in v1.25.0 (https://github.com/numpy/numpy/pull/22666). According to +# comment in the linked PR, it should have been unnecessary since v1.19. +if compat.is_conda and numpy_version < (1, 19): + hiddenimports += ["six"] + +# Remove testing and building code and packages that are referenced throughout NumPy but are not really dependencies. +excludedimports = [ + "scipy", + "pytest", + "nose", + "f2py", + "setuptools", +] + +# As of v1.22.0, numpy.testing (imported for example by some scipy modules) requires numpy.distutils and distutils. +# This was due to numpy.testing adding import of numpy.testing._private.extbuild, which in turn imported numpy.distutils +# and distutils. These imports were moved into functions that require them in v1.22.2 and v.1.23.0. +# See: https://github.com/numpy/numpy/pull/20831 and https://github.com/numpy/numpy/pull/20906 +# So we can exclude them for all numpy versions except for v1.22.0 and v1.22.1 - the main motivation is to avoid pulling +# in `setuptools` (which nowadays provides its vendored version of `distutils`). +if numpy_version < (1, 22, 0) or numpy_version > (1, 22, 1): + excludedimports += [ + "distutils", + "numpy.distutils", + ] + +# In numpy v2.0.0, numpy.f2py submodule has been added to numpy's `__all__` attribute. Therefore, using +# `from numpy import *` leads to an error if `numpy.f2py` is excluded (seen in scipy 1.14). The exclusion in earlier +# releases was not reported to cause any issues, so keep it around. Although it should be noted that it does break an +# explicit import (i.e., ˙import numpy.f2py`) from user's code as well, because it prevents collection of other +# submodules from `numpy.f2py`. +if numpy_version < (2, 0): + excludedimports += [ + "numpy.f2py", + ] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-packaging.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-packaging.py new file mode 100644 index 0000000..c742b4a --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-packaging.py @@ -0,0 +1,13 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +# Duplicate hook-pkg_resources.py. +hiddenimports = ["pkg_resources"] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-pandas.io.clipboard.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-pandas.io.clipboard.py new file mode 100644 index 0000000..2395920 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-pandas.io.clipboard.py @@ -0,0 +1,19 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2024, 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) +#----------------------------------------------------------------------------- + +# This module conditionally imports PyQt5: +# https://github.com/pandas-dev/pandas/blob/95308514e1221200e4526dfaf248283f3d7ade06/pandas/io/clipboard/__init__.py#L578-L597 +# Suppress this import to prevent PyQt5 from being accidentally pulled in; the actually relevant Qt bindings are +# determined by our hook for `qtpy` module, which contemporary versions of pandas mandate as part of `clipboard` and +# `all` extras: +# https://github.com/pandas-dev/pandas/blob/95308514e1221200e4526dfaf248283f3d7ade06/pyproject.toml#L86 +# https://github.com/pandas-dev/pandas/blob/95308514e1221200e4526dfaf248283f3d7ade06/pyproject.toml#L115 +excludedimports = ['PyQt5'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-pandas.io.formats.style.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-pandas.io.formats.style.py new file mode 100644 index 0000000..2a56828 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-pandas.io.formats.style.py @@ -0,0 +1,18 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks import collect_data_files + +# This module indirectly imports jinja2 +hiddenimports = ['jinja2'] + +# It also requires template file stored in pandas/io/formats/templates +datas = collect_data_files('pandas.io.formats') diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-pandas.plotting.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-pandas.plotting.py new file mode 100644 index 0000000..948dd88 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-pandas.plotting.py @@ -0,0 +1,18 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks import check_requirement + +# Starting with pandas 1.3.0, pandas.plotting._matplotlib is imported via importlib.import_module() and needs to be +# added to hidden imports. But do this only if matplotlib is available in the first place (as it is soft dependency +# of pandas). +if check_requirement('pandas >= 1.3.0') and check_requirement('matplotlib'): + hiddenimports = ['pandas.plotting._matplotlib'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-pandas.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-pandas.py new file mode 100644 index 0000000..7b3acad --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-pandas.py @@ -0,0 +1,20 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2017-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks import collect_submodules, check_requirement + +# Pandas keeps Python extensions loaded with dynamic imports here. +hiddenimports = collect_submodules('pandas._libs') + +# Pandas 1.2.0 and later require cmath hidden import on linux and macOS. On Windows, this is not strictly required, but +# we add it anyway to keep things simple (and future-proof). +if check_requirement('pandas >= 1.2.0'): + hiddenimports += ['cmath'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-pickle.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-pickle.py new file mode 100644 index 0000000..8d023bb --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-pickle.py @@ -0,0 +1,13 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2015-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) +#----------------------------------------------------------------------------- + +# Only required when run as `__main__` +excludedimports = ["argparse", "doctest"] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-pkg_resources.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-pkg_resources.py new file mode 100644 index 0000000..286671f --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-pkg_resources.py @@ -0,0 +1,68 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks import collect_submodules, can_import_module +from PyInstaller.utils.hooks.setuptools import setuptools_info + +hiddenimports = [] +excludedimports = ['__main__'] + +# pkg_resources keeps vendored modules in its _vendor subpackage, and does sys.meta_path based import magic to expose +# them as pkg_resources.extern.* +# +# With setuptools >= 71.0, pkg_resources ceased to vendor packages, because vendoring is now done at the setuptools +# level. +if setuptools_info.available and setuptools_info.version < (71, 0, 0): + # The `railroad` package is an optional requirement for `pyparsing`. `pyparsing.diagrams` depends on `railroad`, so + # filter it out when `railroad` is not available. + if can_import_module('railroad'): + hiddenimports += collect_submodules('pkg_resources._vendor') + else: + hiddenimports += collect_submodules( + 'pkg_resources._vendor', filter=lambda name: 'pkg_resources._vendor.pyparsing.diagram' not in name + ) + + # pkg_resources v45.0 dropped support for Python 2 and added this module printing a warning. We could save some + # bytes if we would replace this by a fake module. + if setuptools_info.version >= (45, 0, 0) and setuptools_info.version < (49, 1, 1): + hiddenimports += ['pkg_resources.py2_warn'] + + # As of v60.7, setuptools vendored jaraco and has pkg_resources use it. Currently, the pkg_resources._vendor.jaraco + # namespace package cannot be automatically scanned due to limited support for pure namespace packages in our hook + # utilities. + # + # In setuptools 60.7.0, the vendored jaraco.text package included "Lorem Ipsum.txt" data file, which also has to be + # collected. However, the presence of the data file (and the resulting directory hierarchy) confuses the importer's + # redirection logic; instead of trying to work-around that, tell user to upgrade or downgrade their setuptools. + if setuptools_info.version == (60, 7, 0): + raise SystemExit( + "ERROR: Setuptools 60.7.0 is incompatible with PyInstaller. " + "Downgrade to an earlier version or upgrade to a later version." + ) + # In setuptools 60.7.1, the "Lorem Ipsum.txt" data file was dropped from the vendored jaraco.text package, so we can + # accommodate it with couple of hidden imports. + elif setuptools_info.version >= (60, 7, 1): + hiddenimports += [ + 'pkg_resources._vendor.jaraco.functools', + 'pkg_resources._vendor.jaraco.context', + 'pkg_resources._vendor.jaraco.text', + ] + + # As of setuptools 70.0.0, we need pkg_resources.extern added to hidden imports. + if setuptools_info.version >= (70, 0, 0): + hiddenimports += [ + 'pkg_resources.extern', + ] + +# Some more hidden imports. See: +# https://github.com/pyinstaller/pyinstaller-hooks-contrib/issues/15#issuecomment-663699288 `packaging` can either be +# its own package, or embedded in `pkg_resources._vendor.packaging`, or both. +hiddenimports += collect_submodules('packaging') diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-platform.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-platform.py new file mode 100644 index 0000000..d1d8e1d --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-platform.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- +import sys + +# see https://github.com/python/cpython/blob/3.9/Lib/platform.py#L411 +# This will exclude `plistlib` for sys.platform != 'darwin' +if sys.platform != 'darwin': + excludedimports = ["plistlib"] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-pygments.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-pygments.py new file mode 100644 index 0000000..529d82b --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-pygments.py @@ -0,0 +1,29 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- +""" +PyInstaller hook file for Pygments. Tested with version 2.0.2. +""" + +from PyInstaller.utils.hooks import collect_submodules + +# The following applies to pygments version 2.0.2, as reported by ``pip show pygments``. +# +# From pygments.formatters, line 37:: +# +# def _load_formatters(module_name): +# """Load a formatter (and all others in the module too).""" +# mod = __import__(module_name, None, None, ['__all__']) +# +# Therefore, we need all the modules in ``pygments.formatters``. + +hiddenimports = collect_submodules('pygments.formatters') +hiddenimports.extend(collect_submodules('pygments.lexers')) +hiddenimports.extend(collect_submodules('pygments.styles')) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-pytz.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-pytz.py new file mode 100644 index 0000000..d6b6486 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-pytz.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks import collect_data_files + +# On Linux pytz installed from distribution repository uses zoneinfo from /usr/share/zoneinfo/ and no data files might +# be collected. +datas = collect_data_files('pytz') diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-pytzdata.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-pytzdata.py new file mode 100644 index 0000000..e45626c --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-pytzdata.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("pytzdata") diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-qtawesome.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-qtawesome.py new file mode 100644 index 0000000..9829a03 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-qtawesome.py @@ -0,0 +1,19 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2017-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) +#----------------------------------------------------------------------------- +""" +Hook for QtAwesome (https://github.com/spyder-ide/qtawesome). +Font files and charmaps need to be included with module. +Tested with QtAwesome 0.4.4 and Python 3.6 on macOS 10.12.4. +""" + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('qtawesome') diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-qtpy.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-qtpy.py new file mode 100644 index 0000000..a6ce00c --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-qtpy.py @@ -0,0 +1,25 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2024, 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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks import qt as qtutils + +# This module conditionally imports all Qt bindings. Prevent all available bindings from being pulled in by trying to +# select the most applicable one. +# +# The preference order for this module appears to be: PyQt5, PySide2, PyQt6, PySide6. See: +# https://github.com/spyder-ide/qtpy/blob/3238de7a3e038daeb585c1a76fd9a0c4baf22f11/qtpy/__init__.py#L199-L289 +# +# We, however, use the default preference order of the helper function, in order to keep it consistent across multiple +# hooks that use the same helper. +excludedimports = qtutils.exclude_extraneous_qt_bindings( + hook_name="hook-qtpy", + qt_bindings_order=None, +) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-scapy.layers.all.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-scapy.layers.all.py new file mode 100644 index 0000000..fdcc779 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-scapy.layers.all.py @@ -0,0 +1,19 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks import collect_submodules + +# The layers to load can be configured using scapy's conf.load_layers. +# from scapy.config import conf; print(conf.load_layers) +# I decided not to use this, but to include all layer modules. The reason is: When building the package, load_layers may +# not include all the layer modules the program will use later. + +hiddenimports = collect_submodules('scapy.layers') diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-scipy.io.matlab.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-scipy.io.matlab.py new file mode 100644 index 0000000..c69c767 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-scipy.io.matlab.py @@ -0,0 +1,13 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +# Module scipy.io.matlab allows to parse matlab files. The hidden import is necessary for SciPy 0.11+. +hiddenimports = ['scipy.io.matlab.streams'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-scipy.linalg.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-scipy.linalg.py new file mode 100644 index 0000000..b1a68b8 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-scipy.linalg.py @@ -0,0 +1,13 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +# The hidden import is necessary for SciPy 0.16+. +hiddenimports = ['scipy.linalg.cython_blas', 'scipy.linalg.cython_lapack'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-scipy.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-scipy.py new file mode 100644 index 0000000..6c16e92 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-scipy.py @@ -0,0 +1,52 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +# ----------------------------------------------------------------------------- + +import glob +import os + +from PyInstaller.compat import is_win +from PyInstaller.utils.hooks import ( + get_module_file_attribute, + check_requirement, + collect_delvewheel_libs_directory, + collect_submodules, +) + +binaries = [] +datas = [] + +# Package the DLL bundle that official scipy wheels for Windows ship The DLL bundle will either be in extra-dll on +# windows proper and in .libs if installed on a virtualenv created from MinGW (Git-Bash for example) +if is_win: + extra_dll_locations = ['extra-dll', '.libs'] + for location in extra_dll_locations: + dll_glob = os.path.join(os.path.dirname(get_module_file_attribute('scipy')), location, "*.dll") + if glob.glob(dll_glob): + binaries.append((dll_glob, ".")) + +# Handle delvewheel-enabled win32 wheels, which have external scipy.libs directory (scipy >= 0.9.2) +if check_requirement("scipy >= 1.9.2") and is_win: + datas, binaries = collect_delvewheel_libs_directory('scipy', datas=datas, binaries=binaries) + +# collect library-wide utility extension modules +hiddenimports = ['scipy._lib.%s' % m for m in ['messagestream', "_ccallback_c", "_fpumode"]] + +# In scipy 1.14.0, `scipy._lib.array_api_compat.numpy` added a programmatic import of its `.fft` submodule, which needs +# to be added to hiddenimports. +if check_requirement("scipy >= 1.14.0"): + hiddenimports += ['scipy._lib.array_api_compat.numpy.fft'] + +# The `scipy._lib.array_api_compat.numpy` module performs a `from numpy import *`; in numpy 2.0.0, `numpy.f2py` was +# added to `numpy.__all__` attribute, but at the same time, the upstream numpy hook adds `numpy.f2py` to +# `excludedimports`. Therefore, the `numpy.f2py` sub-package ends up missing. Due to the way exclusion mechanism works, +# we need to add both `numpy.f2py` and all its submodules to hiddenimports here. +if check_requirement("numpy >= 2.0.0"): + hiddenimports += collect_submodules('numpy.f2py', filter=lambda name: name != 'numpy.f2py.tests') diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-scipy.sparse.csgraph.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-scipy.sparse.csgraph.py new file mode 100644 index 0000000..9cabdbd --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-scipy.sparse.csgraph.py @@ -0,0 +1,13 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +# The hidden import is necessary for SciPy 0.11+. +hiddenimports = ['scipy.sparse.csgraph._validation'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-scipy.spatial.transform.rotation.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-scipy.spatial.transform.rotation.py new file mode 100644 index 0000000..4840cf2 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-scipy.spatial.transform.rotation.py @@ -0,0 +1,17 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks import check_requirement + +# As of scipy 1.6.0, scipy.spatial.transform.rotation is cython-compiled, so we fail to automatically pick up its +# imports. +if check_requirement("scipy >= 1.6.0"): + hiddenimports = ['scipy.spatial.transform._rotation_groups'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-scipy.special._ellip_harm_2.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-scipy.special._ellip_harm_2.py new file mode 100644 index 0000000..5115b02 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-scipy.special._ellip_harm_2.py @@ -0,0 +1,30 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- +""" +Module hook for the `scipy.special._ellip_harm_2` C extension first introduced by SciPy >= 0.15.0. + +See Also +---------- +https://github.com/scipy/scipy/blob/master/scipy/special/_ellip_harm_2.pyx + This C extension's Cython-based implementation. +""" + +# In SciPy >= 0.15.0: +# +# 1. The "scipy.special.__init__" module imports... +# 2. The "scipy.special._ellip_harm" module imports... +# 3. The "scipy.special._ellip_harm_2" C extension imports... +# 4. The "scipy.integrate" package. +# +# The third import is undetectable by PyInstaller and hence explicitly listed. Since "_ellip_harm" and "_ellip_harm_2" +# were first introduced by SciPy 0.15.0, the following hidden import will only be applied for versions of SciPy +# guaranteed to provide these modules and C extensions. +hiddenimports = ['scipy.integrate'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-scipy.special._ufuncs.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-scipy.special._ufuncs.py new file mode 100644 index 0000000..f94b22e --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-scipy.special._ufuncs.py @@ -0,0 +1,25 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks import is_module_satisfies + +# Module scipy.io._ufunc depends on some other C/C++ extensions. The hidden import is necessary for SciPy 0.13+. +# Thanks to dyadkin; see issue #826. +hiddenimports = ['scipy.special._ufuncs_cxx'] + +# SciPy 1.13.0 cythonized cdflib; this introduced new `scipy.special._cdflib` extension that is imported from the +# `scipy.special._ufuncs` extension, and thus we need a hidden import here. +if is_module_satisfies('scipy >= 1.13.0'): + hiddenimports += ['scipy.special._cdflib'] + +# SciPy 1.14.0 introduced `scipy.special._special_ufuncs`, which is imported from `scipy.special._ufuncs` extension. +if is_module_satisfies('scipy >= 1.14.0'): + hiddenimports += ['scipy.special._special_ufuncs'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-scipy.stats._stats.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-scipy.stats._stats.py new file mode 100644 index 0000000..e5f72a0 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-scipy.stats._stats.py @@ -0,0 +1,15 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks import check_requirement + +if check_requirement("scipy >= 1.5.0"): + hiddenimports = ['scipy.special.cython_special'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-scrapy.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-scrapy.py new file mode 100644 index 0000000..f110bb0 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-scrapy.py @@ -0,0 +1,18 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +# Hook for https://pypi.org/project/Scrapy/ +# https://stackoverflow.com/questions/49085970/no-such-file-or-directory-error-using-pyinstaller-and-scrapy + +from PyInstaller.utils.hooks import collect_data_files, collect_submodules + +datas = collect_data_files('scrapy') +hiddenimports = collect_submodules('scrapy') diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-setuptools._vendor.importlib_metadata.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-setuptools._vendor.importlib_metadata.py new file mode 100644 index 0000000..e7c92d0 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-setuptools._vendor.importlib_metadata.py @@ -0,0 +1,21 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2024, 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) +#----------------------------------------------------------------------------- + +import fnmatch +from PyInstaller.utils.hooks.setuptools import setuptools_info + +# Collect metadata for setuptools-vendored copy of importlib-metadata, to match the behavior of hook for +# stand-alone version of the package (i.e., `hook-importlib_metadata.py`). + +# Use cached data files list from setuptools_info, and extract relevant bits (to avoid having to call another +# `collect_data_files` and import `setuptools` in isolated process). +datas = [(src_name, dest_name) for src_name, dest_name in setuptools_info.vendored_data + if fnmatch.fnmatch(src_name, "**/setuptools/_vendor/importlib_metadata-*.dist-info/*")] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-setuptools._vendor.jaraco.text.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-setuptools._vendor.jaraco.text.py new file mode 100644 index 0000000..47e65da --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-setuptools._vendor.jaraco.text.py @@ -0,0 +1,18 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2024, 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) +#----------------------------------------------------------------------------- + +import fnmatch +from PyInstaller.utils.hooks.setuptools import setuptools_info + +# Use cached data files list from setuptools_info, and extract relevant bits (to avoid having to call another +# `collect_data_files` and import `setuptools` in isolated process). +datas = [(src_name, dest_name) for src_name, dest_name in setuptools_info.vendored_data + if fnmatch.fnmatch(src_name, "**/setuptools/_vendor/jaraco/text/*")] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-setuptools.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-setuptools.py new file mode 100644 index 0000000..6c2c1bb --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-setuptools.py @@ -0,0 +1,75 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller import compat +from PyInstaller.utils.hooks.setuptools import setuptools_info + +datas = [] + +hiddenimports = [ + # Test case import/test_zipimport2 fails during importing pkg_resources or setuptools when module not present. + 'distutils.command.build_ext', + 'setuptools.msvc', +] + +# Necessary for setuptools on Mac/Unix +if compat.is_unix or compat.is_darwin: + hiddenimports.append('syslog') + +# Prevent the following modules from being collected solely due to reference from anywhere within setuptools (or +# its vendored dependencies). +excludedimports = [ + 'pytest', + 'numpy', # originally from hook-setuptools.msvc + 'docutils', # originally from hool-setuptools._distutils.command.check +] + +# setuptools >= 39.0.0 is "vendoring" its own direct dependencies from "_vendor" to "extern". This also requires +# 'pre_safe_import_module/hook-setuptools.extern.six.moves.py' to make the moves defined in 'setuptools._vendor.six' +# importable under 'setuptools.extern.six'. +# +# With setuptools 71.0.0, the vendored packages are exposed to the outside world by `setuptools._vendor` location being +# appended to `sys.path`, and the `VendorImporter` is gone (i.e., no more mapping to `setuptools.extern`). Since the +# vendored dependencies are now exposed as top-level modules (provided upstream versions are not available, as they +# would take precedence due to `sys.path` ordering), we need pre-safe-import-module hooks that detect when only vendored +# version is available, and add aliases to prevent duplicated collection. For list of vendored packages for which we +# need such pre-safe-import-module hooks, see the code in `PyInstaller.utils.hooks.setuptools`. +# +# The list of submodules from `setuptools._vendor` is now available in `setuptools_info.vendored_modules` (and covers +# all setuptools versions). +# +# NOTE: with setuptools >= 71.0, we do not need to add modules from `setuptools._vendored` to hidden imports anymore, +# because the aliases we set up should ensure that the necessary parts get collected. We still need them for earlier +# versions of setuptools, though. +if setuptools_info.version < (71, 0): + hiddenimports += setuptools_info.vendored_modules + +# The situation with vendored distutils (from `setuptools._distutils`) is a bit more complicated; python >= 3.12 does +# not provide stdlib version of `distutils` anymore, so our corresponding pre-safe-import-module hook sets up aliases. +# In earlier python versions, stdlib version is available as well, and at run-time, we might need both versions present, +# so that whichever is applicable can be used. Therefore, for python < 3.12, we need to add the vendored distuils +# modules to hidden imports. +if setuptools_info.distutils_vendored and not compat.is_py312: + hiddenimports += setuptools_info.distutils_modules + +# With setuptools >= 71.0.0, the vendored packages also have metadata, and might also contain data files that need to +# be collected. The list of corresponding data files is kept cached in `setuptools_info.vendored_data` (to minimize the +# number of times we need to call collect_data_files()). +# +# While it might be tempting to simply collect all data files and be done with it, we actually need to match the +# collection behavior for the stand-alone versions of these packages; i.e., we should collect metadata (and/or data +# files) for the vendored package only if the same data is also collected for stand-alone version. Otherwise, we risk +# inconsistent behavior and potential mismatches; for example, if we collected metadata for vendored package A here, +# but end up collecting stand-alone A, for which we normally do not collect the metadata, then at run-time, we will end +# up with stand-alone copy of A and vendored copy of its metadata being discoverable. +# +# Therefore, if metadata and/or metadata needs to be collected, do it in corresponding sub-package hook (for an example, +# see `hook-setuptools._vendor.jaraco.text.py`). diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-shelve.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-shelve.py new file mode 100644 index 0000000..1df601a --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-shelve.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +# Tested on Windows 7 x64 With Python 3.5 + +hiddenimports = ["dbm.ndbm", "dbm.dumb", "dbm.gnu"] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-shiboken6.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-shiboken6.py new file mode 100644 index 0000000..17cf0c3 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-shiboken6.py @@ -0,0 +1,17 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 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) +#----------------------------------------------------------------------------- + +from PyInstaller import compat + +# Up until python 3.12, `xxsubtype` was built-in on all OSes. Now it is an extension on non-Windows, and without it, +# shiboken6 initialization segfaults. +if compat.is_py312 and not compat.is_win: + hiddenimports = ['xxsubtype'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-sphinx.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-sphinx.py new file mode 100644 index 0000000..f5a13ac --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-sphinx.py @@ -0,0 +1,41 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks import collect_data_files, collect_submodules, eval_statement + +# Sphinx consists of several extensions that are lazily loaded. So collect all submodules to ensure we do not miss +# any of them. +hiddenimports = collect_submodules('sphinx') + +# For each extension in sphinx.application.builtin_extensions that does not come from the sphinx package, do a +# collect_submodules(). We need to do this explicitly because collect_submodules() does not seem to work with +# namespace packages, which precludes us from simply doing hiddenimports += collect_submodules('sphinxcontrib') +builtin_extensions = list( + eval_statement( + """ + from sphinx.application import builtin_extensions + print(builtin_extensions) + """ + ) +) +for extension in builtin_extensions: + if extension.startswith('sphinx.'): + continue # Already collected + hiddenimports += collect_submodules(extension) + +# This is inherited from an earlier version of the hook, and seems to have been required in Sphinx v.1.3.1 era due to +# https://github.com/sphinx-doc/sphinx/blob/b87ce32e7dc09773f9e71305e66e8d6aead53dd1/sphinx/cmdline.py#L173. +# It does not hurt to keep it around, just in case. +hiddenimports += ['locale'] + +# Collect all data files: *.html and *.conf files in ``sphinx.themes``, translation files in ``sphinx.locale``, etc. +# Also collect all data files for the alabaster theme. +datas = collect_data_files('sphinx') + collect_data_files('alabaster') diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-sqlalchemy.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-sqlalchemy.py new file mode 100644 index 0000000..3aafc50 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-sqlalchemy.py @@ -0,0 +1,88 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +import re +import importlib.util + +from PyInstaller import isolated +from PyInstaller.lib.modulegraph.modulegraph import SourceModule +from PyInstaller.utils.hooks import check_requirement, collect_entry_point, logger + +datas = [] + +# 'sqlalchemy.testing' causes bundling a lot of unnecessary modules. +excludedimports = ['sqlalchemy.testing'] + +# Include most common database bindings some database bindings are detected and include some are not. We should +# explicitly include database backends. +hiddenimports = ['pysqlite2', 'MySQLdb', 'psycopg2', 'sqlalchemy.ext.baked'] + +if check_requirement('sqlalchemy >= 1.4'): + hiddenimports.append("sqlalchemy.sql.default_comparator") + + +@isolated.decorate +def _get_dialect_modules(module_name): + import importlib + module = importlib.import_module(module_name) + return [f"{module_name}.{submodule_name}" for submodule_name in module.__all__] + + +# In SQLAlchemy >= 0.6, the "sqlalchemy.dialects" package provides dialects. +# In SQLAlchemy <= 0.5, the "sqlalchemy.databases" package provides dialects. +if check_requirement('sqlalchemy >= 0.6'): + hiddenimports += _get_dialect_modules("sqlalchemy.dialects") +else: + hiddenimports += _get_dialect_modules("sqlalchemy.databases") + +# Collect additional dialects and plugins that are registered via entry-points, under assumption that they are available +# in the build environment for a reason (i.e., they are used). +for entry_point_name in ('sqlalchemy.dialects', 'sqlalchemy.plugins'): + ep_datas, ep_hiddenimports = collect_entry_point(entry_point_name) + datas += ep_datas + hiddenimports += ep_hiddenimports + + +def hook(hook_api): + """ + SQLAlchemy 0.9 introduced the decorator 'util.dependencies'. This decorator does imports. E.g.: + + @util.dependencies("sqlalchemy.sql.schema") + + This hook scans for included SQLAlchemy modules and then scans those modules for any util.dependencies and marks + those modules as hidden imports. + """ + + if not check_requirement('sqlalchemy >= 0.9'): + return + + # this parser is very simplistic but seems to catch all cases as of V1.1 + depend_regex = re.compile(r'@util.dependencies\([\'"](.*?)[\'"]\)') + + hidden_imports_set = set() + known_imports = set() + for node in hook_api.module_graph.iter_graph(start=hook_api.module): + if isinstance(node, SourceModule) and node.identifier.startswith('sqlalchemy.'): + known_imports.add(node.identifier) + + # Read the source... + with open(node.filename, 'rb') as f: + source_code = f.read() + source_code = importlib.util.decode_source(source_code) + + # ... and scan it + for match in depend_regex.findall(source_code): + hidden_imports_set.add(match) + + hidden_imports_set -= known_imports + if len(hidden_imports_set): + logger.info(" Found %d sqlalchemy hidden imports", len(hidden_imports_set)) + hook_api.add_imports(*list(hidden_imports_set)) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-sqlite3.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-sqlite3.py new file mode 100644 index 0000000..805bf8f --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-sqlite3.py @@ -0,0 +1,19 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks import collect_submodules + +hiddenimports = [] + +# On Windows in Python 3.4 'sqlite3' package might contain tests that are not required in frozen application. +for mod in collect_submodules('sqlite3'): + if not mod.startswith('sqlite3.test'): + hiddenimports.append(mod) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-sysconfig.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-sysconfig.py new file mode 100644 index 0000000..d4331cf --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-sysconfig.py @@ -0,0 +1,29 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- +import sys + +# see https://github.com/python/cpython/blob/3.9/Lib/sysconfig.py#L593 +# This will exclude `_osx_support`, `distutils`, `distutils.log` for sys.platform != 'darwin' +if sys.platform != 'darwin': + excludedimports = ["_osx_support"] + +# Python 3.6 uses additional modules like `_sysconfigdata_m_linux_x86_64-linux-gnu`, see +# https://github.com/python/cpython/blob/3.6/Lib/sysconfig.py#L417 +# Note: Some versions of Anaconda backport this feature to before 3.6. See issue #3105. +# Note: on Windows, python.org and Anaconda python provide _get_sysconfigdata_name, but calling it fails due to sys +# module lacking abiflags attribute. It does work on MSYS2/MINGW python, where we need to collect corresponding file. +try: + import sysconfig + hiddenimports = [sysconfig._get_sysconfigdata_name()] +except AttributeError: + # Either sysconfig has no attribute _get_sysconfigdata_name (i.e., the function does not exist), or this is Windows + # and the _get_sysconfigdata_name() call failed due to missing sys.abiflags attribute. + pass diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-wcwidth.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-wcwidth.py new file mode 100644 index 0000000..dc7c2dd --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-wcwidth.py @@ -0,0 +1,14 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2017-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) +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('wcwidth') diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-win32ctypes.core.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-win32ctypes.core.py new file mode 100644 index 0000000..6971473 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-win32ctypes.core.py @@ -0,0 +1,22 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2020-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) +#----------------------------------------------------------------------------- + +# TODO: remove this hook during PyInstaller 4.5 release cycle! + +from PyInstaller.utils.hooks import can_import_module, collect_submodules + +# We need to collect submodules from win32ctypes.core.cffi or win32ctypes.core.ctypes for win32ctypes.core to work. +# Always collect the `ctypes` backend, and add the `cffi` one if `cffi` is available. Having the `ctypes` backend always +# available helps in situations when `cffi` is available in the build environment, but is disabled at run-time or not +# collected (e.g., due to `--exclude cffi`). +hiddenimports = collect_submodules('win32ctypes.core.ctypes') +if can_import_module('cffi'): + hiddenimports += collect_submodules('win32ctypes.core.cffi') diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-xml.dom.domreg.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-xml.dom.domreg.py new file mode 100644 index 0000000..eb7161a --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-xml.dom.domreg.py @@ -0,0 +1,13 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +# xml.dom.domreg line 54 +hiddenimports = ['xml.dom.minidom'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-xml.etree.cElementTree.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-xml.etree.cElementTree.py new file mode 100644 index 0000000..95dc702 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-xml.etree.cElementTree.py @@ -0,0 +1,13 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +# cElementTree has a hidden import (Python >=2.5 stdlib version) +hiddenimports = ['xml.etree.ElementTree'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-xml.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-xml.py new file mode 100644 index 0000000..d7776a0 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-xml.py @@ -0,0 +1,12 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +hiddenimports = ['xml.sax.xmlreader', 'xml.sax.expatreader'] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/hook-zope.interface.py b/venv/Lib/site-packages/PyInstaller/hooks/hook-zope.interface.py new file mode 100644 index 0000000..b43d023 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/hook-zope.interface.py @@ -0,0 +1,12 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2015-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) +#----------------------------------------------------------------------------- + +excludedimports = ["unittest"] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/__init__.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/__init__.py new file mode 100644 index 0000000..792d600 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/__init__.py @@ -0,0 +1 @@ +# diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..c10400a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/__pycache__/hook-PyQt5.uic.port_v2.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/__pycache__/hook-PyQt5.uic.port_v2.cpython-311.pyc new file mode 100644 index 0000000..b03c52b Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/__pycache__/hook-PyQt5.uic.port_v2.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/__pycache__/hook-_pyi_rth_utils.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/__pycache__/hook-_pyi_rth_utils.cpython-311.pyc new file mode 100644 index 0000000..8a551ee Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/__pycache__/hook-_pyi_rth_utils.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/__pycache__/hook-distutils.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/__pycache__/hook-distutils.cpython-311.pyc new file mode 100644 index 0000000..ef73bd7 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/__pycache__/hook-distutils.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/__pycache__/hook-pyi_splash.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/__pycache__/hook-pyi_splash.cpython-311.pyc new file mode 100644 index 0000000..a01e929 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/__pycache__/hook-pyi_splash.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/__pycache__/hook-tkinter.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/__pycache__/hook-tkinter.cpython-311.pyc new file mode 100644 index 0000000..9f5e1bf Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/__pycache__/hook-tkinter.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/hook-PyQt5.uic.port_v2.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/hook-PyQt5.uic.port_v2.py new file mode 100644 index 0000000..014c9e2 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/hook-PyQt5.uic.port_v2.py @@ -0,0 +1,15 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + + +def pre_find_module_path(hook_api): + # Forbid imports in the port_v2 directory under Python 3 The code wouldn't import and would crash the build process. + hook_api.search_dirs = [] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/hook-_pyi_rth_utils.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/hook-_pyi_rth_utils.py new file mode 100644 index 0000000..d035df0 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/hook-_pyi_rth_utils.py @@ -0,0 +1,25 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 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) +# ----------------------------------------------------------------------------- +""" +This hook allows discovery and collection of PyInstaller's internal _pyi_rth_utils module that provides utility +functions for run-time hooks. + +The module is implemented in 'PyInstaller/fake-modules/_pyi_rth_utils.py'. +""" + +import os + +from PyInstaller import PACKAGEPATH + + +def pre_find_module_path(api): + module_dir = os.path.join(PACKAGEPATH, 'fake-modules') + api.search_dirs = [module_dir] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/hook-distutils.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/hook-distutils.py new file mode 100644 index 0000000..0e7e646 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/hook-distutils.py @@ -0,0 +1,46 @@ +# ----------------------------------------------------------------------------- +# 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) +# ----------------------------------------------------------------------------- +""" +`distutils`-specific pre-find module path hook. + +When run from within a virtual environment, this hook changes the `__path__` of the `distutils` package to +that of the system-wide rather than virtual-environment-specific `distutils` package. While the former is suitable for +freezing, the latter is intended for use _only_ from within virtual environments. + +NOTE: this behavior seems to be specific to virtual environments created by (an old?) version of `virtualenv`; it is not +applicable to virtual environments created by the `venv`. +""" + +import pathlib + +from PyInstaller.utils.hooks import logger, get_module_file_attribute + + +def pre_find_module_path(api): + # Absolute path of the system-wide "distutils" package when run from within a venv or None otherwise. + + # opcode is not a virtualenv module, so we can use it to find the stdlib. Technique taken from virtualenv's + # "distutils" package detection at + # https://github.com/pypa/virtualenv/blob/16.3.0/virtualenv_embedded/distutils-init.py#L5 + # As opcode is a module, stdlib path corresponds to the parent directory of its ``__file__`` attribute. + stdlib_path = pathlib.Path(get_module_file_attribute('opcode')).parent.resolve() + # As distutils is a package, we need to consider the grandparent directory of its ``__file__`` attribute. + distutils_path = pathlib.Path(get_module_file_attribute('distutils')).parent.parent.resolve() + + if distutils_path.name == 'setuptools': + logger.debug("distutils: provided by setuptools") + elif distutils_path == stdlib_path: + logger.debug("distutils: provided by stdlib") + else: + # Find this package in stdlib. + stdlib_path = str(stdlib_path) + logger.debug("distutils: virtualenv shim - retargeting to stdlib dir %r", stdlib_path) + api.search_dirs = [stdlib_path] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/hook-pyi_splash.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/hook-pyi_splash.py new file mode 100644 index 0000000..15f8009 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/hook-pyi_splash.py @@ -0,0 +1,36 @@ +# ----------------------------------------------------------------------------- +# 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) +# ----------------------------------------------------------------------------- +""" +This hook does not move a module that can be installed by a package manager, but points to a PyInstaller internal +module that can be imported into the users python instance. + +The module is implemented in 'PyInstaller/fake-modules/pyi_splash.py'. +""" + +import os + +from PyInstaller import PACKAGEPATH +from PyInstaller.utils.hooks import logger + + +def pre_find_module_path(api): + try: + # Test if a module named 'pyi_splash' is locally installed. This prevents that a potentially required dependency + # is not packed + import pyi_splash # noqa: F401 + except ImportError: + module_dir = os.path.join(PACKAGEPATH, 'fake-modules') + + api.search_dirs = [module_dir] + logger.info('Adding pyi_splash module to application dependencies.') + else: + logger.info('A local module named "pyi_splash" is installed. Use the installed one instead.') + return diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/hook-tkinter.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/hook-tkinter.py new file mode 100644 index 0000000..1cc5a78 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_find_module_path/hook-tkinter.py @@ -0,0 +1,21 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2024, 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) +#----------------------------------------------------------------------------- + +from PyInstaller import log as logging +from PyInstaller.utils.hooks import tcl_tk + +logger = logging.getLogger(__name__) + + +def pre_find_module_path(hook_api): + if not tcl_tk.tcltk_info.available: + logger.warning("tkinter installation is broken. It will be excluded from the application") + hook_api.search_dirs = [] diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__init__.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__init__.py new file mode 100644 index 0000000..792d600 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__init__.py @@ -0,0 +1 @@ +# diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..1beb735 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-autocommand.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-autocommand.cpython-311.pyc new file mode 100644 index 0000000..9d2d652 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-autocommand.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-backports.tarfile.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-backports.tarfile.cpython-311.pyc new file mode 100644 index 0000000..2ec7499 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-backports.tarfile.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-distutils.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-distutils.cpython-311.pyc new file mode 100644 index 0000000..72149b4 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-distutils.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.cpython-311.pyc new file mode 100644 index 0000000..7802dd0 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Adw.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Adw.cpython-311.pyc new file mode 100644 index 0000000..32ae7ac Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Adw.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.AppIndicator3.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.AppIndicator3.cpython-311.pyc new file mode 100644 index 0000000..4b68d1f Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.AppIndicator3.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Atk.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Atk.cpython-311.pyc new file mode 100644 index 0000000..7c82da5 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Atk.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.AyatanaAppIndicator3.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.AyatanaAppIndicator3.cpython-311.pyc new file mode 100644 index 0000000..bc43bf9 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.AyatanaAppIndicator3.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Champlain.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Champlain.cpython-311.pyc new file mode 100644 index 0000000..af5bcd1 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Champlain.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Clutter.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Clutter.cpython-311.pyc new file mode 100644 index 0000000..b32173e Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Clutter.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.DBus.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.DBus.cpython-311.pyc new file mode 100644 index 0000000..640d228 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.DBus.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GIRepository.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GIRepository.cpython-311.pyc new file mode 100644 index 0000000..a0932b6 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GIRepository.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GLib.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GLib.cpython-311.pyc new file mode 100644 index 0000000..4546efd Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GLib.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GModule.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GModule.cpython-311.pyc new file mode 100644 index 0000000..c3436fc Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GModule.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GObject.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GObject.cpython-311.pyc new file mode 100644 index 0000000..c824f61 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GObject.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Gdk.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Gdk.cpython-311.pyc new file mode 100644 index 0000000..6254041 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Gdk.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GdkPixbuf.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GdkPixbuf.cpython-311.pyc new file mode 100644 index 0000000..b88971a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GdkPixbuf.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Gio.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Gio.cpython-311.pyc new file mode 100644 index 0000000..9abbcc8 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Gio.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Graphene.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Graphene.cpython-311.pyc new file mode 100644 index 0000000..7bdca1c Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Graphene.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Gsk.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Gsk.cpython-311.pyc new file mode 100644 index 0000000..7296651 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Gsk.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Gst.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Gst.cpython-311.pyc new file mode 100644 index 0000000..cbbd38a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Gst.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstAllocators.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstAllocators.cpython-311.pyc new file mode 100644 index 0000000..5963862 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstAllocators.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstApp.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstApp.cpython-311.pyc new file mode 100644 index 0000000..a3dc336 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstApp.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstAudio.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstAudio.cpython-311.pyc new file mode 100644 index 0000000..6d3c37f Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstAudio.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstBadAudio.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstBadAudio.cpython-311.pyc new file mode 100644 index 0000000..183b6eb Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstBadAudio.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstBase.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstBase.cpython-311.pyc new file mode 100644 index 0000000..32cff71 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstBase.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstCheck.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstCheck.cpython-311.pyc new file mode 100644 index 0000000..88975b2 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstCheck.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstCodecs.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstCodecs.cpython-311.pyc new file mode 100644 index 0000000..8955524 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstCodecs.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstController.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstController.cpython-311.pyc new file mode 100644 index 0000000..07216ac Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstController.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstGL.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstGL.cpython-311.pyc new file mode 100644 index 0000000..1f2d1f6 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstGL.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstGLEGL.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstGLEGL.cpython-311.pyc new file mode 100644 index 0000000..d20e28f Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstGLEGL.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstGLWayland.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstGLWayland.cpython-311.pyc new file mode 100644 index 0000000..c8e6b55 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstGLWayland.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstGLX11.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstGLX11.cpython-311.pyc new file mode 100644 index 0000000..512e1c0 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstGLX11.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstInsertBin.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstInsertBin.cpython-311.pyc new file mode 100644 index 0000000..ca9a0f7 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstInsertBin.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstMpegts.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstMpegts.cpython-311.pyc new file mode 100644 index 0000000..e84b298 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstMpegts.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstNet.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstNet.cpython-311.pyc new file mode 100644 index 0000000..2406f01 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstNet.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstPbutils.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstPbutils.cpython-311.pyc new file mode 100644 index 0000000..0b7dc5e Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstPbutils.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstPlay.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstPlay.cpython-311.pyc new file mode 100644 index 0000000..e26e9e2 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstPlay.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstPlayer.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstPlayer.cpython-311.pyc new file mode 100644 index 0000000..99170f5 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstPlayer.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstRtp.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstRtp.cpython-311.pyc new file mode 100644 index 0000000..2e6dc63 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstRtp.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstRtsp.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstRtsp.cpython-311.pyc new file mode 100644 index 0000000..36530e5 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstRtsp.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstRtspServer.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstRtspServer.cpython-311.pyc new file mode 100644 index 0000000..a97afba Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstRtspServer.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstSdp.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstSdp.cpython-311.pyc new file mode 100644 index 0000000..966d36a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstSdp.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstTag.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstTag.cpython-311.pyc new file mode 100644 index 0000000..49c25e9 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstTag.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstTranscoder.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstTranscoder.cpython-311.pyc new file mode 100644 index 0000000..9526c16 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstTranscoder.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstVideo.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstVideo.cpython-311.pyc new file mode 100644 index 0000000..35459a7 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstVideo.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstVulkan.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstVulkan.cpython-311.pyc new file mode 100644 index 0000000..d331ecb Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstVulkan.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstVulkanWayland.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstVulkanWayland.cpython-311.pyc new file mode 100644 index 0000000..7b955c8 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstVulkanWayland.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstVulkanXCB.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstVulkanXCB.cpython-311.pyc new file mode 100644 index 0000000..db565e0 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstVulkanXCB.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstWebRTC.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstWebRTC.cpython-311.pyc new file mode 100644 index 0000000..4ac09b7 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstWebRTC.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Gtk.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Gtk.cpython-311.pyc new file mode 100644 index 0000000..9511602 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Gtk.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GtkChamplain.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GtkChamplain.cpython-311.pyc new file mode 100644 index 0000000..6b458cd Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GtkChamplain.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GtkClutter.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GtkClutter.cpython-311.pyc new file mode 100644 index 0000000..fb59830 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GtkClutter.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GtkSource.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GtkSource.cpython-311.pyc new file mode 100644 index 0000000..d9cb2a7 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GtkSource.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GtkosxApplication.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GtkosxApplication.cpython-311.pyc new file mode 100644 index 0000000..58acb41 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GtkosxApplication.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.HarfBuzz.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.HarfBuzz.cpython-311.pyc new file mode 100644 index 0000000..3c32b64 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.HarfBuzz.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Pango.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Pango.cpython-311.pyc new file mode 100644 index 0000000..7e2b400 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Pango.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.PangoCairo.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.PangoCairo.cpython-311.pyc new file mode 100644 index 0000000..9818502 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.PangoCairo.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.cairo.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.cairo.cpython-311.pyc new file mode 100644 index 0000000..bafad28 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.cairo.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.freetype2.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.freetype2.cpython-311.pyc new file mode 100644 index 0000000..fa881c7 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.freetype2.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.xlib.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.xlib.cpython-311.pyc new file mode 100644 index 0000000..f77cbd5 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.xlib.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-importlib_metadata.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-importlib_metadata.cpython-311.pyc new file mode 100644 index 0000000..15ea273 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-importlib_metadata.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-importlib_resources.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-importlib_resources.cpython-311.pyc new file mode 100644 index 0000000..42dfbcb Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-importlib_resources.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-inflect.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-inflect.cpython-311.pyc new file mode 100644 index 0000000..d7db18e Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-inflect.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-jaraco.context.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-jaraco.context.cpython-311.pyc new file mode 100644 index 0000000..7708e5f Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-jaraco.context.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-jaraco.functools.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-jaraco.functools.cpython-311.pyc new file mode 100644 index 0000000..07319ec Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-jaraco.functools.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-jaraco.text.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-jaraco.text.cpython-311.pyc new file mode 100644 index 0000000..1b4fb0a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-jaraco.text.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-more_itertools.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-more_itertools.cpython-311.pyc new file mode 100644 index 0000000..a6875c5 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-more_itertools.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-ordered_set.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-ordered_set.cpython-311.pyc new file mode 100644 index 0000000..794f5cb Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-ordered_set.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-packaging.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-packaging.cpython-311.pyc new file mode 100644 index 0000000..c261d49 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-packaging.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-platformdirs.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-platformdirs.cpython-311.pyc new file mode 100644 index 0000000..581e2c0 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-platformdirs.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-setuptools.extern.six.moves.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-setuptools.extern.six.moves.cpython-311.pyc new file mode 100644 index 0000000..8857f99 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-setuptools.extern.six.moves.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-six.moves.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-six.moves.cpython-311.pyc new file mode 100644 index 0000000..aaf3319 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-six.moves.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-tomli.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-tomli.cpython-311.pyc new file mode 100644 index 0000000..ea8b7e8 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-tomli.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-typeguard.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-typeguard.cpython-311.pyc new file mode 100644 index 0000000..c87254e Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-typeguard.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-typing_extensions.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-typing_extensions.cpython-311.pyc new file mode 100644 index 0000000..5fdafb4 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-typing_extensions.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-urllib3.packages.six.moves.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-urllib3.packages.six.moves.cpython-311.pyc new file mode 100644 index 0000000..2d02592 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-urllib3.packages.six.moves.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-wheel.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-wheel.cpython-311.pyc new file mode 100644 index 0000000..c9807e6 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-wheel.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-zipp.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-zipp.cpython-311.pyc new file mode 100644 index 0000000..8f70291 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-zipp.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-autocommand.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-autocommand.py new file mode 100644 index 0000000..83c7249 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-autocommand.py @@ -0,0 +1,15 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2024, 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) +#----------------------------------------------------------------------------- + +# This package/module might be provided by setuptools >= 71.0.0, which makes its vendored dependencies public by +# appending path to its `setuptools._vendored` directory to `sys.path`. The following shared pre-safe-import-module +# hook implementation checks whether this is the case, and sets up aliases to prevent duplicate collection. +from PyInstaller.utils.hooks.setuptools import pre_safe_import_module # noqa: F401 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-backports.tarfile.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-backports.tarfile.py new file mode 100644 index 0000000..83c7249 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-backports.tarfile.py @@ -0,0 +1,15 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2024, 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) +#----------------------------------------------------------------------------- + +# This package/module might be provided by setuptools >= 71.0.0, which makes its vendored dependencies public by +# appending path to its `setuptools._vendored` directory to `sys.path`. The following shared pre-safe-import-module +# hook implementation checks whether this is the case, and sets up aliases to prevent duplicate collection. +from PyInstaller.utils.hooks.setuptools import pre_safe_import_module # noqa: F401 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-distutils.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-distutils.py new file mode 100644 index 0000000..7f88845 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-distutils.py @@ -0,0 +1,23 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 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) +#----------------------------------------------------------------------------- + +from PyInstaller import compat +from PyInstaller.utils.hooks.setuptools import setuptools_info + + +def pre_safe_import_module(api): + # `distutils` was removed from from stdlib in python 3.12; if it is available, it is provided by `setuptools`. + # Therefore, we need to create package/module alias entries, which prevent the setuptools._distutils` and its + # submodules from being collected as top-level modules (as `distutils` and its submodules) in addition to being + # collected as their "true" names. + if compat.is_py312 and setuptools_info.distutils_vendored: + for aliased_name, real_vendored_name in setuptools_info.get_distutils_aliases(): + api.add_alias_module(real_vendored_name, aliased_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.py new file mode 100644 index 0000000..e71843d --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.py @@ -0,0 +1,37 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2022-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) +#----------------------------------------------------------------------------- + +from PyInstaller import compat +from PyInstaller.utils import hooks as hookutils + + +def pre_safe_import_module(api): + if compat.is_linux: + # RHEL/Fedora RPM package for GObject introspection is known to split the `gi` package into two locations: + # - /usr/lib64/python3.x/site-packages/gi + # - /usr/lib/python3.x/site-packages/gi + # The `__init__.py` is located in the first directory, while `repository` and `overrides` are located in + # the second, and `__init__.py` dynamically extends the `__path__` during package import, using + # `__path__ = pkgutil.extend_path(__path__, __name__)`. + # The modulegraph has no way of knowing this, so we need extend the package path in this hook. Otherwise, + # only the first location is scanned, and the `gi.repository` ends up missing. + # + # NOTE: the `get_package_paths`/`get_package_all_paths` helpers read the paths from package's spec without + # importing the (top-level) package, so they do not catch run-time path modifications. Instead, we use + # `get_module_attribute` to import the package in isolated process and query its `__path__` attribute. + try: + paths = hookutils.get_module_attribute(api.module_name, "__path__") + except Exception: + # Most likely `gi` cannot be imported. + paths = [] + + for path in paths: + api.append_package_path(path) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Adw.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Adw.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Adw.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.AppIndicator3.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.AppIndicator3.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.AppIndicator3.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Atk.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Atk.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Atk.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.AyatanaAppIndicator3.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.AyatanaAppIndicator3.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.AyatanaAppIndicator3.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Champlain.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Champlain.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Champlain.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Clutter.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Clutter.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Clutter.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.DBus.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.DBus.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.DBus.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GIRepository.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GIRepository.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GIRepository.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GLib.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GLib.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GLib.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GModule.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GModule.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GModule.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GObject.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GObject.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GObject.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Gdk.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Gdk.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Gdk.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GdkPixbuf.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GdkPixbuf.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GdkPixbuf.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Gio.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Gio.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Gio.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Graphene.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Graphene.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Graphene.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Gsk.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Gsk.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Gsk.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Gst.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Gst.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Gst.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstAllocators.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstAllocators.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstAllocators.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstApp.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstApp.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstApp.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstAudio.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstAudio.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstAudio.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstBadAudio.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstBadAudio.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstBadAudio.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstBase.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstBase.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstBase.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstCheck.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstCheck.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstCheck.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstCodecs.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstCodecs.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstCodecs.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstController.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstController.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstController.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstGL.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstGL.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstGL.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstGLEGL.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstGLEGL.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstGLEGL.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstGLWayland.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstGLWayland.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstGLWayland.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstGLX11.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstGLX11.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstGLX11.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstInsertBin.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstInsertBin.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstInsertBin.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstMpegts.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstMpegts.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstMpegts.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstNet.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstNet.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstNet.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstPbutils.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstPbutils.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstPbutils.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstPlay.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstPlay.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstPlay.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstPlayer.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstPlayer.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstPlayer.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstRtp.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstRtp.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstRtp.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstRtsp.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstRtsp.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstRtsp.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstRtspServer.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstRtspServer.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstRtspServer.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstSdp.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstSdp.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstSdp.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstTag.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstTag.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstTag.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstTranscoder.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstTranscoder.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstTranscoder.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstVideo.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstVideo.py new file mode 100644 index 0000000..e75bfee --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstVideo.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert + # them to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstVulkan.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstVulkan.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstVulkan.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstVulkanWayland.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstVulkanWayland.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstVulkanWayland.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstVulkanXCB.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstVulkanXCB.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstVulkanXCB.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstWebRTC.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstWebRTC.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstWebRTC.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Gtk.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Gtk.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Gtk.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GtkChamplain.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GtkChamplain.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GtkChamplain.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GtkClutter.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GtkClutter.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GtkClutter.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GtkSource.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GtkSource.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GtkSource.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GtkosxApplication.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GtkosxApplication.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GtkosxApplication.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.HarfBuzz.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.HarfBuzz.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.HarfBuzz.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Pango.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Pango.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Pango.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.PangoCairo.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.PangoCairo.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.PangoCairo.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.cairo.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.cairo.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.cairo.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.freetype2.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.freetype2.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.freetype2.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.xlib.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.xlib.py new file mode 100644 index 0000000..131ce95 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.xlib.py @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + + +def pre_safe_import_module(api): + # PyGObject modules loaded through the gi repository are marked as MissingModules by modulegraph, so we convert them + # to RuntimeModules in order for their hooks to be loaded and executed. + api.add_runtime_module(api.module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-importlib_metadata.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-importlib_metadata.py new file mode 100644 index 0000000..83c7249 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-importlib_metadata.py @@ -0,0 +1,15 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2024, 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) +#----------------------------------------------------------------------------- + +# This package/module might be provided by setuptools >= 71.0.0, which makes its vendored dependencies public by +# appending path to its `setuptools._vendored` directory to `sys.path`. The following shared pre-safe-import-module +# hook implementation checks whether this is the case, and sets up aliases to prevent duplicate collection. +from PyInstaller.utils.hooks.setuptools import pre_safe_import_module # noqa: F401 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-importlib_resources.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-importlib_resources.py new file mode 100644 index 0000000..83c7249 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-importlib_resources.py @@ -0,0 +1,15 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2024, 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) +#----------------------------------------------------------------------------- + +# This package/module might be provided by setuptools >= 71.0.0, which makes its vendored dependencies public by +# appending path to its `setuptools._vendored` directory to `sys.path`. The following shared pre-safe-import-module +# hook implementation checks whether this is the case, and sets up aliases to prevent duplicate collection. +from PyInstaller.utils.hooks.setuptools import pre_safe_import_module # noqa: F401 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-inflect.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-inflect.py new file mode 100644 index 0000000..83c7249 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-inflect.py @@ -0,0 +1,15 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2024, 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) +#----------------------------------------------------------------------------- + +# This package/module might be provided by setuptools >= 71.0.0, which makes its vendored dependencies public by +# appending path to its `setuptools._vendored` directory to `sys.path`. The following shared pre-safe-import-module +# hook implementation checks whether this is the case, and sets up aliases to prevent duplicate collection. +from PyInstaller.utils.hooks.setuptools import pre_safe_import_module # noqa: F401 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-jaraco.context.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-jaraco.context.py new file mode 100644 index 0000000..83c7249 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-jaraco.context.py @@ -0,0 +1,15 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2024, 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) +#----------------------------------------------------------------------------- + +# This package/module might be provided by setuptools >= 71.0.0, which makes its vendored dependencies public by +# appending path to its `setuptools._vendored` directory to `sys.path`. The following shared pre-safe-import-module +# hook implementation checks whether this is the case, and sets up aliases to prevent duplicate collection. +from PyInstaller.utils.hooks.setuptools import pre_safe_import_module # noqa: F401 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-jaraco.functools.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-jaraco.functools.py new file mode 100644 index 0000000..83c7249 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-jaraco.functools.py @@ -0,0 +1,15 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2024, 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) +#----------------------------------------------------------------------------- + +# This package/module might be provided by setuptools >= 71.0.0, which makes its vendored dependencies public by +# appending path to its `setuptools._vendored` directory to `sys.path`. The following shared pre-safe-import-module +# hook implementation checks whether this is the case, and sets up aliases to prevent duplicate collection. +from PyInstaller.utils.hooks.setuptools import pre_safe_import_module # noqa: F401 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-jaraco.text.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-jaraco.text.py new file mode 100644 index 0000000..83c7249 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-jaraco.text.py @@ -0,0 +1,15 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2024, 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) +#----------------------------------------------------------------------------- + +# This package/module might be provided by setuptools >= 71.0.0, which makes its vendored dependencies public by +# appending path to its `setuptools._vendored` directory to `sys.path`. The following shared pre-safe-import-module +# hook implementation checks whether this is the case, and sets up aliases to prevent duplicate collection. +from PyInstaller.utils.hooks.setuptools import pre_safe_import_module # noqa: F401 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-more_itertools.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-more_itertools.py new file mode 100644 index 0000000..83c7249 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-more_itertools.py @@ -0,0 +1,15 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2024, 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) +#----------------------------------------------------------------------------- + +# This package/module might be provided by setuptools >= 71.0.0, which makes its vendored dependencies public by +# appending path to its `setuptools._vendored` directory to `sys.path`. The following shared pre-safe-import-module +# hook implementation checks whether this is the case, and sets up aliases to prevent duplicate collection. +from PyInstaller.utils.hooks.setuptools import pre_safe_import_module # noqa: F401 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-ordered_set.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-ordered_set.py new file mode 100644 index 0000000..83c7249 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-ordered_set.py @@ -0,0 +1,15 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2024, 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) +#----------------------------------------------------------------------------- + +# This package/module might be provided by setuptools >= 71.0.0, which makes its vendored dependencies public by +# appending path to its `setuptools._vendored` directory to `sys.path`. The following shared pre-safe-import-module +# hook implementation checks whether this is the case, and sets up aliases to prevent duplicate collection. +from PyInstaller.utils.hooks.setuptools import pre_safe_import_module # noqa: F401 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-packaging.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-packaging.py new file mode 100644 index 0000000..83c7249 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-packaging.py @@ -0,0 +1,15 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2024, 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) +#----------------------------------------------------------------------------- + +# This package/module might be provided by setuptools >= 71.0.0, which makes its vendored dependencies public by +# appending path to its `setuptools._vendored` directory to `sys.path`. The following shared pre-safe-import-module +# hook implementation checks whether this is the case, and sets up aliases to prevent duplicate collection. +from PyInstaller.utils.hooks.setuptools import pre_safe_import_module # noqa: F401 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-platformdirs.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-platformdirs.py new file mode 100644 index 0000000..83c7249 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-platformdirs.py @@ -0,0 +1,15 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2024, 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) +#----------------------------------------------------------------------------- + +# This package/module might be provided by setuptools >= 71.0.0, which makes its vendored dependencies public by +# appending path to its `setuptools._vendored` directory to `sys.path`. The following shared pre-safe-import-module +# hook implementation checks whether this is the case, and sets up aliases to prevent duplicate collection. +from PyInstaller.utils.hooks.setuptools import pre_safe_import_module # noqa: F401 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-setuptools.extern.six.moves.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-setuptools.extern.six.moves.py new file mode 100644 index 0000000..5a09a89 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-setuptools.extern.six.moves.py @@ -0,0 +1,39 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller import isolated + +# This is basically a copy of pre_safe_import_module/hook-six.moves.py adopted to setuptools.extern.six resp. +# setuptools._vendor.six. Please see pre_safe_import_module/hook-six.moves.py for documentation. + +# Note that the moves are defined in 'setuptools._vendor.six' but are imported under 'setuptools.extern.six'. + + +def pre_safe_import_module(api): + @isolated.call + def real_to_six_module_name(): + try: + import setuptools._vendor.six as six + except ImportError: + try: + import setuptools.extern.six as six + except ImportError: + return None # unavailable + + return { + moved.mod: 'setuptools.extern.six.moves.' + moved.name + for moved in six._moved_attributes if isinstance(moved, (six.MovedModule, six.MovedAttribute)) + } + + if real_to_six_module_name is not None: + api.add_runtime_package(api.module_name) + for real_module_name, six_module_name in real_to_six_module_name.items(): + api.add_alias_module(real_module_name, six_module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-six.moves.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-six.moves.py new file mode 100644 index 0000000..1c86669 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-six.moves.py @@ -0,0 +1,62 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller import isolated + + +def pre_safe_import_module(api): + """ + Add the `six.moves` module as a dynamically defined runtime module node and all modules mapped by + `six._SixMetaPathImporter` as aliased module nodes to the passed graph. + + The `six.moves` module is dynamically defined at runtime by the `six` module and hence cannot be imported in the + standard way. Instead, this hook adds a placeholder node for the `six.moves` module to the graph, + which implicitly adds an edge from that node to the node for its parent `six` module. This ensures that the `six` + module will be frozen into the executable. (Phew!) + + `six._SixMetaPathImporter` is a PEP 302-compliant module importer converting imports independent of the current + Python version into imports specific to that version (e.g., under Python 3, from `from six.moves import + tkinter_tix` to `import tkinter.tix`). For each such mapping, this hook adds a corresponding module alias to the + graph allowing PyInstaller to translate the former to the latter. + """ + @isolated.call + def real_to_six_module_name(): + """ + Generate a dictionary from conventional module names to "six.moves" attribute names (e.g., from `tkinter.tix` to + `six.moves.tkinter_tix`). + """ + try: + import six + except ImportError: + return None # unavailable + + # Iterate over the "six._moved_attributes" list rather than the "six._importer.known_modules" dictionary, as + # "urllib"-specific moved modules are overwritten in the latter with unhelpful "LazyModule" objects. If this is + # a moved module or attribute, map the corresponding module. In the case of moved attributes, the attribute's + # module is mapped while the attribute itself is mapped at runtime and hence ignored here. + return { + moved.mod: 'six.moves.' + moved.name + for moved in six._moved_attributes if isinstance(moved, (six.MovedModule, six.MovedAttribute)) + } + + # Add "six.moves" as a runtime package rather than module. Modules cannot physically contain submodules; only + # packages can. In "from"-style import statements (e.g., "from six.moves import queue"), this implies that: + # * Attributes imported from customary modules are guaranteed *NOT* to be submodules. Hence, ModuleGraph justifiably + # ignores these attributes. While some attributes declared by "six.moves" are ignorable non-modules (e.g., + # functions, classes), others are non-ignorable submodules that must be imported. Adding "six.moves" as a runtime + # module causes ModuleGraph to ignore these submodules, which defeats the entire point. + # * Attributes imported from packages could be submodules. To disambiguate non-ignorable submodules from ignorable + # non-submodules (e.g., classes, variables), ModuleGraph first attempts to import these attributes as submodules. + # This is exactly what we want. + if real_to_six_module_name is not None: + api.add_runtime_package(api.module_name) + for real_module_name, six_module_name in real_to_six_module_name.items(): + api.add_alias_module(real_module_name, six_module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-tomli.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-tomli.py new file mode 100644 index 0000000..83c7249 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-tomli.py @@ -0,0 +1,15 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2024, 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) +#----------------------------------------------------------------------------- + +# This package/module might be provided by setuptools >= 71.0.0, which makes its vendored dependencies public by +# appending path to its `setuptools._vendored` directory to `sys.path`. The following shared pre-safe-import-module +# hook implementation checks whether this is the case, and sets up aliases to prevent duplicate collection. +from PyInstaller.utils.hooks.setuptools import pre_safe_import_module # noqa: F401 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-typeguard.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-typeguard.py new file mode 100644 index 0000000..83c7249 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-typeguard.py @@ -0,0 +1,15 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2024, 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) +#----------------------------------------------------------------------------- + +# This package/module might be provided by setuptools >= 71.0.0, which makes its vendored dependencies public by +# appending path to its `setuptools._vendored` directory to `sys.path`. The following shared pre-safe-import-module +# hook implementation checks whether this is the case, and sets up aliases to prevent duplicate collection. +from PyInstaller.utils.hooks.setuptools import pre_safe_import_module # noqa: F401 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-typing_extensions.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-typing_extensions.py new file mode 100644 index 0000000..83c7249 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-typing_extensions.py @@ -0,0 +1,15 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2024, 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) +#----------------------------------------------------------------------------- + +# This package/module might be provided by setuptools >= 71.0.0, which makes its vendored dependencies public by +# appending path to its `setuptools._vendored` directory to `sys.path`. The following shared pre-safe-import-module +# hook implementation checks whether this is the case, and sets up aliases to prevent duplicate collection. +from PyInstaller.utils.hooks.setuptools import pre_safe_import_module # noqa: F401 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-urllib3.packages.six.moves.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-urllib3.packages.six.moves.py new file mode 100644 index 0000000..d257f83 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-urllib3.packages.six.moves.py @@ -0,0 +1,34 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +from PyInstaller import isolated + +# This basically is a copy of pre_safe_import_module/hook-six.moves.py adopted to urllib3.packages.six. Please see +# pre_safe_import_module/hook-six.moves.py for documentation. + + +def pre_safe_import_module(api): + @isolated.call + def real_to_six_module_name(): + try: + import urllib3.packages.six as six + except ImportError: + return None # unavailable + + return { + moved.mod: 'urllib3.packages.six.moves.' + moved.name + for moved in six._moved_attributes if isinstance(moved, (six.MovedModule, six.MovedAttribute)) + } + + if real_to_six_module_name is not None: + api.add_runtime_package(api.module_name) + for real_module_name, six_module_name in real_to_six_module_name.items(): + api.add_alias_module(real_module_name, six_module_name) diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-wheel.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-wheel.py new file mode 100644 index 0000000..83c7249 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-wheel.py @@ -0,0 +1,15 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2024, 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) +#----------------------------------------------------------------------------- + +# This package/module might be provided by setuptools >= 71.0.0, which makes its vendored dependencies public by +# appending path to its `setuptools._vendored` directory to `sys.path`. The following shared pre-safe-import-module +# hook implementation checks whether this is the case, and sets up aliases to prevent duplicate collection. +from PyInstaller.utils.hooks.setuptools import pre_safe_import_module # noqa: F401 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-zipp.py b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-zipp.py new file mode 100644 index 0000000..83c7249 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/pre_safe_import_module/hook-zipp.py @@ -0,0 +1,15 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2024, 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) +#----------------------------------------------------------------------------- + +# This package/module might be provided by setuptools >= 71.0.0, which makes its vendored dependencies public by +# appending path to its `setuptools._vendored` directory to `sys.path`. The following shared pre-safe-import-module +# hook implementation checks whether this is the case, and sets up aliases to prevent duplicate collection. +from PyInstaller.utils.hooks.setuptools import pre_safe_import_module # noqa: F401 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks.dat b/venv/Lib/site-packages/PyInstaller/hooks/rthooks.dat new file mode 100644 index 0000000..c024452 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/rthooks.dat @@ -0,0 +1,23 @@ +{ + 'django': ['pyi_rth_django.py'], + 'gi': ['pyi_rth_gi.py'], + 'gi.repository.Gio': ['pyi_rth_gio.py'], + 'gi.repository.GLib': ['pyi_rth_glib.py'], + 'gi.repository.GdkPixbuf': ['pyi_rth_gdkpixbuf.py'], + 'gi.repository.Gtk': ['pyi_rth_gtk.py'], + 'gi.repository.Gst': ['pyi_rth_gstreamer.py'], + 'gst': ['pyi_rth_gstreamer.py'], + 'inspect': ['pyi_rth_inspect.py'], + 'kivy': ['pyi_rth_kivy.py'], + 'kivy.lib.gstplayer': ['pyi_rth_gstreamer.py'], + 'matplotlib': ['pyi_rth_mplconfig.py'], + 'pkgutil': ['pyi_rth_pkgutil.py'], + 'pkg_resources': ['pyi_rth_pkgres.py'], + 'PyQt5': ['pyi_rth_pyqt5.py'], + 'PyQt6': ['pyi_rth_pyqt6.py'], + 'PySide2': ['pyi_rth_pyside2.py'], + 'PySide6': ['pyi_rth_pyside6.py'], + '_tkinter': ['pyi_rth__tkinter.py'], + 'multiprocessing': ['pyi_rth_multiprocessing.py'], + 'setuptools': ['pyi_rth_setuptools.py'], +} diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__init__.py b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__init__.py new file mode 100644 index 0000000..792d600 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__init__.py @@ -0,0 +1 @@ +# diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..f92a869 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth__tkinter.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth__tkinter.cpython-311.pyc new file mode 100644 index 0000000..c6deef9 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth__tkinter.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_django.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_django.cpython-311.pyc new file mode 100644 index 0000000..1cd9e0d Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_django.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_gdkpixbuf.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_gdkpixbuf.cpython-311.pyc new file mode 100644 index 0000000..a2868d7 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_gdkpixbuf.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_gi.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_gi.cpython-311.pyc new file mode 100644 index 0000000..f918284 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_gi.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_gio.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_gio.cpython-311.pyc new file mode 100644 index 0000000..96ae77e Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_gio.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_glib.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_glib.cpython-311.pyc new file mode 100644 index 0000000..69e3149 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_glib.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_gstreamer.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_gstreamer.cpython-311.pyc new file mode 100644 index 0000000..2a47edc Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_gstreamer.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_gtk.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_gtk.cpython-311.pyc new file mode 100644 index 0000000..df2ee4a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_gtk.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_inspect.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_inspect.cpython-311.pyc new file mode 100644 index 0000000..e16bd0d Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_inspect.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_kivy.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_kivy.cpython-311.pyc new file mode 100644 index 0000000..7f1faa2 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_kivy.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_mplconfig.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_mplconfig.cpython-311.pyc new file mode 100644 index 0000000..0062dac Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_mplconfig.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_multiprocessing.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_multiprocessing.cpython-311.pyc new file mode 100644 index 0000000..a820c3d Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_multiprocessing.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_pkgres.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_pkgres.cpython-311.pyc new file mode 100644 index 0000000..d800002 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_pkgres.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_pkgutil.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_pkgutil.cpython-311.pyc new file mode 100644 index 0000000..af1a724 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_pkgutil.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_pyqt5.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_pyqt5.cpython-311.pyc new file mode 100644 index 0000000..b3482da Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_pyqt5.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_pyqt6.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_pyqt6.cpython-311.pyc new file mode 100644 index 0000000..e293c62 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_pyqt6.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_pyside2.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_pyside2.cpython-311.pyc new file mode 100644 index 0000000..67d3379 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_pyside2.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_pyside6.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_pyside6.cpython-311.pyc new file mode 100644 index 0000000..e535a6b Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_pyside6.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_setuptools.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_setuptools.cpython-311.pyc new file mode 100644 index 0000000..a9b5075 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/__pycache__/pyi_rth_setuptools.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth__tkinter.py b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth__tkinter.py new file mode 100644 index 0000000..ae154f8 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth__tkinter.py @@ -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 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_django.py b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_django.py new file mode 100644 index 0000000..81243bd --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_django.py @@ -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 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_gdkpixbuf.py b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_gdkpixbuf.py new file mode 100644 index 0000000..0bb7a37 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_gdkpixbuf.py @@ -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 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_gi.py b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_gi.py new file mode 100644 index 0000000..3c3b382 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_gi.py @@ -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 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_gio.py b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_gio.py new file mode 100644 index 0000000..f9fc307 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_gio.py @@ -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 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_glib.py b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_glib.py new file mode 100644 index 0000000..35bd7f8 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_glib.py @@ -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 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_gstreamer.py b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_gstreamer.py new file mode 100644 index 0000000..ec3495c --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_gstreamer.py @@ -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 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_gtk.py b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_gtk.py new file mode 100644 index 0000000..d6ae21c --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_gtk.py @@ -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 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_inspect.py b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_inspect.py new file mode 100644 index 0000000..976d78b --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_inspect.py @@ -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 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_kivy.py b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_kivy.py new file mode 100644 index 0000000..0846401 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_kivy.py @@ -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 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_mplconfig.py b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_mplconfig.py new file mode 100644 index 0000000..93fec80 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_mplconfig.py @@ -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 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_multiprocessing.py b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_multiprocessing.py new file mode 100644 index 0000000..f596d93 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_multiprocessing.py @@ -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 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_pkgres.py b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_pkgres.py new file mode 100644 index 0000000..f84ae31 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_pkgres.py @@ -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 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py new file mode 100644 index 0000000..8337fa3 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py @@ -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 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_pyqt5.py b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_pyqt5.py new file mode 100644 index 0000000..fa388e8 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_pyqt5.py @@ -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 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_pyqt6.py b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_pyqt6.py new file mode 100644 index 0000000..d3ed0cd --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_pyqt6.py @@ -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 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_pyside2.py b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_pyside2.py new file mode 100644 index 0000000..3aca93b --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_pyside2.py @@ -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 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_pyside6.py b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_pyside6.py new file mode 100644 index 0000000..73db137 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_pyside6.py @@ -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 diff --git a/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_setuptools.py b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_setuptools.py new file mode 100644 index 0000000..0a3ffb8 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/hooks/rthooks/pyi_rth_setuptools.py @@ -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 diff --git a/venv/Lib/site-packages/PyInstaller/isolated/__init__.py b/venv/Lib/site-packages/PyInstaller/isolated/__init__.py new file mode 100644 index 0000000..3016e7d --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/isolated/__init__.py @@ -0,0 +1,31 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2021-2023, PyInstaller Development Team. +# +# Distributed under the terms of the GNU General Public License (version 2 +# or later) or, at the user's discretion, the MIT License. +# +# The full license is in the file COPYING.txt, distributed with this software. +# +# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception OR MIT) +# ----------------------------------------------------------------------------- +""" +PyInstaller hooks typically will need to import the package which they are written for but doing so may manipulate +globals such as :data:`sys.path` or :data:`os.environ` in ways that affect the build. For example, on Windows, +Qt's binaries are added to then loaded via ``PATH`` in such a way that if you import multiple Qt variants in one +session then there is no guarantee which variant's binaries each variant will get! + +To get around this, PyInstaller does any such tasks in an isolated Python subprocess and ships a +:mod:`PyInstaller.isolated` submodule to do so in hooks. :: + + from PyInstaller import isolated + +This submodule provides: + +* :func:`isolated.call() ` to evaluate functions in isolation. +* :func:`@isolated.decorate ` to mark a function as always called in isolation. +* :class:`isolated.Python() ` to efficiently call many functions in a single child instance of Python. + +""" + +# flake8: noqa +from ._parent import Python, call, decorate, SubprocessDiedError diff --git a/venv/Lib/site-packages/PyInstaller/isolated/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/isolated/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..a8181c0 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/isolated/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/isolated/__pycache__/_child.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/isolated/__pycache__/_child.cpython-311.pyc new file mode 100644 index 0000000..28c1348 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/isolated/__pycache__/_child.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/isolated/__pycache__/_parent.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/isolated/__pycache__/_parent.cpython-311.pyc new file mode 100644 index 0000000..9fc0a17 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/isolated/__pycache__/_parent.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/isolated/_child.py b/venv/Lib/site-packages/PyInstaller/isolated/_child.py new file mode 100644 index 0000000..0709b68 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/isolated/_child.py @@ -0,0 +1,101 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2021-2023, PyInstaller Development Team. +# +# Distributed under the terms of the GNU General Public License (version 2 +# or later) or, at the user's discretion, the MIT License. +# +# The full license is in the file COPYING.txt, distributed with this software. +# +# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception OR MIT) +# ----------------------------------------------------------------------------- +""" +The child process to be invoked by IsolatedPython(). + +This file is to be run directly with pipe handles for reading from and writing to the parent process as command line +arguments. + +""" + +import sys +import os +import types +from marshal import loads, dumps +from base64 import b64encode, b64decode +from traceback import format_exception + +if os.name == "nt": + from msvcrt import open_osfhandle + + def _open(osf_handle, mode): + # Convert system file handles to file descriptors before opening them. + return open(open_osfhandle(osf_handle, 0), mode) +else: + _open = open + + +def run_next_command(read_fh, write_fh): + """ + Listen to **read_fh** for the next function to run. Write the result to **write_fh**. + """ + + # Check the first line of input. Receiving an empty line is the signal that there are no more tasks to be ran. + first_line = read_fh.readline() + if first_line == b"\n": + # It's time to end this child process + return False + + # There are 5 lines to read: The function's code, its default args, its default kwargs, its args, and its kwargs. + code = loads(b64decode(first_line.strip())) + _defaults = loads(b64decode(read_fh.readline().strip())) + _kwdefaults = loads(b64decode(read_fh.readline().strip())) + args = loads(b64decode(read_fh.readline().strip())) + kwargs = loads(b64decode(read_fh.readline().strip())) + + try: + # Define the global namespace available to the function. + GLOBALS = {"__builtins__": __builtins__, "__isolated__": True} + # Reconstruct the function. + function = types.FunctionType(code, GLOBALS) + function.__defaults__ = _defaults + function.__kwdefaults__ = _kwdefaults + + # Run it. + output = function(*args, **kwargs) + + # Verify that the output is serialise-able (i.e. no custom types or module or function references) here so that + # it's caught if it fails. + marshalled = dumps((True, output)) + + except BaseException as ex: + # An exception happened whilst either running the function or serialising its output. Send back a string + # version of the traceback (unfortunately raw traceback objects are not marshal-able) and a boolean to say + # that it failed. + tb_lines = format_exception(type(ex), ex, ex.__traceback__) + if tb_lines[0] == "Traceback (most recent call last):\n": + # This particular line is distracting. Get rid of it. + tb_lines = tb_lines[1:] + marshalled = dumps((False, "".join(tb_lines).rstrip())) + + # Send the output (return value or traceback) back to the parent. + write_fh.write(b64encode(marshalled)) + write_fh.write(b"\n") + write_fh.flush() + + # Signal that an instruction was ran (successfully or otherwise). + return True + + +if __name__ == '__main__': + # Mark this process as PyInstaller's isolated subprocess; this makes attempts at spawning further isolated + # subprocesses via `PyInstaller.isolated` from this process no-op. + sys._pyi_isolated_subprocess = True + + read_from_parent, write_to_parent = map(int, sys.argv[1:]) + + with _open(read_from_parent, "rb") as read_fh: + with _open(write_to_parent, "wb") as write_fh: + sys.path = loads(b64decode(read_fh.readline())) + + # Keep receiving and running instructions until the parent sends the signal to stop. + while run_next_command(read_fh, write_fh): + pass diff --git a/venv/Lib/site-packages/PyInstaller/isolated/_parent.py b/venv/Lib/site-packages/PyInstaller/isolated/_parent.py new file mode 100644 index 0000000..0998e93 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/isolated/_parent.py @@ -0,0 +1,437 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2021-2023, PyInstaller Development Team. +# +# Distributed under the terms of the GNU General Public License (version 2 +# or later) or, at the user's discretion, the MIT License. +# +# The full license is in the file COPYING.txt, distributed with this software. +# +# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception OR MIT) +# ----------------------------------------------------------------------------- + +import os +from pathlib import Path +from marshal import loads, dumps +from base64 import b64encode, b64decode +import functools +import subprocess +import sys + +from PyInstaller import compat +from PyInstaller import log as logging + +logger = logging.getLogger(__name__) + +# WinAPI bindings for Windows-specific codepath +if os.name == "nt": + import msvcrt + import ctypes + import ctypes.wintypes + + # CreatePipe + class SECURITY_ATTRIBUTES(ctypes.Structure): + _fields_ = [ + ("nLength", ctypes.wintypes.DWORD), + ("lpSecurityDescriptor", ctypes.wintypes.LPVOID), + ("bInheritHandle", ctypes.wintypes.BOOL), + ] + + HANDLE_FLAG_INHERIT = 0x0001 + + LPSECURITY_ATTRIBUTES = ctypes.POINTER(SECURITY_ATTRIBUTES) + + CreatePipe = ctypes.windll.kernel32.CreatePipe + CreatePipe.argtypes = [ + ctypes.POINTER(ctypes.wintypes.HANDLE), + ctypes.POINTER(ctypes.wintypes.HANDLE), + LPSECURITY_ATTRIBUTES, + ctypes.wintypes.DWORD, + ] + CreatePipe.restype = ctypes.wintypes.BOOL + + # CloseHandle + CloseHandle = ctypes.windll.kernel32.CloseHandle + CloseHandle.argtypes = [ctypes.wintypes.HANDLE] + CloseHandle.restype = ctypes.wintypes.BOOL + +CHILD_PY = Path(__file__).with_name("_child.py") + + +def create_pipe(read_handle_inheritable, write_handle_inheritable): + """ + Create a one-way pipe for sending data to child processes. + + Args: + read_handle_inheritable: + A boolean flag indicating whether the handle corresponding to the read end-point of the pipe should be + marked as inheritable by subprocesses. + write_handle_inheritable: + A boolean flag indicating whether the handle corresponding to the write end-point of the pipe should be + marked as inheritable by subprocesses. + + Returns: + A read/write pair of file descriptors (which are just integers) on posix or system file handles on Windows. + + The pipe may be used either by this process or subprocesses of this process but not globally. + """ + return _create_pipe_impl(read_handle_inheritable, write_handle_inheritable) + + +def close_pipe_endpoint(pipe_handle): + """ + Close the file descriptor (posix) or handle (Windows) belonging to a pipe. + """ + return _close_pipe_endpoint_impl(pipe_handle) + + +if os.name == "nt": + + def _create_pipe_impl(read_handle_inheritable, write_handle_inheritable): + # Use WinAPI CreatePipe function to create the pipe. Python's os.pipe() does the same, but wraps the resulting + # handles into inheritable file descriptors (https://github.com/python/cpython/issues/77046). Instead, we want + # just handles, and will set the inheritable flag on corresponding handle ourselves. + read_handle = ctypes.wintypes.HANDLE() + write_handle = ctypes.wintypes.HANDLE() + + # SECURITY_ATTRIBUTES with inherit handle set to True + security_attributes = SECURITY_ATTRIBUTES() + security_attributes.nLength = ctypes.sizeof(security_attributes) + security_attributes.bInheritHandle = True + security_attributes.lpSecurityDescriptor = None + + # CreatePipe() + succeeded = CreatePipe( + ctypes.byref(read_handle), # hReadPipe + ctypes.byref(write_handle), # hWritePipe + ctypes.byref(security_attributes), # lpPipeAttributes + 0, # nSize + ) + if not succeeded: + raise ctypes.WinError() + + # Set inheritable flags. Instead of binding and using SetHandleInformation WinAPI function, we can use + # os.set_handle_inheritable(). + os.set_handle_inheritable(read_handle.value, read_handle_inheritable) + os.set_handle_inheritable(write_handle.value, write_handle_inheritable) + + return read_handle.value, write_handle.value + + def _close_pipe_endpoint_impl(pipe_handle): + succeeded = CloseHandle(pipe_handle) + if not succeeded: + raise ctypes.WinError() +else: + + def _create_pipe_impl(read_fd_inheritable, write_fd_inheritable): + # Create pipe, using os.pipe() + read_fd, write_fd = os.pipe() + + # The default behaviour of pipes is that they are process specific. I.e., they can only be used by this + # process to talk to itself. Setting inheritable flags means that child processes may also use these pipes. + os.set_inheritable(read_fd, read_fd_inheritable) + os.set_inheritable(write_fd, write_fd_inheritable) + + return read_fd, write_fd + + def _close_pipe_endpoint_impl(pipe_fd): + os.close(pipe_fd) + + +def child(read_from_parent: int, write_to_parent: int): + """ + Spawn a Python subprocess sending it the two file descriptors it needs to talk back to this parent process. + """ + if os.name != 'nt': + # Explicitly disabling close_fds is a requirement for making file descriptors inheritable by child processes. + extra_kwargs = { + "env": _subprocess_env(), + "close_fds": False, + } + else: + # On Windows, we can use subprocess.STARTUPINFO to explicitly pass the list of file handles to be inherited, + # so we can avoid disabling close_fds + extra_kwargs = { + "env": _subprocess_env(), + "close_fds": True, + "startupinfo": subprocess.STARTUPINFO(lpAttributeList={"handle_list": [read_from_parent, write_to_parent]}) + } + + # Run the _child.py script directly passing it the two file descriptors it needs to talk back to the parent. + cmd, options = compat.__wrap_python([str(CHILD_PY), str(read_from_parent), str(write_to_parent)], extra_kwargs) + + # I'm intentionally leaving stdout and stderr alone so that print() can still be used for emergency debugging and + # unhandled errors in the child are still visible. + return subprocess.Popen(cmd, **options) + + +def _subprocess_env(): + """ + Define the environment variables to be readable in a child process. + """ + from PyInstaller.config import CONF + python_path = CONF["pathex"] + if "PYTHONPATH" in os.environ: + python_path = python_path + [os.environ["PYTHONPATH"]] + env = os.environ.copy() + env["PYTHONPATH"] = os.pathsep.join(python_path) + return env + + +class SubprocessDiedError(RuntimeError): + pass + + +class Python: + """ + Start and connect to a separate Python subprocess. + + This is the lowest level of public API provided by this module. The advantage of using this class directly is + that it allows multiple functions to be evaluated in a single subprocess, making it faster than multiple calls to + :func:`call`. + + The ``strict_mode`` argument controls behavior when the child process fails to shut down; if strict mode is enabled, + an error is raised, otherwise only warning is logged. If the value of ``strict_mode`` is ``None``, the value of + ``PyInstaller.compat.strict_collect_mode`` is used (which in turn is controlled by the + ``PYINSTALLER_STRICT_COLLECT_MODE`` environment variable. + + Examples: + To call some predefined functions ``x = foo()``, ``y = bar("numpy")`` and ``z = bazz(some_flag=True)`` all using + the same isolated subprocess use:: + + with isolated.Python() as child: + x = child.call(foo) + y = child.call(bar, "numpy") + z = child.call(bazz, some_flag=True) + + """ + def __init__(self, strict_mode=None): + self._child = None + + # Re-use the compat.strict_collect_mode and its PYINSTALLER_STRICT_COLLECT_MODE environment variable for + # default strict-mode setting. + self._strict_mode = strict_mode if strict_mode is not None else compat.strict_collect_mode + + # Check if we are already running in PyInstaller's isolated subprocess, to prevent further nesting. + self._already_isolated = getattr(sys, '_pyi_isolated_subprocess', False) + + def __enter__(self): + # No-op if already running in an isolated subprocess. + if self._already_isolated: + return self + + # We need two pipes. One for the child to send data to the parent. The (write) end-point passed to the + # child needs to be marked as inheritable. + read_from_child, write_to_parent = create_pipe(False, True) + # And one for the parent to send data to the child. The (read) end-point passed to the child needs to be + # marked as inheritable. + read_from_parent, write_to_child = create_pipe(True, False) + + # Spawn a Python subprocess sending it the two file descriptors it needs to talk back to this parent process. + self._child = child(read_from_parent, write_to_parent) + + # Close the end-points that were inherited by the child. + close_pipe_endpoint(read_from_parent) + close_pipe_endpoint(write_to_parent) + del read_from_parent + del write_to_parent + + # Open file handles to talk to the child. This should fully transfer ownership of the underlying file + # descriptor to the opened handle; so when we close the latter, the former should be closed as well. + if os.name == 'nt': + # On Windows, we must first open file descriptor on top of the handle using _open_osfhandle (which + # python wraps in msvcrt.open_osfhandle). According to MSDN, this transfers the ownership of the + # underlying file handle to the file descriptors; i.e., they are both closed when the file descriptor + # is closed). + self._write_handle = os.fdopen(msvcrt.open_osfhandle(write_to_child, 0), "wb") + self._read_handle = os.fdopen(msvcrt.open_osfhandle(read_from_child, 0), "rb") + else: + self._write_handle = os.fdopen(write_to_child, "wb") + self._read_handle = os.fdopen(read_from_child, "rb") + + self._send(sys.path) + + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + # No-op if already running in an isolated subprocess. + if self._already_isolated: + return + + if exc_type and issubclass(exc_type, SubprocessDiedError): + self._write_handle.close() + self._read_handle.close() + del self._read_handle, self._write_handle + self._child = None + return + # Send the signal (a blank line) to the child to tell it that it's time to stop. + self._write_handle.write(b"\n") + self._write_handle.flush() + + # Wait for the child process to exit. The timeout is necessary for corner cases when the sub-process fails to + # exit (such as due to dangling non-daemon threads; see #7290). At this point, the subprocess already did all + # its work, so it should be safe to terminate. And as we expect it to shut down quickly (or not at all), the + # timeout is relatively short. + # + # In strict build mode, we raise an error when the subprocess fails to exit on its own, but do so only after + # we attempt to kill the subprocess, to avoid leaving zombie processes. + shutdown_error = False + + try: + self._child.wait(timeout=5) + except subprocess.TimeoutExpired: + logger.warning("Timed out while waiting for the child process to exit!") + shutdown_error = True + self._child.kill() + try: + self._child.wait(timeout=15) + except subprocess.TimeoutExpired: + logger.warning("Timed out while waiting for the child process to be killed!") + # Give up and fall through + + # Close the handles. This should also close the underlying file descriptors. + self._write_handle.close() + self._read_handle.close() + del self._read_handle, self._write_handle + + self._child = None + + # Raise an error in strict mode, after all clean-up has been performed. + if shutdown_error and self._strict_mode: + raise RuntimeError("Timed out while waiting for the child process to exit!") + + def call(self, function, *args, **kwargs): + """ + Call a function in the child Python. Retrieve its return value. Usage of this method is identical to that + of the :func:`call` function. + """ + # If already running in an isolated subprocess, directly execute the function. + if self._already_isolated: + return function(*args, **kwargs) + + if self._child is None: + raise RuntimeError("An isolated.Python object must be used in a 'with' clause.") + + self._send(function.__code__, function.__defaults__, function.__kwdefaults__, args, kwargs) + + # Read a single line of output back from the child. This contains if the function worked and either its return + # value or a traceback. This will block indefinitely until it receives a '\n' byte. + try: + ok, output = loads(b64decode(self._read_handle.readline())) + except (EOFError, BrokenPipeError): + # Subprocess appears to have died in an unhandleable way (e.g. SIGSEV). Raise an error. + raise SubprocessDiedError( + f"Child process died calling {function.__name__}() with args={args} and " + f"kwargs={kwargs}. Its exit code was {self._child.wait()}." + ) from None + + # If all went well, then ``output`` is the return value. + if ok: + return output + + # Otherwise an error happened and ``output`` is a string-ified stacktrace. Raise an error appending the + # stacktrace. Having the output in this order gives a nice fluent transition from parent to child in the stack + # trace. + raise RuntimeError(f"Child process call to {function.__name__}() failed with:\n" + output) + + def _send(self, *objects): + for object in objects: + self._write_handle.write(b64encode(dumps(object))) + self._write_handle.write(b"\n") + # Flushing is very important. Without it, the data is not sent but forever sits in a buffer so that the child is + # forever waiting for its data and the parent in turn is forever waiting for the child's response. + self._write_handle.flush() + + +def call(function, *args, **kwargs): + r""" + Call a function with arguments in a separate child Python. Retrieve its return value. + + Args: + function: + The function to send and invoke. + *args: + **kwargs: + Positional and keyword arguments to send to the function. These must be simple builtin types - not custom + classes. + Returns: + The return value of the function. Again, these must be basic types serialisable by :func:`marshal.dumps`. + Raises: + RuntimeError: + Any exception which happens inside an isolated process is caught and reraised in the parent process. + + To use, define a function which returns the information you're looking for. Any imports it requires must happen in + the body of the function. For example, to safely check the output of ``matplotlib.get_data_path()`` use:: + + # Define a function to be ran in isolation. + def get_matplotlib_data_path(): + import matplotlib + return matplotlib.get_data_path() + + # Call it with isolated.call(). + get_matplotlib_data_path = isolated.call(matplotlib_data_path) + + For single use functions taking no arguments like the above you can abuse the decorator syntax slightly to define + and execute a function in one go. :: + + >>> @isolated.call + ... def matplotlib_data_dir(): + ... import matplotlib + ... return matplotlib.get_data_path() + >>> matplotlib_data_dir + '/home/brenainn/.pyenv/versions/3.9.6/lib/python3.9/site-packages/matplotlib/mpl-data' + + Functions may take positional and keyword arguments and return most generic Python data types. :: + + >>> def echo_parameters(*args, **kwargs): + ... return args, kwargs + >>> isolated.call(echo_parameters, 1, 2, 3) + (1, 2, 3), {} + >>> isolated.call(echo_parameters, foo=["bar"]) + (), {'foo': ['bar']} + + Notes: + To make a function behave differently if it's isolated, check for the ``__isolated__`` global. :: + + if globals().get("__isolated__", False): + # We're inside a child process. + ... + else: + # This is the master process. + ... + + """ + with Python() as isolated: + return isolated.call(function, *args, **kwargs) + + +def decorate(function): + """ + Decorate a function so that it is always called in an isolated subprocess. + + Examples: + + To use, write a function then prepend ``@isolated.decorate``. :: + + @isolated.decorate + def add_1(x): + '''Add 1 to ``x``, displaying the current process ID.''' + import os + print(f"Process {os.getpid()}: Adding 1 to {x}.") + return x + 1 + + The resultant ``add_1()`` function can now be called as you would a + normal function and it'll automatically use a subprocess. + + >>> add_1(4) + Process 4920: Adding 1 to 4. + 5 + >>> add_1(13.2) + Process 4928: Adding 1 to 13.2. + 14.2 + + """ + @functools.wraps(function) + def wrapped(*args, **kwargs): + return call(function, *args, **kwargs) + + return wrapped diff --git a/venv/Lib/site-packages/PyInstaller/lib/README.rst b/venv/Lib/site-packages/PyInstaller/lib/README.rst new file mode 100644 index 0000000..a09f6d5 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/lib/README.rst @@ -0,0 +1,49 @@ +Custom modifications of 3rd party libraries +=========================================== + +NOTE: PyInstaller does not extend PYTHONPATH (sys.path) with this directory +that contains bundled 3rd party libraries. + +Some users complained that PyInstaller failed because their apps were using +too old versions of some libraries that PyInstaller uses too and that's why +extending sys.path was dropped. + +All libraries are tweaked to be importable as:: + + from PyInstaller.lib.LIB_NAME import xyz + +In libraries replace imports like:: + + from altgraph import y + from modulegraph import z + +with relative prefix:: + + from ..altgraph import y + from ..modulegraph import z + + +altgraph +---------- + +- add fixed version string to ./altgraph/__init__.py:: + + # For PyInstaller/lib/ define the version here, since there is no + # package-resource. + __version__ = '0.13' + + +modulegraph +----------- + +https://bitbucket.org/ronaldoussoren/modulegraph/downloads + +- TODO Use official modulegraph version when following issue is resolved and pull request merged + https://bitbucket.org/ronaldoussoren/modulegraph/issues/28/__main__-module-being-analyzed-for-wheel + +- add fixed version string to ./modulegraph/__init__.py:: + + # For PyInstaller/lib/ define the version here, since there is no + # package-resource. + __version__ = '0.13' + diff --git a/venv/Lib/site-packages/PyInstaller/lib/__init__.py b/venv/Lib/site-packages/PyInstaller/lib/__init__.py new file mode 100644 index 0000000..792d600 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/lib/__init__.py @@ -0,0 +1 @@ +# diff --git a/venv/Lib/site-packages/PyInstaller/lib/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/lib/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..76b78fb Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/lib/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/lib/modulegraph/__init__.py b/venv/Lib/site-packages/PyInstaller/lib/modulegraph/__init__.py new file mode 100644 index 0000000..9446169 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/lib/modulegraph/__init__.py @@ -0,0 +1 @@ +__version__ = '0.17' diff --git a/venv/Lib/site-packages/PyInstaller/lib/modulegraph/__main__.py b/venv/Lib/site-packages/PyInstaller/lib/modulegraph/__main__.py new file mode 100644 index 0000000..ea4670b --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/lib/modulegraph/__main__.py @@ -0,0 +1,89 @@ +import sys +import os +import argparse +from .modulegraph import ModuleGraph + + +def parse_arguments(): + parser = argparse.ArgumentParser( + conflict_handler='resolve', prog='%s -mmodulegraph' % ( + os.path.basename(sys.executable))) + parser.add_argument( + '-d', action='count', dest='debug', default=1, + help='Increase debug level') + parser.add_argument( + '-q', action='store_const', dest='debug', const=0, + help='Clear debug level') + parser.add_argument( + '-m', '--modules', action='store_true', + dest='domods', default=False, + help='arguments are module names, not script files') + parser.add_argument( + '-x', metavar='NAME', action='append', dest='excludes', + default=[], help='Add NAME to the excludes list') + parser.add_argument( + '-p', action='append', metavar='PATH', dest='addpath', default=[], + help='Add PATH to the module search path') + parser.add_argument( + '-g', '--dot', action='store_const', dest='output', const='dot', + help='Output a .dot graph') + parser.add_argument( + '-h', '--html', action='store_const', + dest='output', const='html', help='Output a HTML file') + parser.add_argument( + 'scripts', metavar='SCRIPT', nargs='+', help='scripts to analyse') + + opts = parser.parse_args() + return opts + + +def create_graph(scripts, domods, debuglevel, excludes, path_extras): + # Set the path based on sys.path and the script directory + path = sys.path[:] + + if domods: + del path[0] + else: + path[0] = os.path.dirname(scripts[0]) + + path = path_extras + path + if debuglevel > 1: + print("path:", file=sys.stderr) + for item in path: + print(" ", repr(item), file=sys.stderr) + + # Create the module finder and turn its crank + mf = ModuleGraph(path, excludes=excludes, debug=debuglevel) + for arg in scripts: + if domods: + if arg[-2:] == '.*': + mf.import_hook(arg[:-2], None, ["*"]) + else: + mf.import_hook(arg) + else: + mf.add_script(arg) + return mf + + +def output_graph(output_format, mf): + if output_format == 'dot': + mf.graphreport() + elif output_format == 'html': + mf.create_xref() + else: + mf.report() + + +def main(): + opts = parse_arguments() + mf = create_graph( + opts.scripts, opts.domods, opts.debug, + opts.excludes, opts.addpath) + output_graph(opts.output, mf) + + +if __name__ == '__main__': # pragma: no cover + try: + main() + except KeyboardInterrupt: + print("\n[interrupt]") diff --git a/venv/Lib/site-packages/PyInstaller/lib/modulegraph/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/lib/modulegraph/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..bdcee39 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/lib/modulegraph/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/lib/modulegraph/__pycache__/__main__.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/lib/modulegraph/__pycache__/__main__.cpython-311.pyc new file mode 100644 index 0000000..53db782 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/lib/modulegraph/__pycache__/__main__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/lib/modulegraph/__pycache__/find_modules.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/lib/modulegraph/__pycache__/find_modules.cpython-311.pyc new file mode 100644 index 0000000..1a9d36d Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/lib/modulegraph/__pycache__/find_modules.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/lib/modulegraph/__pycache__/modulegraph.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/lib/modulegraph/__pycache__/modulegraph.cpython-311.pyc new file mode 100644 index 0000000..ca73aee Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/lib/modulegraph/__pycache__/modulegraph.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/lib/modulegraph/__pycache__/util.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/lib/modulegraph/__pycache__/util.cpython-311.pyc new file mode 100644 index 0000000..cd0adf3 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/lib/modulegraph/__pycache__/util.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/lib/modulegraph/find_modules.py b/venv/Lib/site-packages/PyInstaller/lib/modulegraph/find_modules.py new file mode 100644 index 0000000..b383b28 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/lib/modulegraph/find_modules.py @@ -0,0 +1,61 @@ +""" +modulegraph.find_modules - High-level module dependency finding interface +========================================================================= + +History +........ + +Originally (loosely) based on code in py2exe's build_exe.py by Thomas Heller. +""" +import os +import pkgutil + +from .modulegraph import Alias + +def get_implies(): + def _xml_etree_modules(): + import xml.etree + return [ + f"xml.etree.{module_name}" + for _, module_name, is_package in pkgutil.iter_modules(xml.etree.__path__) + if not is_package + ] + + result = { + # imports done from C code in built-in and/or extension modules + # (untrackable by modulegraph). + "_curses": ["curses"], + "posix": ["resource"], + "gc": ["time"], + "time": ["_strptime"], + "datetime": ["time"], + "parser": ["copyreg"], + "codecs": ["encodings"], + "_sre": ["copy", "re"], + "zipimport": ["zlib"], + + # _frozen_importlib is part of the interpreter itself + "_frozen_importlib": None, + + # os.path is an alias for a platform specific module, + # ensure that the graph shows this. + "os.path": Alias(os.path.__name__), + + # Python >= 3.2: + "_datetime": ["time", "_strptime"], + "_json": ["json.decoder"], + "_pickle": ["codecs", "copyreg", "_compat_pickle"], + "_posixsubprocess": ["gc"], + "_ssl": ["socket"], + + # Python >= 3.3: + "_elementtree": ["pyexpat"] + _xml_etree_modules(), + + # This is not C extension, but it uses __import__ + "anydbm": ["dbhash", "gdbm", "dbm", "dumbdbm", "whichdb"], + + # Known package aliases + "wxPython.wx": Alias('wx'), + } + + return result diff --git a/venv/Lib/site-packages/PyInstaller/lib/modulegraph/modulegraph.py b/venv/Lib/site-packages/PyInstaller/lib/modulegraph/modulegraph.py new file mode 100644 index 0000000..f5ee148 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/lib/modulegraph/modulegraph.py @@ -0,0 +1,3061 @@ +""" +Find modules used by a script, using bytecode analysis. + +Based on the stdlib modulefinder by Thomas Heller and Just van Rossum, +but uses a graph data structure and 2.3 features + +XXX: Verify all calls to _import_hook (and variants) to ensure that +imports are done in the right way. +""" +#FIXME: To decrease the likelihood of ModuleGraph exceeding the recursion limit +#and hence unpredictably raising fatal exceptions, increase the recursion +#limit at PyInstaller startup (i.e., in the +#PyInstaller.building.build_main.build() function). For details, see: +# https://github.com/pyinstaller/pyinstaller/issues/1919#issuecomment-216016176 + +import ast +import os +import pkgutil +import sys +import re +from collections import deque, namedtuple, defaultdict +import urllib.request +import warnings +import importlib.util +import importlib.machinery + +# The logic in PyInstaller.compat ensures that these are available and +# of correct version. +if sys.version_info >= (3, 10): + import importlib.metadata as importlib_metadata +else: + import importlib_metadata + +from altgraph.ObjectGraph import ObjectGraph +from altgraph import GraphError + +from . import util + + +class BUILTIN_MODULE: + def is_package(fqname): + return False + + +class NAMESPACE_PACKAGE: + def __init__(self, namespace_dirs): + self.namespace_dirs = namespace_dirs + + def is_package(self, fqname): + return True + + +#FIXME: Leverage this rather than magic numbers below. +ABSOLUTE_OR_RELATIVE_IMPORT_LEVEL = -1 +""" +Constant instructing the builtin `__import__()` function to attempt both +absolute and relative imports. +""" + + +#FIXME: Leverage this rather than magic numbers below. +ABSOLUTE_IMPORT_LEVEL = 0 +""" +Constant instructing the builtin `__import__()` function to attempt only +absolute imports. +""" + + +#FIXME: Leverage this rather than magic numbers below. +DEFAULT_IMPORT_LEVEL = ABSOLUTE_IMPORT_LEVEL +""" +Constant instructing the builtin `__import__()` function to attempt the default +import style specific to the active Python interpreter. + +Specifically, under: + +* Python 2, this defaults to attempting both absolute and relative imports. +* Python 3, this defaults to attempting only absolute imports. +""" + + +class InvalidRelativeImportError (ImportError): + pass + + +def _path_from_importerror(exc, default): + # This is a hack, but sadly enough the necessary information + # isn't available otherwise. + m = re.match(r'^No module named (\S+)$', str(exc)) + if m is not None: + return m.group(1) + + return default + + +#FIXME: What is this? Do we actually need this? This appears to provide +#significantly more fine-grained metadata than PyInstaller will ever require. +#It consumes a great deal of space (slots or no slots), since we store an +#instance of this class for each edge of the graph. +class DependencyInfo (namedtuple("DependencyInfo", + ["conditional", "function", "tryexcept", "fromlist"])): + __slots__ = () + + def _merged(self, other): + if (not self.conditional and not self.function and not self.tryexcept) \ + or (not other.conditional and not other.function and not other.tryexcept): + return DependencyInfo( + conditional=False, + function=False, + tryexcept=False, + fromlist=self.fromlist and other.fromlist) + + else: + return DependencyInfo( + conditional=self.conditional or other.conditional, + function=self.function or other.function, + tryexcept=self.tryexcept or other.tryexcept, + fromlist=self.fromlist and other.fromlist) + + +#FIXME: Shift the following Node class hierarchy into a new +#"PyInstaller.lib.modulegraph.node" module. This module is much too long. +#FIXME: Refactor "_deferred_imports" from a tuple into a proper lightweight +#class leveraging "__slots__". If not for backward compatibility, we'd just +#leverage a named tuple -- but this should do just as well. +#FIXME: Move the "packagepath" attribute into the "Package" class. Only +#packages define the "__path__" special attribute. The codebase currently +#erroneously tests whether "module.packagepath is not None" to determine +#whether a node is a package or not. However, "isinstance(module, Package)" is +#a significantly more reliable test. Refactor the former into the latter. +class Node: + """ + Abstract base class (ABC) of all objects added to a `ModuleGraph`. + + Attributes + ---------- + code : codeobject + Code object of the pure-Python module corresponding to this graph node + if any _or_ `None` otherwise. + graphident : str + Synonym of `identifier` required by the `ObjectGraph` superclass of the + `ModuleGraph` class. For readability, the `identifier` attribute should + typically be used instead. + filename : str + Absolute path of this graph node's corresponding module, package, or C + extension if any _or_ `None` otherwise. + identifier : str + Fully-qualified name of this graph node's corresponding module, + package, or C extension. + packagepath : str + List of the absolute paths of all directories comprising this graph + node's corresponding package. If this is a: + * Non-namespace package, this list contains exactly one path. + * Namespace package, this list contains one or more paths. + _deferred_imports : list + List of all target modules imported by the source module corresponding + to this graph node whole importations have been deferred for subsequent + processing in between calls to the `_ModuleGraph._scan_code()` and + `_ModuleGraph._process_imports()` methods for this source module _or_ + `None` otherwise. Each element of this list is a 3-tuple + `(have_star, _safe_import_hook_args, _safe_import_hook_kwargs)` + collecting the importation of a target module from this source module + for subsequent processing, where: + * `have_star` is a boolean `True` only if this is a `from`-style star + import (e.g., resembling `from {target_module_name} import *`). + * `_safe_import_hook_args` is a (typically non-empty) sequence of all + positional arguments to be passed to the `_safe_import_hook()` method + to add this importation to the graph. + * `_safe_import_hook_kwargs` is a (typically empty) dictionary of all + keyword arguments to be passed to the `_safe_import_hook()` method + to add this importation to the graph. + Unlike functional languages, Python imposes a maximum depth on the + interpreter stack (and hence recursion). On breaching this depth, + Python raises a fatal `RuntimeError` exception. Since `ModuleGraph` + parses imports recursively rather than iteratively, this depth _was_ + commonly breached before the introduction of this list. Python + environments installing a large number of modules (e.g., Anaconda) were + particularly susceptible. Why? Because `ModuleGraph` concurrently + descended through both the abstract syntax trees (ASTs) of all source + modules being parsed _and_ the graph of all target modules imported by + these source modules being built. The stack thus consisted of + alternating layers of AST and graph traversal. To unwind such + alternation and effectively halve the stack depth, `ModuleGraph` now + descends through the abstract syntax tree (AST) of each source module + being parsed and adds all importations originating within this module + to this list _before_ descending into the graph of these importations. + See pyinstaller/pyinstaller/#1289 for further details. + _global_attr_names : set + Set of the unqualified names of all global attributes (e.g., classes, + variables) defined in the pure-Python module corresponding to this + graph node if any _or_ the empty set otherwise. This includes the names + of all attributes imported via `from`-style star imports from other + existing modules (e.g., `from {target_module_name} import *`). This + set is principally used to differentiate the non-ignorable importation + of non-existent submodules in a package from the ignorable importation + of existing global attributes defined in that package's pure-Python + `__init__` submodule in `from`-style imports (e.g., `bar` in + `from foo import bar`, which may be either a submodule or attribute of + `foo`), as such imports ambiguously allow both. This set is _not_ used + to differentiate submodules from attributes in `import`-style imports + (e.g., `bar` in `import foo.bar`, which _must_ be a submodule of + `foo`), as such imports unambiguously allow only submodules. + _starimported_ignored_module_names : set + Set of the fully-qualified names of all existing unparsable modules + that the existing parsable module corresponding to this graph node + attempted to perform one or more "star imports" from. If this module + either does _not_ exist or does but is unparsable, this is the empty + set. Equivalently, this set contains each fully-qualified name + `{trg_module_name}` for which: + * This module contains an import statement of the form + `from {trg_module_name} import *`. + * The module whose name is `{trg_module_name}` exists but is _not_ + parsable by `ModuleGraph` (e.g., due to _not_ being pure-Python). + **This set is currently defined but otherwise ignored.** + _submodule_basename_to_node : dict + Dictionary mapping from the unqualified name of each submodule + contained by the parent module corresponding to this graph node to that + submodule's graph node. If this dictionary is non-empty, this parent + module is typically but _not_ always a package (e.g., the non-package + `os` module containing the `os.path` submodule). + """ + + __slots__ = [ + 'code', + 'filename', + 'graphident', + 'identifier', + 'packagepath', + '_deferred_imports', + '_global_attr_names', + '_starimported_ignored_module_names', + '_submodule_basename_to_node', + ] + + def __init__(self, identifier): + """ + Initialize this graph node. + + Parameters + ---------- + identifier : str + Fully-qualified name of this graph node's corresponding module, + package, or C extension. + """ + + self.code = None + self.filename = None + self.graphident = identifier + self.identifier = identifier + self.packagepath = None + self._deferred_imports = None + self._global_attr_names = set() + self._starimported_ignored_module_names = set() + self._submodule_basename_to_node = dict() + + + def is_global_attr(self, attr_name): + """ + `True` only if the pure-Python module corresponding to this graph node + defines a global attribute (e.g., class, variable) with the passed + name. + + If this module is actually a package, this method instead returns + `True` only if this package's pure-Python `__init__` submodule defines + such a global attribute. In this case, note that this package may still + contain an importable submodule of the same name. Callers should + attempt to import this attribute as a submodule of this package + _before_ assuming this attribute to be an ignorable global. See + "Examples" below for further details. + + Parameters + ---------- + attr_name : str + Unqualified name of the attribute to be tested. + + Returns + ---------- + bool + `True` only if this module defines this global attribute. + + Examples + ---------- + Consider a hypothetical module `foo` containing submodules `bar` and + `__init__` where the latter assigns `bar` to be a global variable + (possibly star-exported via the special `__all__` global variable): + + >>> # In "foo.__init__": + >>> bar = 3.1415 + + Python 2 and 3 both permissively permit this. This method returns + `True` in this case (i.e., when called on the `foo` package's graph + node, passed the attribute name `bar`) despite the importability of the + `foo.bar` submodule. + """ + + return attr_name in self._global_attr_names + + + def is_submodule(self, submodule_basename): + """ + `True` only if the parent module corresponding to this graph node + contains the submodule with the passed name. + + If `True`, this parent module is typically but _not_ always a package + (e.g., the non-package `os` module containing the `os.path` submodule). + + Parameters + ---------- + submodule_basename : str + Unqualified name of the submodule to be tested. + + Returns + ---------- + bool + `True` only if this parent module contains this submodule. + """ + + return submodule_basename in self._submodule_basename_to_node + + + def add_global_attr(self, attr_name): + """ + Record the global attribute (e.g., class, variable) with the passed + name to be defined by the pure-Python module corresponding to this + graph node. + + If this module is actually a package, this method instead records this + attribute to be defined by this package's pure-Python `__init__` + submodule. + + Parameters + ---------- + attr_name : str + Unqualified name of the attribute to be added. + """ + + self._global_attr_names.add(attr_name) + + + def add_global_attrs_from_module(self, target_module): + """ + Record all global attributes (e.g., classes, variables) defined by the + target module corresponding to the passed graph node to also be defined + by the source module corresponding to this graph node. + + If the source module is actually a package, this method instead records + these attributes to be defined by this package's pure-Python `__init__` + submodule. + + Parameters + ---------- + target_module : Node + Graph node of the target module to import attributes from. + """ + + self._global_attr_names.update(target_module._global_attr_names) + + + def add_submodule(self, submodule_basename, submodule_node): + """ + Add the submodule with the passed name and previously imported graph + node to the parent module corresponding to this graph node. + + This parent module is typically but _not_ always a package (e.g., the + non-package `os` module containing the `os.path` submodule). + + Parameters + ---------- + submodule_basename : str + Unqualified name of the submodule to add to this parent module. + submodule_node : Node + Graph node of this submodule. + """ + + self._submodule_basename_to_node[submodule_basename] = submodule_node + + + def get_submodule(self, submodule_basename): + """ + Graph node of the submodule with the passed name in the parent module + corresponding to this graph node. + + If this parent module does _not_ contain this submodule, an exception + is raised. Else, this parent module is typically but _not_ always a + package (e.g., the non-package `os` module containing the `os.path` + submodule). + + Parameters + ---------- + module_basename : str + Unqualified name of the submodule to retrieve. + + Returns + ---------- + Node + Graph node of this submodule. + """ + + return self._submodule_basename_to_node[submodule_basename] + + + def get_submodule_or_none(self, submodule_basename): + """ + Graph node of the submodule with the passed unqualified name in the + parent module corresponding to this graph node if this module contains + this submodule _or_ `None`. + + This parent module is typically but _not_ always a package (e.g., the + non-package `os` module containing the `os.path` submodule). + + Parameters + ---------- + submodule_basename : str + Unqualified name of the submodule to retrieve. + + Returns + ---------- + Node + Graph node of this submodule if this parent module contains this + submodule _or_ `None`. + """ + + return self._submodule_basename_to_node.get(submodule_basename) + + + def remove_global_attr_if_found(self, attr_name): + """ + Record the global attribute (e.g., class, variable) with the passed + name if previously recorded as defined by the pure-Python module + corresponding to this graph node to be subsequently undefined by the + same module. + + If this module is actually a package, this method instead records this + attribute to be undefined by this package's pure-Python `__init__` + submodule. + + This method is intended to be called on globals previously defined by + this module that are subsequently undefined via the `del` built-in by + this module, thus "forgetting" or "undoing" these globals. + + For safety, there exists no corresponding `remove_global_attr()` + method. While defining this method is trivial, doing so would invite + `KeyError` exceptions on scanning valid Python that lexically deletes a + global in a scope under this module's top level (e.g., in a function) + _before_ defining this global at this top level. Since `ModuleGraph` + cannot and should not (re)implement a full-blown Python interpreter, + ignoring out-of-order deletions is the only sane policy. + + Parameters + ---------- + attr_name : str + Unqualified name of the attribute to be removed. + """ + + if self.is_global_attr(attr_name): + self._global_attr_names.remove(attr_name) + + def __eq__(self, other): + try: + otherIdent = getattr(other, 'graphident') + except AttributeError: + return False + + return self.graphident == otherIdent + + def __ne__(self, other): + try: + otherIdent = getattr(other, 'graphident') + except AttributeError: + return True + + return self.graphident != otherIdent + + def __lt__(self, other): + try: + otherIdent = getattr(other, 'graphident') + except AttributeError: + return NotImplemented + + return self.graphident < otherIdent + + def __le__(self, other): + try: + otherIdent = getattr(other, 'graphident') + except AttributeError: + return NotImplemented + + return self.graphident <= otherIdent + + def __gt__(self, other): + try: + otherIdent = getattr(other, 'graphident') + except AttributeError: + return NotImplemented + + return self.graphident > otherIdent + + def __ge__(self, other): + try: + otherIdent = getattr(other, 'graphident') + except AttributeError: + return NotImplemented + + return self.graphident >= otherIdent + + def __hash__(self): + return hash(self.graphident) + + def infoTuple(self): + return (self.identifier,) + + def __repr__(self): + return '%s%r' % (type(self).__name__, self.infoTuple()) + + +class Alias(str): + """ + Placeholder aliasing an existing source module to a non-existent target + module (i.e., the desired alias). + + For obscure reasons, this class subclasses `str`. Each instance of this + class is the fully-qualified name of the existing source module being + aliased. Unlike the related `AliasNode` class, instances of this class are + _not_ actual nodes and hence _not_ added to the graph; they only facilitate + communication between the `ModuleGraph.alias_module()` and + `ModuleGraph.find_node()` methods. + """ + + +class AliasNode(Node): + """ + Graph node representing the aliasing of an existing source module under a + non-existent target module name (i.e., the desired alias). + """ + + def __init__(self, name, node=None): + """ + Initialize this alias. + + Parameters + ---------- + name : str + Fully-qualified name of the non-existent target module to be + created (as an alias of the existing source module). + node : Node + Graph node of the existing source module being aliased. Optional; + if not provided here, the attributes from referred node should + be copied later using `copyAttributesFromReferredNode` method. + """ + super(AliasNode, self).__init__(name) + + # Copy attributes from referred node, if provided + self.copyAttributesFromReferredNode(node) + + def copyAttributesFromReferredNode(self, node): + """ + Copy a subset of attributes from referred node (source module) into this target alias. + """ + # FIXME: Why only some? Why not *EVERYTHING* except "graphident", which + # must remain equal to "name" for lookup purposes? This is, after all, + # an alias. The idea is for the two nodes to effectively be the same. + for attr_name in ( + 'identifier', 'packagepath', + '_global_attr_names', '_starimported_ignored_module_names', + '_submodule_basename_to_node'): + if hasattr(node, attr_name): + setattr(self, attr_name, getattr(node, attr_name)) + + def infoTuple(self): + return (self.graphident, self.identifier) + + +class BadModule(Node): + pass + + +class ExcludedModule(BadModule): + pass + + +class MissingModule(BadModule): + pass + + +class InvalidRelativeImport (BadModule): + def __init__(self, relative_path, from_name): + identifier = relative_path + if relative_path.endswith('.'): + identifier += from_name + else: + identifier += '.' + from_name + super(InvalidRelativeImport, self).__init__(identifier) + self.relative_path = relative_path + self.from_name = from_name + + def infoTuple(self): + return (self.relative_path, self.from_name) + + +class Script(Node): + def __init__(self, filename): + super(Script, self).__init__(filename) + self.filename = filename + + def infoTuple(self): + return (self.filename,) + + +class BaseModule(Node): + def __init__(self, name, filename=None, path=None): + super(BaseModule, self).__init__(name) + self.filename = filename + self.packagepath = path + + def infoTuple(self): + return tuple(filter(None, (self.identifier, self.filename, self.packagepath))) + + +class BuiltinModule(BaseModule): + pass + + +class SourceModule(BaseModule): + pass + + +class InvalidSourceModule(SourceModule): + pass + + +class CompiledModule(BaseModule): + pass + + +class InvalidCompiledModule(BaseModule): + pass + + +class Extension(BaseModule): + pass + + +class Package(BaseModule): + """ + Graph node representing a non-namespace package. + """ + pass + + +class ExtensionPackage(Extension, Package): + """ + Graph node representing a package where the __init__ module is an extension + module. + """ + pass + + +class NamespacePackage(Package): + """ + Graph node representing a namespace package. + """ + pass + + +class RuntimeModule(BaseModule): + """ + Graph node representing a non-package Python module dynamically defined at + runtime. + + Most modules are statically defined on-disk as standard Python files. + Some modules, however, are dynamically defined in-memory at runtime + (e.g., `gi.repository.Gst`, dynamically defined by the statically + defined `gi.repository.__init__` module). + + This node represents such a runtime module. Since this is _not_ a package, + all attempts to import submodules from this module in `from`-style import + statements (e.g., the `queue` submodule in `from six.moves import queue`) + will be silently ignored. + + To ensure that the parent package of this module if any is also imported + and added to the graph, this node is typically added to the graph by + calling the `ModuleGraph.add_module()` method. + """ + pass + + +class RuntimePackage(Package): + """ + Graph node representing a non-namespace Python package dynamically defined + at runtime. + + Most packages are statically defined on-disk as standard subdirectories + containing `__init__.py` files. Some packages, however, are dynamically + defined in-memory at runtime (e.g., `six.moves`, dynamically defined by + the statically defined `six` module). + + This node represents such a runtime package. All attributes imported from + this package in `from`-style import statements that are submodules of this + package (e.g., the `queue` submodule in `from six.moves import queue`) will + be imported rather than ignored. + + To ensure that the parent package of this package if any is also imported + and added to the graph, this node is typically added to the graph by + calling the `ModuleGraph.add_module()` method. + """ + pass + + +#FIXME: Safely removable. We don't actually use this anywhere. After removing +#this class, remove the corresponding entry from "compat". +class FlatPackage(BaseModule): + def __init__(self, *args, **kwds): + warnings.warn( + "This class will be removed in a future version of modulegraph", + DeprecationWarning) + super(FlatPackage, *args, **kwds) + + +#FIXME: Safely removable. We don't actually use this anywhere. After removing +#this class, remove the corresponding entry from "compat". +class ArchiveModule(BaseModule): + def __init__(self, *args, **kwds): + warnings.warn( + "This class will be removed in a future version of modulegraph", + DeprecationWarning) + super(FlatPackage, *args, **kwds) + + +# HTML templates for ModuleGraph generator +header = """\ + + + + + %(TITLE)s + + + +

%(TITLE)s

""" +entry = """ +
+ + %(CONTENT)s +
""" +contpl = """%(NAME)s %(TYPE)s""" +contpl_linked = """\ +%(NAME)s +%(TYPE)s""" +imports = """\ +
+%(HEAD)s: + %(LINKS)s +
+""" +footer = """ + +""" + + +def _ast_names(names): + result = [] + for nm in names: + if isinstance(nm, ast.alias): + result.append(nm.name) + else: + result.append(nm) + + result = [r for r in result if r != '__main__'] + return result + + +def uniq(seq): + """Remove duplicates from a list, preserving order""" + # Taken from https://stackoverflow.com/questions/480214 + seen = set() + seen_add = seen.add + return [x for x in seq if not (x in seen or seen_add(x))] + + +DEFAULT_IMPORT_LEVEL = 0 + + +class _Visitor(ast.NodeVisitor): + def __init__(self, graph, module): + self._graph = graph + self._module = module + self._level = DEFAULT_IMPORT_LEVEL + self._in_if = [False] + self._in_def = [False] + self._in_tryexcept = [False] + + @property + def in_if(self): + return self._in_if[-1] + + @property + def in_def(self): + return self._in_def[-1] + + @property + def in_tryexcept(self): + return self._in_tryexcept[-1] + + + def _collect_import(self, name, fromlist, level): + have_star = False + if fromlist is not None: + fromlist = uniq(fromlist) + if '*' in fromlist: + fromlist.remove('*') + have_star = True + + # Record this import as originating from this module for subsequent + # handling by the _process_imports() method. + self._module._deferred_imports.append( + (have_star, + (name, self._module, fromlist, level), + {'edge_attr': DependencyInfo( + conditional=self.in_if, + tryexcept=self.in_tryexcept, + function=self.in_def, + fromlist=False)})) + + + def visit_Import(self, node): + for nm in _ast_names(node.names): + self._collect_import(nm, None, self._level) + + def visit_ImportFrom(self, node): + level = node.level if node.level != 0 else self._level + self._collect_import(node.module or '', _ast_names(node.names), level) + + def visit_If(self, node): + self._in_if.append(True) + self.generic_visit(node) + self._in_if.pop() + + def visit_FunctionDef(self, node): + self._in_def.append(True) + self.generic_visit(node) + self._in_def.pop() + + visit_AsyncFunctionDef = visit_FunctionDef + + def visit_Try(self, node): + self._in_tryexcept.append(True) + self.generic_visit(node) + self._in_tryexcept.pop() + + def visit_TryExcept(self, node): + self._in_tryexcept.append(True) + self.generic_visit(node) + self._in_tryexcept.pop() + + def visit_Expression(self, node): + # Expression node's cannot contain import statements or + # other nodes that are relevant for us. + pass + + # Expression isn't actually used as such in AST trees, + # therefore define visitors for all kinds of expression nodes. + visit_BoolOp = visit_Expression + visit_BinOp = visit_Expression + visit_UnaryOp = visit_Expression + visit_Lambda = visit_Expression + visit_IfExp = visit_Expression + visit_Dict = visit_Expression + visit_Set = visit_Expression + visit_ListComp = visit_Expression + visit_SetComp = visit_Expression + visit_ListComp = visit_Expression + visit_GeneratorExp = visit_Expression + visit_Compare = visit_Expression + visit_Yield = visit_Expression + visit_YieldFrom = visit_Expression + visit_Await = visit_Expression + visit_Call = visit_Expression + visit_Await = visit_Expression + + +class ModuleGraph(ObjectGraph): + """ + Directed graph whose nodes represent modules and edges represent + dependencies between these modules. + """ + + + def createNode(self, cls, name, *args, **kw): + m = self.find_node(name) + + if m is None: + #assert m is None, m + m = super(ModuleGraph, self).createNode(cls, name, *args, **kw) + + return m + + + def __init__(self, path=None, excludes=(), replace_paths=(), implies=(), graph=None, debug=0): + super(ModuleGraph, self).__init__(graph=graph, debug=debug) + if path is None: + path = sys.path + self.path = path + self.lazynodes = {} + # excludes is stronger than implies + self.lazynodes.update(dict(implies)) + for m in excludes: + self.lazynodes[m] = None + self.replace_paths = replace_paths + + # Maintain own list of package path mappings in the scope of Modulegraph + # object. + self._package_path_map = {} + + # Legacy namespace-package paths. Initialized by scan_legacy_namespace_packages. + self._legacy_ns_packages = {} + + def scan_legacy_namespace_packages(self): + """ + Resolve extra package `__path__` entries for legacy setuptools-based + namespace packages, by reading `namespace_packages.txt` from dist + metadata. + """ + legacy_ns_packages = defaultdict(lambda: set()) + + for dist in importlib_metadata.distributions(): + ns_packages = dist.read_text("namespace_packages.txt") + if ns_packages is None: + continue + ns_packages = ns_packages.splitlines() + # Obtain path to dist metadata directory + dist_path = getattr(dist, '_path') + if dist_path is None: + continue + for package_name in ns_packages: + path = os.path.join( + str(dist_path.parent), # might be zipfile.Path if in zipped .egg + *package_name.split('.'), + ) + legacy_ns_packages[package_name].add(path) + + # Convert into dictionary of lists + self._legacy_ns_packages = { + package_name: list(paths) + for package_name, paths in legacy_ns_packages.items() + } + + def implyNodeReference(self, node, other, edge_data=None): + """ + Create a reference from the passed source node to the passed other node, + implying the former to depend upon the latter. + + While the source node _must_ be an existing graph node, the target node + may be either an existing graph node _or_ a fully-qualified module name. + In the latter case, the module with that name and all parent packages of + that module will be imported _without_ raising exceptions and for each + newly imported module or package: + + * A new graph node will be created for that module or package. + * A reference from the passed source node to that module or package will + be created. + + This method allows dependencies between Python objects _not_ importable + with standard techniques (e.g., module aliases, C extensions). + + Parameters + ---------- + node : str + Graph node for this reference's source module or package. + other : {Node, str} + Either a graph node _or_ fully-qualified name for this reference's + target module or package. + """ + + if isinstance(other, Node): + self._updateReference(node, other, edge_data) + else: + if isinstance(other, tuple): + raise ValueError(other) + others = self._safe_import_hook(other, node, None) + for other in others: + self._updateReference(node, other, edge_data) + + def outgoing(self, fromnode): + """ + Yield all nodes that `fromnode` dependes on (that is, + all modules that `fromnode` imports. + """ + + node = self.find_node(fromnode) + out_edges, _ = self.get_edges(node) + return out_edges + + getReferences = outgoing + + def incoming(self, tonode, collapse_missing_modules=True): + node = self.find_node(tonode) + _, in_edges = self.get_edges(node) + + if collapse_missing_modules: + for n in in_edges: + if isinstance(n, MissingModule): + for n in self.incoming(n, False): + yield n + + else: + yield n + + else: + for n in in_edges: + yield n + + getReferers = incoming + + def hasEdge(self, fromnode, tonode): + """ Return True iff there is an edge from 'fromnode' to 'tonode' """ + fromnode = self.find_node(fromnode) + tonode = self.find_node(tonode) + + return self.graph.edge_by_node(fromnode, tonode) is not None + + def foldReferences(self, packagenode): + """ + Create edges to/from `packagenode` based on the edges to/from all + submodules of that package _and_ then hide the graph nodes + corresponding to those submodules. + """ + + pkg = self.find_node(packagenode) + + for n in self.nodes(): + if not n.identifier.startswith(pkg.identifier + '.'): + continue + + iter_out, iter_inc = self.get_edges(n) + for other in iter_out: + if other.identifier.startswith(pkg.identifier + '.'): + continue + + if not self.hasEdge(pkg, other): + # Ignore circular dependencies + self._updateReference(pkg, other, 'pkg-internal-import') + + for other in iter_inc: + if other.identifier.startswith(pkg.identifier + '.'): + # Ignore circular dependencies + continue + + if not self.hasEdge(other, pkg): + self._updateReference(other, pkg, 'pkg-import') + + self.graph.hide_node(n) + + # TODO: unfoldReferences(pkg) that restore the submodule nodes and + # removes 'pkg-import' and 'pkg-internal-import' edges. Care should + # be taken to ensure that references are correct if multiple packages + # are folded and then one of them in unfolded + + def _updateReference(self, fromnode, tonode, edge_data): + try: + ed = self.edgeData(fromnode, tonode) + except (KeyError, GraphError): # XXX: Why 'GraphError' + return self.add_edge(fromnode, tonode, edge_data) + + if not (isinstance(ed, DependencyInfo) and isinstance(edge_data, DependencyInfo)): + self.updateEdgeData(fromnode, tonode, edge_data) + else: + self.updateEdgeData(fromnode, tonode, ed._merged(edge_data)) + + def add_edge(self, fromnode, tonode, edge_data='direct'): + """ + Create a reference from fromnode to tonode + """ + return super(ModuleGraph, self).createReference(fromnode, tonode, edge_data=edge_data) + + createReference = add_edge + + def find_node(self, name, create_nspkg=True): + """ + Graph node uniquely identified by the passed fully-qualified module + name if this module has been added to the graph _or_ `None` otherwise. + + If (in order): + + . A namespace package with this identifier exists _and_ the passed + `create_nspkg` parameter is `True`, this package will be + instantiated and returned. + . A lazy node with this identifier and: + * No dependencies exists, this node will be instantiated and + returned. + * Dependencies exists, this node and all transitive dependencies of + this node be instantiated and this node returned. + . A non-lazy node with this identifier exists, this node will be + returned as is. + + Parameters + ---------- + name : str + Fully-qualified name of the module whose graph node is to be found. + create_nspkg : bool + Ignored. + + Returns + ---------- + Node + Graph node of this module if added to the graph _or_ `None` + otherwise. + """ + + data = super(ModuleGraph, self).findNode(name) + + if data is not None: + return data + + if name in self.lazynodes: + deps = self.lazynodes.pop(name) + + if deps is None: + # excluded module + m = self.createNode(ExcludedModule, name) + elif isinstance(deps, Alias): + # NOTE: the AliasNode must be created and added to graph + # before trying to create the referred node; that might + # (due to recursive import analysis) lead to another + # attempt to resolve the aliased node (and if there is + # a real node that we are trying to shadow with the alias, + # that will end up added to the graph and prevent the + # alias node from being added). + m = self.createNode(AliasNode, name) + + # Create the referred node. + other = self._safe_import_hook(deps, None, None).pop() + + # Copy attributes; this used to be done by AliasNode + # constructor, back when referred node was created before + # the AliasNode (and could thus be passed to its constructor). + m.copyAttributesFromReferredNode(other) + + self.implyNodeReference(m, other) + else: + m = self._safe_import_hook(name, None, None).pop() + for dep in deps: + self.implyNodeReference(m, dep) + + return m + + return None + + findNode = find_node + iter_graph = ObjectGraph.flatten + + def add_script(self, pathname, caller=None): + """ + Create a node by path (not module name). It is expected to be a Python + source file, and will be scanned for dependencies. + """ + self.msg(2, "run_script", pathname) + + pathname = os.path.realpath(pathname) + m = self.find_node(pathname) + if m is not None: + return m + + with open(pathname, 'rb') as fp: + contents = fp.read() + contents = importlib.util.decode_source(contents) + + co_ast = compile(contents, pathname, 'exec', ast.PyCF_ONLY_AST, True) + co = compile(co_ast, pathname, 'exec', 0, True) + m = self.createNode(Script, pathname) + self._updateReference(caller, m, None) + n = self._scan_code(m, co, co_ast) + self._process_imports(n) + m.code = co + if self.replace_paths: + m.code = self._replace_paths_in_code(m.code) + return m + + + #FIXME: For safety, the "source_module" parameter should default to the + #root node of the current graph if unpassed. This parameter currently + #defaults to None, thus disconnected modules imported in this manner (e.g., + #hidden imports imported by depend.analysis.initialize_modgraph()). + def import_hook( + self, + target_module_partname, + source_module=None, + target_attr_names=None, + level=DEFAULT_IMPORT_LEVEL, + edge_attr=None, + ): + """ + Import the module with the passed name, all parent packages of this + module, _and_ all submodules and attributes in this module with the + passed names from the previously imported caller module signified by + the passed graph node. + + Unlike most import methods (e.g., `_safe_import_hook()`), this method + is designed to be publicly called by both external and internal + callers and hence is public. + + Parameters + ---------- + target_module_partname : str + Partially-qualified name of the target module to be imported. See + `_safe_import_hook()` for further details. + source_module : Node + Graph node for the previously imported **source module** (i.e., + module containing the `import` statement triggering the call to + this method) _or_ `None` if this module is to be imported in a + "disconnected" manner. **Passing `None` is _not_ recommended.** + Doing so produces a disconnected graph in which the graph node + created for the module to be imported will be disconnected and + hence unreachable from all other nodes -- which frequently causes + subtle issues in external callers (namely PyInstaller, which + silently ignores unreachable nodes). + target_attr_names : list + List of the unqualified names of all submodules and attributes to + be imported from the module to be imported if this is a "from"- + style import (e.g., `[encode_base64, encode_noop]` for the import + `from email.encoders import encode_base64, encode_noop`) _or_ + `None` otherwise. + level : int + Whether to perform an absolute or relative import. See + `_safe_import_hook()` for further details. + + Returns + ---------- + list + List of the graph nodes created for all modules explicitly imported + by this call, including the passed module and all submodules listed + in `target_attr_names` _but_ excluding all parent packages + implicitly imported by this call. If `target_attr_names` is `None` + or the empty list, this is guaranteed to be a list of one element: + the graph node created for the passed module. + + Raises + ---------- + ImportError + If the target module to be imported is unimportable. + """ + self.msg(3, "_import_hook", target_module_partname, source_module, source_module, level) + + source_package = self._determine_parent(source_module) + target_package, target_module_partname = self._find_head_package( + source_package, target_module_partname, level) + + self.msgin(4, "load_tail", target_package, target_module_partname) + + submodule = target_package + while target_module_partname: + i = target_module_partname.find('.') + if i < 0: + i = len(target_module_partname) + head, target_module_partname = target_module_partname[ + :i], target_module_partname[i+1:] + mname = "%s.%s" % (submodule.identifier, head) + submodule = self._safe_import_module(head, mname, submodule) + + if submodule is None: + # FIXME: Why do we no longer return a MissingModule instance? + # result = self.createNode(MissingModule, mname) + self.msgout(4, "raise ImportError: No module named", mname) + raise ImportError("No module named " + repr(mname)) + + self.msgout(4, "load_tail ->", submodule) + + target_module = submodule + target_modules = [target_module] + + # If this is a "from"-style import *AND* this target module is + # actually a package, import all submodules of this package specified + # by the "import" half of this import (e.g., the submodules "bar" and + # "car" of the target package "foo" in "from foo import bar, car"). + # + # If this target module is a non-package, it could still contain + # importable submodules (e.g., the non-package `os` module containing + # the `os.path` submodule). In this case, these submodules are already + # imported by this target module's pure-Python code. Since our import + # scanner already detects such imports, these submodules need *NOT* be + # reimported here. + if target_attr_names and isinstance(target_module, + (Package, AliasNode)): + for target_submodule in self._import_importable_package_submodules( + target_module, target_attr_names): + if target_submodule not in target_modules: + target_modules.append(target_submodule) + + # Add an edge from this source module to each target module. + for target_module in target_modules: + self._updateReference( + source_module, target_module, edge_data=edge_attr) + + return target_modules + + + def _determine_parent(self, caller): + """ + Determine the package containing a node. + """ + self.msgin(4, "determine_parent", caller) + + parent = None + if caller: + pname = caller.identifier + + if isinstance(caller, Package): + parent = caller + + elif '.' in pname: + pname = pname[:pname.rfind('.')] + parent = self.find_node(pname) + + elif caller.packagepath: + # XXX: I have no idea why this line + # is necessary. + parent = self.find_node(pname) + + self.msgout(4, "determine_parent ->", parent) + return parent + + + def _find_head_package( + self, + source_package, + target_module_partname, + level=DEFAULT_IMPORT_LEVEL): + """ + Import the target package providing the target module with the passed + name to be subsequently imported from the previously imported source + package corresponding to the passed graph node. + + Parameters + ---------- + source_package : Package + Graph node for the previously imported **source package** (i.e., + package containing the module containing the `import` statement + triggering the call to this method) _or_ `None` if this module is + to be imported in a "disconnected" manner. **Passing `None` is + _not_ recommended.** See the `_import_hook()` method for further + details. + target_module_partname : str + Partially-qualified name of the target module to be imported. See + `_safe_import_hook()` for further details. + level : int + Whether to perform absolute or relative imports. See the + `_safe_import_hook()` method for further details. + + Returns + ---------- + (target_package, target_module_tailname) + 2-tuple describing the imported target package, where: + * `target_package` is the graph node created for this package. + * `target_module_tailname` is the unqualified name of the target + module to be subsequently imported (e.g., `text` when passed a + `target_module_partname` of `email.mime.text`). + + Raises + ---------- + ImportError + If the package to be imported is unimportable. + """ + self.msgin(4, "find_head_package", source_package, target_module_partname, level) + + #FIXME: Rename all local variable names to something sensible. No, + #"p_fqdn" is not a sensible name. + + # If this target module is a submodule... + if '.' in target_module_partname: + target_module_headname, target_module_tailname = ( + target_module_partname.split('.', 1)) + # Else, this target module is a top-level module. + else: + target_module_headname = target_module_partname + target_module_tailname = '' + + # If attempting both absolute and relative imports... + if level == ABSOLUTE_OR_RELATIVE_IMPORT_LEVEL: + if source_package: + target_package_name = source_package.identifier + '.' + target_module_headname + else: + target_package_name = target_module_headname + # Else if attempting only absolute imports... + elif level == ABSOLUTE_IMPORT_LEVEL: + target_package_name = target_module_headname + + # Absolute import, ignore the parent + source_package = None + # Else if attempting only relative imports... + else: + if source_package is None: + self.msg(2, "Relative import outside of package") + raise InvalidRelativeImportError( + "Relative import outside of package (name=%r, parent=%r, level=%r)" % ( + target_module_partname, source_package, level)) + + for i in range(level - 1): + if '.' not in source_package.identifier: + self.msg(2, "Relative import outside of package") + raise InvalidRelativeImportError( + "Relative import outside of package (name=%r, parent=%r, level=%r)" % ( + target_module_partname, source_package, level)) + + p_fqdn = source_package.identifier.rsplit('.', 1)[0] + new_parent = self.find_node(p_fqdn) + if new_parent is None: + #FIXME: Repetition detected. Exterminate. Exterminate. + self.msg(2, "Relative import outside of package") + raise InvalidRelativeImportError( + "Relative import outside of package (name=%r, parent=%r, level=%r)" % ( + target_module_partname, source_package, level)) + + assert new_parent is not source_package, ( + new_parent, source_package) + source_package = new_parent + + if target_module_headname: + target_package_name = ( + source_package.identifier + '.' + target_module_headname) + else: + target_package_name = source_package.identifier + + # Graph node of this target package. + target_package = self._safe_import_module( + target_module_headname, target_package_name, source_package) + + # If this target package is *NOT* importable and a source package was + # passed, attempt to import this target package as an absolute import. + # + # ADDENDUM: but do this only if the passed "level" is either + # ABSOLUTE_IMPORT_LEVEL (0) or ABSOLUTE_OR_RELATIVE_IMPORT_LEVEL (-1). + # Otherwise, an attempt at relative import of a missing sub-module + # (from .module import something) might pull in an unrelated + # but eponymous top-level module, which should not happen. + if target_package is None and source_package is not None and level <= ABSOLUTE_IMPORT_LEVEL: + target_package_name = target_module_headname + source_package = None + + # Graph node for the target package, again. + target_package = self._safe_import_module( + target_module_headname, target_package_name, source_package) + + # If this target package is importable, return this package. + if target_package is not None: + self.msgout(4, "find_head_package ->", (target_package, target_module_tailname)) + return target_package, target_module_tailname + + # Else, raise an exception. + self.msgout(4, "raise ImportError: No module named", target_package_name) + raise ImportError("No module named " + target_package_name) + + + + + #FIXME: Refactor from a generator yielding graph nodes into a non-generator + #returning a list or tuple of all yielded graph nodes. This method is only + #called once above and the return value of that call is only iterated over + #as a list or tuple. There's no demonstrable reason for this to be a + #generator. Generators are great for their intended purposes (e.g., as + #continuations). This isn't one of those purposes. + def _import_importable_package_submodules(self, package, attr_names): + """ + Generator importing and yielding each importable submodule (of the + previously imported package corresponding to the passed graph node) + whose unqualified name is in the passed list. + + Elements of this list that are _not_ importable submodules of this + package are either: + + * Ignorable attributes (e.g., classes, globals) defined at the top + level of this package's `__init__` submodule, which will be ignored. + * Else, unignorable unimportable submodules, in which case an + exception is raised. + + Parameters + ---------- + package : Package + Graph node of the previously imported package containing the + modules to be imported and yielded. + + attr_names : list + List of the unqualified names of all attributes of this package to + attempt to import as submodules. This list will be internally + converted into a set, safely ignoring any duplicates in this list + (e.g., reducing the "from"-style import + `from foo import bar, car, far, bar, car, far` to merely + `from foo import bar, car, far`). + + Yields + ---------- + Node + Graph node created for the currently imported submodule. + + Raises + ---------- + ImportError + If any attribute whose name is in `attr_names` is neither: + * An importable submodule of this package. + * An ignorable global attribute (e.g., class, variable) defined at + the top level of this package's `__init__` submodule. + In this case, this attribute _must_ be an unimportable submodule of + this package. + """ + + # Ignore duplicate submodule names in the passed list. + attr_names = set(attr_names) + self.msgin(4, "_import_importable_package_submodules", package, attr_names) + + #FIXME: This test *SHOULD* be superfluous and hence safely removable. + #The higher-level _scan_bytecode() and _collect_import() methods + #already guarantee "*" characters to be removed from fromlists. + if '*' in attr_names: + attr_names.update(self._find_all_submodules(package)) + attr_names.remove('*') + + # self.msg(4, '_import_importable_package_submodules (global attrs)', package.identifier, package._global_attr_names) + + # For the name of each attribute to be imported from this package... + for attr_name in attr_names: + # self.msg(4, '_import_importable_package_submodules (fromlist attr)', package.identifier, attr_name) + + # Graph node of this attribute if this attribute is a previously + # imported module or None otherwise. + submodule = package.get_submodule_or_none(attr_name) + + # If this attribute is *NOT* a previously imported module, attempt + # to import this attribute as a submodule of this package. + if submodule is None: + # Fully-qualified name of this submodule. + submodule_name = package.identifier + '.' + attr_name + + # Graph node of this submodule if importable or None otherwise. + submodule = self._safe_import_module( + attr_name, submodule_name, package) + + # If this submodule is unimportable... + if submodule is None: + # If this attribute is a global (e.g., class, variable) + # defined at the top level of this package's "__init__" + # submodule, this importation is safely ignorable. Do so + # and skip to the next attribute. + # + # This behaviour is non-conformant with Python behaviour, + # which is bad, but is required to sanely handle all + # possible edge cases, which is good. In Python, a global + # attribute defined at the top level of a package's + # "__init__" submodule shadows a submodule of the same name + # in that package. Attempting to import that submodule + # instead imports that attribute; thus, that submodule is + # effectively unimportable. In this method and elsewhere, + # that submodule is tested for first and hence shadows that + # attribute -- the opposite logic. Attempts to import that + # attribute are mistakenly seen as attempts to import that + # submodule! Why? + # + # Edge cases. PyInstaller (and by extension ModuleGraph) + # only cares about module imports. Global attribute imports + # are parsed only as the means to this ends and are + # otherwise ignorable. The cost of erroneously shadowing: + # + # * Submodules by attributes is significant. Doing so + # prevents such submodules from being frozen and hence + # imported at application runtime. + # * Attributes by submodules is insignificant. Doing so + # could erroneously freeze such submodules despite their + # never being imported at application runtime. However, + # ModuleGraph is incapable of determining with certainty + # that Python logic in another module other than the + # "__init__" submodule containing these attributes does + # *NOT* delete these attributes and hence unshadow these + # submodules, which would then become importable at + # runtime and require freezing. Hence, ModuleGraph *MUST* + # permissively assume submodules of the same name as + # attributes to be unshadowed elsewhere and require + # freezing -- even if they do not. + # + # It is practically difficult (albeit technically feasible) + # for ModuleGraph to determine whether or not the target + # attribute names of "from"-style import statements (e.g., + # "bar" and "car" in "from foo import bar, car") refer to + # non-ignorable submodules or ignorable non-module globals + # during opcode scanning. Distinguishing these two cases + # during opcode scanning would require a costly call to the + # _find_module() method, which would subsequently be + # repeated during import-graph construction. This could be + # ameliorated with caching, which itself would require + # costly space consumption and developer time. + # + # Since opcode scanning fails to distinguish these two + # cases, this and other methods subsequently called at + # import-graph construction time (e.g., + # _safe_import_hook()) must do so. Since submodules of the + # same name as attributes must assume to be unshadowed + # elsewhere and require freezing, the only solution is to + # attempt to import an attribute as a non-ignorable module + # *BEFORE* assuming an attribute to be an ignorable + # non-module. Which is what this and other methods do. + # + # See Package.is_global_attr() for similar discussion. + if package.is_global_attr(attr_name): + self.msg(4, '_import_importable_package_submodules: ignoring from-imported global', package.identifier, attr_name) + continue + # Else, this attribute is an unimportable submodule. Since + # this is *NOT* safely ignorable, raise an exception. + else: + raise ImportError("No module named " + submodule_name) + + # Yield this submodule's graph node to the caller. + yield submodule + + self.msgin(4, "_import_importable_package_submodules ->") + + + def _find_all_submodules(self, m): + if not m.packagepath: + return + # 'suffixes' used to be a list hardcoded to [".py", ".pyc", ".pyo"]. + # But we must also collect Python extension modules - although + # we cannot separate normal dlls from Python extensions. + for path in m.packagepath: + try: + names = os.listdir(path) + except (os.error, IOError): + self.msg(2, "can't list directory", path) + continue + for name in names: + for suffix in importlib.machinery.all_suffixes(): + if path.endswith(suffix): + name = os.path.basename(path)[:-len(suffix)] + break + else: + continue + if name != '__init__': + yield name + + + def alias_module(self, src_module_name, trg_module_name): + """ + Alias the source module to the target module with the passed names. + + This method ensures that the next call to findNode() given the target + module name will resolve this alias. This includes importing and adding + a graph node for the source module if needed as well as adding a + reference from the target to source module. + + Parameters + ---------- + src_module_name : str + Fully-qualified name of the existing **source module** (i.e., the + module being aliased). + trg_module_name : str + Fully-qualified name of the non-existent **target module** (i.e., + the alias to be created). + """ + self.msg(3, 'alias_module "%s" -> "%s"' % (src_module_name, trg_module_name)) + # print('alias_module "%s" -> "%s"' % (src_module_name, trg_module_name)) + assert isinstance(src_module_name, str), '"%s" not a module name.' % str(src_module_name) + assert isinstance(trg_module_name, str), '"%s" not a module name.' % str(trg_module_name) + + # If the target module has already been added to the graph as either a + # non-alias or as a different alias, raise an exception. + trg_module = self.find_node(trg_module_name) + if trg_module is not None and not ( + isinstance(trg_module, AliasNode) and + trg_module.identifier == src_module_name): + raise ValueError( + 'Target module "%s" already imported as "%s".' % ( + trg_module_name, trg_module)) + + # See findNode() for details. + self.lazynodes[trg_module_name] = Alias(src_module_name) + + + def add_module(self, module): + """ + Add the passed module node to the graph if not already added. + + If that module has a parent module or package with a previously added + node, this method also adds a reference from this module node to its + parent node and adds this module node to its parent node's namespace. + + This high-level method wraps the low-level `addNode()` method, but is + typically _only_ called by graph hooks adding runtime module nodes. For + all other node types, the `import_module()` method should be called. + + Parameters + ---------- + module : BaseModule + Graph node of the module to be added. + """ + self.msg(3, 'add_module', module) + + # If no node exists for this module, add such a node. + module_added = self.find_node(module.identifier) + if module_added is None: + self.addNode(module) + else: + assert module == module_added, 'New module %r != previous %r.' % (module, module_added) + + # If this module has a previously added parent, reference this module to + # its parent and add this module to its parent's namespace. + parent_name, _, module_basename = module.identifier.rpartition('.') + if parent_name: + parent = self.find_node(parent_name) + if parent is None: + self.msg(4, 'add_module parent not found:', parent_name) + else: + self.add_edge(module, parent) + parent.add_submodule(module_basename, module) + + + def append_package_path(self, package_name, directory): + """ + Modulegraph does a good job at simulating Python's, but it can not + handle packagepath '__path__' modifications packages make at runtime. + + Therefore there is a mechanism whereby you can register extra paths + in this map for a package, and it will be honored. + + NOTE: This method has to be called before a package is resolved by + modulegraph. + + Parameters + ---------- + module : str + Fully-qualified module name. + directory : str + Absolute or relative path of the directory to append to the + '__path__' attribute. + """ + + paths = self._package_path_map.setdefault(package_name, []) + paths.append(directory) + + + def _safe_import_module( + self, module_partname, module_name, parent_module): + """ + Create a new graph node for the module with the passed name under the + parent package signified by the passed graph node _without_ raising + `ImportError` exceptions. + + If this module has already been imported, this module's existing graph + node will be returned; else if this module is importable, a new graph + node will be added for this module and returned; else this module is + unimportable, in which case `None` will be returned. Like the + `_safe_import_hook()` method, this method does _not_ raise + `ImportError` exceptions when this module is unimportable. + + Parameters + ---------- + module_partname : str + Unqualified name of the module to be imported (e.g., `text`). + module_name : str + Fully-qualified name of this module (e.g., `email.mime.text`). + parent_module : Package + Graph node of the previously imported parent module containing this + submodule _or_ `None` if this is a top-level module (i.e., + `module_name` contains no `.` delimiters). This parent module is + typically but _not_ always a package (e.g., the `os.path` submodule + contained by the `os` module). + + Returns + ---------- + Node + Graph node created for this module _or_ `None` if this module is + unimportable. + """ + self.msgin(3, "safe_import_module", module_partname, module_name, parent_module) + + # If this module has *NOT* already been imported, do so. + module = self.find_node(module_name) + if module is None: + # List of the absolute paths of all directories to be searched for + # this module. This effectively defaults to "sys.path". + search_dirs = None + + # If this module has a parent package... + if parent_module is not None: + # ...with a list of the absolute paths of all directories + # comprising this package, prefer that to "sys.path". + if parent_module.packagepath is not None: + search_dirs = parent_module.packagepath + # Else, something is horribly wrong. Return emptiness. + else: + self.msgout(3, "safe_import_module -> None (parent_parent.packagepath is None)") + return None + + try: + pathname, loader = self._find_module( + module_partname, search_dirs, parent_module) + except ImportError as exc: + self.msgout(3, "safe_import_module -> None (%r)" % exc) + return None + + (module, co) = self._load_module(module_name, pathname, loader) + if co is not None: + try: + if isinstance(co, ast.AST): + co_ast = co + co = compile(co_ast, pathname, 'exec', 0, True) + else: + co_ast = None + n = self._scan_code(module, co, co_ast) + self._process_imports(n) + + if self.replace_paths: + co = self._replace_paths_in_code(co) + module.code = co + except SyntaxError: + self.msg( + 1, "safe_import_module: SyntaxError in ", pathname, + ) + cls = InvalidSourceModule + module = self.createNode(cls, module_name) + + # If this is a submodule rather than top-level module... + if parent_module is not None: + self.msg(4, "safe_import_module create reference", module, "->", parent_module) + + # Add an edge from this submodule to its parent module. + self._updateReference( + module, parent_module, edge_data=DependencyInfo( + conditional=False, + fromlist=False, + function=False, + tryexcept=False, + )) + + # Add this submodule to its parent module. + parent_module.add_submodule(module_partname, module) + + # Return this module. + self.msgout(3, "safe_import_module ->", module) + return module + + def _load_module(self, fqname, pathname, loader): + from importlib._bootstrap_external import ExtensionFileLoader + self.msgin(2, "load_module", fqname, pathname, + loader.__class__.__name__) + partname = fqname.rpartition(".")[-1] + + if loader.is_package(partname): + if isinstance(loader, NAMESPACE_PACKAGE): + # This is a PEP-420 namespace package. + m = self.createNode(NamespacePackage, fqname) + m.filename = '-' + m.packagepath = loader.namespace_dirs[:] # copy for safety + else: + # Regular package. + # + # NOTE: this might be a legacy setuptools (pkg_resources) + # based namespace package (with __init__.py, but calling + # `pkg_resources.declare_namespace(__name__)`). To properly + # handle the case when such a package is split across + # multiple locations, we need to resolve the package + # paths via metadata. + ns_pkgpaths = self._legacy_ns_packages.get(fqname, []) + + if isinstance(loader, ExtensionFileLoader): + m = self.createNode(ExtensionPackage, fqname) + else: + m = self.createNode(Package, fqname) + m.filename = pathname + # PEP-302-compliant loaders return the pathname of the + # `__init__`-file, not the package directory. + assert os.path.basename(pathname).startswith('__init__.') + m.packagepath = [os.path.dirname(pathname)] + ns_pkgpaths + + # As per comment at top of file, simulate runtime packagepath + # additions + m.packagepath = m.packagepath + self._package_path_map.get( + fqname, []) + + if isinstance(m, NamespacePackage): + return (m, None) + + co = None + if loader is BUILTIN_MODULE: + cls = BuiltinModule + elif isinstance(loader, ExtensionFileLoader): + cls = Extension + else: + try: + src = loader.get_source(partname) + except (UnicodeDecodeError, SyntaxError) as e: + # The `UnicodeDecodeError` is typically raised here when the + # source file contains non-ASCII characters in some local + # encoding that is different from UTF-8, but fails to + # declare it via PEP361 encoding header. Python seems to + # be able to load and run such module, but we cannot retrieve + # the source for it via the `loader.get_source()`. + # + # The `UnicodeDecoreError` in turn triggers a `SyntaxError` + # when such invalid character appears on the first line of + # the source file (and interrupts the scan for PEP361 + # encoding header). + # + # In such cases, we try to fall back to reading the source + # as raw data file. + + # If `SyntaxError` was not raised during handling of + # a `UnicodeDecodeError`, it was likely a genuine syntax + # error, so re-raise it. + if isinstance(e, SyntaxError): + if not isinstance(e.__context__, UnicodeDecodeError): + raise + + self.msg(2, "load_module: failed to obtain source for " + f"{partname}: {e}! Falling back to reading as " + "raw data!") + + path = loader.get_filename(partname) + src = loader.get_data(path) + + if src is not None: + try: + co = compile(src, pathname, 'exec', ast.PyCF_ONLY_AST, True) + cls = SourceModule + except SyntaxError: + co = None + cls = InvalidSourceModule + except Exception as exc: # FIXME: more specific? + cls = InvalidSourceModule + self.msg(2, "load_module: InvalidSourceModule", pathname, + exc) + else: + # no src available + try: + co = loader.get_code(partname) + cls = (CompiledModule if co is not None + else InvalidCompiledModule) + except Exception as exc: # FIXME: more specific? + self.msg(2, "load_module: InvalidCompiledModule, " + "Cannot load code", pathname, exc) + cls = InvalidCompiledModule + + m = self.createNode(cls, fqname) + m.filename = pathname + + self.msgout(2, "load_module ->", m) + return (m, co) + + def _safe_import_hook( + self, target_module_partname, source_module, target_attr_names, + level=DEFAULT_IMPORT_LEVEL, edge_attr=None): + """ + Import the module with the passed name and all parent packages of this + module from the previously imported caller module signified by the + passed graph node _without_ raising `ImportError` exceptions. + + This method wraps the lowel-level `_import_hook()` method. On catching + an `ImportError` exception raised by that method, this method creates + and adds a `MissingNode` instance describing the unimportable module to + the graph instead. + + Parameters + ---------- + target_module_partname : str + Partially-qualified name of the module to be imported. If `level` + is: + * `ABSOLUTE_OR_RELATIVE_IMPORT_LEVEL` (e.g., the Python 2 default) + or a positive integer (e.g., an explicit relative import), the + fully-qualified name of this module is the concatenation of the + fully-qualified name of the caller module's package and this + parameter. + * `ABSOLUTE_IMPORT_LEVEL` (e.g., the Python 3 default), this name + is already fully-qualified. + * A non-negative integer (e.g., `1`), this name is typically the + empty string. In this case, this is a "from"-style relative + import (e.g., "from . import bar") and the fully-qualified name + of this module is dynamically resolved by import machinery. + source_module : Node + Graph node for the previously imported **caller module** (i.e., + module containing the `import` statement triggering the call to + this method) _or_ `None` if this module is to be imported in a + "disconnected" manner. **Passing `None` is _not_ recommended.** + Doing so produces a disconnected graph in which the graph node + created for the module to be imported will be disconnected and + hence unreachable from all other nodes -- which frequently causes + subtle issues in external callers (e.g., PyInstaller, which + silently ignores unreachable nodes). + target_attr_names : list + List of the unqualified names of all submodules and attributes to + be imported via a `from`-style import statement from this target + module if any (e.g., the list `[encode_base64, encode_noop]` for + the import `from email.encoders import encode_base64, encode_noop`) + _or_ `None` otherwise. Ignored unless `source_module` is the graph + node of a package (i.e., is an instance of the `Package` class). + Why? Because: + * Consistency. The `_import_importable_package_submodules()` + method accepts a similar list applicable only to packages. + * Efficiency. Unlike packages, modules cannot physically contain + submodules. Hence, any target module imported via a `from`-style + import statement as an attribute from another target parent + module must itself have been imported in that target parent + module. The import statement responsible for that import must + already have been previously parsed by `ModuleGraph`, in which + case that target module will already be frozen by PyInstaller. + These imports are safely ignorable here. + level : int + Whether to perform an absolute or relative import. This parameter + corresponds exactly to the parameter of the same name accepted by + the `__import__()` built-in: "The default is -1 which indicates + both absolute and relative imports will be attempted. 0 means only + perform absolute imports. Positive values for level indicate the + number of parent directories to search relative to the directory of + the module calling `__import__()`." Defaults to -1 under Python 2 + and 0 under Python 3. Since this default depends on the major + version of the current Python interpreter, depending on this + default can result in unpredictable and non-portable behaviour. + Callers are strongly recommended to explicitly pass this parameter + rather than implicitly accept this default. + + Returns + ---------- + list + List of the graph nodes created for all modules explicitly imported + by this call, including the passed module and all submodules listed + in `target_attr_names` _but_ excluding all parent packages + implicitly imported by this call. If `target_attr_names` is either + `None` or the empty list, this is guaranteed to be a list of one + element: the graph node created for the passed module. As above, + `MissingNode` instances are created for all unimportable modules. + """ + self.msg(3, "_safe_import_hook", target_module_partname, source_module, target_attr_names, level) + + def is_swig_candidate(): + return (source_module is not None and + target_attr_names is None and + level == ABSOLUTE_IMPORT_LEVEL and + type(source_module) is SourceModule and + target_module_partname == + '_' + source_module.identifier.rpartition('.')[2]) + + def is_swig_wrapper(source_module): + with open(source_module.filename, 'rb') as fp: + contents = fp.read() + contents = importlib.util.decode_source(contents) + first_line = contents.splitlines()[0] if contents else '' + self.msg(5, 'SWIG wrapper candidate first line: %r' % (first_line)) + return "automatically generated by SWIG" in first_line + + + # List of the graph nodes created for all target modules both + # imported by and returned from this call, whose: + # + # * First element is the graph node for the core target module + # specified by the "target_module_partname" parameter. + # * Remaining elements are the graph nodes for all target submodules + # specified by the "target_attr_names" parameter. + target_modules = None + + # True if this is a Python 2-style implicit relative import of a + # SWIG-generated C extension. False if we checked and it is not SWIG. + # None if we haven't checked yet. + is_swig_import = None + + # Attempt to import this target module in the customary way. + try: + target_modules = self.import_hook( + target_module_partname, source_module, + target_attr_names=None, level=level, edge_attr=edge_attr) + # Failing that, defer to custom module importers handling non-standard + # import schemes (namely, SWIG). + except InvalidRelativeImportError: + self.msgout(2, "Invalid relative import", level, + target_module_partname, target_attr_names) + result = [] + for sub in target_attr_names or '*': + m = self.createNode(InvalidRelativeImport, + '.' * level + target_module_partname, sub) + self._updateReference(source_module, m, edge_data=edge_attr) + result.append(m) + return result + except ImportError as msg: + # If this is an absolute top-level import under Python 3 and if the + # name to be imported is the caller's name prefixed by "_", this + # could be a SWIG-generated Python 2-style implicit relative import. + # SWIG-generated files contain functions named swig_import_helper() + # importing dynamic libraries residing in the same directory. For + # example, a SWIG-generated caller module "csr.py" might resemble: + # + # # This file was automatically generated by SWIG (http://www.swig.org). + # ... + # def swig_import_helper(): + # ... + # try: + # fp, pathname, description = imp.find_module('_csr', + # [dirname(__file__)]) + # except ImportError: + # import _csr + # return _csr + # + # While there exists no reasonable means for modulegraph to parse + # the call to imp.find_module(), the subsequent implicit relative + # import is trivially parsable. This import is prohibited under + # Python 3, however, and thus parsed only if the caller's file is + # parsable plaintext (as indicated by a filetype of ".py") and the + # first line of this file is the above SWIG header comment. + # + # The constraint that this library's name be the caller's name + # prefixed by '_' is explicitly mandated by SWIG and thus a + # reliable indicator of "SWIG-ness". The SWIG documentation states: + # "When linking the module, the name of the output file has to match + # the name of the module prefixed by an underscore." + # + # Only source modules (e.g., ".py"-suffixed files) are SWIG import + # candidates. All other node types are safely ignorable. + if is_swig_candidate(): + self.msg( + 4, + 'SWIG import candidate (name=%r, caller=%r, level=%r)' % ( + target_module_partname, source_module, level)) + is_swig_import = is_swig_wrapper(source_module) + if is_swig_import: + # Convert this Python 2-compliant implicit relative + # import prohibited by Python 3 into a Python + # 3-compliant explicit relative "from"-style import for + # the duration of this function call by overwriting the + # original parameters passed to this call. + target_attr_names = [target_module_partname] + target_module_partname = '' + level = 1 + self.msg(2, + 'SWIG import (caller=%r, fromlist=%r, level=%r)' + % (source_module, target_attr_names, level)) + # Import this target SWIG C extension's package. + try: + target_modules = self.import_hook( + target_module_partname, source_module, + target_attr_names=None, + level=level, + edge_attr=edge_attr) + except ImportError as msg: + self.msg(2, "SWIG ImportError:", str(msg)) + + # If this module remains unimportable... + if target_modules is None: + self.msg(2, "ImportError:", str(msg)) + + # Add this module as a MissingModule node. + target_module = self.createNode( + MissingModule, + _path_from_importerror(msg, target_module_partname)) + self._updateReference( + source_module, target_module, edge_data=edge_attr) + + # Initialize this list to this node. + target_modules = [target_module] + + # Ensure that the above logic imported exactly one target module. + assert len(target_modules) == 1, ( + 'Expected import_hook() to' + 'return only one module but received: {}'.format(target_modules)) + + # Target module imported above. + target_module = target_modules[0] + + if isinstance(target_module, MissingModule) \ + and is_swig_import is None and is_swig_candidate() \ + and is_swig_wrapper(source_module): + # if this possible swig C module was previously imported from + # a python module other than its corresponding swig python + # module, then it may have been considered a MissingModule. + # Try to reimport it now. For details see pull-request #2578 + # and issue #1522. + # + # If this module was takes as a SWIG candidate above, but failed + # to import, this would be a MissingModule, too. Thus check if + # this was the case (is_swig_import would be not None) to avoid + # recursion error. If `is_swig_import` is None and we are still a + # swig candidate then that means we haven't properly imported this + # swig module yet so do that below. + # + # Remove the MissingModule node from the graph so that we can + # attempt a reimport and avoid collisions. This node should be + # fine to remove because the proper module will be imported and + # added to the graph in the next line (call to _safe_import_hook). + self.removeNode(target_module) + # Reimport the SWIG C module relative to the wrapper + target_modules = self._safe_import_hook( + target_module_partname, source_module, + target_attr_names=None, level=1, edge_attr=edge_attr) + # return the output regardless because it would just be + # duplicating the processing below + return target_modules + + if isinstance(edge_attr, DependencyInfo): + edge_attr = edge_attr._replace(fromlist=True) + + # If this is a "from"-style import *AND* this target module is a + # package, import all attributes listed by the "import" clause of this + # import that are submodules of this package. If this target module is + # *NOT* a package, these attributes are always ignorable globals (e.g., + # classes, variables) defined at the top level of this module. + # + # If this target module is a non-package, it could still contain + # importable submodules (e.g., the non-package `os` module containing + # the `os.path` submodule). In this case, these submodules are already + # imported by this target module's pure-Python code. Since our import + # scanner already detects these imports, these submodules need *NOT* be + # reimported here. (Doing so would be harmless but inefficient.) + if target_attr_names and isinstance(target_module, + (Package, AliasNode)): + # For the name of each attribute imported from this target package + # into this source module... + for target_submodule_partname in target_attr_names: + #FIXME: Is this optimization *REALLY* an optimization or at all + #necessary? The findNode() method called below should already + #be heavily optimized, in which case this optimization here is + #premature, senseless, and should be eliminated. + + # If this attribute is a previously imported submodule of this + # target module, optimize this edge case. + if target_module.is_submodule(target_submodule_partname): + # Graph node for this submodule. + target_submodule = target_module.get_submodule( + target_submodule_partname) + + #FIXME: What? Shouldn't "target_submodule" *ALWAYS* be + #non-None here? Assert this to be non-None instead. + if target_submodule is not None: + #FIXME: Why does duplication matter? List searches are + #mildly expensive. + + # If this submodule has not already been added to the + # list of submodules to be returned, do so. + if target_submodule not in target_modules: + self._updateReference( + source_module, + target_submodule, + edge_data=edge_attr) + target_modules.append(target_submodule) + continue + + # Fully-qualified name of this submodule. + target_submodule_name = ( + target_module.identifier + '.' + target_submodule_partname) + + # Graph node of this submodule if previously imported or None. + target_submodule = self.find_node(target_submodule_name) + + # If this submodule has not been imported, do so as if this + # submodule were the only attribute listed by the "import" + # clause of this import (e.g., as "from foo import bar" rather + # than "from foo import car, far, bar"). + if target_submodule is None: + # Attempt to import this submodule. + try: + # Ignore the list of graph nodes returned by this + # method. If both this submodule's package and this + # submodule are importable, this method returns a + # 2-element list whose second element is this + # submodule's graph node. However, if this submodule's + # package is importable but this submodule is not, + # this submodule is either: + # + # * An ignorable global attribute defined at the top + # level of this package's "__init__" submodule. In + # this case, this method returns a 1-element list + # without raising an exception. + # * A non-ignorable unimportable submodule. In this + # case, this method raises an "ImportError". + # + # While the first two cases are disambiguatable by the + # length of this list, doing so would render this code + # dependent on import_hook() details subject to change. + # Instead, call findNode() to decide the truthiness. + self.import_hook( + target_module_partname, source_module, + target_attr_names=[target_submodule_partname], + level=level, + edge_attr=edge_attr) + + # Graph node of this submodule imported by the prior + # call if importable or None otherwise. + target_submodule = self.find_node(target_submodule_name) + + # If this submodule does not exist, this *MUST* be an + # ignorable global attribute defined at the top level + # of this package's "__init__" submodule. + if target_submodule is None: + # Assert this to actually be the case. + assert target_module.is_global_attr( + target_submodule_partname), ( + 'No global named {} in {}.__init__'.format( + target_submodule_partname, + target_module.identifier)) + + # Skip this safely ignorable importation to the + # next attribute. See similar logic in the body of + # _import_importable_package_submodules(). + self.msg(4, '_safe_import_hook', 'ignoring imported non-module global', target_module.identifier, target_submodule_partname) + continue + + # If this is a SWIG C extension, instruct PyInstaller + # to freeze this extension under its unqualified rather + # than qualified name (e.g., as "_csr" rather than + # "scipy.sparse.sparsetools._csr"), permitting the + # implicit relative import in its parent SWIG module to + # successfully find this extension. + if is_swig_import: + # If a graph node with this name already exists, + # avoid collisions by emitting an error instead. + if self.find_node(target_submodule_partname): + self.msg( + 2, + 'SWIG import error: %r basename %r ' + 'already exists' % ( + target_submodule_name, + target_submodule_partname)) + else: + self.msg( + 4, + 'SWIG import renamed from %r to %r' % ( + target_submodule_name, + target_submodule_partname)) + target_submodule.identifier = ( + target_submodule_partname) + # If this submodule is unimportable, add a MissingModule. + except ImportError as msg: + self.msg(2, "ImportError:", str(msg)) + target_submodule = self.createNode( + MissingModule, target_submodule_name) + + # Add this submodule to its package. + target_module.add_submodule( + target_submodule_partname, target_submodule) + if target_submodule is not None: + self._updateReference( + target_module, target_submodule, edge_data=edge_attr) + self._updateReference( + source_module, target_submodule, edge_data=edge_attr) + + if target_submodule not in target_modules: + target_modules.append(target_submodule) + + # Return the list of all target modules imported by this call. + return target_modules + + + def _scan_code( + self, + module, + module_code_object, + module_code_object_ast=None): + """ + Parse and add all import statements from the passed code object of the + passed source module to this graph, recursively. + + **This method is at the root of all `ModuleGraph` recursion.** + Recursion begins here and ends when all import statements in all code + objects of all modules transitively imported by the source module + passed to the first call to this method have been added to the graph. + Specifically, this method: + + 1. If the passed `module_code_object_ast` parameter is non-`None`, + parses all import statements from this object. + 2. Else, parses all import statements from the passed + `module_code_object` parameter. + 1. For each such import statement: + 1. Adds to this `ModuleGraph` instance: + 1. Nodes for all target modules of these imports. + 1. Directed edges from this source module to these target + modules. + 2. Recursively calls this method with these target modules. + + Parameters + ---------- + module : Node + Graph node of the module to be parsed. + module_code_object : PyCodeObject + Code object providing this module's disassembled Python bytecode. + Ignored unless `module_code_object_ast` is `None`. + module_code_object_ast : optional[ast.AST] + Optional abstract syntax tree (AST) of this module if any or `None` + otherwise. Defaults to `None`, in which case the passed + `module_code_object` is parsed instead. + Returns + ---------- + module : Node + Graph node of the module to be parsed. + """ + + # For safety, guard against multiple scans of the same module by + # resetting this module's list of deferred target imports. + module._deferred_imports = [] + + # Parse all imports from this module *BEFORE* adding these imports to + # the graph. If an AST is provided, parse that rather than this + # module's code object. + if module_code_object_ast is not None: + # Parse this module's AST for imports. + self._scan_ast(module, module_code_object_ast) + + # Parse this module's code object for all relevant non-imports + # (e.g., global variable declarations and undeclarations). + self._scan_bytecode( + module, module_code_object, is_scanning_imports=False) + # Else, parse this module's code object for imports. + else: + self._scan_bytecode( + module, module_code_object, is_scanning_imports=True) + + return module + + def _scan_ast(self, module, module_code_object_ast): + """ + Parse and add all import statements from the passed abstract syntax + tree (AST) of the passed source module to this graph, non-recursively. + + Parameters + ---------- + module : Node + Graph node of the module to be parsed. + module_code_object_ast : ast.AST + Abstract syntax tree (AST) of this module to be parsed. + """ + + visitor = _Visitor(self, module) + visitor.visit(module_code_object_ast) + + #FIXME: Optimize. Global attributes added by this method are tested by + #other methods *ONLY* for packages, implying this method should scan and + #handle opcodes pertaining to global attributes (e.g., + #"STORE_NAME", "DELETE_GLOBAL") only if the passed "module" + #object is an instance of the "Package" class. For all other module types, + #these opcodes should simply be ignored. + # + #After doing so, the "Node._global_attr_names" attribute and all methods + #using this attribute (e.g., Node.is_global()) should be moved from the + #"Node" superclass to the "Package" subclass. + def _scan_bytecode( + self, module, module_code_object, is_scanning_imports): + """ + Parse and add all import statements from the passed code object of the + passed source module to this graph, non-recursively. + + This method parses all reasonably parsable operations (i.e., operations + that are both syntactically and semantically parsable _without_ + requiring Turing-complete interpretation) directly or indirectly + involving module importation from this code object. This includes: + + * `IMPORT_NAME`, denoting an import statement. Ignored unless + the passed `is_scanning_imports` parameter is `True`. + * `STORE_NAME` and `STORE_GLOBAL`, denoting the + declaration of a global attribute (e.g., class, variable) in this + module. This method stores each such declaration for subsequent + lookup. While global attributes are usually irrelevant to import + parsing, they remain the only means of distinguishing erroneous + non-ignorable attempts to import non-existent submodules of a package + from successful ignorable attempts to import existing global + attributes of a package's `__init__` submodule (e.g., the `bar` in + `from foo import bar`, which is either a non-ignorable submodule of + `foo` or an ignorable global attribute of `foo.__init__`). + * `DELETE_NAME` and `DELETE_GLOBAL`, denoting the + undeclaration of a previously declared global attribute in this + module. + + Since `ModuleGraph` is _not_ intended to replicate the behaviour of a + full-featured Turing-complete Python interpreter, this method ignores + operations that are _not_ reasonably parsable from this code object -- + even those directly or indirectly involving module importation. This + includes: + + * `STORE_ATTR(namei)`, implementing `TOS.name = TOS1`. If `TOS` is the + name of a target module currently imported into the namespace of the + passed source module, this opcode would ideally be parsed to add that + global attribute to that target module. Since this addition only + conditionally occurs on the importation of this source module and + execution of the code branch in this module performing this addition, + however, that global _cannot_ be unconditionally added to that target + module. In short, only Turing-complete behaviour suffices. + * `DELETE_ATTR(namei)`, implementing `del TOS.name`. If `TOS` is the + name of a target module currently imported into the namespace of the + passed source module, this opcode would ideally be parsed to remove + that global attribute from that target module. Again, however, only + Turing-complete behaviour suffices. + + Parameters + ---------- + module : Node + Graph node of the module to be parsed. + module_code_object : PyCodeObject + Code object of the module to be parsed. + is_scanning_imports : bool + `True` only if this method is parsing import statements from + `IMPORT_NAME` opcodes. If `False`, no import statements will be + parsed. This parameter is typically: + * `True` when parsing this module's code object for such imports. + * `False` when parsing this module's abstract syntax tree (AST) + (rather than code object) for such imports. In this case, that + parsing will have already parsed import statements, which this + parsing must avoid repeating. + """ + level = None + fromlist = None + + # 'deque' is a list-like container with fast appends, pops on + # either end, and automatically discarding elements too much. + prev_insts = deque(maxlen=2) + for inst in util.iterate_instructions(module_code_object): + if not inst: + continue + # If this is an import statement originating from this module, + # parse this import. + # + # Note that the related "IMPORT_FROM" opcode need *NOT* be parsed. + # "IMPORT_NAME" suffices. For further details, see + # http://probablyprogramming.com/2008/04/14/python-import_name + if inst.opname == 'IMPORT_NAME': + # If this method is ignoring import statements, skip to the + # next opcode. + if not is_scanning_imports: + continue + + assert prev_insts[-2].opname == 'LOAD_CONST' + assert prev_insts[-1].opname == 'LOAD_CONST' + + # Python >=2.5: LOAD_CONST flags, LOAD_CONST names, IMPORT_NAME name + level = prev_insts[-2].argval + fromlist = prev_insts[-1].argval + + assert fromlist is None or type(fromlist) is tuple + target_module_partname = inst.argval + + #FIXME: The exact same logic appears in _collect_import(), + #which isn't particularly helpful. Instead, defer this logic + #until later by: + # + #* Refactor the "_deferred_imports" list to contain 2-tuples + # "(_safe_import_hook_args, _safe_import_hook_kwargs)" rather + # than 3-tuples "(have_star, _safe_import_hook_args, + # _safe_import_hook_kwargs)". + #* Stop prepending these tuples by a "have_star" boolean both + # here, in _collect_import(), and in _process_imports(). + #* Shift the logic below to _process_imports(). + #* Remove the same logic from _collect_import(). + have_star = False + if fromlist is not None: + fromlist = uniq(fromlist) + if '*' in fromlist: + fromlist.remove('*') + have_star = True + + # Record this import as originating from this module for + # subsequent handling by the _process_imports() method. + module._deferred_imports.append(( + have_star, + (target_module_partname, module, fromlist, level), + {} + )) + + elif inst.opname in ('STORE_NAME', 'STORE_GLOBAL'): + # If this is the declaration of a global attribute (e.g., + # class, variable) in this module, store this declaration for + # subsequent lookup. See method docstring for further details. + # + # Global attributes are usually irrelevant to import parsing, but + # remain the only means of distinguishing erroneous non-ignorable + # attempts to import non-existent submodules of a package from + # successful ignorable attempts to import existing global + # attributes of a package's "__init__" submodule (e.g., the "bar" + # in "from foo import bar", which is either a non-ignorable + # submodule of "foo" or an ignorable global attribute of + # "foo.__init__"). + name = inst.argval + module.add_global_attr(name) + + elif inst.opname in ('DELETE_NAME', 'DELETE_GLOBAL'): + # If this is the undeclaration of a previously declared global + # attribute (e.g., class, variable) in this module, remove that + # declaration to prevent subsequent lookup. See method docstring + # for further details. + name = inst.argval + module.remove_global_attr_if_found(name) + + prev_insts.append(inst) + + + def _process_imports(self, source_module): + """ + Graph all target modules whose importations were previously parsed from + the passed source module by a prior call to the `_scan_code()` method + and methods call by that method (e.g., `_scan_ast()`, + `_scan_bytecode()`, `_scan_bytecode_stores()`). + + Parameters + ---------- + source_module : Node + Graph node of the source module to graph target imports for. + """ + + # If this source module imported no target modules, noop. + if not source_module._deferred_imports: + return + + # For each target module imported by this source module... + for have_star, import_info, kwargs in source_module._deferred_imports: + # Graph node of the target module specified by the "from" portion + # of this "from"-style star import (e.g., an import resembling + # "from {target_module_name} import *") or ignored otherwise. + target_modules = self._safe_import_hook(*import_info, **kwargs) + if not target_modules: + # If _safe_import_hook suppressed the module, quietly drop it. + # Do not create an ExcludedModule instance, because that might + # completely suppress the module whereas it might need to be + # included due to reference from another module (that does + # not exclude it via hook). + continue + target_module = target_modules[0] + + # If this is a "from"-style star import, process this import. + if have_star: + #FIXME: Sadly, the current approach to importing attributes + #from "from"-style star imports is... simplistic. This should + #be revised as follows. If this target module is: + # + #* A package: + # * Whose "__init__" submodule defines the "__all__" global + # attribute, only attributes listed by this attribute should + # be imported. + # * Else, *NO* attributes should be imported. + #* A non-package: + # * Defining the "__all__" global attribute, only attributes + # listed by this attribute should be imported. + # * Else, only public attributes whose names are *NOT* + # prefixed by "_" should be imported. + source_module.add_global_attrs_from_module(target_module) + + source_module._starimported_ignored_module_names.update( + target_module._starimported_ignored_module_names) + + # If this target module has no code object and hence is + # unparsable, record its name for posterity. + if target_module.code is None: + target_module_name = import_info[0] + source_module._starimported_ignored_module_names.add( + target_module_name) + + # For safety, prevent these imports from being reprocessed. + source_module._deferred_imports = None + + + def _find_module(self, name, path, parent=None): + """ + 3-tuple describing the physical location of the module with the passed + name if this module is physically findable _or_ raise `ImportError`. + + This high-level method wraps the low-level `modulegraph.find_module()` + function with additional support for graph-based module caching. + + Parameters + ---------- + name : str + Fully-qualified name of the Python module to be found. + path : list + List of the absolute paths of all directories to search for this + module _or_ `None` if the default path list `self.path` is to be + searched. + parent : Node + Package containing this module if this module is a submodule of a + package _or_ `None` if this is a top-level module. + + Returns + ---------- + (filename, loader) + See `modulegraph._find_module()` for details. + + Raises + ---------- + ImportError + If this module is _not_ found. + """ + + if parent is not None: + # assert path is not None + fullname = parent.identifier + '.' + name + else: + fullname = name + + node = self.find_node(fullname) + if node is not None: + self.msg(3, "find_module: already included?", node) + raise ImportError(name) + + if path is None: + if name in sys.builtin_module_names: + return (None, BUILTIN_MODULE) + + path = self.path + + return self._find_module_path(fullname, name, path) + + + def _find_module_path(self, fullname, module_name, search_dirs): + """ + 3-tuple describing the physical location of the module with the passed + name if this module is physically findable _or_ raise `ImportError`. + + This low-level function is a variant on the standard `imp.find_module()` + function with additional support for: + + * Multiple search paths. The passed list of absolute paths will be + iteratively searched for the first directory containing a file + corresponding to this module. + * Compressed (e.g., zipped) packages. + + For efficiency, the higher level `ModuleGraph._find_module()` method + wraps this function with support for module caching. + + Parameters + ---------- + module_name : str + Fully-qualified name of the module to be found. + search_dirs : list + List of the absolute paths of all directories to search for this + module (in order). Searching will halt at the first directory + containing this module. + + Returns + ---------- + (filename, loader) + 2-tuple describing the physical location of this module, where: + * `filename` is the absolute path of this file. + * `loader` is the import loader. + In case of a namespace package, this is a NAMESPACE_PACKAGE + instance + + Raises + ---------- + ImportError + If this module is _not_ found. + """ + self.msgin(4, "_find_module_path <-", fullname, search_dirs) + + # Top-level 2-tuple to be returned. + path_data = None + + # List of the absolute paths of all directories comprising the + # namespace package to which this module belongs if any. + namespace_dirs = [] + + try: + for search_dir in search_dirs: + # PEP 302-compliant importer making loaders for this directory. + importer = pkgutil.get_importer(search_dir) + + # If this directory is not importable, continue. + if importer is None: + # self.msg(4, "_find_module_path importer not found", search_dir) + continue + + # Get the PEP 302-compliant loader object loading this module. + # + # If this importer defines the PEP 451-compliant find_spec() + # method, use that, and obtain loader from spec. This should + # be available on python >= 3.4. + if hasattr(importer, 'find_spec'): + loader = None + spec = importer.find_spec(module_name) + if spec is not None: + loader = spec.loader + namespace_dirs.extend(spec.submodule_search_locations or []) + # Else if this importer defines the PEP 302-compliant find_loader() + # method, use that. + elif hasattr(importer, 'find_loader'): + loader, loader_namespace_dirs = importer.find_loader( + module_name) + namespace_dirs.extend(loader_namespace_dirs) + # Else if this importer defines the Python 2-specific + # find_module() method, fall back to that. Despite the method + # name, this method returns a loader rather than a module. + elif hasattr(importer, 'find_module'): + loader = importer.find_module(module_name) + # Else, raise an exception. + else: + raise ImportError( + "Module %r importer %r loader unobtainable" % (module_name, importer)) + + # If this module is not loadable from this directory, continue. + if loader is None: + # self.msg(4, "_find_module_path loader not found", search_dir) + continue + + # Absolute path of this module. If this module resides in a + # compressed archive, this is the absolute path of this module + # after extracting this module from that archive and hence + # should not exist; else, this path should typically exist. + pathname = None + + # If this loader defines the PEP 302-compliant get_filename() + # method, preferably call that method first. Most if not all + # loaders (including zipimporter objects) define this method. + if hasattr(loader, 'get_filename'): + pathname = loader.get_filename(module_name) + # Else if this loader provides a "path" attribute, defer to that. + elif hasattr(loader, 'path'): + pathname = loader.path + # Else, raise an exception. + else: + raise ImportError( + "Module %r loader %r path unobtainable" % (module_name, loader)) + + # If no path was found, this is probably a namespace package. In + # such case, continue collecting namespace directories. + if pathname is None: + self.msg(4, "_find_module_path path not found", pathname) + continue + + # Return such metadata. + path_data = (pathname, loader) + break + # Else if this is a namespace package, return such metadata. + else: + if namespace_dirs: + path_data = (namespace_dirs[0], + NAMESPACE_PACKAGE(namespace_dirs)) + except UnicodeDecodeError as exc: + self.msgout(1, "_find_module_path -> unicode error", exc) + # Ensure that exceptions are logged, as this function is typically + # called by the import_module() method which squelches ImportErrors. + except Exception as exc: + self.msgout(4, "_find_module_path -> exception", exc) + raise + + # If this module was not found, raise an exception. + self.msgout(4, "_find_module_path ->", path_data) + if path_data is None: + raise ImportError("No module named " + repr(module_name)) + + return path_data + + + def create_xref(self, out=None): + global header, footer, entry, contpl, contpl_linked, imports + if out is None: + out = sys.stdout + scripts = [] + mods = [] + for mod in self.iter_graph(): + name = os.path.basename(mod.graphident) + if isinstance(mod, Script): + scripts.append((name, mod)) + else: + mods.append((name, mod)) + scripts.sort() + mods.sort() + scriptnames = [sn for sn, m in scripts] + scripts.extend(mods) + mods = scripts + + title = "modulegraph cross reference for " + ', '.join(scriptnames) + print(header % {"TITLE": title}, file=out) + + def sorted_namelist(mods): + lst = [os.path.basename(mod.graphident) for mod in mods if mod] + lst.sort() + return lst + for name, m in mods: + content = "" + if isinstance(m, BuiltinModule): + content = contpl % {"NAME": name, + "TYPE": "(builtin module)"} + elif isinstance(m, Extension): + content = contpl % {"NAME": name, + "TYPE": "%s" % m.filename} + else: + url = urllib.request.pathname2url(m.filename or "") + content = contpl_linked % {"NAME": name, "URL": url, + 'TYPE': m.__class__.__name__} + oute, ince = map(sorted_namelist, self.get_edges(m)) + if oute: + links = [] + for n in oute: + links.append(""" %s\n""" % (n, n)) + # #8226 = bullet-point; can't use html-entities since the + # test-suite uses xml.etree.ElementTree.XMLParser, which + # does't supprot them. + links = " • ".join(links) + content += imports % {"HEAD": "imports", "LINKS": links} + if ince: + links = [] + for n in ince: + links.append(""" %s\n""" % (n, n)) + # #8226 = bullet-point; can't use html-entities since the + # test-suite uses xml.etree.ElementTree.XMLParser, which + # does't supprot them. + links = " • ".join(links) + content += imports % {"HEAD": "imported by", "LINKS": links} + print(entry % {"NAME": name, "CONTENT": content}, file=out) + print(footer, file=out) + + def itergraphreport(self, name='G', flatpackages=()): + # XXX: Can this be implemented using Dot()? + nodes = list(map(self.graph.describe_node, self.graph.iterdfs(self))) + describe_edge = self.graph.describe_edge + edges = deque() + packagenodes = set() + packageidents = {} + nodetoident = {} + inpackages = {} + mainedges = set() + + # XXX - implement + flatpackages = dict(flatpackages) + + def nodevisitor(node, data, outgoing, incoming): + if not isinstance(data, Node): + return {'label': str(node)} + #if isinstance(d, (ExcludedModule, MissingModule, BadModule)): + # return None + s = ' ' + type(data).__name__ + for i, v in enumerate(data.infoTuple()[:1], 1): + s += '| %s' % (i, v) + return {'label': s, 'shape': 'record'} + + + def edgevisitor(edge, data, head, tail): + # XXX: This method nonsense, the edge + # data is never initialized. + if data == 'orphan': + return {'style': 'dashed'} + elif data == 'pkgref': + return {'style': 'dotted'} + return {} + + yield 'digraph %s {\ncharset="UTF-8";\n' % (name,) + attr = dict(rankdir='LR', concentrate='true') + cpatt = '%s="%s"' + for item in attr.items(): + yield '\t%s;\n' % (cpatt % item,) + + # find all packages (subgraphs) + for (node, data, outgoing, incoming) in nodes: + nodetoident[node] = getattr(data, 'graphident', None) + if isinstance(data, Package): + packageidents[data.graphident] = node + inpackages[node] = set([node]) + packagenodes.add(node) + + # create sets for subgraph, write out descriptions + for (node, data, outgoing, incoming) in nodes: + # update edges + for edge in (describe_edge(e) for e in outgoing): + edges.append(edge) + + # describe node + yield '\t"%s" [%s];\n' % ( + node, + ','.join([ + (cpatt % item) for item in + nodevisitor(node, data, outgoing, incoming).items() + ]), + ) + + inside = inpackages.get(node) + if inside is None: + inside = inpackages[node] = set() + ident = nodetoident[node] + if ident is None: + continue + pkgnode = packageidents.get(ident[:ident.rfind('.')]) + if pkgnode is not None: + inside.add(pkgnode) + + graph = [] + subgraphs = {} + for key in packagenodes: + subgraphs[key] = [] + + while edges: + edge, data, head, tail = edges.popleft() + if ((head, tail)) in mainedges: + continue + mainedges.add((head, tail)) + tailpkgs = inpackages[tail] + common = inpackages[head] & tailpkgs + if not common and tailpkgs: + usepkgs = sorted(tailpkgs) + if len(usepkgs) != 1 or usepkgs[0] != tail: + edges.append((edge, data, head, usepkgs[0])) + edges.append((edge, 'pkgref', usepkgs[-1], tail)) + continue + if common: + common = common.pop() + if tail == common: + edges.append((edge, data, tail, head)) + elif head == common: + subgraphs[common].append((edge, 'pkgref', head, tail)) + else: + edges.append((edge, data, common, head)) + edges.append((edge, data, common, tail)) + + else: + graph.append((edge, data, head, tail)) + + def do_graph(edges, tabs): + edgestr = tabs + '"%s" -> "%s" [%s];\n' + # describe edge + for (edge, data, head, tail) in edges: + attribs = edgevisitor(edge, data, head, tail) + yield edgestr % ( + head, + tail, + ','.join([(cpatt % item) for item in attribs.items()]), + ) + + for g, edges in subgraphs.items(): + yield '\tsubgraph "cluster_%s" {\n' % (g,) + yield '\t\tlabel="%s";\n' % (nodetoident[g],) + for s in do_graph(edges, '\t\t'): + yield s + yield '\t}\n' + + for s in do_graph(graph, '\t'): + yield s + + yield '}\n' + + def graphreport(self, fileobj=None, flatpackages=()): + if fileobj is None: + fileobj = sys.stdout + fileobj.writelines(self.itergraphreport(flatpackages=flatpackages)) + + def report(self): + """Print a report to stdout, listing the found modules with their + paths, as well as modules that are missing, or seem to be missing. + """ + print() + print("%-15s %-25s %s" % ("Class", "Name", "File")) + print("%-15s %-25s %s" % ("-----", "----", "----")) + for m in sorted(self.iter_graph(), key=lambda n: n.graphident): + if isinstance(m, AliasNode): + print("%-15s %-25s %s" % (type(m).__name__, m.graphident, m.identifier)) + else: + print("%-15s %-25s %s" % (type(m).__name__, m.graphident, m.filename or "")) + + def _replace_paths_in_code(self, co): + new_filename = original_filename = os.path.normpath(co.co_filename) + for f, r in self.replace_paths: + f = os.path.join(f, '') + r = os.path.join(r, '') + if original_filename.startswith(f): + new_filename = r + original_filename[len(f):] + break + + else: + return co + + consts = list(co.co_consts) + for i in range(len(consts)): + if isinstance(consts[i], type(co)): + consts[i] = self._replace_paths_in_code(consts[i]) + + return co.replace(co_consts=tuple(consts), co_filename=new_filename) diff --git a/venv/Lib/site-packages/PyInstaller/lib/modulegraph/util.py b/venv/Lib/site-packages/PyInstaller/lib/modulegraph/util.py new file mode 100644 index 0000000..dab8c06 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/lib/modulegraph/util.py @@ -0,0 +1,21 @@ +import dis +import inspect + + +def iterate_instructions(code_object): + """Delivers the byte-code instructions as a continuous stream. + + Yields `dis.Instruction`. After each code-block (`co_code`), `None` is + yielded to mark the end of the block and to interrupt the steam. + """ + # The arg extension the EXTENDED_ARG opcode represents is automatically handled by get_instructions() but the + # instruction is left in. Get rid of it to make subsequent parsing easier/safer. + yield from (i for i in dis.get_instructions(code_object) if i.opname != "EXTENDED_ARG") + + yield None + + # For each constant in this code object that is itself a code object, + # parse this constant in the same manner. + for constant in code_object.co_consts: + if inspect.iscode(constant): + yield from iterate_instructions(constant) diff --git a/venv/Lib/site-packages/PyInstaller/loader/__init__.py b/venv/Lib/site-packages/PyInstaller/loader/__init__.py new file mode 100644 index 0000000..792d600 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/loader/__init__.py @@ -0,0 +1 @@ +# diff --git a/venv/Lib/site-packages/PyInstaller/loader/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/loader/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..2a2d1e2 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/loader/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/loader/__pycache__/pyiboot01_bootstrap.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/loader/__pycache__/pyiboot01_bootstrap.cpython-311.pyc new file mode 100644 index 0000000..5fb90bc Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/loader/__pycache__/pyiboot01_bootstrap.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/loader/__pycache__/pyimod01_archive.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/loader/__pycache__/pyimod01_archive.cpython-311.pyc new file mode 100644 index 0000000..e19ddd3 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/loader/__pycache__/pyimod01_archive.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/loader/__pycache__/pyimod02_importers.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/loader/__pycache__/pyimod02_importers.cpython-311.pyc new file mode 100644 index 0000000..b19a03a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/loader/__pycache__/pyimod02_importers.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/loader/__pycache__/pyimod03_ctypes.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/loader/__pycache__/pyimod03_ctypes.cpython-311.pyc new file mode 100644 index 0000000..a240a61 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/loader/__pycache__/pyimod03_ctypes.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/loader/__pycache__/pyimod04_pywin32.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/loader/__pycache__/pyimod04_pywin32.cpython-311.pyc new file mode 100644 index 0000000..7640fbf Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/loader/__pycache__/pyimod04_pywin32.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/loader/pyiboot01_bootstrap.py b/venv/Lib/site-packages/PyInstaller/loader/pyiboot01_bootstrap.py new file mode 100644 index 0000000..b0da1dd --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/loader/pyiboot01_bootstrap.py @@ -0,0 +1,95 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +#-- Start bootstrap process +# Only python built-in modules can be used. + +import sys + +import pyimod02_importers + +# Extend Python import machinery by adding PEP302 importers to sys.meta_path. +pyimod02_importers.install() + +#-- Bootstrap process is complete. +# We can use other python modules (e.g. os) + +import os # noqa: E402 + +# Let other python modules know that the code is running in frozen mode. +if not hasattr(sys, 'frozen'): + sys.frozen = True + +# sys._MEIPASS is now set in the bootloader. Hooray. + +# Python 3 C-API function Py_SetPath() resets sys.prefix to empty string. Python 2 was using PYTHONHOME for sys.prefix. +# Let's do the same for Python 3. +sys.prefix = sys._MEIPASS +sys.exec_prefix = sys.prefix + +# Python 3.3+ defines also sys.base_prefix. Let's set them too. +sys.base_prefix = sys.prefix +sys.base_exec_prefix = sys.exec_prefix + +# Some packages behave differently when running inside virtual environment. E.g., IPython tries to append path +# VIRTUAL_ENV to sys.path. For the frozen app we want to prevent this behavior. +VIRTENV = 'VIRTUAL_ENV' +if VIRTENV in os.environ: + # On some platforms (e.g., AIX) 'os.unsetenv()' is unavailable and deleting the var from os.environ does not + # delete it from the environment. + os.environ[VIRTENV] = '' + del os.environ[VIRTENV] + +# Ensure sys.path contains absolute paths. Otherwise, import of other python modules will fail when current working +# directory is changed by the frozen application. +python_path = [] +for pth in sys.path: + python_path.append(os.path.abspath(pth)) + sys.path = python_path + +# At least on Windows, Python seems to hook up the codecs on this import, so it is not enough to just package up all +# the encodings. +# +# It was also reported that without 'encodings' module, the frozen executable fails to load in some configurations: +# http://www.pyinstaller.org/ticket/651 +# +# Importing 'encodings' module in a run-time hook is not enough, since some run-time hooks require this module, and the +# order of running the code from the run-time hooks is not defined. +try: + import encodings # noqa: F401 +except ImportError: + pass + +# In the Python interpreter 'warnings' module is imported when 'sys.warnoptions' is not empty. Mimic this behavior. +if sys.warnoptions: + import warnings # noqa: F401 + +# Install the hooks for ctypes +import pyimod03_ctypes # noqa: E402 + +pyimod03_ctypes.install() + +# Install the hooks for pywin32 (Windows only) +if sys.platform.startswith('win'): + import pyimod04_pywin32 + pyimod04_pywin32.install() + +# Apply a hack for metadata that was collected from (unzipped) python eggs; the EGG-INFO directories are collected into +# their parent directories (my_package-version.egg/EGG-INFO), and for metadata to be discoverable by +# `importlib.metadata`, the .egg directory needs to be in `sys.path`. The deprecated `pkg_resources` does not have this +# limitation, and seems to work as long as the .egg directory's parent directory (in our case `sys._MEIPASS` is in +# `sys.path`. +for entry in os.listdir(sys._MEIPASS): + entry = os.path.join(sys._MEIPASS, entry) + if not os.path.isdir(entry): + continue + if entry.endswith('.egg'): + sys.path.append(entry) diff --git a/venv/Lib/site-packages/PyInstaller/loader/pyimod01_archive.py b/venv/Lib/site-packages/PyInstaller/loader/pyimod01_archive.py new file mode 100644 index 0000000..f74d468 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/loader/pyimod01_archive.py @@ -0,0 +1,135 @@ +#----------------------------------------------------------------------------- +# 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 \\?\). + 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: + return None + typecode, entry_offset, entry_length = entry + + # 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"{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, PYZ_ITEM_NSPKG) 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 diff --git a/venv/Lib/site-packages/PyInstaller/loader/pyimod02_importers.py b/venv/Lib/site-packages/PyInstaller/loader/pyimod02_importers.py new file mode 100644 index 0000000..a3844ab --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/loader/pyimod02_importers.py @@ -0,0 +1,702 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- +""" +PEP-302 and PEP-451 importers for frozen applications. +""" + +# **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 sys +import os +import io + +import _frozen_importlib +import _thread + +import pyimod01_archive + +if sys.flags.verbose and sys.stderr: + + def trace(msg, *a): + sys.stderr.write(msg % a) + sys.stderr.write("\n") +else: + + def trace(msg, *a): + pass + + +def _decode_source(source_bytes): + """ + Decode bytes representing source code and return the string. Universal newline support is used in the decoding. + Based on CPython's implementation of the same functionality: + https://github.com/python/cpython/blob/3.9/Lib/importlib/_bootstrap_external.py#L679-L688 + """ + # Local import to avoid including `tokenize` and its dependencies in `base_library.zip` + from tokenize import detect_encoding + source_bytes_readline = io.BytesIO(source_bytes).readline + encoding = detect_encoding(source_bytes_readline) + newline_decoder = io.IncrementalNewlineDecoder(decoder=None, translate=True) + return newline_decoder.decode(source_bytes.decode(encoding[0])) + + +# Global instance of PYZ archive reader. Initialized by install(). +pyz_archive = None + +# Some runtime hooks might need to traverse available frozen package/module hierarchy to simulate filesystem. +# Such traversals can be efficiently implemented using a prefix tree (trie), whose computation we defer until first +# access. +_pyz_tree_lock = _thread.RLock() +_pyz_tree = None + + +def get_pyz_toc_tree(): + global _pyz_tree + + with _pyz_tree_lock: + if _pyz_tree is None: + _pyz_tree = _build_pyz_prefix_tree(pyz_archive) + return _pyz_tree + + +# Fully resolve sys._MEIPASS, so we can compare fully-resolved paths to it. +_RESOLVED_TOP_LEVEL_DIRECTORY = os.path.realpath(sys._MEIPASS) + +# If we are running as macOS .app bundle, compute the alternative top-level directory path as well. +_is_macos_app_bundle = False +if sys.platform == 'darwin' and _RESOLVED_TOP_LEVEL_DIRECTORY.endswith("Contents/Frameworks"): + _is_macos_app_bundle = True + _ALTERNATIVE_TOP_LEVEL_DIRECTORY = os.path.join( + os.path.dirname(_RESOLVED_TOP_LEVEL_DIRECTORY), + 'Resources', + ) + + +# Helper for computing PYZ prefix tree +def _build_pyz_prefix_tree(pyz_archive): + tree = dict() + for entry_name, entry_data in pyz_archive.toc.items(): + name_components = entry_name.split('.') + typecode = entry_data[0] + current = tree + if typecode in {pyimod01_archive.PYZ_ITEM_PKG, pyimod01_archive.PYZ_ITEM_NSPKG}: + # Package; create new dictionary node for its modules + for name_component in name_components: + current = current.setdefault(name_component, {}) + else: + # Module; create the leaf node (empty string) + for name_component in name_components[:-1]: + current = current.setdefault(name_component, {}) + current[name_components[-1]] = '' + return tree + + +class PyiFrozenImporter: + """ + PyInstaller's frozen module importer (finder + loader) for specific search path. + + Per-path instances allow us to properly translate the given module name ("fullname") into full PYZ entry name. + For example, with search path being `sys._MEIPASS`, the module "mypackage.mod" would translate to "mypackage.mod" + in the PYZ archive. However, if search path was `sys._MEIPASS/myotherpackage/_vendored` (for example, if + `myotherpacakge` added this path to `sys.path`), then "mypackage.mod" would need to translate to + "myotherpackage._vendored.mypackage.mod" in the PYZ archive. + """ + def __repr__(self): + return f"{self.__class__.__name__}({self._path})" + + @classmethod + def path_hook(cls, path): + trace(f"PyInstaller: running path finder hook for path: {path!r}") + try: + finder = cls(path) + trace("PyInstaller: hook succeeded") + return finder + except Exception as e: + trace(f"PyInstaller: hook failed: {e}") + raise + + @staticmethod + def _compute_relative_path(path, top_level): + try: + relative_path = os.path.relpath(path, top_level) + except ValueError as e: + raise ImportError("Path outside of top-level application directory") from e + + if relative_path.startswith('..'): + raise ImportError("Path outside of top-level application directory") + + return relative_path + + def __init__(self, path): + self._path = path # Store original path, as given. + self._pyz_archive = pyz_archive + + # Resolve path for comparison + resolved_path = os.path.realpath(path) + + # Compare resolved path to resolved top-level application directory. + try: + relative_path = self._compute_relative_path(resolved_path, _RESOLVED_TOP_LEVEL_DIRECTORY) + except Exception: + if _is_macos_app_bundle: + relative_path = self._compute_relative_path(resolved_path, _ALTERNATIVE_TOP_LEVEL_DIRECTORY) + else: + raise + + # Ensure that path does not point to a file on filesystem. Strictly speaking, we should be checking that the + # given path is a valid directory, but that would need to check both PYZ and filesystem. So for now, limit the + # check to catch paths pointing to file, because that breaks `runpy.run_path()`, as per #8767. + if os.path.isfile(path): + raise ImportError("only directories are supported") + + if relative_path == '.': + self._pyz_entry_prefix = '' + else: + self._pyz_entry_prefix = '.'.join(relative_path.split(os.path.sep)) + + def _compute_pyz_entry_name(self, fullname): + """ + Convert module fullname into PYZ entry name, subject to the prefix implied by this finder's search path. + """ + tail_module = fullname.rpartition('.')[2] + + if self._pyz_entry_prefix: + return self._pyz_entry_prefix + "." + tail_module + else: + return tail_module + + @property + def fallback_finder(self): + """ + Opportunistically create a *fallback finder* using `sys.path_hooks` entries that are located *after* our hook. + The main goal of this exercise is to obtain an instance of python's FileFinder, but in theory any other hook + that comes after ours is eligible to be a fallback. + + Having this fallback allows our finder to "cooperate" with python's FileFinder, as if the two were a single + finder, which allows us to work around the python's PathFinder permitting only one finder instance per path + without subclassing FileFinder. + """ + if hasattr(self, '_fallback_finder'): + return self._fallback_finder + + # Try to instantiate fallback finder + our_hook_found = False + + self._fallback_finder = None + for idx, hook in enumerate(sys.path_hooks): + if hook == self.path_hook: + our_hook_found = True + continue # Our hook + + if not our_hook_found: + continue # Skip hooks before our hook + + try: + self._fallback_finder = hook(self._path) + break + except ImportError: + pass + + return self._fallback_finder + + def _find_fallback_spec(self, fullname, target): + """ + Attempt to find the spec using fallback finder, which is opportunistically created here. Typically, this would + be python's FileFinder, which can discover specs for on-filesystem modules, such as extension modules and + modules that are collected only as source .py files. + + Having this fallback allows our finder to "cooperate" with python's FileFinder, as if the two were a single + finder, which allows us to work around the python's PathFinder permitting only one finder instance per path + without subclassing FileFinder. + """ + if not hasattr(self, '_fallback_finder'): + self._fallback_finder = self._get_fallback_finder() + + if self._fallback_finder is None: + return None + + return self._fallback_finder.find_spec(fullname, target) + + #-- Core PEP451 finder functionality, modeled after importlib.abc.PathEntryFinder + # https://docs.python.org/3/library/importlib.html#importlib.abc.PathEntryFinder + def invalidate_caches(self): + """ + A method which, when called, should invalidate any internal cache used by the finder. Used by + importlib.invalidate_caches() when invalidating the caches of all finders on sys.meta_path. + + https://docs.python.org/3/library/importlib.html#importlib.abc.MetaPathFinder.invalidate_caches + """ + # We do not use any caches, but if we have created a fallback finder, propagate the function call. + # NOTE: use getattr() with _fallback_finder attribute, in order to avoid unnecessary creation of the + # fallback finder in case when it does not exist yet. + fallback_finder = getattr(self, '_fallback_finder', None) + if fallback_finder is not None: + if hasattr(fallback_finder, 'invalidate_caches'): + fallback_finder.invalidate_caches() + + def find_spec(self, fullname, target=None): + """ + A method for finding a spec for the specified module. The finder will search for the module only within the + path entry to which it is assigned. If a spec cannot be found, None is returned. When passed in, target is a + module object that the finder may use to make a more educated guess about what spec to return. + + https://docs.python.org/3/library/importlib.html#importlib.abc.PathEntryFinder.find_spec + """ + trace(f"{self}: find_spec: called with fullname={fullname!r}, target={fullname!r}") + + # Convert fullname to PYZ entry name. + pyz_entry_name = self._compute_pyz_entry_name(fullname) + + # Try looking up the entry in the PYZ archive + entry_data = self._pyz_archive.toc.get(pyz_entry_name) + if entry_data is None: + # Entry not found - try using fallback finder (for example, python's own FileFinder) to resolve on-disk + # resources, such as extension modules and modules that are collected only as source .py files. + trace(f"{self}: find_spec: {fullname!r} not found in PYZ...") + + if self.fallback_finder is not None: + trace(f"{self}: find_spec: attempting resolve using fallback finder {self.fallback_finder!r}.") + fallback_spec = self.fallback_finder.find_spec(fullname, target) + trace(f"{self}: find_spec: fallback finder returned spec: {fallback_spec!r}.") + return fallback_spec + else: + trace(f"{self}: find_spec: fallback finder is not available.") + + return None + + # Entry found + typecode = entry_data[0] + trace(f"{self}: find_spec: found {fullname!r} in PYZ as {pyz_entry_name!r}, typecode={typecode}") + + if typecode == pyimod01_archive.PYZ_ITEM_NSPKG: + # PEP420 namespace package + # We can use regular list for submodule_search_locations; the caller (i.e., python's PathFinder) takes care + # of constructing _NamespacePath from it. + spec = _frozen_importlib.ModuleSpec(fullname, None) + spec.submodule_search_locations = [ + # NOTE: since we are using sys._MEIPASS as prefix, we need to construct path from resolved PYZ entry + # name (equivalently, we could combine `self._path` and last part of `fullname`). + os.path.join(sys._MEIPASS, pyz_entry_name.replace('.', os.path.sep)), + ] + return spec + + # Resolve full filename, as if the module/package was located on filesystem. + origin = self.get_filename(fullname) + is_package = typecode == pyimod01_archive.PYZ_ITEM_PKG + + spec = _frozen_importlib.ModuleSpec( + fullname, + self, # loader + is_package=is_package, + origin=origin, + ) + + # Make the import machinery set __file__. + # PEP 451 says: "has_location" is true if the module is locatable. In that case the spec's origin is used + # as the location and __file__ is set to spec.origin. If additional location information is required + # (e.g., zipimport), that information may be stored in spec.loader_state. + spec.has_location = True + + # Set submodule_search_locations for packages. Seems to be required for importlib_resources from 3.2.0; + # see issue #5395. + if is_package: + spec.submodule_search_locations = [os.path.dirname(origin)] + + return spec + + # The following methods are part of legacy PEP302 finder interface. They have been deprecated since python 3.4, + # and removed in python 3.12. Provide compatibility shims to accommodate code that might still be using them. + if sys.version_info[:2] < (3, 12): + + def find_loader(self, fullname): + """ + A legacy method for finding a loader for the specified module. Returns a 2-tuple of (loader, portion) where + portion is a sequence of file system locations contributing to part of a namespace package. The loader may + be None while specifying portion to signify the contribution of the file system locations to a namespace + package. An empty list can be used for portion to signify the loader is not part of a namespace package. If + loader is None and portion is the empty list then no loader or location for a namespace package were found + (i.e. failure to find anything for the module). + + Deprecated since python 3.4, removed in 3.12. + """ + # Based on: + # https://github.com/python/cpython/blob/v3.11.9/Lib/importlib/_bootstrap_external.py#L1587-L1600 + spec = self.find_spec(fullname) + if spec is None: + return None, [] + return spec.loader, spec.submodule_search_locations or [] + + def find_module(self, fullname): + """ + A concrete implementation of Finder.find_module() which is equivalent to self.find_loader(fullname)[0]. + + Deprecated since python 3.4, removed in 3.12. + """ + # Based on: + # https://github.com/python/cpython/blob/v3.11.9/Lib/importlib/_bootstrap_external.py#L1585 + # https://github.com/python/cpython/blob/v3.11.9/Lib/importlib/_bootstrap_external.py#L622-L639 + # + loader, portions = self.find_loader(fullname) + return loader + + #-- Core PEP451 loader functionality as defined by importlib.abc.Loader + # https://docs.python.org/3/library/importlib.html#importlib.abc.Loader + def create_module(self, spec): + """ + A method that returns the module object to use when importing a module. This method may return None, indicating + that default module creation semantics should take place. + + https://docs.python.org/3/library/importlib.html#importlib.abc.Loader.create_module + """ + return None + + def exec_module(self, module): + """ + A method that executes the module in its own namespace when a module is imported or reloaded. The module + should already be initialized when exec_module() is called. When this method exists, create_module() + must be defined. + + https://docs.python.org/3/library/importlib.html#importlib.abc.Loader.exec_module + """ + spec = module.__spec__ + bytecode = self.get_code(spec.name) + if bytecode is None: + raise RuntimeError(f"Failed to retrieve bytecode for {spec.name!r}!") + + # Set by the import machinery + assert hasattr(module, '__file__') + + # If `submodule_search_locations` is not None, this is a package; set __path__. + if spec.submodule_search_locations is not None: + module.__path__ = spec.submodule_search_locations + + exec(bytecode, module.__dict__) + + # The following method is part of legacy PEP302 loader interface. It has been deprecated since python 3.4, and + # slated for removal in python 3.12, although that has not happened yet. Provide compatibility shim to accommodate + # code that might still be using it. + if True: + + def load_module(self, fullname): + """ + A legacy method for loading a module. If the module cannot be loaded, ImportError is raised, otherwise the + loaded module is returned. + + Deprecated since python 3.4, slated for removal in 3.12 (but still present in python's own FileLoader in + both v3.12.4 and v3.13.0rc1). + """ + # Based on: + # https://github.com/python/cpython/blob/v3.11.9/Lib/importlib/_bootstrap_external.py#L942-L945 + import importlib._bootstrap as _bootstrap + return _bootstrap._load_module_shim(self, fullname) + + #-- PEP302 protocol extensions as defined by importlib.abc.ExecutionLoader + # https://docs.python.org/3/library/importlib.html#importlib.abc.ExecutionLoader + def get_filename(self, fullname): + """ + A method that is to return the value of __file__ for the specified module. If no path is available, ImportError + is raised. + + If source code is available, then the method should return the path to the source file, regardless of whether a + bytecode was used to load the module. + + https://docs.python.org/3/library/importlib.html#importlib.abc.ExecutionLoader.get_filename + """ + # Resolve fullname -> PYZ entry name (in case custom search path is in effect) + pyz_entry_name = self._compute_pyz_entry_name(fullname) + + # Look up the PYZ entry + entry_data = self._pyz_archive.toc.get(pyz_entry_name) + if entry_data is None: + raise ImportError(f'Module {fullname!r} not found in PYZ archive (entry {pyz_entry_name!r}).') + typecode = entry_data[0] + + # NOTE: since we are using sys._MEIPASS as prefix, we need to construct path from resolved PYZ entry name + # (equivalently, we could combine `self._path` and last part of `fullname`). + if typecode == pyimod01_archive.PYZ_ITEM_PKG: + return os.path.join(sys._MEIPASS, pyz_entry_name.replace('.', os.path.sep), '__init__.pyc') + elif typecode == pyimod01_archive.PYZ_ITEM_MODULE: + return os.path.join(sys._MEIPASS, pyz_entry_name.replace('.', os.path.sep) + '.pyc') + + # Unsupported entry type + return None + + #-- PEP302 protocol extensions as defined by importlib.abc.InspectLoader + # https://docs.python.org/3/library/importlib.html#importlib.abc.InspectLoader + def get_code(self, fullname): + """ + Return the code object for a module, or None if the module does not have a code object (as would be the case, + for example, for a built-in module). Raise an ImportError if loader cannot find the requested module. + + https://docs.python.org/3/library/importlib.html#importlib.abc.InspectLoader.get_code + """ + # Resolve fullname -> PYZ entry name (in case custom search path is in effect) + pyz_entry_name = self._compute_pyz_entry_name(fullname) + + # Look up the PYZ entry - so we can raise ImportError for non-existing modules. + entry_data = self._pyz_archive.toc.get(pyz_entry_name) + if entry_data is None: + raise ImportError(f'Module {fullname!r} not found in PYZ archive (entry {pyz_entry_name!r}).') + + return self._pyz_archive.extract(pyz_entry_name) + + def get_source(self, fullname): + """ + A method to return the source of a module. It is returned as a text string using universal newlines, translating + all recognized line separators into '\n' characters. Returns None if no source is available (e.g. a built-in + module). Raises ImportError if the loader cannot find the module specified. + + https://docs.python.org/3/library/importlib.html#importlib.abc.InspectLoader.get_source + """ + # Use getfilename() to obtain path to file if it were located on filesystem. This implicitly checks that the + # fullname is valid. + filename = self.get_filename(fullname) + + # FIXME: according to python docs "if source code is available, then the [getfilename()] method should return + # the path to the source file, regardless of whether a bytecode was used to load the module.". At the moment, + # our implementation always returns pyc suffix. + filename = filename[:-1] + + try: + # Read in binary mode, then decode + with open(filename, 'rb') as fp: + source_bytes = fp.read() + return _decode_source(source_bytes) + except FileNotFoundError: + pass + + # Source code is unavailable. + return None + + def is_package(self, fullname): + """ + A method to return a true value if the module is a package, a false value otherwise. ImportError is raised if + the loader cannot find the module. + + https://docs.python.org/3/library/importlib.html#importlib.abc.InspectLoader.is_package + """ + # Resolve fullname -> PYZ entry name (in case custom search path is in effect) + pyz_entry_name = self._compute_pyz_entry_name(fullname) + + # Look up the PYZ entry - so we can raise ImportError for non-existing modules. + entry_data = self._pyz_archive.toc.get(pyz_entry_name) + if entry_data is None: + raise ImportError(f'Module {fullname!r} not found in PYZ archive (entry {pyz_entry_name!r}).') + typecode = entry_data[0] + + # We do not need to worry about PEP420 namespace package entries (pyimod01_archive.PYZ_ITEM_NSPKG) here, because + # namespace packages do not use the loader part of this importer. + return typecode == pyimod01_archive.PYZ_ITEM_PKG + + #-- PEP302 protocol extensions as dfined by importlib.abc.ResourceLoader + # https://docs.python.org/3/library/importlib.html#importlib.abc.ResourceLoader + def get_data(self, path): + """ + A method to return the bytes for the data located at path. Loaders that have a file-like storage back-end that + allows storing arbitrary data can implement this abstract method to give direct access to the data stored. + OSError is to be raised if the path cannot be found. The path is expected to be constructed using a module’s + __file__ attribute or an item from a package’s __path__. + + https://docs.python.org/3/library/importlib.html#importlib.abc.ResourceLoader.get_data + """ + # Try to fetch the data from the filesystem. Since __file__ attribute works properly, just try to open the file + # and read it. + with open(path, 'rb') as fp: + return fp.read() + + #-- Support for `importlib.resources`. + def get_resource_reader(self, fullname): + """ + Return resource reader compatible with `importlib.resources`. + """ + # Resolve fullname -> PYZ entry name (in case custom search path is in effect) + pyz_entry_name = self._compute_pyz_entry_name(fullname) + + return PyiFrozenResourceReader(self, pyz_entry_name) + + +class PyiFrozenResourceReader: + """ + Resource reader for importlib.resources / importlib_resources support. + + Supports only on-disk resources, which should cover the typical use cases, i.e., the access to data files; + PyInstaller collects data files onto filesystem, and as of v6.0.0, the embedded PYZ archive is guaranteed + to contain only .pyc modules. + + When listing resources, source .py files will not be listed as they are not collected by default. Similarly, + sub-directories that contained only .py files are not reconstructed on filesystem, so they will not be listed, + either. If access to .py files is required for whatever reason, they need to be explicitly collected as data files + anyway, which will place them on filesystem and make them appear as resources. + + For on-disk resources, we *must* return path compatible with pathlib.Path() in order to avoid copy to a temporary + file, which might break under some circumstances, e.g., metpy with importlib_resources back-port, due to: + https://github.com/Unidata/MetPy/blob/a3424de66a44bf3a92b0dcacf4dff82ad7b86712/src/metpy/plots/wx_symbols.py#L24-L25 + (importlib_resources tries to use 'fonts/wx_symbols.ttf' as a temporary filename suffix, which fails as it contains + a separator). + + Furthermore, some packages expect files() to return either pathlib.Path or zipfile.Path, e.g., + https://github.com/tensorflow/datasets/blob/master/tensorflow_datasets/core/utils/resource_utils.py#L81-L97 + This makes implementation of mixed support for on-disk and embedded resources using importlib.abc.Traversable + protocol rather difficult. + + So in order to maximize compatibility with unfrozen behavior, the below implementation is basically equivalent of + importlib.readers.FileReader from python 3.10: + https://github.com/python/cpython/blob/839d7893943782ee803536a47f1d4de160314f85/Lib/importlib/readers.py#L11 + and its underlying classes, importlib.abc.TraversableResources and importlib.abc.ResourceReader: + https://github.com/python/cpython/blob/839d7893943782ee803536a47f1d4de160314f85/Lib/importlib/abc.py#L422 + https://github.com/python/cpython/blob/839d7893943782ee803536a47f1d4de160314f85/Lib/importlib/abc.py#L312 + """ + def __init__(self, importer, name): + # Local import to avoid including `pathlib` and its dependencies in `base_library.zip` + from pathlib import Path + self.importer = importer + if self.importer.is_package(name): # covers both normal packages and PEP-420 namespace packages + self.path = Path(sys._MEIPASS).joinpath(*name.split('.')) + else: + # For modules, we should return the path to their parent (package) directory. + self.path = Path(sys._MEIPASS).joinpath(*name.split('.')[:-1]) + + def open_resource(self, resource): + return self.files().joinpath(resource).open('rb') + + def resource_path(self, resource): + return str(self.path.joinpath(resource)) + + def is_resource(self, path): + return self.files().joinpath(path).is_file() + + def contents(self): + return (item.name for item in self.files().iterdir()) + + def files(self): + return self.path + + +class PyiFrozenEntryPointLoader: + """ + A special loader that enables retrieval of the code-object for the __main__ module. + """ + def __repr__(self): + return self.__class__.__name__ + + def get_code(self, fullname): + if fullname == '__main__': + # Special handling for __main__ module; the bootloader should store code object to _pyi_main_co + # attribute of the module. + return sys.modules['__main__']._pyi_main_co + + raise ImportError(f'{self} cannot handle module {fullname!r}') + + +def install(): + """ + Install PyInstaller's frozen finders/loaders/importers into python's import machinery. + """ + # Setup PYZ archive reader. + # + # The bootloader should store the path to PYZ archive (the path to the PKG archive and the offset within it; for + # executable-embedded archive, this is for example /path/executable_name?117568) into _pyinstaller_pyz + # attribute of the sys module. + global pyz_archive + + if not hasattr(sys, '_pyinstaller_pyz'): + raise RuntimeError("Bootloader did not set sys._pyinstaller_pyz!") + + try: + pyz_archive = pyimod01_archive.ZlibArchiveReader(sys._pyinstaller_pyz, check_pymagic=True) + except Exception as e: + raise RuntimeError("Failed to setup PYZ archive reader!") from e + + delattr(sys, '_pyinstaller_pyz') + + # On Windows, there is finder called `_frozen_importlib.WindowsRegistryFinder`, which looks for Python module + # locations in Windows registry. The frozen application should not look for those, so remove this finder + # from `sys.meta_path`. + for entry in sys.meta_path: + if getattr(entry, '__name__', None) == 'WindowsRegistryFinder': + sys.meta_path.remove(entry) + break + + # Insert our hook for `PyiFrozenImporter` into `sys.path_hooks`. Place it after `zipimporter`, if available. + for idx, entry in enumerate(sys.path_hooks): + if getattr(entry, '__name__', None) == 'zipimporter': + trace(f"PyInstaller: inserting our finder hook at index {idx + 1} in sys.path_hooks.") + sys.path_hooks.insert(idx + 1, PyiFrozenImporter.path_hook) + break + else: + trace("PyInstaller: zipimporter hook not found in sys.path_hooks! Prepending our finder hook to the list.") + sys.path_hooks.insert(0, PyiFrozenImporter.path_hook) + + # Python might have already created a `FileFinder` for `sys._MEIPASS`. Remove the entry from path importer cache, + # so that next loading attempt creates `PyiFrozenImporter` instead. This could probably be avoided altogether if + # we refrained from adding `sys._MEIPASS` to `sys.path` until our importer hooks is in place. + sys.path_importer_cache.pop(sys._MEIPASS, None) + + # Set the PyiFrozenEntryPointLoader as loader for __main__, in order for python to treat __main__ as a module + # instead of a built-in, and to allow its code object to be retrieved. + try: + sys.modules['__main__'].__loader__ = PyiFrozenEntryPointLoader() + except Exception: + pass + + # Apply hack for python >= 3.11 and its frozen stdlib modules. + if sys.version_info >= (3, 11): + _fixup_frozen_stdlib() + + +# A hack for python >= 3.11 and its frozen stdlib modules. Unless `sys._stdlib_dir` is set, these modules end up +# missing __file__ attribute, which causes problems with 3rd party code. At the time of writing, python interpreter +# configuration API does not allow us to influence `sys._stdlib_dir` - it always resets it to `None`. Therefore, +# we manually set the path, and fix __file__ attribute on modules. +def _fixup_frozen_stdlib(): + import _imp # built-in + + # If sys._stdlib_dir is None or empty, override it with sys._MEIPASS + if not sys._stdlib_dir: + try: + sys._stdlib_dir = sys._MEIPASS + except AttributeError: + pass + + # The sys._stdlib_dir set above should affect newly-imported python-frozen modules. However, most of them have + # been already imported during python initialization and our bootstrap, so we need to retroactively fix their + # __file__ attribute. + for module_name, module in sys.modules.items(): + if not _imp.is_frozen(module_name): + continue + + is_pkg = _imp.is_frozen_package(module_name) + + # Determine "real" name from __spec__.loader_state. + loader_state = module.__spec__.loader_state + + orig_name = loader_state.origname + if is_pkg: + orig_name += '.__init__' + + # We set suffix to .pyc to be consistent with our PyiFrozenImporter. + filename = os.path.join(sys._MEIPASS, *orig_name.split('.')) + '.pyc' + + # Fixup the __file__ attribute + if not hasattr(module, '__file__'): + try: + module.__file__ = filename + except AttributeError: + pass + + # Fixup the loader_state.filename + # Except for _frozen_importlib (importlib._bootstrap), whose loader_state.filename appears to be left at + # None in python. + if loader_state.filename is None and orig_name != 'importlib._bootstrap': + loader_state.filename = filename diff --git a/venv/Lib/site-packages/PyInstaller/loader/pyimod03_ctypes.py b/venv/Lib/site-packages/PyInstaller/loader/pyimod03_ctypes.py new file mode 100644 index 0000000..3ade7dd --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/loader/pyimod03_ctypes.py @@ -0,0 +1,131 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2005-2023, PyInstaller Development Team. +# +# Distributed under the terms of the GNU General Public License with exception +# for distributing bootloader. +# +# The full license is in the file COPYING.txt, distributed with this software. +#----------------------------------------------------------------------------- +""" +Hooks to make ctypes.CDLL, .PyDLL, etc. look in sys._MEIPASS first. +""" + +import sys + + +def install(): + """ + Install the hooks. + + This must be done from a function as opposed to at module-level, because when the module is imported/executed, + the import machinery is not completely set up yet. + """ + + import os + + try: + import ctypes + except ImportError: + # ctypes is not included in the frozen application + return + + def _frozen_name(name): + # If the given (file)name does not exist, fall back to searching for its basename in sys._MEIPASS, where + # PyInstaller usually collects shared libraries. + if name and not os.path.isfile(name): + frozen_name = os.path.join(sys._MEIPASS, os.path.basename(name)) + if os.path.isfile(frozen_name): + name = frozen_name + return name + + class PyInstallerImportError(OSError): + def __init__(self, name): + self.msg = ( + "Failed to load dynlib/dll %r. Most likely this dynlib/dll was not found when the application " + "was frozen." % name + ) + self.args = (self.msg,) + + class PyInstallerCDLL(ctypes.CDLL): + def __init__(self, name, *args, **kwargs): + name = _frozen_name(name) + try: + super().__init__(name, *args, **kwargs) + except Exception as base_error: + raise PyInstallerImportError(name) from base_error + + ctypes.CDLL = PyInstallerCDLL + ctypes.cdll = ctypes.LibraryLoader(PyInstallerCDLL) + + class PyInstallerPyDLL(ctypes.PyDLL): + def __init__(self, name, *args, **kwargs): + name = _frozen_name(name) + try: + super().__init__(name, *args, **kwargs) + except Exception as base_error: + raise PyInstallerImportError(name) from base_error + + ctypes.PyDLL = PyInstallerPyDLL + ctypes.pydll = ctypes.LibraryLoader(PyInstallerPyDLL) + + if sys.platform.startswith('win'): + + class PyInstallerWinDLL(ctypes.WinDLL): + def __init__(self, name, *args, **kwargs): + name = _frozen_name(name) + try: + super().__init__(name, *args, **kwargs) + except Exception as base_error: + raise PyInstallerImportError(name) from base_error + + ctypes.WinDLL = PyInstallerWinDLL + ctypes.windll = ctypes.LibraryLoader(PyInstallerWinDLL) + + class PyInstallerOleDLL(ctypes.OleDLL): + def __init__(self, name, *args, **kwargs): + name = _frozen_name(name) + try: + super().__init__(name, *args, **kwargs) + except Exception as base_error: + raise PyInstallerImportError(name) from base_error + + ctypes.OleDLL = PyInstallerOleDLL + ctypes.oledll = ctypes.LibraryLoader(PyInstallerOleDLL) + + try: + import ctypes.util + except ImportError: + # ctypes.util is not included in the frozen application + return + + # Same implementation as ctypes.util.find_library, except it prepends sys._MEIPASS to the search directories. + def pyinstaller_find_library(name): + if name in ('c', 'm'): + return ctypes.util.find_msvcrt() + # See MSDN for the REAL search order. + search_dirs = [sys._MEIPASS] + os.environ['PATH'].split(os.pathsep) + for directory in search_dirs: + fname = os.path.join(directory, name) + if os.path.isfile(fname): + return fname + if fname.lower().endswith(".dll"): + continue + fname = fname + ".dll" + if os.path.isfile(fname): + return fname + return None + + ctypes.util.find_library = pyinstaller_find_library + + +# On Mac OS insert sys._MEIPASS in the first position of the list of paths that ctypes uses to search for libraries. +# +# Note: 'ctypes' module will NOT be bundled with every app because code in this module is not scanned for module +# dependencies. It is safe to wrap 'ctypes' module into 'try/except ImportError' block. +if sys.platform.startswith('darwin'): + try: + from ctypes.macholib import dyld + dyld.DEFAULT_LIBRARY_FALLBACK.insert(0, sys._MEIPASS) + except ImportError: + # Do nothing when module 'ctypes' is not available. + pass diff --git a/venv/Lib/site-packages/PyInstaller/loader/pyimod04_pywin32.py b/venv/Lib/site-packages/PyInstaller/loader/pyimod04_pywin32.py new file mode 100644 index 0000000..b635d75 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/loader/pyimod04_pywin32.py @@ -0,0 +1,56 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2005-2023, PyInstaller Development Team. +# +# Distributed under the terms of the GNU General Public License with exception +# for distributing bootloader. +# +# The full license is in the file COPYING.txt, distributed with this software. +#----------------------------------------------------------------------------- +""" +Set search path for pywin32 DLLs. Due to the large number of pywin32 modules, we use a single loader-level script +instead of per-module runtime hook scripts. +""" + +import os +import sys + + +def install(): + # Sub-directories containing extensions. In original python environment, these are added to `sys.path` by the + # `pywin32.pth` so the extensions end up treated as top-level modules. We attempt to preserve the directory + # layout, so we need to add these directories to `sys.path` ourselves. + pywin32_ext_paths = ('win32', 'pythonwin') + pywin32_ext_paths = [os.path.join(sys._MEIPASS, pywin32_ext_path) for pywin32_ext_path in pywin32_ext_paths] + pywin32_ext_paths = [path for path in pywin32_ext_paths if os.path.isdir(path)] + sys.path.extend(pywin32_ext_paths) + + # Additional handling of `pywin32_system32` DLL directory + pywin32_system32_path = os.path.join(sys._MEIPASS, 'pywin32_system32') + + if not os.path.isdir(pywin32_system32_path): + # Either pywin32 is not collected, or we are dealing with version that does not use the pywin32_system32 + # sub-directory. In the latter case, the pywin32 DLLs should be in `sys._MEIPASS`, and nothing + # else needs to be done here. + return + + # Add the DLL directory to `sys.path`. + # This is necessary because `__import_pywin32_system_module__` from `pywintypes` module assumes that in a frozen + # application, the pywin32 DLLs (`pythoncom3X.dll` and `pywintypes3X.dll`) that are normally found in + # `pywin32_system32` sub-directory in `sys.path` (site-packages, really) are located directly in `sys.path`. + # This obviously runs afoul of our attempts at preserving the directory layout and placing them in the + # `pywin32_system32` sub-directory instead of the top-level application directory. + sys.path.append(pywin32_system32_path) + + # Add the DLL directory to DLL search path using os.add_dll_directory(). + # This allows extensions from win32 directory (e.g., win32api, win32crypt) to be loaded on their own without + # importing pywintypes first. The extensions are linked against pywintypes3X.dll. + os.add_dll_directory(pywin32_system32_path) + + # Add the DLL directory to PATH. This is necessary under certain versions of + # Anaconda python, where `os.add_dll_directory` does not work. + path = os.environ.get('PATH', None) + if not path: + path = pywin32_system32_path + else: + path = pywin32_system32_path + os.pathsep + path + os.environ['PATH'] = path diff --git a/venv/Lib/site-packages/PyInstaller/log.py b/venv/Lib/site-packages/PyInstaller/log.py new file mode 100644 index 0000000..7eb8f8e --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/log.py @@ -0,0 +1,64 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- +""" +Logging module for PyInstaller. +""" + +__all__ = ['getLogger', 'INFO', 'WARN', 'DEBUG', 'TRACE', 'ERROR', 'FATAL', 'DEPRECATION'] + +import os +import logging +from logging import DEBUG, ERROR, FATAL, INFO, WARN, getLogger + +TRACE = DEBUG - 5 +logging.addLevelName(TRACE, 'TRACE') +DEPRECATION = WARN + 5 +logging.addLevelName(DEPRECATION, 'DEPRECATION') +LEVELS = { + 'TRACE': TRACE, + 'DEBUG': DEBUG, + 'INFO': INFO, + 'WARN': WARN, + 'DEPRECATION': DEPRECATION, + 'ERROR': ERROR, + 'FATAL': FATAL, +} + +FORMAT = '%(relativeCreated)d %(levelname)s: %(message)s' +_env_level = os.environ.get("PYI_LOG_LEVEL", "INFO") +try: + level = LEVELS[_env_level.upper()] +except KeyError: + raise SystemExit(f"Invalid PYI_LOG_LEVEL value '{_env_level}'. Should be one of {list(LEVELS)}.") +logging.basicConfig(format=FORMAT, level=level) +logger = getLogger('PyInstaller') + + +def __add_options(parser): + parser.add_argument( + '--log-level', + choices=LEVELS, + metavar="LEVEL", + dest='loglevel', + help='Amount of detail in build-time console messages. LEVEL may be one of %s (default: INFO). ' + 'Also settable via and overrides the PYI_LOG_LEVEL environment variable.' % ', '.join(LEVELS), + ) + + +def __process_options(parser, opts): + if opts.loglevel: + try: + level = opts.loglevel.upper() + _level = LEVELS[level] + except KeyError: + parser.error('Unknown log level `%s`' % opts.loglevel) + logger.setLevel(_level) + os.environ["PYI_LOG_LEVEL"] = level diff --git a/venv/Lib/site-packages/PyInstaller/utils/__init__.py b/venv/Lib/site-packages/PyInstaller/utils/__init__.py new file mode 100644 index 0000000..792d600 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/utils/__init__.py @@ -0,0 +1 @@ +# diff --git a/venv/Lib/site-packages/PyInstaller/utils/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/utils/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..5350cfa Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/utils/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/utils/__pycache__/conftest.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/utils/__pycache__/conftest.cpython-311.pyc new file mode 100644 index 0000000..8413928 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/utils/__pycache__/conftest.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/utils/__pycache__/misc.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/utils/__pycache__/misc.cpython-311.pyc new file mode 100644 index 0000000..a4aa9cc Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/utils/__pycache__/misc.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/utils/__pycache__/osx.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/utils/__pycache__/osx.cpython-311.pyc new file mode 100644 index 0000000..e16971f Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/utils/__pycache__/osx.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/utils/__pycache__/run_tests.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/utils/__pycache__/run_tests.cpython-311.pyc new file mode 100644 index 0000000..169187a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/utils/__pycache__/run_tests.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/utils/__pycache__/tests.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/utils/__pycache__/tests.cpython-311.pyc new file mode 100644 index 0000000..0d357cb Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/utils/__pycache__/tests.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/utils/cliutils/__init__.py b/venv/Lib/site-packages/PyInstaller/utils/cliutils/__init__.py new file mode 100644 index 0000000..792d600 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/utils/cliutils/__init__.py @@ -0,0 +1 @@ +# diff --git a/venv/Lib/site-packages/PyInstaller/utils/cliutils/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/utils/cliutils/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..4385f82 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/utils/cliutils/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/utils/cliutils/__pycache__/archive_viewer.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/utils/cliutils/__pycache__/archive_viewer.cpython-311.pyc new file mode 100644 index 0000000..325a854 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/utils/cliutils/__pycache__/archive_viewer.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/utils/cliutils/__pycache__/bindepend.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/utils/cliutils/__pycache__/bindepend.cpython-311.pyc new file mode 100644 index 0000000..c2c413d Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/utils/cliutils/__pycache__/bindepend.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/utils/cliutils/__pycache__/grab_version.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/utils/cliutils/__pycache__/grab_version.cpython-311.pyc new file mode 100644 index 0000000..c08b9d0 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/utils/cliutils/__pycache__/grab_version.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/utils/cliutils/__pycache__/makespec.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/utils/cliutils/__pycache__/makespec.cpython-311.pyc new file mode 100644 index 0000000..5eb4d9a Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/utils/cliutils/__pycache__/makespec.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/utils/cliutils/__pycache__/set_version.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/utils/cliutils/__pycache__/set_version.cpython-311.pyc new file mode 100644 index 0000000..249b060 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/utils/cliutils/__pycache__/set_version.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/utils/cliutils/archive_viewer.py b/venv/Lib/site-packages/PyInstaller/utils/cliutils/archive_viewer.py new file mode 100644 index 0000000..912c901 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/utils/cliutils/archive_viewer.py @@ -0,0 +1,268 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- +""" +Viewer for PyInstaller-generated archives. +""" + +import argparse +import os +import sys + +import PyInstaller.log +from PyInstaller.archive.readers import CArchiveReader, ZlibArchiveReader + +try: + from argcomplete import autocomplete +except ImportError: + + def autocomplete(parser): + return None + + +class ArchiveViewer: + def __init__(self, filename, interactive_mode, recursive_mode, brief_mode): + self.filename = filename + self.interactive_mode = interactive_mode + self.recursive_mode = recursive_mode + self.brief_mode = brief_mode + + self.stack = [] + + # Recursive mode implies non-interactive mode + if self.recursive_mode: + self.interactive_mode = False + + def main(self): + # Open top-level (initial) archive + archive = self._open_toplevel_archive(self.filename) + archive_name = os.path.basename(self.filename) + self.stack.append((archive_name, archive)) + + # Not-interactive mode + if not self.interactive_mode: + return self._non_interactive_processing() + + # Interactive mode; show top-level archive + self._show_archive_contents(archive_name, archive) + + # Interactive command processing + while True: + # Read command + try: + tokens = input('? ').split(None, 1) + except EOFError: + # Ctrl-D + print(file=sys.stderr) # Clear line. + break + + # Print usage? + if not tokens: + self._print_usage() + continue + + # Process + command = tokens[0].upper() + if command == 'Q': + break + elif command == 'U': + self._move_up_the_stack() + elif command == 'O': + self._open_embedded_archive(*tokens[1:]) + elif command == 'X': + self._extract_file(*tokens[1:]) + elif command == 'S': + archive_name, archive = self.stack[-1] + self._show_archive_contents(archive_name, archive) + else: + self._print_usage() + + def _non_interactive_processing(self): + archive_count = 0 + + while self.stack: + archive_name, archive = self.stack.pop() + archive_count += 1 + + if archive_count > 1: + print("") + self._show_archive_contents(archive_name, archive) + + if not self.recursive_mode: + continue + + # Scan for embedded archives + if isinstance(archive, CArchiveReader): + for name, (*_, typecode) in archive.toc.items(): + if typecode == 'z': + try: + embedded_archive = archive.open_embedded_archive(name) + except Exception as e: + print(f"Could not open embedded archive {name!r}: {e}", file=sys.stderr) + self.stack.append((name, embedded_archive)) + + def _print_usage(self): + print("U: go up one level", file=sys.stderr) + print("O : open embedded archive with given name", file=sys.stderr) + print("X : extract file with given name", file=sys.stderr) + print("S: list the contents of current archive again", file=sys.stderr) + print("Q: quit", file=sys.stderr) + + def _move_up_the_stack(self): + if len(self.stack) > 1: + self.stack.pop() + archive_name, archive = self.stack[-1] + self._show_archive_contents(archive_name, archive) + else: + print("Already in the top archive!", file=sys.stderr) + + def _open_toplevel_archive(self, filename): + if not os.path.isfile(filename): + print(f"Archive {filename} does not exist!", file=sys.stderr) + sys.exit(1) + + if filename[-4:].lower() == '.pyz': + return ZlibArchiveReader(filename) + return CArchiveReader(filename) + + def _open_embedded_archive(self, archive_name=None): + # Ask for name if not provided + if not archive_name: + archive_name = input('Open name? ') + archive_name = archive_name.strip() + + # No name given; abort + if not archive_name: + return + + # Open the embedded archive + _, parent_archive = self.stack[-1] + + if not hasattr(parent_archive, 'open_embedded_archive'): + print("Archive does not support embedded archives!", file=sys.stderr) + return + + try: + archive = parent_archive.open_embedded_archive(archive_name) + except Exception as e: + print(f"Could not open embedded archive {archive_name!r}: {e}", file=sys.stderr) + return + + # Add to stack and display contents + self.stack.append((archive_name, archive)) + self._show_archive_contents(archive_name, archive) + + def _extract_file(self, name=None): + # Ask for name if not provided + if not name: + name = input('Extract name? ') + name = name.strip() + + # Archive + archive_name, archive = self.stack[-1] + + # Retrieve data + try: + if isinstance(archive, CArchiveReader): + data = archive.extract(name) + elif isinstance(archive, ZlibArchiveReader): + data = archive.extract(name, raw=True) + else: + raise NotImplementedError(f"Extraction from archive type {type(archive)} not implemented!") + except Exception as e: + print(f"Failed to extract data for entry {name!r} from {archive_name!r}: {e}", file=sys.stderr) + + # Write to file + filename = input('Output filename? ') + if not filename: + print(repr(data)) + else: + with open(filename, 'wb') as fp: + fp.write(data) + + def _show_archive_contents(self, archive_name, archive): + if isinstance(archive, CArchiveReader): + if archive.options: + print(f"Options in {archive_name!r} (PKG/CArchive):") + for option in archive.options: + print(f" {option}") + print(f"Contents of {archive_name!r} (PKG/CArchive):") + if self.brief_mode: + for name in archive.toc.keys(): + print(f" {name}") + else: + print(" position, length, uncompressed_length, is_compressed, typecode, name") + for name, (position, length, uncompressed_length, is_compressed, typecode) in archive.toc.items(): + print(f" {position}, {length}, {uncompressed_length}, {is_compressed}, {typecode!r}, {name!r}") + elif isinstance(archive, ZlibArchiveReader): + print(f"Contents of {archive_name!r} (PYZ):") + if self.brief_mode: + for name in archive.toc.keys(): + print(f" {name}") + else: + print(" typecode, position, length, name") + for name, (typecode, position, length) in archive.toc.items(): + print(f" {typecode}, {position}, {length}, {name!r}") + else: + print(f"Contents of {name} (unknown)") + print(f"FIXME: implement content listing for archive type {type(archive)}!") + + +def run(): + parser = argparse.ArgumentParser() + parser.add_argument( + '-l', + '--list', + default=False, + action='store_true', + dest='listing_mode', + help='List the archive contents and exit (default: %(default)s).', + ) + parser.add_argument( + '-r', + '--recursive', + default=False, + action='store_true', + dest='recursive', + help='Recursively print an archive log (default: %(default)s). Implies --list.', + ) + parser.add_argument( + '-b', + '--brief', + default=False, + action='store_true', + dest='brief', + help='When displaying archive contents, show only file names. (default: %(default)s).', + ) + PyInstaller.log.__add_options(parser) + parser.add_argument( + 'filename', + metavar='pyi_archive', + help="PyInstaller archive to process.", + ) + + autocomplete(parser) + args = parser.parse_args() + PyInstaller.log.__process_options(parser, args) + + try: + viewer = ArchiveViewer( + filename=args.filename, + interactive_mode=not args.listing_mode, + recursive_mode=args.recursive, + brief_mode=args.brief, + ) + viewer.main() + except KeyboardInterrupt: + raise SystemExit("Aborted by user.") + + +if __name__ == '__main__': + run() diff --git a/venv/Lib/site-packages/PyInstaller/utils/cliutils/bindepend.py b/venv/Lib/site-packages/PyInstaller/utils/cliutils/bindepend.py new file mode 100644 index 0000000..ebd5fdf --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/utils/cliutils/bindepend.py @@ -0,0 +1,58 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- +""" +Show dll dependencies of executable files or other dynamic libraries. +""" + +import argparse +import glob + +import PyInstaller.depend.bindepend +import PyInstaller.log + +try: + from argcomplete import autocomplete +except ImportError: + + def autocomplete(parser): + return None + + +def run(): + parser = argparse.ArgumentParser() + PyInstaller.log.__add_options(parser) + parser.add_argument( + 'filenames', + nargs='+', + metavar='executable-or-dynamic-library', + help="executables or dynamic libraries for which the dependencies should be shown", + ) + + autocomplete(parser) + args = parser.parse_args() + PyInstaller.log.__process_options(parser, args) + + # Suppress all informative messages from the dependency code. + PyInstaller.log.getLogger('PyInstaller.build.bindepend').setLevel(PyInstaller.log.WARN) + + try: + for input_filename_or_pattern in args.filenames: + for filename in glob.glob(input_filename_or_pattern): + print(f"{filename}:") + for lib_name, lib_path in sorted(PyInstaller.depend.bindepend.get_imports(filename)): + print(f" {lib_name} => {lib_path}") + print("") + except KeyboardInterrupt: + raise SystemExit("Aborted by user request.") + + +if __name__ == '__main__': + run() diff --git a/venv/Lib/site-packages/PyInstaller/utils/cliutils/grab_version.py b/venv/Lib/site-packages/PyInstaller/utils/cliutils/grab_version.py new file mode 100644 index 0000000..284cdd1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/utils/cliutils/grab_version.py @@ -0,0 +1,59 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +import argparse +import codecs + +try: + from argcomplete import autocomplete +except ImportError: + + def autocomplete(parser): + return None + + +def run(): + parser = argparse.ArgumentParser( + epilog=( + 'The printed output may be saved to a file, edited and used as the input for a version resource on any of ' + 'the executable targets in a PyInstaller .spec file.' + ) + ) + parser.add_argument( + 'exe_file', + metavar='exe-file', + help="full pathname of a Windows executable", + ) + parser.add_argument( + 'out_filename', + metavar='out-filename', + nargs='?', + default='file_version_info.txt', + help="filename where the grabbed version info will be saved", + ) + + autocomplete(parser) + args = parser.parse_args() + + try: + from PyInstaller.utils.win32 import versioninfo + info = versioninfo.read_version_info_from_executable(args.exe_file) + if not info: + raise SystemExit("Error: VersionInfo resource not found in exe") + with codecs.open(args.out_filename, 'w', 'utf-8') as fp: + fp.write(str(info)) + print(f"Version info written to: {args.out_filename!r}") + except KeyboardInterrupt: + raise SystemExit("Aborted by user request.") + + +if __name__ == '__main__': + run() diff --git a/venv/Lib/site-packages/PyInstaller/utils/cliutils/makespec.py b/venv/Lib/site-packages/PyInstaller/utils/cliutils/makespec.py new file mode 100644 index 0000000..6225759 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/utils/cliutils/makespec.py @@ -0,0 +1,61 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- +""" +Automatically build a spec file containing the description of the project. +""" + +import argparse +import os + +import PyInstaller.building.makespec +import PyInstaller.log + +try: + from argcomplete import autocomplete +except ImportError: + + def autocomplete(parser): + return None + + +def generate_parser(): + p = argparse.ArgumentParser() + PyInstaller.building.makespec.__add_options(p) + PyInstaller.log.__add_options(p) + p.add_argument( + 'scriptname', + nargs='+', + ) + return p + + +def run(): + p = generate_parser() + autocomplete(p) + args = p.parse_args() + PyInstaller.log.__process_options(p, args) + + # Split pathex by using the path separator. + temppaths = args.pathex[:] + args.pathex = [] + for p in temppaths: + args.pathex.extend(p.split(os.pathsep)) + + try: + name = PyInstaller.building.makespec.main(args.scriptname, **vars(args)) + print('Wrote %s.' % name) + print('Now run pyinstaller.py to build the executable.') + except KeyboardInterrupt: + raise SystemExit("Aborted by user request.") + + +if __name__ == '__main__': + run() diff --git a/venv/Lib/site-packages/PyInstaller/utils/cliutils/set_version.py b/venv/Lib/site-packages/PyInstaller/utils/cliutils/set_version.py new file mode 100644 index 0000000..b936692 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/utils/cliutils/set_version.py @@ -0,0 +1,51 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +import argparse +import os + +try: + from argcomplete import autocomplete +except ImportError: + + def autocomplete(parser): + return None + + +def run(): + parser = argparse.ArgumentParser() + parser.add_argument( + 'info_file', + metavar='info-file', + help="text file containing version info", + ) + parser.add_argument( + 'exe_file', + metavar='exe-file', + help="full pathname of a Windows executable", + ) + autocomplete(parser) + args = parser.parse_args() + + info_file = os.path.abspath(args.info_file) + exe_file = os.path.abspath(args.exe_file) + + try: + from PyInstaller.utils.win32 import versioninfo + info = versioninfo.load_version_info_from_text_file(info_file) + versioninfo.write_version_info_to_executable(exe_file, info) + print(f"Version info written to: {exe_file!r}") + except KeyboardInterrupt: + raise SystemExit("Aborted by user request.") + + +if __name__ == '__main__': + run() diff --git a/venv/Lib/site-packages/PyInstaller/utils/conftest.py b/venv/Lib/site-packages/PyInstaller/utils/conftest.py new file mode 100644 index 0000000..f1c7387 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/utils/conftest.py @@ -0,0 +1,587 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +import copy +import glob +import logging +import os +import platform +import re +import shutil +import subprocess +from contextlib import suppress + +# Set a handler for the root-logger to inhibit 'basicConfig()' (called in PyInstaller.log) is setting up a stream +# handler writing to stderr. This avoids log messages to be written (and captured) twice: once on stderr and +# once by pytests's caplog. +logging.getLogger().addHandler(logging.NullHandler()) + +# Manages subprocess timeout. +import psutil # noqa: E402 +import py # noqa: E402 +import pytest # noqa: E402 +import sys # noqa: E402 + +# Expand sys.path with PyInstaller source. +_ROOT_DIR = os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '..')) +sys.path.append(_ROOT_DIR) + +from PyInstaller import __main__ as pyi_main # noqa: E402 +from PyInstaller import configure # noqa: E402 +from PyInstaller.compat import architecture, is_darwin, is_win # noqa: E402 +from PyInstaller.depend.analysis import initialize_modgraph # noqa: E402 +from PyInstaller.archive.readers import pkg_archive_contents # noqa: E402 +from PyInstaller.utils.tests import gen_sourcefile # noqa: E402 +from PyInstaller.utils.win32 import winutils # noqa: E402 + +# Timeout for running the executable. If executable does not exit in this time, it is interpreted as a test failure. +_EXE_TIMEOUT = 3 * 60 # In sec. +# All currently supported platforms +SUPPORTED_OSES = {"darwin", "linux", "win32"} +# Have pyi_builder fixure clean-up the temporary directories of successful tests. Controlled by environment variable. +_PYI_BUILDER_CLEANUP = os.environ.get("PYI_BUILDER_CLEANUP", "1") == "1" + +# Fixtures +# -------- + + +@pytest.fixture +def SPEC_DIR(request): + """ + Return the directory where the test spec-files reside. + """ + return py.path.local(_get_spec_dir(request)) + + +@pytest.fixture +def SCRIPT_DIR(request): + """ + Return the directory where the test scripts reside. + """ + return py.path.local(_get_script_dir(request)) + + +def pytest_runtest_setup(item): + """ + Markers to skip tests based on the current platform. + https://pytest.org/en/stable/example/markers.html#marking-platform-specific-tests-with-pytest + + Available markers: see setup.cfg [tool:pytest] markers + - @pytest.mark.darwin (macOS) + - @pytest.mark.linux (GNU/Linux) + - @pytest.mark.win32 (Windows) + """ + supported_platforms = SUPPORTED_OSES.intersection(mark.name for mark in item.iter_markers()) + plat = sys.platform + if supported_platforms and plat not in supported_platforms: + pytest.skip("does not run on %s" % plat) + + +@pytest.hookimpl(tryfirst=True, hookwrapper=True) +def pytest_runtest_makereport(item, call): + # Execute all other hooks to obtain the report object. + outcome = yield + rep = outcome.get_result() + + # Set a report attribute for each phase of a call, which can be "setup", "call", "teardown". + setattr(item, "rep_" + rep.when, rep) + + +# Return the base directory which contains the current test module. +def _get_base_dir(request): + return os.path.dirname(os.path.abspath(request.fspath.strpath)) + + +# Directory with Python scripts for functional tests. +def _get_script_dir(request): + return os.path.join(_get_base_dir(request), 'scripts') + + +# Directory with testing modules used in some tests. +def _get_modules_dir(request): + return os.path.join(_get_base_dir(request), 'modules') + + +# Directory with .toc log files. +def _get_logs_dir(request): + return os.path.join(_get_base_dir(request), 'logs') + + +# Return the directory where data for tests is located. +def _get_data_dir(request): + return os.path.join(_get_base_dir(request), 'data') + + +# Directory with .spec files used in some tests. +def _get_spec_dir(request): + return os.path.join(_get_base_dir(request), 'specs') + + +@pytest.fixture +def script_dir(request): + return py.path.local(_get_script_dir(request)) + + +# A helper function to copy from data/dir to tmpdir/data. +def _data_dir_copy( + # The pytest request object. + request, + # The name of the subdirectory located in data/name to copy. + subdir_name, + # The tmpdir object for this test. See: https://pytest.org/latest/tmpdir.html. + tmpdir +): + + # Form the source and tmp paths. + source_data_dir = py.path.local(_get_data_dir(request)).join(subdir_name) + tmp_data_dir = tmpdir.join('data', subdir_name) + # Copy the data. + shutil.copytree(source_data_dir.strpath, tmp_data_dir.strpath) + # Return the temporary data directory, so that the copied data can now be used. + return tmp_data_dir + + +# Define a fixure for the DataDir object. +@pytest.fixture +def data_dir( + # The request object for this test. See + # https://pytest.org/latest/builtin.html#_pytest.python.FixtureRequest + # and + # https://pytest.org/latest/fixture.html#fixtures-can-introspect-the-requesting-test-context. + request, + # The tmpdir object for this test. See https://pytest.org/latest/tmpdir.html. + tmpdir +): + + # Strip the leading 'test_' from the test's name. + name = request.function.__name__[5:] + # Copy to tmpdir and return the path. + return _data_dir_copy(request, name, tmpdir) + + +class AppBuilder: + def __init__(self, tmpdir, request, bundle_mode): + self._tmpdir = tmpdir + self._request = request + self._mode = bundle_mode + self._specdir = str(tmpdir) + self._distdir = str(tmpdir / 'dist') + self._builddir = str(tmpdir / 'build') + self._is_spec = False + + def test_spec(self, specfile, *args, **kwargs): + """ + Test a Python script that is referenced in the supplied .spec file. + """ + __tracebackhide__ = True + specfile = os.path.join(_get_spec_dir(self._request), specfile) + # 'test_script' should handle .spec properly as script. + self._is_spec = True + return self.test_script(specfile, *args, **kwargs) + + def test_source(self, source, *args, **kwargs): + """ + Test a Python script given as source code. + + The source will be written into a file named like the test-function. This file will then be passed to + `test_script`. If you need other related file, e.g., as `.toc`-file for testing the content, put it at at the + normal place. Just mind to take the basnename from the test-function's name. + + :param script: Source code to create executable from. This will be saved into a temporary file which is then + passed on to `test_script`. + + :param test_id: Test-id for parametrized tests. If given, it will be appended to the script filename, separated + by two underscores. + + All other arguments are passed straight on to `test_script`. + + Ensure that the caller of `test_source` is in a UTF-8 encoded file with the correct '# -*- coding: utf-8 -*-' + marker. + + """ + __tracebackhide__ = True + # For parametrized test append the test-id. + scriptfile = gen_sourcefile(self._tmpdir, source, kwargs.setdefault('test_id')) + del kwargs['test_id'] + return self.test_script(str(scriptfile), *args, **kwargs) + + def test_script( + self, script, pyi_args=None, app_name=None, app_args=None, runtime=None, run_from_path=False, **kwargs + ): + """ + Main method to wrap all phases of testing a Python script. + + :param script: Name of script to create executable from. + :param pyi_args: Additional arguments to pass to PyInstaller when creating executable. + :param app_name: Name of the executable. This is equivalent to argument --name=APPNAME. + :param app_args: Additional arguments to pass to + :param runtime: Time in seconds how long to keep executable running. + :param toc_log: List of modules that are expected to be bundled with the executable. + """ + __tracebackhide__ = True + + def marker(line): + # Print some marker to stdout and stderr to make it easier to distinguish the phases in the CI test output. + print('-------', line, '-------') + print('-------', line, '-------', file=sys.stderr) + + if pyi_args is None: + pyi_args = [] + if app_args is None: + app_args = [] + + if app_name: + if not self._is_spec: + pyi_args.extend(['--name', app_name]) + else: + # Derive name from script name. + app_name = os.path.splitext(os.path.basename(script))[0] + + # Relative path means that a script from _script_dir is referenced. + if not os.path.isabs(script): + script = os.path.join(_get_script_dir(self._request), script) + self.script = script + assert os.path.exists(self.script), 'Script %s not found.' % script + + marker('Starting build.') + if not self._test_building(args=pyi_args): + pytest.fail('Building of %s failed.' % script) + + marker('Build finished, now running executable.') + self._test_executables(app_name, args=app_args, runtime=runtime, run_from_path=run_from_path, **kwargs) + marker('Running executable finished.') + + def _test_executables(self, name, args, runtime, run_from_path, **kwargs): + """ + Run created executable to make sure it works. + + Multipackage-tests generate more than one exe-file and all of them have to be run. + + :param args: CLI options to pass to the created executable. + :param runtime: Time in seconds how long to keep the executable running. + + :return: Exit code of the executable. + """ + __tracebackhide__ = True + exes = self._find_executables(name) + # Empty list means that PyInstaller probably failed to create any executable. + assert exes != [], 'No executable file was found.' + for exe in exes: + # Try to find .toc log file. .toc log file has the same basename as exe file. + toc_log = os.path.join(_get_logs_dir(self._request), os.path.splitext(os.path.basename(exe))[0] + '.toc') + if os.path.exists(toc_log): + if not self._examine_executable(exe, toc_log): + pytest.fail('Matching .toc of %s failed.' % exe) + retcode = self._run_executable(exe, args, run_from_path, runtime) + if retcode != kwargs.get('retcode', 0): + pytest.fail('Running exe %s failed with return-code %s.' % (exe, retcode)) + + def _find_executables(self, name): + """ + Search for all executables generated by the testcase. + + If the test-case is called e.g. 'test_multipackage1', this is searching for each of 'test_multipackage1.exe' + and 'multipackage1_?.exe' in both one-file- and one-dir-mode. + + :param name: Name of the executable to look for. + + :return: List of executables + """ + exes = [] + onedir_pt = os.path.join(self._distdir, name, name) + onefile_pt = os.path.join(self._distdir, name) + patterns = [ + onedir_pt, + onefile_pt, + # Multipackage one-dir + onedir_pt + '_?', + # Multipackage one-file + onefile_pt + '_?' + ] + # For Windows append .exe extension to patterns. + if is_win: + patterns = [pt + '.exe' for pt in patterns] + # For Mac OS append pattern for .app bundles. + if is_darwin: + # e.g: ./dist/name.app/Contents/MacOS/name + pt = os.path.join(self._distdir, name + '.app', 'Contents', 'MacOS', name) + patterns.append(pt) + # Apply file patterns. + for pattern in patterns: + for prog in glob.glob(pattern): + if os.path.isfile(prog): + exes.append(prog) + return exes + + def _run_executable(self, prog, args, run_from_path, runtime): + """ + Run executable created by PyInstaller. + + :param args: CLI options to pass to the created executable. + """ + # Run the test in a clean environment to make sure they're really self-contained. + prog_env = copy.deepcopy(os.environ) + prog_env['PATH'] = '' + del prog_env['PATH'] + # For Windows we need to keep minimal PATH for successful running of some tests. + if is_win: + # Minimum Windows PATH is in most cases: C:\Windows\system32;C:\Windows + prog_env['PATH'] = os.pathsep.join(winutils.get_system_path()) + # On macOS, we similarly set up minimal PATH with system directories, in case utilities from there are used by + # tested python code (for example, matplotlib >= 3.9.0 uses `system_profiler` that is found in /usr/sbin). + if is_darwin: + # The following paths are registered when application is launched via Finder, and are a subset of what is + # typically available in the shell. + prog_env['PATH'] = os.pathsep.join(['/usr/bin', '/bin', '/usr/sbin', '/sbin']) + + exe_path = prog + if run_from_path: + # Run executable in the temp directory. Add the directory containing the executable to $PATH. Basically, + # pretend we are a shell executing the program from $PATH. + prog_cwd = str(self._tmpdir) + prog_name = os.path.basename(prog) + prog_env['PATH'] = os.pathsep.join([prog_env.get('PATH', ''), os.path.dirname(prog)]) + + else: + # Run executable in the directory where it is. + prog_cwd = os.path.dirname(prog) + # The executable will be called with argv[0] as relative not absolute path. + prog_name = os.path.join(os.curdir, os.path.basename(prog)) + + args = [prog_name] + args + # Using sys.stdout/sys.stderr for subprocess fixes printing messages in Windows command prompt. Py.test is then + # able to collect stdout/sterr messages and display them if a test fails. + return self._run_executable_(args, exe_path, prog_env, prog_cwd, runtime) + + def _run_executable_(self, args, exe_path, prog_env, prog_cwd, runtime): + process = psutil.Popen( + args, executable=exe_path, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=prog_env, cwd=prog_cwd + ) + + def _msg(*text): + print('[' + str(process.pid) + '] ', *text) + + # Run executable. stderr is redirected to stdout. + _msg('RUNNING: ', repr(exe_path), ', args: ', repr(args)) + # 'psutil' allows to use timeout in waiting for a subprocess. If not timeout was specified then it is 'None' - + # no timeout, just waiting. Runtime is useful mostly for interactive tests. + try: + timeout = runtime if runtime else _EXE_TIMEOUT + stdout, stderr = process.communicate(timeout=timeout) + retcode = process.returncode + except (psutil.TimeoutExpired, subprocess.TimeoutExpired): + if runtime: + # When 'runtime' is set, the expired timeout is a good sign that the executable was running successfully + # for a specified time. + # TODO: is there a better way return success than 'retcode = 0'? + retcode = 0 + else: + # Exe is running and it is not interactive. Fail the test. + retcode = 1 + _msg(f'TIMED OUT while running executable (timeout: {timeout} sec)!') + # Kill the subprocess and its child processes. + for p in list(process.children(recursive=True)) + [process]: + with suppress(psutil.NoSuchProcess): + p.kill() + stdout, stderr = process.communicate() + + sys.stdout.buffer.write(stdout) + sys.stderr.buffer.write(stderr) + + return retcode + + def _test_building(self, args): + """ + Run building of test script. + + :param args: additional CLI options for PyInstaller. + + Return True if build succeeded False otherwise. + """ + if self._is_spec: + default_args = [ + '--distpath', self._distdir, + '--workpath', self._builddir, + '--log-level=INFO', + ] # yapf: disable + else: + default_args = [ + '--debug=bootloader', + '--noupx', + '--specpath', self._specdir, + '--distpath', self._distdir, + '--workpath', self._builddir, + '--path', _get_modules_dir(self._request), + '--log-level=INFO', + ] # yapf: disable + + # Choose bundle mode. + if self._mode == 'onedir': + default_args.append('--onedir') + elif self._mode == 'onefile': + default_args.append('--onefile') + # if self._mode is None then just the spec file was supplied. + + pyi_args = [self.script] + default_args + args + # TODO: fix return code in running PyInstaller programmatically. + PYI_CONFIG = configure.get_config() + # Override CACHEDIR for PyInstaller and put it into self.tmpdir + PYI_CONFIG['cachedir'] = str(self._tmpdir) + + pyi_main.run(pyi_args, PYI_CONFIG) + retcode = 0 + + return retcode == 0 + + def _examine_executable(self, exe, toc_log): + """ + Compare log files (now used mostly by multipackage test_name). + + :return: True if .toc files match + """ + print('EXECUTING MATCHING:', toc_log) + fname_list = pkg_archive_contents(exe) + with open(toc_log, 'r', encoding='utf-8') as f: + pattern_list = eval(f.read()) + # Alphabetical order of patterns. + pattern_list.sort() + missing = [] + for pattern in pattern_list: + for fname in fname_list: + if re.match(pattern, fname): + print('MATCH:', pattern, '-->', fname) + break + else: + # No matching entry found + missing.append(pattern) + print('MISSING:', pattern) + + # Not all modules matched. Stop comparing other .toc files and fail the test. + if missing: + for m in missing: + print('Missing', m, 'in', exe) + return False + # All patterns matched. + return True + + +# Scope 'session' should keep the object unchanged for whole tests. This fixture caches basic module graph dependencies +# that are same for every executable. +@pytest.fixture(scope='session') +def pyi_modgraph(): + # Explicitly set the log level since the plugin `pytest-catchlog` (un-) sets the root logger's level to NOTSET for + # the setup phase, which will lead to TRACE messages been written out. + import PyInstaller.log as logging + logging.logger.setLevel(logging.DEBUG) + initialize_modgraph() + + +# Run by default test as onedir and onefile. +@pytest.fixture(params=['onedir', 'onefile']) +def pyi_builder(tmpdir, monkeypatch, request, pyi_modgraph): + # Save/restore environment variable PATH. + monkeypatch.setenv('PATH', os.environ['PATH']) + # PyInstaller or a test case might manipulate 'sys.path'. Reset it for every test. + monkeypatch.syspath_prepend(None) + # Set current working directory to + monkeypatch.chdir(tmpdir) + # Clean up configuration and force PyInstaller to do a clean configuration for another app/test. The value is same + # as the original value. + monkeypatch.setattr('PyInstaller.config.CONF', {'pathex': []}) + + yield AppBuilder(tmpdir, request, request.param) + + # Clean up the temporary directory of a successful test + if _PYI_BUILDER_CLEANUP and request.node.rep_setup.passed and request.node.rep_call.passed: + if tmpdir.exists(): + tmpdir.remove(rec=1, ignore_errors=True) + + +# Fixture for .spec based tests. With .spec it does not make sense to differentiate onefile/onedir mode. +@pytest.fixture +def pyi_builder_spec(tmpdir, request, monkeypatch, pyi_modgraph): + # Save/restore environment variable PATH. + monkeypatch.setenv('PATH', os.environ['PATH']) + # Set current working directory to + monkeypatch.chdir(tmpdir) + # PyInstaller or a test case might manipulate 'sys.path'. Reset it for every test. + monkeypatch.syspath_prepend(None) + # Clean up configuration and force PyInstaller to do a clean configuration for another app/test. The value is same + # as the original value. + monkeypatch.setattr('PyInstaller.config.CONF', {'pathex': []}) + + yield AppBuilder(tmpdir, request, None) + + # Clean up the temporary directory of a successful test + if _PYI_BUILDER_CLEANUP and request.node.rep_setup.passed and request.node.rep_call.passed: + if tmpdir.exists(): + tmpdir.remove(rec=1, ignore_errors=True) + + +# Define a fixture which compiles the data/load_dll_using_ctypes/ctypes_dylib.c program in the tmpdir, returning the +# tmpdir object. +@pytest.fixture() +def compiled_dylib(tmpdir, request): + tmp_data_dir = _data_dir_copy(request, 'ctypes_dylib', tmpdir) + + # Compile the ctypes_dylib in the tmpdir: Make tmpdir/data the CWD. Do NOT use monkeypatch.chdir() to change and + # monkeypatch.undo() to restore the CWD, since this will undo ALL monkeypatches (such as the pyi_builder's additions + # to sys.path), breaking the test. + old_wd = tmp_data_dir.chdir() + try: + if is_win: + tmp_data_dir = tmp_data_dir.join('ctypes_dylib.dll') + # For Mingw-x64 we must pass '-m32' to build 32-bit binaries + march = '-m32' if architecture == '32bit' else '-m64' + ret = subprocess.call('gcc -shared ' + march + ' ctypes_dylib.c -o ctypes_dylib.dll', shell=True) + if ret != 0: + # Find path to cl.exe file. + from distutils.msvccompiler import MSVCCompiler + comp = MSVCCompiler() + comp.initialize() + cl_path = comp.cc + # Fallback to msvc. + ret = subprocess.call([cl_path, '/LD', 'ctypes_dylib.c'], shell=False) + elif is_darwin: + tmp_data_dir = tmp_data_dir.join('ctypes_dylib.dylib') + # On Mac OS X we need to detect architecture - 32 bit or 64 bit. + arch = 'arm64' if platform.machine() == 'arm64' else 'i386' if architecture == '32bit' else 'x86_64' + cmd = ( + 'gcc -arch ' + arch + ' -Wall -dynamiclib ' + 'ctypes_dylib.c -o ctypes_dylib.dylib -headerpad_max_install_names' + ) + ret = subprocess.call(cmd, shell=True) + id_dylib = os.path.abspath('ctypes_dylib.dylib') + ret = subprocess.call('install_name_tool -id %s ctypes_dylib.dylib' % (id_dylib,), shell=True) + else: + tmp_data_dir = tmp_data_dir.join('ctypes_dylib.so') + ret = subprocess.call('gcc -fPIC -shared ctypes_dylib.c -o ctypes_dylib.so', shell=True) + assert ret == 0, 'Compile ctypes_dylib failed.' + finally: + # Reset the CWD directory. + old_wd.chdir() + + return tmp_data_dir + + +@pytest.fixture +def pyi_windowed_builder(pyi_builder: AppBuilder): + """A pyi_builder equivalent for testing --windowed applications.""" + + # psutil.Popen() somehow bypasses an application's windowed/console mode so that any application built in + # --windowed mode but invoked with psutil still receives valid std{in,out,err} handles and behaves exactly like + # a console application. In short, testing windowed mode with psutil is a null test. We must instead use subprocess. + + def _run_executable_(args, exe_path, prog_env, prog_cwd, runtime): + return subprocess.run([exe_path, *args], env=prog_env, cwd=prog_cwd, timeout=runtime).returncode + + pyi_builder._run_executable_ = _run_executable_ + yield pyi_builder diff --git a/venv/Lib/site-packages/PyInstaller/utils/hooks/__init__.py b/venv/Lib/site-packages/PyInstaller/utils/hooks/__init__.py new file mode 100644 index 0000000..231f4e2 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/utils/hooks/__init__.py @@ -0,0 +1,1339 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +from __future__ import annotations + +import copy +import os +import subprocess +import textwrap +import fnmatch +from pathlib import Path +from collections import deque +from typing import Callable + +import packaging.requirements + +from PyInstaller import HOMEPATH, compat +from PyInstaller import log as logging +from PyInstaller.depend.imphookapi import PostGraphAPI +from PyInstaller import isolated +from PyInstaller.compat import importlib_metadata + +logger = logging.getLogger(__name__) + +# These extensions represent Python executables and should therefore be ignored when collecting data files. +# NOTE: .dylib files are not Python executable and should not be in this list. +PY_IGNORE_EXTENSIONS = set(compat.ALL_SUFFIXES) + +# Some hooks need to save some values. This is the dict that can be used for that. +# +# When running tests this variable should be reset before every test. +# +# For example the 'wx' module needs variable 'wxpubsub'. This tells PyInstaller which protocol of the wx module +# should be bundled. +hook_variables = {} + + +def __exec_python_cmd(cmd, env=None, capture_stdout=True): + """ + Executes an externally spawned Python interpreter. If capture_stdout is set to True, returns anything that was + emitted in the standard output as a single string. Otherwise, returns the exit code. + """ + # 'PyInstaller.config' cannot be imported as other top-level modules. + from PyInstaller.config import CONF + if env is None: + env = {} + # Update environment. Defaults to 'os.environ' + pp_env = copy.deepcopy(os.environ) + pp_env.update(env) + # Prepend PYTHONPATH with pathex. + # Some functions use some PyInstaller code in subprocess, so add PyInstaller HOMEPATH to sys.path as well. + pp = os.pathsep.join(CONF['pathex'] + [HOMEPATH]) + + # PYTHONPATH might be already defined in the 'env' argument or in the original 'os.environ'. Prepend it. + if 'PYTHONPATH' in pp_env: + pp = os.pathsep.join([pp_env.get('PYTHONPATH'), pp]) + pp_env['PYTHONPATH'] = pp + + if capture_stdout: + txt = compat.exec_python(*cmd, env=pp_env) + return txt.strip() + else: + return compat.exec_python_rc(*cmd, env=pp_env) + + +def __exec_statement(statement, capture_stdout=True): + statement = textwrap.dedent(statement) + cmd = ['-c', statement] + return __exec_python_cmd(cmd, capture_stdout=capture_stdout) + + +def exec_statement(statement: str): + """ + Execute a single Python statement in an externally-spawned interpreter, and return the resulting standard output + as a string. + + Examples:: + + tk_version = exec_statement("from _tkinter import TK_VERSION; print(TK_VERSION)") + + mpl_data_dir = exec_statement("import matplotlib; print(matplotlib.get_data_path())") + datas = [ (mpl_data_dir, "") ] + + Notes: + As of v5.0, usage of this function is discouraged in favour of the + new :mod:`PyInstaller.isolated` module. + + """ + return __exec_statement(statement, capture_stdout=True) + + +def exec_statement_rc(statement: str): + """ + Executes a Python statement in an externally spawned interpreter, and returns the exit code. + """ + return __exec_statement(statement, capture_stdout=False) + + +def eval_statement(statement: str): + """ + Execute a single Python statement in an externally-spawned interpreter, and :func:`eval` its output (if any). + + Example:: + + databases = eval_statement(''' + import sqlalchemy.databases + print(sqlalchemy.databases.__all__) + ''') + for db in databases: + hiddenimports.append("sqlalchemy.databases." + db) + + Notes: + As of v5.0, usage of this function is discouraged in favour of the + new :mod:`PyInstaller.isolated` module. + + """ + txt = exec_statement(statement).strip() + if not txt: + # Return an empty string, which is "not true" but is iterable. + return '' + return eval(txt) + + +@isolated.decorate +def get_pyextension_imports(module_name: str): + """ + Return list of modules required by binary (C/C++) Python extension. + + Python extension files ends with .so (Unix) or .pyd (Windows). It is almost impossible to analyze binary extension + and its dependencies. + + Module cannot be imported directly. + + Let's at least try import it in a subprocess and observe the difference in module list from sys.modules. + + This function could be used for 'hiddenimports' in PyInstaller hooks files. + """ + import sys + import importlib + + original = set(sys.modules.keys()) + + # When importing this module - sys.modules gets updated. + importlib.import_module(module_name) + + # Find and return which new modules have been loaded. + return list(set(sys.modules.keys()) - original - {module_name}) + + +def get_homebrew_path(formula: str = ''): + """ + Return the homebrew path to the requested formula, or the global prefix when called with no argument. + + Returns the path as a string or None if not found. + """ + import subprocess + brewcmd = ['brew', '--prefix'] + path = None + if formula: + brewcmd.append(formula) + dbgstr = 'homebrew formula "%s"' % formula + else: + dbgstr = 'homebrew prefix' + try: + path = subprocess.check_output(brewcmd).strip() + logger.debug('Found %s at "%s"' % (dbgstr, path)) + except OSError: + logger.debug('Detected homebrew not installed') + except subprocess.CalledProcessError: + logger.debug('homebrew formula "%s" not installed' % formula) + if path: + return path.decode('utf8') # Mac OS filenames are UTF-8 + else: + return None + + +def remove_prefix(string: str, prefix: str): + """ + This function removes the given prefix from a string, if the string does indeed begin with the prefix; otherwise, + it returns the original string. + """ + if string.startswith(prefix): + return string[len(prefix):] + else: + return string + + +def remove_suffix(string: str, suffix: str): + """ + This function removes the given suffix from a string, if the string does indeed end with the suffix; otherwise, + it returns the original string. + """ + # Special case: if suffix is empty, string[:0] returns ''. So, test for a non-empty suffix. + if suffix and string.endswith(suffix): + return string[:-len(suffix)] + else: + return string + + +# TODO: Do we really need a helper for this? This is pretty trivially obvious. +def remove_file_extension(filename: str): + """ + This function returns filename without its extension. + + For Python C modules it removes even whole '.cpython-34m.so' etc. + """ + for suff in compat.EXTENSION_SUFFIXES: + if filename.endswith(suff): + return filename[0:filename.rfind(suff)] + # Fallback to ordinary 'splitext'. + return os.path.splitext(filename)[0] + + +def can_import_module(module_name: str): + """ + Check if the specified module can be imported. + + Intended as a silent module availability check, as it does not print ModuleNotFoundError traceback to stderr when + the module is unavailable. + + Parameters + ---------- + module_name : str + Fully-qualified name of the module. + + Returns + ---------- + bool + Boolean indicating whether the module can be imported or not. + """ + + # Run the check in isolated sub-process, so we can gracefully handle cases when importing the module ends up + # crashing python interpreter. + @isolated.decorate + def _can_import_module(module_name): + try: + __import__(module_name) + return True + except Exception: + return False + + try: + return _can_import_module(module_name) + except isolated.SubprocessDiedError: + return False + + +# TODO: Replace most calls to exec_statement() with calls to this function. +def get_module_attribute(module_name: str, attr_name: str): + """ + Get the string value of the passed attribute from the passed module if this attribute is defined by this module + _or_ raise `AttributeError` otherwise. + + Since modules cannot be directly imported during analysis, this function spawns a subprocess importing this module + and returning the string value of this attribute in this module. + + Parameters + ---------- + module_name : str + Fully-qualified name of this module. + attr_name : str + Name of the attribute in this module to be retrieved. + + Returns + ---------- + str + String value of this attribute. + + Raises + ---------- + AttributeError + If this attribute is undefined. + """ + @isolated.decorate + def _get_module_attribute(module_name, attr_name): + import importlib + module = importlib.import_module(module_name) + return getattr(module, attr_name) + + # Return AttributeError on any kind of errors, to preserve old behavior. + try: + return _get_module_attribute(module_name, attr_name) + except Exception as e: + raise AttributeError(f"Failed to retrieve attribute {attr_name} from module {module_name}") from e + + +def get_module_file_attribute(package: str): + """ + Get the absolute path to the specified module or package. + + Modules and packages *must not* be directly imported in the main process during the analysis. Therefore, to + avoid leaking the imports, this function uses an isolated subprocess when it needs to import the module and + obtain its ``__file__`` attribute. + + Parameters + ---------- + package : str + Fully-qualified name of module or package. + + Returns + ---------- + str + Absolute path of this module. + """ + # First, try to use 'importlib.util.find_spec' and obtain loader from the spec (and filename from the loader). + # It is the fastest way, but does not work on certain modules in pywin32 that replace all module attributes with + # those of the .dll. In addition, we need to avoid it for submodules/subpackages, because it ends up importing + # their parent package, which would cause an import leak during the analysis. + filename: str | None = None + if '.' not in package: + try: + import importlib.util + loader = importlib.util.find_spec(package).loader + filename = loader.get_filename(package) + # Apparently in the past, ``None`` could be returned for built-in ``datetime`` module. Just in case this + # is still possible, return only if filename is valid. + if filename: + return filename + except (ImportError, AttributeError, TypeError, ValueError): + pass + + # Second attempt: try to obtain module/package's __file__ attribute in an isolated subprocess. + @isolated.decorate + def _get_module_file_attribute(package): + # First, try to use 'importlib.util.find_spec' and obtain loader from the spec (and filename from the loader). + # This should return the filename even if the module or package cannot be imported (e.g., a C-extension module + # with missing dependencies). + try: + import importlib.util + loader = importlib.util.find_spec(package).loader + filename = loader.get_filename(package) + # Safe-guard against ``None`` being returned (see comment in the non-isolated codepath). + if filename: + return filename + except (ImportError, AttributeError, TypeError, ValueError): + pass + + # Fall back to import attempt + import importlib + p = importlib.import_module(package) + return p.__file__ + + # The old behavior was to return ImportError (and that is what the test are also expecting...). + try: + filename = _get_module_file_attribute(package) + except Exception as e: + raise ImportError(f"Failed to obtain the __file__ attribute of package/module {package}!") from e + + return filename + + +def get_pywin32_module_file_attribute(module_name): + """ + Get the absolute path of the PyWin32 DLL specific to the PyWin32 module with the passed name (`pythoncom` + or `pywintypes`). + + On import, each PyWin32 module: + + * Imports a DLL specific to that module. + * Overwrites the values of all module attributes with values specific to that DLL. This includes that module's + `__file__` attribute, which then provides the absolute path of that DLL. + + This function imports the module in isolated subprocess and retrieves its `__file__` attribute. + """ + + # NOTE: we cannot use `get_module_file_attribute` as it does not account for the __file__ rewriting magic + # done by the module. Use `get_module_attribute` instead. + return get_module_attribute(module_name, '__file__') + + +def check_requirement(requirement: str): + """ + Check if a :pep:`0508` requirement is satisfied. Usually used to check if a package distribution is installed, + or if it is installed and satisfies the specified version requirement. + + Parameters + ---------- + requirement : str + Requirement string in :pep:`0508` format. + + Returns + ---------- + bool + Boolean indicating whether the requirement is satisfied or not. + + Examples + -------- + + :: + + # Assume Pillow 10.0.0 is installed. + >>> from PyInstaller.utils.hooks import check_requirement + >>> check_requirement('Pillow') + True + >>> check_requirement('Pillow < 9.0') + False + >>> check_requirement('Pillow >= 9.0, < 11.0') + True + """ + parsed_requirement = packaging.requirements.Requirement(requirement) + + # Fetch the actual version of the specified dist + try: + version = importlib_metadata.version(parsed_requirement.name) + except importlib_metadata.PackageNotFoundError: + return False # Not available at all + + # If specifier is not given, the only requirement is that dist is available + if not parsed_requirement.specifier: + return True + + # Parse specifier, and compare version. Enable pre-release matching, + # because we need "package >= 2.0.0" to match "2.5.0b1". + return parsed_requirement.specifier.contains(version, prereleases=True) + + +# Keep the `is_module_satisfies` as an alias for backwards compatibility with existing hooks. The old fallback +# to module version check does not work any more, though. +def is_module_satisfies( + requirements: str, + version: None = None, + version_attr: None = None, +): + """ + A compatibility wrapper for :func:`check_requirement`, intended for backwards compatibility with existing hooks. + + In contrast to original implementation from PyInstaller < 6, this implementation only checks the specified + :pep:`0508` requirement string; i.e., it tries to retrieve the distribution metadata, and compare its version + against optional version specifier(s). It does not attempt to fall back to checking the module's version attribute, + nor does it support ``version`` and ``version_attr`` arguments. + + Parameters + ---------- + requirements : str + Requirements string passed to the :func:`check_requirement`. + version : None + Deprecated and unsupported. Must be ``None``. + version_attr : None + Deprecated and unsupported. Must be ``None``. + + Returns + ---------- + bool + Boolean indicating whether the requirement is satisfied or not. + + Raises + ---------- + ValueError + If either ``version`` or ``version_attr`` are specified and are not None. + """ + if version is not None: + raise ValueError("Calling is_module_satisfies with version argument is not supported anymore.") + if version_attr is not None: + raise ValueError("Calling is_module_satisfies with version argument_attr is not supported anymore.") + return check_requirement(requirements) + + +def is_package(module_name: str): + """ + Check if a Python module is really a module or is a package containing other modules, without importing anything + in the main process. + + :param module_name: Module name to check. + :return: True if module is a package else otherwise. + """ + def _is_package(module_name: str): + """ + Determines whether the given name represents a package or not. If the name represents a top-level module or + a package, it is not imported. If the name represents a sub-module or a sub-package, its parent is imported. + In such cases, this function should be called from an isolated suprocess. + + NOTE: the fallback check for `__init__.py` is there because `_distutils_hack.DistutilsMetaFinder` from + `setuptools` does not set spec.submodule_search_locations for `distutils` / `setuptools._distutils` even though + it is a package. The alternative would be to always perform full import, and check for the `__path__` attribute, + but that would also always require full isolation. + """ + try: + import importlib.util + spec = importlib.util.find_spec(module_name) + return bool(spec.submodule_search_locations) or spec.origin.endswith('__init__.py') + except Exception: + return False + + # For top-level packages/modules, we can perform check in the main process; otherwise, we need to isolate the + # call to prevent import leaks in the main process. + if '.' not in module_name: + return _is_package(module_name) + else: + return isolated.call(_is_package, module_name) + + +def get_all_package_paths(package: str): + """ + Given a package name, return all paths associated with the package. Typically, packages have a single location + path, but PEP 420 namespace packages may be split across multiple locations. Returns an empty list if the specified + package is not found or is not a package. + """ + def _get_package_paths(package: str): + """ + Retrieve package path(s), as advertised by submodule_search_paths attribute of the spec obtained via + importlib.util.find_spec(package). If the name represents a top-level package, the package is not imported. + If the name represents a sub-module or a sub-package, its parent is imported. In such cases, this function + should be called from an isolated suprocess. Returns an empty list if specified package is not found or is not + a package. + """ + try: + import importlib.util + spec = importlib.util.find_spec(package) + if not spec or not spec.submodule_search_locations: + return [] + return [str(path) for path in spec.submodule_search_locations] + except Exception: + return [] + + # For top-level packages/modules, we can perform check in the main process; otherwise, we need to isolate the + # call to prevent import leaks in the main process. + if '.' not in package: + pkg_paths = _get_package_paths(package) + else: + pkg_paths = isolated.call(_get_package_paths, package) + + return pkg_paths + + +def package_base_path(package_path: str, package: str): + """ + Given a package location path and package name, return the package base path, i.e., the directory in which the + top-level package is located. For example, given the path ``/abs/path/to/python/libs/pkg/subpkg`` and + package name ``pkg.subpkg``, the function returns ``/abs/path/to/python/libs``. + """ + return remove_suffix(package_path, package.replace('.', os.sep)) # Base directory + + +def get_package_paths(package: str): + """ + Given a package, return the path to packages stored on this machine and also returns the path to this particular + package. For example, if pkg.subpkg lives in /abs/path/to/python/libs, then this function returns + ``(/abs/path/to/python/libs, /abs/path/to/python/libs/pkg/subpkg)``. + + NOTE: due to backwards compatibility, this function returns only one package path along with its base directory. + In case of PEP 420 namespace package with multiple location, only first location is returned. To obtain all + package paths, use the ``get_all_package_paths`` function and obtain corresponding base directories using the + ``package_base_path`` helper. + """ + pkg_paths = get_all_package_paths(package) + if not pkg_paths: + raise ValueError(f"Package '{package}' does not exist or is not a package!") + + if len(pkg_paths) > 1: + logger.warning( + "get_package_paths - package %s has multiple paths (%r); returning only first one!", package, pkg_paths + ) + + pkg_dir = pkg_paths[0] + pkg_base = package_base_path(pkg_dir, package) + + return pkg_base, pkg_dir + + +def collect_submodules( + package: str, + filter: Callable[[str], bool] = lambda name: True, + on_error: str = "warn once", +): + """ + List all submodules of a given package. + + Arguments: + package: + An ``import``-able package. + filter: + Filter the submodules found: A callable that takes a submodule name and returns True if it should be + included. + on_error: + The action to take when a submodule fails to import. May be any of: + + - raise: Errors are reraised and terminate the build. + - warn: Errors are downgraded to warnings. + - warn once: The first error issues a warning but all + subsequent errors are ignored to minimise *stderr pollution*. This + is the default. + - ignore: Skip all errors. Don't warn about anything. + Returns: + All submodules to be assigned to ``hiddenimports`` in a hook. + + This function is intended to be used by hook scripts, not by main PyInstaller code. + + Examples:: + + # Collect all submodules of Sphinx don't contain the word ``test``. + hiddenimports = collect_submodules( + "Sphinx", ``filter=lambda name: 'test' not in name) + + .. versionchanged:: 4.5 + Add the **on_error** parameter. + + """ + # Accept only strings as packages. + if not isinstance(package, str): + raise TypeError('package must be a str') + if on_error not in ("ignore", "warn once", "warn", "raise"): + raise ValueError( + f"Invalid on-error action '{on_error}': Must be one of ('ignore', 'warn once', 'warn', 'raise')" + ) + + logger.debug('Collecting submodules for %s', package) + + # Skip a module which is not a package. + if not is_package(package): + logger.debug('collect_submodules - %s is not a package.', package) + # If module is importable, return its name in the list, in order to keep behavior consistent with the + # one we have for packages (i.e., we include the package in the list of returned names) + if can_import_module(package): + return [package] + return [] + + # Determine the filesystem path(s) to the specified package. + package_submodules = [] + + todo = deque() + todo.append(package) + + with isolated.Python() as isolated_python: + while todo: + # Scan the given (sub)package + name = todo.pop() + modules, subpackages, on_error = isolated_python.call(_collect_submodules, name, on_error) + + # Add modules to the list of all submodules + package_submodules += [module for module in modules if filter(module)] + + # Add sub-packages to deque for subsequent recursion + for subpackage_name in subpackages: + if filter(subpackage_name): + todo.append(subpackage_name) + + package_submodules = sorted(package_submodules) + + logger.debug("collect_submodules - found submodules: %s", package_submodules) + return package_submodules + + +# This function is called in an isolated sub-process via `isolated.Python.call`. +def _collect_submodules(name, on_error): + import sys + import pkgutil + from traceback import format_exception_only + + from PyInstaller.utils.hooks import logger + + logger.debug("collect_submodules - scanning (sub)package %s", name) + + modules = [] + subpackages = [] + + # Resolve package location(s) + try: + __import__(name) + except Exception as ex: + # Catch all errors and either raise, warn, or ignore them as determined by the *on_error* parameter. + if on_error in ("warn", "warn once"): + from PyInstaller.log import logger + ex = "".join(format_exception_only(type(ex), ex)).strip() + logger.warning(f"Failed to collect submodules for '{name}' because importing '{name}' raised: {ex}") + if on_error == "warn once": + on_error = "ignore" + return modules, subpackages, on_error + elif on_error == "raise": + raise ImportError(f"Unable to load subpackage '{name}'.") from ex + + # Do not attempt to recurse into package if it did not make it into sys.modules. + if name not in sys.modules: + return modules, subpackages, on_error + + # Or if it does not have __path__ attribute. + paths = getattr(sys.modules[name], '__path__', None) or [] + if not paths: + return modules, subpackages, on_error + + # Package was successfully imported - include it in the list of modules. + modules.append(name) + + # Iterate package contents + logger.debug("collect_submodules - scanning (sub)package %s in location(s): %s", name, paths) + for importer, name, ispkg in pkgutil.iter_modules(paths, name + '.'): + if not ispkg: + modules.append(name) + else: + subpackages.append(name) + + return modules, subpackages, on_error + + +def is_module_or_submodule(name: str, mod_or_submod: str): + """ + This helper function is designed for use in the ``filter`` argument of :func:`collect_submodules`, by returning + ``True`` if the given ``name`` is a module or a submodule of ``mod_or_submod``. + + Examples: + + The following excludes ``foo.test`` and ``foo.test.one`` but not ``foo.testifier``. :: + + collect_submodules('foo', lambda name: not is_module_or_submodule(name, 'foo.test'))`` + """ + return name.startswith(mod_or_submod + '.') or name == mod_or_submod + + +# Patterns of dynamic library filenames that might be bundled with some installed Python packages. +PY_DYLIB_PATTERNS = [ + '*.dll', + '*.dylib', + 'lib*.so', +] + + +def collect_dynamic_libs(package: str, destdir: str | None = None, search_patterns: list = PY_DYLIB_PATTERNS): + """ + This function produces a list of (source, dest) of dynamic library files that reside in package. Its output can be + directly assigned to ``binaries`` in a hook script. The package parameter must be a string which names the package. + + :param destdir: Relative path to ./dist/APPNAME where the libraries should be put. + :param search_patterns: List of dynamic library filename patterns to collect. + """ + logger.debug('Collecting dynamic libraries for %s' % package) + + # Accept only strings as packages. + if not isinstance(package, str): + raise TypeError('package must be a str') + + # Skip a module which is not a package. + if not is_package(package): + logger.warning( + "collect_dynamic_libs - skipping library collection for module '%s' as it is not a package.", package + ) + return [] + + pkg_dirs = get_all_package_paths(package) + dylibs = [] + for pkg_dir in pkg_dirs: + pkg_base = package_base_path(pkg_dir, package) + # Recursively glob for all file patterns in the package directory + for pattern in search_patterns: + files = Path(pkg_dir).rglob(pattern) + for source in files: + # Produce the tuple ('/abs/path/to/source/mod/submod/file.pyd', 'mod/submod') + if destdir: + # Put libraries in the specified target directory. + dest = destdir + else: + # Preserve original directory hierarchy. + dest = source.parent.relative_to(pkg_base) + logger.debug(' %s, %s' % (source, dest)) + dylibs.append((str(source), str(dest))) + + return dylibs + + +def collect_data_files( + package: str, + include_py_files: bool = False, + subdir: str | os.PathLike | None = None, + excludes: list | None = None, + includes: list | None = None, +): + r""" + This function produces a list of ``(source, dest)`` entries for data files that reside in ``package``. + Its output can be directly assigned to ``datas`` in a hook script; for example, see ``hook-sphinx.py``. + The data files are all files that are not shared libraries / binary python extensions (based on extension + check) and are not python source (.py) files or byte-compiled modules (.pyc). Collection of the .py and .pyc + files can be toggled via the ``include_py_files`` flag. + Parameters: + + - The ``package`` parameter is a string which names the package. + - By default, python source files and byte-compiled modules (files with ``.py`` and ``.pyc`` suffix) are not + collected; setting the ``include_py_files`` argument to ``True`` collects these files as well. This is typically + used when a package requires source .py files to be available; for example, JIT compilation used in + deep-learning frameworks, code that requires access to .py files (for example, to check their date), or code + that tries to extend `sys.path` with subpackage paths in a way that is incompatible with PyInstaller's frozen + importer.. However, in contemporary PyInstaller versions, the preferred way of collecting source .py files is by + using the **module collection mode** setting (which enables collection of source .py files in addition to or + in lieu of collecting byte-compiled modules into PYZ archive). + - The ``subdir`` argument gives a subdirectory relative to ``package`` to search, which is helpful when submodules + are imported at run-time from a directory lacking ``__init__.py``. + - The ``excludes`` argument contains a sequence of strings or Paths. These provide a list of + `globs `_ + to exclude from the collected data files; if a directory matches the provided glob, all files it contains will + be excluded as well. All elements must be relative paths, which are relative to the provided package's path + (/ ``subdir`` if provided). + + Therefore, ``*.txt`` will exclude only ``.txt`` files in ``package``\ 's path, while ``**/*.txt`` will exclude + all ``.txt`` files in ``package``\ 's path and all its subdirectories. Likewise, ``**/__pycache__`` will exclude + all files contained in any subdirectory named ``__pycache__``. + - The ``includes`` function like ``excludes``, but only include matching paths. ``excludes`` override + ``includes``: a file or directory in both lists will be excluded. + + This function does not work on zipped Python eggs. + + This function is intended to be used by hook scripts, not by main PyInstaller code. + """ + logger.debug('Collecting data files for %s' % package) + + # Accept only strings as packages. + if not isinstance(package, str): + raise TypeError('package must be a str') + + # Skip a module which is not a package. + if not is_package(package): + logger.warning("collect_data_files - skipping data collection for module '%s' as it is not a package.", package) + return [] + + # Make sure the excludes are a list; this also makes a copy, so we don't modify the original. + excludes = list(excludes) if excludes else [] + # These excludes may contain directories which need to be searched. + excludes_len = len(excludes) + # Including py files means don't exclude them. This pattern will search any directories for containing files, so + # do not modify ``excludes_len``. + if not include_py_files: + excludes += ['**/*' + s for s in compat.ALL_SUFFIXES] + else: + # include_py_files should collect only .py and .pyc files, and not the extensions / shared libs. + excludes += ['**/*' + s for s in compat.ALL_SUFFIXES if s not in {'.py', '.pyc'}] + + # Never, ever, collect .pyc files from __pycache__. + excludes.append('**/__pycache__/*.pyc') + + # If not specified, include all files. Follow the same process as the excludes. + includes = list(includes) if includes else ["**/*"] + includes_len = len(includes) + + # A helper function to glob the in/ex "cludes", adding a wildcard to refer to all files under a subdirectory if a + # subdirectory is matched by the first ``clude_len`` patterns. Otherwise, it in/excludes the matched file. + # **This modifies** ``cludes``. + def clude_walker( + # Package directory to scan + pkg_dir, + # A list of paths relative to ``pkg_dir`` to in/exclude. + cludes, + # The number of ``cludes`` for which matching directories should be searched for all files under them. + clude_len, + # True if the list is includes, False for excludes. + is_include + ): + for i, c in enumerate(cludes): + for g in Path(pkg_dir).glob(c): + if g.is_dir(): + # Only files are sources. Subdirectories are not. + if i < clude_len: + # In/exclude all files under a matching subdirectory. + cludes.append(str((g / "**/*").relative_to(pkg_dir))) + else: + # In/exclude a matching file. + sources.add(g) if is_include else sources.discard(g) + + # Obtain all paths for the specified package, and process each path independently. + datas = [] + + pkg_dirs = get_all_package_paths(package) + for pkg_dir in pkg_dirs: + sources = set() # Reset sources set + + pkg_base = package_base_path(pkg_dir, package) + if subdir: + pkg_dir = os.path.join(pkg_dir, subdir) + + # Process the package path with clude walker + clude_walker(pkg_dir, includes, includes_len, True) + clude_walker(pkg_dir, excludes, excludes_len, False) + + # Transform the sources into tuples for ``datas``. + datas += [(str(s), str(s.parent.relative_to(pkg_base))) for s in sources] + + logger.debug("collect_data_files - Found files: %s", datas) + return datas + + +def collect_system_data_files(path: str, destdir: str | os.PathLike | None = None, include_py_files: bool = False): + """ + This function produces a list of (source, dest) non-Python (i.e., data) files that reside somewhere on the system. + Its output can be directly assigned to ``datas`` in a hook script. + + This function is intended to be used by hook scripts, not by main PyInstaller code. + """ + # Accept only strings as paths. + if not isinstance(path, str): + raise TypeError('path must be a str') + + # Walk through all file in the given package, looking for data files. + datas = [] + for dirpath, dirnames, files in os.walk(path): + for f in files: + extension = os.path.splitext(f)[1] + if include_py_files or (extension not in PY_IGNORE_EXTENSIONS): + # Produce the tuple: (/abs/path/to/source/mod/submod/file.dat, mod/submod/destdir) + source = os.path.join(dirpath, f) + dest = str(Path(dirpath).relative_to(path)) + if destdir is not None: + dest = os.path.join(destdir, dest) + datas.append((source, dest)) + + return datas + + +def copy_metadata(package_name: str, recursive: bool = False): + """ + Collect distribution metadata so that ``importlib.metadata.distribution()`` or ``pkg_resources.get_distribution()`` + can find it. + + This function returns a list to be assigned to the ``datas`` global variable. This list instructs PyInstaller to + copy the metadata for the given package to the frozen application's data directory. + + Parameters + ---------- + package_name : str + Specifies the name of the package for which metadata should be copied. + recursive : bool + If true, collect metadata for the package's dependencies too. This enables use of + ``importlib.metadata.requires('package')`` or ``pkg_resources.require('package')`` inside the frozen + application. + + Returns + ------- + list + This should be assigned to ``datas``. + + Examples + -------- + >>> from PyInstaller.utils.hooks import copy_metadata + >>> copy_metadata('sphinx') + [('c:\\python27\\lib\\site-packages\\Sphinx-1.3.2.dist-info', + 'Sphinx-1.3.2.dist-info')] + + + Some packages rely on metadata files accessed through the ``importlib.metadata`` (or the now-deprecated + ``pkg_resources``) module. PyInstaller does not collect these metadata files by default. + If a package fails without the metadata (either its own, or of another package that it depends on), you can use this + function in a hook to collect the corresponding metadata files into the frozen application. The tuples in the + returned list contain two strings. The first is the full path to the package's metadata directory on the system. The + second is the destination name, which typically corresponds to the basename of the metadata directory. Adding these + tuples the the ``datas`` hook global variable, the metadata is collected into top-level application directory (where + it is usually searched for). + + .. versionchanged:: 4.3.1 + + Prevent ``dist-info`` metadata folders being renamed to ``egg-info`` which broke ``pkg_resources.require`` with + *extras* (see :issue:`#3033`). + + .. versionchanged:: 4.4.0 + + Add the **recursive** option. + """ + from collections import deque + + todo = deque([package_name]) + done = set() + out = [] + + while todo: + package_name = todo.pop() + if package_name in done: + continue + + dist = importlib_metadata.distribution(package_name) + + # We support only `importlib_metadata.PathDistribution`, since we need to rely on its private `_path` attribute + # to obtain the path to metadata file/directory. But we need to account for possible sub-classes and vendored + # variants (`setuptools._vendor.importlib_metadata.PathDistribution˙), so just check that `_path` is available. + if not hasattr(dist, '_path'): + raise RuntimeError( + f"Unsupported distribution type {type(dist)} for {package_name} - does not have _path attribute" + ) + src_path = dist._path + + # We expect the `_path` attribute to be an instance of `pathlib.Path`. This assumption is violated when the + # package happens to be installed as a zipped egg. In such case, `_path` is an instance of either `zipp.Path` + # (when using `importlib.metadata` from `importlib-metadata`, which in turn uses 3rd party `zipp` package) or + # `zipfile.Path` (when using stdlib's `importlib.metadata`). While we could attempt to read the metadata + # from the zip, we dropped geberal support for zipped eggs from PyInstaller in 6.0, so raise an error. + if not isinstance(src_path, Path): + # NOTE: `src_path.parent` is also an instance of `zipfile.Path` or `zipp.Path`, and calling its `is_file()` + # method returns False, because the root of zip file is (rightfully) considered a directory. Therefore, we + # convert the path to `pathlib.Path˙ by taking the parent of `src_path.parent` (which turns out to be a + # `pathlib.Path`) and add to it the name of the `src_path.parent` (the name of .egg file). + try: + src_parent = src_path.parent.parent / src_path.parent.name + except Exception: + src_parent = src_path.parent + + if src_parent.is_file() and src_parent.name.endswith('.egg'): + raise RuntimeError( + f"Cannot collect metadata from path {str(src_path)!r}, which appears to be inside a zipped egg. " + f"PyInstaller >= 6.0 does not support zipped eggs anymore. Please reinstall {package_name!r} " + "using modern package installation method instead of deprecated 'python setup.py install'. " + "For example, if you are using pip package manager:\n" + "1. uninstall the zipped egg:\n" + f" pip uninstall {package_name}\n" + "2. make sure pip and its dependencies are up-to-date:\n" + " python -m pip install --upgrade pip wheel setuptools\n" + "3. install the package:\n" + f" pip install {package_name}\n" + "To install a package from source, pass the path to the source directory to 'pip install' command." + ) + else: + # Generic message for unforeseen cases. + raise RuntimeError( + f"Cannot collect metadata from path {src_path!r}, which is of unsupported type {type(src_path)}." + ) + + if src_path.is_dir(): + # The metadata is stored in a directory (.egg-info, .dist-info), so collect the whole directory. If the + # package is installed as an egg, the metadata directory is ([...]/package_name-version.egg/EGG-INFO), + # and requires special handling (as of PyInstaller v6, we support only non-zipped eggs). + if src_path.name == 'EGG-INFO' and src_path.parent.name.endswith('.egg'): + dest_path = os.path.join(*src_path.parts[-2:]) + else: + dest_path = src_path.name + elif src_path.is_file(): + # The metadata is stored in a single file. Collect it into top-level application directory. + # The .egg-info file is commonly used by Debian/Ubuntu when packaging python packages. + dest_path = '.' + else: + raise RuntimeError( + f"Distribution metadata path {src_path!r} for {package_name} is neither file nor directory!" + ) + + # Hack for metadata from packages vendored by setuptools >= 71. If source path is rooted in setuptools/_vendor, + # prepend the same to the destination path and avoid collecting into top-level directory. + if src_path.parent.name == '_vendor' and src_path.parent.parent.name == 'setuptools': + dest_path = os.path.join('setuptools', '_vendor', dest_path) + + out.append((str(src_path), str(dest_path))) + + if not recursive: + return out + done.add(package_name) + + # Process requirements; `importlib.metadata` has no API for parsing requirements, so we need to use + # `packaging.requirements`. This is necessary to discard requirements with markers that do not match the + # environment (e.g., `python_version`, `sys_platform`). + requirements = [packaging.requirements.Requirement(req) for req in dist.requires or []] + requirements = [req.name for req in requirements if req.marker is None or req.marker.evaluate()] + + todo += requirements + + return out + + +def get_installer(module: str): + """ + Try to find which package manager installed a module. + + :param module: Module to check + :return: Package manager or None + """ + # Resolve distribution for given module/package name (e.g., enchant -> pyenchant). + pkg_to_dist = importlib_metadata.packages_distributions() + dist_names = pkg_to_dist.get(module) + if dist_names is not None: + # A namespace package might result in multiple dists; take the first one... + try: + dist = importlib_metadata.distribution(dist_names[0]) + installer_text = dist.read_text('INSTALLER') + if installer_text is not None: + return installer_text.strip() + except importlib_metadata.PackageNotFoundError: + # This might happen with eggs if the egg directory name does not match the dist name declared in the + # metadata. + pass + + if compat.is_darwin: + try: + file_name = get_module_file_attribute(module) + except ImportError: + return None + + # Attempt to resolve the module file via macports' port command + try: + output = subprocess.run(['port', 'provides', file_name], + check=True, + stdout=subprocess.PIPE, + encoding='utf-8').stdout + if 'is provided by' in output: + return 'macports' + except Exception: + pass + + # Check if the file is located in homebrew's Cellar directory + file_name = os.path.realpath(file_name) + if 'Cellar' in file_name: + return 'homebrew' + + return None + + +def collect_all( + package_name: str, + include_py_files: bool = True, + filter_submodules: Callable = lambda name: True, + exclude_datas: list | None = None, + include_datas: list | None = None, + on_error: str = "warn once", +): + """ + Collect everything for a given package name. + + Arguments: + package_name: + An ``import``-able package name. + include_py_files: + Forwarded to :func:`collect_data_files`. + filter_submodules: + Forwarded to :func:`collect_submodules`. + exclude_datas: + Forwarded to :func:`collect_data_files`. + include_datas: + Forwarded to :func:`collect_data_files`. + on_error: + Forwarded onto :func:`collect_submodules`. + + Returns: + tuple: A ``(datas, binaries, hiddenimports)`` triplet containing: + + - All data files, raw Python files (if **include_py_files**), and distribution metadata directories (if + applicable). + - All dynamic libraries as returned by :func:`collect_dynamic_libs`. + - All submodules of **package_name**. + + Typical use:: + + datas, binaries, hiddenimports = collect_all('my_package_name') + """ + datas = collect_data_files(package_name, include_py_files, excludes=exclude_datas, includes=include_datas) + binaries = collect_dynamic_libs(package_name) + hiddenimports = collect_submodules(package_name, on_error=on_error, filter=filter_submodules) + + # `copy_metadata` requires a dist name instead of importable/package name. + # A namespace package might belong to multiple distributions, so process all of them. + pkg_to_dist = importlib_metadata.packages_distributions() + dist_names = set(pkg_to_dist.get(package_name, [])) + for dist_name in dist_names: + # Copy metadata + try: + datas += copy_metadata(dist_name) + except Exception: + pass + + return datas, binaries, hiddenimports + + +def collect_entry_point(name: str): + """ + Collect modules and metadata for all exporters of a given entry point. + + Args: + name: + The name of the entry point. Check the documentation for the library that uses the entry point to find + its name. + Returns: + A ``(datas, hiddenimports)`` pair that should be assigned to the ``datas`` and ``hiddenimports``, respectively. + + For libraries, such as ``pytest`` or ``keyring``, that rely on plugins to extend their behaviour. + + Examples: + Pytest uses an entry point called ``'pytest11'`` for its extensions. + To collect all those extensions use:: + + datas, hiddenimports = collect_entry_point("pytest11") + + These values may be used in a hook or added to the ``datas`` and ``hiddenimports`` arguments in the ``.spec`` + file. See :ref:`using spec files`. + + .. versionadded:: 4.3 + """ + datas = [] + imports = [] + for entry_point in importlib_metadata.entry_points(group=name): + datas += copy_metadata(entry_point.dist.name) + imports.append(entry_point.module) + return datas, imports + + +def get_hook_config(hook_api: PostGraphAPI, module_name: str, key: str): + """ + Get user settings for hooks. + + Args: + module_name: + The module/package for which the key setting belong to. + key: + A key for the config. + Returns: + The value for the config. ``None`` if not set. + + The ``get_hook_config`` function will lookup settings in the ``Analysis.hooksconfig`` dict. + + The hook settings can be added to ``.spec`` file in the form of:: + + a = Analysis(["my-app.py"], + ... + hooksconfig = { + "gi": { + "icons": ["Adwaita"], + "themes": ["Adwaita"], + "languages": ["en_GB", "zh_CN"], + }, + }, + ... + ) + """ + config = hook_api.analysis.hooksconfig + value = None + if module_name in config and key in config[module_name]: + value = config[module_name][key] + return value + + +def include_or_exclude_file( + filename: str, + include_list: list | None = None, + exclude_list: list | None = None, +): + """ + Generic inclusion/exclusion decision function based on filename and list of include and exclude patterns. + + Args: + filename: + Filename considered for inclusion. + include_list: + List of inclusion file patterns. + exclude_list: + List of exclusion file patterns. + + Returns: + A boolean indicating whether the file should be included or not. + + If ``include_list`` is provided, True is returned only if the filename matches one of include patterns (and does not + match any patterns in ``exclude_list``, if provided). If ``include_list`` is not provided, True is returned if + filename does not match any patterns in ``exclude list``, if provided. If neither list is provided, True is + returned for any filename. + """ + if include_list is not None: + for pattern in include_list: + if fnmatch.fnmatch(filename, pattern): + break + else: + return False # Not explicitly included; exclude + + if exclude_list is not None: + for pattern in exclude_list: + if fnmatch.fnmatch(filename, pattern): + return False # Explicitly excluded + + return True + + +def collect_delvewheel_libs_directory(package_name, libdir_name=None, datas=None, binaries=None): + """ + Collect data files and binaries from the .libs directory of a delvewheel-enabled python wheel. Such wheels ship + their shared libraries in a .libs directory that is located next to the package directory, and therefore falls + outside the purview of the collect_dynamic_libs() utility function. + + Args: + package_name: + Name of the package (e.g., scipy). + libdir_name: + Optional name of the .libs directory (e.g., scipy.libs). If not provided, ".libs" is added to + ``package_name``. + datas: + Optional list of datas to which collected data file entries are added. The combined result is retuned + as part of the output tuple. + binaries: + Optional list of binaries to which collected binaries entries are added. The combined result is retuned + as part of the output tuple. + + Returns: + tuple: A ``(datas, binaries)`` pair that should be assigned to the ``datas`` and ``binaries``, respectively. + + Examples: + Collect the ``scipy.libs`` delvewheel directory belonging to the Windows ``scipy`` wheel:: + + datas, binaries = collect_delvewheel_libs_directory("scipy") + + When the collected entries should be added to existing ``datas`` and ``binaries`` listst, the following form + can be used to avoid using intermediate temporary variables and merging those into existing lists:: + + datas, binaries = collect_delvewheel_libs_directory("scipy", datas=datas, binaries=binaries) + + .. versionadded:: 5.6 + """ + + datas = datas or [] + binaries = binaries or [] + + if libdir_name is None: + libdir_name = package_name + '.libs' + + # delvewheel is applicable only to Windows wheels + if not compat.is_win: + return datas, binaries + + # Get package's parent path + pkg_base, pkg_dir = get_package_paths(package_name) + pkg_base = Path(pkg_base) + libs_dir = pkg_base / libdir_name + + if not libs_dir.is_dir(): + return datas, binaries + + # Collect all dynamic libs - collect them as binaries in order to facilitate proper binary dependency analysis + # (for example, to ensure that system-installed VC runtime DLLs are collected, if needed). + # As of PyInstaller 5.4, this should be safe (should not result in duplication), because binary dependency + # analysis attempts to preserve the DLL directory structure. + binaries += [(str(dll_file), str(dll_file.parent.relative_to(pkg_base))) for dll_file in libs_dir.glob('*.dll')] + + # Collect the .load-order file; strictly speaking, this should be necessary only under python < 3.8, but let us + # collect it for completeness sake. Differently named variants have been observed: `.load_order`, `.load-order`, + # and `.load-order-Name`. + datas += [(str(load_order_file), str(load_order_file.parent.relative_to(pkg_base))) + for load_order_file in libs_dir.glob('.load[-_]order*')] + + return datas, binaries + + +if compat.is_pure_conda: + from PyInstaller.utils.hooks import conda as conda_support # noqa: F401 +elif compat.is_conda: + from PyInstaller.utils.hooks.conda import CONDA_META_DIR as _tmp + logger.warning( + "Assuming this is not an Anaconda environment or an additional venv/pipenv/... environment manager is being " + "used on top, because the conda-meta folder %s does not exist.", _tmp + ) + del _tmp diff --git a/venv/Lib/site-packages/PyInstaller/utils/hooks/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/utils/hooks/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..2135e67 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/utils/hooks/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/utils/hooks/__pycache__/conda.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/utils/hooks/__pycache__/conda.cpython-311.pyc new file mode 100644 index 0000000..142fca3 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/utils/hooks/__pycache__/conda.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/utils/hooks/__pycache__/django.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/utils/hooks/__pycache__/django.cpython-311.pyc new file mode 100644 index 0000000..6c6ea7d Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/utils/hooks/__pycache__/django.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/utils/hooks/__pycache__/gi.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/utils/hooks/__pycache__/gi.cpython-311.pyc new file mode 100644 index 0000000..3b542fa Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/utils/hooks/__pycache__/gi.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/utils/hooks/__pycache__/setuptools.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/utils/hooks/__pycache__/setuptools.cpython-311.pyc new file mode 100644 index 0000000..b0347a8 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/utils/hooks/__pycache__/setuptools.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/utils/hooks/__pycache__/tcl_tk.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/utils/hooks/__pycache__/tcl_tk.cpython-311.pyc new file mode 100644 index 0000000..98ff87b Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/utils/hooks/__pycache__/tcl_tk.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/utils/hooks/conda.py b/venv/Lib/site-packages/PyInstaller/utils/hooks/conda.py new file mode 100644 index 0000000..1ae28b1 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/utils/hooks/conda.py @@ -0,0 +1,396 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +# language=rst +""" +Additional helper methods for working specifically with Anaconda distributions are found at +:mod:`PyInstaller.utils.hooks.conda_support` +which is designed to mimic (albeit loosely) the `importlib.metadata`_ package. These functions find and parse the +distribution metadata from json files located in the ``conda-meta`` directory. + +.. versionadded:: 4.2.0 + +This module is available only if run inside a Conda environment. Usage of this module should therefore be wrapped in +a conditional clause:: + + from PyInstaller.compat import is_pure_conda + + if is_pure_conda: + from PyInstaller.utils.hooks import conda_support + + # Code goes here. e.g. + binaries = conda_support.collect_dynamic_libs("numpy") + ... + +Packages are all referenced by the *distribution name* you use to install it, rather than the *package name* you import +it with. I.e., use ``distribution("pillow")`` instead of ``distribution("PIL")`` or use ``package_distribution("PIL")``. +""" +from __future__ import annotations + +import fnmatch +import json +import sys +from pathlib import Path +from typing import Iterable, List +from importlib.metadata import PackagePath as _PackagePath + +from PyInstaller import compat +from PyInstaller.log import logger + +# Conda virtual environments each get their own copy of `conda-meta` so the use of `sys.prefix` instead of +# `sys.base_prefix`, `sys.real_prefix` or anything from our `compat` module is intentional. +CONDA_ROOT = Path(sys.prefix) +CONDA_META_DIR = CONDA_ROOT / "conda-meta" + +# Find all paths in `sys.path` that are inside Conda root. +PYTHONPATH_PREFIXES = [] +for _path in sys.path: + _path = Path(_path) + try: + PYTHONPATH_PREFIXES.append(_path.relative_to(sys.prefix)) + except ValueError: + pass + +PYTHONPATH_PREFIXES.sort(key=lambda p: len(p.parts), reverse=True) + + +class Distribution: + """ + A bucket class representation of a Conda distribution. + + This bucket exports the following attributes: + + :ivar name: The distribution's name. + :ivar version: Its version. + :ivar files: All filenames as :meth:`PackagePath`\\ s included with this distribution. + :ivar dependencies: Names of other distributions that this distribution depends on (with version constraints + removed). + :ivar packages: Names of importable packages included in this distribution. + + This class is not intended to be constructed directly by users. Rather use :meth:`distribution` or + :meth:`package_distribution` to provide one for you. + """ + def __init__(self, json_path: str): + try: + self._json_path = Path(json_path) + assert self._json_path.exists() + except (TypeError, AssertionError): + raise TypeError( + "Distribution requires a path to a conda-meta json. Perhaps you want " + "`distribution({})` instead?".format(repr(json_path)) + ) + + # Everything we need (including this distribution's name) is kept in the metadata json. + self.raw: dict = json.loads(self._json_path.read_text()) + + # Unpack the more useful contents of the json. + self.name: str = self.raw["name"] + self.version: str = self.raw["version"] + self.files = [PackagePath(i) for i in self.raw["files"]] + self.dependencies = self._init_dependencies() + self.packages = self._init_package_names() + + def __repr__(self): + return "{}(name=\"{}\", packages={})".format(type(self).__name__, self.name, self.packages) + + def _init_dependencies(self): + """ + Read dependencies from ``self.raw["depends"]``. + + :return: Dependent distribution names. + :rtype: list + + The names in ``self.raw["depends"]`` come with extra version constraint information which must be stripped. + """ + dependencies = [] + # For each dependency: + for dependency in self.raw["depends"]: + # ``dependency`` is a string of the form: "[name] [version constraints]" + name, *version_constraints = dependency.split(maxsplit=1) + dependencies.append(name) + return dependencies + + def _init_package_names(self): + """ + Search ``self.files`` for package names shipped by this distribution. + + :return: Package names. + :rtype: list + + These are names you would ``import`` rather than names you would install. + """ + packages = [] + for file in self.files: + package = _get_package_name(file) + if package is not None: + packages.append(package) + return packages + + @classmethod + def from_name(cls, name: str): + """ + Get distribution information for a given distribution **name** (i.e., something you would ``conda install``). + + :rtype: :class:`Distribution` + """ + if name in distributions: + return distributions[name] + raise ModuleNotFoundError( + "Distribution {} is either not installed or was not installed using Conda.".format(name) + ) + + @classmethod + def from_package_name(cls, name: str): + """ + Get distribution information for a **package** (i.e., something you would import). + + :rtype: :class:`Distribution` + + For example, the package ``pkg_resources`` belongs to the distribution ``setuptools``, which contains three + packages. + + >>> package_distribution("pkg_resources") + Distribution(name="setuptools", + packages=['easy_install', 'pkg_resources', 'setuptools']) + """ + if name in distributions_by_package: + return distributions_by_package[name] + raise ModuleNotFoundError("Package {} is either not installed or was not installed using Conda.".format(name)) + + +distribution = Distribution.from_name +package_distribution = Distribution.from_package_name + + +class PackagePath(_PackagePath): + """ + A filename relative to Conda's root (``sys.prefix``). + + This class inherits from :class:`pathlib.PurePosixPath` even on non-Posix OSs. To convert to a :class:`pathlib.Path` + pointing to the real file, use the :meth:`locate` method. + """ + def locate(self): + """ + Return a path-like object for this path pointing to the file's true location. + """ + return Path(sys.prefix) / self + + +def walk_dependency_tree(initial: str, excludes: Iterable[str] | None = None): + """ + Collect a :class:`Distribution` and all direct and indirect dependencies of that distribution. + + Arguments: + initial: + Distribution name to collect from. + excludes: + Distributions to exclude. + Returns: + A ``{name: distribution}`` mapping where ``distribution`` is the output of + :func:`conda_support.distribution(name) `. + """ + if excludes is not None: + excludes = set(excludes) + + # Rather than use true recursion, mimic it with a to-do queue. + from collections import deque + done = {} + names_to_do = deque([initial]) + + while names_to_do: + # Grab a distribution name from the to-do list. + name = names_to_do.pop() + try: + # Collect and save it's metadata. + done[name] = distribution = Distribution.from_name(name) + logger.debug("Collected Conda distribution '%s', a dependency of '%s'.", name, initial) + except ModuleNotFoundError: + logger.warning( + "Conda distribution '%s', dependency of '%s', was not found. " + "If you installed this distribution with pip then you may ignore this warning.", name, initial + ) + continue + # For each dependency: + for _name in distribution.dependencies: + if _name in done: + # Skip anything already done. + continue + if _name == name: + # Avoid infinite recursion if a distribution depends on itself. This will probably never happen but I + # certainly would not chance it. + continue + if excludes is not None and _name in excludes: + # Do not recurse to excluded dependencies. + continue + names_to_do.append(_name) + return done + + +def _iter_distributions(name, dependencies, excludes): + if dependencies: + return walk_dependency_tree(name, excludes).values() + else: + return [Distribution.from_name(name)] + + +def requires(name: str, strip_versions: bool = False) -> List[str]: + """ + List requirements of a distribution. + + Arguments: + name: + The name of the distribution. + strip_versions: + List only their names, not their version constraints. + Returns: + A list of distribution names. + """ + if strip_versions: + return distribution(name).dependencies + return distribution(name).raw["depends"] + + +def files(name: str, dependencies: bool = False, excludes: list | None = None) -> List[PackagePath]: + """ + List all files belonging to a distribution. + + Arguments: + name: + The name of the distribution. + dependencies: + Recursively collect files of dependencies too. + excludes: + Distributions to ignore if **dependencies** is true. + Returns: + All filenames belonging to the given distribution. + + With ``dependencies=False``, this is just a shortcut for:: + + conda_support.distribution(name).files + """ + return [file for dist in _iter_distributions(name, dependencies, excludes) for file in dist.files] + + +if compat.is_win: + lib_dir = PackagePath("Library", "bin") +else: + lib_dir = PackagePath("lib") + + +def collect_dynamic_libs(name: str, dest: str = ".", dependencies: bool = True, excludes: Iterable[str] | None = None): + """ + Collect DLLs for distribution **name**. + + Arguments: + name: + The distribution's project-name. + dest: + Target destination, defaults to ``'.'``. + dependencies: + Recursively collect libs for dependent distributions (recommended). + excludes: + Dependent distributions to skip, defaults to ``None``. + Returns: + List of DLLs in PyInstaller's ``(source, dest)`` format. + + This collects libraries only from Conda's shared ``lib`` (Unix) or ``Library/bin`` (Windows) folders. To collect + from inside a distribution's installation use the regular :func:`PyInstaller.utils.hooks.collect_dynamic_libs`. + """ + DLL_SUFFIXES = ("*.dll", "*.dylib", "*.so", "*.so.*") + _files = [] + for file in files(name, dependencies, excludes): + # A file is classified as a dynamic library if: + # 1) it lives inside the dedicated ``lib_dir`` DLL folder + if file.parent != lib_dir: + continue + # 2) it is a file (and not a directory or a symbolic link pointing to a directory) + resolved_file = file.locate() + if not resolved_file.is_file(): + continue + # 3) has a correct suffix + if not any([resolved_file.match(suffix) for suffix in DLL_SUFFIXES]): + continue + + _files.append((str(resolved_file), dest)) + return _files + + +# --- Map packages to distributions and vice-versa --- + + +def _get_package_name(file: PackagePath): + """ + Determine the package name of a Python file in :data:`sys.path`. + + Arguments: + file: + A Python filename relative to Conda root (sys.prefix). + Returns: + Package name or None. + + This function only considers single file packages e.g. ``foo.py`` or top level ``foo/__init__.py``\\ s. + Anything else is ignored (returning ``None``). + """ + file = Path(file) + # TODO: Handle PEP 420 namespace packages (which are missing `__init__` module). No such Conda PEP 420 namespace + # packages are known. + + # Get top-level folders by finding parents of `__init__.xyz`s + if file.stem == "__init__" and file.suffix in compat.ALL_SUFFIXES: + file = file.parent + elif file.suffix not in compat.ALL_SUFFIXES: + # Keep single-file packages but skip DLLs, data and junk files. + return + + # Check if this file/folder's parent is in ``sys.path`` i.e. it's directly importable. This intentionally excludes + # submodules which would cause confusion because ``sys.prefix`` is in ``sys.path``, meaning that every file in an + # Conda installation is a submodule. + for prefix in PYTHONPATH_PREFIXES: + if len(file.parts) != len(prefix.parts) + 1: + # This check is redundant but speeds it up quite a bit. + continue + # There are no wildcards involved here. The use of ``fnmatch`` is simply to handle the `if case-insensitive + # file system: use case-insensitive string matching.` + if fnmatch.fnmatch(str(file.parent), str(prefix)): + return file.stem + + +# All the information we want is organised the wrong way. + +# We want to look up distribution based on package names, but we can only search for packages using distribution names. +# And we would like to search for a distribution's json file, but, due to the noisy filenames of the jsons, we can only +# find a json's distribution rather than a distribution's json. + +# So we have to read everything, then regroup distributions in the ways we want them grouped. This will likely be a +# spectacular bottleneck on full-blown Conda (non miniconda) with 250+ packages by default at several GiBs. I suppose we +# could cache this on a per-json basis if it gets too much. + + +def _init_distributions(): + distributions = {} + for path in CONDA_META_DIR.glob("*.json"): + dist = Distribution(path) + distributions[dist.name] = dist + return distributions + + +distributions = _init_distributions() + + +def _init_packages(): + distributions_by_package = {} + for distribution in distributions.values(): + for package in distribution.packages: + distributions_by_package[package] = distribution + return distributions_by_package + + +distributions_by_package = _init_packages() diff --git a/venv/Lib/site-packages/PyInstaller/utils/hooks/django.py b/venv/Lib/site-packages/PyInstaller/utils/hooks/django.py new file mode 100644 index 0000000..5b8bdae --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/utils/hooks/django.py @@ -0,0 +1,152 @@ +# ---------------------------------------------------------------------------- +# 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) +# ---------------------------------------------------------------------------- +import os + +from PyInstaller import isolated + + +@isolated.decorate +def django_dottedstring_imports(django_root_dir): + """ + An isolated helper that returns list of all Django dependencies, parsed from the `mysite.settings` module. + + NOTE: With newer version of Django this is most likely the part of PyInstaller that will be broken. + + Tested with Django 2.2 + """ + + import sys + import os + + import PyInstaller.utils.misc + from PyInstaller.utils import hooks as hookutils + + # Extra search paths to add to sys.path: + # - parent directory of the django_root_dir + # - django_root_dir itself; often, Django users do not specify absolute imports in the settings module. + search_paths = [ + PyInstaller.utils.misc.get_path_to_toplevel_modules(django_root_dir), + django_root_dir, + ] + sys.path += search_paths + + # Set the path to project's settings module + default_settings_module = os.path.basename(django_root_dir) + '.settings' + settings_module = os.environ.get('DJANGO_SETTINGS_MODULE', default_settings_module) + os.environ['DJANGO_SETTINGS_MODULE'] = settings_module + + # Calling django.setup() avoids the exception AppRegistryNotReady() and also reads the user settings + # from DJANGO_SETTINGS_MODULE. + # https://stackoverflow.com/questions/24793351/django-appregistrynotready + import django # noqa: E402 + + django.setup() + + # This allows to access all django settings even from the settings.py module. + from django.conf import settings # noqa: E402 + + hiddenimports = list(settings.INSTALLED_APPS) + + # Do not fail script when settings does not have such attributes. + if hasattr(settings, 'TEMPLATE_CONTEXT_PROCESSORS'): + hiddenimports += list(settings.TEMPLATE_CONTEXT_PROCESSORS) + + if hasattr(settings, 'TEMPLATE_LOADERS'): + hiddenimports += list(settings.TEMPLATE_LOADERS) + + hiddenimports += [settings.ROOT_URLCONF] + + def _remove_class(class_name): + return '.'.join(class_name.split('.')[0:-1]) + + #-- Changes in Django 1.7. + + # Remove class names and keep just modules. + if hasattr(settings, 'AUTHENTICATION_BACKENDS'): + for cl in settings.AUTHENTICATION_BACKENDS: + cl = _remove_class(cl) + hiddenimports.append(cl) + # Deprecated since 4.2, may be None until it is removed + cl = getattr(settings, 'DEFAULT_FILE_STORAGE', None) + if cl: + hiddenimports.append(_remove_class(cl)) + if hasattr(settings, 'FILE_UPLOAD_HANDLERS'): + for cl in settings.FILE_UPLOAD_HANDLERS: + cl = _remove_class(cl) + hiddenimports.append(cl) + if hasattr(settings, 'MIDDLEWARE_CLASSES'): + for cl in settings.MIDDLEWARE_CLASSES: + cl = _remove_class(cl) + hiddenimports.append(cl) + # Templates is a dict: + if hasattr(settings, 'TEMPLATES'): + for templ in settings.TEMPLATES: + backend = _remove_class(templ['BACKEND']) + hiddenimports.append(backend) + # Include context_processors. + if hasattr(templ, 'OPTIONS'): + if hasattr(templ['OPTIONS'], 'context_processors'): + # Context processors are functions - strip last word. + mods = templ['OPTIONS']['context_processors'] + mods = [_remove_class(x) for x in mods] + hiddenimports += mods + # Include database backends - it is a dict. + for v in settings.DATABASES.values(): + hiddenimports.append(v['ENGINE']) + + # Add templatetags and context processors for each installed app. + for app in settings.INSTALLED_APPS: + app_templatetag_module = app + '.templatetags' + app_ctx_proc_module = app + '.context_processors' + hiddenimports.append(app_templatetag_module) + hiddenimports += hookutils.collect_submodules(app_templatetag_module) + hiddenimports.append(app_ctx_proc_module) + + # Deduplicate imports. + hiddenimports = list(set(hiddenimports)) + + # Return the hidden imports + return hiddenimports + + +def django_find_root_dir(): + """ + Return path to directory (top-level Python package) that contains main django files. Return None if no directory + was detected. + + Main Django project directory contain files like '__init__.py', 'settings.py' and 'url.py'. + + In Django 1.4+ the script 'manage.py' is not in the directory with 'settings.py' but usually one level up. We + need to detect this special case too. + """ + # 'PyInstaller.config' cannot be imported as other top-level modules. + from PyInstaller.config import CONF + + # Get the directory with manage.py. Manage.py is supplied to PyInstaller as the first main executable script. + manage_py = CONF['main_script'] + manage_dir = os.path.dirname(os.path.abspath(manage_py)) + + # Get the Django root directory. The directory that contains settings.py and url.py. It could be the directory + # containing manage.py or any of its subdirectories. + settings_dir = None + files = set(os.listdir(manage_dir)) + if ('settings.py' in files or 'settings' in files) and 'urls.py' in files: + settings_dir = manage_dir + else: + for f in files: + if os.path.isdir(os.path.join(manage_dir, f)): + subfiles = os.listdir(os.path.join(manage_dir, f)) + # Subdirectory contains critical files. + if ('settings.py' in subfiles or 'settings' in subfiles) and 'urls.py' in subfiles: + settings_dir = os.path.join(manage_dir, f) + break # Find the first directory. + + return settings_dir diff --git a/venv/Lib/site-packages/PyInstaller/utils/hooks/gi.py b/venv/Lib/site-packages/PyInstaller/utils/hooks/gi.py new file mode 100644 index 0000000..0ac8236 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/utils/hooks/gi.py @@ -0,0 +1,426 @@ +# ---------------------------------------------------------------------------- +# 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) +# ---------------------------------------------------------------------------- +import os +import pathlib +import shutil +import subprocess +import hashlib +import re + +from PyInstaller.depend.utils import _resolveCtypesImports +from PyInstaller.utils.hooks import collect_submodules, collect_system_data_files, get_hook_config +from PyInstaller import isolated +from PyInstaller import log as logging +from PyInstaller import compat +from PyInstaller.depend.bindepend import findSystemLibrary + +logger = logging.getLogger(__name__) + + +class GiModuleInfo: + def __init__(self, module, version, hook_api=None): + self.name = module + self.version = version + self.available = False + self.sharedlibs = [] + self.typelib = None + self.dependencies = [] + + # If hook API is available, use it to override the version from hookconfig. + if hook_api is not None: + module_versions = get_hook_config(hook_api, 'gi', 'module-versions') + if module_versions: + self.version = module_versions.get(module, version) + + logger.debug("Gathering GI module info for %s %s", module, self.version) + + @isolated.decorate + def _get_module_info(module, version): + import gi + gi.require_version("GIRepository", "2.0") + from gi.repository import GIRepository + + repo = GIRepository.Repository.get_default() + repo.require(module, version, GIRepository.RepositoryLoadFlags.IREPOSITORY_LOAD_FLAG_LAZY) + + # Shared library/libraries + # Comma-separated list of paths to shared libraries, or None if none are associated. Convert to list. + sharedlibs = repo.get_shared_library(module) + sharedlibs = [lib.strip() for lib in sharedlibs.split(",")] if sharedlibs else [] + + # Path to .typelib file + typelib = repo.get_typelib_path(module) + + # Dependencies + # GIRepository.Repository.get_immediate_dependencies is available from gobject-introspection v1.44 on + if hasattr(repo, 'get_immediate_dependencies'): + dependencies = repo.get_immediate_dependencies(module) + else: + dependencies = repo.get_dependencies(module) + + return { + 'sharedlibs': sharedlibs, + 'typelib': typelib, + 'dependencies': dependencies, + } + + # Try to query information; if this fails, mark module as unavailable. + try: + info = _get_module_info(module, self.version) + self.sharedlibs = info['sharedlibs'] + self.typelib = info['typelib'] + self.dependencies = info['dependencies'] + self.available = True + except Exception as e: + logger.debug("Failed to query GI module %s %s: %s", module, self.version, e) + self.available = False + + def get_libdir(self): + """ + Return the path to shared library used by the module. If no libraries are associated with the typelib, None is + returned. If multiple library names are associated with the typelib, the path to the first resolved shared + library is returned. Raises exception if module is unavailable or none of the shared libraries could be + resolved. + """ + # Module unavailable + if not self.available: + raise ValueError(f"Module {self.name} {self.version} is unavailable!") + # Module has no associated shared libraries + if not self.sharedlibs: + return None + for lib in self.sharedlibs: + path = findSystemLibrary(lib) + if path: + return os.path.normpath(os.path.dirname(path)) + raise ValueError(f"Could not resolve any shared library of {self.name} {self.version}: {self.sharedlibs}!") + + def collect_typelib_data(self): + """ + Return a tuple of (binaries, datas, hiddenimports) to be used by PyGObject related hooks. + """ + datas = [] + binaries = [] + hiddenimports = [] + + logger.debug("Collecting module data for %s %s", self.name, self.version) + + # Module unavailable + if not self.available: + raise ValueError(f"Module {self.name} {self.version} is unavailable!") + + # Find shared libraries + resolved_libs = _resolveCtypesImports(self.sharedlibs) + for resolved_lib in resolved_libs: + logger.debug("Collecting shared library %s at %s", resolved_lib[0], resolved_lib[1]) + binaries.append((resolved_lib[1], ".")) + + # Find and collect .typelib file. Run it through the `gir_library_path_fix` to fix the library path, if + # necessary. + typelib_entry = gir_library_path_fix(self.typelib) + if typelib_entry: + logger.debug('Collecting gir typelib at %s', typelib_entry[0]) + datas.append(typelib_entry) + + # Overrides for the module + hiddenimports += collect_submodules('gi.overrides', lambda name: name.endswith('.' + self.name)) + + # Module dependencies + for dep in self.dependencies: + dep_module, _ = dep.rsplit('-', 1) + hiddenimports += [f'gi.repository.{dep_module}'] + + return binaries, datas, hiddenimports + + +# The old function, provided for backwards compatibility in 3rd party hooks. +def get_gi_libdir(module, version): + module_info = GiModuleInfo(module, version) + return module_info.get_libdir() + + +# The old function, provided for backwards compatibility in 3rd party hooks. +def get_gi_typelibs(module, version): + """ + Return a tuple of (binaries, datas, hiddenimports) to be used by PyGObject related hooks. Searches for and adds + dependencies recursively. + + :param module: GI module name, as passed to 'gi.require_version()' + :param version: GI module version, as passed to 'gi.require_version()' + """ + module_info = GiModuleInfo(module, version) + return module_info.collect_typelib_data() + + +def gir_library_path_fix(path): + import subprocess + + # 'PyInstaller.config' cannot be imported as other top-level modules. + from PyInstaller.config import CONF + + path = os.path.abspath(path) + + # On Mac OS we need to recompile the GIR files to reference the loader path, + # but this is not necessary on other platforms. + if compat.is_darwin: + + # If using a virtualenv, the base prefix and the path of the typelib + # have really nothing to do with each other, so try to detect that. + common_path = os.path.commonprefix([compat.base_prefix, path]) + if common_path == '/': + logger.debug("virtualenv detected? fixing the gir path...") + common_path = os.path.abspath(os.path.join(path, '..', '..', '..')) + + gir_path = os.path.join(common_path, 'share', 'gir-1.0') + + typelib_name = os.path.basename(path) + gir_name = os.path.splitext(typelib_name)[0] + '.gir' + + gir_file = os.path.join(gir_path, gir_name) + + if not os.path.exists(gir_path): + logger.error( + "Unable to find gir directory: %s.\nTry installing your platform's gobject-introspection package.", + gir_path + ) + return None + if not os.path.exists(gir_file): + logger.error( + "Unable to find gir file: %s.\nTry installing your platform's gobject-introspection package.", gir_file + ) + return None + + with open(gir_file, 'r', encoding='utf-8') as f: + lines = f.readlines() + # GIR files are `XML encoded `_, + # which means they are by definition encoded using UTF-8. + with open(os.path.join(CONF['workpath'], gir_name), 'w', encoding='utf-8') as f: + for line in lines: + if 'shared-library' in line: + split = re.split('(=)', line) + files = re.split('(["|,])', split[2]) + for count, item in enumerate(files): + if 'lib' in item: + files[count] = '@loader_path/' + os.path.basename(item) + line = ''.join(split[0:2]) + ''.join(files) + f.write(line) + + # g-ir-compiler expects a file so we cannot just pipe the fixed file to it. + command = subprocess.Popen(( + 'g-ir-compiler', os.path.join(CONF['workpath'], gir_name), + '-o', os.path.join(CONF['workpath'], typelib_name) + )) # yapf: disable + command.wait() + + return os.path.join(CONF['workpath'], typelib_name), 'gi_typelibs' + else: + return path, 'gi_typelibs' + + +@isolated.decorate +def get_glib_system_data_dirs(): + import gi + gi.require_version('GLib', '2.0') + from gi.repository import GLib + return GLib.get_system_data_dirs() + + +def get_glib_sysconf_dirs(): + """ + Try to return the sysconf directories (e.g., /etc). + """ + if compat.is_win: + # On Windows, if you look at gtkwin32.c, sysconfdir is actually relative to the location of the GTK DLL. Since + # that is what we are actually interested in (not the user path), we have to do that the hard way... + return [os.path.join(get_gi_libdir('GLib', '2.0'), 'etc')] + + @isolated.call + def data_dirs(): + import gi + gi.require_version('GLib', '2.0') + from gi.repository import GLib + return GLib.get_system_config_dirs() + + return data_dirs + + +def collect_glib_share_files(*path): + """ + Path is relative to the system data directory (e.g., /usr/share). + """ + glib_data_dirs = get_glib_system_data_dirs() + if glib_data_dirs is None: + return [] + + destdir = os.path.join('share', *path) + + # TODO: will this return too much? + collected = [] + for data_dir in glib_data_dirs: + p = os.path.join(data_dir, *path) + collected += collect_system_data_files(p, destdir=destdir, include_py_files=False) + + return collected + + +def collect_glib_etc_files(*path): + """ + Path is relative to the system config directory (e.g., /etc). + """ + glib_config_dirs = get_glib_sysconf_dirs() + if glib_config_dirs is None: + return [] + + destdir = os.path.join('etc', *path) + + # TODO: will this return too much? + collected = [] + for config_dir in glib_config_dirs: + p = os.path.join(config_dir, *path) + collected += collect_system_data_files(p, destdir=destdir, include_py_files=False) + + return collected + + +_glib_translations = None + + +def collect_glib_translations(prog, lang_list=None): + """ + Return a list of translations in the system locale directory whose names equal prog.mo. + """ + global _glib_translations + if _glib_translations is None: + if lang_list is not None: + trans = [] + for lang in lang_list: + trans += collect_glib_share_files(os.path.join("locale", lang)) + _glib_translations = trans + else: + _glib_translations = collect_glib_share_files('locale') + + names = [os.sep + prog + '.mo', os.sep + prog + '.po'] + namelen = len(names[0]) + + return [(src, dst) for src, dst in _glib_translations if src[-namelen:] in names] + + +# Not a hook utility function per-se (used by main Analysis class), but kept here to have all GLib/GObject functions +# in one place... +def compile_glib_schema_files(datas_toc, workdir, collect_source_files=False): + """ + Compile collected GLib schema files. Extracts the list of GLib schema files from the given input datas TOC, copies + them to temporary working directory, and compiles them. The resulting `gschemas.compiled` file is added to the + output TOC, replacing any existing entry with that name. If `collect_source_files` flag is set, the source XML + schema files are also (re)added to the output TOC; by default, they are not. This function is no-op (returns the + original TOC) if no GLib schemas are found in TOC or if `glib-compile-schemas` executable is not found in `PATH`. + """ + SCHEMA_DEST_DIR = pathlib.PurePath("share/glib-2.0/schemas") + workdir = pathlib.Path(workdir) + + schema_files = [] + output_toc = [] + for toc_entry in datas_toc: + dest_name, src_name, typecode = toc_entry + dest_name = pathlib.PurePath(dest_name) + src_name = pathlib.PurePath(src_name) + + # Pass-through for non-schema files, identified based on the destination directory. + if dest_name.parent != SCHEMA_DEST_DIR: + output_toc.append(toc_entry) + continue + + # It seems schemas directory contains different files with different suffices: + # - .gschema.xml + # - .schema.override + # - .enums.xml + # To avoid omitting anything, simply collect everything into temporary directory. + # Exemptions are gschema.dtd (which should be unnecessary) and gschemas.compiled (which we will generate + # ourselves in this function). + if src_name.name in {"gschema.dtd", "gschemas.compiled"}: + continue + + schema_files.append(src_name) + + # If there are no schema files available, simply return the input datas TOC. + if not schema_files: + return datas_toc + + # Ensure that `glib-compile-schemas` executable is in PATH, just in case... + schema_compiler_exe = shutil.which('glib-compile-schemas') + if not schema_compiler_exe: + logger.warning("GLib schema compiler (glib-compile-schemas) not found! Skipping GLib schema recompilation...") + return datas_toc + + # If `gschemas.compiled` file already exists in the temporary working directory, record its modification time and + # hash. This will allow us to restore the modification time on the newly-compiled copy, if the latter turns out + # to be identical to the existing old one. Just in case, if the file becomes subject to timestamp-based caching + # mechanism. + compiled_file = workdir / "gschemas.compiled" + old_compiled_file_hash = None + old_compiled_file_stat = None + + if compiled_file.is_file(): + # Record creation/modification time + old_compiled_file_stat = compiled_file.stat() + # Compute SHA1 hash; since compiled schema files are relatively small, do it in single step. + old_compiled_file_hash = hashlib.sha1(compiled_file.read_bytes()).digest() + + # Ensure that temporary working directory exists, and is empty. + if workdir.exists(): + shutil.rmtree(workdir) + workdir.mkdir(exist_ok=True) + + # Copy schema (source) files to temporary working directory + for schema_file in schema_files: + shutil.copy(schema_file, workdir) + + # Compile. The glib-compile-schema might produce warnings on its own (e.g., schemas using deprecated paths, or + # overrides for non-existent keys). Since these are non-actionable, capture and display them only as a DEBUG + # message, or as a WARNING one if the command fails. + logger.info("Compiling collected GLib schema files in %r...", str(workdir)) + try: + cmd_args = [schema_compiler_exe, str(workdir), '--targetdir', str(workdir)] + p = subprocess.run( + cmd_args, + stdin=subprocess.DEVNULL, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + check=True, + errors='ignore', + encoding='utf-8', + ) + logger.debug("Output from glib-compile-schemas:\n%s", p.stdout) + except subprocess.CalledProcessError as e: + # The called glib-compile-schema returned error. Display stdout/stderr, and return original datas TOC to + # minimize damage. + logger.warning("Failed to recompile GLib schemas! Returning collected files as-is!", exc_info=True) + logger.warning("Output from glib-compile-schemas:\n%s", e.stdout) + return datas_toc + except Exception: + # Compilation failed for whatever reason. Return original datas TOC to minimize damage. + logger.warning("Failed to recompile GLib schemas! Returning collected files as-is!", exc_info=True) + return datas_toc + + # Compute the checksum of the new compiled file, and if it matches the old checksum, restore the modification time. + if old_compiled_file_hash is not None: + new_compiled_file_hash = hashlib.sha1(compiled_file.read_bytes()).digest() + if new_compiled_file_hash == old_compiled_file_hash: + os.utime(compiled_file, ns=(old_compiled_file_stat.st_atime_ns, old_compiled_file_stat.st_mtime_ns)) + + # Add the resulting gschemas.compiled file to the output TOC + output_toc.append((str(SCHEMA_DEST_DIR / compiled_file.name), str(compiled_file), "DATA")) + + # Include source schema files in the output TOC (optional) + if collect_source_files: + for schema_file in schema_files: + output_toc.append((str(SCHEMA_DEST_DIR / schema_file.name), str(schema_file), "DATA")) + + return output_toc diff --git a/venv/Lib/site-packages/PyInstaller/utils/hooks/qt/__init__.py b/venv/Lib/site-packages/PyInstaller/utils/hooks/qt/__init__.py new file mode 100644 index 0000000..416cbb4 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/utils/hooks/qt/__init__.py @@ -0,0 +1,1424 @@ +# ---------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- + +import glob +import os +import pathlib +import re + +from PyInstaller import compat +from PyInstaller import isolated +from PyInstaller import log as logging +from PyInstaller.depend import bindepend +from PyInstaller.utils import hooks, misc +from PyInstaller.utils.hooks.qt import _modules_info + +logger = logging.getLogger(__name__) + +# Qt deployment approach +# ---------------------- +# This is the core of PyInstaller's approach to Qt deployment. It is based on: +# +# - Discovering the location of Qt libraries by introspection, using QtLibraryInfo_. This provides compatibility with +# many variants of Qt5/6 (conda, self-compiled, provided by a Linux distro, etc.) and many versions of Qt5/6, all of +# which vary in the location of Qt files. +# +# - Placing all frozen PyQt5/6 or PySide2/6 Qt files in a standard subdirectory layout, which matches the layout of the +# corresponding wheel on PyPI. This is necessary to support Qt installs which are not in a subdirectory of the PyQt5/6 +# or PySide2/6 wrappers. See ``hooks/rthooks/pyi_rth_qt5.py`` for the use of environment variables to establish this +# layout. +# +# - Emitting warnings on missing QML and translation files which some installations do not have. +# +# - Determining additional files needed for deployment based on the information in the centralized Qt module information +# list in the ``_modules_info`` module. This includes plugins and translation files associated with each Qt python +# extension module, as well as additional python Qt extension modules. +# +# - Collecting additional files that are specific to each module and are handled separately, for example: +# +# - For dynamic OpenGL applications, the ``libEGL.dll``, ``libGLESv2.dll``, ``d3dcompiler_XX.dll`` (the XX is a +# version number), and ``opengl32sw.dll`` libraries need to be collected on Windows. This is handled by the +# "base" bindings hook, for example ``hook-PyQt5.py``. +# +# - If Qt was configured to use ICU, the ``icudtXX.dll``, ``icuinXX.dll``, and ``icuucXX.dll`` libraries need to +# be collected on Windows. This is handled by the "base" bindings hook, for example ``hook-PyQt5.py``. +# +# - Per the `Deploying QML Applications `_ page, QML-based +# applications need the ``qml/`` directory available. This is handled by ``QtQuick`` hook, for example +# ``hook-PyQt5.QtQuick.py``. +# +# - For ``QtWebEngine``-based applications, we follow the `deployWebEngineCore +# `_ +# function copies the following files from ``resources/``, and also copies the web engine process executable. +# - ``icudtl.dat`` +# - ``qtwebengine_devtools_resources.pak`` +# - ``qtwebengine_resources.pak`` +# - ``qtwebengine_resources_100p.pak`` +# - ``qtwebengine_resources_200p.pak`` +# +# This is handled by the ``QtWebEngineCore`` hook, for example ``hook-PyQt5.QtWebEngineCore.py``. +# +# For details and references, see the `original write-up +# `_ +# and the documentation in the ``_modules_info`` module. + + +# QtModuleInfo +# ------------ +# This class contains information about python module (extension), its corresponding Qt module (shared library), and +# associated plugins and translations. It is used within QtLibraryInfo_ to establish name-based mappings for file +# collection. +class QtModuleInfo: + def __init__(self, module, shared_lib=None, translations=None, plugins=None): + # Python module (extension) name without package namespace. For example, `QtCore`. + # Can be None if python bindings do not bind the module, but we still need to establish relationship between + # the Qt module (shared library) and its plugins and translations. + self.module = module + # Associated Qt module (shared library), if any. Used during recursive dependency analysis, where a python + # module (extension) is analyzed for linked Qt modules (shared libraries), and then their corresponding + # python modules (extensions) are added to hidden imports. For example, the Qt module name is `Qt5Core` or + # `Qt6Core`, depending on the Qt version. Can be None for python modules that are not tied to a particular + # Qt shared library (for example, the corresponding Qt module is headers-only) and hence they cannot be + # inferred from recursive link-time dependency analysis. + self.shared_lib = shared_lib + # List of base names of translation files (if any) associated with the Qt module. Multiple base names may be + # associated with a single module. + # For example, `['qt', 'qtbase']` for `QtCore` or `['qtmultimedia']` for `QtMultimedia`. + self.translations = translations or [] + # List of plugins associated with the Qt module. + self.plugins = plugins or [] + + def __repr__(self): + return f"(module={self.module!r}, shared_lib={self.shared_lib!r}, " \ + f"translations={self.translations!r}, plugins={self.plugins!r}" + + +# QtLibraryInfo +# -------------- +# This class uses introspection to determine the location of Qt files. This is essential to deal with the many variants +# of the PyQt5/6 and PySide2/6 package, each of which places files in a different location. Therefore, this class +# provides all location-related members of `QLibraryInfo `_. +class QtLibraryInfo: + def __init__(self, namespace): + if namespace not in ['PyQt5', 'PyQt6', 'PySide2', 'PySide6']: + raise Exception('Invalid namespace: {0}'.format(namespace)) + self.namespace = namespace + # Distinction between PyQt5/6 and PySide2/6 + self.is_pyqt = namespace in {'PyQt5', 'PyQt6'} + # Distinction between Qt5 and Qt6 + self.qt_major = 6 if namespace in {'PyQt6', 'PySide6'} else 5 + # Determine relative path where Qt libraries and data need to be collected in the frozen application. This + # varies between PyQt5/PyQt6/PySide2/PySide6, their versions, and platforms. NOTE: it is tempting to consider + # deriving this path as simply the value of QLibraryInfo.PrefixPath, taken relative to the package's root + # directory. However, we also need to support non-wheel deployments (e.g., with Qt installed in custom path on + # Windows, or with Qt and PyQt5 installed on linux using native package manager), and in those, the Qt + # PrefixPath does not reflect the required relative target path for the frozen application. + if namespace == 'PyQt5': + if self._use_new_layout("PyQt5", "5.15.4", False): + self.qt_rel_dir = os.path.join('PyQt5', 'Qt5') + else: + self.qt_rel_dir = os.path.join('PyQt5', 'Qt') + elif namespace == 'PyQt6': + if self._use_new_layout("PyQt6", "6.0.3", True): + self.qt_rel_dir = os.path.join('PyQt6', 'Qt6') + else: + self.qt_rel_dir = os.path.join('PyQt6', 'Qt') + elif namespace == 'PySide2': + # PySide2 uses PySide2/Qt on linux and macOS, and PySide2 on Windows + if compat.is_win: + self.qt_rel_dir = 'PySide2' + else: + self.qt_rel_dir = os.path.join('PySide2', 'Qt') + else: + # PySide6 follows the same logic as PySide2 + if compat.is_win: + self.qt_rel_dir = 'PySide6' + else: + self.qt_rel_dir = os.path.join('PySide6', 'Qt') + + # Process module information list to construct python-module-name -> info and shared-lib-name -> info mappings. + self._load_module_info() + + def __repr__(self): + return f"QtLibraryInfo({self.namespace})" + + # Delay initialization of the Qt library information until the corresponding attributes are first requested. + def __getattr__(self, name): + if 'version' in self.__dict__: + # Initialization was already done, but requested attribute is not available. + raise AttributeError(name) + + # Load Qt library info... + self._load_qt_info() + # ... and return the requested attribute + return getattr(self, name) + + # Check whether we must use the new layout (e.g. PyQt5/Qt5, PyQt6/Qt6) instead of the old layout (PyQt5/Qt, + # PyQt6/Qt). + @staticmethod + def _use_new_layout(package_basename: str, version: str, fallback_value: bool) -> bool: + # The PyQt wheels come in both non-commercial and commercial variants. So we need to check if a particular + # variant is installed before testing its version. + if hooks.check_requirement(package_basename): + return hooks.check_requirement(f"{package_basename} >= {version}") + if hooks.check_requirement(f"{package_basename}_commercial"): + return hooks.check_requirement(f"{package_basename}_commercial >= {version}") + return fallback_value + + # Load Qt information (called on first access to related fields) + def _load_qt_info(self): + """ + Load and process Qt library information. Called on the first access to the related attributes of the class + (e.g., `version` or `location`). + """ + + # Ensure self.version exists, even if PyQt{5,6}/PySide{2,6} cannot be imported. Hooks and util functions use + # `if .version` to check whether package was imported and other attributes are expected to be available. + # This also serves as a marker that initialization was already done. + self.version = None + + # Get library path information from Qt. See QLibraryInfo_. + @isolated.decorate + def _read_qt_library_info(package): + import os + import sys + import importlib + + # Import the Qt-based package + # equivalent to: from package.QtCore import QLibraryInfo, QCoreApplication + try: + QtCore = importlib.import_module('.QtCore', package) + except ModuleNotFoundError: + return None # Signal that package is unavailable + QLibraryInfo = QtCore.QLibraryInfo + QCoreApplication = QtCore.QCoreApplication + + # QLibraryInfo is not always valid until a QCoreApplication is instantiated. + app = QCoreApplication(sys.argv) # noqa: F841 + + # Qt6 deprecated QLibraryInfo.location() in favor of QLibraryInfo.path(), and + # QLibraryInfo.LibraryLocation enum was replaced by QLibraryInfo.LibraryPath. + if hasattr(QLibraryInfo, 'path'): + # Qt6; enumerate path enum values directly from the QLibraryInfo.LibraryPath enum. + path_names = [x for x in dir(QLibraryInfo.LibraryPath) if x.endswith('Path')] + location = {x: QLibraryInfo.path(getattr(QLibraryInfo.LibraryPath, x)) for x in path_names} + else: + # Qt5; in recent versions, location enum values can be enumeratd from QLibraryInfo.LibraryLocation. + # However, in older versions of Qt5 and its python bindings, that is unavailable. Hence the + # enumeration of "*Path"-named members of QLibraryInfo. + path_names = [x for x in dir(QLibraryInfo) if x.endswith('Path')] + location = {x: QLibraryInfo.location(getattr(QLibraryInfo, x)) for x in path_names} + + # Determine the python-based package location, by looking where the QtCore module is located. + package_location = os.path.dirname(QtCore.__file__) + + # Determine Qt version. Works for Qt 5.8 and later, where QLibraryInfo.version() was introduced. + try: + version = QLibraryInfo.version().segments() + except AttributeError: + version = [] + + return { + 'is_debug_build': QLibraryInfo.isDebugBuild(), + 'version': version, + 'location': location, + 'package_location': package_location, + } + + try: + qt_info = _read_qt_library_info(self.namespace) + except Exception as e: + logger.warning("%s: failed to obtain Qt library info: %s", self, e) + return + + # If package could not be imported, `_read_qt_library_info` returns None. In such cases, emit a debug message + # instead of a warning, because this initialization might be triggered by a helper function that is trying to + # determine availability of bindings by inspecting the `version` attribute of `QtLibraryInfo` for all bindings. + if qt_info is None: + logger.debug("%s: failed to obtain Qt library info: %s.QtCore could not be imported.", self, self.namespace) + return + + for k, v in qt_info.items(): + setattr(self, k, v) + + # Turn package_location into pathlib.Path(), and fully resolve it. + self.package_location = pathlib.Path(self.package_location).resolve() + + # Determine if the Qt is bundled with python package itself; this usually means we are dealing with with PyPI + # wheels. + resolved_qt_prefix_path = pathlib.Path(self.location['PrefixPath']).resolve() + self.qt_inside_package = ( + self.package_location == resolved_qt_prefix_path or # PySide2 and PySide6 Windows PyPI wheels + self.package_location in resolved_qt_prefix_path.parents + ) + + # Determine directory that contains Qt shared libraries. On non-Windows, this is typically location given by + # `LibrariesPath`. On Windows, it is usually `BinariesPath`, except for PySide PyPI wheels, where DLLs are + # placed in top-level `PrefixPath`. + if compat.is_win: + if self.qt_inside_package and not self.is_pyqt: + # Windows PyPI wheel + qt_lib_dir = self.location['PrefixPath'] + else: + qt_lib_dir = self.location['BinariesPath'] + else: + qt_lib_dir = self.location['LibrariesPath'] + self.qt_lib_dir = pathlib.Path(qt_lib_dir).resolve() + + # Module information list loading/processing + def _load_module_info(self): + """ + Process the Qt modules info definition list and construct two dictionaries: + - dictionary that maps Qt python module names to Qt module info entries + - dictionary that maps shared library names to Qt module info entries + """ + + self.python_modules = dict() + self.shared_libraries = dict() + + for entry in _modules_info.QT_MODULES_INFO: + # If entry specifies applicable bindings, check them + if entry.bindings: + applicable_bindings = _modules_info.process_namespace_strings(entry.bindings) + if self.namespace not in applicable_bindings: + continue + + # Create a QtModuleInfo entry + info_entry = QtModuleInfo( + module=entry.module, + shared_lib=f"Qt{self.qt_major}{entry.shared_lib}" if entry.shared_lib else None, + translations=entry.translations, + plugins=entry.plugins + ) + + # If we have python module (extension) name, create python-module-name -> info mapping. + if info_entry.module is not None: + self.python_modules[info_entry.module] = info_entry + + # If we have Qt module (shared library) name, create shared-lib-name -> info mapping. + if info_entry.shared_lib is not None: + self.shared_libraries[info_entry.shared_lib.lower()] = info_entry + + def _normalize_shared_library_name(self, filename): + """ + Normalize a shared library name into common form that we can use for look-ups and comparisons. + Primarily intended for Qt shared library names. + """ + + # Take base name, remove suffix, and lower case it. + lib_name = os.path.splitext(os.path.basename(filename))[0].lower() + # Linux libraries sometimes have a dotted version number -- ``libfoo.so.3``. It is now ''libfoo.so``, + # but the ``.so`` must also be removed. + if compat.is_linux and os.path.splitext(lib_name)[1] == '.so': + lib_name = os.path.splitext(lib_name)[0] + # Remove the "lib" prefix (Linux, macOS). + if lib_name.startswith('lib'): + lib_name = lib_name[3:] + # macOS: handle different naming schemes. PyPI wheels ship framework-enabled Qt builds, where shared + # libraries are part of .framework bundles (e.g., ``PyQt5/Qt5/lib/QtCore.framework/Versions/5/QtCore``). + # In Anaconda (Py)Qt installations, the shared libraries are installed in environment's library directory, + # and contain versioned extensions, e.g., ``libQt5Core.5.dylib``. + if compat.is_darwin: + if lib_name.startswith('qt') and not lib_name.startswith('qt' + str(self.qt_major)): + # Qt library from a framework bundle (e.g., ``QtCore``); change prefix from ``qt`` to ``qt5`` or + # ``qt6`` to match names in Windows/Linux. + lib_name = 'qt' + str(self.qt_major) + lib_name[2:] + if lib_name.endswith('.' + str(self.qt_major)): + # Qt library from Anaconda, which originally had versioned extension, e.g., ``libfoo.5.dynlib``. + # The above processing turned it into ``foo.5``, so we need to remove the last two characters. + lib_name = lib_name[:-2] + + # Handle cases with QT_LIBINFIX set to '_conda', i.e. conda-forge builds. + if lib_name.endswith('_conda'): + lib_name = lib_name[:-6] + + return lib_name + + # Collection + def collect_module(self, module_name): + """ + Collect all dependencies (hiddenimports, binaries, datas) for the given Qt python module. + + This function performs recursive analysis of extension module's link-time dependencies, and uses dictionaries + built by `_load_module_info` to discover associated plugin types, translation file base names, and hidden + imports that need to be collected. + """ + + # Accumulate all dependencies in a set to avoid duplicates. + hiddenimports = set() + translation_base_names = set() + plugin_types = set() + + # Exit if the requested library cannot be imported. + # NOTE: self..version can be empty list on older Qt5 versions (#5381). + if self.version is None: + return [], [], [] + + logger.debug('%s: processing module %s...', self, module_name) + + # Look up the associated Qt module information by python module name. + # This allows us to collect associated module data directly, even if there is no associated shared library + # (e.g., header-only Qt module, or statically-built one). + short_module_name = module_name.split('.', 1)[-1] # PySide2.QtModule -> QtModule + if short_module_name in self.python_modules: + qt_module_info = self.python_modules[short_module_name] + + # NOTE: no need to add a hiddenimport here, because this is the module under consideration. + + # Add plugins + plugin_types.update(qt_module_info.plugins) + + # Add translation base name(s) + translation_base_names.update(qt_module_info.translations) + + # Find the actual module extension file. + module_file = hooks.get_module_file_attribute(module_name) + + # Additional search path for shared library resolution. This is mostly required for library resolution on + # Windows (Linux and macOS binaries use run paths to find Qt libs). + qtlib_search_paths = [ + # For PyQt5 and PyQt6 wheels, shared libraries should be in BinariesPath, while for PySide2 and PySide6, + # they should be in PrefixPath. + self.location['BinariesPath' if self.is_pyqt else 'PrefixPath'], + ] + + # Walk through all the link-time dependencies of a dynamically-linked library (``.so``/``.dll``/``.dylib``). + imported_libraries = bindepend.get_imports(module_file, qtlib_search_paths) + while imported_libraries: + imported_lib_name, imported_lib_path = imported_libraries.pop() # (name, fullpath) tuple + + # Skip unresolved libraries + if imported_lib_path is None: + logger.debug("%s: ignoring unresolved library import %r", self, imported_lib_name) + continue + + # Normalize the shared library name + lib_name = self._normalize_shared_library_name(imported_lib_path) + logger.debug( + '%s: imported library %r, full path %r -> parsed name %r.', self, imported_lib_name, imported_lib_path, + lib_name + ) + + # PySide2 and PySide6 on linux seem to link all extension modules against libQt5Core, libQt5Network, and + # libQt5Qml (or their libQt6* equivalents). While the first two are reasonable, the libQt5Qml dependency + # pulls in whole QtQml module, along with its data and plugins, which in turn pull in several other Qt + # libraries, greatly inflating the bundle size (see #6447). + # + # Similarly, some extension modules (QtWebChannel, QtWebEngine*) seem to be also linked against libQt5Qml, + # even when the module can be used without having the whole QtQml module collected. + # + # Therefore, we explicitly prevent inclusion of QtQml based on the dynamic library dependency, except for + # QtQml* and QtQuick* modules, whose use directly implies the use of QtQml. + if lib_name in ("qt5qml", "qt6qml"): + if not short_module_name.startswith(('QtQml', 'QtQuick')): + logger.debug('%s: ignoring imported library %r.', self, lib_name) + continue + + # Use the parsed library name to look up associated Qt module information. + if lib_name in self.shared_libraries: + logger.debug('%s: collecting Qt module associated with %r.', self, lib_name) + + # Look up associated module info + qt_module_info = self.shared_libraries[lib_name] + + # If there is a python extension module associated with Qt module, add it to hiddenimports. Since this + # means that we (most likely) have a hook available for that module, we can avoid analyzing the shared + # library itself (i.e., stop the recursive analysis), because this will be done by the corresponding + # hook. + if qt_module_info.module: + if qt_module_info.module == short_module_name: + # The one exception is if we are analyzing shared library associated with the input module; in + # that case, avoid adding a hidden import and analyze the library's link-time dependencies. We + # do not need to worry about plugins and translations for this particular module, because those + # have been handled at the beginning of this function. + imported_libraries.update(bindepend.get_imports(imported_lib_path, qtlib_search_paths)) + else: + hiddenimports.add(self.namespace + "." + qt_module_info.module) + continue + + # Add plugins + plugin_types.update(qt_module_info.plugins) + + # Add translation base name(s) + translation_base_names.update(qt_module_info.translations) + + # Analyze the linked shared libraries for its dependencies (recursive analysis). + imported_libraries.update(bindepend.get_imports(imported_lib_path, qtlib_search_paths)) + + # Collect plugin files. + binaries = [] + for plugin_type in plugin_types: + binaries += self.collect_plugins(plugin_type) + + # Collect translation files. + datas = [] + translation_src = self.location['TranslationsPath'] + translation_dst = os.path.join(self.qt_rel_dir, 'translations') + + for translation_base_name in translation_base_names: + # Not all PyQt5 installations include translations. See + # https://github.com/pyinstaller/pyinstaller/pull/3229#issuecomment-359479893 + # and + # https://github.com/pyinstaller/pyinstaller/issues/2857#issuecomment-368744341. + translation_pattern = os.path.join(translation_src, translation_base_name + '_*.qm') + translation_files = glob.glob(translation_pattern) + if translation_files: + datas += [(translation_file, translation_dst) for translation_file in translation_files] + else: + logger.warning( + '%s: could not find translations with base name %r! These translations will not be collected.', + self, translation_base_name + ) + + # Convert hiddenimports to a list. + hiddenimports = list(hiddenimports) + + logger.debug( + '%s: dependencies for %s:\n' + ' hiddenimports = %r\n' + ' binaries = %r\n' + ' datas = %r', self, module_name, hiddenimports, binaries, datas + ) + + return hiddenimports, binaries, datas + + @staticmethod + def _filter_release_plugins(plugin_files): + """ + Filter the provided list of Qt plugin files and remove the debug variants, under the assumption that both the + release version of a plugin (qtplugin.dll) and its debug variant (qtplugind.dll) appear in the list. + """ + # All basenames for lookup + plugin_basenames = {os.path.normcase(os.path.basename(f)) for f in plugin_files} + # Process all given filenames + release_plugin_files = [] + for plugin_filename in plugin_files: + plugin_basename = os.path.normcase(os.path.basename(plugin_filename)) + if plugin_basename.endswith('d.dll'): + # If we can find a variant without trailing 'd' in the plugin list, then the DLL we are dealing with is + # a debug variant and needs to be excluded. + release_name = os.path.splitext(plugin_basename)[0][:-1] + '.dll' + if release_name in plugin_basenames: + continue + release_plugin_files.append(plugin_filename) + return release_plugin_files + + def collect_plugins(self, plugin_type): + """ + Collect all plugins of the specified type from the Qt plugin directory. + + Returns list of (src, dst) tuples. + """ + # Ensure plugin directory exists + plugin_src_dir = self.location['PluginsPath'] + if not os.path.isdir(plugin_src_dir): + raise Exception(f"Qt plugin directory '{plugin_src_dir}' does not exist!") + + # Collect all shared lib files in plugin type (sub)directory + plugin_files = misc.dlls_in_dir(os.path.join(plugin_src_dir, plugin_type)) + + # Windows: + # + # dlls_in_dir() grabs all files ending with ``*.dll``, ``*.so`` and ``*.dylib`` in a certain directory. On + # Windows this would grab debug copies of Qt plugins, which then causes PyInstaller to add a dependency on the + # Debug CRT *in addition* to the release CRT. + if compat.is_win: + plugin_files = self._filter_release_plugins(plugin_files) + + logger.debug("%s: found plugin files for plugin type %r: %r", self, plugin_type, plugin_files) + + plugin_dst_dir = os.path.join(self.qt_rel_dir, 'plugins', plugin_type) + + # Exclude plugins with invalid Qt dependencies. + binaries = [] + for plugin_file in plugin_files: + valid, reason = self._validate_plugin_dependencies(plugin_file) + if valid: + binaries.append((plugin_file, plugin_dst_dir)) + else: + logger.debug("%s: excluding plugin %r (%r)! Reason: %s", self, plugin_file, plugin_type, reason) + return binaries + + def _validate_plugin_dependencies(self, plugin_file): + """ + Validate Qt dependencies of the given Qt plugin file. For the plugin to pass validation, all its Qt dependencies + must be available (resolvable), and must be resolvable from the default Qt shared library directory (to avoid + pulling in libraries from unrelated Qt installations that happen to be in search path). + """ + + imported_libraries = bindepend.get_imports(plugin_file, search_paths=[self.qt_lib_dir]) + for imported_lib_name, imported_lib_path in imported_libraries: + # Parse/normalize the (unresolved) library name, to determine if dependency is a Qt shared library. If not, + # skip the validation. + lib_name = self._normalize_shared_library_name(imported_lib_name) + if not lib_name.startswith(f"qt{self.qt_major}"): + continue + + if imported_lib_path is None: + return False, f"Missing Qt dependency {imported_lib_name!r}." + + imported_lib_path = pathlib.Path(imported_lib_path).resolve() + if self.qt_lib_dir not in imported_lib_path.parents: + return ( + False, + f"Qt dependency {imported_lib_name!r} ({str(imported_lib_path)!r}) has been resolved outside of " + f"the Qt shared library directory ({str(self.qt_lib_dir)!r})." + ) + + return True, None + + def _collect_all_or_none(self, mandatory_dll_patterns, optional_dll_patterns=None): + """ + Try to find Qt DLLs from the specified mandatory pattern list. If all mandatory patterns resolve to DLLs, + collect them all, as well as any DLLs from the optional pattern list. If a mandatory pattern fails to resolve + to a DLL, return an empty list. + + This allows all-or-none collection of particular groups of Qt DLLs that may or may not be available. + """ + optional_dll_patterns = optional_dll_patterns or [] + + # Package parent path; used to preserve the directory structure when DLLs are collected from the python + # package (e.g., PyPI wheels). + package_parent_path = self.package_location.parent + + # On Windows, DLLs are typically placed in `location['BinariesPath']`, except for PySide PyPI wheels, where + # `location['PrefixPath']` is used. This difference is already handled by `qt_lib_dir`, which is also fully + # resolved. + dll_path = self.qt_lib_dir + + # Helper for processing single DLL pattern + def _process_dll_pattern(dll_pattern): + discovered_dlls = [] + + dll_files = dll_path.glob(dll_pattern) + for dll_file in dll_files: + if package_parent_path in dll_file.parents: + # The DLL is located within python package; preserve the layout + dst_dll_dir = dll_file.parent.relative_to(package_parent_path) + else: + # The DLL is not located within python package; collect into top-level directory + dst_dll_dir = '.' + discovered_dlls.append((str(dll_file), str(dst_dll_dir))) + + return discovered_dlls + + # Process mandatory patterns + collected_dlls = [] + for pattern in mandatory_dll_patterns: + discovered_dlls = _process_dll_pattern(pattern) + if not discovered_dlls: + return [] # Mandatory pattern resulted in no DLLs; abort + collected_dlls += discovered_dlls + + # Process optional patterns + for pattern in optional_dll_patterns: + collected_dlls += _process_dll_pattern(pattern) + + return collected_dlls + + # Collect required Qt binaries, but only if all binaries in a group exist. + def collect_extra_binaries(self): + """ + Collect extra binaries/DLLs required by Qt. These include ANGLE DLLs, OpenGL software renderer DLL, and ICU + DLLs. Applicable only on Windows (on other OSes, empty list is returned). + """ + + binaries = [] + + # Applicable only to Windows. + if not compat.is_win: + return [] + + # OpenGL: EGL/GLES via ANGLE, software OpenGL renderer. + binaries += self._collect_all_or_none(['libEGL.dll', 'libGLESv2.dll'], ['d3dcompiler_??.dll']) + binaries += self._collect_all_or_none(['opengl32sw.dll']) + + # Include ICU files, if they exist. + # See the "Deployment approach" section at the top of this file. + binaries += self._collect_all_or_none(['icudt??.dll', 'icuin??.dll', 'icuuc??.dll']) + + return binaries + + # Collect additional shared libraries required for SSL support in QtNetwork, if they are available. + # Primarily applicable to Windows (see issue #3520, #4048). + def collect_qtnetwork_files(self): + """ + Collect extra binaries/shared libraries required by the QtNetwork module, such as OpenSSL shared libraries. + """ + + # No-op if requested Qt-based package is not available. + if self.version is None: + return [] + + # Check if QtNetwork supports SSL and has OpenSSL backend available (Qt >= 6.1). + # Also query the run-time OpenSSL version, so we know what dynamic libraries we need to search for. + @isolated.decorate + def _check_if_openssl_enabled(package): + import sys + import importlib + + # Import the Qt-based package + # equivalent to: from package.QtCore import QCoreApplication + QtCore = importlib.import_module('.QtCore', package) + QCoreApplication = QtCore.QCoreApplication + QLibraryInfo = QtCore.QLibraryInfo + # equivalent to: from package.QtNetwork import QSslSocket + QtNetwork = importlib.import_module('.QtNetwork', package) + QSslSocket = QtNetwork.QSslSocket + + # Instantiate QCoreApplication to suppress warnings + app = QCoreApplication(sys.argv) # noqa: F841 + + if not QSslSocket.supportsSsl(): + return False, None + + # Query the run-time OpenSSL version + openssl_version = QSslSocket.sslLibraryVersionNumber() + + # For Qt >= 6.1, check if `openssl` TLS backend is available + try: + qt_version = QLibraryInfo.version().segments() + except AttributeError: + qt_version = [] # Qt <= 5.8 + + if qt_version < [6, 1]: + return True, openssl_version # TLS backends not implemented yet + + return ('openssl' in QSslSocket.availableBackends(), openssl_version) + + openssl_enabled, openssl_version = _check_if_openssl_enabled(self.namespace) + if not openssl_enabled or openssl_version == 0: + logger.debug("%s: QtNetwork: does not support SSL or does not use OpenSSL.", self) + return [] + + # The actual search is handled in OS-specific ways. + if compat.is_win: + return self._collect_qtnetwork_openssl_windows(openssl_version) + elif compat.is_darwin: + return self._collect_qtnetwork_openssl_macos(openssl_version) + elif compat.is_linux: + return self._collect_qtnetwork_openssl_linux(openssl_version) + else: + logger.warning("%s: QtNetwork: collection of OpenSSL not implemented for this platform!") + return [] + + def _collect_qtnetwork_openssl_windows(self, openssl_version): + """ + Windows-specific collection of OpenSSL DLLs required by QtNetwork module. + """ + + # Package parent path; used to preserve the directory structure when DLLs are collected from the python + # package (e.g., PyPI wheels). + package_parent_path = self.package_location.parent + + # The OpenSSL DLLs might be shipped with PyPI wheel (PyQt5), might be available in the environment (msys2, + # anaconda), or might be expected to be available in the environment (PySide2, PySide6, PyQt6 PyPI wheels). + # + # The OpenSSL DLL naming scheme depends on the version: + # - OpenSSL 1.0.x: libeay32.dll, ssleay32.dll + # - OpenSSL 1.1.x 32-bit: libssl-1_1.dll, libcrypto-1_1.dll + # - OpenSSL 1.1.x 64-bit: libssl-1_1-x64.dll, libcrypto-1_1-x64.dll + # - OpenSSL 3.0.x 32-bit: libssl-1.dll, libcrypto-3.dll + # - OpenSSL 3.0.x 64-bit: libssl-3-x64.dll, libcrypto-3-x64.dll + # + # The official Qt builds (which are used by PySide and PyQt PyPI wheels) seem to be build against: + # - OpenSSL 1.1.x starting with Qt5 5.14.2: + # https://www.qt.io/blog/2019/06/17/qt-5-12-4-released-support-openssl-1-1-1 + # - OpenSSL 3.x starting with Qt6 6.5.0: + # https://www.qt.io/blog/moving-to-openssl-3-in-binary-builds-starting-from-qt-6.5-beta-2 + # + # However, a package can build Qt against OpenSSL version of their own choice. For example, at the time of + # writing, both mingw-w64-x86_64-qt5-base 5.15.11+kde+r138-1 and mingw-w64-x86_64-qt6-base 6.6.0-2 packages + # depend on mingw-w64-x86_64-openssl 3.1.4-1 (so OpenSSL 3). + # + # Luckily, we can query the run-time version of OpenSSL by calling `QSslSocket.sslLibraryVersionNumber()`, + # and narrow down the search for specific version. + if openssl_version >= 0x10000000 and openssl_version < 0x10100000: + # OpenSSL 1.0.x - used by old Qt5 builds + dll_names = ( + 'libeay32.dll', + 'ssleay32.dll', + ) + logger.debug("%s: QtNetwork: looking for OpenSSL 1.0.x DLLs: %r", self, dll_names) + elif openssl_version >= 0x10100000 and openssl_version < 0x30000000: + # OpenSSL 1.1.x + dll_names = ( + 'libssl-1_1-x64.dll' if compat.is_64bits else 'libssl-1_1.dll', + 'libcrypto-1_1-x64.dll' if compat.is_64bits else 'libcrypto-1_1.dll', + ) + logger.debug("%s: QtNetwork: looking for OpenSSL 1.1.x DLLs: %r", self, dll_names) + elif openssl_version >= 0x30000000 and openssl_version < 0x40000000: + # OpenSSL 3.0.x + dll_names = ( + 'libssl-3-x64.dll' if compat.is_64bits else 'libssl-3.dll', + 'libcrypto-3-x64.dll' if compat.is_64bits else 'libcrypto-3.dll', + ) + logger.debug("%s: QtNetwork: looking for OpenSSL 3.0.x DLLs: %r", self, dll_names) + else: + dll_names = [] # Nothing to search for + logger.warning("%s: QtNetwork: unsupported OpenSSL version: %X", self, openssl_version) + + binaries = [] + found_in_package = False + for dll in dll_names: + # Attempt to resolve the DLL path + dll_file_path = bindepend.resolve_library_path(dll, search_paths=[self.qt_lib_dir]) + if dll_file_path is None: + continue + dll_file_path = pathlib.Path(dll_file_path).resolve() + if package_parent_path in dll_file_path.parents: + # The DLL is located within python package; preserve the layout + dst_dll_path = dll_file_path.parent.relative_to(package_parent_path) + found_in_package = True + else: + # The DLL is not located within python package; collect into top-level directory + dst_dll_path = '.' + binaries.append((str(dll_file_path), str(dst_dll_path))) + + # If we found at least one OpenSSL DLL in the bindings' python package directory, discard all external + # OpenSSL DLLs. + if found_in_package: + binaries = [(dll_src_path, dll_dest_path) for dll_src_path, dll_dest_path in binaries + if package_parent_path in pathlib.Path(dll_src_path).parents] + + return binaries + + def _collect_qtnetwork_openssl_macos(self, openssl_version): + """ + macOS-specific collection of OpenSSL dylibs required by QtNetwork module. + """ + + # The official Qt5 builds on macOS (shipped by PyPI wheels) appear to be built with Apple's SecureTransport API + # instead of OpenSSL; for example, `QSslSocket.sslLibraryVersionNumber` returns 0, while + # `sslLibraryVersionString()` returns "Secure Transport, macOS 12.6". So with PySide2 and PyQt5, we do not need + # to worry about collection of OpenSSL shared libraries. + # + # Support for OpenSSL was introduced in Qt 6.1 with `openssl` TLS backend; the official Qt6 builds prior to 6.5 + # seem to be built with OpenSSL 1.1.x, and later versions with 3.0.x. However, PySide6 and PyQt6 PyPI wheels do + # not ship OpenSSL dynamic libraries at all , so whether `openssl` TLS backend is used or not depends on the + # presence of externally provided OpenSSL dynamic libraries (for example, provided by Homebrew). It is worth + # noting that python.org python installers *do* provide OpenSSL shared libraries (1.1.x for python <= 3.10, + # 3.0.x for python >= 3.12, and both for python 3.11) for its `_ssl` extension - however, these are NOT visible + # to Qt and its QtNetwork module. + # + # When the frozen application is built and we collect python's `_ssl` extension, we also collect the OpenSSL + # shared libraries shipped by python. So at least in theory, those should be available to QtNetwork module as + # well (assuming they are of compatible version). However, this is not exactly the case - QtNetwork looks for + # the libraries in locations given by `DYLD_LIBRARY_PATH` environment variable and in .app/Contents/Frameworks + # (if the program is an .app bundle): + # + # https://github.com/qt/qtbase/blob/6.6.0/src/plugins/tls/openssl/qsslsocket_openssl_symbols.cpp#L590-L599 + # + # So it works out-of-the box for our .app bundles, because starting with PyInstaller 6.0, `sys._MEIPASS` is in + # .app/Contents/Frameworks. But it does not with POSIX builds, because bootloader does not modify the + # `DYLD_LIBRARY_PATH` environment variable to include `sys._MEIPASS` (since we usually do not need that; + # regular linked library resolution in our macOS builds is done via path rewriting and rpaths). So either we + # need a run-time hook to add `sys._MEIPASS` to `DYLD_LIBRARY_PATH`, or modify the bootloader to always do that. + # + # Collecting the OpenSSL library and making it discoverable by adding `sys._MEIPASS` to `DYLD_LIBRARY_PATH` + # should also prevent QtNetwork from "accidentally" pulling in Homebrew version at run-time (if Homebrew is + # installed on the target system and provides compatible OpenSSL version). + # + # Therefore, try to resolve OpenSSL library via the version indicated by `QSslSocket.sslLibraryVersionNumber`; + # however, we first explicitly search only {sys.base_prefix}/lib (which is where python.org builds put their + # dynamic libs), and only if that fails, perform regular dylib path resolution. This way we ensure that if the + # OpenSSL dylibs are provided by python itself, we always prefer those over the Homebrew version (since we are + # very likely going to collect them for python's `_ssl` extension anyway). + + # As per above text, we need to worry only about Qt6, and thus OpenSSL 1.1.x or 3.0.x + if openssl_version >= 0x10100000 and openssl_version < 0x30000000: + # OpenSSL 1.1.x + dylib_names = ( + 'libcrypto.1.1.dylib', + 'libssl.1.1.dylib', + ) + logger.debug("%s: QtNetwork: looking for OpenSSL 1.1.x dylibs: %r", self, dylib_names) + elif openssl_version >= 0x30000000 and openssl_version < 0x40000000: + # OpenSSL 3.0.x + dylib_names = ( + 'libcrypto.3.dylib', + 'libssl.3.dylib', + ) + logger.debug("%s: QtNetwork: looking for OpenSSL 3.0.x dylibs: %r", self, dylib_names) + else: + dylib_names = [] # Nothing to search for + logger.warning("%s: QtNetwork: unsupported OpenSSL version: %X", self, openssl_version) + + # Compared to Windows, we do not have to worry about dylib's path preservation, as these are never part of + # the package, and are therefore always collected to the top-level application directory. + binaries = [] + base_prefix_lib_dir = os.path.join(compat.base_prefix, 'lib') + for dylib in dylib_names: + # First, attempt to resolve using only {sys.base_prefix}/lib - `bindepend.resolve_library_path` uses + # standard dyld search semantics and uses the given search paths as fallback (and would therefore + # favor Homebrew-provided version of the library). + dylib_path = bindepend._resolve_library_path_in_search_paths(dylib, search_paths=[base_prefix_lib_dir]) + if dylib_path is None: + dylib_path = bindepend.resolve_library_path(dylib, search_paths=[base_prefix_lib_dir, self.qt_lib_dir]) + if dylib_path is None: + continue + binaries.append((str(dylib_path), '.')) + + return binaries + + def _collect_qtnetwork_openssl_linux(self, openssl_version): + """ + Linux-specific collection of OpenSSL dylibs required by QtNetwork module. + """ + + # Out of the supported OSes, Linux is by far the most straight-forward, because OpenSSL shared libraries are + # expected to be provided by the system. So we can just use standard library path resolution with library names + # inferred from the run-time OpenSSL version. At run-time, QtNetwork searches paths from `LD_LIBRARY_PATH`, and + # on Linux, our bootloader already adds `sys._MEIPASS` to that environment variable. + + if openssl_version >= 0x10000000 and openssl_version < 0x10100000: + # OpenSSL 1.0.x - used by old Qt5 builds + shlib_names = ( + 'libcrypto.so.10', + 'libssl.so.10', + ) + logger.debug("%s: QtNetwork: looking for OpenSSL 1.0.x shared libraries: %r", self, shlib_names) + elif openssl_version >= 0x10100000 and openssl_version < 0x30000000: + # OpenSSL 1.1.x + shlib_names = ( + 'libcrypto.so.1.1', + 'libssl.so.1.1', + ) + logger.debug("%s: QtNetwork: looking for OpenSSL 1.1.x shared libraries: %r", self, shlib_names) + elif openssl_version >= 0x30000000 and openssl_version < 0x40000000: + # OpenSSL 3.0.x + shlib_names = ( + 'libcrypto.so.3', + 'libssl.so.3', + ) + logger.debug("%s: QtNetwork: looking for OpenSSL 3.0.x shared libraries: %r", self, shlib_names) + else: + shlib_names = [] # Nothing to search for + logger.warning("%s: QtNetwork: unsupported OpenSSL version: %X", self, openssl_version) + + binaries = [] + for shlib in shlib_names: + shlib_path = bindepend.resolve_library_path(shlib) + if shlib_path is None: + continue + binaries.append((str(shlib_path), '.')) + + return binaries + + def collect_qtqml_files(self): + """ + Collect additional binaries and data for QtQml module. + """ + + # No-op if requested Qt-based package is not available. + if self.version is None: + return [], [] + + # Not all PyQt5/PySide2 installs have QML files. In this case, location['Qml2ImportsPath'] is empty. + # Furthermore, even if location path is provided, the directory itself may not exist. + # + # https://github.com/pyinstaller/pyinstaller/pull/3229#issuecomment-359735031 + # https://github.com/pyinstaller/pyinstaller/issues/3864 + # + # In Qt 6, Qml2ImportsPath was deprecated in favor of QmlImportsPath. The former is not available in PySide6 + # 6.4.0 anymore (but is in PyQt6 6.4.0). Use the new QmlImportsPath if available. + if 'QmlImportsPath' in self.location: + qml_src_dir = self.location['QmlImportsPath'] + else: + qml_src_dir = self.location['Qml2ImportsPath'] + if not qml_src_dir or not os.path.isdir(qml_src_dir): + logger.warning('%s: QML directory %r does not exist. QML files not packaged.', self, qml_src_dir) + return [], [] + + qml_src_path = pathlib.Path(qml_src_dir).resolve() + qml_dest_path = pathlib.PurePath(self.qt_rel_dir) / 'qml' + + binaries = [] + datas = [] + + # Helper that computes the destination directory for the given file or directory from a QML plugin directory. + def _compute_dest_dir(src_filename): + if src_filename.is_dir(): + rel_path = src_filename.relative_to(qml_src_path) + else: + rel_path = src_filename.relative_to(qml_src_path).parent + return qml_dest_path / rel_path + + # Discover all QML plugin sub-directories by searching for `qmldir` files. + qmldir_files = qml_src_path.rglob('**/qmldir') + for qmldir_file in sorted(qmldir_files): + plugin_dir = qmldir_file.parent + logger.debug("%s: processing QML plugin directory %s", self, plugin_dir) + + try: + # Obtain lists of source files (separated into binaries and data files). + plugin_binaries, plugin_datas = self._process_qml_plugin(qmldir_file) + # Convert into (src, dest) tuples. + binaries += [(str(src_file), str(_compute_dest_dir(src_file))) for src_file in plugin_binaries] + datas += [(str(src_file), str(_compute_dest_dir(src_file))) for src_file in plugin_datas] + except Exception: + logger.warning("%s: failed to process QML plugin directory %s", self, plugin_dir, exc_info=True) + + return binaries, datas + + # https://doc.qt.io/qt-6/qtqml-modules-qmldir.html#plugin-declaration + # [optional] plugin [ + _qml_plugin_def = re.compile(r"^(?:(?:optional)\s+)?(?:plugin)\s+(?P\w+)(?:\s+(?P\.+))?$") + + def _process_qml_plugin(self, qmldir_file): + """ + Processes the QML directory corresponding to the given `qmldir` file. + + Returns lists of binaries and data files, but only the source file names. It is up to caller to turn these into + lists of (src, dest) tuples. + """ + plugin_dir = qmldir_file.parent + + plugin_binaries = set() + + # Read the `qmldir` file to determine the names of plugin binaries, if any. + contents = qmldir_file.read_text(encoding="utf-8") + for line in contents.splitlines(): + m = self._qml_plugin_def.match(line) + if m is None: + continue + + plugin_name = m.group("name") + plugin_path = m.group("path") + + # We currently do not support custom plugin path - neither relative nor absolute (the latter will never + # be supported, because to make it relocatable, we would need to modify the `qmpldir file`). + if plugin_path is not None: + raise Exception(f"Non-empty plugin path ({plugin_path!r} is not supported yet!") + + # Turn the plugin base name into actual shared lib name. + if compat.is_linux: + plugin_file = plugin_dir / f"lib{plugin_name}.so" + elif compat.is_win: + plugin_file = plugin_dir / f"{plugin_name}.dll" + elif compat.is_darwin: + plugin_file = plugin_dir / f"lib{plugin_name}.dylib" + else: + continue # This implicitly disables subsequent validation on unhandled platforms. + + # Warn if plugin file does not exist + if not plugin_file.is_file(): + logger.warn("%s: QML plugin binary %r does not exist!", str(plugin_file)) + continue + + plugin_binaries.add(plugin_file) + + # Exclude plugins with invalid Qt dependencies. + invalid_binaries = False + for plugin_binary in plugin_binaries: + valid, reason = self._validate_plugin_dependencies(plugin_binary) + if not valid: + logger.debug("%s: excluding QML plugin binary %r! Reason: %s", self, str(plugin_binary), reason) + invalid_binaries = True + + # If there was an invalid binary, discard the plugin. + if invalid_binaries: + logger.debug("%s: excluding QML plugin directory %r due to invalid plugin binaries!", self, str(plugin_dir)) + return [], [] + + # Generate binaries list. + binaries = sorted(plugin_binaries) + + # Generate list of data files - all content of this directory, except for the plugin binaries. Sub-directories + # are included if they do not contain a `qmldir` file (we do not recurse into the directory, but instead pass + # only its name, leaving the recursion to PyInstaller's built-in expansion of paths returned by hooks). + datas = [] + for entry in plugin_dir.iterdir(): + if entry.is_file(): + if entry in plugin_binaries: + continue + else: + if (entry / "qmldir").is_file(): + continue + datas.append(entry) + + return binaries, datas + + def collect_qtwebengine_files(self): + """ + Collect QtWebEngine helper process executable, translations, and resources. + """ + + binaries = [] + datas = [] + + # Output directory (varies between PyQt and PySide and among OSes; the difference is abstracted by + # QtLibraryInfo.qt_rel_dir) + rel_data_path = self.qt_rel_dir + + is_macos_framework = False + if compat.is_darwin: + # Determine if we are dealing with a framework-based Qt build (e.g., PyPI wheels) or a dylib-based one + # (e.g., Anaconda). The former requires special handling, while the latter is handled in the same way as + # Windows and Linux builds. + is_macos_framework = os.path.exists( + os.path.join(self.location['LibrariesPath'], 'QtWebEngineCore.framework') + ) + + if is_macos_framework: + # macOS .framework bundle + src_framework_path = os.path.join(self.location['LibrariesPath'], 'QtWebEngineCore.framework') + + # If Qt libraries are bundled with the package, collect the .framework bundle into corresponding package's + # subdirectory, because binary dependency analysis will also try to preserve the directory structure. + # However, if we are collecting from system-wide Qt installation (e.g., Homebrew-installed Qt), the binary + # depndency analysis will attempt to re-create .framework bundle in top-level directory, so we need to + # collect the extra files there. + bundled_qt_libs = pathlib.Path(self.package_location) in pathlib.Path(src_framework_path).parents + if bundled_qt_libs: + dst_framework_path = os.path.join(rel_data_path, 'lib/QtWebEngineCore.framework') + else: + dst_framework_path = 'QtWebEngineCore.framework' # In top-level directory + + # Determine the version directory - for now, we assume we are dealing with single-version framework; + # i.e., the Versions directory contains only a single directory, and Current symlink to it. + versions = sorted([ + version for version in os.listdir(os.path.join(src_framework_path, 'Versions')) if version != 'Current' + ]) + if len(versions) == 0: + raise RuntimeError("Could not determine version of the QtWebEngineCore.framework!") + elif len(versions) > 1: + logger.warning( + "Found multiple versions in QtWebEngineCore.framework (%r) - using the last one!", versions + ) + version = versions[-1] + + # Collect the Helpers directory. In well-formed .framework bundles (such as the ones provided by Homebrew), + # the Helpers directory is located in the versioned directory, and symlinked to the top-level directory. + src_helpers_path = os.path.join(src_framework_path, 'Versions', version, 'Helpers') + dst_helpers_path = os.path.join(dst_framework_path, 'Versions', version, 'Helpers') + if not os.path.exists(src_helpers_path): + # Alas, the .framework bundles shipped with contemporary PyPI PyQt/PySide wheels are not well-formed + # (presumably because .whl cannot preserve symlinks?). The Helpers in the top-level directory is in fact + # the hard copy, and there is either no Helpers in versioned directory, or there is a duplicate. + # So fall back to collecting from the top-level, but collect into versioned directory in order to + # be compliant with codesign's expectations. + src_helpers_path = os.path.join(src_framework_path, 'Helpers') + + helper_datas = hooks.collect_system_data_files(src_helpers_path, dst_helpers_path) + + # Filter out the actual helper executable from datas, and add it to binaries instead. This ensures that it + # undergoes additional binary processing that rewrites the paths to linked libraries. + HELPER_EXE = 'QtWebEngineProcess.app/Contents/MacOS/QtWebEngineProcess' + for src_name, dest_name in helper_datas: + if src_name.endswith(HELPER_EXE): + binaries.append((src_name, dest_name)) + else: + datas.append((src_name, dest_name)) + + # Collect the Resources directory; same logic is used as with Helpers directory. + src_resources_path = os.path.join(src_framework_path, 'Versions', version, 'Resources') + dst_resources_path = os.path.join(dst_framework_path, 'Versions', version, 'Resources') + if not os.path.exists(src_resources_path): + src_resources_path = os.path.join(src_framework_path, 'Resources') + + datas += hooks.collect_system_data_files(src_resources_path, dst_resources_path) + + # NOTE: the QtWebEngineProcess helper is actually sought within the `QtWebEngineCore.framework/Helpers`, + # which ought to be a symlink to `QtWebEngineCore.framework/Versions/Current/Helpers`, where `Current` + # is also a symlink to the actual version directory, `A`. + # + # These symlinks are created automatically when the TOC list of collected resources is post-processed + # using `PyInstaller.utils.osx.collect_files_from_framework_bundles` helper, so we do not have to + # worry about them here... + else: + # Windows and linux (or Anaconda on macOS) + locales = 'qtwebengine_locales' + resources = 'resources' + + # Translations + datas.append(( + os.path.join(self.location['TranslationsPath'], locales), + os.path.join(rel_data_path, 'translations', locales), + )) + + # Resources; ``DataPath`` is the base directory for ``resources``, as per the + # `docs `_. + datas.append((os.path.join(self.location['DataPath'], resources), os.path.join(rel_data_path, resources)),) + + # Helper process executable (QtWebEngineProcess), located in ``LibraryExecutablesPath``. + # The target directory is determined as `LibraryExecutablesPath` relative to `PrefixPath`. On Windows, + # this should handle the differences between PySide2/PySide6 and PyQt5/PyQt6 PyPI wheel layout. + rel_helper_path = os.path.relpath(self.location['LibraryExecutablesPath'], self.location['PrefixPath']) + + # However, on Linux, we need to account for distribution-packaged Qt, where `LibraryExecutablesPath` might + # be nested deeper under `PrefixPath` than anticipated (w.r.t. PyPI wheel layout). For example, in Fedora, + # the helper is located under `/usr/lib64/qt5/libexec/QtWebEngineProcess`, with `PrefixPath` being `/usr` + # and `LibraryExecutablesPath` being `/usr/lib64/qt5/libexec/`, so the relative path ends up being + # `lib64/qt5/libexec` instead of just `libexec`. So on linux, we explicitly force the PyPI-compliant + # layout, by overriding relative helper path to just `libexec`. + if compat.is_linux and rel_helper_path != "libexec": + logger.info( + "%s: overriding relative destination path of QtWebEngineProcess helper from %r to %r!", self, + rel_helper_path, "libexec" + ) + rel_helper_path = "libexec" + + # Similarly, force the relative helper path for PySide2/PySide6 on Windows to `.`. This is already the case + # with PyPI PySide Windows wheels. But it is not the case with conda-installed PySide2, where the Qt's + # `PrefixPath` is for example `C:/Users//miniconda3/envs//Library`, while the corresponding + # `LibraryExecutablesPath` is `C:/Users//miniconda3/envs//Library/bin`. + if compat.is_win and not self.is_pyqt and rel_helper_path != ".": + logger.info( + "%s: overriding relative destination path of QtWebEngineProcess helper from %r to %r!", self, + rel_helper_path, "." + ) + rel_helper_path = "." + + dest = os.path.normpath(os.path.join(rel_data_path, rel_helper_path)) + binaries.append((os.path.join(self.location['LibraryExecutablesPath'], 'QtWebEngineProcess*'), dest)) + + # The helper QtWebEngineProcess executable should have an accompanying qt.conf file that helps it locate the + # Qt shared libraries. Try collecting it as well + qt_conf_file = os.path.join(self.location['LibraryExecutablesPath'], 'qt.conf') + if not os.path.isfile(qt_conf_file): + # The file seems to have been dropped from Qt 6.3 (and corresponding PySide6 and PyQt6) due to + # redundancy; however, we still need it in the frozen application - so generate our own. + from PyInstaller.config import CONF # workpath + # Relative path to root prefix of bundled Qt - this corresponds to the "inverse" of `rel_helper_path` + # variable that we computed earlier. + if rel_helper_path == '.': + rel_prefix = '.' + else: + # Replace each directory component in `rel_helper_path` with `..`. + rel_prefix = os.path.join(*['..' for _ in range(len(rel_helper_path.split(os.pathsep)))]) + # We expect the relative path to be either . or .. depending on PySide/PyQt layout; if that is not the + # case, warn about irregular path. + if rel_prefix not in ('.', '..'): + logger.warning( + "%s: unexpected relative Qt prefix path for QtWebEngineProcess qt.conf: %s", self, rel_prefix + ) + # The Qt docs on qt.conf (https://doc.qt.io/qt-5/qt-conf.html) recommend using forward slashes on + # Windows as well, due to backslash having to be escaped. This should not matter as we expect the + # relative path to be . or .., but you never know... + if os.sep == '\\': + rel_prefix = rel_prefix.replace(os.sep, '/') + # Create temporary file in workpath + qt_conf_file = os.path.join(CONF['workpath'], "qt.conf") + with open(qt_conf_file, 'w', encoding='utf-8') as fp: + print("[Paths]", file=fp) + print("Prefix = {}".format(rel_prefix), file=fp) + datas.append((qt_conf_file, dest)) + + # Add Linux-specific libraries. + if compat.is_linux: + # The automatic library detection fails for `NSS `_, + # which is used by QtWebEngine. In some distributions, the ``libnss`` supporting libraries are stored in a + # subdirectory ``nss``. Since ``libnss`` is not linked against them but loads them dynamically at run-time, + # we need to search for and add them. + # + # Specifically, the files we are looking for are + # - libfreebl3.so + # - libfreeblpriv3.so + # - libnssckbi.so + # - libnssdbm3.so + # - libsoftokn3.so + # and they might be in the same directory as ``libnss3.so`` (instead of ``nss`` subdirectory); this is + # the case even with contemporary Debian releases. See + # https://packages.debian.org/bullseye/amd64/libnss3/filelist + # vs. + # https://packages.debian.org/bookworm/amd64/libnss3/filelist + + # Analyze imports of ``QtWebEngineCore`` extension module, and look for ``libnss3.so`` to determine its + # parent directory. + libnss_dir = None + module_file = hooks.get_module_file_attribute(self.namespace + '.QtWebEngineCore') + for lib_name, lib_path in bindepend.get_imports(module_file): # (name, fullpath) tuples + if lib_path is None: + continue # Skip unresolved libraries + # Look for ``libnss3.so``. + if os.path.basename(lib_path).startswith('libnss3.so'): + libnss_dir = os.path.dirname(lib_path) + break + + # Search for NSS libraries + logger.debug("%s: QtWebEngineCore is linked against libnss3.so; collecting NSS libraries...", self) + if libnss_dir is not None: + # Libraries to search for + NSS_LIBS = [ + 'libfreebl3.so', + 'libfreeblpriv3.so', + 'libnssckbi.so', + 'libnssdbm3.so', + 'libsoftokn3.so', + ] + # Directories (relative to `libnss_dir`) to search in. Also serve as relative destination paths. + NSS_LIB_SUBDIRS = [ + 'nss', + '.', + ] + + for subdir in NSS_LIB_SUBDIRS: + for lib_name in NSS_LIBS: + lib_file = os.path.normpath(os.path.join(libnss_dir, subdir, lib_name)) + if os.path.isfile(lib_file): + logger.debug("%s: collecting NSS library: %r", self, lib_file) + binaries.append((lib_file, subdir)) + + return binaries, datas + + +# Provide single instances of this class to avoid each hook constructing its own. +pyqt5_library_info = QtLibraryInfo('PyQt5') +pyqt6_library_info = QtLibraryInfo('PyQt6') +pyside2_library_info = QtLibraryInfo('PySide2') +pyside6_library_info = QtLibraryInfo('PySide6') + + +def get_qt_library_info(namespace): + """ + Return QtLibraryInfo instance for the given namespace. + """ + if namespace == 'PyQt5': + return pyqt5_library_info + if namespace == 'PyQt6': + return pyqt6_library_info + elif namespace == 'PySide2': + return pyside2_library_info + elif namespace == 'PySide6': + return pyside6_library_info + + raise ValueError(f'Invalid namespace: {namespace}!') + + +# add_qt_dependencies +# -------------------- +# Generic implemnentation that finds the Qt 5/6 dependencies based on the hook name of a PyQt5/PyQt6/PySide2/PySide6 +# hook. Returns (hiddenimports, binaries, datas). Typical usage: +# ``hiddenimports, binaries, datas = add_qt5_dependencies(__file__)``. +def add_qt_dependencies(hook_file): + # Find the module underlying this Qt hook: change ``/path/to/hook-PyQt5.blah.py`` to ``PyQt5.blah``. + hook_name, hook_ext = os.path.splitext(os.path.basename(hook_file)) + assert hook_ext.startswith('.py') + assert hook_name.startswith('hook-') + module_name = hook_name[5:] + namespace = module_name.split('.')[0] + + # Retrieve Qt library info structure.... + qt_info = get_qt_library_info(namespace) + # ... and use it to collect module dependencies + return qt_info.collect_module(module_name) + + +# add_qt5_dependencies +# -------------------- +# Find the Qt5 dependencies based on the hook name of a PySide2/PyQt5 hook. Returns (hiddenimports, binaries, datas). +# Typical usage: ``hiddenimports, binaries, datas = add_qt5_dependencies(__file__)``. +add_qt5_dependencies = add_qt_dependencies # Use generic implementation + +# add_qt6_dependencies +# -------------------- +# Find the Qt6 dependencies based on the hook name of a PySide6/PyQt6 hook. Returns (hiddenimports, binaries, datas). +# Typical usage: ``hiddenimports, binaries, datas = add_qt6_dependencies(__file__)``. +add_qt6_dependencies = add_qt_dependencies # Use generic implementation + + +# A helper for ensuring that only one Qt bindings package is collected into frozen application. Intended to be called +# from hooks for top-level bindings packages. +def ensure_single_qt_bindings_package(qt_bindings): + # For the lack of better alternative, use CONF structure. Note that this enforces single bindings for the whole + # spec file instead of individual Analysis instances! + from PyInstaller.config import CONF + + seen_qt_bindings = CONF.get("_seen_qt_bindings") + if seen_qt_bindings is None: + CONF["_seen_qt_bindings"] = qt_bindings + elif qt_bindings != seen_qt_bindings: + # Raise SystemExit to abort build process + raise SystemExit( + "Aborting build process due to attempt to collect multiple Qt bindings packages: attempting to run hook " + f"for {qt_bindings!r}, while hook for {seen_qt_bindings!r} has already been run! PyInstaller does not " + "support multiple Qt bindings packages in a frozen application - either ensure that the build environment " + "has only one Qt bindings package installed, or exclude the extraneous bindings packages via the module " + "exclusion mechanism (--exclude command-line option, or excludes list in the spec file)." + ) + + +# A helper for generating exclude rules for extraneous Qt bindings. Intended for use in hooks for packages that pull in +# multiple Qt bindings packages due to conditional imports (for example, `matplotlib.backends.qt_compat`, `qtpy`). +def exclude_extraneous_qt_bindings(hook_name, qt_bindings_order=None): + _QT_BINDINGS = ['PyQt5', 'PySide2', 'PyQt6', 'PySide6'] # Known bindings, and also their preferred order + _QT_API_ENV = 'QT_API' + + def _create_excludes(selected_bindings): + return [bindings for bindings in _QT_BINDINGS if bindings != selected_bindings] + + logger.debug("%s: selecting Qt bindings package...", hook_name) + + if not qt_bindings_order: + qt_bindings_order = _QT_BINDINGS # Use default preference order + + env_qt_bindings = os.environ.get(_QT_API_ENV) + if env_qt_bindings is not None and env_qt_bindings not in _QT_BINDINGS: + logger.warning( + "%s: ignoring unsupported Qt bindings specified via %s environment variable (supported values: %r)!", + hook_name, _QT_API_ENV, _QT_BINDINGS + ) + env_qt_bindings = None + + # First choice: see if a hook for top-level Qt bindings package has already been run; if it has, use that bindings + # package. Due to check in the `ensure_single_qt_bindings_package` that these hooks use, only one such hook could + # have been run. This should cover cases when the entry-point script explicitly imports one of Qt bindings before + # importing a package that supports multiple bindings. + from PyInstaller.config import CONF + seen_qt_bindings = CONF.get("_seen_qt_bindings") + if seen_qt_bindings is not None: + # If bindings are also specified via environment variable and they differ, display a warning. + if env_qt_bindings is not None and env_qt_bindings != seen_qt_bindings: + logger.warning( + "%s: ignoring %s environment variable (%r) because hook for %r has been run!", hook_name, _QT_API_ENV, + env_qt_bindings, seen_qt_bindings + ) + + logger.info( + "%s: selected %r as Qt bindings because hook for %r has been run before.", hook_name, seen_qt_bindings, + seen_qt_bindings + ) + return _create_excludes(seen_qt_bindings) + + # Second choice: honor the QT_API environment variable, if it specified a valid Qt bindings package. + if env_qt_bindings is not None: + logger.info( + "%s: selected %r as Qt bindings as specified by the %s environment variable.", hook_name, env_qt_bindings, + _QT_API_ENV + ) + return _create_excludes(env_qt_bindings) + + # Third choice: select first available bindings (sorted by the given preference order), and display a warning if + # multiple bindings are available. + available_qt_bindings = [] + for bindings_name in qt_bindings_order: + # Check if bindings are available + info = get_qt_library_info(bindings_name) + if info.version is None: + continue + available_qt_bindings.append(bindings_name) + + if not available_qt_bindings: + logger.warning("%s: no Qt bindings are available!", hook_name) + return [] # No need to generate any excludes... + + selected_qt_bindings = available_qt_bindings[0] + if len(available_qt_bindings) == 1: + logger.info("%s: selected %r as the only available Qt bindings.", hook_name, selected_qt_bindings) + else: + # Warn on multiple bindings, and tell user to use QT_API environment variable + logger.warning( + "%s: selected %r as Qt bindings, but multiple bindings are available: %r. Use the %s environment variable " + "to select different bindings and suppress this warning.", hook_name, selected_qt_bindings, + available_qt_bindings, _QT_API_ENV + ) + return _create_excludes(selected_qt_bindings) diff --git a/venv/Lib/site-packages/PyInstaller/utils/hooks/qt/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/utils/hooks/qt/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..e2921aa Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/utils/hooks/qt/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/utils/hooks/qt/__pycache__/_modules_info.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/utils/hooks/qt/__pycache__/_modules_info.cpython-311.pyc new file mode 100644 index 0000000..0de7661 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/utils/hooks/qt/__pycache__/_modules_info.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/utils/hooks/qt/_modules_info.py b/venv/Lib/site-packages/PyInstaller/utils/hooks/qt/_modules_info.py new file mode 100644 index 0000000..c68a4b7 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/utils/hooks/qt/_modules_info.py @@ -0,0 +1,450 @@ +# ---------------------------------------------------------------------------- +# Copyright (c) 2022-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) +#----------------------------------------------------------------------------- + +# Qt modules information - the core of our Qt collection approach +# ---------------------------------------------------------------- +# +# The python bindings for Qt (``PySide2``, ``PyQt5``, ``PySide6``, ``PyQt6``) consist of several python binary extension +# modules that provide bindings for corresponding Qt modules. For example, the ``PySide2.QtNetwork`` python extension +# module provides bindings for the ``QtNetwork`` Qt module from the ``qt/qtbase`` Qt repository. +# +# A Qt module can be considered as consisting of: +# * a shared library (for example, on Linux, the shared library names for the ``QtNetwork`` Qt module in Qt5 and Qt6 +# are ``libQt5Network.so`` and ``libQt6Network.so``, respectively). +# * plugins: a certain type (or class) of plugins is usually associated with a single Qt module (for example, +# ``imageformats`` plugins are associated with the ``QtGui`` Qt module from the ``qt/qtbase`` Qt repository), but +# additional plugins of that type may come from other Qt repositories. For example, ``imageformats/qsvg`` plugin +# is provided by ``qtsvg/src/plugins/imageformats/svg`` from the ``qt/qtsvg`` repository, and ``imageformats/qpdf`` +# is provided by ``qtwebengine/src/pdf/plugins/imageformats/pdf`` from the ``qt/qtwebengine`` repository. +# * translation files: names of translation files consist of a base name, which typically corresponds to the Qt +# repository name, and language code. A single translation file usually covers all Qt modules contained within +# the same repository. For example, translation files with base name ``qtbase`` contain translations for ``QtCore``, +# ``QtGui``, ``QtWidgets``, ``QtNetwork``, and other Qt modules from the ``qt/qtbase`` Qt repository. +# +# The PyInstaller's built-in analysis of link-time dependencies ensures that when collecting a Qt python extension +# module, we automatically pick up the linked Qt shared libraries. However, collection of linked Qt shared libraries +# does not result in collection of plugins, nor translation files. In addition, the dependency of a Qt python extension +# module on other Qt python extension modules (i.e., at the bindings level) cannot be automatically determined due to +# PyInstaller's inability to scan imports in binary extensions. +# +# PyInstaller < 5.7 solved this problem using a dictionary that associated a Qt shared library name with python +# extension name, plugins, and translation files. For each hooked Qt python extension module, the hook calls a helper +# that analyzes the extension file for link-time dependencies, and matches those against the dictionary. Therefore, +# based on linked shared libraries, we could recursively infer the list of files to collect in addition to the shared +# libraries themselves: +# - plugins and translation files belonging to Qt modules whose shared libraries we collect +# - Qt python extension modules corresponding to the Qt modules that we collect +# +# The above approach ensures that even if analyzed python script contains only ``from PySide2 import QtWidgets``, +# we would also collect ``PySide2.QtGui`` and ``PySide2.QtCore``, as well as all corresponding Qt module files +# (the shared libraries, plugins, translation files). For this to work, a hook must be provided for the +# ``PySide2.QtWidgets`` that performs the recursive analysis of the extension module file; so to ensure that each +# Qt python extension module by itself ensures collection of all its dependencies, we need to hook all Qt python +# extension modules provided by specific python Qt bindings package. +# +# The above approach with single dictionary, however, has several limitations: +# - it cannot provide association for Qt python module that binds a Qt module without a shared library (i.e., a +# headers-only module, or a statically-built module). In such cases, potential plugins and translations should +# be associated directly with the Qt python extension file instead of the Qt module's (non-existent) shared library. +# - it cannot (directly) handle differences between Qt5 and Qt6; we had to build a second dictionary +# - it cannot handle differences between the bindings themselves; for example, PyQt5 binds some Qt modules that +# PySide2 does not bind. Or, the binding's Qt python extension module is named differently in PyQt and PySide +# bindings (or just differently in PyQt5, while PySide2, PySide6, and PyQt6 use the same name). +# +# In order address the above shortcomings, we now store all information a list of structures that contain information +# for a particular Qt python extension and/or Qt module (shared library): +# - python extension name (if applicable) +# - Qt module name base (if applicable) +# - plugins +# - translation files base name +# - applicable Qt version (if necessary) +# - applicable Qt bindings (if necessary) +# +# This list is used to dynamically construct two dictionaries (based on the bindings name and Qt version): +# - mapping python extension names to associated module information +# - mapping Qt shared library names to associated module information +# This allows us to associate plugins and translations with either Qt python extension or with the Qt module's shared +# library (or both), whichever is applicable. +# +# The `qt_dynamic_dependencies_dict`_ from the original approach was constructed using several information sources, as +# documented `here +# ˙_. +# +# In the current approach, the relations stored in the `QT_MODULES_INFO`_ list were determined directly, by inspecting +# the Qt source code. This requires some prior knowledge of how the Qt code is organized (repositories and individual Qt +# modules within them), as well as some searching based on guesswork. The procedure can be outlined as follows: +# * check out the `main Qt repository `_. This repository contains references to all other +# Qt repositories in the form of git submodules. +# * for Qt5: +# * check out the latest release tag, e.g., v5.15.2, then check out the submodules. +# * search the Qt modules' qmake .pro files; for example, ``qtbase/src/network/network.pro`` for QtNetwork module. +# The plugin types associated with the module are listed in the ``MODULE_PLUGIN_TYPES`` variable (in this case, +# ``bearer``). +# * all translations are gathered in ``qttranslations`` sub-module/repository, and their association with +# individual repositories can be seen in ``qttranslations/translations/translations.pro``. +# * for Qt6: +# * check out the latest release tag, e.g., v6.3.1, then check out the submodules. +# * search the Qt modules' CMake files; for example, ``qtbase/src/network/CMakeLists.txt`` for QtNetwork module. +# The plugin types associated with the module are listed under ``PLUGIN_TYPES`` argument of the +# ``qt_internal_add_module()`` function that defines the Qt module. +# +# The idea is to make a list of all extension modules found in a Qt bindings package, as well as all available plugin +# directories (which correspond to plugin types) and translation files. For each extension, identify the corresponding +# Qt module (shared library name) and its associated plugins and translation files. Once this is done, most of available +# plugins and translations in the python bindings package should have a corresponding python Qt extension module +# available; this gives us associations based on the python extension module names as well as based on the Qt shared +# library names. For any plugins and translation files remaining unassociated, identify the corresponding Qt module; +# this gives us associations based only on Qt shared library names. While this second group of associations are never +# processed directly (due to lack of corresponding python extension), they may end up being processed during the +# recursive dependency analysis, if the corresponding Qt shared library is linked against by some Qt python extension +# or another Qt shared library. + + +# This structure is used to define Qt module information, such as python module/extension name, Qt module (shared +# library) name, translation files' base names, plugins, as well as associated python bindings (which implicitly +# also encode major Qt version). +class _QtModuleDef: + def __init__(self, module, shared_lib=None, translations=None, plugins=None, bindings=None): + # Python module (extension) name without package namespace. For example, `QtCore`. + # Can be None if python bindings do not bind the module, but we still need to establish relationship between + # the Qt module (shared library) and its plugins and translations. + self.module = module + # Associated Qt module (shared library), if any. Used during recursive dependency analysis, where a python + # module (extension) is analyzed for linked Qt modules (shared libraries), and then their corresponding + # python modules (extensions) are added to hidden imports. For example, the Qt module name is `Qt5Core` or + # `Qt6Core`, depending on the Qt version. Can be None for python modules that are not tied to a particular + # Qt shared library (for example, the corresponding Qt module is headers-only) and hence they cannot be + # inferred from recursive link-time dependency analysis. + self.shared_lib = shared_lib + # List of base names of translation files (if any) associated with the Qt module. Multiple base names may be + # associated with a single module. + # For example, `['qt', 'qtbase']` for `QtCore` or `['qtmultimedia']` for `QtMultimedia`. + self.translations = translations or [] + # List of plugins associated with the Qt module. + self.plugins = plugins or [] + # List of bindings (PySide2, PyQt5, PySide6, PyQt6) that provide the python module. This allows association of + # plugins and translations with shared libraries even for bindings that do not provide python module binding + # for the Qt module. + self.bindings = set(bindings or []) + + +# All Qt-based bindings. +ALL_QT_BINDINGS = {"PySide2", "PyQt5", "PySide6", "PyQt6"} + +# Qt modules information - the core of our Qt collection approach. +# +# For every python module/extension (i.e., entry in the list below that has valid `module`), we need a corresponding +# hook, ensuring that the extension file is analyzed, so that we collect the associated plugins and translation +# files, as well as perform recursive analysis of link-time binary dependencies (so that plugins and translation files +# belonging to those dependencies are collected as well). +QT_MODULES_INFO = ( + # *** qt/qt3d *** + _QtModuleDef("Qt3DAnimation", shared_lib="3DAnimation"), + _QtModuleDef("Qt3DCore", shared_lib="3DCore"), + _QtModuleDef("Qt3DExtras", shared_lib="3DExtras"), + _QtModuleDef("Qt3DInput", shared_lib="3DInput", plugins=["3dinputdevices"]), + _QtModuleDef("Qt3DLogic", shared_lib="3DLogic"), + _QtModuleDef( + "Qt3DRender", shared_lib="3DRender", plugins=["geometryloaders", "renderplugins", "renderers", "sceneparsers"] + ), + + # *** qt/qtactiveqt *** + # The python module is called QAxContainer in PyQt bindings, but QtAxContainer in PySide. The associated Qt module + # is header-only, so there is no shared library. + _QtModuleDef("QAxContainer", bindings=["PyQt*"]), + _QtModuleDef("QtAxContainer", bindings=["PySide*"]), + + # *** qt/qtcharts *** + # The python module is called QtChart in PyQt5, and QtCharts in PySide2, PySide6, and PyQt6 (which corresponds to + # the associated Qt module name, QtCharts). + _QtModuleDef("QtChart", shared_lib="Charts", bindings=["PyQt5"]), + _QtModuleDef("QtCharts", shared_lib="Charts", bindings=["!PyQt5"]), + + # *** qt/qtbase *** + # QtConcurrent python module is available only in PySide bindings. + _QtModuleDef(None, shared_lib="Concurrent", bindings=["PyQt*"]), + _QtModuleDef("QtConcurrent", shared_lib="Concurrent", bindings=["PySide*"]), + _QtModuleDef("QtCore", shared_lib="Core", translations=["qt", "qtbase"]), + # QtDBus python module is available in all bindings but PySide2. + _QtModuleDef(None, shared_lib="DBus", bindings=["PySide2"]), + _QtModuleDef("QtDBus", shared_lib="DBus", bindings=["!PySide2"]), + # QtNetwork uses different plugins in Qt5 and Qt6. + _QtModuleDef("QtNetwork", shared_lib="Network", plugins=["bearer"], bindings=["PySide2", "PyQt5"]), + _QtModuleDef( + "QtNetwork", + shared_lib="Network", + plugins=["networkaccess", "networkinformation", "tls"], + bindings=["PySide6", "PyQt6"] + ), + _QtModuleDef( + "QtGui", + shared_lib="Gui", + plugins=[ + "accessiblebridge", + "egldeviceintegrations", + "generic", + "iconengines", + "imageformats", + "platforms", + "platforms/darwin", + "platforminputcontexts", + "platformthemes", + "xcbglintegrations", + # The ``wayland-*`` plugins are part of QtWaylandClient Qt module, whose shared library + # (e.g., libQt5WaylandClient.so) is linked by the wayland-related ``platforms`` plugins. Ideally, we would + # collect these plugins based on the QtWaylandClient shared library entry, but as our Qt hook utilities do + # not scan the plugins for dependencies, that would not work. So instead we list these plugins under QtGui + # to achieve pretty much the same end result. + "wayland-decoration-client", + "wayland-graphics-integration-client", + "wayland-shell-integration" + ] + ), + _QtModuleDef("QtOpenGL", shared_lib="OpenGL"), + # This python module is specific to PySide2 and has no associated Qt module. + _QtModuleDef("QtOpenGLFunctions", bindings=["PySide2"]), + # This Qt module was introduced with Qt6. + _QtModuleDef("QtOpenGLWidgets", shared_lib="OpenGLWidgets", bindings=["PySide6", "PyQt6"]), + _QtModuleDef("QtPrintSupport", shared_lib="PrintSupport", plugins=["printsupport"]), + _QtModuleDef("QtSql", shared_lib="Sql", plugins=["sqldrivers"]), + _QtModuleDef("QtTest", shared_lib="Test"), + _QtModuleDef("QtWidgets", shared_lib="Widgets", plugins=["styles"]), + _QtModuleDef("QtXml", shared_lib="Xml"), + + # *** qt/qtconnectivity *** + _QtModuleDef("QtBluetooth", shared_lib="QtBluetooth", translations=["qtconnectivity"]), + _QtModuleDef("QtNfc", shared_lib="Nfc", translations=["qtconnectivity"]), + + # *** qt/qtdatavis3d *** + _QtModuleDef("QtDataVisualization", shared_lib="DataVisualization"), + + # *** qt/qtdeclarative *** + _QtModuleDef("QtQml", shared_lib="Qml", translations=["qtdeclarative"], plugins=["qmltooling"]), + # Have the Qt5 variant collect translations for qtquickcontrols (qt/qtquickcontrols provides only QtQuick plugins). + _QtModuleDef( + "QtQuick", + shared_lib="Quick", + translations=["qtquickcontrols"], + plugins=["scenegraph"], + bindings=["PySide2", "PyQt5"] + ), + _QtModuleDef("QtQuick", shared_lib="Quick", plugins=["scenegraph"], bindings=["PySide6", "PyQt6"]), + # Qt6-only; in Qt5, this module is part of qt/qtquickcontrols2. Python module is available only in PySide6. + _QtModuleDef(None, shared_lib="QuickControls2", bindings=["PyQt6"]), + _QtModuleDef("QtQuickControls2", shared_lib="QuickControls2", bindings=["PySide6"]), + _QtModuleDef("QtQuickWidgets", shared_lib="QuickWidgets"), + + # *** qt/qtgamepad *** + # No python module; shared library -> plugins association entry. + _QtModuleDef(None, shared_lib="Gamepad", plugins=["gamepads"]), + + # *** qt/qtgraphs *** + # Qt6 >= 6.6.0; python module is available only in PySide6. + _QtModuleDef("QtGraphs", shared_lib="Graphs", bindings=["PySide6"]), + + # *** qt/qthttpserver *** + # Qt6 >= 6.4.0; python module is available only in PySide6. + _QtModuleDef("QtHttpServer", shared_lib="HttpServer", bindings=["PySide6"]), + + # *** qt/qtlocation *** + # QtLocation was reintroduced in Qt6 v6.5.0. + _QtModuleDef( + "QtLocation", + shared_lib="Location", + translations=["qtlocation"], + plugins=["geoservices"], + bindings=["PySide2", "PyQt5", "PySide6"] + ), + _QtModuleDef( + "QtPositioning", + shared_lib="Positioning", + translations=["qtlocation"], + plugins=["position"], + ), + + # *** qt/qtmacextras *** + # Qt5-only Qt module. + _QtModuleDef("QtMacExtras", shared_lib="MacExtras", bindings=["PySide2", "PyQt5"]), + + # *** qt/qtmultimedia *** + # QtMultimedia on Qt6 currently uses only a subset of plugin names from Qt5 counterpart. + _QtModuleDef( + "QtMultimedia", + shared_lib="Multimedia", + translations=["qtmultimedia"], + plugins=[ + "mediaservice", "audio", "video/bufferpool", "video/gstvideorenderer", "video/videonode", "playlistformats", + "resourcepolicy" + ], + bindings=["PySide2", "PyQt5"] + ), + _QtModuleDef( + "QtMultimedia", + shared_lib="Multimedia", + translations=["qtmultimedia"], + # `multimedia` plugins are available as of Qt6 >= 6.4.0; earlier versions had `video/gstvideorenderer` and + # `video/videonode` plugins. + plugins=["multimedia", "video/gstvideorenderer", "video/videonode"], + bindings=["PySide6", "PyQt6"] + ), + _QtModuleDef("QtMultimediaWidgets", shared_lib="MultimediaWidgets"), + # Qt6-only Qt module; python module is available in PySide6 >= 6.4.0 and PyQt6 >= 6.5.0 + _QtModuleDef("QtSpatialAudio", shared_lib="SpatialAudio", bindings=["PySide6", "PyQt6"]), + + # *** qt/qtnetworkauth *** + # QtNetworkAuth python module is available in all bindings but PySide2. + _QtModuleDef(None, shared_lib="NetworkAuth", bindings=["PySide2"]), + _QtModuleDef("QtNetworkAuth", shared_lib="NetworkAuth", bindings=["!PySide2"]), + + # *** qt/qtpurchasing *** + # Qt5-only Qt module, python module is available only in PyQt5. + _QtModuleDef("QtPurchasing", shared_lib="Purchasing", bindings=["PyQt5"]), + + # *** qt/qtquick1 *** + # This is an old, Qt 5.3-era module... + _QtModuleDef( + "QtDeclarative", + shared_lib="Declarative", + translations=["qtquick1"], + plugins=["qml1tooling"], + bindings=["PySide2", "PyQt5"] + ), + + # *** qt/qtquick3d *** + # QtQuick3D python module is available in all bindings but PySide2. + _QtModuleDef(None, shared_lib="Quick3D", bindings=["PySide2"]), + _QtModuleDef("QtQuick3D", shared_lib="Quick3D", bindings=["!PySide2"]), + # No python module; shared library -> plugins association entry. + _QtModuleDef(None, shared_lib="Quick3DAssetImport", plugins=["assetimporters"]), + + # *** qt/qtquickcontrols2 *** + # Qt5-only module; in Qt6, this module is part of qt/declarative. Python module is available only in PySide2. + _QtModuleDef(None, translations=["qtquickcontrols2"], shared_lib="QuickControls2", bindings=["PyQt5"]), + _QtModuleDef( + "QtQuickControls2", translations=["qtquickcontrols2"], shared_lib="QuickControls2", bindings=["PySide2"] + ), + + # *** qt/qtremoteobjects *** + _QtModuleDef("QtRemoteObjects", shared_lib="RemoteObjects"), + + # *** qt/qtscxml *** + # Python module is available only in PySide bindings. Plugins are available only in Qt6. + # PyQt wheels do not seem to ship the corresponding Qt modules (shared libs) at all. + _QtModuleDef("QtScxml", shared_lib="Scxml", bindings=["PySide2"]), + _QtModuleDef("QtScxml", shared_lib="Scxml", plugins=["scxmldatamodel"], bindings=["PySide6"]), + # Qt6-only Qt module, python module is available only in PySide6. + _QtModuleDef("QtStateMachine", shared_lib="StateMachine", bindings=["PySide6"]), + + # *** qt/qtsensors *** + _QtModuleDef("QtSensors", shared_lib="Sensors", plugins=["sensors", "sensorgestures"]), + + # *** qt/qtserialport *** + _QtModuleDef("QtSerialPort", shared_lib="SerialPort", translations=["qtserialport"]), + + # *** qt/qtscript *** + # Qt5-only Qt module, python module is available only in PySide2. PyQt5 wheels do not seem to ship the corresponding + # Qt modules (shared libs) at all. + _QtModuleDef("QtScript", shared_lib="Script", translations=["qtscript"], plugins=["script"], bindings=["PySide2"]), + _QtModuleDef("QtScriptTools", shared_lib="ScriptTools", bindings=["PySide2"]), + + # *** qt/qtserialbus *** + # No python module; shared library -> plugins association entry. + # PySide6 6.5.0 introduced python module. + _QtModuleDef(None, shared_lib="SerialBus", plugins=["canbus"], bindings=["!PySide6"]), + _QtModuleDef("QtSerialBus", shared_lib="SerialBus", plugins=["canbus"], bindings=["PySide6"]), + + # *** qt/qtsvg *** + _QtModuleDef("QtSvg", shared_lib="Svg"), + # Qt6-only Qt module. + _QtModuleDef("QtSvgWidgets", shared_lib="SvgWidgets", bindings=["PySide6", "PyQt6"]), + + # *** qt/qtspeech *** + _QtModuleDef("QtTextToSpeech", shared_lib="TextToSpeech", plugins=["texttospeech"]), + + # *** qt/qttools *** + # QtDesigner python module is available in all bindings but PySide2. + _QtModuleDef(None, shared_lib="Designer", plugins=["designer"], bindings=["PySide2"]), + _QtModuleDef( + "QtDesigner", shared_lib="Designer", translations=["designer"], plugins=["designer"], bindings=["!PySide2"] + ), + _QtModuleDef("QtHelp", shared_lib="Help", translations=["qt_help"]), + # Python module is available only in PySide bindings. + _QtModuleDef("QtUiTools", shared_lib="UiTools", bindings=["PySide*"]), + + # *** qt/qtvirtualkeyboard *** + # No python module; shared library -> plugins association entry. + _QtModuleDef(None, shared_lib="VirtualKeyboard", plugins=["virtualkeyboard"]), + + # *** qt/qtwebchannel *** + _QtModuleDef("QtWebChannel", shared_lib="WebChannel"), + + # *** qt/qtwebengine *** + # QtWebEngine is Qt5-only module (replaced by QtWebEngineQuick in Qt6). + _QtModuleDef("QtWebEngine", shared_lib="WebEngine", bindings=["PySide2", "PyQt5"]), + _QtModuleDef("QtWebEngineCore", shared_lib="WebEngineCore", translations=["qtwebengine"]), + # QtWebEngineQuick is Qt6-only module (replacement for QtWebEngine in Qt5). + _QtModuleDef("QtWebEngineQuick", shared_lib="WebEngineQuick", bindings=["PySide6", "PyQt6"]), + _QtModuleDef("QtWebEngineWidgets", shared_lib="WebEngineWidgets"), + # QtPdf and QtPdfWidgets have python module available in PySide6 and PyQt6 >= 6.4.0. + _QtModuleDef("QtPdf", shared_lib="Pdf", bindings=["PySide6", "PyQt6"]), + _QtModuleDef("QtPdfWidgets", shared_lib="PdfWidgets", bindings=["PySide6", "PyQt6"]), + + # *** qt/qtwebsockets *** + _QtModuleDef("QtWebSockets", shared_lib="WebSockets", translations=["qtwebsockets"]), + + # *** qt/qtwebview *** + # No python module; shared library -> plugins association entry. + _QtModuleDef(None, shared_lib="WebView", plugins=["webview"]), + + # *** qt/qtwinextras *** + # Qt5-only Qt module. + _QtModuleDef("QtWinExtras", shared_lib="WinExtras", bindings=["PySide2", "PyQt5"]), + + # *** qt/qtx11extras *** + # Qt5-only Qt module. + _QtModuleDef("QtX11Extras", shared_lib="X11Extras", bindings=["PySide2", "PyQt5"]), + + # *** qt/qtxmlpatterns *** + # Qt5-only Qt module. + _QtModuleDef( + "QtXmlPatterns", shared_lib="XmlPatterns", translations=["qtxmlpatterns"], bindings=["PySide2", "PyQt5"] + ), + + # *** qscintilla *** + # Python module is available only in PyQt bindings. No associated shared library. + _QtModuleDef("Qsci", translations=["qscintilla"], bindings=["PyQt*"]), +) + + +# Helpers for turning Qt namespace specifiers, such as "!PySide2" or "PyQt*", into set of applicable +# namespaces. +def process_namespace_strings(namespaces): + """"Process list of Qt namespace specifier strings into set of namespaces.""" + bindings = set() + for namespace in namespaces: + bindings |= _process_namespace_string(namespace) + return bindings + + +def _process_namespace_string(namespace): + """Expand a Qt namespace specifier string into set of namespaces.""" + if namespace.startswith("!"): + bindings = _process_namespace_string(namespace[1:]) + return ALL_QT_BINDINGS - bindings + else: + if namespace == "PySide*": + return {"PySide2", "PySide6"} + elif namespace == "PyQt*": + return {"PyQt5", "PyQt6"} + elif namespace in ALL_QT_BINDINGS: + return {namespace} + else: + raise ValueError(f"Invalid Qt namespace specifier: {namespace}!") diff --git a/venv/Lib/site-packages/PyInstaller/utils/hooks/setuptools.py b/venv/Lib/site-packages/PyInstaller/utils/hooks/setuptools.py new file mode 100644 index 0000000..c57b262 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/utils/hooks/setuptools.py @@ -0,0 +1,247 @@ +# ---------------------------------------------------------------------------- +# Copyright (c) 2024, 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) +#----------------------------------------------------------------------------- +from PyInstaller import log as logging +from PyInstaller import isolated + +logger = logging.getLogger(__name__) + + +# Import setuptools and analyze its properties in an isolated subprocess. This function is called by `SetuptoolsInfo` +# to initialize its properties. +@isolated.decorate +def _retrieve_setuptools_info(): + import importlib + + try: + setuptools = importlib.import_module("setuptools") # noqa: F841 + except ModuleNotFoundError: + return None + + # Delay these imports until after we have confirmed that setuptools is importable. + import pathlib + + import packaging.version + + from PyInstaller.compat import importlib_metadata + from PyInstaller.utils.hooks import ( + collect_data_files, + collect_submodules, + ) + + # Try to retrieve the version. At this point, failure is consider an error. + version_string = importlib_metadata.version("setuptools") + version = packaging.version.Version(version_string).release # Use the version tuple + + # setuptools >= 60.0 its vendored copy of distutils (mainly due to its removal from stdlib in python >= 3.12). + distutils_vendored = False + distutils_modules = [] + if version >= (60, 0): + distutils_vendored = True + distutils_modules += ["_distutils_hack"] + distutils_modules += collect_submodules( + "setuptools._distutils", + # setuptools 71.0.1 ~ 71.0.4 include `setuptools._distutils.tests`; avoid explicitly collecting it + # (t was not included in earlier setuptools releases). + filter=lambda name: name != 'setuptools._distutils.tests', + ) + + # Check for exposed packages/modules that are vendored by setuptools. If stand-alone version is not provided in the + # environment, setuptools-vendored version is exposed (due to location of `setuptools._vendor` being appended to + # `sys.path`. Applicable to v71.0.0 and later. + vendored_status = dict() + if version >= (71, 0): + VENDORED_CANDIDATES = ( + "autocommand", + "backports.tarfile", + "importlib_metadata", + "importlib_resources", + "inflect", + "jaraco.context", + "jaraco.functools", + "jaraco.text", + "more_itertools", + "ordered_set", + "packaging", + "platformdirs", + "tomli", + "typeguard", + "typing_extensions", + "wheel", + "zipp", + ) + + # Resolve path(s) of `setuptools_vendor` package + setuptools_vendor = importlib.import_module("setuptools._vendor") + setuptools_vendor_paths = [pathlib.Path(path).resolve() for path in setuptools_vendor.__path__] + + # Process each candidate + for candidate_name in VENDORED_CANDIDATES: + try: + candidate = importlib.import_module(candidate_name) + except ImportError: + continue + + # Check the __file__ attribute (modules and regular packages). Will not work with namespace packages, but + # at the moment, there are none. + candidate_file_attr = getattr(candidate, '__file__', None) + if candidate_file_attr is not None: + candidate_path = pathlib.Path(candidate_file_attr).parent.resolve() + is_vendored = any([ + setuptools_vendor_path in candidate_path.parents + for setuptools_vendor_path in setuptools_vendor_paths + ]) + vendored_status[candidate_name] = is_vendored + + # Collect submodules from `setuptools._vendor`, regardless of whether the vendored package is exposed or + # not (because setuptools might need/use it either way). + EXCLUDED_VENDORED_MODULES = ( + # Prevent recursing into setuptools._vendor.pyparsing.diagram, which typically fails to be imported due + # to missing dependencies (railroad, pyparsing (?), jinja2) and generates a warning... As the module is + # usually unimportable, it is likely not to be used by setuptools. NOTE: pyparsing was removed from + # vendored packages in setuptools v67.0.0; keep this exclude around for earlier versions. + 'setuptools._vendor.pyparsing.diagram', + # Setuptools >= 71 started shipping vendored dependencies that include tests; avoid collecting those via + # hidden imports. (Note that this also prevents creation of aliases for these module, but that should + # not be an issue, as they should not be referenced from anywhere). + 'setuptools._vendor.importlib_resources.tests', + # These appear to be utility scripts bundled with the jaraco.text package - exclude them. + 'setuptools._vendor.jaraco.text.show-newlines', + 'setuptools._vendor.jaraco.text.strip-prefix', + 'setuptools._vendor.jaraco.text.to-dvorak', + 'setuptools._vendor.jaraco.text.to-qwerty', + ) + vendored_modules = collect_submodules( + 'setuptools._vendor', + filter=lambda name: name not in EXCLUDED_VENDORED_MODULES, + ) + + # `collect_submodules` (and its underlying `pkgutil.iter_modules` do not discover namespace sub-packages, in + # this case `setuptools._vendor.jaraco`. So force a manual scan of modules/packages inside it. + vendored_modules += collect_submodules( + 'setuptools._vendor.jaraco', + filter=lambda name: name not in EXCLUDED_VENDORED_MODULES, + ) + + # *** Data files for vendored packages *** + vendored_data = [] + + if version >= (71, 0): + # Since the vendored dependencies from `setuptools/_vendor` are now visible to the outside world, make + # sure we collect their metadata. (We cannot use copy_metadata here, because we need to collect data + # files to their original locations). + vendored_data += collect_data_files('setuptools._vendor', includes=['**/*.dist-info']) + # Similarly, ensure that `Lorem ipsum.txt` from vendored jaraco.text is collected + vendored_data += collect_data_files('setuptools._vendor.jaraco.text', includes=['**/Lorem ipsum.txt']) + + # Return dictionary with collected information + return { + "available": True, + "version": version, + "distutils_vendored": distutils_vendored, + "distutils_modules": distutils_modules, + "vendored_status": vendored_status, + "vendored_modules": vendored_modules, + "vendored_data": vendored_data, + } + + +class SetuptoolsInfo: + def __init__(self): + pass + + def __repr__(self): + return "SetuptoolsInfo" + + # Delay initialization of setuptools information until until the corresponding attributes are first requested. + def __getattr__(self, name): + if 'available' in self.__dict__: + # Initialization was already done, but requested attribute is not available. + raise AttributeError(name) + + # Load setuptools info... + self._load_setuptools_info() + # ... and return the requested attribute + return getattr(self, name) + + def _load_setuptools_info(self): + logger.info("%s: initializing cached setuptools info...", self) + + # Initialize variables so that they might be accessed even if setuptools is unavailable or if initialization + # fails for some reason. + self.available = False + self.version = None + self.distutils_vendored = False + self.distutils_modules = [] + self.vendored_status = dict() + self.vendored_modules = [] + self.vendored_data = [] + + try: + setuptools_info = _retrieve_setuptools_info() + except Exception as e: + logger.warning("%s: failed to obtain setuptools info: %s", self, e) + return + + # If package could not be imported, `_retrieve_setuptools_info` returns None. In such cases, emit a debug + # message instead of a warning, because this initialization might be triggered by a helper function that is + # trying to determine availability of `setuptools` by inspecting the `available` attribute. + if setuptools_info is None: + logger.debug("%s: failed to obtain setuptools info: setuptools could not be imported.", self) + return + + # Copy properties + for key, value in setuptools_info.items(): + setattr(self, key, value) + + def is_vendored(self, module_name): + return self.vendored_status.get(module_name, False) + + @staticmethod + def _create_vendored_aliases(vendored_name, module_name, modules_list): + # Create aliases for all submodules + prefix_len = len(vendored_name) # Length of target-name prefix to remove + return ((module_name + vendored_module[prefix_len:], vendored_module) for vendored_module in modules_list + if vendored_module.startswith(vendored_name)) + + def get_vendored_aliases(self, module_name): + vendored_name = f"setuptools._vendor.{module_name}" + return self._create_vendored_aliases(vendored_name, module_name, self.vendored_modules) + + def get_distutils_aliases(self): + vendored_name = "setuptools._distutils" + return self._create_vendored_aliases(vendored_name, "distutils", self.distutils_modules) + + +setuptools_info = SetuptoolsInfo() + + +def pre_safe_import_module(api): + """ + A common implementation of pre_safe_import_module hook function. + + This function can be either called from the `pre_safe_import_module` function in a pre-safe-import-module hook, or + just imported into the hook. + """ + module_name = api.module_name + + # Check if the package/module is a vendored copy. This also returns False is setuptools is unavailable, because + # vendored module status dictionary will be empty. + if not setuptools_info.is_vendored(module_name): + return + + vendored_name = f"setuptools._vendor.{module_name}" + logger.info( + "Setuptools: %r appears to be a setuptools-vendored copy - creating alias to %r!", module_name, vendored_name + ) + + # Create aliases for all (sub)modules + for aliased_name, real_vendored_name in setuptools_info.get_vendored_aliases(module_name): + api.add_alias_module(real_vendored_name, aliased_name) diff --git a/venv/Lib/site-packages/PyInstaller/utils/hooks/tcl_tk.py b/venv/Lib/site-packages/PyInstaller/utils/hooks/tcl_tk.py new file mode 100644 index 0000000..869356c --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/utils/hooks/tcl_tk.py @@ -0,0 +1,340 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +import os +import fnmatch + +from PyInstaller import compat +from PyInstaller import isolated +from PyInstaller import log as logging +from PyInstaller.depend import bindepend + +if compat.is_darwin: + from PyInstaller.utils import osx as osxutils + +logger = logging.getLogger(__name__) + + +@isolated.decorate +def _get_tcl_tk_info(): + """ + Isolated-subprocess helper to retrieve the basic Tcl/Tk information: + - tkinter_extension_file = the value of __file__ attribute of the _tkinter binary extension (path to file). + - tcl_data_dir = path to the Tcl library/data directory. + - tcl_version = Tcl version + - tk_version = Tk version + - tcl_theaded = boolean indicating whether Tcl/Tk is built with multi-threading support. + """ + try: + import tkinter + import _tkinter + except ImportError: + # tkinter unavailable + return None + try: + tcl = tkinter.Tcl() + except tkinter.TclError: # e.g. "Can't find a usable init.tcl in the following directories: ..." + return None + + # Query the location of Tcl library/data directory. + tcl_data_dir = tcl.eval("info library") + + # Check if Tcl/Tk is built with multi-threaded support (built with --enable-threads), as indicated by the presence + # of optional `threaded` member in `tcl_platform` array. + try: + tcl.getvar("tcl_platform(threaded)") # Ignore the actual value. + tcl_threaded = True + except tkinter.TclError: + tcl_threaded = False + + return { + "available": True, + "tkinter_extension_file": _tkinter.__file__, + "tcl_version": _tkinter.TCL_VERSION, + "tk_version": _tkinter.TK_VERSION, + "tcl_threaded": tcl_threaded, + "tcl_data_dir": tcl_data_dir, + } + + +class TclTkInfo: + # Root directory names of Tcl and Tk library/data directories in the frozen application. These directories are + # originally fully versioned (e.g., tcl8.6 and tk8.6); we want to remap them to unversioned variants, so that our + # run-time hook (pyi_rthook__tkinter.py) does not have to determine version numbers when setting `TCL_LIBRARY` + # and `TK_LIBRARY` environment variables. + # + # We also cannot use plain "tk" and "tcl", because on macOS, the Tcl and Tk shared libraries might come from + # framework bundles, and would therefore end up being collected as "Tcl" and "Tk" in the top-level application + # directory, causing clash due to filesystem being case-insensitive by default. + TCL_ROOTNAME = '_tcl_data' + TK_ROOTNAME = '_tk_data' + + def __init__(self): + pass + + def __repr__(self): + return "TclTkInfo" + + # Delay initialization of Tcl/Tk information until until the corresponding attributes are first requested. + def __getattr__(self, name): + if 'available' in self.__dict__: + # Initialization was already done, but requested attribute is not available. + raise AttributeError(name) + + # Load Qt library info... + self._load_tcl_tk_info() + # ... and return the requested attribute + return getattr(self, name) + + def _load_tcl_tk_info(self): + logger.info("%s: initializing cached Tcl/Tk info...", self) + + # Initialize variables so that they might be accessed even if tkinter/Tcl/Tk is unavailable or if initialization + # fails for some reason. + self.available = False + self.tkinter_extension_file = None + self.tcl_version = None + self.tk_version = None + self.tcl_threaded = False + self.tcl_data_dir = None + + self.tk_data_dir = None + self.tcl_module_dir = None + + self.is_macos_system_framework = False + self.tcl_shared_library = (None, None) + self.tk_shared_library = (None, None) + + self.data_files = [] + + try: + tcl_tk_info = _get_tcl_tk_info() + except Exception as e: + logger.warning("%s: failed to obtain Tcl/Tk info: %s", self, e) + return + + # If tkinter could not be imported, `_get_tcl_tk_info` returns None. In such cases, emit a debug message instead + # of a warning, because this initialization might be triggered by a helper function that is trying to determine + # availability of `tkinter` by inspecting the `available` attribute. + if tcl_tk_info is None: + logger.debug("%s: failed to obtain Tcl/Tk info: tkinter/_tkinter could not be imported.", self) + return + + # Copy properties + for key, value in tcl_tk_info.items(): + setattr(self, key, value) + + # Parse Tcl/Tk version into (major, minor) tuple. + self.tcl_version = tuple((int(x) for x in self.tcl_version.split(".")[:2])) + self.tk_version = tuple((int(x) for x in self.tk_version.split(".")[:2])) + + # Determine full path to Tcl and Tk shared libraries against which the _tkinter extension module is linked. + try: + ( + self.tcl_shared_library, + self.tk_shared_library, + ) = self._find_tcl_tk_shared_libraries(self.tkinter_extension_file) + except Exception: + logger.warning("%s: failed to determine Tcl and Tk shared library location!", self, exc_info=True) + + # macOS: check if _tkinter is linked against system-provided Tcl.framework and Tk.framework. This is the case + # with python3 from XCode tools (and was the case with very old homebrew python builds). In such cases, we + # should not be collecting Tcl/Tk files. + if compat.is_darwin: + self.is_macos_system_framework = self._check_macos_system_framework(self.tcl_shared_library) + + # Emit a warning in the unlikely event that we are dealing with Teapot-distributed version of ActiveTcl. + if not self.is_macos_system_framework: + self._warn_if_using_activetcl_or_teapot(self.tcl_data_dir) + + # Infer location of Tk library/data directory. Ideally, we could infer this by running + # + # import tkinter + # root = tkinter.Tk() + # tk_data_dir = root.tk.exprstring('$tk_library') + # + # in the isolated subprocess as part of `_get_tcl_tk_info`. However, that is impractical, as it shows the empty + # window, and on some platforms (e.g., linux) requires display server. Therefore, try to guess the location, + # based on the following heuristic: + # - if Tk is built as macOS framework bundle, look for Scripts sub-directory in Resources directory next to + # the shared library. + # - otherwise, look for: $tcl_root/../tkX.Y, where X and Y are Tk major and minor version. + if compat.is_darwin and self.tk_shared_library and ( + # is_framework_bundle_lib handles only fully-versioned framework library paths... + (osxutils.is_framework_bundle_lib(self.tk_shared_library)) or + # ... so manually handle top-level-symlinked variant for now. + (self.tk_shared_library).endswith("Tk.framework/Tk") + ): + # Fully resolve the library path, in case it is a top-level symlink; for example, resolve + # /Library/Frameworks/Python.framework/Versions/3.13/Frameworks/Tk.framework/Tk + # into + # /Library/Frameworks/Python.framework/Versions/3.13/Frameworks/Tk.framework/Versions/8.6/Tk + tk_lib_realpath = os.path.realpath(self.tk_shared_library) + # Resources/Scripts directory next to the shared library + self.tk_data_dir = os.path.join(os.path.dirname(tk_lib_realpath), "Resources", "Scripts") + else: + self.tk_data_dir = os.path.join( + os.path.dirname(self.tcl_data_dir), + f"tk{self.tk_version[0]}.{self.tk_version[1]}", + ) + + # Infer location of Tcl module directory. The modules directory is separate from the library/data one, and + # is located at $tcl_root/../tclX, where X is the major Tcl version. + self.tcl_module_dir = os.path.join( + os.path.dirname(self.tcl_data_dir), + f"tcl{self.tcl_version[0]}", + ) + + # Find all data files + if self.is_macos_system_framework: + logger.info("%s: using macOS system Tcl/Tk framework - not collecting data files.", self) + else: + # Collect Tcl and Tk scripts from their corresponding library/data directories. See comment at the + # definition of TK_ROOTNAME and TK_ROOTNAME variables. + if os.path.isdir(self.tcl_data_dir): + self.data_files += self._collect_files_from_directory( + self.tcl_data_dir, + prefix=self.TCL_ROOTNAME, + excludes=['demos', '*.lib', 'tclConfig.sh'], + ) + else: + logger.warning("%s: Tcl library/data directory %r does not exist!", self, self.tcl_data_dir) + + if os.path.isdir(self.tk_data_dir): + self.data_files += self._collect_files_from_directory( + self.tk_data_dir, + prefix=self.TK_ROOTNAME, + excludes=['demos', '*.lib', 'tkConfig.sh'], + ) + else: + logger.warning("%s: Tk library/data directory %r does not exist!", self, self.tk_data_dir) + + # Collect Tcl modules from modules directory + if os.path.isdir(self.tcl_module_dir): + self.data_files += self._collect_files_from_directory( + self.tcl_module_dir, + prefix=os.path.basename(self.tcl_module_dir), + ) + else: + logger.warning("%s: Tcl module directory %r does not exist!", self, self.tcl_module_dir) + + @staticmethod + def _collect_files_from_directory(root, prefix=None, excludes=None): + """ + A minimal port of PyInstaller.building.datastruct.Tree() functionality, which allows us to avoid using Tree + here. This way, the TclTkInfo data structure can be used without having PyInstaller's config context set up. + """ + excludes = excludes or [] + + todo = [(root, prefix)] + output = [] + while todo: + target_dir, prefix = todo.pop() + + for entry in os.listdir(target_dir): + # Basic name-based exclusion + if any((fnmatch.fnmatch(entry, exclude) for exclude in excludes)): + continue + + src_path = os.path.join(target_dir, entry) + dest_path = os.path.join(prefix, entry) if prefix else entry + + if os.path.isdir(src_path): + todo.append((src_path, dest_path)) + else: + # Return 3-element tuples with fully-resolved dest path, since other parts of code depend on that. + output.append((dest_path, src_path, 'DATA')) + + return output + + @staticmethod + def _find_tcl_tk_shared_libraries(tkinter_ext_file): + """ + Find Tcl and Tk shared libraries against which the _tkinter extension module is linked. + """ + tcl_lib = None + tk_lib = None + + for _, lib_path in bindepend.get_imports(tkinter_ext_file): # (name, fullpath) tuple + if lib_path is None: + continue # Skip unresolved entries + + # For comparison, take basename of lib_path. On macOS, lib_name returned by get_imports is in fact + # referenced name, which is not necessarily just a basename. + lib_name = os.path.basename(lib_path) + lib_name_lower = lib_name.lower() # lower-case for comparisons + + if 'tcl' in lib_name_lower: + tcl_lib = lib_path + elif 'tk' in lib_name_lower: + tk_lib = lib_path + + return tcl_lib, tk_lib + + @staticmethod + def _check_macos_system_framework(tcl_shared_lib): + # Starting with macOS 11, system libraries are hidden (unless both Python and PyInstaller's bootloader are built + # against MacOS 11.x SDK). Therefore, Tcl shared library might end up unresolved (None); but that implicitly + # indicates that the system framework is used. + if tcl_shared_lib is None: + return True + + # Check if the path corresponds to the system framework, i.e., [/System]/Library/Frameworks/Tcl.framework/Tcl + return 'Library/Frameworks/Tcl.framework' in tcl_shared_lib + + @staticmethod + def _warn_if_using_activetcl_or_teapot(tcl_root): + """ + Check if Tcl installation is a Teapot-distributed version of ActiveTcl, and log a non-fatal warning that the + resulting frozen application will (likely) fail to run on other systems. + + PyInstaller does *not* freeze all ActiveTcl dependencies -- including Teapot, which is typically ignorable. + Since Teapot is *not* ignorable in this case, this function warns of impending failure. + + See Also + ------- + https://github.com/pyinstaller/pyinstaller/issues/621 + """ + if tcl_root is None: + return + + # Read the "init.tcl" script and look for mentions of "activetcl" and "teapot" + init_tcl = os.path.join(tcl_root, 'init.tcl') + if not os.path.isfile(init_tcl): + return + + mentions_activetcl = False + mentions_teapot = False + + # Tcl/Tk reads files using the system encoding (https://www.tcl.tk/doc/howto/i18n.html#system_encoding); + # on macOS, this is UTF-8. + with open(init_tcl, 'r', encoding='utf8') as fp: + for line in fp.readlines(): + line = line.strip().lower() + if line.startswith('#'): + continue + if 'activetcl' in line: + mentions_activetcl = True + if 'teapot' in line: + mentions_teapot = True + if mentions_activetcl and mentions_teapot: + break + + if mentions_activetcl and mentions_teapot: + logger.warning( + "You appear to be using an ActiveTcl build of Tcl/Tk, which PyInstaller has\n" + "difficulty freezing. To fix this, comment out all references to 'teapot' in\n" + f"{init_tcl!r}\n" + "See https://github.com/pyinstaller/pyinstaller/issues/621 for more information." + ) + + +tcltk_info = TclTkInfo() diff --git a/venv/Lib/site-packages/PyInstaller/utils/misc.py b/venv/Lib/site-packages/PyInstaller/utils/misc.py new file mode 100644 index 0000000..77a3e8e --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/utils/misc.py @@ -0,0 +1,229 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- +""" +This module contains miscellaneous functions that do not fit anywhere else. +""" + +import glob +import os +import pprint +import codecs +import re +import tokenize +import io +import pathlib + +from PyInstaller import log as logging +from PyInstaller.compat import is_win + +logger = logging.getLogger(__name__) + + +def dlls_in_subdirs(directory): + """ + Returns a list *.dll, *.so, *.dylib in the given directory and its subdirectories. + """ + filelist = [] + for root, dirs, files in os.walk(directory): + filelist.extend(dlls_in_dir(root)) + return filelist + + +def dlls_in_dir(directory): + """ + Returns a list of *.dll, *.so, *.dylib in the given directory. + """ + return files_in_dir(directory, ["*.so", "*.dll", "*.dylib"]) + + +def files_in_dir(directory, file_patterns=None): + """ + Returns a list of files in the given directory that match the given pattern. + """ + + file_patterns = file_patterns or [] + + files = [] + for file_pattern in file_patterns: + files.extend(glob.glob(os.path.join(directory, file_pattern))) + return files + + +def get_path_to_toplevel_modules(filename): + """ + Return the path to top-level directory that contains Python modules. + + It will look in parent directories for __init__.py files. The first parent directory without __init__.py is the + top-level directory. + + Returned directory might be used to extend the PYTHONPATH. + """ + curr_dir = os.path.dirname(os.path.abspath(filename)) + pattern = '__init__.py' + + # Try max. 10 levels up. + try: + for i in range(10): + files = set(os.listdir(curr_dir)) + # 'curr_dir' is still not top-level; go to parent dir. + if pattern in files: + curr_dir = os.path.dirname(curr_dir) + # Top-level dir found; return it. + else: + return curr_dir + except IOError: + pass + # No top-level directory found, or error was encountered. + return None + + +def mtime(fnm): + try: + # TODO: explain why this does not use os.path.getmtime() ? + # - It is probably not used because it returns float and not int. + return os.stat(fnm)[8] + except Exception: + return 0 + + +def save_py_data_struct(filename, data): + """ + Save data into text file as Python data structure. + :param filename: + :param data: + :return: + """ + dirname = os.path.dirname(filename) + if not os.path.exists(dirname): + os.makedirs(dirname) + with open(filename, 'w', encoding='utf-8') as f: + pprint.pprint(data, f) + + +def load_py_data_struct(filename): + """ + Load data saved as python code and interpret that code. + :param filename: + :return: + """ + with open(filename, 'r', encoding='utf-8') as f: + if is_win: + # import versioninfo so that VSVersionInfo can parse correctly. + from PyInstaller.utils.win32 import versioninfo # noqa: F401 + + return eval(f.read()) + + +def absnormpath(apath): + return os.path.abspath(os.path.normpath(apath)) + + +def module_parent_packages(full_modname): + """ + Return list of parent package names. + 'aaa.bb.c.dddd' -> ['aaa', 'aaa.bb', 'aaa.bb.c'] + :param full_modname: Full name of a module. + :return: List of parent module names. + """ + prefix = '' + parents = [] + # Ignore the last component in module name and get really just parent, grandparent, great grandparent, etc. + for pkg in full_modname.split('.')[0:-1]: + # Ensure that first item does not start with dot '.' + prefix += '.' + pkg if prefix else pkg + parents.append(prefix) + return parents + + +def is_file_qt_plugin(filename): + """ + Check if the given file is a Qt plugin file. + :param filename: Full path to file to check. + :return: True if given file is a Qt plugin file, False if not. + """ + + # Check the file contents; scan for QTMETADATA string. The scan is based on the brute-force Windows codepath of + # findPatternUnloaded() from qtbase/src/corelib/plugin/qlibrary.cpp in Qt5. + with open(filename, 'rb') as fp: + fp.seek(0, os.SEEK_END) + end_pos = fp.tell() + + SEARCH_CHUNK_SIZE = 8192 + QTMETADATA_MAGIC = b'QTMETADATA ' + + magic_offset = -1 + while end_pos >= len(QTMETADATA_MAGIC): + start_pos = max(end_pos - SEARCH_CHUNK_SIZE, 0) + chunk_size = end_pos - start_pos + # Is the remaining chunk large enough to hold the pattern? + if chunk_size < len(QTMETADATA_MAGIC): + break + # Read and scan the chunk + fp.seek(start_pos, os.SEEK_SET) + buf = fp.read(chunk_size) + pos = buf.rfind(QTMETADATA_MAGIC) + if pos != -1: + magic_offset = start_pos + pos + break + # Adjust search location for next chunk; ensure proper overlap. + end_pos = start_pos + len(QTMETADATA_MAGIC) - 1 + if magic_offset == -1: + return False + + return True + + +BOM_MARKERS_TO_DECODERS = { + codecs.BOM_UTF32_LE: codecs.utf_32_le_decode, + codecs.BOM_UTF32_BE: codecs.utf_32_be_decode, + codecs.BOM_UTF32: codecs.utf_32_decode, + codecs.BOM_UTF16_LE: codecs.utf_16_le_decode, + codecs.BOM_UTF16_BE: codecs.utf_16_be_decode, + codecs.BOM_UTF16: codecs.utf_16_decode, + codecs.BOM_UTF8: codecs.utf_8_decode, +} +BOM_RE = re.compile(rb"\A(%s)?(.*)" % b"|".join(map(re.escape, BOM_MARKERS_TO_DECODERS)), re.DOTALL) + + +def decode(raw: bytes): + """ + Decode bytes to string, respecting and removing any byte-order marks if present, or respecting but not removing any + PEP263 encoding comments (# encoding: cp1252). + """ + bom, raw = BOM_RE.match(raw).groups() + if bom: + return BOM_MARKERS_TO_DECODERS[bom](raw)[0] + + encoding, _ = tokenize.detect_encoding(io.BytesIO(raw).readline) + return raw.decode(encoding) + + +def is_iterable(arg): + """ + Check if the passed argument is an iterable." + """ + try: + iter(arg) + except TypeError: + return False + return True + + +def path_to_parent_archive(filename): + """ + Check if the given file path points to a file inside an existing archive file. Returns first path from the set of + parent paths that points to an existing file, or `None` if no such path exists (i.e., file is an actual stand-alone + file). + """ + for parent in pathlib.Path(filename).parents: + if parent.is_file(): + return parent + return None diff --git a/venv/Lib/site-packages/PyInstaller/utils/osx.py b/venv/Lib/site-packages/PyInstaller/utils/osx.py new file mode 100644 index 0000000..d8d770e --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/utils/osx.py @@ -0,0 +1,692 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2014-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) +#----------------------------------------------------------------------------- +""" +Utils for Mac OS platform. +""" + +import math +import os +import pathlib +import subprocess +import shutil +import tempfile + +from macholib.mach_o import ( + LC_BUILD_VERSION, + LC_CODE_SIGNATURE, + LC_ID_DYLIB, + LC_LOAD_DYLIB, + LC_LOAD_UPWARD_DYLIB, + LC_LOAD_WEAK_DYLIB, + LC_PREBOUND_DYLIB, + LC_REEXPORT_DYLIB, + LC_RPATH, + LC_SEGMENT_64, + LC_SYMTAB, + LC_VERSION_MIN_MACOSX, +) +from macholib.MachO import MachO +import macholib.util + +import PyInstaller.log as logging +from PyInstaller import compat + +logger = logging.getLogger(__name__) + + +def is_homebrew_env(): + """ + Check if Python interpreter was installed via Homebrew command 'brew'. + + :return: True if Homebrew else otherwise. + """ + # Python path prefix should start with Homebrew prefix. + env_prefix = get_homebrew_prefix() + if env_prefix and compat.base_prefix.startswith(env_prefix): + return True + return False + + +def is_macports_env(): + """ + Check if Python interpreter was installed via Macports command 'port'. + + :return: True if Macports else otherwise. + """ + # Python path prefix should start with Macports prefix. + env_prefix = get_macports_prefix() + if env_prefix and compat.base_prefix.startswith(env_prefix): + return True + return False + + +def get_homebrew_prefix(): + """ + :return: Root path of the Homebrew environment. + """ + prefix = shutil.which('brew') + # Conversion: /usr/local/bin/brew -> /usr/local + prefix = os.path.dirname(os.path.dirname(prefix)) + return prefix + + +def get_macports_prefix(): + """ + :return: Root path of the Macports environment. + """ + prefix = shutil.which('port') + # Conversion: /usr/local/bin/port -> /usr/local + prefix = os.path.dirname(os.path.dirname(prefix)) + return prefix + + +def _find_version_cmd(header): + """ + Helper that finds the version command in the given MachO header. + """ + # The SDK version is stored in LC_BUILD_VERSION command (used when targeting the latest versions of macOS) or in + # older LC_VERSION_MIN_MACOSX command. Check for presence of either. + version_cmd = [cmd for cmd in header.commands if cmd[0].cmd in {LC_BUILD_VERSION, LC_VERSION_MIN_MACOSX}] + assert len(version_cmd) == 1, \ + f"Expected exactly one LC_BUILD_VERSION or LC_VERSION_MIN_MACOSX command, found {len(version_cmd)}!" + return version_cmd[0] + + +def get_macos_sdk_version(filename): + """ + Obtain the version of macOS SDK against which the given binary was built. + + NOTE: currently, version is retrieved only from the first arch slice in the binary. + + :return: (major, minor, revision) tuple + """ + binary = MachO(filename) + header = binary.headers[0] + # Find version command using helper + version_cmd = _find_version_cmd(header) + return _hex_triplet(version_cmd[1].sdk) + + +def _hex_triplet(version): + # Parse SDK version number + major = (version & 0xFF0000) >> 16 + minor = (version & 0xFF00) >> 8 + revision = (version & 0xFF) + return major, minor, revision + + +def macosx_version_min(filename: str) -> tuple: + """ + Get the -macosx-version-min used to compile a macOS binary. + + For fat binaries, the minimum version is selected. + """ + versions = [] + for header in MachO(filename).headers: + cmd = _find_version_cmd(header) + if cmd[0].cmd == LC_VERSION_MIN_MACOSX: + versions.append(cmd[1].version) + else: + # macOS >= 10.14 uses LC_BUILD_VERSION instead. + versions.append(cmd[1].minos) + + return min(map(_hex_triplet, versions)) + + +def set_macos_sdk_version(filename, major, minor, revision): + """ + Overwrite the macOS SDK version declared in the given binary with the specified version. + + NOTE: currently, only version in the first arch slice is modified. + """ + # Validate values + assert 0 <= major <= 255, "Invalid major version value!" + assert 0 <= minor <= 255, "Invalid minor version value!" + assert 0 <= revision <= 255, "Invalid revision value!" + # Open binary + binary = MachO(filename) + header = binary.headers[0] + # Find version command using helper + version_cmd = _find_version_cmd(header) + # Write new SDK version number + version_cmd[1].sdk = major << 16 | minor << 8 | revision + # Write changes back. + with open(binary.filename, 'rb+') as fp: + binary.write(fp) + + +def fix_exe_for_code_signing(filename): + """ + Fixes the Mach-O headers to make code signing possible. + + Code signing on Mac OS does not work out of the box with embedding .pkg archive into the executable. + + The fix is done this way: + - Make the embedded .pkg archive part of the Mach-O 'String Table'. 'String Table' is at end of the Mac OS exe file, + so just change the size of the table to cover the end of the file. + - Fix the size of the __LINKEDIT segment. + + Note: the above fix works only if the single-arch thin executable or the last arch slice in a multi-arch fat + executable is not signed, because LC_CODE_SIGNATURE comes after LC_SYMTAB, and because modification of headers + invalidates the code signature. On modern arm64 macOS, code signature is mandatory, and therefore compilers + create a dummy signature when executable is built. In such cases, that signature needs to be removed before this + function is called. + + Mach-O format specification: http://developer.apple.com/documentation/Darwin/Reference/ManPages/man5/Mach-O.5.html + """ + # Estimate the file size after data was appended + file_size = os.path.getsize(filename) + + # Take the last available header. A single-arch thin binary contains a single slice, while a multi-arch fat binary + # contains multiple, and we need to modify the last one, which is adjacent to the appended data. + executable = MachO(filename) + header = executable.headers[-1] + + # Sanity check: ensure the executable slice is not signed (otherwise signature's section comes last in the + # __LINKEDIT segment). + sign_sec = [cmd for cmd in header.commands if cmd[0].cmd == LC_CODE_SIGNATURE] + assert len(sign_sec) == 0, "Executable contains code signature!" + + # Find __LINKEDIT segment by name (16-byte zero padded string) + __LINKEDIT_NAME = b'__LINKEDIT\x00\x00\x00\x00\x00\x00' + linkedit_seg = [cmd for cmd in header.commands if cmd[0].cmd == LC_SEGMENT_64 and cmd[1].segname == __LINKEDIT_NAME] + assert len(linkedit_seg) == 1, "Expected exactly one __LINKEDIT segment!" + linkedit_seg = linkedit_seg[0][1] # Take the segment command entry + # Find SYMTAB section + symtab_sec = [cmd for cmd in header.commands if cmd[0].cmd == LC_SYMTAB] + assert len(symtab_sec) == 1, "Expected exactly one SYMTAB section!" + symtab_sec = symtab_sec[0][1] # Take the symtab command entry + + # The string table is located at the end of the SYMTAB section, which in turn is the last section in the __LINKEDIT + # segment. Therefore, the end of SYMTAB section should be aligned with the end of __LINKEDIT segment, and in turn + # both should be aligned with the end of the file (as we are in the last or the only arch slice). + # + # However, when removing the signature from the executable using codesign under Mac OS 10.13, the codesign utility + # may produce an invalid file, with the declared length of the __LINKEDIT segment (linkedit_seg.filesize) pointing + # beyond the end of file, as reported in issue #6167. + # + # We can compensate for that by not using the declared sizes anywhere, and simply recompute them. In the final + # binary, the __LINKEDIT segment and the SYMTAB section MUST end at the end of the file (otherwise, we have bigger + # issues...). So simply recompute the declared sizes as difference between the final file length and the + # corresponding start offset (NOTE: the offset is relative to start of the slice, which is stored in header.offset. + # In thin binaries, header.offset is zero and start offset is relative to the start of file, but with fat binaries, + # header.offset is non-zero) + symtab_sec.strsize = file_size - (header.offset + symtab_sec.stroff) + linkedit_seg.filesize = file_size - (header.offset + linkedit_seg.fileoff) + + # Compute new vmsize by rounding filesize up to full page size. + page_size = (0x4000 if _get_arch_string(header.header).startswith('arm64') else 0x1000) + linkedit_seg.vmsize = math.ceil(linkedit_seg.filesize / page_size) * page_size + + # NOTE: according to spec, segments need to be aligned to page boundaries: 0x4000 (16 kB) for arm64, 0x1000 (4 kB) + # for other arches. But it seems we can get away without rounding and padding the segment file size - perhaps + # because it is the last one? + + # Write changes + with open(filename, 'rb+') as fp: + executable.write(fp) + + # In fat binaries, we also need to adjust the fat header. macholib as of version 1.14 does not support this, so we + # need to do it ourselves... + if executable.fat: + from macholib.mach_o import (FAT_MAGIC, FAT_MAGIC_64, fat_arch, fat_arch64, fat_header) + with open(filename, 'rb+') as fp: + # Taken from MachO.load_fat() implementation. The fat header's signature has already been validated when we + # loaded the file for the first time. + fat = fat_header.from_fileobj(fp) + if fat.magic == FAT_MAGIC: + archs = [fat_arch.from_fileobj(fp) for i in range(fat.nfat_arch)] + elif fat.magic == FAT_MAGIC_64: + archs = [fat_arch64.from_fileobj(fp) for i in range(fat.nfat_arch)] + # Adjust the size in the fat header for the last slice. + arch = archs[-1] + arch.size = file_size - arch.offset + # Now write the fat headers back to the file. + fp.seek(0) + fat.to_fileobj(fp) + for arch in archs: + arch.to_fileobj(fp) + + +def _get_arch_string(header): + """ + Converts cputype and cpusubtype from mach_o.mach_header_64 into arch string comparible with lipo/codesign. + The list of supported architectures can be found in man(1) arch. + """ + # NOTE: the constants below are taken from macholib.mach_o + cputype = header.cputype + cpusubtype = header.cpusubtype & 0x0FFFFFFF + if cputype == 0x01000000 | 7: + if cpusubtype == 8: + return 'x86_64h' # 64-bit intel (haswell) + else: + return 'x86_64' # 64-bit intel + elif cputype == 0x01000000 | 12: + if cpusubtype == 2: + return 'arm64e' + else: + return 'arm64' + elif cputype == 7: + return 'i386' # 32-bit intel + assert False, 'Unhandled architecture!' + + +class InvalidBinaryError(Exception): + """ + Exception raised by ˙get_binary_architectures˙ when it is passed an invalid binary. + """ + pass + + +class IncompatibleBinaryArchError(Exception): + """ + Exception raised by `binary_to_target_arch` when the passed binary fails the strict architecture check. + """ + def __init__(self, message): + url = "https://pyinstaller.org/en/stable/feature-notes.html#macos-multi-arch-support" + super().__init__(f"{message} For details about this error message, see: {url}") + + +def get_binary_architectures(filename): + """ + Inspects the given binary and returns tuple (is_fat, archs), where is_fat is boolean indicating fat/thin binary, + and arch is list of architectures with lipo/codesign compatible names. + """ + try: + executable = MachO(filename) + except ValueError as e: + raise InvalidBinaryError("Invalid Mach-O binary!") from e + return bool(executable.fat), [_get_arch_string(hdr.header) for hdr in executable.headers] + + +def convert_binary_to_thin_arch(filename, thin_arch, output_filename=None): + """ + Convert the given fat binary into thin one with the specified target architecture. + """ + output_filename = output_filename or filename + cmd_args = ['lipo', '-thin', thin_arch, filename, '-output', output_filename] + p = subprocess.run(cmd_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding='utf-8') + if p.returncode: + raise SystemError(f"lipo command ({cmd_args}) failed with error code {p.returncode}!\noutput: {p.stdout}") + + +def merge_into_fat_binary(output_filename, *slice_filenames): + """ + Merge the given single-arch thin binary files into a fat binary. + """ + cmd_args = ['lipo', '-create', '-output', output_filename, *slice_filenames] + p = subprocess.run(cmd_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding='utf-8') + if p.returncode: + raise SystemError(f"lipo command ({cmd_args}) failed with error code {p.returncode}!\noutput: {p.stdout}") + + +def binary_to_target_arch(filename, target_arch, display_name=None): + """ + Check that the given binary contains required architecture slice(s) and convert the fat binary into thin one, + if necessary. + """ + if not display_name: + display_name = filename # Same as input file + # Check the binary + is_fat, archs = get_binary_architectures(filename) + if target_arch == 'universal2': + if not is_fat: + raise IncompatibleBinaryArchError(f"{display_name} is not a fat binary!") + # Assume fat binary is universal2; nothing to do + else: + if is_fat: + if target_arch not in archs: + raise IncompatibleBinaryArchError(f"{display_name} does not contain slice for {target_arch}!") + # Convert to thin arch + logger.debug("Converting fat binary %s (%s) to thin binary (%s)", filename, display_name, target_arch) + convert_binary_to_thin_arch(filename, target_arch) + else: + if target_arch not in archs: + raise IncompatibleBinaryArchError( + f"{display_name} is incompatible with target arch {target_arch} (has arch: {archs[0]})!" + ) + # Binary has correct arch; nothing to do + + +def remove_signature_from_binary(filename): + """ + Remove the signature from all architecture slices of the given binary file using the codesign utility. + """ + logger.debug("Removing signature from file %r", filename) + cmd_args = ['/usr/bin/codesign', '--remove', '--all-architectures', filename] + p = subprocess.run(cmd_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding='utf-8') + if p.returncode: + raise SystemError(f"codesign command ({cmd_args}) failed with error code {p.returncode}!\noutput: {p.stdout}") + + +def sign_binary(filename, identity=None, entitlements_file=None, deep=False): + """ + Sign the binary using codesign utility. If no identity is provided, ad-hoc signing is performed. + """ + extra_args = [] + if not identity: + identity = '-' # ad-hoc signing + else: + extra_args.append('--options=runtime') # hardened runtime + if entitlements_file: + extra_args.append('--entitlements') + extra_args.append(entitlements_file) + if deep: + extra_args.append('--deep') + + logger.debug("Signing file %r", filename) + cmd_args = [ + '/usr/bin/codesign', '-s', identity, '--force', '--all-architectures', '--timestamp', *extra_args, filename + ] + p = subprocess.run(cmd_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding='utf-8') + if p.returncode: + raise SystemError(f"codesign command ({cmd_args}) failed with error code {p.returncode}!\noutput: {p.stdout}") + + +def set_dylib_dependency_paths(filename, target_rpath): + """ + Modify the given dylib's identity (in LC_ID_DYLIB command) and the paths to dependent dylibs (in LC_LOAD_DYLIB) + commands into `@rpath/` format, remove any existing rpaths (LC_RPATH commands), and add a new rpath + (LC_RPATH command) with the specified path. + + Uses `install-tool-name` utility to make the changes. + + The system libraries (e.g., the ones found in /usr/lib) are exempted from path rewrite. + + For multi-arch fat binaries, this function extracts each slice into temporary file, processes it separately, + and then merges all processed slices back into fat binary. This is necessary because `install-tool-name` cannot + modify rpaths in cases when an existing rpath is present only in one slice. + """ + + # Check if we are dealing with a fat binary; the `install-name-tool` seems to be unable to remove an rpath that is + # present only in one slice, so we need to extract each slice, process it separately, and then stich processed + # slices back into a fat binary. + is_fat, archs = get_binary_architectures(filename) + + if is_fat: + with tempfile.TemporaryDirectory() as tmpdir: + slice_filenames = [] + for arch in archs: + slice_filename = os.path.join(tmpdir, arch) + convert_binary_to_thin_arch(filename, arch, output_filename=slice_filename) + _set_dylib_dependency_paths(slice_filename, target_rpath) + slice_filenames.append(slice_filename) + merge_into_fat_binary(filename, *slice_filenames) + else: + # Thin binary - we can process it directly + _set_dylib_dependency_paths(filename, target_rpath) + + +def _set_dylib_dependency_paths(filename, target_rpath): + """ + The actual implementation of set_dylib_dependency_paths functionality. + + Implicitly assumes that a single-arch thin binary is given. + """ + + # Relocatable commands that we should overwrite - same list as used by `macholib`. + _RELOCATABLE = { + LC_LOAD_DYLIB, + LC_LOAD_UPWARD_DYLIB, + LC_LOAD_WEAK_DYLIB, + LC_PREBOUND_DYLIB, + LC_REEXPORT_DYLIB, + } + + # Parse dylib's header to extract the following commands: + # - LC_LOAD_DYLIB (or any member of _RELOCATABLE list): dylib load commands (dependent libraries) + # - LC_RPATH: rpath definitions + # - LC_ID_DYLIB: dylib's identity + binary = MachO(filename) + + dylib_id = None + rpaths = set() + linked_libs = set() + + for header in binary.headers: + for cmd in header.commands: + lc_type = cmd[0].cmd + if lc_type not in _RELOCATABLE and lc_type not in {LC_RPATH, LC_ID_DYLIB}: + continue + + # Decode path, strip trailing NULL characters + path = cmd[2].decode('utf-8').rstrip('\x00') + + if lc_type in _RELOCATABLE: + linked_libs.add(path) + elif lc_type == LC_RPATH: + rpaths.add(path) + elif lc_type == LC_ID_DYLIB: + dylib_id = path + + del binary + + # If dylib has identifier set, compute the normalized version, in form of `@rpath/basename`. + normalized_dylib_id = None + if dylib_id: + normalized_dylib_id = str(pathlib.PurePath('@rpath') / pathlib.PurePath(dylib_id).name) + + # Find dependent libraries that should have their prefix path changed to `@rpath`. If any dependent libraries + # end up using `@rpath` (originally or due to rewrite), set the `rpath_required` boolean to True, so we know + # that we need to add our rpath. + changed_lib_paths = [] + rpath_required = False + for linked_lib in linked_libs: + # Leave system dynamic libraries unchanged. + if macholib.util.in_system_path(linked_lib): + continue + + # The older python.org builds that use system Tcl/Tk framework have their _tkinter.cpython-*-darwin.so + # library linked against /Library/Frameworks/Tcl.framework/Versions/8.5/Tcl and + # /Library/Frameworks/Tk.framework/Versions/8.5/Tk, although the actual frameworks are located in + # /System/Library/Frameworks. Therefore, they slip through the above in_system_path() check, and we need to + # exempt them manually. + _exemptions = [ + '/Library/Frameworks/Tcl.framework/', + '/Library/Frameworks/Tk.framework/', + ] + if any([x in linked_lib for x in _exemptions]): + continue + + # This linked library will end up using `@rpath`, whether modified or not... + rpath_required = True + + new_path = str(pathlib.PurePath('@rpath') / pathlib.PurePath(linked_lib).name) + if linked_lib == new_path: + continue + + changed_lib_paths.append((linked_lib, new_path)) + + # Gather arguments for `install-name-tool` + install_name_tool_args = [] + + # Modify the dylib identifier if necessary + if normalized_dylib_id and normalized_dylib_id != dylib_id: + install_name_tool_args += ["-id", normalized_dylib_id] + + # Changed libs + for original_path, new_path in changed_lib_paths: + install_name_tool_args += ["-change", original_path, new_path] + + # Remove all existing rpaths except for the target rpath (if it already exists). `install_name_tool` disallows using + # `-delete_rpath` and `-add_rpath` with the same argument. + for rpath in rpaths: + if rpath == target_rpath: + continue + install_name_tool_args += [ + "-delete_rpath", + rpath, + ] + + # If any of linked libraries use @rpath now and our target rpath is not already added, add it. + # NOTE: @rpath in the dylib identifier does not actually require the rpath to be set on the binary... + if rpath_required and target_rpath not in rpaths: + install_name_tool_args += [ + "-add_rpath", + target_rpath, + ] + + # If we have no arguments, finish immediately. + if not install_name_tool_args: + return + + # Run `install_name_tool` + cmd_args = ["install_name_tool", *install_name_tool_args, filename] + p = subprocess.run(cmd_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding='utf-8') + if p.returncode: + raise SystemError( + f"install_name_tool command ({cmd_args}) failed with error code {p.returncode}!\noutput: {p.stdout}" + ) + + +def is_framework_bundle_lib(lib_path): + """ + Check if the given shared library is part of a .framework bundle. + """ + + lib_path = pathlib.PurePath(lib_path) + + # For now, focus only on versioned layout, such as `QtCore.framework/Versions/5/QtCore` + if lib_path.parent.parent.name != "Versions": + return False + if lib_path.parent.parent.parent.name != lib_path.name + ".framework": + return False + + return True + + +def collect_files_from_framework_bundles(collected_files): + """ + Scan the given TOC list of collected files for shared libraries that are collected from macOS .framework bundles, + and collect the bundles' Info.plist files. Additionally, the following symbolic links: + - `Versions/Current` pointing to the `Versions/` directory containing the binary + - `` in the top-level .framework directory, pointing to `Versions/Current/` + - `Resources` in the top-level .framework directory, pointing to `Versions/Current/Resources` + - additional directories in top-level .framework directory, pointing to their counterparts in `Versions/Current` + directory. + + Returns TOC list for the discovered Info.plist files and generated symbolic links. The list does not contain + duplicated entries. + """ + invalid_framework_found = False + + framework_files = set() # Additional entries for collected files. Use set for de-duplication. + framework_paths = set() # Registered framework paths for 2nd pass. + + # 1st pass: discover binaries from .framework bundles, and for each such binary: + # - collect `Info.plist` + # - create `Current` -> `` symlink in `.framework/Versions` directory. + # - create `.framework/` -> `.framework/Versions/Current/` symlink. + # - create `.framework/Resources` -> `.framework/Versions/Current/Resources` symlink. + for dest_name, src_name, typecode in collected_files: + if typecode != 'BINARY': + continue + + src_path = pathlib.Path(src_name) # /src/path/to/.framework/Versions// + dest_path = pathlib.PurePath(dest_name) # /dest/path/to/.framework/Versions// + + # Check whether binary originates from a .framework bundle + if not is_framework_bundle_lib(src_path): + continue + + # Check whether binary is also collected into a .framework bundle (i.e., the original layout is preserved) + if not is_framework_bundle_lib(dest_path): + continue + + # Assuming versioned layout, Info.plist should exist in Resources directory located next to the binary. + info_plist_src = src_path.parent / "Resources" / "Info.plist" + if not info_plist_src.is_file(): + # Alas, the .framework bundles shipped with PySide/PyQt might have Info.plist available only in the + # top-level Resources directory. So accommodate this scenario as well, but collect the file into + # versioned directory to appease the code-signing gods... + info_plist_src_top = src_path.parent.parent.parent / "Resources" / "Info.plist" + if not info_plist_src_top.is_file(): + # Strictly speaking, a .framework bundle without Info.plist is invalid. However, that did not prevent + # PyQt from shipping such Qt .framework bundles up until v5.14.1. So by default, we just complain via + # a warning message; if such binaries work in unfrozen python, they should also work in frozen + # application. The codesign will refuse to sign the .app bundle (if we are generating one), but there + # is nothing we can do about that. + invalid_framework_found = True + framework_dir = src_path.parent.parent.parent + if compat.strict_collect_mode: + raise SystemError(f"Could not find Info.plist in {framework_dir}!") + else: + logger.warning("Could not find Info.plist in %s!", framework_dir) + continue + info_plist_src = info_plist_src_top + info_plist_dest = dest_path.parent / "Resources" / "Info.plist" + framework_files.add((str(info_plist_dest), str(info_plist_src), "DATA")) + + # Reconstruct the symlink Versions/Current -> Versions/. + # This one seems to be necessary for code signing, but might be absent from .framework bundles shipped with + # python packages. So we always create it ourselves. + framework_files.add((str(dest_path.parent.parent / "Current"), str(dest_path.parent.name), "SYMLINK")) + + dest_framework_path = dest_path.parent.parent.parent # Top-level .framework directory path. + + # Symlink the binary in the `Current` directory to the top-level .framework directory. + framework_files.add(( + str(dest_framework_path / dest_path.name), + str(pathlib.PurePath("Versions/Current") / dest_path.name), + "SYMLINK", + )) + + # Ditto for the `Resources` directory. + framework_files.add(( + str(dest_framework_path / "Resources"), + "Versions/Current/Resources", + "SYMLINK", + )) + + # Register the framework parent path to use in additional directories scan in subsequent pass. + framework_paths.add(dest_framework_path) + + # 2nd pass: scan for additional collected directories from .framework bundles, and create symlinks to the top-level + # application directory. Make the outer loop go over the registered framework paths, so it becomes no-op if no + # framework paths are registered. + VALID_SUBDIRS = {'Helpers', 'Resources'} + + for dest_framework_path in framework_paths: + for dest_name, src_name, typecode in collected_files: + dest_path = pathlib.PurePath(dest_name) + + # Try matching against framework path + try: + remaining_path = dest_path.relative_to(dest_framework_path) + except ValueError: # dest_path is not subpath of dest_framework_path + continue + + remaining_path_parts = remaining_path.parts + + # We are interested only in entries under Versions directory. + if remaining_path_parts[0] != 'Versions': + continue + + # If the entry name is among valid sub-directory names, create symlink. + dir_name = remaining_path_parts[2] + if dir_name not in VALID_SUBDIRS: + continue + + framework_files.add(( + str(dest_framework_path / dir_name), + str(pathlib.PurePath("Versions/Current") / dir_name), + "SYMLINK", + )) + + # If we encountered an invalid .framework bundle without Info.plist, warn the user that code-signing will most + # likely fail. + if invalid_framework_found: + logger.warning( + "One or more collected .framework bundles have missing Info.plist file. If you are building an .app " + "bundle, you will most likely not be able to code-sign it." + ) + + return sorted(framework_files) diff --git a/venv/Lib/site-packages/PyInstaller/utils/run_tests.py b/venv/Lib/site-packages/PyInstaller/utils/run_tests.py new file mode 100644 index 0000000..c655c7a --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/utils/run_tests.py @@ -0,0 +1,70 @@ +# ----------------------------------------------------------------------------- +# 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) +# ----------------------------------------------------------------------------- + +import argparse +import sys + +import pytest + +from PyInstaller.compat import importlib_metadata + + +def paths_to_test(include_only=None): + """ + If ``include_only`` is falsey, this functions returns paths from all entry points. Otherwise, this parameter + must be a string or sequence of strings. In this case, this function will return *only* paths from entry points + whose ``module_name`` begins with the provided string(s). + """ + # Convert a string to a list. + if isinstance(include_only, str): + include_only = [include_only] + + # Walk through all entry points. + test_path_list = [] + for entry_point in importlib_metadata.entry_points(group="pyinstaller40", name="tests"): + # Implement ``include_only``. + if ( + not include_only # If falsey, include everything, + # Otherwise, include only the specified modules. + or any(entry_point.module.startswith(name) for name in include_only) + ): + test_path_list += list(entry_point.load()()) + return test_path_list + + +# Run pytest on all tests registered by the PyInstaller setuptools testing entry point. If provided, +# the ``include_only`` argument is passed to ``path_to_test``. +def run_pytest(*args, **kwargs): + paths = paths_to_test(include_only=kwargs.pop("include_only", None)) + # Return an error code if no tests were discovered. + if not paths: + print("Error: no tests discovered.", file=sys.stderr) + # This indicates no tests were discovered; see + # https://docs.pytest.org/en/latest/usage.html#possible-exit-codes. + return 5 + else: + # See https://docs.pytest.org/en/latest/usage.html#calling-pytest-from-python-code. + # Omit ``args[0]``, which is the name of this script. + print("pytest " + " ".join([*paths, *args[1:]])) + return pytest.main([*paths, *args[1:]], **kwargs) + + +if __name__ == "__main__": + # Look only for the ``--include_only`` argument. + parser = argparse.ArgumentParser(description='Run PyInstaller packaging tests.') + parser.add_argument( + "--include_only", + action="append", + help="Only run tests from the specified package.", + ) + args, unknown = parser.parse_known_args(sys.argv) + # Convert the parsed args into a dict using ``vars(args)``. + sys.exit(run_pytest(*unknown, **vars(args))) diff --git a/venv/Lib/site-packages/PyInstaller/utils/tests.py b/venv/Lib/site-packages/PyInstaller/utils/tests.py new file mode 100644 index 0000000..ae5ee36 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/utils/tests.py @@ -0,0 +1,152 @@ +#----------------------------------------------------------------------------- +# 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) +#----------------------------------------------------------------------------- +""" +Decorators for skipping PyInstaller tests when specific requirements are not met. +""" + +import distutils.ccompiler +import inspect +import os +import shutil +import textwrap + +import pytest +import sys + +from PyInstaller.compat import is_win +from PyInstaller.utils.hooks import check_requirement + +# Wrap some pytest decorators to be consistent in tests. +parametrize = pytest.mark.parametrize +skipif = pytest.mark.skipif +xfail = pytest.mark.xfail + + +def _check_for_compiler(): + import tempfile + + # Change to some tempdir since cc.has_function() would compile into the current directory, leaving garbage. + old_wd = os.getcwd() + tmp = tempfile.mkdtemp() + os.chdir(tmp) + cc = distutils.ccompiler.new_compiler() # NOTE: Mingw32CCompiler on Windows does not have `initialize` method. + if is_win and hasattr(cc, 'initialize'): + try: + cc.initialize() + has_compiler = True + # This error is raised on Windows if a compiler can't be found. + except distutils.errors.DistutilsPlatformError: + has_compiler = False + else: + # The C standard library contains the ``clock`` function. Use that to determine if a compiler is installed. This + # does not work on Windows:: + # + # Users\bjones\AppData\Local\Temp\a.out.exe.manifest : general error + # c1010070: Failed to load and parse the manifest. The system cannot + # find the file specified. + has_compiler = cc.has_function('clock', includes=['time.h']) + os.chdir(old_wd) + # TODO: Find a way to remove the generated clockXXXX.c file, too + shutil.rmtree(tmp) + return has_compiler + + +# A decorator to skip tests if a C compiler is not detected. +has_compiler = _check_for_compiler() +skipif_no_compiler = skipif(not has_compiler, reason="Requires a C compiler") + +skip = pytest.mark.skip + + +def importorskip(package: str): + """ + Skip a decorated test if **package** is not importable. + + Arguments: + package: + The name of the module. May be anything that is allowed after the ``import`` keyword. e.g. 'numpy' or + 'PIL.Image'. + Returns: + A pytest marker which either skips the test or does nothing. + + This function intentionally does not import the module. Doing so can lead to `sys.path` and `PATH` being + polluted, which then breaks later builds. + """ + if not importable(package): + return pytest.mark.skip(f"Can't import '{package}'.") + return pytest.mark.skipif(False, reason=f"Don't skip: '{package}' is importable.") + + +def importable(package: str): + from importlib.util import find_spec + + # The find_spec() function is used by the importlib machinery to locate a module to import. Using it finds the + # module but does not run it. Unfortunately, it does import parent modules to check submodules. + if "." in package: + # Using subprocesses is slow. If the top level module doesn't exist then we can skip it. + if not importable(package.split(".")[0]): + return False + # This is a submodule, import it in isolation. + from subprocess import DEVNULL, run + return run([sys.executable, "-c", "import " + package], stdout=DEVNULL, stderr=DEVNULL).returncode == 0 + + return find_spec(package) is not None + + +def requires(requirement: str): + """ + Mark a test to be skipped if **requirement** is not satisfied. + + Args: + requirement: + A distribution name and optional version specifier(s). See :func:`PyInstaller.utils.hooks.check_requirement` + which this argument is forwarded to. + Returns: + Either a skip marker or a dummy marker. + + This function operates on distribution metadata, and does not import any modules. + """ + if check_requirement(requirement): + return pytest.mark.skipif(False, reason=f"Don't skip: '{requirement}' is satisfied.") + else: + return pytest.mark.skip(f"Requires {requirement}.") + + +def gen_sourcefile(tmpdir, source, test_id=None): + """ + Generate a source file for testing. + + The source will be written into a file named like the test-function. This file will then be passed to + `test_script`. If you need other related file, e.g. as `.toc`-file for testing the content, put it at at the + normal place. Just mind to take the basnename from the test-function's name. + + :param script: Source code to create executable from. This will be saved into a temporary file which is then + passed on to `test_script`. + + :param test_id: Test-id for parametrized tests. If given, it will be appended to the script filename, + separated by two underscores. + + Ensure that the caller of `test_source` is in a UTF-8 encoded file with the correct '# -*- coding: utf-8 -*-' + marker. + """ + testname = inspect.stack()[1][3] + if test_id: + # For parametrized test append the test-id. + testname = testname + '__' + test_id + + # Periods are not allowed in Python module names. + testname = testname.replace('.', '_') + scriptfile = tmpdir / (testname + '.py') + source = textwrap.dedent(source) + with scriptfile.open('w', encoding='utf-8') as ofh: + print('# -*- coding: utf-8 -*-', file=ofh) + print(source, file=ofh) + return scriptfile diff --git a/venv/Lib/site-packages/PyInstaller/utils/win32/__init__.py b/venv/Lib/site-packages/PyInstaller/utils/win32/__init__.py new file mode 100644 index 0000000..a7501ae --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/utils/win32/__init__.py @@ -0,0 +1 @@ +__author__ = 'martin' diff --git a/venv/Lib/site-packages/PyInstaller/utils/win32/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/utils/win32/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..460b634 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/utils/win32/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/utils/win32/__pycache__/icon.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/utils/win32/__pycache__/icon.cpython-311.pyc new file mode 100644 index 0000000..c71d822 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/utils/win32/__pycache__/icon.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/utils/win32/__pycache__/versioninfo.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/utils/win32/__pycache__/versioninfo.cpython-311.pyc new file mode 100644 index 0000000..eedd90b Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/utils/win32/__pycache__/versioninfo.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/utils/win32/__pycache__/winmanifest.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/utils/win32/__pycache__/winmanifest.cpython-311.pyc new file mode 100644 index 0000000..b515071 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/utils/win32/__pycache__/winmanifest.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/utils/win32/__pycache__/winresource.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/utils/win32/__pycache__/winresource.cpython-311.pyc new file mode 100644 index 0000000..50b3e75 Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/utils/win32/__pycache__/winresource.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/utils/win32/__pycache__/winutils.cpython-311.pyc b/venv/Lib/site-packages/PyInstaller/utils/win32/__pycache__/winutils.cpython-311.pyc new file mode 100644 index 0000000..f6ecf7f Binary files /dev/null and b/venv/Lib/site-packages/PyInstaller/utils/win32/__pycache__/winutils.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/PyInstaller/utils/win32/icon.py b/venv/Lib/site-packages/PyInstaller/utils/win32/icon.py new file mode 100644 index 0000000..e596464 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/utils/win32/icon.py @@ -0,0 +1,251 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- +""" +The code in this module supports the --icon parameter on Windows. +(For --icon support under Mac OS, see building/osx.py.) + +The only entry point, called from api.py, is CopyIcons(), below. All the elaborate structure of classes that follows +is used to support the operation of CopyIcons_FromIco(). None of these classes and globals are referenced outside +this module. +""" + +import os +import os.path +import struct + +import PyInstaller.log as logging +from PyInstaller import config +from PyInstaller.compat import pywintypes, win32api +from PyInstaller.building.icon import normalize_icon_type + +logger = logging.getLogger(__name__) + +RT_ICON = 3 +RT_GROUP_ICON = 14 +LOAD_LIBRARY_AS_DATAFILE = 2 + + +class Structure: + def __init__(self): + size = self._sizeInBytes = struct.calcsize(self._format_) + self._fields_ = list(struct.unpack(self._format_, b'\000' * size)) + indexes = self._indexes_ = {} + for i, nm in enumerate(self._names_): + indexes[nm] = i + + def dump(self): + logger.info("DUMP of %s", self) + for name in self._names_: + if not name.startswith('_'): + logger.info("%20s = %s", name, getattr(self, name)) + logger.info("") + + def __getattr__(self, name): + if name in self._names_: + index = self._indexes_[name] + return self._fields_[index] + try: + return self.__dict__[name] + except KeyError as e: + raise AttributeError(name) from e + + def __setattr__(self, name, value): + if name in self._names_: + index = self._indexes_[name] + self._fields_[index] = value + else: + self.__dict__[name] = value + + def tostring(self): + return struct.pack(self._format_, *self._fields_) + + def fromfile(self, file): + data = file.read(self._sizeInBytes) + self._fields_ = list(struct.unpack(self._format_, data)) + + +class ICONDIRHEADER(Structure): + _names_ = "idReserved", "idType", "idCount" + _format_ = "hhh" + + +class ICONDIRENTRY(Structure): + _names_ = ("bWidth", "bHeight", "bColorCount", "bReserved", "wPlanes", "wBitCount", "dwBytesInRes", "dwImageOffset") + _format_ = "bbbbhhii" + + +class GRPICONDIR(Structure): + _names_ = "idReserved", "idType", "idCount" + _format_ = "hhh" + + +class GRPICONDIRENTRY(Structure): + _names_ = ("bWidth", "bHeight", "bColorCount", "bReserved", "wPlanes", "wBitCount", "dwBytesInRes", "nID") + _format_ = "bbbbhhih" + + +# An IconFile instance is created for each .ico file given. +class IconFile: + def __init__(self, path): + self.path = path + try: + # The path is from the user parameter, don't trust it. + file = open(self.path, "rb") + except OSError: + # The icon file can't be opened for some reason. Stop the + # program with an informative message. + raise SystemExit(f'Unable to open icon file {self.path}!') + with file: + self.entries = [] + self.images = [] + header = self.header = ICONDIRHEADER() + header.fromfile(file) + for i in range(header.idCount): + entry = ICONDIRENTRY() + entry.fromfile(file) + self.entries.append(entry) + for e in self.entries: + file.seek(e.dwImageOffset, 0) + self.images.append(file.read(e.dwBytesInRes)) + + def grp_icon_dir(self): + return self.header.tostring() + + def grp_icondir_entries(self, id=1): + data = b'' + for entry in self.entries: + e = GRPICONDIRENTRY() + for n in e._names_[:-1]: + setattr(e, n, getattr(entry, n)) + e.nID = id + id = id + 1 + data = data + e.tostring() + return data + + +def CopyIcons_FromIco(dstpath, srcpath, id=1): + """ + Use the Win API UpdateResource facility to apply the icon resource(s) to the .exe file. + + :param str dstpath: absolute path of the .exe file being built. + :param str srcpath: list of 1 or more .ico file paths + """ + icons = map(IconFile, srcpath) + logger.debug("Copying icons from %s", srcpath) + + hdst = win32api.BeginUpdateResource(dstpath, 0) + + iconid = 1 + # Each step in the following enumerate() will instantiate an IconFile object, as a result of deferred execution + # of the map() above. + for i, f in enumerate(icons): + data = f.grp_icon_dir() + data = data + f.grp_icondir_entries(iconid) + win32api.UpdateResource(hdst, RT_GROUP_ICON, i + 1, data) + logger.debug("Writing RT_GROUP_ICON %d resource with %d bytes", i + 1, len(data)) + for data in f.images: + win32api.UpdateResource(hdst, RT_ICON, iconid, data) + logger.debug("Writing RT_ICON %d resource with %d bytes", iconid, len(data)) + iconid = iconid + 1 + + win32api.EndUpdateResource(hdst, 0) + + +def CopyIcons(dstpath, srcpath): + """ + Called from building/api.py to handle icons. If the input was by --icon on the command line, srcpath is a single + string. However, it is possible to modify the spec file adding icon=['foo.ico','bar.ico'] to the EXE() statement. + In that case, srcpath is a list of strings. + + The string format is either path-to-.ico or path-to-.exe,n for n an integer resource index in the .exe. In either + case, the path can be relative or absolute. + """ + + if isinstance(srcpath, (str, os.PathLike)): + # Just a single string, make it a one-element list. + srcpath = [srcpath] + # Convert possible PathLike elements to strings to allow the splitter function to work. + srcpath = [str(path) for path in srcpath] + + def splitter(s): + """ + Convert "pathname" to tuple ("pathname", None) + Convert "pathname,n" to tuple ("pathname", n) + """ + try: + srcpath, index = s.split(',') + return srcpath.strip(), int(index) + except ValueError: + return s, None + + # split all the items in the list into tuples as above. + srcpath = list(map(splitter, srcpath)) + + if len(srcpath) > 1: + # More than one icon source given. We currently handle multiple icons by calling CopyIcons_FromIco(), which only + # allows .ico, but will convert to that format if needed. + # + # Note that a ",index" on a .ico is just ignored in the single or multiple case. + srcs = [] + for s in srcpath: + srcs.append(normalize_icon_type(s[0], ("ico",), "ico", config.CONF["workpath"])) + return CopyIcons_FromIco(dstpath, srcs) + + # Just one source given. + srcpath, index = srcpath[0] + + # Makes sure the icon exists and attempts to convert to the proper format if applicable + srcpath = normalize_icon_type(srcpath, ("exe", "ico"), "ico", config.CONF["workpath"]) + + srcext = os.path.splitext(srcpath)[1] + + # Handle the simple case of foo.ico, ignoring any index. + if srcext.lower() == '.ico': + return CopyIcons_FromIco(dstpath, [srcpath]) + + # Single source is not .ico, presumably it is .exe (and if not, some error will occur). + if index is not None: + logger.debug("Copying icon from %s, %d", srcpath, index) + else: + logger.debug("Copying icons from %s", srcpath) + + try: + # Attempt to load the .ico or .exe containing the icon into memory using the same mechanism as if it were a DLL. + # If this fails for any reason (for example if the file does not exist or is not a .ico/.exe) then LoadLibraryEx + # returns a null handle and win32api raises a unique exception with a win error code and a string. + hsrc = win32api.LoadLibraryEx(srcpath, 0, LOAD_LIBRARY_AS_DATAFILE) + except pywintypes.error as W32E: + # We could continue with no icon (i.e., just return), but it seems best to terminate the build with a message. + raise SystemExit( + "Unable to load icon file {}\n {} (Error code {})".format(srcpath, W32E.strerror, W32E.winerror) + ) + hdst = win32api.BeginUpdateResource(dstpath, 0) + if index is None: + grpname = win32api.EnumResourceNames(hsrc, RT_GROUP_ICON)[0] + elif index >= 0: + grpname = win32api.EnumResourceNames(hsrc, RT_GROUP_ICON)[index] + else: + grpname = -index + data = win32api.LoadResource(hsrc, RT_GROUP_ICON, grpname) + win32api.UpdateResource(hdst, RT_GROUP_ICON, grpname, data) + for iconname in win32api.EnumResourceNames(hsrc, RT_ICON): + data = win32api.LoadResource(hsrc, RT_ICON, iconname) + win32api.UpdateResource(hdst, RT_ICON, iconname, data) + win32api.FreeLibrary(hsrc) + win32api.EndUpdateResource(hdst, 0) + + +if __name__ == "__main__": + import sys + + dstpath = sys.argv[1] + srcpath = sys.argv[2:] + CopyIcons(dstpath, srcpath) diff --git a/venv/Lib/site-packages/PyInstaller/utils/win32/versioninfo.py b/venv/Lib/site-packages/PyInstaller/utils/win32/versioninfo.py new file mode 100644 index 0000000..4a56425 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/utils/win32/versioninfo.py @@ -0,0 +1,605 @@ +# -*- coding: utf-8 -*- +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- + +import struct + +import pefile + +from PyInstaller.compat import win32api + + +def pefile_check_control_flow_guard(filename): + """ + Checks if the specified PE file has CFG (Control Flow Guard) enabled. + + Parameters + ---------- + filename : str + Path to the PE file to inspect. + + Returns + ---------- + bool + True if file is a PE file with CFG enabled. False if CFG is not enabled or if file could not be processed using + the pefile library. + """ + try: + pe = pefile.PE(filename, fast_load=True) + # https://docs.microsoft.com/en-us/windows/win32/debug/pe-format + # IMAGE_DLLCHARACTERISTICS_GUARD_CF = 0x4000 + return bool(pe.OPTIONAL_HEADER.DllCharacteristics & 0x4000) + except Exception: + return False + + +# Ensures no code from the executable is executed. +LOAD_LIBRARY_AS_DATAFILE = 2 + + +def getRaw(text): + """ + Encodes text as UTF-16LE (Microsoft 'Unicode') for use in structs. + """ + return text.encode('UTF-16LE') + + +def read_version_info_from_executable(exe_filename): + """ + Read the version information structure from the given executable's resources, and return it as an instance of + `VSVersionInfo` structure. + """ + h = win32api.LoadLibraryEx(exe_filename, 0, LOAD_LIBRARY_AS_DATAFILE) + res = win32api.EnumResourceNames(h, pefile.RESOURCE_TYPE['RT_VERSION']) + if not len(res): + return None + data = win32api.LoadResource(h, pefile.RESOURCE_TYPE['RT_VERSION'], res[0]) + info = VSVersionInfo() + info.fromRaw(data) + win32api.FreeLibrary(h) + return info + + +def nextDWord(offset): + """ + Align `offset` to the next 4-byte boundary. + """ + return ((offset + 3) >> 2) << 2 + + +class VSVersionInfo: + """ + WORD wLength; // length of the VS_VERSION_INFO structure + WORD wValueLength; // length of the Value member + WORD wType; // 1 means text, 0 means binary + WCHAR szKey[]; // Contains the Unicode string "VS_VERSION_INFO". + WORD Padding1[]; + VS_FIXEDFILEINFO Value; + WORD Padding2[]; + WORD Children[]; // zero or more StringFileInfo or VarFileInfo + // structures (or both) that are children of the + // current version structure. + """ + def __init__(self, ffi=None, kids=None): + self.ffi = ffi + self.kids = kids or [] + + def fromRaw(self, data): + i, (sublen, vallen, wType, nm) = parseCommon(data) + #vallen is length of the ffi, typ is 0, nm is 'VS_VERSION_INFO'. + i = nextDWord(i) + # Now a VS_FIXEDFILEINFO + self.ffi = FixedFileInfo() + j = self.ffi.fromRaw(data, i) + i = j + while i < sublen: + j = i + i, (csublen, cvallen, ctyp, nm) = parseCommon(data, i) + if nm.strip() == 'StringFileInfo': + sfi = StringFileInfo() + k = sfi.fromRaw(csublen, cvallen, nm, data, i, j + csublen) + self.kids.append(sfi) + i = k + else: + vfi = VarFileInfo() + k = vfi.fromRaw(csublen, cvallen, nm, data, i, j + csublen) + self.kids.append(vfi) + i = k + i = j + csublen + i = nextDWord(i) + return i + + def toRaw(self): + raw_name = getRaw('VS_VERSION_INFO') + rawffi = self.ffi.toRaw() + vallen = len(rawffi) + typ = 0 + sublen = 6 + len(raw_name) + 2 + pad = b'' + if sublen % 4: + pad = b'\000\000' + sublen = sublen + len(pad) + vallen + pad2 = b'' + if sublen % 4: + pad2 = b'\000\000' + tmp = b''.join([kid.toRaw() for kid in self.kids]) + sublen = sublen + len(pad2) + len(tmp) + return struct.pack('hhh', sublen, vallen, typ) + raw_name + b'\000\000' + pad + rawffi + pad2 + tmp + + def __eq__(self, other): + return self.toRaw() == other + + def __str__(self, indent=''): + indent = indent + ' ' + tmp = [kid.__str__(indent + ' ') for kid in self.kids] + tmp = ', \n'.join(tmp) + return '\n'.join([ + "# UTF-8", + "#", + "# For more details about fixed file info 'ffi' see:", + "# http://msdn.microsoft.com/en-us/library/ms646997.aspx", + "VSVersionInfo(", + indent + f"ffi={self.ffi.__str__(indent)},", + indent + "kids=[", + tmp, + indent + "]", + ")", + ]) + + def __repr__(self): + return "versioninfo.VSVersionInfo(ffi=%r, kids=%r)" % (self.ffi, self.kids) + + +def parseCommon(data, start=0): + i = start + 6 + (wLength, wValueLength, wType) = struct.unpack('3h', data[start:i]) + i, text = parseUString(data, i, i + wLength) + return i, (wLength, wValueLength, wType, text) + + +def parseUString(data, start, limit): + i = start + while i < limit: + if data[i:i + 2] == b'\000\000': + break + i += 2 + text = data[start:i].decode('UTF-16LE') + i += 2 + return i, text + + +class FixedFileInfo: + """ + DWORD dwSignature; //Contains the value 0xFEEFO4BD + DWORD dwStrucVersion; // binary version number of this structure. + // The high-order word of this member contains + // the major version number, and the low-order + // word contains the minor version number. + DWORD dwFileVersionMS; // most significant 32 bits of the file's binary + // version number + DWORD dwFileVersionLS; // + DWORD dwProductVersionMS; // most significant 32 bits of the binary version + // number of the product with which this file was + // distributed + DWORD dwProductVersionLS; // + DWORD dwFileFlagsMask; // bitmask that specifies the valid bits in + // dwFileFlags. A bit is valid only if it was + // defined when the file was created. + DWORD dwFileFlags; // VS_FF_DEBUG, VS_FF_PATCHED etc. + DWORD dwFileOS; // VOS_NT, VOS_WINDOWS32 etc. + DWORD dwFileType; // VFT_APP etc. + DWORD dwFileSubtype; // 0 unless VFT_DRV or VFT_FONT or VFT_VXD + DWORD dwFileDateMS; + DWORD dwFileDateLS; + """ + def __init__( + self, + filevers=(0, 0, 0, 0), + prodvers=(0, 0, 0, 0), + mask=0x3f, + flags=0x0, + OS=0x40004, + fileType=0x1, + subtype=0x0, + date=(0, 0) + ): + self.sig = 0xfeef04bd + self.strucVersion = 0x10000 + self.fileVersionMS = (filevers[0] << 16) | (filevers[1] & 0xffff) + self.fileVersionLS = (filevers[2] << 16) | (filevers[3] & 0xffff) + self.productVersionMS = (prodvers[0] << 16) | (prodvers[1] & 0xffff) + self.productVersionLS = (prodvers[2] << 16) | (prodvers[3] & 0xffff) + self.fileFlagsMask = mask + self.fileFlags = flags + self.fileOS = OS + self.fileType = fileType + self.fileSubtype = subtype + self.fileDateMS = date[0] + self.fileDateLS = date[1] + + def fromRaw(self, data, i): + ( + self.sig, + self.strucVersion, + self.fileVersionMS, + self.fileVersionLS, + self.productVersionMS, + self.productVersionLS, + self.fileFlagsMask, + self.fileFlags, + self.fileOS, + self.fileType, + self.fileSubtype, + self.fileDateMS, + self.fileDateLS, + ) = struct.unpack('13L', data[i:i + 52]) + return i + 52 + + def toRaw(self): + return struct.pack( + '13L', + self.sig, + self.strucVersion, + self.fileVersionMS, + self.fileVersionLS, + self.productVersionMS, + self.productVersionLS, + self.fileFlagsMask, + self.fileFlags, + self.fileOS, + self.fileType, + self.fileSubtype, + self.fileDateMS, + self.fileDateLS, + ) + + def __eq__(self, other): + return self.toRaw() == other + + def __str__(self, indent=''): + fv = ( + self.fileVersionMS >> 16, self.fileVersionMS & 0xffff, + self.fileVersionLS >> 16, self.fileVersionLS & 0xffff, + ) # yapf: disable + pv = ( + self.productVersionMS >> 16, self.productVersionMS & 0xffff, + self.productVersionLS >> 16, self.productVersionLS & 0xffff, + ) # yapf: disable + fd = (self.fileDateMS, self.fileDateLS) + tmp = [ + 'FixedFileInfo(', + '# filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4)', + '# Set not needed items to zero 0.', + 'filevers=%s,' % (fv,), + 'prodvers=%s,' % (pv,), + "# Contains a bitmask that specifies the valid bits 'flags'r", + 'mask=%s,' % hex(self.fileFlagsMask), + '# Contains a bitmask that specifies the Boolean attributes of the file.', + 'flags=%s,' % hex(self.fileFlags), + '# The operating system for which this file was designed.', + '# 0x4 - NT and there is no need to change it.', + 'OS=%s,' % hex(self.fileOS), + '# The general type of file.', + '# 0x1 - the file is an application.', + 'fileType=%s,' % hex(self.fileType), + '# The function of the file.', + '# 0x0 - the function is not defined for this fileType', + 'subtype=%s,' % hex(self.fileSubtype), + '# Creation date and time stamp.', + 'date=%s' % (fd,), + ')', + ] + return f'\n{indent} '.join(tmp) + + def __repr__(self): + fv = ( + self.fileVersionMS >> 16, self.fileVersionMS & 0xffff, + self.fileVersionLS >> 16, self.fileVersionLS & 0xffff, + ) # yapf: disable + pv = ( + self.productVersionMS >> 16, self.productVersionMS & 0xffff, + self.productVersionLS >> 16, self.productVersionLS & 0xffff, + ) # yapf: disable + fd = (self.fileDateMS, self.fileDateLS) + return ( + 'versioninfo.FixedFileInfo(filevers=%r, prodvers=%r, ' + 'mask=0x%x, flags=0x%x, OS=0x%x, ' + 'fileType=%r, subtype=0x%x, date=%r)' % + (fv, pv, self.fileFlagsMask, self.fileFlags, self.fileOS, self.fileType, self.fileSubtype, fd) + ) + + +class StringFileInfo: + """ + WORD wLength; // length of the version resource + WORD wValueLength; // length of the Value member in the current + // VS_VERSION_INFO structure + WORD wType; // 1 means text, 0 means binary + WCHAR szKey[]; // Contains the Unicode string 'StringFileInfo'. + WORD Padding[]; + StringTable Children[]; // list of zero or more String structures + """ + def __init__(self, kids=None): + self.name = 'StringFileInfo' + self.kids = kids or [] + + def fromRaw(self, sublen, vallen, name, data, i, limit): + self.name = name + while i < limit: + st = StringTable() + j = st.fromRaw(data, i, limit) + self.kids.append(st) + i = j + return i + + def toRaw(self): + raw_name = getRaw(self.name) + vallen = 0 + typ = 1 + sublen = 6 + len(raw_name) + 2 + pad = b'' + if sublen % 4: + pad = b'\000\000' + tmp = b''.join([kid.toRaw() for kid in self.kids]) + sublen = sublen + len(pad) + len(tmp) + return struct.pack('hhh', sublen, vallen, typ) + raw_name + b'\000\000' + pad + tmp + + def __eq__(self, other): + return self.toRaw() == other + + def __str__(self, indent=''): + new_indent = indent + ' ' + tmp = ', \n'.join(kid.__str__(new_indent) for kid in self.kids) + return f'{indent}StringFileInfo(\n{new_indent}[\n{tmp}\n{new_indent}])' + + def __repr__(self): + return 'versioninfo.StringFileInfo(%r)' % self.kids + + +class StringTable: + """ + WORD wLength; + WORD wValueLength; + WORD wType; + WCHAR szKey[]; + String Children[]; // list of zero or more String structures. + """ + def __init__(self, name=None, kids=None): + self.name = name or '' + self.kids = kids or [] + + def fromRaw(self, data, i, limit): + i, (cpsublen, cpwValueLength, cpwType, self.name) = parseCodePage(data, i, limit) # should be code page junk + i = nextDWord(i) + while i < limit: + ss = StringStruct() + j = ss.fromRaw(data, i, limit) + i = j + self.kids.append(ss) + i = nextDWord(i) + return i + + def toRaw(self): + raw_name = getRaw(self.name) + vallen = 0 + typ = 1 + sublen = 6 + len(raw_name) + 2 + tmp = [] + for kid in self.kids: + raw = kid.toRaw() + if len(raw) % 4: + raw = raw + b'\000\000' + tmp.append(raw) + tmp = b''.join(tmp) + sublen += len(tmp) + return struct.pack('hhh', sublen, vallen, typ) + raw_name + b'\000\000' + tmp + + def __eq__(self, other): + return self.toRaw() == other + + def __str__(self, indent=''): + new_indent = indent + ' ' + tmp = (',\n' + new_indent).join(str(kid) for kid in self.kids) + return f"{indent}StringTable(\n{new_indent}'{self.name}',\n{new_indent}[{tmp}])" + + def __repr__(self): + return 'versioninfo.StringTable(%r, %r)' % (self.name, self.kids) + + +class StringStruct: + """ + WORD wLength; + WORD wValueLength; + WORD wType; + WCHAR szKey[]; + WORD Padding[]; + String Value[]; + """ + def __init__(self, name=None, val=None): + self.name = name or '' + self.val = val or '' + + def fromRaw(self, data, i, limit): + i, (sublen, vallen, typ, self.name) = parseCommon(data, i) + limit = i + sublen + i = nextDWord(i) + i, self.val = parseUString(data, i, limit) + return i + + def toRaw(self): + raw_name = getRaw(self.name) + raw_val = getRaw(self.val) + # TODO: document the size of vallen and sublen. + vallen = len(self.val) + 1 # Number of (wide-)characters, not bytes! + typ = 1 + sublen = 6 + len(raw_name) + 2 + pad = b'' + if sublen % 4: + pad = b'\000\000' + sublen = sublen + len(pad) + (vallen * 2) + return struct.pack('hhh', sublen, vallen, typ) + raw_name + b'\000\000' + pad + raw_val + b'\000\000' + + def __eq__(self, other): + return self.toRaw() == other + + def __str__(self, indent=''): + return "StringStruct(%r, %r)" % (self.name, self.val) + + def __repr__(self): + return 'versioninfo.StringStruct(%r, %r)' % (self.name, self.val) + + +def parseCodePage(data, i, limit): + i, (sublen, wValueLength, wType, nm) = parseCommon(data, i) + return i, (sublen, wValueLength, wType, nm) + + +class VarFileInfo: + """ + WORD wLength; // length of the version resource + WORD wValueLength; // length of the Value member in the current + // VS_VERSION_INFO structure + WORD wType; // 1 means text, 0 means binary + WCHAR szKey[]; // Contains the Unicode string 'VarFileInfo'. + WORD Padding[]; + Var Children[]; // list of zero or more Var structures + """ + def __init__(self, kids=None): + self.kids = kids or [] + + def fromRaw(self, sublen, vallen, name, data, i, limit): + self.sublen = sublen + self.vallen = vallen + self.name = name + i = nextDWord(i) + while i < limit: + vs = VarStruct() + j = vs.fromRaw(data, i, limit) + self.kids.append(vs) + i = j + return i + + def toRaw(self): + self.vallen = 0 + self.wType = 1 + self.name = 'VarFileInfo' + raw_name = getRaw(self.name) + sublen = 6 + len(raw_name) + 2 + pad = b'' + if sublen % 4: + pad = b'\000\000' + tmp = b''.join([kid.toRaw() for kid in self.kids]) + self.sublen = sublen + len(pad) + len(tmp) + return struct.pack('hhh', self.sublen, self.vallen, self.wType) + raw_name + b'\000\000' + pad + tmp + + def __eq__(self, other): + return self.toRaw() == other + + def __str__(self, indent=''): + return indent + "VarFileInfo([%s])" % ', '.join(str(kid) for kid in self.kids) + + def __repr__(self): + return 'versioninfo.VarFileInfo(%r)' % self.kids + + +class VarStruct: + """ + WORD wLength; // length of the version resource + WORD wValueLength; // length of the Value member in the current + // VS_VERSION_INFO structure + WORD wType; // 1 means text, 0 means binary + WCHAR szKey[]; // Contains the Unicode string 'Translation' + // or a user-defined key string value + WORD Padding[]; // + WORD Value[]; // list of one or more values that are language + // and code-page identifiers + """ + def __init__(self, name=None, kids=None): + self.name = name or '' + self.kids = kids or [] + + def fromRaw(self, data, i, limit): + i, (self.sublen, self.wValueLength, self.wType, self.name) = parseCommon(data, i) + i = nextDWord(i) + for j in range(0, self.wValueLength, 2): + kid = struct.unpack('h', data[i:i + 2])[0] + self.kids.append(kid) + i += 2 + return i + + def toRaw(self): + self.wValueLength = len(self.kids) * 2 + self.wType = 0 + raw_name = getRaw(self.name) + sublen = 6 + len(raw_name) + 2 + pad = b'' + if sublen % 4: + pad = b'\000\000' + self.sublen = sublen + len(pad) + self.wValueLength + tmp = b''.join([struct.pack('h', kid) for kid in self.kids]) + return struct.pack('hhh', self.sublen, self.wValueLength, self.wType) + raw_name + b'\000\000' + pad + tmp + + def __eq__(self, other): + return self.toRaw() == other + + def __str__(self, indent=''): + return "VarStruct('%s', %r)" % (self.name, self.kids) + + def __repr__(self): + return 'versioninfo.VarStruct(%r, %r)' % (self.name, self.kids) + + +def load_version_info_from_text_file(filename): + """ + Load the `VSVersionInfo` structure from its string-based (`VSVersionInfo.__str__`) serialization by reading the + text from the file and running it through `eval()`. + """ + + # Read and parse the version file. It may have a byte order marker or encoding cookie - respect it if it does. + import PyInstaller.utils.misc as miscutils + with open(filename, 'rb') as fp: + text = miscutils.decode(fp.read()) + + # Deserialize via eval() + try: + info = eval(text) + except Exception as e: + raise ValueError("Failed to deserialize VSVersionInfo from text-based representation!") from e + + # Sanity check + assert isinstance(info, VSVersionInfo), \ + f"Loaded incompatible structure type! Expected VSVersionInfo, got: {type(info)!r}" + + return info + + +def write_version_info_to_executable(exe_filename, info): + assert isinstance(info, VSVersionInfo) + + # Remember overlay + pe = pefile.PE(exe_filename, fast_load=True) + overlay_before = pe.get_overlay() + pe.close() + + hdst = win32api.BeginUpdateResource(exe_filename, 0) + win32api.UpdateResource(hdst, pefile.RESOURCE_TYPE['RT_VERSION'], 1, info.toRaw()) + win32api.EndUpdateResource(hdst, 0) + + if overlay_before: + # Check if the overlay is still present + pe = pefile.PE(exe_filename, fast_load=True) + overlay_after = pe.get_overlay() + pe.close() + + # If the update removed the overlay data, re-append it + if not overlay_after: + with open(exe_filename, 'ab') as exef: + exef.write(overlay_before) diff --git a/venv/Lib/site-packages/PyInstaller/utils/win32/winmanifest.py b/venv/Lib/site-packages/PyInstaller/utils/win32/winmanifest.py new file mode 100644 index 0000000..1d338df --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/utils/win32/winmanifest.py @@ -0,0 +1,244 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- +import xml.dom +import xml.dom.minidom + +#- Relevant constants from Windows headers +# Manifest resource code +RT_MANIFEST = 24 + +# Resource IDs (names) for manifest. +# See: https://www.gamedev.net/blogs/entry/2154553-manifest-embedding-and-activation +CREATEPROCESS_MANIFEST_RESOURCE_ID = 1 +ISOLATIONAWARE_MANIFEST_RESOURCE_ID = 2 + +LANG_NEUTRAL = 0 + +#- Default application manifest template, based on the one found in python executable. + +_DEFAULT_MANIFEST_XML = \ +b""" + + + + + + + + + + + + + + + + + + + + true + + + + + + + + +""" # noqa: E122,E501 + +#- DOM navigation helpers + + +def _find_elements_by_tag(root, tag): + """ + Find all elements with given tag under the given root element. + """ + return [node for node in root.childNodes if node.nodeType == xml.dom.Node.ELEMENT_NODE and node.tagName == tag] + + +def _find_element_by_tag(root, tag): + """ + Attempt to find a single element with given tag under the given root element, and return None if no such element + is found. Raises an error if multiple elements are found. + """ + elements = _find_elements_by_tag(root, tag) + if len(elements) > 1: + raise ValueError(f"Expected a single {tag!r} element, found {len(elements)} element(s)!") + if not elements: + return None + return elements[0] + + +#- Application manifest modification helpers + + +def _set_execution_level(manifest_dom, root_element, uac_admin=False, uac_uiaccess=False): + """ + Find -> -> element, and set its `level` and `uiAccess` + attributes based on supplied arguments. Create the XML elements if necessary, as they are optional. + """ + + # + trust_info_element = _find_element_by_tag(root_element, "trustInfo") + if not trust_info_element: + trust_info_element = manifest_dom.createElement("trustInfo") + trust_info_element.setAttribute("xmlns", "urn:schemas-microsoft-com:asm.v3") + root_element.appendChild(trust_info_element) + + # + security_element = _find_element_by_tag(trust_info_element, "security") + if not security_element: + security_element = manifest_dom.createElement("security") + trust_info_element.appendChild(security_element) + + # + requested_privileges_element = _find_element_by_tag(security_element, "requestedPrivileges") + if not requested_privileges_element: + requested_privileges_element = manifest_dom.createElement("requestedPrivileges") + security_element.appendChild(requested_privileges_element) + + # + requested_execution_level_element = _find_element_by_tag(requested_privileges_element, "requestedExecutionLevel") + if not requested_execution_level_element: + requested_execution_level_element = manifest_dom.createElement("requestedExecutionLevel") + requested_privileges_element.appendChild(requested_execution_level_element) + + requested_execution_level_element.setAttribute("level", "requireAdministrator" if uac_admin else "asInvoker") + requested_execution_level_element.setAttribute("uiAccess", "true" if uac_uiaccess else "false") + + +def _ensure_common_controls_dependency(manifest_dom, root_element): + """ + Scan elements for the one whose < -> corresponds to the + `Microsoft.Windows.Common-Controls`. If found, overwrite its properties. If not, create new + element with corresponding sub-elements and attributes. + """ + + # + dependency_elements = _find_elements_by_tag(root_element, "dependency") + for dependency_element in dependency_elements: + # + dependent_assembly_element = _find_element_by_tag(dependency_element, "dependentAssembly") + # + assembly_identity_element = _find_element_by_tag(dependent_assembly_element, "assemblyIdentity") + # Check the name attribute + if assembly_identity_element.attributes["name"].value == "Microsoft.Windows.Common-Controls": + common_controls_element = assembly_identity_element + break + else: + # Create + dependency_element = manifest_dom.createElement("dependency") + root_element.appendChild(dependency_element) + # Create + dependent_assembly_element = manifest_dom.createElement("dependentAssembly") + dependency_element.appendChild(dependent_assembly_element) + # Create + common_controls_element = manifest_dom.createElement("assemblyIdentity") + dependent_assembly_element.appendChild(common_controls_element) + + common_controls_element.setAttribute("type", "win32") + common_controls_element.setAttribute("name", "Microsoft.Windows.Common-Controls") + common_controls_element.setAttribute("version", "6.0.0.0") + common_controls_element.setAttribute("processorArchitecture", "*") + common_controls_element.setAttribute("publicKeyToken", "6595b64144ccf1df") + common_controls_element.setAttribute("language", "*") + + +def create_application_manifest(manifest_xml=None, uac_admin=False, uac_uiaccess=False): + """ + Create application manifest, from built-in or custom manifest XML template. If provided, `manifest_xml` must be + a string or byte string containing XML source. The returned manifest is a byte string, encoded in UTF-8. + + This function sets the attributes of `requestedExecutionLevel` based on provided `uac_admin` and `auc_uiacces` + arguments (creating the parent elements in the XML, if necessary). It also scans `dependency` elements for the + entry corresponding to `Microsoft.Windows.Common-Controls` and creates or modifies it as necessary. + """ + + if manifest_xml is None: + manifest_xml = _DEFAULT_MANIFEST_XML + + with xml.dom.minidom.parseString(manifest_xml) as manifest_dom: + root_element = manifest_dom.documentElement + + # Validate root element - must be + assert root_element.tagName == "assembly" + assert root_element.namespaceURI == "urn:schemas-microsoft-com:asm.v1" + assert root_element.attributes["manifestVersion"].value == "1.0" + + # Modify the manifest + _set_execution_level(manifest_dom, root_element, uac_admin, uac_uiaccess) + _ensure_common_controls_dependency(manifest_dom, root_element) + + # Create output XML + output = manifest_dom.toprettyxml(indent=" ", encoding="UTF-8") + + # Strip extra newlines + output = [line for line in output.splitlines() if line.strip()] + + # Replace: `` with ``. + # Support for `standalone` was added to `toprettyxml` in python 3.9, so do a manual work around. + output[0] = b"""""" + + output = b"\n".join(output) + + return output + + +def write_manifest_to_executable(filename, manifest_xml): + """ + Write the given manifest XML to the given executable's RT_MANIFEST resource. + """ + from PyInstaller.utils.win32 import winresource + + # CREATEPROCESS_MANIFEST_RESOURCE_ID is used for manifest resource in executables. + # ISOLATIONAWARE_MANIFEST_RESOURCE_ID is used for manifest resources in DLLs. + names = [CREATEPROCESS_MANIFEST_RESOURCE_ID] + + # Ensure LANG_NEUTRAL is updated, and also update any other present languages. + languages = [LANG_NEUTRAL, "*"] + + winresource.add_or_update_resource(filename, manifest_xml, RT_MANIFEST, names, languages) + + +def read_manifest_from_executable(filename): + """ + Read manifest from the given executable." + """ + from PyInstaller.utils.win32 import winresource + + resources = winresource.get_resources(filename, [RT_MANIFEST]) + + # `resources` is a three-level dictionary: + # - level 1: resource type (RT_MANIFEST) + # - level 2: resource name (CREATEPROCESS_MANIFEST_RESOURCE_ID) + # - level 3: resource language (LANG_NEUTRAL) + + # Level 1 + if RT_MANIFEST not in resources: + raise ValueError(f"No RT_MANIFEST resources found in {filename!r}.") + resources = resources[RT_MANIFEST] + + # Level 2 + if CREATEPROCESS_MANIFEST_RESOURCE_ID not in resources: + raise ValueError(f"No RT_MANIFEST resource named CREATEPROCESS_MANIFEST_RESOURCE_ID found in {filename!r}.") + resources = resources[CREATEPROCESS_MANIFEST_RESOURCE_ID] + + # Level 3 + # We prefer LANG_NEUTRAL, but allow fall back to the first available entry. + if LANG_NEUTRAL in resources: + resources = resources[LANG_NEUTRAL] + else: + resources = next(iter(resources.items())) + + manifest_xml = resources + return manifest_xml diff --git a/venv/Lib/site-packages/PyInstaller/utils/win32/winresource.py b/venv/Lib/site-packages/PyInstaller/utils/win32/winresource.py new file mode 100644 index 0000000..f21d66c --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/utils/win32/winresource.py @@ -0,0 +1,189 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- +""" +Read and write resources from/to Win32 PE files. +""" + +import PyInstaller.log as logging +from PyInstaller.compat import pywintypes, win32api + +logger = logging.getLogger(__name__) + +LOAD_LIBRARY_AS_DATAFILE = 2 +ERROR_BAD_EXE_FORMAT = 193 +ERROR_RESOURCE_DATA_NOT_FOUND = 1812 +ERROR_RESOURCE_TYPE_NOT_FOUND = 1813 +ERROR_RESOURCE_NAME_NOT_FOUND = 1814 +ERROR_RESOURCE_LANG_NOT_FOUND = 1815 + + +def get_resources(filename, types=None, names=None, languages=None): + """ + Retrieve resources from the given PE file. + + filename: path to the PE file. + types: a list of resource types (integers or strings) to search for (None = all). + names: a list of resource names (integers or strings) to search for (None = all). + languages: a list of resource languages (integers) to search for (None = all). + + Returns a dictionary of the form {type: {name: {language: data}}}, which might also be empty if no matching + resources were found. + """ + types = set(types) if types is not None else {"*"} + names = set(names) if names is not None else {"*"} + languages = set(languages) if languages is not None else {"*"} + + output = {} + + # Errors codes for which we swallow exceptions + _IGNORE_EXCEPTIONS = { + ERROR_RESOURCE_DATA_NOT_FOUND, + ERROR_RESOURCE_TYPE_NOT_FOUND, + ERROR_RESOURCE_NAME_NOT_FOUND, + ERROR_RESOURCE_LANG_NOT_FOUND, + } + + # Open file + module_handle = win32api.LoadLibraryEx(filename, 0, LOAD_LIBRARY_AS_DATAFILE) + + # Enumerate available resource types + try: + available_types = win32api.EnumResourceTypes(module_handle) + except pywintypes.error as e: + if e.args[0] not in _IGNORE_EXCEPTIONS: + raise + available_types = [] + + if "*" not in types: + available_types = [res_type for res_type in available_types if res_type in types] + + for res_type in available_types: + # Enumerate available names for the resource type. + try: + available_names = win32api.EnumResourceNames(module_handle, res_type) + except pywintypes.error as e: + if e.args[0] not in _IGNORE_EXCEPTIONS: + raise + continue + + if "*" not in names: + available_names = [res_name for res_name in available_names if res_name in names] + + for res_name in available_names: + # Enumerate available languages for the resource type and name combination. + try: + available_languages = win32api.EnumResourceLanguages(module_handle, res_type, res_name) + except pywintypes.error as e: + if e.args[0] not in _IGNORE_EXCEPTIONS: + raise + continue + + if "*" not in languages: + available_languages = [res_lang for res_lang in available_languages if res_lang in languages] + + for res_lang in available_languages: + # Read data + try: + data = win32api.LoadResource(module_handle, res_type, res_name, res_lang) + except pywintypes.error as e: + if e.args[0] not in _IGNORE_EXCEPTIONS: + raise + continue + + if res_type not in output: + output[res_type] = {} + if res_name not in output[res_type]: + output[res_type][res_name] = {} + output[res_type][res_name][res_lang] = data + + # Close file + win32api.FreeLibrary(module_handle) + + return output + + +def add_or_update_resource(filename, data, res_type, names=None, languages=None): + """ + Update or add a single resource in the PE file with the given binary data. + + filename: path to the PE file. + data: binary data to write to the resource. + res_type: resource type to add/update (integer or string). + names: a list of resource names (integers or strings) to update (None = all). + languages: a list of resource languages (integers) to update (None = all). + """ + if res_type == "*": + raise ValueError("res_type cannot be a wildcard (*)!") + + names = set(names) if names is not None else {"*"} + languages = set(languages) if languages is not None else {"*"} + + # Retrieve existing resources, filtered by the given resource type and given resource names and languages. + resources = get_resources(filename, [res_type], names, languages) + + # Add res_type, name, language combinations that are not already present + resources = resources.get(res_type, {}) # This is now a {name: {language: data}} dictionary + + for res_name in names: + if res_name == "*": + continue + if res_name not in resources: + resources[res_name] = {} + + for res_lang in languages: + if res_lang == "*": + continue + if res_lang not in resources[res_name]: + resources[res_name][res_lang] = None # Just an indicator + + # Add resource to the target file, overwriting the existing resources with same type, name, language combinations. + module_handle = win32api.BeginUpdateResource(filename, 0) + for res_name in resources.keys(): + for res_lang in resources[res_name].keys(): + win32api.UpdateResource(module_handle, res_type, res_name, data, res_lang) + win32api.EndUpdateResource(module_handle, 0) + + +def copy_resources_from_pe_file(filename, src_filename, types=None, names=None, languages=None): + """ + Update or add resources in the given PE file by copying them over from the specified source PE file. + + filename: path to the PE file. + src_filename: path to the source PE file. + types: a list of resource types (integers or strings) to add/update via copy for (None = all). + names: a list of resource names (integers or strings) to add/update via copy (None = all). + languages: a list of resource languages (integers) to add/update via copy (None = all). + """ + types = set(types) if types is not None else {"*"} + names = set(names) if names is not None else {"*"} + languages = set(languages) if languages is not None else {"*"} + + # Retrieve existing resources, filtered by the given resource type and given resource names and languages. + resources = get_resources(src_filename, types, names, languages) + + for res_type, resources_for_type in resources.items(): + if "*" not in types and res_type not in types: + continue + for res_name, resources_for_type_name in resources_for_type.items(): + if "*" not in names and res_name not in names: + continue + for res_lang, data in resources_for_type_name.items(): + if "*" not in languages and res_lang not in languages: + continue + add_or_update_resource(filename, data, res_type, [res_name], [res_lang]) + + +def remove_all_resources(filename): + """ + Remove all resources from the given PE file: + """ + module_handle = win32api.BeginUpdateResource(filename, True) # bDeleteExistingResources=True + win32api.EndUpdateResource(module_handle, False) diff --git a/venv/Lib/site-packages/PyInstaller/utils/win32/winutils.py b/venv/Lib/site-packages/PyInstaller/utils/win32/winutils.py new file mode 100644 index 0000000..d8716c3 --- /dev/null +++ b/venv/Lib/site-packages/PyInstaller/utils/win32/winutils.py @@ -0,0 +1,257 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-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) +#----------------------------------------------------------------------------- +""" +Utilities for Windows platform. +""" + +from PyInstaller import compat + + +def get_windows_dir(): + """ + Return the Windows directory, e.g., C:\\Windows. + """ + windir = compat.win32api.GetWindowsDirectory() + if not windir: + raise SystemExit("Error: Cannot determine Windows directory!") + return windir + + +def get_system_path(): + """ + Return the required Windows system paths. + """ + sys_dir = compat.win32api.GetSystemDirectory() + # Ensure C:\Windows\system32 and C:\Windows directories are always present in PATH variable. + # C:\Windows\system32 is valid even for 64-bit Windows. Access do DLLs are transparently redirected to + # C:\Windows\syswow64 for 64bit applactions. + # See http://msdn.microsoft.com/en-us/library/aa384187(v=vs.85).aspx + return [sys_dir, get_windows_dir()] + + +def get_pe_file_machine_type(filename): + """ + Return the machine type code from the header of the given PE file. + """ + import pefile + + with pefile.PE(filename, fast_load=True) as pe: + return pe.FILE_HEADER.Machine + + +def set_exe_build_timestamp(exe_path, timestamp): + """ + Modifies the executable's build timestamp by updating values in the corresponding PE headers. + """ + import pefile + + with pefile.PE(exe_path, fast_load=True) as pe: + # Manually perform a full load. We need it to load all headers, but specifying it in the constructor triggers + # byte statistics gathering that takes forever with large files. So we try to go around that... + pe.full_load() + + # Set build timestamp. + # See: https://0xc0decafe.com/malware-analyst-guide-to-pe-timestamps + timestamp = int(timestamp) + # Set timestamp field in FILE_HEADER + pe.FILE_HEADER.TimeDateStamp = timestamp + # MSVC-compiled executables contain (at least?) one DIRECTORY_ENTRY_DEBUG entry that also contains timestamp + # with same value as set in FILE_HEADER. So modify that as well, as long as it is set. + debug_entries = getattr(pe, 'DIRECTORY_ENTRY_DEBUG', []) + for debug_entry in debug_entries: + if debug_entry.struct.TimeDateStamp: + debug_entry.struct.TimeDateStamp = timestamp + + # Generate updated EXE data + data = pe.write() + + # Rewrite the exe + with open(exe_path, 'wb') as fp: + fp.write(data) + + +def update_exe_pe_checksum(exe_path): + """ + Compute the executable's PE checksum, and write it to PE headers. + + This optional checksum is supposed to protect the executable against corruption but some anti-viral software have + taken to flagging anything without it set correctly as malware. See issue #5579. + """ + import pefile + + # Compute checksum using our equivalent of the MapFileAndCheckSumW - for large files, it is significantly faster + # than pure-pyton pefile.PE.generate_checksum(). However, it requires the file to be on disk (i.e., cannot operate + # on a memory buffer). + try: + checksum = compute_exe_pe_checksum(exe_path) + except Exception as e: + raise RuntimeError("Failed to compute PE checksum!") from e + + # Update the checksum + with pefile.PE(exe_path, fast_load=True) as pe: + pe.OPTIONAL_HEADER.CheckSum = checksum + + # Generate updated EXE data + data = pe.write() + + # Rewrite the exe + with open(exe_path, 'wb') as fp: + fp.write(data) + + +def compute_exe_pe_checksum(exe_path): + """ + This is a replacement for the MapFileAndCheckSumW function. As noted in MSDN documentation, the Microsoft's + implementation of MapFileAndCheckSumW internally calls its ASCII variant (MapFileAndCheckSumA), and therefore + cannot handle paths that contain characters that are not representable in the current code page. + See: https://docs.microsoft.com/en-us/windows/win32/api/imagehlp/nf-imagehlp-mapfileandchecksumw + + This function is based on Wine's implementation of MapFileAndCheckSumW, and due to being based entirely on + the pure widechar-API functions, it is not limited by the current code page. + """ + # ctypes bindings for relevant win32 API functions + import ctypes + from ctypes import windll, wintypes + + INVALID_HANDLE = wintypes.HANDLE(-1).value + + GetLastError = ctypes.windll.kernel32.GetLastError + GetLastError.argtypes = () + GetLastError.restype = wintypes.DWORD + + CloseHandle = windll.kernel32.CloseHandle + CloseHandle.argtypes = ( + wintypes.HANDLE, # hObject + ) + CloseHandle.restype = wintypes.BOOL + + CreateFileW = windll.kernel32.CreateFileW + CreateFileW.argtypes = ( + wintypes.LPCWSTR, # lpFileName + wintypes.DWORD, # dwDesiredAccess + wintypes.DWORD, # dwShareMode + wintypes.LPVOID, # lpSecurityAttributes + wintypes.DWORD, # dwCreationDisposition + wintypes.DWORD, # dwFlagsAndAttributes + wintypes.HANDLE, # hTemplateFile + ) + CreateFileW.restype = wintypes.HANDLE + + CreateFileMappingW = windll.kernel32.CreateFileMappingW + CreateFileMappingW.argtypes = ( + wintypes.HANDLE, # hFile + wintypes.LPVOID, # lpSecurityAttributes + wintypes.DWORD, # flProtect + wintypes.DWORD, # dwMaximumSizeHigh + wintypes.DWORD, # dwMaximumSizeLow + wintypes.LPCWSTR, # lpName + ) + CreateFileMappingW.restype = wintypes.HANDLE + + MapViewOfFile = windll.kernel32.MapViewOfFile + MapViewOfFile.argtypes = ( + wintypes.HANDLE, # hFileMappingObject + wintypes.DWORD, # dwDesiredAccess + wintypes.DWORD, # dwFileOffsetHigh + wintypes.DWORD, # dwFileOffsetLow + wintypes.DWORD, # dwNumberOfBytesToMap + ) + MapViewOfFile.restype = wintypes.LPVOID + + UnmapViewOfFile = windll.kernel32.UnmapViewOfFile + UnmapViewOfFile.argtypes = ( + wintypes.LPCVOID, # lpBaseAddress + ) + UnmapViewOfFile.restype = wintypes.BOOL + + GetFileSizeEx = windll.kernel32.GetFileSizeEx + GetFileSizeEx.argtypes = ( + wintypes.HANDLE, # hFile + wintypes.PLARGE_INTEGER, # lpFileSize + ) + + CheckSumMappedFile = windll.imagehlp.CheckSumMappedFile + CheckSumMappedFile.argtypes = ( + wintypes.LPVOID, # BaseAddress + wintypes.DWORD, # FileLength + wintypes.PDWORD, # HeaderSum + wintypes.PDWORD, # CheckSum + ) + CheckSumMappedFile.restype = wintypes.LPVOID + + # Open file + hFile = CreateFileW( + ctypes.c_wchar_p(exe_path), + 0x80000000, # dwDesiredAccess = GENERIC_READ + 0x00000001 | 0x00000002, # dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE, + None, # lpSecurityAttributes = NULL + 3, # dwCreationDisposition = OPEN_EXISTING + 0x80, # dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL + None # hTemplateFile = NULL + ) + if hFile == INVALID_HANDLE: + err = GetLastError() + raise RuntimeError(f"Failed to open file {exe_path}! Error code: {err}") + + # Query file size + fileLength = wintypes.LARGE_INTEGER(0) + if GetFileSizeEx(hFile, fileLength) == 0: + err = GetLastError() + CloseHandle(hFile) + raise RuntimeError(f"Failed to query file size file! Error code: {err}") + fileLength = fileLength.value + if fileLength > (2**32 - 1): + raise RuntimeError("Executable size exceeds maximum allowed executable size on Windows (4 GiB)!") + + # Map the file + hMapping = CreateFileMappingW( + hFile, + None, # lpFileMappingAttributes = NULL + 0x02, # flProtect = PAGE_READONLY + 0, # dwMaximumSizeHigh = 0 + 0, # dwMaximumSizeLow = 0 + None # lpName = NULL + ) + if not hMapping: + err = GetLastError() + CloseHandle(hFile) + raise RuntimeError(f"Failed to map file! Error code: {err}") + + # Create map view + baseAddress = MapViewOfFile( + hMapping, + 4, # dwDesiredAccess = FILE_MAP_READ + 0, # dwFileOffsetHigh = 0 + 0, # dwFileOffsetLow = 0 + 0 # dwNumberOfBytesToMap = 0 + ) + if baseAddress == 0: + err = GetLastError() + CloseHandle(hMapping) + CloseHandle(hFile) + raise RuntimeError(f"Failed to create map view! Error code: {err}") + + # Finally, compute the checksum + headerSum = wintypes.DWORD(0) + checkSum = wintypes.DWORD(0) + ret = CheckSumMappedFile(baseAddress, fileLength, ctypes.byref(headerSum), ctypes.byref(checkSum)) + if ret is None: + err = GetLastError() + + # Cleanup + UnmapViewOfFile(baseAddress) + CloseHandle(hMapping) + CloseHandle(hFile) + + if ret is None: + raise RuntimeError(f"CheckSumMappedFile failed! Error code: {err}") + + return checkSum.value diff --git a/venv/Lib/site-packages/__pycache__/pefile.cpython-311.pyc b/venv/Lib/site-packages/__pycache__/pefile.cpython-311.pyc new file mode 100644 index 0000000..1ad0d8a Binary files /dev/null and b/venv/Lib/site-packages/__pycache__/pefile.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/__pycache__/peutils.cpython-311.pyc b/venv/Lib/site-packages/__pycache__/peutils.cpython-311.pyc new file mode 100644 index 0000000..1fc0666 Binary files /dev/null and b/venv/Lib/site-packages/__pycache__/peutils.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/__init__.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/__init__.py new file mode 100644 index 0000000..4dca97c --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/__init__.py @@ -0,0 +1,26 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +__version__ = '2024.10' +__maintainer__ = 'Legorooj, bwoodsend' +__uri__ = 'https://github.com/pyinstaller/pyinstaller-hooks-contrib' + + +def get_hook_dirs(): + import os + hooks_dir = os.path.dirname(__file__) + return [ + # Required because standard hooks are in sub-directory instead of the top-level hooks directory. + os.path.join(hooks_dir, 'stdhooks'), + # pre_* and run-time hooks + hooks_dir, + ] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..1015abd Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000..c9c7524 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/__pycache__/__init__.cpython-39.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/__pycache__/compat.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/__pycache__/compat.cpython-311.pyc new file mode 100644 index 0000000..7c767ea Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/__pycache__/compat.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/compat.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/compat.py new file mode 100644 index 0000000..4acba2f --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/compat.py @@ -0,0 +1,42 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +import sys + +from PyInstaller.utils.hooks import is_module_satisfies + + +if is_module_satisfies("PyInstaller >= 6.0"): + # PyInstaller >= 6.0 imports importlib_metadata in its compat module + from PyInstaller.compat import importlib_metadata +else: + # Older PyInstaller version - duplicate logic from PyInstaller 6.0 + class ImportlibMetadataError(SystemExit): + def __init__(self): + super().__init__( + "pyinstaller-hooks-contrib requires importlib.metadata from python >= 3.10 stdlib or " + "importlib_metadata from importlib-metadata >= 4.6" + ) + + if sys.version_info >= (3, 10): + import importlib.metadata as importlib_metadata + else: + try: + import importlib_metadata + except ImportError as e: + raise ImportlibMetadataError() from e + + import packaging.version # For importlib_metadata version check + + # Validate the version + if packaging.version.parse(importlib_metadata.version("importlib-metadata")) < packaging.version.parse("4.6"): + raise ImportlibMetadataError() diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/pre_find_module_path/__init__.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/pre_find_module_path/__init__.py new file mode 100644 index 0000000..89c0c0f --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/pre_find_module_path/__init__.py @@ -0,0 +1,11 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/pre_find_module_path/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/pre_find_module_path/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..093385b Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/pre_find_module_path/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/pre_safe_import_module/__init__.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/pre_safe_import_module/__init__.py new file mode 100644 index 0000000..89c0c0f --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/pre_safe_import_module/__init__.py @@ -0,0 +1,11 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/pre_safe_import_module/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/pre_safe_import_module/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..b93c18b Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/pre_safe_import_module/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/pre_safe_import_module/__pycache__/hook-tensorflow.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/pre_safe_import_module/__pycache__/hook-tensorflow.cpython-311.pyc new file mode 100644 index 0000000..4e07158 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/pre_safe_import_module/__pycache__/hook-tensorflow.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/pre_safe_import_module/__pycache__/hook-win32com.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/pre_safe_import_module/__pycache__/hook-win32com.cpython-311.pyc new file mode 100644 index 0000000..8a3e8b6 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/pre_safe_import_module/__pycache__/hook-win32com.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/pre_safe_import_module/hook-tensorflow.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/pre_safe_import_module/hook-tensorflow.py new file mode 100644 index 0000000..0d135b6 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/pre_safe_import_module/hook-tensorflow.py @@ -0,0 +1,28 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2022, PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks import is_module_satisfies + + +def pre_safe_import_module(api): + # As of tensorflow 2.8.0, the `tensorflow.keras` is entirely gone, replaced by a lazy-loaded alias for + # `keras.api._v2.keras`. Without us registering the alias here, a program that imports only from + # `tensorflow.keras` fails to collect `tensorflow`. + # See: https://github.com/pyinstaller/pyinstaller/discussions/6890 + # The alias was already present in earlier releases, but it does not seem to be causing problems there, + # so keep this specific to tensorflow >= 2.8.0 to avoid accidentally breaking something else. + # + # Starting with tensorflow 2.16.0, the alias points to `keras._tf_keras.keras`. + if is_module_satisfies("tensorflow >= 2.16.0"): + api.add_alias_module('keras._tf_keras.keras', 'tensorflow.keras') + elif is_module_satisfies("tensorflow >= 2.8.0"): + api.add_alias_module('keras.api._v2.keras', 'tensorflow.keras') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/pre_safe_import_module/hook-win32com.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/pre_safe_import_module/hook-win32com.py new file mode 100644 index 0000000..afb61f7 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/pre_safe_import_module/hook-win32com.py @@ -0,0 +1,46 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2005-2020, PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +#----------------------------------------------------------------------------- +""" +PyWin32 package 'win32com' extends it's __path__ attribute with win32comext +directory and thus PyInstaller is not able to find modules in it. For example +module 'win32com.shell' is in reality 'win32comext.shell'. + +>>> win32com.__path__ +['win32com', 'C:\\Python27\\Lib\\site-packages\\win32comext'] + +""" + +import os + +from PyInstaller.utils.hooks import logger, exec_statement +from PyInstaller.compat import is_win, is_cygwin + + +def pre_safe_import_module(api): + if not (is_win or is_cygwin): + return + win32com_file = exec_statement( + """ + try: + from win32com import __file__ + print(__file__) + except Exception: + pass + """).strip() + if not win32com_file: + logger.debug('win32com: module not available') + return # win32com unavailable + win32com_dir = os.path.dirname(win32com_file) + comext_dir = os.path.join(os.path.dirname(win32com_dir), 'win32comext') + logger.debug('win32com: extending __path__ with dir %r' % comext_dir) + # Append the __path__ where PyInstaller will look for 'win32com' modules.' + api.append_package_path(comext_dir) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks.dat b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks.dat new file mode 100644 index 0000000..f868f56 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks.dat @@ -0,0 +1,16 @@ +{ + 'cryptography': ['pyi_rth_cryptography_openssl.py'], + 'enchant': ['pyi_rth_enchant.py'], + 'findlibs': ['pyi_rth_findlibs.py'], + 'ffpyplayer': ['pyi_rth_ffpyplayer.py'], + 'osgeo': ['pyi_rth_osgeo.py'], + 'traitlets': ['pyi_rth_traitlets.py'], + 'usb': ['pyi_rth_usb.py'], + 'nltk': ['pyi_rth_nltk.py'], + 'pyproj': ['pyi_rth_pyproj.py'], + 'pygraphviz': ['pyi_rth_pygraphviz.py'], + 'pythoncom': ['pyi_rth_pythoncom.py'], + 'pyqtgraph': ['pyi_rth_pyqtgraph_multiprocess.py'], + 'pywintypes': ['pyi_rth_pywintypes.py'], + 'tensorflow': ['pyi_rth_tensorflow.py'], +} diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__init__.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__init__.py new file mode 100644 index 0000000..30d22ed --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__init__.py @@ -0,0 +1,10 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the Apache License 2.0 +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: Apache-2.0 +# ------------------------------------------------------------------ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..110855a Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_cryptography_openssl.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_cryptography_openssl.cpython-311.pyc new file mode 100644 index 0000000..deddf8b Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_cryptography_openssl.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_enchant.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_enchant.cpython-311.pyc new file mode 100644 index 0000000..6c1a686 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_enchant.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_ffpyplayer.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_ffpyplayer.cpython-311.pyc new file mode 100644 index 0000000..47491d6 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_ffpyplayer.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_findlibs.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_findlibs.cpython-311.pyc new file mode 100644 index 0000000..f6047ac Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_findlibs.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_nltk.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_nltk.cpython-311.pyc new file mode 100644 index 0000000..4baee7b Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_nltk.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_osgeo.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_osgeo.cpython-311.pyc new file mode 100644 index 0000000..e721840 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_osgeo.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_pygraphviz.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_pygraphviz.cpython-311.pyc new file mode 100644 index 0000000..a4f487f Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_pygraphviz.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_pyproj.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_pyproj.cpython-311.pyc new file mode 100644 index 0000000..c4d5a47 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_pyproj.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_pyqtgraph_multiprocess.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_pyqtgraph_multiprocess.cpython-311.pyc new file mode 100644 index 0000000..2df878a Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_pyqtgraph_multiprocess.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_pythoncom.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_pythoncom.cpython-311.pyc new file mode 100644 index 0000000..bc1d2b3 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_pythoncom.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_pywintypes.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_pywintypes.cpython-311.pyc new file mode 100644 index 0000000..3784fa8 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_pywintypes.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_tensorflow.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_tensorflow.cpython-311.pyc new file mode 100644 index 0000000..891712b Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_tensorflow.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_traitlets.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_traitlets.cpython-311.pyc new file mode 100644 index 0000000..674b223 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_traitlets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_usb.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_usb.cpython-311.pyc new file mode 100644 index 0000000..2cb34af Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_usb.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_cryptography_openssl.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_cryptography_openssl.py new file mode 100644 index 0000000..dbabe69 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_cryptography_openssl.py @@ -0,0 +1,20 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2024, PyInstaller Development Team. +# +# This file is distributed under the terms of the Apache License 2.0 +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: Apache-2.0 +#----------------------------------------------------------------------------- + +import os +import sys + +# If we collected OpenSSL modules into `ossl-modules` directory, override the OpenSSL search path by setting the +# `OPENSSL_MODULES` environment variable. +_ossl_modules_dir = os.path.join(sys._MEIPASS, 'ossl-modules') +if os.path.isdir(_ossl_modules_dir): + os.environ['OPENSSL_MODULES'] = _ossl_modules_dir +del _ossl_modules_dir diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_enchant.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_enchant.py new file mode 100644 index 0000000..36c185d --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_enchant.py @@ -0,0 +1,22 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2005-2020, PyInstaller Development Team. +# +# This file is distributed under the terms of the Apache License 2.0 +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: Apache-2.0 +#----------------------------------------------------------------------------- + +import os +import sys + +# On Mac OS X tell enchant library where to look for enchant backends (aspell, myspell, ...). +# Enchant is looking for backends in directory 'PREFIX/lib/enchant' +# Note: env. var. ENCHANT_PREFIX_DIR is implemented only in the development version: +# https://github.com/AbiWord/enchant +# https://github.com/AbiWord/enchant/pull/2 +# TODO Test this rthook. +if sys.platform.startswith('darwin'): + os.environ['ENCHANT_PREFIX_DIR'] = os.path.join(sys._MEIPASS, 'enchant') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_ffpyplayer.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_ffpyplayer.py new file mode 100644 index 0000000..6a024de --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_ffpyplayer.py @@ -0,0 +1,19 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2023, PyInstaller Development Team. +# +# This file is distributed under the terms of the Apache License 2.0 +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: Apache-2.0 +#----------------------------------------------------------------------------- + +# Starting with v4.3.5, the `ffpyplayer` package attempts to use `site.USER_BASE` in path manipulation functions. +# As frozen application runs with disabled `site`, the value of this variable is `None`, and causes path manipulation +# functions to raise an error. As a work-around, we set `site.USER_BASE` to an empty string, which is also what the +# fake `site` module available in PyInstaller prior to v5.5 did. +import site + +if site.USER_BASE is None: + site.USER_BASE = '' diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_findlibs.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_findlibs.py new file mode 100644 index 0000000..43d3db1 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_findlibs.py @@ -0,0 +1,52 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2024, 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 +#----------------------------------------------------------------------------- + +# Override the findlibs.find() function to give precedence to sys._MEIPASS, followed by `ctypes.util.find_library`, +# and only then the hard-coded paths from the original implementation. The main aim here is to avoid loading libraries +# from Homebrew environment on macOS when it happens to be present at run-time and we have a bundled copy collected from +# the build system. This happens because we (try not to) modify `DYLD_LIBRARY_PATH`, and the original `findlibs.find()` +# implementation gives precedence to environment variables and several fixed/hard-coded locations, and uses +# `ctypes.util.find_library` as the final fallback... +def _pyi_rthook(): + import sys + import os + import ctypes.util + + import findlibs + + _orig_find = getattr(findlibs, 'find', None) + + def _pyi_find(lib_name, pkg_name=None): + pkg_name = pkg_name or lib_name + extension = findlibs.EXTENSIONS.get(sys.platform, ".so") + + # First check sys._MEIPASS + fullname = os.path.join(sys._MEIPASS, "lib{}{}".format(lib_name, extension)) + if os.path.isfile(fullname): + return fullname + + # Fall back to `ctypes.util.find_library` (to give it precedence over hard-coded paths from original + # implementation). + lib = ctypes.util.find_library(lib_name) + if lib is not None: + return lib + + # Finally, fall back to original implementation + if _orig_find is not None: + return _orig_find(lib_name, pkg_name) + + return None + + findlibs.find = _pyi_find + + +_pyi_rthook() +del _pyi_rthook diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_nltk.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_nltk.py new file mode 100644 index 0000000..feb9eb7 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_nltk.py @@ -0,0 +1,17 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-2020, PyInstaller Development Team. +# +# This file is distributed under the terms of the Apache License 2.0 +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: Apache-2.0 +#----------------------------------------------------------------------------- + +import sys +import os +import nltk + +#add the path to nltk_data +nltk.data.path.insert(0, os.path.join(sys._MEIPASS, "nltk_data")) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_osgeo.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_osgeo.py new file mode 100644 index 0000000..7b31027 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_osgeo.py @@ -0,0 +1,32 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2015-2020, PyInstaller Development Team. +# +# This file is distributed under the terms of the Apache License 2.0 +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: Apache-2.0 +#----------------------------------------------------------------------------- + +import os +import sys + +# Installing `osgeo` Conda packages requires to set `GDAL_DATA` + +is_win = sys.platform.startswith('win') +if is_win: + + gdal_data = os.path.join(sys._MEIPASS, 'data', 'gdal') + if not os.path.exists(gdal_data): + + gdal_data = os.path.join(sys._MEIPASS, 'Library', 'share', 'gdal') + # last attempt, check if one of the required file is in the generic folder Library/data + if not os.path.exists(os.path.join(gdal_data, 'gcs.csv')): + gdal_data = os.path.join(sys._MEIPASS, 'Library', 'data') + +else: + gdal_data = os.path.join(sys._MEIPASS, 'share', 'gdal') + +if os.path.exists(gdal_data): + os.environ['GDAL_DATA'] = gdal_data diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_pygraphviz.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_pygraphviz.py new file mode 100644 index 0000000..cfae2b3 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_pygraphviz.py @@ -0,0 +1,32 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2021, PyInstaller Development Team. +# +# This file is distributed under the terms of the Apache License 2.0 +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: Apache-2.0 +#----------------------------------------------------------------------------- + +import pygraphviz + +# Override pygraphviz.AGraph._which method to search for graphviz executables inside sys._MEIPASS +if hasattr(pygraphviz.AGraph, '_which'): + + def _pygraphviz_override_which(self, name): + import os + import sys + import platform + + program_name = name + if platform.system() == "Windows": + program_name += ".exe" + + program_path = os.path.join(sys._MEIPASS, program_name) + if not os.path.isfile(program_path): + raise ValueError(f"Prog {name} not found in the PyInstaller-frozen application bundle!") + + return program_path + + pygraphviz.AGraph._which = _pygraphviz_override_which diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_pyproj.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_pyproj.py new file mode 100644 index 0000000..b78b70b --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_pyproj.py @@ -0,0 +1,26 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2015-2020, PyInstaller Development Team. +# +# This file is distributed under the terms of the Apache License 2.0 +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: Apache-2.0 +#----------------------------------------------------------------------------- + +import os +import sys + +# Installing `pyproj` Conda packages requires to set `PROJ_LIB` + +is_win = sys.platform.startswith('win') +if is_win: + + proj_data = os.path.join(sys._MEIPASS, 'Library', 'share', 'proj') + +else: + proj_data = os.path.join(sys._MEIPASS, 'share', 'proj') + +if os.path.exists(proj_data): + os.environ['PROJ_LIB'] = proj_data diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_pyqtgraph_multiprocess.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_pyqtgraph_multiprocess.py new file mode 100644 index 0000000..e3168dc --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_pyqtgraph_multiprocess.py @@ -0,0 +1,51 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2022, PyInstaller Development Team. +# +# This file is distributed under the terms of the Apache License 2.0 +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: Apache-2.0 +#----------------------------------------------------------------------------- + +import sys +import os + + +def _setup_pyqtgraph_multiprocess_hook(): + # NOTE: pyqtgraph.multiprocess spawns the sub-process using subprocess.Popen (or equivalent). This means that in + # onefile builds, the executable in subprocess will unpack itself again, into different sys._MEIPASS, because + # the _MEIPASS2 environment variable is not set (bootloader / bootstrap script cleans it up). This will make the + # argv[1] check below fail, due to different sys._MEIPASS value in the subprocess. + # + # To work around this, at the time of writing (PyInstaller 5.5), the user needs to set _MEIPASS2 environment + # variable to sys._MEIPASS before using `pyqtgraph.multiprocess` in onefile builds. And stlib's + # `multiprocessing.freeze_support` needs to be called in the entry-point program, due to `pyqtgraph.multiprocess` + # internally using stdlib's `multiprocessing` primitives. + if len(sys.argv) == 2 and sys.argv[1] == os.path.join(sys._MEIPASS, 'pyqtgraph', 'multiprocess', 'bootstrap.py'): + # Load as module; this requires --hiddenimport pyqtgraph.multiprocess.bootstrap + try: + mod_name = 'pyqtgraph.multiprocess.bootstrap' + mod = __import__(mod_name) + bootstrap_co = mod.__loader__.get_code(mod_name) + except Exception: + bootstrap_co = None + + if bootstrap_co: + exec(bootstrap_co) + sys.exit(0) + + # Load from file; requires pyqtgraph/multiprocess/bootstrap.py collected as data file + bootstrap_file = os.path.join(sys._MEIPASS, 'pyqtgraph', 'multiprocess', 'bootstrap.py') + if os.path.isfile(bootstrap_file): + with open(bootstrap_file, 'r') as fp: + bootstrap_code = fp.read() + exec(bootstrap_code) + sys.exit(0) + + raise RuntimeError("Could not find pyqtgraph.multiprocess bootstrap code or script!") + + +_setup_pyqtgraph_multiprocess_hook() +del _setup_pyqtgraph_multiprocess_hook diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_pythoncom.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_pythoncom.py new file mode 100644 index 0000000..4f11fb8 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_pythoncom.py @@ -0,0 +1,24 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2022, PyInstaller Development Team. +# +# This file is distributed under the terms of the Apache License 2.0 +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: Apache-2.0 +#----------------------------------------------------------------------------- + +# Unfortunately, __import_pywin32_system_module__ from pywintypes module assumes that in a frozen application, the +# pythoncom3X.dll and pywintypes3X.dll that are normally found in site-packages/pywin32_system32, are located +# directly in the sys.path, without bothering to check first if they are actually available in the standard location. +# This obviously runs afoul of our attempts at preserving the directory layout and placing them in the pywin32_system32 +# sub-directory instead of the top-level application directory. So as a work-around, add the sub-directory to sys.path +# to keep pywintypes happy... +import sys +import os + +pywin32_system32_path = os.path.join(sys._MEIPASS, 'pywin32_system32') +if os.path.isdir(pywin32_system32_path) and pywin32_system32_path not in sys.path: + sys.path.append(pywin32_system32_path) +del pywin32_system32_path diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_pywintypes.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_pywintypes.py new file mode 100644 index 0000000..4f11fb8 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_pywintypes.py @@ -0,0 +1,24 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2022, PyInstaller Development Team. +# +# This file is distributed under the terms of the Apache License 2.0 +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: Apache-2.0 +#----------------------------------------------------------------------------- + +# Unfortunately, __import_pywin32_system_module__ from pywintypes module assumes that in a frozen application, the +# pythoncom3X.dll and pywintypes3X.dll that are normally found in site-packages/pywin32_system32, are located +# directly in the sys.path, without bothering to check first if they are actually available in the standard location. +# This obviously runs afoul of our attempts at preserving the directory layout and placing them in the pywin32_system32 +# sub-directory instead of the top-level application directory. So as a work-around, add the sub-directory to sys.path +# to keep pywintypes happy... +import sys +import os + +pywin32_system32_path = os.path.join(sys._MEIPASS, 'pywin32_system32') +if os.path.isdir(pywin32_system32_path) and pywin32_system32_path not in sys.path: + sys.path.append(pywin32_system32_path) +del pywin32_system32_path diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_tensorflow.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_tensorflow.py new file mode 100644 index 0000000..747ea45 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_tensorflow.py @@ -0,0 +1,53 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2023, PyInstaller Development Team. +# +# This file is distributed under the terms of the Apache License 2.0 +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: Apache-2.0 +#----------------------------------------------------------------------------- + +def _pyi_rthook(): + import sys + + # `tensorflow` versions prior to 2.3.0 attempt to use `site.USER_SITE` in path/string manipulation functions. + # As frozen application runs with disabled `site`, the value of this variable is `None`, and causes path/string + # manipulation functions to raise an error. As a work-around, we set `site.USER_SITE` to an empty string, which is + # also what the fake `site` module available in PyInstaller prior to v5.5 did. + import site + + if site.USER_SITE is None: + site.USER_SITE = '' + + # The issue described about with site.USER_SITE being None has largely been resolved in contemporary `tensorflow` + # versions, which now check that `site.ENABLE_USER_SITE` is set and that `site.USER_SITE` is not None before + # trying to use it. + # + # However, `tensorflow` will attempt to search and load its plugins only if it believes that it is running from + # "a pip-based installation" - if the package's location is rooted in one of the "site-packages" directories. See + # https://github.com/tensorflow/tensorflow/blob/6887368d6d46223f460358323c4b76d61d1558a8/tensorflow/api_template.__init__.py#L110C76-L156 + # Unfortunately, they "cleverly" infer the module's location via `inspect.getfile(inspect.currentframe())`, which + # in the frozen application returns anonymized relative source file name (`tensorflow/__init__.py`) - so we need one + # of the "site directories" to be just "tensorflow" (to fool the `_running_from_pip_package()` check), and we also + # need `sys._MEIPASS` to be among them (to load the plugins from the actual `sys._MEIPASS/tensorflow-plugins`). + # Therefore, we monkey-patch `site.getsitepackages` to add those two entries to the list of "site directories". + + _orig_getsitepackages = getattr(site, 'getsitepackages', None) + + def _pyi_getsitepackages(): + return [ + sys._MEIPASS, + "tensorflow", + *(_orig_getsitepackages() if _orig_getsitepackages is not None else []), + ] + + site.getsitepackages = _pyi_getsitepackages + + # NOTE: instead of the above override, we could also set TF_PLUGGABLE_DEVICE_LIBRARY_PATH, but that works only + # for tensorflow >= 2.12. + + +_pyi_rthook() +del _pyi_rthook diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_traitlets.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_traitlets.py new file mode 100644 index 0000000..5ec3a9f --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_traitlets.py @@ -0,0 +1,25 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2005-2020, PyInstaller Development Team. +# +# This file is distributed under the terms of the Apache License 2.0 +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: Apache-2.0 +#----------------------------------------------------------------------------- + +# 'traitlets' uses module 'inspect' from default Python library to inspect +# source code of modules. However, frozen app does not contain source code +# of Python modules. +# +# hook-IPython depends on module 'traitlets'. + +import traitlets.traitlets + + +def _disabled_deprecation_warnings(method, cls, method_name, msg): + pass + + +traitlets.traitlets._deprecated_method = _disabled_deprecation_warnings diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_usb.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_usb.py new file mode 100644 index 0000000..2a455a6 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/rthooks/pyi_rth_usb.py @@ -0,0 +1,75 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2013-2020, PyInstaller Development Team. +# +# This file is distributed under the terms of the Apache License 2.0 +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: Apache-2.0 +#----------------------------------------------------------------------------- + +import ctypes +import glob +import os +import sys +# Pyusb changed these libusb module names in commit 2082e7. +try: + import usb.backend.libusb10 as libusb10 +except ImportError: + import usb.backend.libusb1 as libusb10 +try: + import usb.backend.libusb01 as libusb01 +except ImportError: + import usb.backend.libusb0 as libusb01 +import usb.backend.openusb as openusb + + +def get_load_func(type, candidates): + + def _load_library(find_library=None): + exec_path = sys._MEIPASS + + library = None + for candidate in candidates: + # Do linker's path lookup work to force load bundled copy. + if os.name == 'posix' and sys.platform == 'darwin': + libs = glob.glob("%s/%s*.dylib*" % (exec_path, candidate)) + elif sys.platform == 'win32' or sys.platform == 'cygwin': + libs = glob.glob("%s\\%s*.dll" % (exec_path, candidate)) + else: + libs = glob.glob("%s/%s*.so*" % (exec_path, candidate)) + for libname in libs: + try: + # NOTE: libusb01 is using CDLL under win32. + # (see usb.backends.libusb01) + if sys.platform == 'win32' and type != 'libusb01': + library = ctypes.WinDLL(libname) + else: + library = ctypes.CDLL(libname) + if library is not None: + break + except OSError: + library = None + if library is not None: + break + else: + raise OSError('USB library could not be found') + + if type == 'libusb10': + if not hasattr(library, 'libusb_init'): + raise OSError('USB library could not be found') + return library + + return _load_library + + +# NOTE: Need to keep in sync with future PyUSB updates. +if sys.platform == 'cygwin': + libusb10._load_library = get_load_func('libusb10', ('cygusb-1.0', )) + libusb01._load_library = get_load_func('libusb01', ('cygusb0', )) + openusb._load_library = get_load_func('openusb', ('openusb', )) +else: + libusb10._load_library = get_load_func('libusb10', ('usb-1.0', 'libusb-1.0', 'usb')) + libusb01._load_library = get_load_func('libusb01', ('usb-0.1', 'usb', 'libusb0', 'libusb')) + openusb._load_library = get_load_func('openusb', ('openusb', )) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__init__.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__init__.py new file mode 100644 index 0000000..89c0c0f --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__init__.py @@ -0,0 +1,11 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..a20b913 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-BTrees.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-BTrees.cpython-311.pyc new file mode 100644 index 0000000..e8a1578 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-BTrees.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-CTkMessagebox.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-CTkMessagebox.cpython-311.pyc new file mode 100644 index 0000000..fa10b60 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-CTkMessagebox.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-Crypto.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-Crypto.cpython-311.pyc new file mode 100644 index 0000000..776c537 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-Crypto.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-Cryptodome.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-Cryptodome.cpython-311.pyc new file mode 100644 index 0000000..f2f559d Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-Cryptodome.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-HtmlTestRunner.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-HtmlTestRunner.cpython-311.pyc new file mode 100644 index 0000000..01d02e5 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-HtmlTestRunner.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-IPython.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-IPython.cpython-311.pyc new file mode 100644 index 0000000..d453646 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-IPython.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-OpenGL.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-OpenGL.cpython-311.pyc new file mode 100644 index 0000000..b931dc1 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-OpenGL.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-OpenGL_accelerate.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-OpenGL_accelerate.cpython-311.pyc new file mode 100644 index 0000000..c306396 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-OpenGL_accelerate.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-PyTaskbar.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-PyTaskbar.cpython-311.pyc new file mode 100644 index 0000000..117541b Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-PyTaskbar.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-Xlib.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-Xlib.cpython-311.pyc new file mode 100644 index 0000000..3b91346 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-Xlib.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-_mssql.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-_mssql.cpython-311.pyc new file mode 100644 index 0000000..2b69647 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-_mssql.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-_mysql.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-_mysql.cpython-311.pyc new file mode 100644 index 0000000..c85e13f Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-_mysql.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-accessible_output2.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-accessible_output2.cpython-311.pyc new file mode 100644 index 0000000..9fb4726 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-accessible_output2.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-adbutils.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-adbutils.cpython-311.pyc new file mode 100644 index 0000000..229c9ff Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-adbutils.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-adios.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-adios.cpython-311.pyc new file mode 100644 index 0000000..e4cce1e Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-adios.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-afmformats.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-afmformats.cpython-311.pyc new file mode 100644 index 0000000..67f3341 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-afmformats.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-aliyunsdkcore.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-aliyunsdkcore.cpython-311.pyc new file mode 100644 index 0000000..67b544b Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-aliyunsdkcore.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-altair.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-altair.cpython-311.pyc new file mode 100644 index 0000000..800e80b Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-altair.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-amazonproduct.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-amazonproduct.cpython-311.pyc new file mode 100644 index 0000000..086a123 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-amazonproduct.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-anyio.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-anyio.cpython-311.pyc new file mode 100644 index 0000000..f869dab Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-anyio.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-appdirs.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-appdirs.cpython-311.pyc new file mode 100644 index 0000000..c0e8d21 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-appdirs.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-appy.pod.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-appy.pod.cpython-311.pyc new file mode 100644 index 0000000..6544114 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-appy.pod.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-apscheduler.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-apscheduler.cpython-311.pyc new file mode 100644 index 0000000..fe6d3fa Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-apscheduler.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-argon2.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-argon2.cpython-311.pyc new file mode 100644 index 0000000..c607bda Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-argon2.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-astor.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-astor.cpython-311.pyc new file mode 100644 index 0000000..56924ca Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-astor.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-astroid.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-astroid.cpython-311.pyc new file mode 100644 index 0000000..b39c456 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-astroid.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-astropy.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-astropy.cpython-311.pyc new file mode 100644 index 0000000..70be08b Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-astropy.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-astropy_iers_data.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-astropy_iers_data.cpython-311.pyc new file mode 100644 index 0000000..635fb80 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-astropy_iers_data.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-av.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-av.cpython-311.pyc new file mode 100644 index 0000000..0275702 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-av.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-avro.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-avro.cpython-311.pyc new file mode 100644 index 0000000..c4e4aae Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-avro.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-azurerm.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-azurerm.cpython-311.pyc new file mode 100644 index 0000000..3c49258 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-azurerm.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-backports.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-backports.cpython-311.pyc new file mode 100644 index 0000000..83279eb Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-backports.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-backports.zoneinfo.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-backports.zoneinfo.cpython-311.pyc new file mode 100644 index 0000000..f8f9859 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-backports.zoneinfo.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-bacon.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-bacon.cpython-311.pyc new file mode 100644 index 0000000..5c97b6c Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-bacon.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-bcrypt.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-bcrypt.cpython-311.pyc new file mode 100644 index 0000000..0223aa8 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-bcrypt.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-bitsandbytes.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-bitsandbytes.cpython-311.pyc new file mode 100644 index 0000000..c7a48a3 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-bitsandbytes.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-bleak.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-bleak.cpython-311.pyc new file mode 100644 index 0000000..ade9ba8 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-bleak.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-blspy.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-blspy.cpython-311.pyc new file mode 100644 index 0000000..4125e5b Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-blspy.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-bokeh.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-bokeh.cpython-311.pyc new file mode 100644 index 0000000..996de3e Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-bokeh.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-boto.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-boto.cpython-311.pyc new file mode 100644 index 0000000..1459386 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-boto.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-boto3.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-boto3.cpython-311.pyc new file mode 100644 index 0000000..f4aa9f3 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-boto3.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-botocore.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-botocore.cpython-311.pyc new file mode 100644 index 0000000..d3d5d36 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-botocore.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-branca.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-branca.cpython-311.pyc new file mode 100644 index 0000000..6969635 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-branca.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cairocffi.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cairocffi.cpython-311.pyc new file mode 100644 index 0000000..27ac5bd Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cairocffi.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cairosvg.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cairosvg.cpython-311.pyc new file mode 100644 index 0000000..21cf0a3 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cairosvg.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-capstone.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-capstone.cpython-311.pyc new file mode 100644 index 0000000..7994fd0 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-capstone.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cassandra.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cassandra.cpython-311.pyc new file mode 100644 index 0000000..7209002 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cassandra.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-celpy.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-celpy.cpython-311.pyc new file mode 100644 index 0000000..7343cfd Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-celpy.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-certifi.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-certifi.cpython-311.pyc new file mode 100644 index 0000000..19ab4a9 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-certifi.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cf_units.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cf_units.cpython-311.pyc new file mode 100644 index 0000000..fc44c99 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cf_units.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cftime.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cftime.cpython-311.pyc new file mode 100644 index 0000000..31d82e5 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cftime.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-charset_normalizer.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-charset_normalizer.cpython-311.pyc new file mode 100644 index 0000000..9dcc2b8 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-charset_normalizer.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cloudpickle.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cloudpickle.cpython-311.pyc new file mode 100644 index 0000000..d6acff5 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cloudpickle.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cloudscraper.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cloudscraper.cpython-311.pyc new file mode 100644 index 0000000..d05a024 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cloudscraper.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-clr.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-clr.cpython-311.pyc new file mode 100644 index 0000000..5d92910 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-clr.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-clr_loader.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-clr_loader.cpython-311.pyc new file mode 100644 index 0000000..84a98bf Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-clr_loader.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cmocean.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cmocean.cpython-311.pyc new file mode 100644 index 0000000..1eaf8d8 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cmocean.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-compliance_checker.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-compliance_checker.cpython-311.pyc new file mode 100644 index 0000000..dcde162 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-compliance_checker.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-comtypes.client.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-comtypes.client.cpython-311.pyc new file mode 100644 index 0000000..32243e7 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-comtypes.client.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-countrycode.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-countrycode.cpython-311.pyc new file mode 100644 index 0000000..f7a35c7 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-countrycode.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-countryinfo.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-countryinfo.cpython-311.pyc new file mode 100644 index 0000000..8263f42 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-countryinfo.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cryptography.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cryptography.cpython-311.pyc new file mode 100644 index 0000000..162c2e1 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cryptography.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-customtkinter.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-customtkinter.cpython-311.pyc new file mode 100644 index 0000000..2705837 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-customtkinter.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cv2.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cv2.cpython-311.pyc new file mode 100644 index 0000000..bb0d333 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cv2.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cx_Oracle.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cx_Oracle.cpython-311.pyc new file mode 100644 index 0000000..0d880e3 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cx_Oracle.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cytoolz.itertoolz.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cytoolz.itertoolz.cpython-311.pyc new file mode 100644 index 0000000..43c3b91 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cytoolz.itertoolz.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dash.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dash.cpython-311.pyc new file mode 100644 index 0000000..b0a6aac Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dash.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dash_bootstrap_components.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dash_bootstrap_components.cpython-311.pyc new file mode 100644 index 0000000..40604b7 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dash_bootstrap_components.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dash_core_components.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dash_core_components.cpython-311.pyc new file mode 100644 index 0000000..633ce8a Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dash_core_components.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dash_html_components.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dash_html_components.cpython-311.pyc new file mode 100644 index 0000000..0c4895e Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dash_html_components.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dash_renderer.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dash_renderer.cpython-311.pyc new file mode 100644 index 0000000..c5281a6 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dash_renderer.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dash_table.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dash_table.cpython-311.pyc new file mode 100644 index 0000000..99c6501 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dash_table.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dash_uploader.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dash_uploader.cpython-311.pyc new file mode 100644 index 0000000..0ffa09d Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dash_uploader.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dask.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dask.cpython-311.pyc new file mode 100644 index 0000000..c289e77 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dask.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-datasets.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-datasets.cpython-311.pyc new file mode 100644 index 0000000..104fd90 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-datasets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dateparser.utils.strptime.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dateparser.utils.strptime.cpython-311.pyc new file mode 100644 index 0000000..4253a19 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dateparser.utils.strptime.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dbus_fast.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dbus_fast.cpython-311.pyc new file mode 100644 index 0000000..28b7287 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dbus_fast.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dclab.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dclab.cpython-311.pyc new file mode 100644 index 0000000..94049ed Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dclab.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-detectron2.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-detectron2.cpython-311.pyc new file mode 100644 index 0000000..823bf2e Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-detectron2.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-discid.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-discid.cpython-311.pyc new file mode 100644 index 0000000..2b70b25 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-discid.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-distorm3.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-distorm3.cpython-311.pyc new file mode 100644 index 0000000..6821ec2 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-distorm3.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dns.rdata.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dns.rdata.cpython-311.pyc new file mode 100644 index 0000000..f2c5e03 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dns.rdata.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-docutils.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-docutils.cpython-311.pyc new file mode 100644 index 0000000..27c8b71 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-docutils.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-docx.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-docx.cpython-311.pyc new file mode 100644 index 0000000..e627a60 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-docx.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-docx2pdf.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-docx2pdf.cpython-311.pyc new file mode 100644 index 0000000..87d15da Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-docx2pdf.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dynaconf.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dynaconf.cpython-311.pyc new file mode 100644 index 0000000..67b398a Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dynaconf.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-easyocr.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-easyocr.cpython-311.pyc new file mode 100644 index 0000000..ca58b23 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-easyocr.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eel.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eel.cpython-311.pyc new file mode 100644 index 0000000..2104236 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eel.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-enchant.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-enchant.cpython-311.pyc new file mode 100644 index 0000000..dc8134c Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-enchant.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eng_to_ipa.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eng_to_ipa.cpython-311.pyc new file mode 100644 index 0000000..747f9fb Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eng_to_ipa.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ens.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ens.cpython-311.pyc new file mode 100644 index 0000000..2d86082 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ens.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-enzyme.parsers.ebml.core.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-enzyme.parsers.ebml.core.cpython-311.pyc new file mode 100644 index 0000000..6a4d9bc Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-enzyme.parsers.ebml.core.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_abi.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_abi.cpython-311.pyc new file mode 100644 index 0000000..77822c1 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_abi.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_account.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_account.cpython-311.pyc new file mode 100644 index 0000000..cc33514 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_account.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_hash.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_hash.cpython-311.pyc new file mode 100644 index 0000000..2b0c6ee Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_hash.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_keyfile.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_keyfile.cpython-311.pyc new file mode 100644 index 0000000..99cf524 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_keyfile.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_keys.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_keys.cpython-311.pyc new file mode 100644 index 0000000..a86dea3 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_keys.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_rlp.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_rlp.cpython-311.pyc new file mode 100644 index 0000000..37944e5 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_rlp.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_typing.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_typing.cpython-311.pyc new file mode 100644 index 0000000..05a0762 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_typing.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_utils.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_utils.cpython-311.pyc new file mode 100644 index 0000000..398e622 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_utils.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_utils.network.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_utils.network.cpython-311.pyc new file mode 100644 index 0000000..d560b93 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_utils.network.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-exchangelib.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-exchangelib.cpython-311.pyc new file mode 100644 index 0000000..1b88a13 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-exchangelib.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-fabric.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-fabric.cpython-311.pyc new file mode 100644 index 0000000..7222f2e Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-fabric.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-fairscale.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-fairscale.cpython-311.pyc new file mode 100644 index 0000000..2a31d2b Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-fairscale.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-faker.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-faker.cpython-311.pyc new file mode 100644 index 0000000..c5f3b5a Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-faker.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-falcon.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-falcon.cpython-311.pyc new file mode 100644 index 0000000..a80243d Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-falcon.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-fastai.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-fastai.cpython-311.pyc new file mode 100644 index 0000000..3962eef Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-fastai.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-fastparquet.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-fastparquet.cpython-311.pyc new file mode 100644 index 0000000..76a016b Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-fastparquet.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ffpyplayer.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ffpyplayer.cpython-311.pyc new file mode 100644 index 0000000..3996304 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ffpyplayer.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-fiona.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-fiona.cpython-311.pyc new file mode 100644 index 0000000..3025dbf Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-fiona.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-flask_compress.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-flask_compress.cpython-311.pyc new file mode 100644 index 0000000..07e7201 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-flask_compress.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-flask_restx.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-flask_restx.cpython-311.pyc new file mode 100644 index 0000000..0b7ab08 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-flask_restx.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-flex.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-flex.cpython-311.pyc new file mode 100644 index 0000000..2b6706f Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-flex.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-flirpy.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-flirpy.cpython-311.pyc new file mode 100644 index 0000000..a3d1807 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-flirpy.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-fmpy.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-fmpy.cpython-311.pyc new file mode 100644 index 0000000..8fc8372 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-fmpy.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-folium.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-folium.cpython-311.pyc new file mode 100644 index 0000000..0b02f97 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-folium.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-freetype.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-freetype.cpython-311.pyc new file mode 100644 index 0000000..716d82b Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-freetype.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-fvcore.nn.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-fvcore.nn.cpython-311.pyc new file mode 100644 index 0000000..a1245cc Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-fvcore.nn.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gadfly.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gadfly.cpython-311.pyc new file mode 100644 index 0000000..b0dcbf2 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gadfly.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gbulb.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gbulb.cpython-311.pyc new file mode 100644 index 0000000..944ad48 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gbulb.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gcloud.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gcloud.cpython-311.pyc new file mode 100644 index 0000000..2bb3c9b Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gcloud.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-geopandas.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-geopandas.cpython-311.pyc new file mode 100644 index 0000000..777779e Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-geopandas.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gitlab.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gitlab.cpython-311.pyc new file mode 100644 index 0000000..86df680 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gitlab.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gmplot.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gmplot.cpython-311.pyc new file mode 100644 index 0000000..489b071 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gmplot.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gmsh.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gmsh.cpython-311.pyc new file mode 100644 index 0000000..a825ca9 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gmsh.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gooey.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gooey.cpython-311.pyc new file mode 100644 index 0000000..b9b7737 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gooey.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.api_core.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.api_core.cpython-311.pyc new file mode 100644 index 0000000..c68f9c2 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.api_core.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.cloud.bigquery.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.cloud.bigquery.cpython-311.pyc new file mode 100644 index 0000000..1d90f07 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.cloud.bigquery.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.cloud.core.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.cloud.core.cpython-311.pyc new file mode 100644 index 0000000..6a8a2bf Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.cloud.core.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.cloud.kms_v1.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.cloud.kms_v1.cpython-311.pyc new file mode 100644 index 0000000..483e3b5 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.cloud.kms_v1.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.cloud.pubsub_v1.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.cloud.pubsub_v1.cpython-311.pyc new file mode 100644 index 0000000..9db6845 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.cloud.pubsub_v1.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.cloud.speech.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.cloud.speech.cpython-311.pyc new file mode 100644 index 0000000..5ab2965 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.cloud.speech.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.cloud.storage.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.cloud.storage.cpython-311.pyc new file mode 100644 index 0000000..3be5e19 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.cloud.storage.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.cloud.translate.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.cloud.translate.cpython-311.pyc new file mode 100644 index 0000000..d9fcba5 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.cloud.translate.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-googleapiclient.model.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-googleapiclient.model.cpython-311.pyc new file mode 100644 index 0000000..eedc11a Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-googleapiclient.model.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-grapheme.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-grapheme.cpython-311.pyc new file mode 100644 index 0000000..c64d282 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-grapheme.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-graphql_query.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-graphql_query.cpython-311.pyc new file mode 100644 index 0000000..fe3edf4 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-graphql_query.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-great_expectations.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-great_expectations.cpython-311.pyc new file mode 100644 index 0000000..cc07685 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-great_expectations.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gribapi.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gribapi.cpython-311.pyc new file mode 100644 index 0000000..dfe8a4e Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gribapi.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-grpc.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-grpc.cpython-311.pyc new file mode 100644 index 0000000..7d3f275 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-grpc.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gst._gst.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gst._gst.cpython-311.pyc new file mode 100644 index 0000000..4c41fb7 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gst._gst.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gtk.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gtk.cpython-311.pyc new file mode 100644 index 0000000..f61d19c Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gtk.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-h3.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-h3.cpython-311.pyc new file mode 100644 index 0000000..ebcda56 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-h3.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-h5py.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-h5py.cpython-311.pyc new file mode 100644 index 0000000..532971a Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-h5py.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-hdf5plugin.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-hdf5plugin.cpython-311.pyc new file mode 100644 index 0000000..2685104 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-hdf5plugin.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-hexbytes.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-hexbytes.cpython-311.pyc new file mode 100644 index 0000000..eafd24b Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-hexbytes.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-httplib2.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-httplib2.cpython-311.pyc new file mode 100644 index 0000000..c1d5d8e Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-httplib2.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-humanize.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-humanize.cpython-311.pyc new file mode 100644 index 0000000..7ca7b6a Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-humanize.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-hydra.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-hydra.cpython-311.pyc new file mode 100644 index 0000000..f755114 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-hydra.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ijson.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ijson.cpython-311.pyc new file mode 100644 index 0000000..01f9848 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ijson.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-imageio.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-imageio.cpython-311.pyc new file mode 100644 index 0000000..a62367a Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-imageio.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-imageio_ffmpeg.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-imageio_ffmpeg.cpython-311.pyc new file mode 100644 index 0000000..dd2ee7b Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-imageio_ffmpeg.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-iminuit.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-iminuit.cpython-311.pyc new file mode 100644 index 0000000..4fe07b1 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-iminuit.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-iso639.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-iso639.cpython-311.pyc new file mode 100644 index 0000000..f61c6cb Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-iso639.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-itk.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-itk.cpython-311.pyc new file mode 100644 index 0000000..abf54cc Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-itk.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jaraco.text.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jaraco.text.cpython-311.pyc new file mode 100644 index 0000000..758ebba Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jaraco.text.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jedi.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jedi.cpython-311.pyc new file mode 100644 index 0000000..f763a6f Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jedi.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jieba.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jieba.cpython-311.pyc new file mode 100644 index 0000000..c34d76b Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jieba.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jinja2.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jinja2.cpython-311.pyc new file mode 100644 index 0000000..be80371 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jinja2.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jinxed.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jinxed.cpython-311.pyc new file mode 100644 index 0000000..f746ade Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jinxed.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jira.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jira.cpython-311.pyc new file mode 100644 index 0000000..ab12281 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jira.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jsonpath_rw_ext.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jsonpath_rw_ext.cpython-311.pyc new file mode 100644 index 0000000..90bbd6c Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jsonpath_rw_ext.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jsonrpcserver.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jsonrpcserver.cpython-311.pyc new file mode 100644 index 0000000..417bdc2 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jsonrpcserver.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jsonschema.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jsonschema.cpython-311.pyc new file mode 100644 index 0000000..4625d63 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jsonschema.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jsonschema_specifications.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jsonschema_specifications.cpython-311.pyc new file mode 100644 index 0000000..245babb Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jsonschema_specifications.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jupyterlab.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jupyterlab.cpython-311.pyc new file mode 100644 index 0000000..f7268cd Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jupyterlab.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-kaleido.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-kaleido.cpython-311.pyc new file mode 100644 index 0000000..76cf981 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-kaleido.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-khmernltk.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-khmernltk.cpython-311.pyc new file mode 100644 index 0000000..0e5cad4 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-khmernltk.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-kinterbasdb.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-kinterbasdb.cpython-311.pyc new file mode 100644 index 0000000..67edea7 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-kinterbasdb.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-langchain.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-langchain.cpython-311.pyc new file mode 100644 index 0000000..517213d Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-langchain.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-langcodes.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-langcodes.cpython-311.pyc new file mode 100644 index 0000000..73d2f88 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-langcodes.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-langdetect.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-langdetect.cpython-311.pyc new file mode 100644 index 0000000..e716291 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-langdetect.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-laonlp.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-laonlp.cpython-311.pyc new file mode 100644 index 0000000..29fcb6d Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-laonlp.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lark.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lark.cpython-311.pyc new file mode 100644 index 0000000..b53ff76 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lark.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ldfparser.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ldfparser.cpython-311.pyc new file mode 100644 index 0000000..48f28fc Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ldfparser.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lensfunpy.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lensfunpy.cpython-311.pyc new file mode 100644 index 0000000..ea0d7d9 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lensfunpy.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-libaudioverse.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-libaudioverse.cpython-311.pyc new file mode 100644 index 0000000..fef2b38 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-libaudioverse.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-librosa.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-librosa.cpython-311.pyc new file mode 100644 index 0000000..3dfce6e Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-librosa.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lightgbm.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lightgbm.cpython-311.pyc new file mode 100644 index 0000000..f96ff6f Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lightgbm.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lightning.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lightning.cpython-311.pyc new file mode 100644 index 0000000..bac1678 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lightning.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-limits.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-limits.cpython-311.pyc new file mode 100644 index 0000000..4511719 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-limits.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-linear_operator.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-linear_operator.cpython-311.pyc new file mode 100644 index 0000000..d19805f Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-linear_operator.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lingua.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lingua.cpython-311.pyc new file mode 100644 index 0000000..61fc09c Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lingua.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-litestar.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-litestar.cpython-311.pyc new file mode 100644 index 0000000..c91bbe8 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-litestar.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-llvmlite.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-llvmlite.cpython-311.pyc new file mode 100644 index 0000000..36875c6 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-llvmlite.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-logilab.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-logilab.cpython-311.pyc new file mode 100644 index 0000000..f0cc645 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-logilab.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lxml.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lxml.cpython-311.pyc new file mode 100644 index 0000000..2654e54 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lxml.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lxml.etree.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lxml.etree.cpython-311.pyc new file mode 100644 index 0000000..92b3922 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lxml.etree.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lxml.isoschematron.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lxml.isoschematron.cpython-311.pyc new file mode 100644 index 0000000..3ead57f Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lxml.isoschematron.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lxml.objectify.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lxml.objectify.cpython-311.pyc new file mode 100644 index 0000000..0c9befb Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lxml.objectify.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lz4.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lz4.cpython-311.pyc new file mode 100644 index 0000000..129293b Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lz4.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-magic.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-magic.cpython-311.pyc new file mode 100644 index 0000000..0d4dd7d Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-magic.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-mako.codegen.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-mako.codegen.cpython-311.pyc new file mode 100644 index 0000000..21fa6f0 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-mako.codegen.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-mariadb.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-mariadb.cpython-311.pyc new file mode 100644 index 0000000..bad2bd8 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-mariadb.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-markdown.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-markdown.cpython-311.pyc new file mode 100644 index 0000000..6f45028 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-markdown.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-mecab.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-mecab.cpython-311.pyc new file mode 100644 index 0000000..af55f1c Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-mecab.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-metpy.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-metpy.cpython-311.pyc new file mode 100644 index 0000000..23bcf16 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-metpy.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-migrate.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-migrate.cpython-311.pyc new file mode 100644 index 0000000..dc61c79 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-migrate.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-mimesis.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-mimesis.cpython-311.pyc new file mode 100644 index 0000000..1d130ce Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-mimesis.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-minecraft_launcher_lib.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-minecraft_launcher_lib.cpython-311.pyc new file mode 100644 index 0000000..c30baeb Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-minecraft_launcher_lib.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-mistune.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-mistune.cpython-311.pyc new file mode 100644 index 0000000..7ea2d8d Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-mistune.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-mnemonic.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-mnemonic.cpython-311.pyc new file mode 100644 index 0000000..9df7ffa Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-mnemonic.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-monai.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-monai.cpython-311.pyc new file mode 100644 index 0000000..b8942c4 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-monai.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-moviepy.audio.fx.all.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-moviepy.audio.fx.all.cpython-311.pyc new file mode 100644 index 0000000..1f3c6ca Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-moviepy.audio.fx.all.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-moviepy.video.fx.all.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-moviepy.video.fx.all.cpython-311.pyc new file mode 100644 index 0000000..fbbadf9 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-moviepy.video.fx.all.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-mpl_toolkits.basemap.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-mpl_toolkits.basemap.cpython-311.pyc new file mode 100644 index 0000000..6ba34d5 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-mpl_toolkits.basemap.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-msoffcrypto.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-msoffcrypto.cpython-311.pyc new file mode 100644 index 0000000..73dc27c Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-msoffcrypto.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nacl.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nacl.cpython-311.pyc new file mode 100644 index 0000000..d6733bb Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nacl.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-names.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-names.cpython-311.pyc new file mode 100644 index 0000000..a8e95f3 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-names.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nanite.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nanite.cpython-311.pyc new file mode 100644 index 0000000..1e96ce2 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nanite.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nbconvert.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nbconvert.cpython-311.pyc new file mode 100644 index 0000000..6df00d1 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nbconvert.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nbdime.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nbdime.cpython-311.pyc new file mode 100644 index 0000000..c5fa92c Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nbdime.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nbformat.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nbformat.cpython-311.pyc new file mode 100644 index 0000000..5d86547 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nbformat.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nbt.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nbt.cpython-311.pyc new file mode 100644 index 0000000..b97d9c8 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nbt.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ncclient.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ncclient.cpython-311.pyc new file mode 100644 index 0000000..a99f05e Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ncclient.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-netCDF4.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-netCDF4.cpython-311.pyc new file mode 100644 index 0000000..894740a Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-netCDF4.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nltk.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nltk.cpython-311.pyc new file mode 100644 index 0000000..1a71257 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nltk.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nnpy.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nnpy.cpython-311.pyc new file mode 100644 index 0000000..611a30f Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nnpy.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-notebook.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-notebook.cpython-311.pyc new file mode 100644 index 0000000..22f5253 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-notebook.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-numba.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-numba.cpython-311.pyc new file mode 100644 index 0000000..6d9802c Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-numba.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-numbers_parser.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-numbers_parser.cpython-311.pyc new file mode 100644 index 0000000..fab255a Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-numbers_parser.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-numcodecs.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-numcodecs.cpython-311.pyc new file mode 100644 index 0000000..a211d6d Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-numcodecs.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cublas.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cublas.cpython-311.pyc new file mode 100644 index 0000000..c750b4c Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cublas.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cuda_cupti.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cuda_cupti.cpython-311.pyc new file mode 100644 index 0000000..879f999 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cuda_cupti.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cuda_nvcc.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cuda_nvcc.cpython-311.pyc new file mode 100644 index 0000000..338a207 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cuda_nvcc.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cuda_nvrtc.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cuda_nvrtc.cpython-311.pyc new file mode 100644 index 0000000..1490fe5 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cuda_nvrtc.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cuda_runtime.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cuda_runtime.cpython-311.pyc new file mode 100644 index 0000000..d4b9fed Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cuda_runtime.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cudnn.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cudnn.cpython-311.pyc new file mode 100644 index 0000000..cc28472 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cudnn.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cufft.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cufft.cpython-311.pyc new file mode 100644 index 0000000..b56a7bf Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cufft.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.curand.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.curand.cpython-311.pyc new file mode 100644 index 0000000..40ac98f Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.curand.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cusolver.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cusolver.cpython-311.pyc new file mode 100644 index 0000000..9ecdfa3 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cusolver.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cusparse.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cusparse.cpython-311.pyc new file mode 100644 index 0000000..b279bd5 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cusparse.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.nccl.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.nccl.cpython-311.pyc new file mode 100644 index 0000000..4e1c8ff Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.nccl.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.nvjitlink.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.nvjitlink.cpython-311.pyc new file mode 100644 index 0000000..73e0cea Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.nvjitlink.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.nvtx.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.nvtx.cpython-311.pyc new file mode 100644 index 0000000..e2e5d4e Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.nvtx.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-office365.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-office365.cpython-311.pyc new file mode 100644 index 0000000..bb9f87d Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-office365.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-onnxruntime.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-onnxruntime.cpython-311.pyc new file mode 100644 index 0000000..aca6692 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-onnxruntime.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-opencc.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-opencc.cpython-311.pyc new file mode 100644 index 0000000..c6506cf Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-opencc.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-openpyxl.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-openpyxl.cpython-311.pyc new file mode 100644 index 0000000..97aa3b6 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-openpyxl.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-opentelemetry.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-opentelemetry.cpython-311.pyc new file mode 100644 index 0000000..287e7d6 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-opentelemetry.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-orjson.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-orjson.cpython-311.pyc new file mode 100644 index 0000000..3cee2b4 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-orjson.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-osgeo.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-osgeo.cpython-311.pyc new file mode 100644 index 0000000..3c52154 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-osgeo.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pandas_flavor.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pandas_flavor.cpython-311.pyc new file mode 100644 index 0000000..fa93150 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pandas_flavor.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-panel.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-panel.cpython-311.pyc new file mode 100644 index 0000000..b79a6d4 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-panel.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-parsedatetime.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-parsedatetime.cpython-311.pyc new file mode 100644 index 0000000..a6dcbb1 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-parsedatetime.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-parso.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-parso.cpython-311.pyc new file mode 100644 index 0000000..e974861 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-parso.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-passlib.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-passlib.cpython-311.pyc new file mode 100644 index 0000000..b93d1d3 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-passlib.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-paste.exceptions.reporter.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-paste.exceptions.reporter.cpython-311.pyc new file mode 100644 index 0000000..d4ae56d Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-paste.exceptions.reporter.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-patoolib.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-patoolib.cpython-311.pyc new file mode 100644 index 0000000..869c0da Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-patoolib.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-patsy.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-patsy.cpython-311.pyc new file mode 100644 index 0000000..55e46a0 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-patsy.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pdfminer.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pdfminer.cpython-311.pyc new file mode 100644 index 0000000..d7399bd Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pdfminer.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pendulum.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pendulum.cpython-311.pyc new file mode 100644 index 0000000..17aeb28 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pendulum.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-phonenumbers.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-phonenumbers.cpython-311.pyc new file mode 100644 index 0000000..08ae9b8 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-phonenumbers.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pingouin.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pingouin.cpython-311.pyc new file mode 100644 index 0000000..b58b980 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pingouin.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pint.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pint.cpython-311.pyc new file mode 100644 index 0000000..0ef5d11 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pint.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pinyin.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pinyin.cpython-311.pyc new file mode 100644 index 0000000..6070afe Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pinyin.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-platformdirs.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-platformdirs.cpython-311.pyc new file mode 100644 index 0000000..638abb1 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-platformdirs.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-plotly.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-plotly.cpython-311.pyc new file mode 100644 index 0000000..508b559 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-plotly.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pptx.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pptx.cpython-311.pyc new file mode 100644 index 0000000..1aa87c1 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pptx.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-prettytable.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-prettytable.cpython-311.pyc new file mode 100644 index 0000000..1e98189 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-prettytable.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-psutil.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-psutil.cpython-311.pyc new file mode 100644 index 0000000..8a9c3ca Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-psutil.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-psychopy.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-psychopy.cpython-311.pyc new file mode 100644 index 0000000..31584de Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-psychopy.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-psycopg2.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-psycopg2.cpython-311.pyc new file mode 100644 index 0000000..e90ab71 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-psycopg2.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-publicsuffix2.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-publicsuffix2.cpython-311.pyc new file mode 100644 index 0000000..4bc2026 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-publicsuffix2.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pubsub.core.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pubsub.core.cpython-311.pyc new file mode 100644 index 0000000..a44c775 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pubsub.core.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-puremagic.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-puremagic.cpython-311.pyc new file mode 100644 index 0000000..b054a4e Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-puremagic.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-py.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-py.cpython-311.pyc new file mode 100644 index 0000000..e2f2ab4 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-py.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyarrow.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyarrow.cpython-311.pyc new file mode 100644 index 0000000..5ad64e9 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyarrow.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pycountry.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pycountry.cpython-311.pyc new file mode 100644 index 0000000..8d33745 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pycountry.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pycparser.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pycparser.cpython-311.pyc new file mode 100644 index 0000000..97ac127 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pycparser.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pycrfsuite.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pycrfsuite.cpython-311.pyc new file mode 100644 index 0000000..6932a4c Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pycrfsuite.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pydantic.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pydantic.cpython-311.pyc new file mode 100644 index 0000000..2c4c924 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pydantic.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pydicom.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pydicom.cpython-311.pyc new file mode 100644 index 0000000..0ec14b8 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pydicom.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pydivert.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pydivert.cpython-311.pyc new file mode 100644 index 0000000..00b388d Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pydivert.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel-io.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel-io.cpython-311.pyc new file mode 100644 index 0000000..999195b Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel-io.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel-ods.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel-ods.cpython-311.pyc new file mode 100644 index 0000000..29f3064 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel-ods.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel-ods3.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel-ods3.cpython-311.pyc new file mode 100644 index 0000000..90487b6 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel-ods3.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel-odsr.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel-odsr.cpython-311.pyc new file mode 100644 index 0000000..777fe1e Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel-odsr.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel-xls.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel-xls.cpython-311.pyc new file mode 100644 index 0000000..7cd5ddc Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel-xls.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel-xlsx.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel-xlsx.cpython-311.pyc new file mode 100644 index 0000000..5c4324f Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel-xlsx.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel-xlsxw.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel-xlsxw.cpython-311.pyc new file mode 100644 index 0000000..b9f926a Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel-xlsxw.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel.cpython-311.pyc new file mode 100644 index 0000000..b5c9136 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel_io.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel_io.cpython-311.pyc new file mode 100644 index 0000000..1e2b036 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel_io.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel_ods.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel_ods.cpython-311.pyc new file mode 100644 index 0000000..0242294 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel_ods.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel_ods3.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel_ods3.cpython-311.pyc new file mode 100644 index 0000000..7714d23 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel_ods3.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel_odsr.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel_odsr.cpython-311.pyc new file mode 100644 index 0000000..4a5e0a2 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel_odsr.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel_xls.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel_xls.cpython-311.pyc new file mode 100644 index 0000000..b5d54c6 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel_xls.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel_xlsx.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel_xlsx.cpython-311.pyc new file mode 100644 index 0000000..c09cb80 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel_xlsx.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel_xlsxw.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel_xlsxw.cpython-311.pyc new file mode 100644 index 0000000..307eccc Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel_xlsxw.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcelerate.Writer.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcelerate.Writer.cpython-311.pyc new file mode 100644 index 0000000..1dee051 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcelerate.Writer.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pygraphviz.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pygraphviz.cpython-311.pyc new file mode 100644 index 0000000..87253f3 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pygraphviz.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pygwalker.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pygwalker.cpython-311.pyc new file mode 100644 index 0000000..b47aafd Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pygwalker.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pylibmagic.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pylibmagic.cpython-311.pyc new file mode 100644 index 0000000..ddae1bd Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pylibmagic.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pylint.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pylint.cpython-311.pyc new file mode 100644 index 0000000..49d751a Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pylint.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pylsl.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pylsl.cpython-311.pyc new file mode 100644 index 0000000..ee5a36b Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pylsl.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pymediainfo.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pymediainfo.cpython-311.pyc new file mode 100644 index 0000000..6fcd685 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pymediainfo.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pymorphy3.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pymorphy3.cpython-311.pyc new file mode 100644 index 0000000..5e955db Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pymorphy3.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pymssql.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pymssql.cpython-311.pyc new file mode 100644 index 0000000..7ec78d5 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pymssql.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pynput.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pynput.cpython-311.pyc new file mode 100644 index 0000000..39a7c00 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pynput.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyodbc.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyodbc.cpython-311.pyc new file mode 100644 index 0000000..3f4ba1e Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyodbc.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyopencl.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyopencl.cpython-311.pyc new file mode 100644 index 0000000..76712c3 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyopencl.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pypemicro.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pypemicro.cpython-311.pyc new file mode 100644 index 0000000..bc3fd23 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pypemicro.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyphen.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyphen.cpython-311.pyc new file mode 100644 index 0000000..d6463a5 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyphen.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyppeteer.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyppeteer.cpython-311.pyc new file mode 100644 index 0000000..c6a8db1 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyppeteer.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyproj.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyproj.cpython-311.pyc new file mode 100644 index 0000000..d462e0a Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyproj.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pypsexec.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pypsexec.cpython-311.pyc new file mode 100644 index 0000000..e39fdc0 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pypsexec.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pypylon.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pypylon.cpython-311.pyc new file mode 100644 index 0000000..6fbeb67 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pypylon.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyqtgraph.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyqtgraph.cpython-311.pyc new file mode 100644 index 0000000..6afe36a Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyqtgraph.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyshark.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyshark.cpython-311.pyc new file mode 100644 index 0000000..e105cf3 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyshark.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pysnmp.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pysnmp.cpython-311.pyc new file mode 100644 index 0000000..220df2c Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pysnmp.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pystray.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pystray.cpython-311.pyc new file mode 100644 index 0000000..248a037 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pystray.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pytest.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pytest.cpython-311.pyc new file mode 100644 index 0000000..f828e23 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pytest.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pythainlp.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pythainlp.cpython-311.pyc new file mode 100644 index 0000000..68597ac Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pythainlp.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pythoncom.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pythoncom.cpython-311.pyc new file mode 100644 index 0000000..2d21bbb Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pythoncom.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyttsx.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyttsx.cpython-311.pyc new file mode 100644 index 0000000..c559dad Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyttsx.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyttsx3.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyttsx3.cpython-311.pyc new file mode 100644 index 0000000..d9ad1d1 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyttsx3.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyviz_comms.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyviz_comms.cpython-311.pyc new file mode 100644 index 0000000..185f317 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyviz_comms.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyvjoy.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyvjoy.cpython-311.pyc new file mode 100644 index 0000000..10e323c Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyvjoy.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pywintypes.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pywintypes.cpython-311.pyc new file mode 100644 index 0000000..7cedd79 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pywintypes.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pywt.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pywt.cpython-311.pyc new file mode 100644 index 0000000..9ba98ba Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pywt.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-qtmodern.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-qtmodern.cpython-311.pyc new file mode 100644 index 0000000..914e8d3 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-qtmodern.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-radicale.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-radicale.cpython-311.pyc new file mode 100644 index 0000000..3e515b2 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-radicale.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-raven.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-raven.cpython-311.pyc new file mode 100644 index 0000000..f5e0763 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-raven.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-rawpy.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-rawpy.cpython-311.pyc new file mode 100644 index 0000000..fd7ef3e Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-rawpy.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-rdflib.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-rdflib.cpython-311.pyc new file mode 100644 index 0000000..a156dd4 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-rdflib.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-redmine.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-redmine.cpython-311.pyc new file mode 100644 index 0000000..90e0d51 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-redmine.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-regex.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-regex.cpython-311.pyc new file mode 100644 index 0000000..f162605 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-regex.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-reportlab.lib.utils.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-reportlab.lib.utils.cpython-311.pyc new file mode 100644 index 0000000..47e2f4b Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-reportlab.lib.utils.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-reportlab.pdfbase._fontdata.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-reportlab.pdfbase._fontdata.cpython-311.pyc new file mode 100644 index 0000000..584edd5 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-reportlab.pdfbase._fontdata.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-resampy.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-resampy.cpython-311.pyc new file mode 100644 index 0000000..4eac77f Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-resampy.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-rlp.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-rlp.cpython-311.pyc new file mode 100644 index 0000000..88e46de Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-rlp.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-rpy2.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-rpy2.cpython-311.pyc new file mode 100644 index 0000000..890a467 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-rpy2.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-rtree.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-rtree.cpython-311.pyc new file mode 100644 index 0000000..5f557d6 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-rtree.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-rubicon.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-rubicon.cpython-311.pyc new file mode 100644 index 0000000..4e52cd5 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-rubicon.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sacremoses.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sacremoses.cpython-311.pyc new file mode 100644 index 0000000..10f0ab0 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sacremoses.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-saml2.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-saml2.cpython-311.pyc new file mode 100644 index 0000000..0447056 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-saml2.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-schwifty.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-schwifty.cpython-311.pyc new file mode 100644 index 0000000..fb398a1 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-schwifty.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-seedir.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-seedir.cpython-311.pyc new file mode 100644 index 0000000..697d572 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-seedir.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-selenium.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-selenium.cpython-311.pyc new file mode 100644 index 0000000..1454bc1 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-selenium.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sentry_sdk.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sentry_sdk.cpython-311.pyc new file mode 100644 index 0000000..c3bdc55 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sentry_sdk.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-setuptools_scm.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-setuptools_scm.cpython-311.pyc new file mode 100644 index 0000000..cb96784 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-setuptools_scm.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-shapely.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-shapely.cpython-311.pyc new file mode 100644 index 0000000..db2e69f Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-shapely.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-shotgun_api3.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-shotgun_api3.cpython-311.pyc new file mode 100644 index 0000000..624615a Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-shotgun_api3.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-simplemma.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-simplemma.cpython-311.pyc new file mode 100644 index 0000000..a721257 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-simplemma.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.color.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.color.cpython-311.pyc new file mode 100644 index 0000000..3b0e9ba Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.color.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.cpython-311.pyc new file mode 100644 index 0000000..79023b5 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.data.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.data.cpython-311.pyc new file mode 100644 index 0000000..a05d1fd Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.data.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.draw.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.draw.cpython-311.pyc new file mode 100644 index 0000000..7a7c6c1 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.draw.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.exposure.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.exposure.cpython-311.pyc new file mode 100644 index 0000000..5584422 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.exposure.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.feature.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.feature.cpython-311.pyc new file mode 100644 index 0000000..57df446 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.feature.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.filters.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.filters.cpython-311.pyc new file mode 100644 index 0000000..c20ac3a Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.filters.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.future.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.future.cpython-311.pyc new file mode 100644 index 0000000..4f1ba23 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.future.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.graph.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.graph.cpython-311.pyc new file mode 100644 index 0000000..fd7c467 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.graph.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.io.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.io.cpython-311.pyc new file mode 100644 index 0000000..471a218 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.io.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.measure.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.measure.cpython-311.pyc new file mode 100644 index 0000000..7868c92 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.measure.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.metrics.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.metrics.cpython-311.pyc new file mode 100644 index 0000000..aedc1e5 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.metrics.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.morphology.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.morphology.cpython-311.pyc new file mode 100644 index 0000000..f666350 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.morphology.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.registration.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.registration.cpython-311.pyc new file mode 100644 index 0000000..08d0180 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.registration.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.restoration.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.restoration.cpython-311.pyc new file mode 100644 index 0000000..eec9ebf Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.restoration.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.transform.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.transform.cpython-311.pyc new file mode 100644 index 0000000..e525bb2 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.transform.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.cluster.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.cluster.cpython-311.pyc new file mode 100644 index 0000000..a66a928 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.cluster.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.cpython-311.pyc new file mode 100644 index 0000000..840423b Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.linear_model.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.linear_model.cpython-311.pyc new file mode 100644 index 0000000..53f10f2 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.linear_model.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.metrics.cluster.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.metrics.cluster.cpython-311.pyc new file mode 100644 index 0000000..6f6556f Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.metrics.cluster.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.metrics.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.metrics.cpython-311.pyc new file mode 100644 index 0000000..e6d10bc Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.metrics.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.metrics.pairwise.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.metrics.pairwise.cpython-311.pyc new file mode 100644 index 0000000..c65f630 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.metrics.pairwise.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.neighbors.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.neighbors.cpython-311.pyc new file mode 100644 index 0000000..3d92921 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.neighbors.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.tree.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.tree.cpython-311.pyc new file mode 100644 index 0000000..af8420a Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.tree.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.utils.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.utils.cpython-311.pyc new file mode 100644 index 0000000..ab22f97 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.utils.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skyfield.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skyfield.cpython-311.pyc new file mode 100644 index 0000000..8d8a914 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skyfield.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-slixmpp.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-slixmpp.cpython-311.pyc new file mode 100644 index 0000000..e111b8e Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-slixmpp.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sound_lib.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sound_lib.cpython-311.pyc new file mode 100644 index 0000000..75b462d Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sound_lib.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sounddevice.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sounddevice.cpython-311.pyc new file mode 100644 index 0000000..44ccb7f Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sounddevice.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-soundfile.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-soundfile.cpython-311.pyc new file mode 100644 index 0000000..9d70532 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-soundfile.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-spacy.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-spacy.cpython-311.pyc new file mode 100644 index 0000000..e5e7b59 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-spacy.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-speech_recognition.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-speech_recognition.cpython-311.pyc new file mode 100644 index 0000000..6726cb7 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-speech_recognition.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-spiceypy.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-spiceypy.cpython-311.pyc new file mode 100644 index 0000000..1926d9c Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-spiceypy.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-spnego.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-spnego.cpython-311.pyc new file mode 100644 index 0000000..9ea3d66 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-spnego.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-srsly.msgpack._packer.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-srsly.msgpack._packer.cpython-311.pyc new file mode 100644 index 0000000..60dc896 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-srsly.msgpack._packer.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sspilib.raw.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sspilib.raw.cpython-311.pyc new file mode 100644 index 0000000..c3e6048 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sspilib.raw.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-statsmodels.tsa.statespace.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-statsmodels.tsa.statespace.cpython-311.pyc new file mode 100644 index 0000000..bc7900b Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-statsmodels.tsa.statespace.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-stdnum.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-stdnum.cpython-311.pyc new file mode 100644 index 0000000..39e6211 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-stdnum.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-storm.database.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-storm.database.cpython-311.pyc new file mode 100644 index 0000000..e3330d3 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-storm.database.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sudachipy.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sudachipy.cpython-311.pyc new file mode 100644 index 0000000..ac6acd6 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sudachipy.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sunpy.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sunpy.cpython-311.pyc new file mode 100644 index 0000000..07353f9 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sunpy.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sv_ttk.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sv_ttk.cpython-311.pyc new file mode 100644 index 0000000..10fe354 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sv_ttk.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-swagger_spec_validator.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-swagger_spec_validator.cpython-311.pyc new file mode 100644 index 0000000..4ba07ee Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-swagger_spec_validator.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sympy.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sympy.cpython-311.pyc new file mode 100644 index 0000000..acbad9e Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sympy.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-tableauhyperapi.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-tableauhyperapi.cpython-311.pyc new file mode 100644 index 0000000..9a9cf34 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-tableauhyperapi.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-tables.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-tables.cpython-311.pyc new file mode 100644 index 0000000..ae5d94a Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-tables.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-tcod.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-tcod.cpython-311.pyc new file mode 100644 index 0000000..433d633 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-tcod.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-tensorflow.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-tensorflow.cpython-311.pyc new file mode 100644 index 0000000..eb2c021 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-tensorflow.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-text_unidecode.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-text_unidecode.cpython-311.pyc new file mode 100644 index 0000000..f39f9d4 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-text_unidecode.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-textdistance.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-textdistance.cpython-311.pyc new file mode 100644 index 0000000..a34bc48 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-textdistance.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-thinc.backends.numpy_ops.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-thinc.backends.numpy_ops.cpython-311.pyc new file mode 100644 index 0000000..1e7342d Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-thinc.backends.numpy_ops.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-thinc.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-thinc.cpython-311.pyc new file mode 100644 index 0000000..c8185d3 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-thinc.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-timezonefinder.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-timezonefinder.cpython-311.pyc new file mode 100644 index 0000000..839e24a Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-timezonefinder.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-timm.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-timm.cpython-311.pyc new file mode 100644 index 0000000..93f42b1 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-timm.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-tinycss2.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-tinycss2.cpython-311.pyc new file mode 100644 index 0000000..76d1429 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-tinycss2.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-toga.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-toga.cpython-311.pyc new file mode 100644 index 0000000..8d76112 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-toga.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-toga_cocoa.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-toga_cocoa.cpython-311.pyc new file mode 100644 index 0000000..0f381bc Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-toga_cocoa.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-toga_gtk.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-toga_gtk.cpython-311.pyc new file mode 100644 index 0000000..6697c9e Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-toga_gtk.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-toga_winforms.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-toga_winforms.cpython-311.pyc new file mode 100644 index 0000000..3b04aea Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-toga_winforms.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-torch.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-torch.cpython-311.pyc new file mode 100644 index 0000000..95196a4 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-torch.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-torchaudio.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-torchaudio.cpython-311.pyc new file mode 100644 index 0000000..47a5e52 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-torchaudio.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-torchtext.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-torchtext.cpython-311.pyc new file mode 100644 index 0000000..167ac2f Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-torchtext.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-torchvision.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-torchvision.cpython-311.pyc new file mode 100644 index 0000000..7df8201 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-torchvision.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-torchvision.io.image.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-torchvision.io.image.cpython-311.pyc new file mode 100644 index 0000000..276d2bd Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-torchvision.io.image.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame.cpython-311.pyc new file mode 100644 index 0000000..31896ab Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_client.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_client.cpython-311.pyc new file mode 100644 index 0000000..1fce2c4 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_client.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_code.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_code.cpython-311.pyc new file mode 100644 index 0000000..e02a8ec Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_code.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_components.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_components.cpython-311.pyc new file mode 100644 index 0000000..71391f1 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_components.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_datagrid.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_datagrid.cpython-311.pyc new file mode 100644 index 0000000..c42fc2d Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_datagrid.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_deckgl.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_deckgl.cpython-311.pyc new file mode 100644 index 0000000..33f13b7 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_deckgl.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_formkit.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_formkit.cpython-311.pyc new file mode 100644 index 0000000..47abc43 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_formkit.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_grid.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_grid.cpython-311.pyc new file mode 100644 index 0000000..e30d883 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_grid.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_iframe.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_iframe.cpython-311.pyc new file mode 100644 index 0000000..c68e105 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_iframe.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_keycloak.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_keycloak.cpython-311.pyc new file mode 100644 index 0000000..c22cc2a Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_keycloak.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_leaflet.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_leaflet.cpython-311.pyc new file mode 100644 index 0000000..6c7cbd9 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_leaflet.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_markdown.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_markdown.cpython-311.pyc new file mode 100644 index 0000000..ff7f0c5 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_markdown.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_matplotlib.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_matplotlib.cpython-311.pyc new file mode 100644 index 0000000..a541f9c Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_matplotlib.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_mesh_streamer.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_mesh_streamer.cpython-311.pyc new file mode 100644 index 0000000..9f98ccd Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_mesh_streamer.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_plotly.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_plotly.cpython-311.pyc new file mode 100644 index 0000000..cec0271 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_plotly.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_pvui.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_pvui.cpython-311.pyc new file mode 100644 index 0000000..40fbafd Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_pvui.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_quasar.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_quasar.cpython-311.pyc new file mode 100644 index 0000000..dd4cf9b Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_quasar.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_rca.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_rca.cpython-311.pyc new file mode 100644 index 0000000..5295452 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_rca.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_router.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_router.cpython-311.pyc new file mode 100644 index 0000000..5611a85 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_router.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_simput.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_simput.cpython-311.pyc new file mode 100644 index 0000000..492bac0 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_simput.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_tauri.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_tauri.cpython-311.pyc new file mode 100644 index 0000000..a9fd674 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_tauri.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_tweakpane.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_tweakpane.cpython-311.pyc new file mode 100644 index 0000000..2b444a7 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_tweakpane.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_vega.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_vega.cpython-311.pyc new file mode 100644 index 0000000..48c76f1 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_vega.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_vtk.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_vtk.cpython-311.pyc new file mode 100644 index 0000000..66eab66 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_vtk.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_vtk3d.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_vtk3d.cpython-311.pyc new file mode 100644 index 0000000..3d7d401 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_vtk3d.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_vtklocal.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_vtklocal.cpython-311.pyc new file mode 100644 index 0000000..c411c4e Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_vtklocal.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_vuetify.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_vuetify.cpython-311.pyc new file mode 100644 index 0000000..106e408 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_vuetify.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_xterm.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_xterm.cpython-311.pyc new file mode 100644 index 0000000..cdc4f54 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_xterm.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-transformers.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-transformers.cpython-311.pyc new file mode 100644 index 0000000..7efd13c Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-transformers.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-travertino.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-travertino.cpython-311.pyc new file mode 100644 index 0000000..26fb45e Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-travertino.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trimesh.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trimesh.cpython-311.pyc new file mode 100644 index 0000000..51a1eb0 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trimesh.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-triton.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-triton.cpython-311.pyc new file mode 100644 index 0000000..12085ed Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-triton.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ttkthemes.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ttkthemes.cpython-311.pyc new file mode 100644 index 0000000..2036e94 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ttkthemes.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ttkwidgets.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ttkwidgets.cpython-311.pyc new file mode 100644 index 0000000..fd5c3bc Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ttkwidgets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-tzdata.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-tzdata.cpython-311.pyc new file mode 100644 index 0000000..6d5b12c Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-tzdata.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-tzwhere.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-tzwhere.cpython-311.pyc new file mode 100644 index 0000000..308bd2e Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-tzwhere.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-u1db.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-u1db.cpython-311.pyc new file mode 100644 index 0000000..e30c79c Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-u1db.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ultralytics.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ultralytics.cpython-311.pyc new file mode 100644 index 0000000..76432c7 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ultralytics.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-umap.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-umap.cpython-311.pyc new file mode 100644 index 0000000..80eab3e Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-umap.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-unidecode.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-unidecode.cpython-311.pyc new file mode 100644 index 0000000..ddfe15e Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-unidecode.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-uniseg.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-uniseg.cpython-311.pyc new file mode 100644 index 0000000..b471042 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-uniseg.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-usb.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-usb.cpython-311.pyc new file mode 100644 index 0000000..faf0a4b Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-usb.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-uvicorn.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-uvicorn.cpython-311.pyc new file mode 100644 index 0000000..c4b8c2a Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-uvicorn.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-uvloop.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-uvloop.cpython-311.pyc new file mode 100644 index 0000000..d019903 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-uvloop.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-vaderSentiment.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-vaderSentiment.cpython-311.pyc new file mode 100644 index 0000000..94104e4 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-vaderSentiment.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-vtkpython.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-vtkpython.cpython-311.pyc new file mode 100644 index 0000000..f1fad4f Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-vtkpython.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-wavefile.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-wavefile.cpython-311.pyc new file mode 100644 index 0000000..517376d Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-wavefile.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-weasyprint.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-weasyprint.cpython-311.pyc new file mode 100644 index 0000000..1a6504d Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-weasyprint.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-web3.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-web3.cpython-311.pyc new file mode 100644 index 0000000..e6c2b00 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-web3.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-webassets.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-webassets.cpython-311.pyc new file mode 100644 index 0000000..dad0777 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-webassets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-webrtcvad.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-webrtcvad.cpython-311.pyc new file mode 100644 index 0000000..c836d17 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-webrtcvad.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-websockets.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-websockets.cpython-311.pyc new file mode 100644 index 0000000..7bcf562 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-websockets.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-webview.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-webview.cpython-311.pyc new file mode 100644 index 0000000..1a6c316 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-webview.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-win32com.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-win32com.cpython-311.pyc new file mode 100644 index 0000000..9fb5e8f Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-win32com.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-wordcloud.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-wordcloud.cpython-311.pyc new file mode 100644 index 0000000..175430c Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-wordcloud.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-workflow.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-workflow.cpython-311.pyc new file mode 100644 index 0000000..cf12676 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-workflow.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-wx.lib.activex.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-wx.lib.activex.cpython-311.pyc new file mode 100644 index 0000000..56ea398 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-wx.lib.activex.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-wx.lib.pubsub.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-wx.lib.pubsub.cpython-311.pyc new file mode 100644 index 0000000..e5ae66d Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-wx.lib.pubsub.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-wx.xrc.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-wx.xrc.cpython-311.pyc new file mode 100644 index 0000000..8fa905e Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-wx.xrc.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-xarray.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-xarray.cpython-311.pyc new file mode 100644 index 0000000..1e0cf73 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-xarray.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-xml.dom.html.HTMLDocument.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-xml.dom.html.HTMLDocument.cpython-311.pyc new file mode 100644 index 0000000..4254e65 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-xml.dom.html.HTMLDocument.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-xml.sax.saxexts.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-xml.sax.saxexts.cpython-311.pyc new file mode 100644 index 0000000..1f3b71c Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-xml.sax.saxexts.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-xmldiff.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-xmldiff.cpython-311.pyc new file mode 100644 index 0000000..90947ca Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-xmldiff.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-xmlschema.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-xmlschema.cpython-311.pyc new file mode 100644 index 0000000..637553c Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-xmlschema.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-xsge_gui.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-xsge_gui.cpython-311.pyc new file mode 100644 index 0000000..9c8e51d Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-xsge_gui.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-xyzservices.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-xyzservices.cpython-311.pyc new file mode 100644 index 0000000..833bfcd Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-xyzservices.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-yapf_third_party.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-yapf_third_party.cpython-311.pyc new file mode 100644 index 0000000..18ed18a Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-yapf_third_party.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-z3c.rml.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-z3c.rml.cpython-311.pyc new file mode 100644 index 0000000..2ce011e Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-z3c.rml.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-zeep.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-zeep.cpython-311.pyc new file mode 100644 index 0000000..5be059f Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-zeep.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-zmq.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-zmq.cpython-311.pyc new file mode 100644 index 0000000..1e2ccb5 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-zmq.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-zoneinfo.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-zoneinfo.cpython-311.pyc new file mode 100644 index 0000000..37ee5ba Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-zoneinfo.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-BTrees.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-BTrees.py new file mode 100644 index 0000000..1213dfd --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-BTrees.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for BTrees: https://pypi.org/project/BTrees/4.5.1/ + +from PyInstaller.utils.hooks import collect_submodules + +hiddenimports = collect_submodules('BTrees') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-CTkMessagebox.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-CTkMessagebox.py new file mode 100644 index 0000000..dd43aad --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-CTkMessagebox.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +# A fully customizable messagebox for customtkinter! +# (extension/add-on) +# ------------------------------------------------------------------ +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("CTkMessagebox") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-Crypto.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-Crypto.py new file mode 100644 index 0000000..a52de53 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-Crypto.py @@ -0,0 +1,62 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Hook for PyCryptodome library: https://pypi.python.org/pypi/pycryptodome + +PyCryptodome is an almost drop-in replacement for the now unmaintained +PyCrypto library. The two are mutually exclusive as they live under +the same package ("Crypto"). + +PyCryptodome distributes dynamic libraries and builds them as if they were +Python C extensions (even though they are not extensions - as they can't be +imported by Python). It might sound a bit weird, but this decision is rooted +in PyPy and its partial and slow support for C extensions. However, this also +invalidates several of the existing methods used by PyInstaller to decide the +right files to pull in. + +Even though this hook is meant to help with PyCryptodome only, it will be +triggered also when PyCrypto is installed, so it must be tested with both. + +Tested with PyCryptodome 3.5.1, PyCrypto 2.6.1, Python 2.7 & 3.6, Fedora & Windows +""" + +import os +import glob + +from PyInstaller.compat import EXTENSION_SUFFIXES +from PyInstaller.utils.hooks import get_module_file_attribute + +# Include the modules as binaries in a subfolder named like the package. +# Cryptodome's loader expects to find them inside the package directory for +# the main module. We cannot use hiddenimports because that would add the +# modules outside the package. + +binaries = [] +binary_module_names = [ + 'Crypto.Math', # First in the list + 'Crypto.Cipher', + 'Crypto.Util', + 'Crypto.Hash', + 'Crypto.Protocol', + 'Crypto.PublicKey', +] + +try: + for module_name in binary_module_names: + m_dir = os.path.dirname(get_module_file_attribute(module_name)) + for ext in EXTENSION_SUFFIXES: + module_bin = glob.glob(os.path.join(m_dir, '_*%s' % ext)) + for f in module_bin: + binaries.append((f, module_name.replace('.', os.sep))) +except ImportError: + # Do nothing for PyCrypto (Crypto.Math does not exist there) + pass diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-Cryptodome.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-Cryptodome.py new file mode 100644 index 0000000..3a88482 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-Cryptodome.py @@ -0,0 +1,44 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Hook for Cryptodome module: https://pypi.python.org/pypi/pycryptodomex + +Tested with Cryptodomex 3.4.2, Python 2.7 & 3.5, Windows +""" + +import os +import glob + +from PyInstaller.compat import EXTENSION_SUFFIXES +from PyInstaller.utils.hooks import get_module_file_attribute + +# Include the modules as binaries in a subfolder named like the package. +# Cryptodome's loader expects to find them inside the package directory for +# the main module. We cannot use hiddenimports because that would add the +# modules outside the package. + +binaries = [] +binary_module_names = [ + 'Cryptodome.Cipher', + 'Cryptodome.Util', + 'Cryptodome.Hash', + 'Cryptodome.Protocol', + 'Cryptodome.Math', + 'Cryptodome.PublicKey', +] + +for module_name in binary_module_names: + m_dir = os.path.dirname(get_module_file_attribute(module_name)) + for ext in EXTENSION_SUFFIXES: + module_bin = glob.glob(os.path.join(m_dir, '_*%s' % ext)) + for f in module_bin: + binaries.append((f, module_name.replace('.', '/'))) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-HtmlTestRunner.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-HtmlTestRunner.py new file mode 100644 index 0000000..56abec9 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-HtmlTestRunner.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for HtmlTestRunner: https://pypi.org/project/html-testRunner//1.2.1 + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('HtmlTestRunner') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-IPython.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-IPython.py new file mode 100644 index 0000000..8fec50b --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-IPython.py @@ -0,0 +1,42 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Tested with IPython 4.0.0. + +from PyInstaller.compat import is_win, is_darwin +from PyInstaller.utils.hooks import collect_data_files + +# Ignore 'matplotlib'. IPython contains support for matplotlib. +# Ignore GUI libraries. IPython supports integration with GUI frameworks. +# Assume that it will be imported by any other module when the user really +# uses it. +excludedimports = [ + 'gtk', + 'matplotlib', + 'PySide', + 'PyQt4', + 'PySide2', + 'PyQt5', + 'PySide6', + 'PyQt6', +] + +# IPython uses 'tkinter' for clipboard access on Linux/Unix. Exclude it on Windows and OS X. +if is_win or is_darwin: + excludedimports.append('tkinter') + +datas = collect_data_files('IPython') + +# IPython imports extensions by changing to the extensions directory and using +# importlib.import_module, so we need to copy over the extensions as if they +# were data files. +datas += collect_data_files('IPython.extensions', include_py_files=True) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-OpenGL.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-OpenGL.py new file mode 100644 index 0000000..f959702 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-OpenGL.py @@ -0,0 +1,65 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Hook for PyOpenGL 3.x versions from 3.0.0b6 up. Previous versions have a +plugin system based on pkg_resources which is problematic to handle correctly +under pyinstaller; 2.x versions used to run fine without hooks, so this one +shouldn't hurt. +""" + +from PyInstaller.compat import is_win, is_darwin +from PyInstaller.utils.hooks import collect_data_files, exec_statement +import os +import glob + + +def opengl_arrays_modules(): + """ + Return list of array modules for OpenGL module. + e.g. 'OpenGL.arrays.vbo' + """ + statement = 'import OpenGL; print(OpenGL.__path__[0])' + opengl_mod_path = exec_statement(statement) + arrays_mod_path = os.path.join(opengl_mod_path, 'arrays') + files = glob.glob(arrays_mod_path + '/*.py') + modules = [] + + for f in files: + mod = os.path.splitext(os.path.basename(f))[0] + # Skip __init__ module. + if mod == '__init__': + continue + modules.append('OpenGL.arrays.' + mod) + + return modules + + +# PlatformPlugin performs a conditional import based on os.name and +# sys.platform. PyInstaller misses this so let's add it ourselves... +if is_win: + hiddenimports = ['OpenGL.platform.win32'] +elif is_darwin: + hiddenimports = ['OpenGL.platform.darwin'] +# Use glx for other platforms (Linux, ...) +else: + hiddenimports = ['OpenGL.platform.glx'] + +# Arrays modules are needed too. +hiddenimports += opengl_arrays_modules() + +# PyOpenGL 3.x uses ctypes to load DLL libraries. PyOpenGL windows installer +# adds necessary dll files to +# DLL_DIRECTORY = os.path.join( os.path.dirname( OpenGL.__file__ ), 'DLLS') +# PyInstaller is not able to find these dlls. Just include them all as data +# files. +if is_win: + datas = collect_data_files('OpenGL') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-OpenGL_accelerate.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-OpenGL_accelerate.py new file mode 100644 index 0000000..5d6998b --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-OpenGL_accelerate.py @@ -0,0 +1,22 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +OpenGL_accelerate contais modules written in cython. This module +should speed up some functions from OpenGL module. The following +hiddenimports are not resolved by PyInstaller because OpenGL_accelerate +is compiled to native Python modules. +""" + +hiddenimports = [ + 'OpenGL_accelerate.wrapper', + 'OpenGL_accelerate.formathandler', +] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-PyTaskbar.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-PyTaskbar.py new file mode 100644 index 0000000..55a82a1 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-PyTaskbar.py @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("PyTaskbar") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-Xlib.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-Xlib.py new file mode 100644 index 0000000..8ce588e --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-Xlib.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_submodules + +hiddenimports = collect_submodules('Xlib') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-_mssql.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-_mssql.py new file mode 100644 index 0000000..356a314 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-_mssql.py @@ -0,0 +1,13 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +hiddenimports = ['uuid'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-_mysql.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-_mysql.py new file mode 100644 index 0000000..252fd2a --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-_mysql.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Hook for _mysql, required if higher-level pure python module is not imported +""" + +hiddenimports = ['_mysql_exceptions'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-accessible_output2.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-accessible_output2.py new file mode 100644 index 0000000..8d69536 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-accessible_output2.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +accessible_output2: http://hg.q-continuum.net/accessible_output2 +""" + +from PyInstaller.utils.hooks import collect_dynamic_libs + +binaries = collect_dynamic_libs('accessible_output2') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-adbutils.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-adbutils.py new file mode 100644 index 0000000..302439e --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-adbutils.py @@ -0,0 +1,23 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files, is_module_satisfies + +# adb.exe is not automatically collected by collect_dynamic_libs() +datas = collect_data_files("adbutils", subdir="binaries", includes=["adb*"]) + +# adbutils v2.2.2 replaced `pkg_resources` with `importlib.resources`, and now uses the following code to determine the +# path to the `adbutils.binaries` sub-package directory: +# https://github.com/openatx/adbutils/blob/2.2.2/adbutils/_utils.py#L78-L87 +# As `adbutils.binaries` is not directly imported anywhere, we need a hidden import. +if is_module_satisfies('adbutils >= 2.2.2'): + hiddenimports = ['adbutils.binaries'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-adios.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-adios.py new file mode 100644 index 0000000..761de00 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-adios.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Hook for http://pypi.python.org/pypi/adios/ +""" + +hiddenimports = ['adios._hl.selections'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-afmformats.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-afmformats.py new file mode 100644 index 0000000..79eafa6 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-afmformats.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for afmformats: https://pypi.python.org/pypi/afmformats + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('afmformats') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-aliyunsdkcore.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-aliyunsdkcore.py new file mode 100644 index 0000000..50b0d96 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-aliyunsdkcore.py @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("aliyunsdkcore") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-altair.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-altair.py new file mode 100644 index 0000000..126115b --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-altair.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("altair") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-amazonproduct.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-amazonproduct.py new file mode 100644 index 0000000..46b8467 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-amazonproduct.py @@ -0,0 +1,26 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Hook for Python bindings for Amazon's Product Advertising API. +https://bitbucket.org/basti/python-amazon-product-api +""" + +hiddenimports = ['amazonproduct.processors.__init__', + 'amazonproduct.processors._lxml', + 'amazonproduct.processors.objectify', + 'amazonproduct.processors.elementtree', + 'amazonproduct.processors.etree', + 'amazonproduct.processors.minidom', + 'amazonproduct.contrib.__init__', + 'amazonproduct.contrib.cart', + 'amazonproduct.contrib.caching', + 'amazonproduct.contrib.retry'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-anyio.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-anyio.py new file mode 100644 index 0000000..c19fb44 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-anyio.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +AnyIO contains a number of back-ends as dynamically imported modules. +This hook was tested against AnyIO v1.4.0. +""" + +from PyInstaller.utils.hooks import collect_submodules + +hiddenimports = collect_submodules('anyio._backends') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-appdirs.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-appdirs.py new file mode 100644 index 0000000..d49d5ba --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-appdirs.py @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Import hook for appdirs. + +On Windows, appdirs tries 2 different methods to get well-known directories +from the system: First with win32com, then with ctypes. Excluding win32com here +avoids including all the win32com related DLLs in programs that don't include +them otherwise. +""" + +excludedimports = ['win32com'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-appy.pod.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-appy.pod.py new file mode 100644 index 0000000..056aea2 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-appy.pod.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for appy.pod: https://pypi.python.org/pypi/appy/0.9.1 + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('appy.pod', True) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-apscheduler.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-apscheduler.py new file mode 100644 index 0000000..4ac1838 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-apscheduler.py @@ -0,0 +1,27 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +APScheduler uses entry points to dynamically load executors, job +stores and triggers. +This hook was tested against APScheduler 3.6.3. +""" + +from PyInstaller.utils.hooks import (collect_submodules, copy_metadata, + is_module_satisfies) + +if is_module_satisfies("apscheduler < 4"): + if is_module_satisfies("pyinstaller >= 4.4"): + datas = copy_metadata('APScheduler', recursive=True) + else: + datas = copy_metadata('APScheduler') + + hiddenimports = collect_submodules('apscheduler') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-argon2.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-argon2.py new file mode 100644 index 0000000..505639a --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-argon2.py @@ -0,0 +1,13 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +hiddenimports = ["_cffi_backend"] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-astor.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-astor.py new file mode 100644 index 0000000..93452da --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-astor.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('astor') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-astroid.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-astroid.py new file mode 100644 index 0000000..22323cd --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-astroid.py @@ -0,0 +1,48 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +# +# *************************************************** +# hook-astriod.py - PyInstaller hook file for astriod +# *************************************************** +# The astriod package, in __pkginfo__.py, is version 1.1.1. Looking at its +# source: +# +# From __init__.py, starting at line 111:: +# +# BRAIN_MODULES_DIR = join(dirname(__file__), 'brain') +# if BRAIN_MODULES_DIR not in sys.path: +# # add it to the end of the list so user path take precedence +# sys.path.append(BRAIN_MODULES_DIR) +# # load modules in this directory +# for module in listdir(BRAIN_MODULES_DIR): +# if module.endswith('.py'): +# __import__(module[:-3]) +# +# So, we need all the Python source in the ``brain/`` subdirectory, +# since this is run-time discovered and loaded. Therefore, these +# files are all data files. + +from PyInstaller.utils.hooks import collect_data_files, collect_submodules, \ + is_module_or_submodule + +# Note that brain/ isn't a module (it lacks an __init__.py, so it can't be +# referred to as astroid.brain; instead, locate it as package astriod, +# subdirectory brain/. +datas = collect_data_files('astroid', True, 'brain') + +# Update: in astroid v 1.4.1, the brain/ module import parts of astroid. Since +# everything in brain/ is dynamically imported, these are hidden imports. For +# simplicity, include everything in astroid. Exclude all the test/ subpackage +# contents and the test_util module. +hiddenimports = ['six'] + collect_submodules('astroid', + lambda name: (not is_module_or_submodule(name, 'astroid.tests')) and + (not name == 'test_util')) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-astropy.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-astropy.py new file mode 100644 index 0000000..925ca4d --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-astropy.py @@ -0,0 +1,42 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files, collect_submodules, \ + copy_metadata, is_module_satisfies + +# Astropy includes a number of non-Python files that need to be present +# at runtime, so we include these explicitly here. +datas = collect_data_files('astropy') + +# In a number of places, astropy imports other sub-modules in a way that is not +# always auto-discovered by pyinstaller, so we always include all submodules. +hiddenimports = collect_submodules('astropy') + +# We now need to include the *_parsetab.py and *_lextab.py files for unit and +# coordinate parsing, since these are loaded as files rather than imported as +# sub-modules. We leverage collect_data_files to get all files in astropy then +# filter these. +ply_files = [] +for path, target in collect_data_files('astropy', include_py_files=True): + if path.endswith(('_parsetab.py', '_lextab.py')): + ply_files.append((path, target)) + +datas += ply_files + +# Astropy version >= 5.0 queries metadata to get version information. +if is_module_satisfies('astropy >= 5.0'): + datas += copy_metadata('astropy') + datas += copy_metadata('numpy') + +# In the Cython code, Astropy imports numpy.lib.recfunctions which isn't +# automatically discovered by pyinstaller, so we add this as a hidden import. +hiddenimports += ['numpy.lib.recfunctions'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-astropy_iers_data.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-astropy_iers_data.py new file mode 100644 index 0000000..828dd45 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-astropy_iers_data.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for https://github.com/astropy/astropy-iers-data + +from PyInstaller.utils.hooks import collect_data_files +datas = collect_data_files("astropy_iers_data") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-av.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-av.py new file mode 100644 index 0000000..8770d6d --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-av.py @@ -0,0 +1,44 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +import os + +from PyInstaller.compat import is_win +from PyInstaller.utils.hooks import collect_submodules, is_module_satisfies, get_package_paths + +hiddenimports = ['fractions'] + collect_submodules("av") + +# Starting with av 9.1.1, the DLLs shipped with Windows PyPI wheels are stored +# in site-packages/av.libs instead of directly in the site-packages/av. +if is_module_satisfies("av >= 9.1.1") and is_win: + pkg_base, pkg_dir = get_package_paths("av") + lib_dir = os.path.join(pkg_base, "av.libs") + if os.path.isdir(lib_dir): + # We collect DLLs as data files instead of binaries to suppress binary + # analysis, which would result in duplicates (because it collects a copy + # into the top-level directory instead of preserving the original layout). + # In addition to DLls, this also collects .load-order* file (required on + # python < 3.8), and ensures that Shapely.libs directory exists (required + # on python >= 3.8 due to os.add_dll_directory call). + datas = [ + (os.path.join(lib_dir, lib_file), 'av.libs') + for lib_file in os.listdir(lib_dir) + ] + +# With av 13.0.0, one of the cythonized modules (`av.audio.layout`) started using `dataclasses`. Add it to hidden +# imports to ensure it is collected in cases when it is not referenced from anywhere else. +if is_module_satisfies("av >= 13.0.0"): + hiddenimports += ['dataclasses'] + +# av 13.1.0 added a cythonized `av.opaque` module that uses `uuid`; add it to hidden imports to ensure it is collected +# in cases when it is not referenced from anywhere else. +if is_module_satisfies("av >= 13.1.0"): + hiddenimports += ['uuid'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-avro.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-avro.py new file mode 100644 index 0000000..178fa29 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-avro.py @@ -0,0 +1,27 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Avro is a serialization and RPC framework. +""" + +import os +from PyInstaller.utils.hooks import get_module_file_attribute + +res_loc = os.path.dirname(get_module_file_attribute("avro")) +# see https://github.com/apache/avro/blob/master/lang/py3/setup.py +datas = [ + # Include the version.txt file, used to set __version__ + (os.path.join(res_loc, "VERSION.txt"), "avro"), + # The handshake schema is needed for IPC communication + (os.path.join(res_loc, "HandshakeRequest.avsc"), "avro"), + (os.path.join(res_loc, "HandshakeResponse.avsc"), "avro"), +] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-azurerm.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-azurerm.py new file mode 100644 index 0000000..52e9c51 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-azurerm.py @@ -0,0 +1,22 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +# Azurerm is a lite api to microsoft azure. +# Azurerm is using pkg_resources internally which is not supported by py-installer. +# This hook will collect the module metadata. +# Tested with Azurerm 0.10.0 + +from PyInstaller.utils.hooks import copy_metadata, is_module_satisfies + +if is_module_satisfies("pyinstaller >= 4.4"): + datas = copy_metadata("azurerm", recursive=True) +else: + datas = copy_metadata("azurerm") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-backports.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-backports.py new file mode 100644 index 0000000..af9ead4 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-backports.py @@ -0,0 +1,20 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Some of jaraco's backports packages (backports.functools-lru-cache, backports.tarfile) use pkgutil-style `backports` +# namespace package, with `__init__.py` file that contains: +# +# __path__ = __import__('pkgutil').extend_path(__path__, __name__) +# +# This import via `__import__` function slips past PyInstaller's modulegraph analysis; so add a hidden import, in case +# the user's program (and its dependencies) have no other direct imports of `pkgutil`. +hiddenimports = ['pkgutil'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-backports.zoneinfo.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-backports.zoneinfo.py new file mode 100644 index 0000000..03a5e41 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-backports.zoneinfo.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.compat import is_win + +# On Windows, timezone data is provided by the tzdata package that is +# not directly loaded. +if is_win: + hiddenimports = ['tzdata'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-bacon.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-bacon.py new file mode 100644 index 0000000..febf11b --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-bacon.py @@ -0,0 +1,50 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for Bacon (https://github.com/aholkner/bacon) +# Bacon requires its native DLLs to be copied alongside frozen executable. + +import os +import ctypes + +from PyInstaller.compat import is_win, is_darwin +from PyInstaller.utils.hooks import get_package_paths + + +def collect_native_files(package, files): + pkg_base, pkg_dir = get_package_paths(package) + return [(os.path.join(pkg_dir, file), '.') for file in files] + + +if is_win: + files = ['Bacon.dll', + 'd3dcompiler_46.dll', + 'libEGL.dll', + 'libGLESv2.dll', + 'msvcp110.dll', + 'msvcr110.dll', + 'vccorllib110.dll'] + if ctypes.sizeof(ctypes.c_void_p) == 4: + hiddenimports = ["bacon.windows32"] + datas = collect_native_files('bacon.windows32', files) + else: + hiddenimports = ["bacon.windows64"] + datas = collect_native_files('bacon.windows64', files) +elif is_darwin: + if ctypes.sizeof(ctypes.c_void_p) == 4: + hiddenimports = ["bacon.darwin32"] + files = ['Bacon.dylib'] + datas = collect_native_files('bacon.darwin32', files) + else: + hiddenimports = ["bacon.darwin64"] + files = ['Bacon64.dylib'] + datas = collect_native_files('bacon.darwin64', files) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-bcrypt.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-bcrypt.py new file mode 100644 index 0000000..adbb592 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-bcrypt.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Hook for https://pypi.org/project/bcrypt/ +""" + +hiddenimports = ['_cffi_backend'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-bitsandbytes.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-bitsandbytes.py new file mode 100644 index 0000000..a6cb7e0 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-bitsandbytes.py @@ -0,0 +1,23 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# --------------------------------------------------- + +from PyInstaller.utils.hooks import collect_dynamic_libs + +# bitsandbytes contains several extensions for CPU and different CUDA versions: libbitsandbytes_cpu.so, +# libbitsandbytes_cuda110_nocublaslt.so, libbitsandbytes_cuda110.so, etc. At build-time, we could query the +# `bitsandbytes.cextension.setup` and its `binary_name˙ attribute for the extension that is in use. However, if the +# build system does not have CUDA available, this would automatically mean that we will not collect any of the CUDA +# libs. So for now, we collect them all. +binaries = collect_dynamic_libs("bitsandbytes") + +# bitsandbytes uses triton's JIT module, which requires access to source .py files. +module_collection_mode = 'pyz+py' diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-bleak.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-bleak.py new file mode 100644 index 0000000..9fa261e --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-bleak.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +# hook for https://github.com/hbldh/bleak + +from PyInstaller.utils.hooks import collect_data_files, collect_dynamic_libs +from PyInstaller.compat import is_win + +if is_win: + datas = collect_data_files('bleak', subdir=r'backends\dotnet') + binaries = collect_dynamic_libs('bleak') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-blspy.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-blspy.py new file mode 100644 index 0000000..18cbca2 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-blspy.py @@ -0,0 +1,35 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +import os +import glob + +from PyInstaller.utils.hooks import get_module_file_attribute +from PyInstaller.compat import is_win + +# blspy comes as a stand-alone extension module that's placed directly +# in site-packages. +# +# On macOS and Linux, it is linked against the GMP library, whose shared +# library is stored in blspy.libs and .dylibsblspy, respectively. As this +# is a linked dependency, it is collected properly by PyInstaller and +# no further work is needed. +# +# On Windows, however, the blspy extension is linked against MPIR library, +# whose DLLs are placed directly into site-packages. The mpir.dll is +# linked dependency and is picked up automatically, but it in turn +# dynamically loads CPU-specific backends that are named mpir_*.dll. +# We need to colllect these manually. +if is_win: + blspy_dir = os.path.dirname(get_module_file_attribute('blspy')) + mpir_dlls = glob.glob(os.path.join(blspy_dir, 'mpir_*.dll')) + binaries = [(mpir_dll, '.') for mpir_dll in mpir_dlls] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-bokeh.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-bokeh.py new file mode 100644 index 0000000..8c42be6 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-bokeh.py @@ -0,0 +1,27 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files, copy_metadata, is_module_satisfies + +# core/_templates/* +# server/static/**/* +# subcommands/*.py +# bokeh/_sri.json + +datas = collect_data_files('bokeh.core') + \ + collect_data_files('bokeh.server') + \ + collect_data_files('bokeh.command.subcommands', include_py_files=True) + \ + collect_data_files('bokeh') + +# bokeh >= 3.0.0 sets its __version__ from metadata +if is_module_satisfies('bokeh >= 3.0.0'): + datas += copy_metadata('bokeh') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-boto.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-boto.py new file mode 100644 index 0000000..4ee2144 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-boto.py @@ -0,0 +1,25 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +# +# Boto3, the next version of Boto, is now stable and recommended for general +# use. +# +# Boto is an integrated interface to current and future infrastructural +# services offered by Amazon Web Services. +# +# http://boto.readthedocs.org/en/latest/ +# +# Tested with boto 2.38.0 + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('boto') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-boto3.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-boto3.py new file mode 100644 index 0000000..579463c --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-boto3.py @@ -0,0 +1,29 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +# +# Boto is the Amazon Web Services (AWS) SDK for Python, which allows Python +# developers to write software that makes use of Amazon services like S3 and +# EC2. Boto provides an easy to use, object-oriented API as well as low-level +# direct service access. +# +# http://boto3.readthedocs.org/en/latest/ +# +# Tested with boto3 1.2.1 + +from PyInstaller.utils.hooks import collect_data_files, collect_submodules + +hiddenimports = ( + collect_submodules('boto3.dynamodb') + + collect_submodules('boto3.ec2') + + collect_submodules('boto3.s3') +) +datas = collect_data_files('boto3') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-botocore.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-botocore.py new file mode 100644 index 0000000..47ab1a0 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-botocore.py @@ -0,0 +1,30 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +# +# Botocore is a low-level interface to a growing number of Amazon Web Services. +# Botocore serves as the foundation for the AWS-CLI command line utilities. It +# will also play an important role in the boto3.x project. +# +# The botocore package is compatible with Python versions 2.6.5, Python 2.7.x, +# and Python 3.3.x and higher. +# +# https://botocore.readthedocs.org/en/latest/ +# +# Tested with botocore 1.4.36 + +from PyInstaller.utils.hooks import collect_data_files +from PyInstaller.utils.hooks import is_module_satisfies + +if is_module_satisfies('botocore >= 1.4.36'): + hiddenimports = ['html.parser'] + +datas = collect_data_files('botocore') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-branca.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-branca.py new file mode 100644 index 0000000..9cb01f9 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-branca.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("branca") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cairocffi.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cairocffi.py new file mode 100644 index 0000000..c7db979 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cairocffi.py @@ -0,0 +1,45 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +import ctypes.util +import os + +from PyInstaller.depend.utils import _resolveCtypesImports +from PyInstaller.utils.hooks import collect_data_files, is_module_satisfies, logger + +datas = collect_data_files("cairocffi") + +binaries = [] + +# NOTE: Update this if cairocffi requires more libraries +libs = ["cairo-2", "cairo", "libcairo-2"] + +try: + lib_basenames = [] + for lib in libs: + libname = ctypes.util.find_library(lib) + if libname is not None: + lib_basenames += [os.path.basename(libname)] + + if lib_basenames: + resolved_libs = _resolveCtypesImports(lib_basenames) + for resolved_lib in resolved_libs: + binaries.append((resolved_lib[1], '.')) +except Exception as e: + logger.warning("Error while trying to find system-installed Cairo library: %s", e) + +if not binaries: + logger.warning("Cairo library not found - cairocffi will likely fail to work!") + +# cairocffi 1.6.0 requires cairocffi/constants.py source file, so make sure it is collected. +# The module collection mode setting requires PyInstaller >= 5.3. +if is_module_satisfies('cairocffi >= 1.6.0'): + module_collection_mode = {'cairocffi.constants': 'pyz+py'} diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cairosvg.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cairosvg.py new file mode 100644 index 0000000..6098bf2 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cairosvg.py @@ -0,0 +1,40 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +import ctypes.util +import os + +from PyInstaller.depend.utils import _resolveCtypesImports +from PyInstaller.utils.hooks import collect_data_files, logger + +datas = collect_data_files("cairosvg") + +binaries = [] + +# NOTE: Update this if cairosvg requires more libraries +libs = ["cairo-2", "cairo", "libcairo-2"] + +try: + lib_basenames = [] + for lib in libs: + libname = ctypes.util.find_library(lib) + if libname is not None: + lib_basenames += [os.path.basename(libname)] + + if lib_basenames: + resolved_libs = _resolveCtypesImports(lib_basenames) + for resolved_lib in resolved_libs: + binaries.append((resolved_lib[1], '.')) +except Exception as e: + logger.warning("Error while trying to find system-installed Cairo library: %s", e) + +if not binaries: + logger.warning("Cairo library not found - cairosvg will likely fail to work!") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-capstone.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-capstone.py new file mode 100644 index 0000000..3f18043 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-capstone.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +from PyInstaller.utils.hooks import collect_dynamic_libs + +# Collect needed libraries for capstone +binaries = collect_dynamic_libs('capstone') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cassandra.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cassandra.py new file mode 100644 index 0000000..1ebd1dd --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cassandra.py @@ -0,0 +1,22 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2022 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +# +# A modern, feature-rich and highly-tunable Python client library for Apache Cassandra (2.1+) and +# DataStax Enterprise (4.7+) using exclusively Cassandra's binary protocol and Cassandra Query Language v3. +# +# http://datastax.github.io/python-driver/api/index.html +# +# Tested with cassandra-driver 3.25.0 + +from PyInstaller.utils.hooks import collect_submodules + +hiddenimports = collect_submodules('cassandra') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-celpy.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-celpy.py new file mode 100644 index 0000000..6d66a0e --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-celpy.py @@ -0,0 +1,24 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +# +# cel-python is Pure Python implementation of Google Common Expression Language, +# https://opensource.google/projects/cel +# This implementation has minimal dependencies, runs quickly, and can be embedded into Python-based applications. +# Specifically, the intent is to be part of Cloud Custodian, C7N, as part of the security policy filter. +# https://github.com/cloud-custodian/cel-python +# +# Tested with cel-python 0.1.5 + +from PyInstaller.utils.hooks import collect_data_files + +# Collect *.lark file(s) from the package +datas = collect_data_files('celpy') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-certifi.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-certifi.py new file mode 100644 index 0000000..22c3d0b --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-certifi.py @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Certifi is a carefully curated collection of Root Certificates for +# validating the trustworthiness of SSL certificates while verifying +# the identity of TLS hosts. + +# It has been extracted from the Requests project. + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('certifi') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cf_units.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cf_units.py new file mode 100644 index 0000000..e8c1f3f --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cf_units.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2022 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +# Include data files from cf_units/etc sub-directory. +datas = collect_data_files('cf_units', includes=['etc/**']) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cftime.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cftime.py new file mode 100644 index 0000000..20cfc82 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cftime.py @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2022 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# The cftime._cftime is a cython exension with following hidden imports: +hiddenimports = [ + 're', + 'time', + 'datetime', + 'warnings', + 'numpy', + 'cftime._strptime', +] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-charset_normalizer.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-charset_normalizer.py new file mode 100644 index 0000000..17618ac --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-charset_normalizer.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import is_module_satisfies + +if is_module_satisfies("charset_normalizer >= 3.0.1"): + hiddenimports = ["charset_normalizer.md__mypyc"] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cloudpickle.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cloudpickle.py new file mode 100644 index 0000000..bfaff37 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cloudpickle.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import is_module_satisfies + +# cloudpickle to 3.0.0 keeps `cloudpickle_fast` module around for backward compatibility with existing pickled data, +# but does not import it directly anymore. Ensure it is collected nevertheless. +if is_module_satisfies("cloudpickle >= 3.0.0"): + hiddenimports = ["cloudpickle.cloudpickle_fast"] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cloudscraper.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cloudscraper.py new file mode 100644 index 0000000..3656f24 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cloudscraper.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('cloudscraper') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-clr.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-clr.py new file mode 100644 index 0000000..3004f1d --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-clr.py @@ -0,0 +1,60 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# There is a name clash between pythonnet's clr module/extension (which this hooks is for) and clr package that provides +# the terminal styling library (https://pypi.org/project/clr/). Therefore, we must first check if pythonnet is actually +# available... +from PyInstaller.utils.hooks import is_module_satisfies +from PyInstaller.compat import is_win + +if is_module_satisfies("pythonnet"): + # pythonnet requires both clr.pyd and Python.Runtime.dll, but the latter isn't found by PyInstaller. + import ctypes.util + from PyInstaller.log import logger + + try: + import importlib.metadata as importlib_metadata + except ImportError: + import importlib_metadata + + collected_runtime_files = [] + + # Try finding Python.Runtime.dll via distribution's file list + dist_files = importlib_metadata.files('pythonnet') + if dist_files is not None: + runtime_dll_files = [f for f in dist_files if f.match('Python.Runtime.dll')] + if len(runtime_dll_files) == 1: + runtime_dll_file = runtime_dll_files[0] + collected_runtime_files = [(runtime_dll_file.locate(), runtime_dll_file.parent.as_posix())] + logger.debug("hook-clr: Python.Runtime.dll discovered via metadata.") + elif len(runtime_dll_files) > 1: + logger.warning("hook-clr: multiple instances of Python.Runtime.dll listed in metadata - cannot resolve.") + + # Fall back to the legacy way + if not collected_runtime_files: + runtime_dll_file = ctypes.util.find_library('Python.Runtime') + if runtime_dll_file: + collected_runtime_files = [(runtime_dll_file, '.')] + logger.debug('hook-clr: Python.Runtime.dll discovered via legacy method.') + + if not collected_runtime_files: + raise Exception('Python.Runtime.dll not found') + + # On Windows, collect runtime DLL file(s) as binaries; on other OSes, collect them as data files, to prevent fatal + # errors in binary dependency analysis. + if is_win: + binaries = collected_runtime_files + else: + datas = collected_runtime_files + + # These modules are imported inside Python.Runtime.dll + hiddenimports = ["platform", "warnings"] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-clr_loader.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-clr_loader.py new file mode 100644 index 0000000..e997c41 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-clr_loader.py @@ -0,0 +1,22 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2022 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.compat import is_win, is_cygwin +from PyInstaller.utils.hooks import collect_dynamic_libs + +# The clr-loader is used by pythonnet 3.x to load CLR (.NET) runtime. +# On Windows, the default runtime is the .NET Framework, and its corresponding +# loader requires DLLs from clr_loader\ffi\dlls to be collected. This runtime +# is supported only on Windows, so we do not have to worry about it on other +# OSes (where Mono or .NET Core are supported). +if is_win or is_cygwin: + binaries = collect_dynamic_libs("clr_loader") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cmocean.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cmocean.py new file mode 100644 index 0000000..d7201b5 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cmocean.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("cmocean", subdir="rgb") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-compliance_checker.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-compliance_checker.py new file mode 100644 index 0000000..d8fb4be --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-compliance_checker.py @@ -0,0 +1,22 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2022 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_submodules, copy_metadata, collect_data_files + +# Collect submodules to ensure that checker plugins are collected. but avoid collecting tests sub-package. +hiddenimports = collect_submodules('compliance_checker', filter=lambda name: name != 'compliance_checker.tests') + +# Copy metadata, because checker plugins are discovered via entry-points +datas = copy_metadata('compliance_checker') + +# Include data files from compliance_checker/data sub-directory. +datas += collect_data_files('compliance_checker', includes=['data/**']) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-comtypes.client.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-comtypes.client.py new file mode 100644 index 0000000..a96e16d --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-comtypes.client.py @@ -0,0 +1,22 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# https://github.com/enthought/comtypes/blob/1.4.5/comtypes/client/_generate.py#L271-L280 +hiddenimports = [ + "comtypes.persist", + "comtypes.typeinfo", + "comtypes.automation", + "comtypes.stream", + "comtypes", + "ctypes.wintypes", + "ctypes", +] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-countrycode.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-countrycode.py new file mode 100644 index 0000000..535105d --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-countrycode.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('countrycode') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-countryinfo.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-countryinfo.py new file mode 100644 index 0000000..aa05a06 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-countryinfo.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import copy_metadata, collect_data_files + +datas = copy_metadata("countryinfo") + collect_data_files("countryinfo") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cryptography.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cryptography.py new file mode 100644 index 0000000..86f1d80 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cryptography.py @@ -0,0 +1,125 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Hook for cryptography module from the Python Cryptography Authority. +""" + +import os +import glob +import pathlib + +from PyInstaller import compat +from PyInstaller import isolated +from PyInstaller.utils.hooks import ( + collect_submodules, + copy_metadata, + get_module_file_attribute, + is_module_satisfies, + logger, +) + +# get the package data so we can load the backends +datas = copy_metadata('cryptography') + +# Add the backends as hidden imports +hiddenimports = collect_submodules('cryptography.hazmat.backends') + +# Add the OpenSSL FFI binding modules as hidden imports +hiddenimports += collect_submodules('cryptography.hazmat.bindings.openssl') + ['_cffi_backend'] + + +# Include the cffi extensions as binaries in a subfolder named like the package. +# The cffi verifier expects to find them inside the package directory for +# the main module. We cannot use hiddenimports because that would add the modules +# outside the package. +# NOTE: this is not true anymore with PyInstaller >= 6.0, but we keep it like this for compatibility with 5.x series. +binaries = [] +cryptography_dir = os.path.dirname(get_module_file_attribute('cryptography')) +for ext in compat.EXTENSION_SUFFIXES: + ffimods = glob.glob(os.path.join(cryptography_dir, '*_cffi_*%s*' % ext)) + for f in ffimods: + binaries.append((f, 'cryptography')) + + +# Check if cryptography was built with support for OpenSSL >= 3.0.0. In that case, we might need to collect external +# OpenSSL modules, if OpenSSL was built with modules support. It seems the best indication of this is the presence +# of ossl-modules directory next to the OpenSSL shared library. +try: + @isolated.decorate + def _check_cryptography_openssl3(): + from cryptography.hazmat.backends.openssl.backend import backend + openssl_version = backend.openssl_version_number() + return openssl_version >= 0x30000000 + + uses_openssl3 = _check_cryptography_openssl3() +except Exception: + logger.warning( + "hook-cryptography: failed to determine whether cryptography is using OpenSSL >= 3.0.0", exc_info=True + ) + uses_openssl3 = False + +if uses_openssl3: + # Determine location of OpenSSL shared library. + # This requires the new PyInstaller.bindepend API from PyInstaller >= 6.0. + openssl_lib = None + if is_module_satisfies("PyInstaller >= 6.0"): + from PyInstaller.depend import bindepend + + if compat.is_win: + # Resolve the given library name; first, search the python library directory for python-provided OpenSSL. + lib_name = 'libssl-3-x64.dll' if compat.is_64bits else 'libssl-3.dll' + openssl_lib = bindepend.resolve_library_path(lib_name, search_paths=[compat.base_prefix]) + elif compat.is_darwin: + # First, attempt to resolve using only {sys.base_prefix}/lib - `bindepend.resolve_library_path` uses + # standard dyld search semantics and uses the given search paths as fallback (and would therefore + # favor Homebrew-provided version of the library). + lib_name = 'libssl.3.dylib' + base_prefix_lib_dir = os.path.join(compat.base_prefix, 'lib') + openssl_lib = bindepend._resolve_library_path_in_search_paths(lib_name, search_paths=[base_prefix_lib_dir]) + if openssl_lib is None: + openssl_lib = bindepend.resolve_library_path(lib_name, search_paths=[base_prefix_lib_dir]) + else: + # Linux and other POSIX systems + lib_name = 'libssl.so.3' + openssl_lib = bindepend.resolve_library_path(lib_name) + if openssl_lib is None and compat.is_musl: + # Work-around for bug in `bindepend.resolve_library_path` in PyInstaller 6.x, <= 6.6; for search without + # ldconfig cache (for example, with musl libc on Alpine linux), we need library name without suffix. + lib_name = 'libssl' + openssl_lib = bindepend.resolve_library_path(lib_name) + else: + logger.warning( + "hook-cryptography: full support for cryptography + OpenSSL >= 3.0.0 requires PyInstaller >= 6.0" + ) + + # Check for presence of ossl-modules directory next to the OpenSSL shared library. + if openssl_lib: + logger.debug("hook-cryptography: OpenSSL shared library location: %r", openssl_lib) + + openssl_lib_dir = pathlib.Path(openssl_lib).parent + + # Collect whole ossl-modules directory, if it exists. + ossl_modules_dir = openssl_lib_dir / 'ossl-modules' + + # Msys2/MinGW installations on Windows put the shared library into `bin` directory, but the modules are + # located in `lib` directory. Account for that possibility. + if not ossl_modules_dir.is_dir() and openssl_lib_dir.name == 'bin': + ossl_modules_dir = openssl_lib_dir.parent / 'lib' / 'ossl-modules' + + # On Alpine linux, the true location of shared library is /lib directory, but the modules' directory is located + # in /usr/lib instead. Account for that possibility. + if not ossl_modules_dir.is_dir() and openssl_lib_dir == pathlib.Path('/lib'): + ossl_modules_dir = pathlib.Path('/usr/lib/ossl-modules') + + if ossl_modules_dir.is_dir(): + logger.debug("hook-cryptography: collecting OpenSSL modules directory: %r", str(ossl_modules_dir)) + binaries.append((str(ossl_modules_dir), 'ossl-modules')) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-customtkinter.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-customtkinter.py new file mode 100644 index 0000000..0247ad6 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-customtkinter.py @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("customtkinter") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cv2.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cv2.py new file mode 100644 index 0000000..d6573c1 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cv2.py @@ -0,0 +1,168 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +import sys +import os +import glob +import pathlib + +import PyInstaller.utils.hooks as hookutils +from PyInstaller import compat + +hiddenimports = ['numpy'] + +# On Windows, make sure that opencv_videoio_ffmpeg*.dll is bundled +binaries = [] +if compat.is_win: + # If conda is active, look for the DLL in its library path + if compat.is_conda: + libdir = os.path.join(compat.base_prefix, 'Library', 'bin') + pattern = os.path.join(libdir, 'opencv_videoio_ffmpeg*.dll') + for f in glob.glob(pattern): + + binaries.append((f, '.')) + + # Include any DLLs from site-packages/cv2 (opencv_videoio_ffmpeg*.dll + # can be found there in the PyPI version) + binaries += hookutils.collect_dynamic_libs('cv2') + +# Collect auxiliary sub-packages, such as `cv2.gapi`, `cv2.mat_wrapper`, `cv2.misc`, and `cv2.utils`. This also +# picks up submodules with valid module names, such as `cv2.config`, `cv2.load_config_py2`, and `cv2.load_config_py3`. +# Therefore, filter out `cv2.load_config_py2`. +hiddenimports += hookutils.collect_submodules('cv2', filter=lambda name: name != 'cv2.load_config_py2') + +# We also need to explicitly exclude `cv2.load_config_py2` due to it being imported in `cv2.__init__`. +excludedimports = ['cv2.load_config_py2'] + +# OpenCV loader from 4.5.4.60 requires extra config files and modules. +# We need to collect `config.py` and `load_config_py3`; to improve compatibility with PyInstaller < 5.2, where +# `module_collection_mode` (see below) is not implemented. +# We also need to collect `config-3.py` or `config-3.X.py`, whichever is available (the former is usually +# provided by PyPI wheels, while the latter seems to be used when user builds OpenCV from source). +datas = hookutils.collect_data_files( + 'cv2', + include_py_files=True, + includes=[ + 'config.py', + f'config-{sys.version_info[0]}.{sys.version_info[1]}.py', + 'config-3.py', + 'load_config_py3.py', + ], +) + + +# The OpenCV versions that attempt to perform module substitution via sys.path manipulation (== 4.5.4.58, >= 4.6.0.66) +# do not directly import the cv2.cv2 extension anymore, so in order to ensure it is collected, we would need to add it +# to hidden imports. However, when OpenCV is built by user from source, the extension is not located in the package's +# root directory, but in python-3.X sub-directory, which precludes referencing via module name due to sub-directory +# not being a valid subpackage name. Hence, emulate the OpenCV's loader and execute `config-3.py` or `config-3.X.py` +# to obtain the search path. +def find_cv2_extension(config_file): + # Prepare environment + PYTHON_EXTENSIONS_PATHS = [] + LOADER_DIR = os.path.dirname(os.path.abspath(os.path.realpath(config_file))) + + global_vars = globals().copy() + local_vars = locals().copy() + + # Exec the config file + with open(config_file) as fp: + code = compile(fp.read(), os.path.basename(config_file), 'exec') + exec(code, global_vars, local_vars) + + # Read the modified PYTHON_EXTENSIONS_PATHS + PYTHON_EXTENSIONS_PATHS = local_vars['PYTHON_EXTENSIONS_PATHS'] + if not PYTHON_EXTENSIONS_PATHS: + return None + + # Search for extension file + for extension_path in PYTHON_EXTENSIONS_PATHS: + extension_path = pathlib.Path(extension_path) + if compat.is_win: + extension_files = list(extension_path.glob('cv2*.pyd')) + else: + extension_files = list(extension_path.glob('cv2*.so')) + if extension_files: + if len(extension_files) > 1: + hookutils.logger.warning("Found multiple cv2 extension candidates: %s", extension_files) + extension_file = extension_files[0] # Take first (or hopefully the only one) + + hookutils.logger.debug("Found cv2 extension module: %s", extension_file) + + # Compute path relative to parent of config file (which should be the package's root) + dest_dir = pathlib.Path("cv2") / extension_file.parent.relative_to(LOADER_DIR) + return str(extension_file), str(dest_dir) + + hookutils.logger.warning( + "Could not find cv2 extension module! Config file: %s, search paths: %s", + config_file, PYTHON_EXTENSIONS_PATHS) + + return None + + +config_file = [ + src_path for src_path, _ in datas + if os.path.basename(src_path) in (f'config-{sys.version_info[0]}.{sys.version_info[1]}.py', 'config-3.py') +] + +if config_file: + try: + extension_info = find_cv2_extension(config_file[0]) + if extension_info: + ext_src, ext_dst = extension_info + # Due to bug in PyInstaller's TOC structure implementation (affecting PyInstaller up to latest version at + # the time of writing, 5.9), we fail to properly resolve `cv2.cv2` EXTENSION entry's destination name if + # we already have a BINARY entry with the same destination name. This results in verbatim `cv2.cv2` file + # created in application directory in addition to the proper copy in the `cv2` sub-directoy. + # Therefoe, if destination directory of the cv2 extension module is the top-level package directory, fall + # back to using hiddenimports instead. + if ext_dst == 'cv2': + # Extension found in top-level package directory; likely a PyPI wheel. + hiddenimports += ['cv2.cv2'] + else: + # Extension found in sub-directory; use BINARY entry + binaries += [extension_info] + except Exception: + hookutils.logger.warning("Failed to determine location of cv2 extension module!", exc_info=True) + + +# Mark the cv2 package to be collected in source form, bypassing PyInstaller's PYZ archive and FrozenImporter. This is +# necessary because recent versions of cv2 package attempt to perform module substritution via sys.path manipulation, +# which is incompatible with the way that FrozenImporter works. This requires pyinstaller/pyinstaller#6945, i.e., +# PyInstaller >= 5.3. On earlier versions, the following statement does nothing, and problematic cv2 versions +# (== 4.5.4.58, >= 4.6.0.66) will not work. +# +# Note that the collect_data_files() above is still necessary, because some of the cv2 loader's config scripts are not +# valid module names (e.g., config-3.py). So the two collection approaches are complementary, and any overlap in files +# (e.g., __init__.py) is handled gracefully due to PyInstaller's uniqueness constraints on collected files. +module_collection_mode = 'py' + +# In linux PyPI opencv-python wheels, the cv2 extension is linked against Qt, and the wheel bundles a basic subset of Qt +# shared libraries, plugins, and font files. This is not the case on other OSes (presumably native UI APIs are used by +# OpenCV HighGUI module), nor in the headless PyPI wheels (opencv-python-headless). +# The bundled Qt shared libraries should be picked up automatically due to binary dependency analysis, but we need to +# collect plugins and font files from the `qt` subdirectory. +if compat.is_linux: + pkg_path = pathlib.Path(hookutils.get_module_file_attribute('cv2')).parent + # Collect .ttf files fron fonts directory. + # NOTE: since we are using glob, we can skip checks for (sub)directories' existence. + qt_fonts_dir = pkg_path / 'qt' / 'fonts' + datas += [ + (str(font_file), str(font_file.parent.relative_to(pkg_path.parent))) + for font_file in qt_fonts_dir.rglob('*.ttf') + ] + # Collect .so files from plugins directory. + qt_plugins_dir = pkg_path / 'qt' / 'plugins' + binaries += [ + (str(plugin_file), str(plugin_file.parent.relative_to(pkg_path.parent))) + for plugin_file in qt_plugins_dir.rglob('*.so') + ] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cx_Oracle.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cx_Oracle.py new file mode 100644 index 0000000..ae5daa8 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cx_Oracle.py @@ -0,0 +1,13 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +hiddenimports = ['decimal'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cytoolz.itertoolz.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cytoolz.itertoolz.py new file mode 100644 index 0000000..fcba975 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-cytoolz.itertoolz.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for the cytoolz package: https://pypi.python.org/pypi/cytoolz +# Tested with cytoolz 0.9.0 and Python 3.5.2, on Ubuntu Linux x64 + +hiddenimports = ['cytoolz.utils', 'cytoolz._signatures'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dash.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dash.py new file mode 100644 index 0000000..07a3fe8 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dash.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('dash') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dash_bootstrap_components.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dash_bootstrap_components.py new file mode 100644 index 0000000..8028d14 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dash_bootstrap_components.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('dash_bootstrap_components') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dash_core_components.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dash_core_components.py new file mode 100644 index 0000000..a41fe5a --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dash_core_components.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('dash_core_components') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dash_html_components.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dash_html_components.py new file mode 100644 index 0000000..077d8a5 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dash_html_components.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('dash_html_components') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dash_renderer.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dash_renderer.py new file mode 100644 index 0000000..854f87e --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dash_renderer.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('dash_renderer') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dash_table.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dash_table.py new file mode 100644 index 0000000..b7bb600 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dash_table.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('dash_table') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dash_uploader.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dash_uploader.py new file mode 100644 index 0000000..f9bf99b --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dash_uploader.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('dash_uploader') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dask.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dask.py new file mode 100644 index 0000000..262737a --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dask.py @@ -0,0 +1,18 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2005-2020, PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +#----------------------------------------------------------------------------- +""" +Collects in-repo dask.yaml and dask-schema.yaml data files. +""" + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('dask', includes=['*.yml', '*.yaml']) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-datasets.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-datasets.py new file mode 100644 index 0000000..1ff1a61 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-datasets.py @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Collect source .py files for JIT/torchscript. Requires PyInstaller >= 5.3, no-op in older versions. +module_collection_mode = 'pyz+py' diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dateparser.utils.strptime.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dateparser.utils.strptime.py new file mode 100644 index 0000000..35e6c92 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dateparser.utils.strptime.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for dateparser: https://pypi.org/project/dateparser/ + +from PyInstaller.utils.hooks import collect_submodules + +hiddenimports = ["_strptime"] + collect_submodules('dateparser.data') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dbus_fast.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dbus_fast.py new file mode 100644 index 0000000..4e2eb72 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dbus_fast.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_submodules + +# Collect all submodules to handle imports made from cythonized extensions. +hiddenimports = collect_submodules('dbus_fast') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dclab.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dclab.py new file mode 100644 index 0000000..3179a16 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dclab.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for dclab: https://pypi.python.org/pypi/dclab + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('dclab') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-detectron2.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-detectron2.py new file mode 100644 index 0000000..1ff1a61 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-detectron2.py @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Collect source .py files for JIT/torchscript. Requires PyInstaller >= 5.3, no-op in older versions. +module_collection_mode = 'pyz+py' diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-discid.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-discid.py new file mode 100644 index 0000000..37cba62 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-discid.py @@ -0,0 +1,40 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2022 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +import os + +from PyInstaller.utils.hooks import get_module_attribute, logger +from PyInstaller.depend.utils import _resolveCtypesImports + +binaries = [] + +# Use the _LIB_NAME attribute of discid.libdiscid to resolve the shared library name. This saves us from having to +# duplicate the name guessing logic from discid.libdiscid. +# On error, PyInstaller >= 5.0 raises exception, earlier versions return an empty string. +try: + lib_name = get_module_attribute("discid.libdiscid", "_LIB_NAME") +except Exception: + lib_name = None + +if lib_name: + lib_name = os.path.basename(lib_name) + try: + resolved_binary = _resolveCtypesImports([lib_name]) + lib_file = resolved_binary[0][1] + except Exception as e: + lib_file = None + logger.warning("Error while trying to resolve %s: %s", lib_name, e) + + if lib_file: + binaries += [(lib_file, '.')] +else: + logger.warning("Failed to determine name of libdiscid shared library from _LIB_NAME attribute of discid.libdiscid!") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-distorm3.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-distorm3.py new file mode 100644 index 0000000..b2fb731 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-distorm3.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for the diStorm3 module: https://pypi.python.org/pypi/distorm3 +# Tested with distorm3 3.3.0, Python 2.7, Windows + +from PyInstaller.utils.hooks import collect_dynamic_libs + +# distorm3 dynamic library should be in the path with other dynamic libraries. +binaries = collect_dynamic_libs('distorm3', destdir='.') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dns.rdata.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dns.rdata.py new file mode 100644 index 0000000..a185ad9 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dns.rdata.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# This is hook for DNS python package dnspython. + +from PyInstaller.utils.hooks import collect_submodules + +hiddenimports = collect_submodules('dns.rdtypes') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-docutils.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-docutils.py new file mode 100644 index 0000000..9d4ee79 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-docutils.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_submodules, collect_data_files + +hiddenimports = (collect_submodules('docutils.languages') + + collect_submodules('docutils.writers') + + collect_submodules('docutils.parsers.rst.languages') + + collect_submodules('docutils.parsers.rst.directives')) +datas = collect_data_files('docutils') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-docx.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-docx.py new file mode 100644 index 0000000..aefe64e --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-docx.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("docx") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-docx2pdf.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-docx2pdf.py new file mode 100644 index 0000000..c746417 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-docx2pdf.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later. +# ------------------------------------------------------------------ + +# Hook for docx2pdf: https://pypi.org/project/docx2pdf/ + +from PyInstaller.utils.hooks import copy_metadata, collect_data_files + +datas = copy_metadata('docx2pdf') +datas += collect_data_files('docx2pdf') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dynaconf.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dynaconf.py new file mode 100644 index 0000000..08c809a --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-dynaconf.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +hiddenimports = ['dynaconf.loaders.env_loader', + 'dynaconf.loaders.redis_loader', + 'dynaconf.loaders.vault.loader'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-easyocr.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-easyocr.py new file mode 100644 index 0000000..a868875 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-easyocr.py @@ -0,0 +1,18 @@ +from PyInstaller.utils.hooks import collect_data_files, get_hook_config + +# Recognition backends are imported with `importlib.import_module()`. +hiddenimports = ['easyocr.model.vgg_model', 'easyocr.model.model'] + + +def hook(hook_api): + lang_codes = get_hook_config(hook_api, 'easyocr', 'lang_codes') + if not lang_codes: + lang_codes = ['*'] + + extra_datas = list() + extra_datas += collect_data_files('easyocr', include_py_files=False, subdir='character', + includes=[f'{lang_code}_char.txt' for lang_code in lang_codes]) + extra_datas += collect_data_files('easyocr', include_py_files=False, subdir='dict', + includes=[f'{lang_code}.txt' for lang_code in lang_codes]) + + hook_api.add_datas(extra_datas) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eel.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eel.py new file mode 100644 index 0000000..ceeb974 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eel.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('eel') +hiddenimports = ['bottle_websocket'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-enchant.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-enchant.py new file mode 100644 index 0000000..ef1aa8a --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-enchant.py @@ -0,0 +1,65 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Import hook for PyEnchant. + +Tested with PyEnchant 1.6.6. +""" + +import os + +from PyInstaller.compat import is_darwin +from PyInstaller.utils.hooks import exec_statement, collect_data_files, \ + collect_dynamic_libs, get_installer + +# TODO Add Linux support +# Collect first all files that were installed directly into pyenchant +# package directory and this includes: +# - Windows: libenchat-1.dll, libenchat_ispell.dll, libenchant_myspell.dll, other +# dependent dlls and dictionaries for several languages (de, en, fr) +# - Mac OS X: usually libenchant.dylib and several dictionaries when installed via pip. +binaries = collect_dynamic_libs('enchant') +datas = collect_data_files('enchant') +excludedimports = ['enchant.tests'] + +# On OS X try to find files from Homebrew or Macports environments. +if is_darwin: + # Note: env. var. ENCHANT_PREFIX_DIR is implemented only in the development version: + # https://github.com/AbiWord/enchant + # https://github.com/AbiWord/enchant/pull/2 + # TODO Test this hook with development version of enchant. + libenchant = exec_statement(""" + from enchant._enchant import e + print(e._name) + """).strip() + + installer = get_installer('enchant') + if installer != 'pip': + # Note: Name of detected enchant library is 'libenchant.dylib'. However, it + # is just symlink to 'libenchant.1.dylib'. + binaries.append((libenchant, '.')) + + # Collect enchant backends from Macports. Using same file structure as on Windows. + backends = exec_statement(""" + from enchant import Broker + for provider in Broker().describe(): + print(provider.file)""").strip().split() + binaries.extend([(b, 'enchant/lib/enchant') for b in backends]) + + # Collect all available dictionaries from Macports. Using same file structure as on Windows. + # In Macports are available mostly hunspell (myspell) and aspell dictionaries. + libdir = os.path.dirname(libenchant) # e.g. /opt/local/lib + sharedir = os.path.join(os.path.dirname(libdir), 'share') # e.g. /opt/local/share + if os.path.exists(os.path.join(sharedir, 'enchant')): + datas.append((os.path.join(sharedir, 'enchant'), 'enchant/share/enchant')) + if os.path.exists(os.path.join(sharedir, 'enchant-2')): + datas.append((os.path.join(sharedir, 'enchant-2'), 'enchant/share/enchant-2')) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eng_to_ipa.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eng_to_ipa.py new file mode 100644 index 0000000..5a78114 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eng_to_ipa.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('eng_to_ipa') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-ens.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-ens.py new file mode 100644 index 0000000..89e496e --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-ens.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("ens") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-enzyme.parsers.ebml.core.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-enzyme.parsers.ebml.core.py new file mode 100644 index 0000000..047274c --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-enzyme.parsers.ebml.core.py @@ -0,0 +1,25 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +enzyme: +https://github.com/Diaoul/enzyme +""" + +import os +from PyInstaller.utils.hooks import get_package_paths + +# get path of enzyme +ep = get_package_paths('enzyme') + +# add the data +data = os.path.join(ep[1], 'parsers', 'ebml', 'specs', 'matroska.xml') +datas = [(data, "enzyme/parsers/ebml/specs")] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eth_abi.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eth_abi.py new file mode 100644 index 0000000..75c26f0 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eth_abi.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import copy_metadata + +datas = copy_metadata("eth_abi") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eth_account.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eth_account.py new file mode 100644 index 0000000..1a9c8f5 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eth_account.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import copy_metadata + +datas = copy_metadata("eth_account") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eth_hash.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eth_hash.py new file mode 100644 index 0000000..0c9d50e --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eth_hash.py @@ -0,0 +1,20 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_submodules, copy_metadata, is_module_satisfies + +# The ``eth_hash.utils.load_backend`` function does a dynamic import. +hiddenimports = collect_submodules('eth_hash.backends') + +# As of eth-hash 0.6.0, it uses importlib.metadata.version() set its __version__ attribute +if is_module_satisfies("eth-hash >= 0.6.0"): + datas = copy_metadata("eth-hash") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eth_keyfile.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eth_keyfile.py new file mode 100644 index 0000000..2d9453a --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eth_keyfile.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import copy_metadata + +datas = copy_metadata("eth_keyfile") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eth_keys.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eth_keys.py new file mode 100644 index 0000000..d96535e --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eth_keys.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import copy_metadata, is_module_satisfies + +# As of eth-keys 0.5.0, it uses importlib.metadata.version() set its __version__ attribute +if is_module_satisfies("eth-keys >= 0.5.0"): + datas = copy_metadata("eth-keys") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eth_rlp.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eth_rlp.py new file mode 100644 index 0000000..01943a6 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eth_rlp.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import is_module_satisfies, copy_metadata + +# Starting with v1.0.0, `eth_rlp` queries its version from metadata. +if is_module_satisfies("eth-rlp >= 1.0.0"): + datas = copy_metadata('eth-rlp') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eth_typing.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eth_typing.py new file mode 100644 index 0000000..f31e4ca --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eth_typing.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import copy_metadata + +# eth-typing queries it's own version using importlib.metadata/pkg_resources. +datas = copy_metadata("eth-typing") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eth_utils.network.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eth_utils.network.py new file mode 100644 index 0000000..3bd88f9 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eth_utils.network.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("eth_utils") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eth_utils.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eth_utils.py new file mode 100644 index 0000000..a87ec3c --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-eth_utils.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import copy_metadata + +datas = copy_metadata("eth_utils") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-exchangelib.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-exchangelib.py new file mode 100644 index 0000000..0c46bcc --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-exchangelib.py @@ -0,0 +1,12 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2022 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +hiddenimports = ['tzdata'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-fabric.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-fabric.py new file mode 100644 index 0000000..3367c0c --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-fabric.py @@ -0,0 +1,22 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2022 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +# +# Fabric is a high level Python (2.7, 3.4+) library designed to execute shell commands remotely over SSH, +# yielding useful Python objects in return +# +# https://docs.fabfile.org/en/latest +# +# Tested with fabric 2.6.0 + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('fabric') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-fairscale.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-fairscale.py new file mode 100644 index 0000000..8b5d53d --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-fairscale.py @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Collect source .py files for JIT/torchscript. Requires PyInstaller >= 5.3, no-op in older versions. +module_collection_mode = 'pyz+py' diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-faker.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-faker.py new file mode 100644 index 0000000..1d5b039 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-faker.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_submodules, collect_data_files + +hiddenimports = collect_submodules('faker.providers') +datas = ( + collect_data_files('text_unidecode') + # noqa: W504 + collect_data_files('faker.providers', include_py_files=True) +) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-falcon.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-falcon.py new file mode 100644 index 0000000..1c1d2b1 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-falcon.py @@ -0,0 +1,41 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.compat import is_py311 +from PyInstaller.utils.hooks import is_module_satisfies + +hiddenimports = [ + 'cgi', + 'falcon.app_helpers', + 'falcon.forwarded', + 'falcon.media', + 'falcon.request_helpers', + 'falcon.responders', + 'falcon.response_helpers', + 'falcon.routing', + 'falcon.vendor.mimeparse', + 'falcon.vendor', + 'uuid', + 'xml.etree.ElementTree', + 'xml.etree' +] + +# falcon v4.0.0 added couple of more cythonized modules that depend on the following stdlib modules. +if is_module_satisfies('falcon >= 4.0.0'): + hiddenimports += [ + 'dataclasses', + 'json', + ] + + # `wsgiref.types` is available (and thus referenced) only under python >= 3.11. + if is_py311: + hiddenimports += ['wsgiref.types'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-fastai.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-fastai.py new file mode 100644 index 0000000..1ff1a61 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-fastai.py @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Collect source .py files for JIT/torchscript. Requires PyInstaller >= 5.3, no-op in older versions. +module_collection_mode = 'pyz+py' diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-fastparquet.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-fastparquet.py new file mode 100644 index 0000000..b43bbb4 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-fastparquet.py @@ -0,0 +1,32 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +import os + +from PyInstaller.compat import is_win +from PyInstaller.utils.hooks import get_package_paths + +# In all versions for which fastparquet provides Windows wheels (>= 0.7.0), delvewheel is used, +# so we need to collect the external site-packages/fastparquet.libs directory. +if is_win: + pkg_base, pkg_dir = get_package_paths("fastparquet") + lib_dir = os.path.join(pkg_base, "fastparquet.libs") + if os.path.isdir(lib_dir): + # We collect DLLs as data files instead of binaries to suppress binary + # analysis, which would result in duplicates (because it collects a copy + # into the top-level directory instead of preserving the original layout). + # In addition to DLls, this also collects .load-order* file (required on + # python < 3.8), and ensures that fastparquet.libs directory exists (required + # on python >= 3.8 due to os.add_dll_directory call). + datas = [ + (os.path.join(lib_dir, lib_file), 'fastparquet.libs') + for lib_file in os.listdir(lib_dir) + ] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-ffpyplayer.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-ffpyplayer.py new file mode 100644 index 0000000..993d8b2 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-ffpyplayer.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import eval_statement, collect_submodules + +hiddenimports = collect_submodules("ffpyplayer") +binaries = [] +# ffpyplayer has an internal variable tells us where the libraries it was using +for bin in eval_statement("import ffpyplayer; print(ffpyplayer.dep_bins)"): + binaries += [(bin, '.')] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-fiona.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-fiona.py new file mode 100644 index 0000000..1e6d3fa --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-fiona.py @@ -0,0 +1,26 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files, is_module_satisfies + +hiddenimports = [ + "fiona._shim", + "fiona.schema", + "json", +] + +# As of fiona 1.9.0, `fiona.enums` is also a hidden import, made in cythonized `fiona.crs`. +if is_module_satisfies("fiona >= 1.9.0"): + hiddenimports.append("fiona.enums") + +# Collect data files that are part of the package (e.g., projections database) +datas = collect_data_files("fiona") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-flask_compress.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-flask_compress.py new file mode 100644 index 0000000..9e04195 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-flask_compress.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import copy_metadata + +datas = copy_metadata('flask_compress') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-flask_restx.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-flask_restx.py new file mode 100644 index 0000000..c83b5b3 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-flask_restx.py @@ -0,0 +1,14 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2005-2020, PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ----------------------------------------------------------------------------- +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('flask_restx') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-flex.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-flex.py new file mode 100644 index 0000000..3faaa82 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-flex.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# hook for https://github.com/pipermerriam/flex + +from PyInstaller.utils.hooks import copy_metadata + +datas = copy_metadata('flex') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-flirpy.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-flirpy.py new file mode 100644 index 0000000..4c51397 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-flirpy.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Hook for flirpy, a library to interact with FLIR thermal imaging cameras and images. +https://github.com/LJMUAstroEcology/flirpy +""" + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('flirpy') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-fmpy.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-fmpy.py new file mode 100644 index 0000000..daeb3c6 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-fmpy.py @@ -0,0 +1,25 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Hook for FMPy, a library to simulate Functional Mockup Units (FMUs) +https://github.com/CATIA-Systems/FMPy + +Adds the data files that are required at runtime: + +- XSD schema files +- dynamic libraries for the CVode solver +- source and header files for the compilation of c-code FMUs +""" + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('fmpy') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-folium.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-folium.py new file mode 100644 index 0000000..a6af178 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-folium.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +# Collect data files (templates) +datas = collect_data_files("folium") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-freetype.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-freetype.py new file mode 100644 index 0000000..0ae5c04 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-freetype.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_dynamic_libs + +# Collect the bundled freetype shared library, if available. +binaries = collect_dynamic_libs('freetype') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-fvcore.nn.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-fvcore.nn.py new file mode 100644 index 0000000..1ff1a61 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-fvcore.nn.py @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Collect source .py files for JIT/torchscript. Requires PyInstaller >= 5.3, no-op in older versions. +module_collection_mode = 'pyz+py' diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-gadfly.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-gadfly.py new file mode 100644 index 0000000..1bf2314 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-gadfly.py @@ -0,0 +1,13 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +hiddenimports = ["sql_mar"] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-gbulb.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-gbulb.py new file mode 100644 index 0000000..68116a1 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-gbulb.py @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Prevent this package from pulling `setuptools_scm` into frozen application, as it makes no sense in that context. +excludedimports = ["setuptools_scm"] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-gcloud.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-gcloud.py new file mode 100644 index 0000000..155426b --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-gcloud.py @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import copy_metadata + +# This hook was written for `gcloud` - https://pypi.org/project/gcloud +# Suppress package-not-found errors when the hook is triggered by `gcloud` namespace package from `gcloud-aio-*` and +# `gcloud-rest-*˙ dists (https://github.com/talkiq/gcloud-aio). +try: + datas = copy_metadata('gcloud') +except Exception: + pass diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-geopandas.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-geopandas.py new file mode 100644 index 0000000..44d9001 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-geopandas.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("geopandas", subdir="datasets") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-gitlab.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-gitlab.py new file mode 100644 index 0000000..8adf54b --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-gitlab.py @@ -0,0 +1,22 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2022 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +# +# python-gitlab is a Python package providing access to the GitLab server API. +# It supports the v4 API of GitLab, and provides a CLI tool (gitlab). +# +# https://python-gitlab.readthedocs.io +# +# Tested with gitlab 3.2.0 + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('gitlab') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-gmplot.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-gmplot.py new file mode 100644 index 0000000..ce2d5ce --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-gmplot.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2005-2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('gmplot') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-gmsh.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-gmsh.py new file mode 100644 index 0000000..d9755d0 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-gmsh.py @@ -0,0 +1,28 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +import os + +from PyInstaller.utils.hooks import logger, get_module_attribute + +# Query the `libpath` attribute of the `gmsh` module to obtain the path to shared library. This way, we do not need to +# duplicate the discovery logic. +try: + lib_file = get_module_attribute('gmsh', 'libpath') +except Exception: + logger.warning("Failed to query gmsh.libpath!", exc_info=True) + lib_file = None + +if lib_file and os.path.isfile(lib_file): + binaries = [(lib_file, '.')] +else: + logger.warning("Could not find gmsh shared library - gmsh will likely fail to load at run-time!") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-gooey.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-gooey.py new file mode 100644 index 0000000..8861b47 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-gooey.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Gooey GUI carries some language and images for it's UI to function. +""" + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('gooey') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-google.api_core.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-google.api_core.py new file mode 100644 index 0000000..641bdf0 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-google.api_core.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import copy_metadata + +datas = copy_metadata('google-api-core') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-google.cloud.bigquery.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-google.cloud.bigquery.py new file mode 100644 index 0000000..1bbfa4a --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-google.cloud.bigquery.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import copy_metadata +datas = (copy_metadata('google-cloud-bigquery') + + # the pakcage queries meta-data about ``request`` + copy_metadata('requests')) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-google.cloud.core.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-google.cloud.core.py new file mode 100644 index 0000000..db7c20e --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-google.cloud.core.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import copy_metadata + +datas = copy_metadata('google-cloud-core') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-google.cloud.kms_v1.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-google.cloud.kms_v1.py new file mode 100644 index 0000000..116d7f4 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-google.cloud.kms_v1.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Client library URL: https://googleapis.dev/python/cloudkms/latest/ +# Import Example for client library: +# https://cloud.google.com/kms/docs/reference/libraries#client-libraries-install-python + +from PyInstaller.utils.hooks import copy_metadata + +datas = copy_metadata('google-cloud-kms') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-google.cloud.pubsub_v1.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-google.cloud.pubsub_v1.py new file mode 100644 index 0000000..d022668 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-google.cloud.pubsub_v1.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import copy_metadata + +datas = copy_metadata('google-cloud-pubsub') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-google.cloud.speech.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-google.cloud.speech.py new file mode 100644 index 0000000..7fed599 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-google.cloud.speech.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import copy_metadata + +datas = copy_metadata('google-cloud-speech') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-google.cloud.storage.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-google.cloud.storage.py new file mode 100644 index 0000000..29866bc --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-google.cloud.storage.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import copy_metadata + +datas = copy_metadata('google-cloud-storage') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-google.cloud.translate.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-google.cloud.translate.py new file mode 100644 index 0000000..465b8e9 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-google.cloud.translate.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import copy_metadata + +datas = copy_metadata('google-cloud-translate') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-googleapiclient.model.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-googleapiclient.model.py new file mode 100644 index 0000000..d1a2293 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-googleapiclient.model.py @@ -0,0 +1,20 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import copy_metadata +from PyInstaller.utils.hooks import collect_data_files + +# googleapiclient.model queries the library version via +# pkg_resources.get_distribution("google-api-python-client").version, +# so we need to collect that package's metadata +datas = copy_metadata('google_api_python_client') +datas += collect_data_files('googleapiclient.discovery_cache', excludes=['*.txt', '**/__pycache__']) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-grapheme.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-grapheme.py new file mode 100644 index 0000000..fbe2a4b --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-grapheme.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('grapheme') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-graphql_query.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-graphql_query.py new file mode 100644 index 0000000..f5a0f80 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-graphql_query.py @@ -0,0 +1,18 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2005-2023, PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +#----------------------------------------------------------------------------- +""" +PyInstaller hook file for graphql_query. Tested with version 1.0.3. +""" + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('graphql_query') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-great_expectations.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-great_expectations.py new file mode 100644 index 0000000..a19b7c4 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-great_expectations.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2022 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('great_expectations') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-gribapi.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-gribapi.py new file mode 100644 index 0000000..45d3f0a --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-gribapi.py @@ -0,0 +1,83 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +import os +import pathlib + +from PyInstaller import isolated +from PyInstaller.utils.hooks import collect_data_files, logger + +# Collect the headers (eccodes.h, gribapi.h) that are bundled with the package. +datas = collect_data_files('gribapi') + +# Collect the eccodes shared library. Starting with eccodes 2.37.0, binary wheels with bundled shared library are +# provided for linux and macOS. + + +# NOTE: custom isolated function is used here instead of `get_module_attribute('gribapi.bindings', 'library_path')` +# hook utility function because with eccodes 2.37.0, `eccodes` needs to be imported before `gribapi` to avoid circular +# imports... Also, this way, we can obtain the root directory of eccodes package at the same time. +@isolated.decorate +def get_eccodes_library_path(): + import eccodes + import gribapi.bindings + + return ( + # Path to eccodes shared library used by the gribapi bindings. + str(gribapi.bindings.library_path), + # Path to eccodes package (implicitly assumed to be next to the gribapi package, since they are part of the + # same eccodes dist). + str(eccodes.__path__[0]), + ) + + +binaries = [] + +try: + library_path, package_path = get_eccodes_library_path() +except Exception: + logger.warning("hook-gribapi: failed to query gribapi.bindings.library_path!", exc_info=True) + library_path = None + +if library_path: + if not os.path.isabs(library_path): + from PyInstaller.depend.utils import _resolveCtypesImports + resolved_binary = _resolveCtypesImports([os.path.basename(library_path)]) + if resolved_binary: + library_path = resolved_binary[0][1] + else: + logger.warning("hook-gribapi: failed to resolve shared library name %r!", library_path) + library_path = None +else: + logger.warning("hook-gribapi: could not determine path to eccodes shared library!") + +if library_path: + # If we are collecting eccodes shared library that is bundled with eccodes >= 2.37.0 binary wheel, attempt to + # preserve its parent directory layout. This ensures that the library is found at run-time, but implicitly requires + # PyInstaller 6.x, whose binary dependency analysis (that might also pick up this shared library) also preserves the + # parent directory layout of discovered shared libraries. With PyInstaller 5.x, this will result in duplication + # because binary dependency analysis collects into top-level application directory, but that copy will not be + # discovered at run-time, so duplication is unavoidable. + library_parent_path = pathlib.PurePath(library_path).parent + package_parent_path = pathlib.PurePath(package_path).parent + + if package_parent_path in library_parent_path.parents: + # Should end up being `eccodes.libs` on Linux, and `eccodes/.dylib` on macOS). + dest_dir = str(library_parent_path.relative_to(package_parent_path)) + else: + # External copy; collect into top-level application directory. + dest_dir = '.' + + logger.info( + "hook-gribapi: collecting eccodes shared library %r to destination directory %r", library_path, dest_dir + ) + binaries.append((library_path, dest_dir)) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-grpc.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-grpc.py new file mode 100644 index 0000000..a592be2 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-grpc.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2022 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('grpc') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-gst._gst.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-gst._gst.py new file mode 100644 index 0000000..5b4f109 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-gst._gst.py @@ -0,0 +1,45 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# GStreamer contains a lot of plugins. We need to collect them and bundle +# them wih the exe file. +# We also need to resolve binary dependencies of these GStreamer plugins. + +import glob +import os +from PyInstaller.compat import is_win +from PyInstaller.utils.hooks import exec_statement + +hiddenimports = ['gmodule', 'gobject'] + +statement = """ +import os +import gst +reg = gst.registry_get_default() +plug = reg.find_plugin('coreelements') +path = plug.get_filename() +print(os.path.dirname(path)) +""" + +plugin_path = exec_statement(statement) + +if is_win: + # TODO Verify that on Windows gst plugins really end with .dll. + pattern = os.path.join(plugin_path, '*.dll') +else: + # Even on OSX plugins end with '.so'. + pattern = os.path.join(plugin_path, '*.so') + +binaries = [ + (os.path.join('gst_plugins', os.path.basename(f)), f) + # 'f' contains the absolute path + for f in glob.glob(pattern)] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-gtk.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-gtk.py new file mode 100644 index 0000000..64b3a4b --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-gtk.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +hiddenimports = ['gtkglext', 'gdkgl', 'gdkglext', 'gdk', 'gtk.gdk', 'gtk.gtkgl', + 'gtk.gtkgl._gtkgl', 'gtkgl', 'pangocairo', 'pango', 'atk', + 'gobject', 'gtk.glade', 'cairo', 'gio', + 'gtk.keysyms'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-h3.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-h3.py new file mode 100644 index 0000000..89f112b --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-h3.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import is_module_satisfies, copy_metadata + +# Starting with v4.0.0, h3 determines its version from its metadata. +if is_module_satisfies("h3 >= 4.0.0"): + datas = copy_metadata("h3") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-h5py.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-h5py.py new file mode 100644 index 0000000..e37e62e --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-h5py.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Hook for http://pypi.python.org/pypi/h5py/ +""" + +hiddenimports = ['h5py._proxy', 'h5py.utils', 'h5py.defs', 'h5py.h5ac'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-hdf5plugin.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-hdf5plugin.py new file mode 100644 index 0000000..b3ef44d --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-hdf5plugin.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2022 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for hdf5plugin: https://pypi.org/project/hdf5plugin/ + +from PyInstaller.utils.hooks import collect_dynamic_libs + +datas = collect_dynamic_libs("hdf5plugin") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-hexbytes.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-hexbytes.py new file mode 100644 index 0000000..8e29e8c --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-hexbytes.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import is_module_satisfies, copy_metadata + +# Starting with v1.1.0, `hexbytes` queries its version from metadata. +if is_module_satisfies("hexbytes >= 1.1.0"): + datas = copy_metadata('hexbytes') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-httplib2.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-httplib2.py new file mode 100644 index 0000000..7789c1f --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-httplib2.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# This is needed to bundle cacerts.txt that comes with httplib2 module + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('httplib2') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-humanize.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-humanize.py new file mode 100644 index 0000000..598dac7 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-humanize.py @@ -0,0 +1,23 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +This modest package contains various common humanization utilities, like turning a number into a fuzzy human +readable duration ("3 minutes ago") or into a human readable size or throughput. + +https://pypi.org/project/humanize + +This hook was tested against humanize 3.5.0. +""" + +from PyInstaller.utils.hooks import copy_metadata + +datas = copy_metadata('humanize') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-hydra.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-hydra.py new file mode 100644 index 0000000..0c61977 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-hydra.py @@ -0,0 +1,36 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2022 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.compat import is_py310 +from PyInstaller.utils.hooks import collect_submodules, collect_data_files, is_module_satisfies + +# Collect core plugins. +hiddenimports = collect_submodules('hydra._internal.core_plugins') + +# Hydra's plugin manager (`hydra.core.plugins.Plugins`) uses PEP-302 `find_module` / `load_module`, which has been +# deprecated since python 3.4, and has been removed from PyInstaller's frozen importer in PyInstaller 5.8. For python +# 3.10 and newer, they implemented new codepath that uses `find_spec`, but for earlier python versions, they opted to +# keep using the old codepath. +# +# See: https://github.com/facebookresearch/hydra/pull/2531 +# +# To work around the incompatibility with PyInstaller >= 5.8 when using python < 3.10, force collection of plugins as +# source .py files. This way, they end up handled by python's built-in finder/importer instead of PyInstaller's +# frozen importer. +if not is_py310 and is_module_satisfies("PyInstaller >= 5.8"): + module_collection_mode = { + 'hydra._internal.core_plugins': 'py', + 'hydra_plugins': 'py', + } + +# Collect package's data files, such as default configuration files. +datas = collect_data_files('hydra') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-ijson.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-ijson.py new file mode 100644 index 0000000..60fa40c --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-ijson.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_submodules + +hiddenimports = collect_submodules("ijson.backends") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-imageio.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-imageio.py new file mode 100644 index 0000000..1cf0e6e --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-imageio.py @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for imageio: http://imageio.github.io/ + +from PyInstaller.utils.hooks import collect_data_files, collect_submodules + +datas = collect_data_files('imageio', subdir="resources") + +# imageio plugins are imported lazily since ImageIO version 2.11.0. +# They are very light-weight, so we can safely include all of them. +hiddenimports = collect_submodules('imageio.plugins') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-imageio_ffmpeg.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-imageio_ffmpeg.py new file mode 100644 index 0000000..4fd469b --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-imageio_ffmpeg.py @@ -0,0 +1,22 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for imageio: http://imageio.github.io/ + +from PyInstaller.utils.hooks import collect_data_files, is_module_satisfies + +datas = collect_data_files('imageio_ffmpeg', subdir="binaries") + +# Starting with imageio_ffmpeg 0.5.0, `imageio_ffmpeg.binaries` is a package accessed via `importlib.resources`. Since +# it is not directly imported anywhere, we need to add it to hidden imports. +if is_module_satisfies('imageio_ffmpeg >= 0.5.0'): + hiddenimports = ['imageio_ffmpeg.binaries'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-iminuit.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-iminuit.py new file mode 100644 index 0000000..4cbb6cb --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-iminuit.py @@ -0,0 +1,25 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# add hooks for iminuit: https://github.com/scikit-hep/iminuit + +# iminuit imports subpackages through a cython module which aren't +# found by default + +from PyInstaller.utils.hooks import collect_submodules + +hiddenimports = [] + +# the iminuit package contains tests which aren't needed when distributing +for mod in collect_submodules('iminuit'): + if not mod.startswith('iminuit.tests'): + hiddenimports.append(mod) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-iso639.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-iso639.py new file mode 100644 index 0000000..974e73e --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-iso639.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +# Collect data files for iso639 +datas = collect_data_files("iso639") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-itk.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-itk.py new file mode 100644 index 0000000..54bf624 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-itk.py @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_submodules + +hiddenimports = collect_submodules("itk.Configuration") + +# `itk` requires `itk/Configuration` directory to exist on filesystem; collect source .py files from `itk.Configuration` +# as a work-around that ensures the existence of this directory. +module_collection_mode = { + "itk.Configuration": "pyz+py", +} diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jaraco.text.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jaraco.text.py new file mode 100644 index 0000000..7126079 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jaraco.text.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for jaraco: https://pypi.python.org/pypi/jaraco.text/3.2.0 + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('jaraco.text') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jedi.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jedi.py new file mode 100644 index 0000000..9601dbe --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jedi.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for Jedi, a static analysis tool https://pypi.org/project/jedi/ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('jedi') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jieba.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jieba.py new file mode 100644 index 0000000..cc53edf --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jieba.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('jieba') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jinja2.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jinja2.py new file mode 100644 index 0000000..f017894 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jinja2.py @@ -0,0 +1,13 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +hiddenimports = ['jinja2.ext'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jinxed.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jinxed.py new file mode 100644 index 0000000..28e7f36 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jinxed.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +hiddenimports = [ + 'jinxed.terminfo.ansicon', 'jinxed.terminfo.vtwin10' +] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jira.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jira.py new file mode 100644 index 0000000..dd64b1e --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jira.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Hook for https://pypi.python.org/pypi/jira/ +""" + +from PyInstaller.utils.hooks import copy_metadata, collect_submodules + +datas = copy_metadata('jira') +hiddenimports = collect_submodules('jira') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jsonpath_rw_ext.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jsonpath_rw_ext.py new file mode 100644 index 0000000..1914af4 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jsonpath_rw_ext.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import copy_metadata + +datas = copy_metadata('jsonpath_rw_ext') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jsonrpcserver.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jsonrpcserver.py new file mode 100644 index 0000000..71947a1 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jsonrpcserver.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# This is needed to bundle request-schema.json file needed by +# jsonrpcserver package + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('jsonrpcserver') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jsonschema.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jsonschema.py new file mode 100644 index 0000000..ca1289c --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jsonschema.py @@ -0,0 +1,20 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# This is needed to bundle draft3.json and draft4.json files that come with jsonschema module. +# NOTE: with jsonschema >= 4.18.0, the specification files are part of jsonschema_specifications package, and are +# handled by the corresponding hook-jsonschema. + +from PyInstaller.utils.hooks import collect_data_files, copy_metadata + +datas = collect_data_files('jsonschema') +datas += copy_metadata('jsonschema') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jsonschema_specifications.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jsonschema_specifications.py new file mode 100644 index 0000000..bbbdafb --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jsonschema_specifications.py @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files +datas = collect_data_files('jsonschema_specifications') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jupyterlab.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jupyterlab.py new file mode 100644 index 0000000..ba77523 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-jupyterlab.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('jupyterlab') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-kaleido.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-kaleido.py new file mode 100644 index 0000000..e21c5eb --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-kaleido.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('kaleido') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-khmernltk.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-khmernltk.py new file mode 100644 index 0000000..021d23c --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-khmernltk.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('khmernltk') +hiddenimports = ['sklearn_crfsuite'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-kinterbasdb.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-kinterbasdb.py new file mode 100644 index 0000000..dff9f4b --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-kinterbasdb.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# kinterbasdb +hiddenimports = ['k_exceptions', 'services', 'typeconv_naked', + 'typeconv_backcompat', 'typeconv_23plus', + 'typeconv_datetime_stdlib', 'typeconv_datetime_mx', + 'typeconv_datetime_naked', 'typeconv_fixed_fixedpoint', + 'typeconv_fixed_stdlib', 'typeconv_text_unicode', + 'typeconv_util_isinstance', '_kinterbasdb', '_kiservices'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-langchain.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-langchain.py new file mode 100644 index 0000000..93cc206 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-langchain.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('langchain') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-langcodes.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-langcodes.py new file mode 100644 index 0000000..65c4723 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-langcodes.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('langcodes') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-langdetect.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-langdetect.py new file mode 100644 index 0000000..2bfe9ac --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-langdetect.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("langdetect") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-laonlp.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-laonlp.py new file mode 100644 index 0000000..2c8b577 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-laonlp.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('laonlp') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-lark.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-lark.py new file mode 100644 index 0000000..653f810 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-lark.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2022 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("lark") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-ldfparser.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-ldfparser.py new file mode 100644 index 0000000..42e9033 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-ldfparser.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2022 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +#----------------------------------------------------------------------------- + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('ldfparser') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-lensfunpy.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-lensfunpy.py new file mode 100644 index 0000000..a44d5e4 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-lensfunpy.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files +# bundle xml DB files, skip other files (like DLL files on Windows) +datas = list(filter(lambda p: p[0].endswith('.xml'), collect_data_files('lensfunpy'))) +hiddenimports = ['numpy', 'enum'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-libaudioverse.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-libaudioverse.py new file mode 100644 index 0000000..9d28d60 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-libaudioverse.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Libaudioverse: https://github.com/libaudioverse/libaudioverse +""" + +from PyInstaller.utils.hooks import collect_dynamic_libs + +binaries = collect_dynamic_libs('libaudioverse') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-librosa.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-librosa.py new file mode 100644 index 0000000..2767038 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-librosa.py @@ -0,0 +1,25 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files, collect_submodules + +# Collect all data files from the package. These include: +# - package's and subpackages' .pyi files for `lazy_loader` +# - example data in librosa/util, required by `librosa.util.files` +# - librosa/core/intervals.msgpack, required by `librosa.core.intervals` +# +# We explicitly exclude `__pycache__` because it might contain .nbi and .nbc files from `numba` cache, which are not +# re-used by `numba` codepaths in the frozen application and are instead re-compiled in user-global cache directory. +datas = collect_data_files("librosa", excludes=['**/__pycache__']) + +# And because modules are lazily loaded, we need to collect them all. +hiddenimports = collect_submodules("librosa") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-lightgbm.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-lightgbm.py new file mode 100644 index 0000000..3718cc4 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-lightgbm.py @@ -0,0 +1,27 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +# +# A fast, distributed, high performance gradient boosting +# (GBT, GBDT, GBRT, GBM or MART) framework based on decision +# tree algorithms, used for ranking, classification and +# many other machine learning tasks. +# +# https://github.com/microsoft/LightGBM +# +# Tested with: +# Tested on Windows 10 & macOS 10.14 with Python 3.7.5 + +from PyInstaller.utils.hooks import collect_dynamic_libs + +binaries = collect_dynamic_libs('lightgbm') +binaries += collect_dynamic_libs('sklearn') +binaries += collect_dynamic_libs('scipy') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-lightning.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-lightning.py new file mode 100644 index 0000000..840bdb9 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-lightning.py @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +# Collect version.info (which is read during package import at run-time). Avoid collecting data from `lightning.app`, +# which likely does not work with PyInstaller without additional tricks (if we need to collect that data, it should +# be done in separate `lightning.app` hook). +datas = collect_data_files( + 'lightning', + includes=['version.info'], +) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-limits.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-limits.py new file mode 100644 index 0000000..3bd9810 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-limits.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("limits") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-linear_operator.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-linear_operator.py new file mode 100644 index 0000000..73c8621 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-linear_operator.py @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# --------------------------------------------------- + +# Collect source .py files for JIT/torchscript. Requires PyInstaller >= 5.3, no-op in older versions. +module_collection_mode = 'pyz+py' diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-lingua.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-lingua.py new file mode 100644 index 0000000..2d6fbb5 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-lingua.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('lingua') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-litestar.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-litestar.py new file mode 100644 index 0000000..ca35e5a --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-litestar.py @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_submodules +hiddenimports = collect_submodules('litestar.logging') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-llvmlite.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-llvmlite.py new file mode 100644 index 0000000..108f521 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-llvmlite.py @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +# +# A lightweight LLVM python binding for writing JIT compilers +# https://github.com/numba/llvmlite +# +# Tested with: +# llvmlite 0.11 (Anaconda 4.1.1, Windows), llvmlite 0.13 (Linux) + +from PyInstaller.utils.hooks import collect_dynamic_libs + +binaries = collect_dynamic_libs("llvmlite") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-logilab.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-logilab.py new file mode 100644 index 0000000..074fc40 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-logilab.py @@ -0,0 +1,26 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +# +# *************************************************** +# hook-logilab.py - PyInstaller hook file for logilab +# *************************************************** +# The following was written about logilab, version 1.1.0, based on executing +# ``pip show logilab-common``. +# +# In logilab.common, line 33:: +# +# __version__ = pkg_resources.get_distribution('logilab-common').version +# +# Therefore, we need metadata for logilab. +from PyInstaller.utils.hooks import copy_metadata + +datas = copy_metadata('logilab-common') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-lxml.etree.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-lxml.etree.py new file mode 100644 index 0000000..b53e89e --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-lxml.etree.py @@ -0,0 +1,13 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +hiddenimports = ['lxml._elementpath', 'gzip', 'contextlib'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-lxml.isoschematron.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-lxml.isoschematron.py new file mode 100644 index 0000000..8ed7659 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-lxml.isoschematron.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files +import os + +# Auxiliary data for isoschematron +datas = collect_data_files('lxml', subdir=os.path.join('isoschematron', 'resources')) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-lxml.objectify.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-lxml.objectify.py new file mode 100644 index 0000000..e8cb2bf --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-lxml.objectify.py @@ -0,0 +1,13 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +hiddenimports = ['lxml.etree'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-lxml.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-lxml.py new file mode 100644 index 0000000..4a70af6 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-lxml.py @@ -0,0 +1,20 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +# +# lxml is not fully embedded when using standard hiddenimports +# see https://github.com/pyinstaller/pyinstaller/issues/5306 +# +# Tested with lxml 4.6.1 + +from PyInstaller.utils.hooks import collect_submodules + +hiddenimports = collect_submodules('lxml') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-lz4.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-lz4.py new file mode 100644 index 0000000..1b01cd4 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-lz4.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +# hook for https://github.com/python-lz4/python-lz4 + +from PyInstaller.utils.hooks import copy_metadata + +datas = copy_metadata('lz4') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-magic.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-magic.py new file mode 100644 index 0000000..e5efe63 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-magic.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# hook for https://pypi.org/project/python-magic-bin + +from PyInstaller.utils.hooks import collect_data_files, collect_dynamic_libs + +datas = collect_data_files('magic') +binaries = collect_dynamic_libs('magic') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-mako.codegen.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-mako.codegen.py new file mode 100644 index 0000000..dcaefa3 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-mako.codegen.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +codegen generates Python code that is then executed through exec(). +This Python code imports the following modules. +""" + +hiddenimports = ['mako.cache', 'mako.runtime', 'mako.filters'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-mariadb.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-mariadb.py new file mode 100644 index 0000000..6466ba1 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-mariadb.py @@ -0,0 +1,25 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import is_module_satisfies, collect_submodules + +# The MariaDB uses a .pyd file that imports ``decimal`` module within its +# module initialization function. On recent python versions (> 3.8), the decimal +# module seems to be picked up nevertheless (presumably due to import in some +# other module), but it is better not to rely on that, and ensure it is always +# collected as a hidden import. +hiddenimports = ['decimal'] + +# mariadb >= 1.1.0 requires several hidden imports from mariadb.constants. +# Collect them all, just to be on the safe side... +if is_module_satisfies("mariadb >= 1.1.0"): + hiddenimports += collect_submodules("mariadb.constants") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-markdown.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-markdown.py new file mode 100644 index 0000000..9918feb --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-markdown.py @@ -0,0 +1,28 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import ( + collect_submodules, + copy_metadata, + is_module_satisfies, +) + +hiddenimports = collect_submodules('markdown.extensions') + +# Markdown 3.3 introduced markdown.htmlparser submodule with hidden +# dependency on html.parser +if is_module_satisfies("markdown >= 3.3"): + hiddenimports += ['html.parser'] + +# Extensions can be referenced by short names, e.g. "extra", through a mechanism +# using entry-points. Thus we need to collect the package metadata as well. +datas = copy_metadata("markdown") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-mecab.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-mecab.py new file mode 100644 index 0000000..2b30f86 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-mecab.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('mecab') +datas += collect_data_files('mecab_ko_dic') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-metpy.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-metpy.py new file mode 100644 index 0000000..be84bb9 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-metpy.py @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import copy_metadata, collect_data_files + +# MetPy requires metadata, because it queries its version via +# pkg_resources.get_distribution(__package__).version or, in newer +# versions, importlib.metadata.version(__package__) +datas = copy_metadata('metpy') + +# Collect data files +datas += collect_data_files('metpy') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-migrate.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-migrate.py new file mode 100644 index 0000000..b1ec0c9 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-migrate.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +# hook for https://github.com/openstack/sqlalchemy-migrate +# Since v0.12.0 importing migrate requires metadata to resolve __version__ +# attribute + +from PyInstaller.utils.hooks import copy_metadata, is_module_satisfies + +if is_module_satisfies('sqlalchemy-migrate >= 0.12.0'): + datas = copy_metadata('sqlalchemy-migrate') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-mimesis.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-mimesis.py new file mode 100644 index 0000000..5accde1 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-mimesis.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2022 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# The bundled 'data/' directory containing locale .json files needs to be collected (as data file). + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('mimesis') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-minecraft_launcher_lib.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-minecraft_launcher_lib.py new file mode 100644 index 0000000..e06a0a9 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-minecraft_launcher_lib.py @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("minecraft_launcher_lib") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-mistune.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-mistune.py new file mode 100644 index 0000000..ea9a804 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-mistune.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for nanite: https://pypi.python.org/pypi/nanite + +from PyInstaller.utils.hooks import is_module_satisfies, collect_submodules + +# As of version 3.0.0, mistune loads its plugins indirectly (but does so during package import nevertheless). +if is_module_satisfies("mistune >= 3.0.0"): + hiddenimports = collect_submodules("mistune.plugins") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-mnemonic.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-mnemonic.py new file mode 100644 index 0000000..68c56e5 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-mnemonic.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('mnemonic') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-monai.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-monai.py new file mode 100644 index 0000000..82676db --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-monai.py @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Collect source .py files for JIT/torchscript. Requires PyInstaller >= 5.3, no-op in older versions. +module_collection_mode = "pyz+py" diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-moviepy.audio.fx.all.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-moviepy.audio.fx.all.py new file mode 100644 index 0000000..4bb9c78 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-moviepy.audio.fx.all.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# `moviepy.audio.fx.all` programmatically imports and forwards all submodules of `moviepy.audio.fx`, so we need to +# collect those as hidden imports. +from PyInstaller.utils.hooks import collect_submodules + +hiddenimports = collect_submodules('moviepy.audio.fx') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-moviepy.video.fx.all.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-moviepy.video.fx.all.py new file mode 100644 index 0000000..cc0b924 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-moviepy.video.fx.all.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# `moviepy.video.fx.all` programmatically imports and forwards all submodules of `moviepy.video.fx`, so we need to +# collect those as hidden imports. +from PyInstaller.utils.hooks import collect_submodules + +hiddenimports = collect_submodules('moviepy.video.fx') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-mpl_toolkits.basemap.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-mpl_toolkits.basemap.py new file mode 100644 index 0000000..839b072 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-mpl_toolkits.basemap.py @@ -0,0 +1,36 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files +from PyInstaller.compat import is_win, base_prefix + +import os + +# mpl_toolkits.basemap (tested with v.1.0.7) is shipped with auxiliary data, +# usually stored in mpl_toolkits\basemap\data and used to plot maps +datas = collect_data_files('mpl_toolkits.basemap', subdir='data') + +# check if the data has been effectively found +if len(datas) == 0: + + # - conda-specific + + if is_win: + tgt_basemap_data = os.path.join('Library', 'share', 'basemap') + src_basemap_data = os.path.join(base_prefix, 'Library', 'share', 'basemap') + + else: # both linux and darwin + tgt_basemap_data = os.path.join('share', 'basemap') + src_basemap_data = os.path.join(base_prefix, 'share', 'basemap') + + if os.path.exists(src_basemap_data): + datas.append((src_basemap_data, tgt_basemap_data)) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-msoffcrypto.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-msoffcrypto.py new file mode 100644 index 0000000..74f75e0 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-msoffcrypto.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +msoffcrypto contains hidden metadata as of v4.12.0 +""" + +from PyInstaller.utils.hooks import copy_metadata + +datas = copy_metadata('msoffcrypto-tool') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nacl.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nacl.py new file mode 100644 index 0000000..9694133 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nacl.py @@ -0,0 +1,30 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Tested with PyNaCl 0.3.0 on Mac OS X. + +import os.path +import glob + +from PyInstaller.compat import EXTENSION_SUFFIXES +from PyInstaller.utils.hooks import collect_data_files, get_module_file_attribute + +datas = collect_data_files('nacl') + +# Include the cffi extensions as binaries in a subfolder named like the package. +binaries = [] +nacl_dir = os.path.dirname(get_module_file_attribute('nacl')) +for ext in EXTENSION_SUFFIXES: + ffimods = glob.glob(os.path.join(nacl_dir, '_lib', '*_cffi_*%s*' % ext)) + dest_dir = os.path.join('nacl', '_lib') + for f in ffimods: + binaries.append((f, dest_dir)) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-names.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-names.py new file mode 100644 index 0000000..ff33b59 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-names.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# names: generate random names +# Module PyPI Homepage: https://pypi.python.org/pypi/names/0.3.0 + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('names') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nanite.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nanite.py new file mode 100644 index 0000000..9d37ecc --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nanite.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for nanite: https://pypi.python.org/pypi/nanite + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('nanite') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nbconvert.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nbconvert.py new file mode 100644 index 0000000..fefb5ae --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nbconvert.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files, copy_metadata + +datas = collect_data_files('nbconvert') + +# nbconvert uses entrypoints to read nbconvert.exporters from metadata file entry_points.txt. +datas += copy_metadata('nbconvert') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nbdime.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nbdime.py new file mode 100644 index 0000000..38452ca --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nbdime.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('nbdime') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nbformat.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nbformat.py new file mode 100644 index 0000000..d193864 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nbformat.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('nbformat') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nbt.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nbt.py new file mode 100644 index 0000000..676ee32 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nbt.py @@ -0,0 +1,12 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +hiddenimports = ["nbt.nbt", "nbt.world", "nbt.region", "nbt.chunk"] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-ncclient.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-ncclient.py new file mode 100644 index 0000000..d41c061 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-ncclient.py @@ -0,0 +1,23 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Hook for ncclient. ncclient is a Python library that facilitates client-side +scripting and application development around the NETCONF protocol. +https://pypi.python.org/pypi/ncclient + +This hook was tested with ncclient 0.4.3. +""" +from PyInstaller.utils.hooks import collect_submodules + +# Modules 'ncclient.devices.*' are dynamically loaded and PyInstaller +# is not able to find them. +hiddenimports = collect_submodules('ncclient.devices') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-netCDF4.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-netCDF4.py new file mode 100644 index 0000000..259d71c --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-netCDF4.py @@ -0,0 +1,37 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.compat import is_win +from PyInstaller.utils.hooks import is_module_satisfies + +# netCDF4 (tested with v.1.1.9) has some hidden imports +hiddenimports = ['netCDF4.utils'] + +# Around netCDF4 1.4.0, netcdftime changed name to cftime +if is_module_satisfies("netCDF4 < 1.4.0"): + hiddenimports += ['netcdftime'] +else: + hiddenimports += ['cftime'] + +# Starting with netCDF 1.6.4, certifi is a hidden import made in +# netCDF4/_netCDF4.pyx. +if is_module_satisfies("netCDF4 >= 1.6.4"): + hiddenimports += ['certifi'] + +# netCDF 1.6.2 is the first version that uses `delvewheel` for bundling DLLs in Windows PyPI wheels. While contemporary +# PyInstaller versions automatically pick up DLLs from external `netCDF4.libs` directory, this does not work on Anaconda +# python 3.8 and 3.9 due to defunct `os.add_dll_directory`, which forces `delvewheel` to use the old load-order file +# approach. So we need to explicitly ensure that load-order file as well as DLLs are collected. +if is_win and is_module_satisfies("netCDF4 >= 1.6.2"): + if is_module_satisfies("PyInstaller >= 5.6"): + from PyInstaller.utils.hooks import collect_delvewheel_libs_directory + datas, binaries = collect_delvewheel_libs_directory("netCDF4") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nltk.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nltk.py new file mode 100644 index 0000000..fa1cf2b --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nltk.py @@ -0,0 +1,27 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# hook for nltk +import nltk +import os +from PyInstaller.utils.hooks import collect_data_files + +# add datas for nltk +datas = collect_data_files('nltk', False) + +# loop through the data directories and add them +for p in nltk.data.path: + if os.path.exists(p): + datas.append((p, "nltk_data")) + +# nltk.chunk.named_entity should be included +hiddenimports = ["nltk.chunk.named_entity"] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nnpy.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nnpy.py new file mode 100644 index 0000000..e4d3951 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nnpy.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Hook for https://pypi.org/project/nnpy/ +""" + +hiddenimports = ['_cffi_backend'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-notebook.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-notebook.py new file mode 100644 index 0000000..ea91dec --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-notebook.py @@ -0,0 +1,27 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +import os +from PyInstaller.utils.hooks import collect_data_files, collect_submodules +from jupyter_core.paths import jupyter_config_path, jupyter_path + +# collect modules for handlers +hiddenimports = collect_submodules('notebook', filter=lambda name: name.endswith('.handles')) +hiddenimports.append('notebook.services.shutdown') + +datas = collect_data_files('notebook') + +# Collect share and etc folder for pre-installed extensions +datas += [(path, 'share/jupyter') + for path in jupyter_path() if os.path.exists(path)] +datas += [(path, 'etc/jupyter') + for path in jupyter_config_path() if os.path.exists(path)] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-numba.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-numba.py new file mode 100644 index 0000000..8196216 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-numba.py @@ -0,0 +1,27 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +# +# NumPy aware dynamic Python compiler using LLVM +# https://github.com/numba/numba +# +# Tested with: +# numba 0.26 (Anaconda 4.1.1, Windows), numba 0.28 (Linux) + +from PyInstaller.utils.hooks import is_module_satisfies + +excludedimports = ["IPython", "scipy"] +hiddenimports = ["llvmlite"] + +# numba 0.59.0 updated its vendored version of cloudpickle to 3.0.0; this version keeps `cloudpickle_fast` module +# around for backward compatibility with existing pickled data, but does not import it directly anymore. +if is_module_satisfies("numba >= 0.59.0"): + hiddenimports += ["numba.cloudpickle.cloudpickle_fast"] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-numbers_parser.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-numbers_parser.py new file mode 100644 index 0000000..d6fd535 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-numbers_parser.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +# Ensure that `numbers_parser/data/empty.numbers` is collected. +datas = collect_data_files('numbers_parser') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-numcodecs.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-numcodecs.py new file mode 100644 index 0000000..ae827e2 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-numcodecs.py @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2022 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# compat_ext is only imported from pyx files, so it is missed +hiddenimports = ['numcodecs.compat_ext'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cublas.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cublas.py new file mode 100644 index 0000000..3404162 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cublas.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from _pyinstaller_hooks_contrib.utils.nvidia_cuda import ( + collect_nvidia_cuda_binaries, + create_symlink_suppression_patterns, +) + +binaries = collect_nvidia_cuda_binaries(__file__) +bindepend_symlink_suppression = create_symlink_suppression_patterns(__file__) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cuda_cupti.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cuda_cupti.py new file mode 100644 index 0000000..3404162 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cuda_cupti.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from _pyinstaller_hooks_contrib.utils.nvidia_cuda import ( + collect_nvidia_cuda_binaries, + create_symlink_suppression_patterns, +) + +binaries = collect_nvidia_cuda_binaries(__file__) +bindepend_symlink_suppression = create_symlink_suppression_patterns(__file__) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cuda_nvcc.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cuda_nvcc.py new file mode 100644 index 0000000..13172ae --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cuda_nvcc.py @@ -0,0 +1,30 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files +from _pyinstaller_hooks_contrib.utils.nvidia_cuda import ( + collect_nvidia_cuda_binaries, + create_symlink_suppression_patterns, +) + +# Ensures that versioned .so files are collected +binaries = collect_nvidia_cuda_binaries(__file__) + +# Prevent binary dependency analysis from creating symlinks to top-level application directory for shared libraries +# from this package. Requires PyInstaller >= 6.11.0; no-op in earlier versions. +bindepend_symlink_suppression = create_symlink_suppression_patterns(__file__) + +# Collect additional resources: +# - ptxas executable (which strictly speaking, should be collected as a binary) +# - nvvm/libdevice/libdevice.10.bc file +# - C headers; assuming ptxas requires them - if that is not the case, we could filter them out. +datas = collect_data_files('nvidia.cuda_nvcc') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cuda_nvrtc.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cuda_nvrtc.py new file mode 100644 index 0000000..3404162 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cuda_nvrtc.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from _pyinstaller_hooks_contrib.utils.nvidia_cuda import ( + collect_nvidia_cuda_binaries, + create_symlink_suppression_patterns, +) + +binaries = collect_nvidia_cuda_binaries(__file__) +bindepend_symlink_suppression = create_symlink_suppression_patterns(__file__) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cuda_runtime.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cuda_runtime.py new file mode 100644 index 0000000..3404162 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cuda_runtime.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from _pyinstaller_hooks_contrib.utils.nvidia_cuda import ( + collect_nvidia_cuda_binaries, + create_symlink_suppression_patterns, +) + +binaries = collect_nvidia_cuda_binaries(__file__) +bindepend_symlink_suppression = create_symlink_suppression_patterns(__file__) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cudnn.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cudnn.py new file mode 100644 index 0000000..3404162 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cudnn.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from _pyinstaller_hooks_contrib.utils.nvidia_cuda import ( + collect_nvidia_cuda_binaries, + create_symlink_suppression_patterns, +) + +binaries = collect_nvidia_cuda_binaries(__file__) +bindepend_symlink_suppression = create_symlink_suppression_patterns(__file__) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cufft.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cufft.py new file mode 100644 index 0000000..3404162 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cufft.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from _pyinstaller_hooks_contrib.utils.nvidia_cuda import ( + collect_nvidia_cuda_binaries, + create_symlink_suppression_patterns, +) + +binaries = collect_nvidia_cuda_binaries(__file__) +bindepend_symlink_suppression = create_symlink_suppression_patterns(__file__) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.curand.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.curand.py new file mode 100644 index 0000000..3404162 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.curand.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from _pyinstaller_hooks_contrib.utils.nvidia_cuda import ( + collect_nvidia_cuda_binaries, + create_symlink_suppression_patterns, +) + +binaries = collect_nvidia_cuda_binaries(__file__) +bindepend_symlink_suppression = create_symlink_suppression_patterns(__file__) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cusolver.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cusolver.py new file mode 100644 index 0000000..3404162 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cusolver.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from _pyinstaller_hooks_contrib.utils.nvidia_cuda import ( + collect_nvidia_cuda_binaries, + create_symlink_suppression_patterns, +) + +binaries = collect_nvidia_cuda_binaries(__file__) +bindepend_symlink_suppression = create_symlink_suppression_patterns(__file__) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cusparse.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cusparse.py new file mode 100644 index 0000000..3404162 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cusparse.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from _pyinstaller_hooks_contrib.utils.nvidia_cuda import ( + collect_nvidia_cuda_binaries, + create_symlink_suppression_patterns, +) + +binaries = collect_nvidia_cuda_binaries(__file__) +bindepend_symlink_suppression = create_symlink_suppression_patterns(__file__) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.nccl.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.nccl.py new file mode 100644 index 0000000..3404162 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.nccl.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from _pyinstaller_hooks_contrib.utils.nvidia_cuda import ( + collect_nvidia_cuda_binaries, + create_symlink_suppression_patterns, +) + +binaries = collect_nvidia_cuda_binaries(__file__) +bindepend_symlink_suppression = create_symlink_suppression_patterns(__file__) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.nvjitlink.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.nvjitlink.py new file mode 100644 index 0000000..3404162 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.nvjitlink.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from _pyinstaller_hooks_contrib.utils.nvidia_cuda import ( + collect_nvidia_cuda_binaries, + create_symlink_suppression_patterns, +) + +binaries = collect_nvidia_cuda_binaries(__file__) +bindepend_symlink_suppression = create_symlink_suppression_patterns(__file__) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.nvtx.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.nvtx.py new file mode 100644 index 0000000..3404162 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.nvtx.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from _pyinstaller_hooks_contrib.utils.nvidia_cuda import ( + collect_nvidia_cuda_binaries, + create_symlink_suppression_patterns, +) + +binaries = collect_nvidia_cuda_binaries(__file__) +bindepend_symlink_suppression = create_symlink_suppression_patterns(__file__) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-office365.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-office365.py new file mode 100644 index 0000000..37a007f --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-office365.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Office365-REST-Python-Client contains xml templates that are needed by some methods +This hook ensures that all of the data used by the package is bundled +""" + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("office365") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-onnxruntime.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-onnxruntime.py new file mode 100644 index 0000000..9c7e807 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-onnxruntime.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_dynamic_libs + +# Collect provider plugins from onnxruntime/capi. +binaries = collect_dynamic_libs("onnxruntime") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-opencc.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-opencc.py new file mode 100644 index 0000000..9204053 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-opencc.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('opencc') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-openpyxl.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-openpyxl.py new file mode 100644 index 0000000..299a1be --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-openpyxl.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for the openpyxl module: https://pypi.python.org/pypi/openpyxl +# Tested with openpyxl 2.3.4, Python 2.7, Windows + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('openpyxl') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-opentelemetry.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-opentelemetry.py new file mode 100644 index 0000000..d8e3e9e --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-opentelemetry.py @@ -0,0 +1,41 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_entry_point + +# All known `opentelementry_` entry-point groups +ENTRY_POINT_GROUPS = ( + 'opentelemetry_context', + 'opentelemetry_environment_variables', + 'opentelemetry_id_generator', + 'opentelemetry_logger_provider', + 'opentelemetry_logs_exporter', + 'opentelemetry_meter_provider', + 'opentelemetry_metrics_exporter', + 'opentelemetry_propagator', + 'opentelemetry_resource_detector', + 'opentelemetry_tracer_provider', + 'opentelemetry_traces_exporter', + 'opentelemetry_traces_sampler', +) + +# Collect entry points +datas = set() +hiddenimports = set() + +for entry_point_group in ENTRY_POINT_GROUPS: + ep_datas, ep_hiddenimports = collect_entry_point(entry_point_group) + datas.update(ep_datas) + hiddenimports.update(ep_hiddenimports) + +datas = list(datas) +hiddenimports = list(hiddenimports) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-orjson.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-orjson.py new file mode 100644 index 0000000..04092dc --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-orjson.py @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2022 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Forced import of these modules happens on first orjson import +# and orjson is a compiled extension module. +hiddenimports = [ + 'uuid', + 'zoneinfo', + 'enum', + 'json', + 'dataclasses', +] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-osgeo.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-osgeo.py new file mode 100644 index 0000000..dbc0b4a --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-osgeo.py @@ -0,0 +1,81 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files +from PyInstaller.compat import is_win, is_darwin + +import os +import sys + +# The osgeo libraries require auxiliary data and may have hidden dependencies. +# There are several possible configurations on how these libraries can be +# deployed. +# This hook evaluates the cases when: +# - the `data` folder is present "in-source" (sharing the same namespace folder +# as the code libraries) +# - the `data` folder is present "out-source" (for instance, on Anaconda for +# Windows, in PYTHONHOME/Library/data) +# In this latter case, the hook also checks for the presence of `proj` library +# (e.g., on Windows in PYTHONHOME) for being added to the bundle. +# +# This hook has been tested with gdal (v.1.11.2 and 1.11.3) on: +# - Win 7 and 10 64bit +# - Ubuntu 15.04 64bit +# - Mac OS X Yosemite 10.10 +# +# TODO: Fix for gdal>=2.0.0, <2.0.3: 'NameError: global name 'help' is not defined' + +# flag used to identify an Anaconda environment +is_conda = False + +# Auxiliary data: +# +# - general case (data in 'osgeo/data'): +datas = collect_data_files('osgeo', subdir='data') + +# check if the data has been effectively found in 'osgeo/data/gdal' +if len(datas) == 0: + + if hasattr(sys, 'real_prefix'): # check if in a virtual environment + root_path = sys.real_prefix + else: + root_path = sys.prefix + + # - conda-specific + if is_win: + tgt_gdal_data = os.path.join('Library', 'share', 'gdal') + src_gdal_data = os.path.join(root_path, 'Library', 'share', 'gdal') + if not os.path.exists(src_gdal_data): + tgt_gdal_data = os.path.join('Library', 'data') + src_gdal_data = os.path.join(root_path, 'Library', 'data') + + else: # both linux and darwin + tgt_gdal_data = os.path.join('share', 'gdal') + src_gdal_data = os.path.join(root_path, 'share', 'gdal') + + if os.path.exists(src_gdal_data): + is_conda = True + datas.append((src_gdal_data, tgt_gdal_data)) + # a real-time hook takes case to define the path for `GDAL_DATA` + +# Hidden dependencies +if is_conda: + # if `proj.4` is present, it provides additional functionalities + if is_win: + proj4_lib = os.path.join(root_path, 'proj.dll') + elif is_darwin: + proj4_lib = os.path.join(root_path, 'lib', 'libproj.dylib') + else: # assumed linux-like settings + proj4_lib = os.path.join(root_path, 'lib', 'libproj.so') + + if os.path.exists(proj4_lib): + binaries = [(proj4_lib, ".")] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pandas_flavor.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pandas_flavor.py new file mode 100644 index 0000000..d76de05 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pandas_flavor.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2022 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# As of version 0.3.0, pandas_flavor uses lazy loader to import `register` and `xarray` sub-modules. In earlier +# versions, these used to be imported directly. +hiddenimports = ['pandas_flavor.register', 'pandas_flavor.xarray'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-panel.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-panel.py new file mode 100644 index 0000000..51c411f --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-panel.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files, collect_submodules + +datas = collect_data_files("panel") + +# Some models are lazy-loaded on runtime, so we need to collect them +hiddenimports = collect_submodules("panel.models") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-parsedatetime.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-parsedatetime.py new file mode 100644 index 0000000..5392a72 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-parsedatetime.py @@ -0,0 +1,29 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2005-2020, PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +#----------------------------------------------------------------------------- +""" +Fixes https://github.com/pyinstaller/pyinstaller/issues/4995 + +Modules under parsedatetime.pdt_locales.* are lazily loaded using __import__. +But they are conviniently listed in parsedatetime.pdt_locales.locales. + +Tested on versions: + +- 1.1.1 +- 1.5 +- 2.0 +- 2.6 (latest) + +""" + +from PyInstaller.utils.hooks import collect_submodules + +hiddenimports = collect_submodules("parsedatetime.pdt_locales") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-parso.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-parso.py new file mode 100644 index 0000000..c00caf1 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-parso.py @@ -0,0 +1,17 @@ +# ----------------------------------------------------------------------------- +# Copyright (c) 2013-2018, PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ----------------------------------------------------------------------------- + +# Hook for Parso, a static analysis tool https://pypi.org/project/jedi/ (IPython dependency) + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('parso') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-passlib.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-passlib.py new file mode 100644 index 0000000..9189b8e --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-passlib.py @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Handlers are imported by a lazy-load proxy, based on a +# name-to-package mapping. Collect all handlers to ease packaging. +# If you want to reduce the size of your application, used +# `--exclude-module` to remove unused ones. +hiddenimports = [ + "passlib.handlers", + "passlib.handlers.digests", + "configparser", +] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-paste.exceptions.reporter.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-paste.exceptions.reporter.py new file mode 100644 index 0000000..9b80044 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-paste.exceptions.reporter.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Some modules use the old-style import: explicitly include +the new module when the old one is referenced. +""" + +hiddenimports = ["email.mime.text", "email.mime.multipart"] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-patoolib.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-patoolib.py new file mode 100644 index 0000000..57d1aa6 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-patoolib.py @@ -0,0 +1,19 @@ +#----------------------------------------------------------------------------- +# Copyright (c) 2017-2024, PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +#----------------------------------------------------------------------------- + + +""" +patoolib uses importlib and pyinstaller doesn't find it and add it to the list of needed modules +""" + +from PyInstaller.utils.hooks import collect_submodules +hiddenimports = collect_submodules('patoolib.programs') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-patsy.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-patsy.py new file mode 100644 index 0000000..39dbf7b --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-patsy.py @@ -0,0 +1,13 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +hiddenimports = ['patsy.builtins'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pdfminer.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pdfminer.py new file mode 100644 index 0000000..e4da9a7 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pdfminer.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('pdfminer') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pendulum.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pendulum.py new file mode 100644 index 0000000..5649b4a --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pendulum.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files, collect_submodules + +# Pendulum checks for locale modules via os.path.exists before import. +# If the include_py_files option is turned off, this check fails, pendulum +# will raise a ValueError. +datas = collect_data_files("pendulum.locales", include_py_files=True) +hiddenimports = collect_submodules("pendulum.locales") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-phonenumbers.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-phonenumbers.py new file mode 100644 index 0000000..1494a21 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-phonenumbers.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +# +# Hook for the phonenumbers package: https://pypi.org/project/phonenumbers/ +# +# Tested with phonenumbers 8.9.7 and Python 3.6.1, on Ubuntu 16.04 64bit. + +from PyInstaller.utils.hooks import collect_submodules + +hiddenimports = collect_submodules('phonenumbers') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pingouin.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pingouin.py new file mode 100644 index 0000000..dd9989b --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pingouin.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('pingouin') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pint.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pint.py new file mode 100644 index 0000000..49d2dee --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pint.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files, copy_metadata + +datas = collect_data_files('pint') +datas += copy_metadata('pint') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pinyin.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pinyin.py new file mode 100644 index 0000000..ad8c547 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pinyin.py @@ -0,0 +1,20 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for the pinyin package: https://pypi.python.org/pypi/pinyin +# Tested with pinyin 0.4.0 and Python 3.6.2, on Windows 10 x64. + +from PyInstaller.utils.hooks import collect_data_files + +# pinyin relies on 'Mandarin.dat' and 'cedict.txt.gz' +# for character and word translation. +datas = collect_data_files('pinyin') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-platformdirs.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-platformdirs.py new file mode 100644 index 0000000..4d6b250 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-platformdirs.py @@ -0,0 +1,27 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.compat import is_darwin, is_win + +modules = ["platformdirs"] + +# platfromdirs contains dynamically loaded per-platform submodules. +if is_darwin: + modules.append("platformdirs.macos") +elif is_win: + modules.append("platformdirs.windows") +else: + # default to unix for all other platforms + # this includes unix, cygwin, and msys2 + modules.append("platformdirs.unix") + +hiddenimports = modules diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-plotly.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-plotly.py new file mode 100644 index 0000000..4897096 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-plotly.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files +from PyInstaller.utils.hooks import collect_submodules + +datas = collect_data_files('plotly', includes=['package_data/**/*.*']) +hiddenimports = collect_submodules('plotly.validators') + ['pandas', 'cmath'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pptx.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pptx.py new file mode 100644 index 0000000..fae9505 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pptx.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('pptx.templates') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-prettytable.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-prettytable.py new file mode 100644 index 0000000..a58ffbc --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-prettytable.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import copy_metadata + +datas = copy_metadata('prettytable') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-psutil.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-psutil.py new file mode 100644 index 0000000..a886d96 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-psutil.py @@ -0,0 +1,50 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +import os +import sys + +# see https://github.com/giampaolo/psutil/blob/release-5.9.5/psutil/_common.py#L82 +WINDOWS = os.name == "nt" +LINUX = sys.platform.startswith("linux") +MACOS = sys.platform.startswith("darwin") +FREEBSD = sys.platform.startswith(("freebsd", "midnightbsd")) +OPENBSD = sys.platform.startswith("openbsd") +NETBSD = sys.platform.startswith("netbsd") +BSD = FREEBSD or OPENBSD or NETBSD +SUNOS = sys.platform.startswith(("sunos", "solaris")) +AIX = sys.platform.startswith("aix") + +excludedimports = [ + "psutil._pslinux", + "psutil._pswindows", + "psutil._psosx", + "psutil._psbsd", + "psutil._pssunos", + "psutil._psaix", +] + +# see https://github.com/giampaolo/psutil/blob/release-5.9.5/psutil/__init__.py#L97 +if LINUX: + excludedimports.remove("psutil._pslinux") +elif WINDOWS: + excludedimports.remove("psutil._pswindows") + # see https://github.com/giampaolo/psutil/blob/release-5.9.5/psutil/_common.py#L856 + # This will exclude `curses` for windows + excludedimports.append("curses") +elif MACOS: + excludedimports.remove("psutil._psosx") +elif BSD: + excludedimports.remove("psutil._psbsd") +elif SUNOS: + excludedimports.remove("psutil._pssunos") +elif AIX: + excludedimports.remove("psutil._psaix") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-psychopy.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-psychopy.py new file mode 100644 index 0000000..4bee8d6 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-psychopy.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Tested on Windows 7 64bit with python 2.7.6 and PsychoPy 1.81.03 + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('psychopy') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-psycopg2.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-psycopg2.py new file mode 100644 index 0000000..7698bbb --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-psycopg2.py @@ -0,0 +1,13 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +hiddenimports = ['mx.DateTime'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-publicsuffix2.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-publicsuffix2.py new file mode 100644 index 0000000..01a5ec2 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-publicsuffix2.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('publicsuffix2') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pubsub.core.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pubsub.core.py new file mode 100644 index 0000000..dea0737 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pubsub.core.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('pubsub.core', include_py_files=True, excludes=['*.txt', '**/__pycache__']) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-puremagic.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-puremagic.py new file mode 100644 index 0000000..8aa599f --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-puremagic.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("puremagic") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-py.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-py.py new file mode 100644 index 0000000..b3bd685 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-py.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2022 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_submodules + +hiddenimports = collect_submodules("py._path") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyarrow.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyarrow.py new file mode 100644 index 0000000..ef98062 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyarrow.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for https://pypi.org/project/pyarrow/ + +from PyInstaller.utils.hooks import collect_submodules, collect_data_files, collect_dynamic_libs + +hiddenimports = collect_submodules('pyarrow', filter=lambda x: "tests" not in x) +datas = collect_data_files('pyarrow') +binaries = collect_dynamic_libs('pyarrow') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pycountry.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pycountry.py new file mode 100644 index 0000000..9dd4f9a --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pycountry.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files, copy_metadata + +# pycountry requires the ISO databases for country data. +# Tested v1.15 on Linux/Ubuntu. +# https://pypi.python.org/pypi/pycountry +datas = copy_metadata('pycountry') + collect_data_files('pycountry') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pycparser.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pycparser.py new file mode 100644 index 0000000..1f2e968 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pycparser.py @@ -0,0 +1,23 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# pycparser needs two modules -- lextab.py and yacctab.py -- which it +# generates at runtime if they cannot be imported. +# +# Those modules are written to the current working directory for which +# the running process may not have write permissions, leading to a runtime +# exception. +# +# This hook tells pyinstaller about those hidden imports, avoiding the +# possibility of such runtime failures. + +hiddenimports = ['pycparser.lextab', 'pycparser.yacctab'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pycrfsuite.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pycrfsuite.py new file mode 100644 index 0000000..8b64162 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pycrfsuite.py @@ -0,0 +1,13 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +hiddenimports = ['pycrfsuite._dumpparser', 'pycrfsuite._logparser', 'tempfile'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pydantic.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pydantic.py new file mode 100644 index 0000000..7780761 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pydantic.py @@ -0,0 +1,48 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import get_module_attribute, collect_submodules +from PyInstaller.utils.hooks import is_module_satisfies + +# By default, PyPi wheels for pydantic < 2.0.0 come with all modules compiled as cython extensions, which prevents +# PyInstaller from automatically picking up the submodules. +if is_module_satisfies('pydantic >= 2.0.0'): + # The `pydantic.compiled` attribute was removed in v2. + is_compiled = False +else: + # NOTE: in PyInstaller 4.x and earlier, get_module_attribute() returns the string representation of the value + # ('True'), while in PyInstaller 5.x and later, the actual value is returned (True). + is_compiled = get_module_attribute('pydantic', 'compiled') in {'True', True} + +if is_compiled: + # Compiled version; we need to manually collect the submodules from + # pydantic... + hiddenimports = collect_submodules('pydantic') + # ... as well as the following modules from the standard library + hiddenimports += [ + 'colorsys', + 'dataclasses', + 'decimal', + 'json', + 'ipaddress', + 'pathlib', + 'uuid', + # Optional dependencies. + 'dotenv', + 'email_validator' + ] + # Older releases (prior 1.4) also import distutils.version + if not is_module_satisfies('pydantic >= 1.4'): + hiddenimports += ['distutils.version'] + # Version 1.8.0 introduced additional dependency on typing_extensions + if is_module_satisfies('pydantic >= 1.8'): + hiddenimports += ['typing_extensions'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pydicom.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pydicom.py new file mode 100644 index 0000000..8b3d497 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pydicom.py @@ -0,0 +1,69 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import is_module_satisfies, collect_data_files + +hiddenimports = [] +datas = [] + +# In pydicom 3.0.0, the `pydicom.encoders` plugins were renamed to `pydicom.pixels.encoders`, and +# `pydicom.pixels.decoders` were also added. We need to collect them all, because they are loaded during +# `pydicom` module initialization. We intentionally avoid using `collect_submodules` here, because that causes +# import of `pydicom` with logging framework initialized, which results in error tracebacks being logged for all plugins +# with missing libraries (see https://github.com/pydicom/pydicom/issues/2128). +if is_module_satisfies('pydicom >= 3.0.0'): + hiddenimports += [ + "pydicom.pixels.decoders.gdcm", + "pydicom.pixels.decoders.pylibjpeg", + "pydicom.pixels.decoders.pillow", + "pydicom.pixels.decoders.pyjpegls", + "pydicom.pixels.decoders.rle", + "pydicom.pixels.encoders.gdcm", + "pydicom.pixels.encoders.pylibjpeg", + "pydicom.pixels.encoders.native", + "pydicom.pixels.encoders.pyjpegls", + ] + + # With pydicom 3.0.0, initialization of `pydicom` (unnecessarily) imports `pydicom.examples`, which attempts to set + # up several test datasets: https://github.com/pydicom/pydicom/blob/v3.0.0/src/pydicom/examples/__init__.py#L10-L24 + # Some of those are bundled with the package itself, some are downloaded (into `.pydicom/data` directory in user's + # home directory) on he first `pydicom.examples` import. + # + # The download code requires `pydicom/data/urls.json` and `pydicom/data/hashes.json`; the lack of former results in + # run-time error, while the lack of latter results in warnings about dataset download failure. + # + # The test data files that are bundled with the package are not listed in `urls.json`, so if they are missing, there + # is not attempt to download them. Therefore, try to get away without collecting them here - if anyone actually + # requires them in the frozen application, let them explicitly collect them. + additional_data_patterns = [ + 'urls.json', + 'hashes.json', + ] +else: + hiddenimports += [ + "pydicom.encoders.gdcm", + "pydicom.encoders.pylibjpeg", + "pydicom.encoders.native", + ] + additional_data_patterns = [] + +# Collect data files from `pydicom.data`; charset files and palettes might be needed during processing, so always +# collect them. Some other data files became required in v3.0.0 - the corresponding patterns are set accordingly in +# `additional_data_patterns` in the above if/else block. +datas += collect_data_files( + 'pydicom.data', + includes=[ + 'charset_files/*', + 'palettes/*', + *additional_data_patterns, + ], +) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pydivert.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pydivert.py new file mode 100644 index 0000000..dab32b8 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pydivert.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('pydivert.windivert_dll') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel-io.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel-io.py new file mode 100644 index 0000000..55fd56a --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel-io.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# This hook was tested with pyexcel-io 0.5.18: +# https://github.com/pyexcel/pyexcel-io + +hiddenimports = ['pyexcel_io'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel-ods.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel-ods.py new file mode 100644 index 0000000..160e1b2 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel-ods.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# This hook was tested with pyexcel-ods 0.5.6: +# https://github.com/pyexcel/pyexcel-ods + +hiddenimports = ['pyexcel_ods'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel-ods3.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel-ods3.py new file mode 100644 index 0000000..a01beed --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel-ods3.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# This hook was tested with pyexcel-ods3 0.5.3: +# https://github.com/pyexcel/pyexcel-ods3 + +hiddenimports = ['pyexcel_ods3'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel-odsr.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel-odsr.py new file mode 100644 index 0000000..0d10d71 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel-odsr.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# This hook was tested with pyexcel-io 0.5.2: +# https://github.com/pyexcel/pyexcel-io + +hiddenimports = ['pyexcel_odsr'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel-xls.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel-xls.py new file mode 100644 index 0000000..60acc3f --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel-xls.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# This hook was tested with pyexcel-xls 0.5.8: +# https://github.com/pyexcel/pyexcel-xls + +hiddenimports = ['pyexcel_xls'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel-xlsx.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel-xlsx.py new file mode 100644 index 0000000..1f12497 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel-xlsx.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# This hook was tested with pyexcel-xlsx 0.4.2: +# https://github.com/pyexcel/pyexcel-xlsx + +hiddenimports = ['pyexcel_xlsx'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel-xlsxw.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel-xlsxw.py new file mode 100644 index 0000000..c0b6778 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel-xlsxw.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# This hook was tested with pyexcel-xlsxw 0.4.2: +# https://github.com/pyexcel/pyexcel-xlsxw + +hiddenimports = ['pyexcel_xlsxw'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel.py new file mode 100644 index 0000000..f000b2d --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel.py @@ -0,0 +1,29 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# This hook was tested with pyexcel 0.5.13: +# https://github.com/pyexcel/pyexcel + +hiddenimports = [ + 'pyexcel.plugins.renderers.sqlalchemy', 'pyexcel.plugins.renderers.django', + 'pyexcel.plugins.renderers.excel', 'pyexcel.plugins.renderers._texttable', + 'pyexcel.plugins.parsers.excel', 'pyexcel.plugins.parsers.sqlalchemy', + 'pyexcel.plugins.sources.http', 'pyexcel.plugins.sources.file_input', + 'pyexcel.plugins.sources.memory_input', + 'pyexcel.plugins.sources.file_output', + 'pyexcel.plugins.sources.output_to_memory', + 'pyexcel.plugins.sources.pydata.bookdict', + 'pyexcel.plugins.sources.pydata.dictsource', + 'pyexcel.plugins.sources.pydata.arraysource', + 'pyexcel.plugins.sources.pydata.records', 'pyexcel.plugins.sources.django', + 'pyexcel.plugins.sources.sqlalchemy', 'pyexcel.plugins.sources.querysets' +] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel_io.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel_io.py new file mode 100644 index 0000000..2096a74 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel_io.py @@ -0,0 +1,26 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# This hook was tested with pyexcel-io 0.5.18: +# https://github.com/pyexcel/pyexcel-io + +hiddenimports = [ + 'pyexcel_io.readers.csvr', 'pyexcel_io.readers.csvz', + 'pyexcel_io.readers.tsv', 'pyexcel_io.readers.tsvz', + 'pyexcel_io.writers.csvw', 'pyexcel_io.writers.csvz', + 'pyexcel_io.writers.tsv', 'pyexcel_io.writers.tsvz', + 'pyexcel_io.readers.csvz', 'pyexcel_io.readers.tsv', + 'pyexcel_io.readers.tsvz', 'pyexcel_io.database.importers.django', + 'pyexcel_io.database.importers.sqlalchemy', + 'pyexcel_io.database.exporters.django', + 'pyexcel_io.database.exporters.sqlalchemy' +] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel_ods.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel_ods.py new file mode 100644 index 0000000..f856a0e --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel_ods.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# This hook was tested with pyexcel-ods 0.5.6: +# https://github.com/pyexcel/pyexcel-ods + +hiddenimports = ['pyexcel_ods', 'pyexcel_ods.odsr', 'pyexcel_ods.odsw', "pyexcel_io.writers"] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel_ods3.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel_ods3.py new file mode 100644 index 0000000..c4f54eb --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel_ods3.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# This hook was tested with pyexcel-ods3 0.5.3: +# https://github.com/pyexcel/pyexcel-ods3 + +hiddenimports = ['pyexcel_ods3', 'pyexcel_ods3.odsr', 'pyexcel_ods3.odsw'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel_odsr.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel_odsr.py new file mode 100644 index 0000000..d895ed1 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel_odsr.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# This hook was tested with pyexcel-io 0.5.2: +# https://github.com/pyexcel/pyexcel-io + +hiddenimports = ['pyexcel_odsr', 'pyexcel_odsr.odsr'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel_xls.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel_xls.py new file mode 100644 index 0000000..4875412 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel_xls.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# This hook was tested with pyexcel-xls 0.5.8: +# https://github.com/pyexcel/pyexcel-xls + +hiddenimports = ['pyexcel_xls', 'pyexcel_xls.xlsr', 'pyexcel_xls.xlsw'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel_xlsx.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel_xlsx.py new file mode 100644 index 0000000..438aab6 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel_xlsx.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# This hook was tested with pyexcel-xlsx 0.4.2: +# https://github.com/pyexcel/pyexcel-xlsx + +hiddenimports = ['pyexcel_xlsx', 'pyexcel_xlsx.xlsxr', 'pyexcel_xlsx.xlsxw'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel_xlsxw.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel_xlsxw.py new file mode 100644 index 0000000..72f7593 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel_xlsxw.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# This hook was tested with pyexcel-xlsxw 0.4.2: +# https://github.com/pyexcel/pyexcel-xlsxw + +hiddenimports = ['pyexcel_xlsxw', 'pyexcel_xlsxw.xlsxw'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcelerate.Writer.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcelerate.Writer.py new file mode 100644 index 0000000..ff9dbc8 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyexcelerate.Writer.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('pyexcelerate') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pygraphviz.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pygraphviz.py new file mode 100644 index 0000000..d497905 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pygraphviz.py @@ -0,0 +1,66 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +import glob +import os +import shutil + +from PyInstaller.compat import is_win, is_darwin +from PyInstaller.depend.bindepend import findLibrary + +binaries = [] +datas = [] + +# List of binaries agraph.py may invoke. +progs = [ + "neato", + "dot", + "twopi", + "circo", + "fdp", + "nop", + "acyclic", + "gvpr", + "gvcolor", + "ccomps", + "sccmap", + "tred", + "sfdp", + "unflatten", +] + +if is_win: + for prog in progs: + for binary in glob.glob("c:/Program Files/Graphviz*/bin/" + prog + ".exe"): + binaries.append((binary, ".")) + for binary in glob.glob("c:/Program Files/Graphviz*/bin/*.dll"): + binaries.append((binary, ".")) + for data in glob.glob("c:/Program Files/Graphviz*/bin/config*"): + datas.append((data, ".")) +else: + # The dot binary in PATH is typically a symlink, handle that. + # graphviz_bindir is e.g. /usr/local/Cellar/graphviz/2.46.0/bin + graphviz_bindir = os.path.dirname(os.path.realpath(shutil.which("dot"))) + for binary in progs: + binaries.append((graphviz_bindir + "/" + binary, ".")) + if is_darwin: + suffix = "dylib" + # graphviz_libdir is e.g. /usr/local/Cellar/graphviz/2.46.0/lib/graphviz + graphviz_libdir = os.path.realpath(graphviz_bindir + "/../lib/graphviz") + else: + suffix = "so" + # graphviz_libdir is e.g. /usr/lib64/graphviz + graphviz_libdir = os.path.join(os.path.dirname(findLibrary('libcdt')), 'graphviz') + for binary in glob.glob(graphviz_libdir + "/*." + suffix): + binaries.append((binary, "graphviz")) + for data in glob.glob(graphviz_libdir + "/config*"): + datas.append((data, "graphviz")) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pygwalker.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pygwalker.py new file mode 100644 index 0000000..9e78db1 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pygwalker.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('pygwalker') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pylibmagic.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pylibmagic.py new file mode 100644 index 0000000..5fb8024 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pylibmagic.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Pylibmagic contains data files (libmagic compiled and configurations) required to use the python-magic package. +""" + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("pylibmagic") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pylint.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pylint.py new file mode 100644 index 0000000..3e2e804 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pylint.py @@ -0,0 +1,75 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +# +# ************************************************* +# hook-pylint.py - PyInstaller hook file for pylint +# ************************************************* +# The pylint package, in __pkginfo__.py, is version 1.4.3. Looking at its +# source: +# +# From checkers/__init__.py, starting at line 122:: +# +# def initialize(linter): +# """initialize linter with checkers in this package """ +# register_plugins(linter, __path__[0]) +# +# From reporters/__init__.py, starting at line 131:: +# +# def initialize(linter): +# """initialize linter with reporters in this package """ +# utils.register_plugins(linter, __path__[0]) +# +# From utils.py, starting at line 881:: +# +# def register_plugins(linter, directory): +# """load all module and package in the given directory, looking for a +# 'register' function in each one, used to register pylint checkers +# """ +# imported = {} +# for filename in os.listdir(directory): +# base, extension = splitext(filename) +# if base in imported or base == '__pycache__': +# continue +# if extension in PY_EXTS and base != '__init__' or ( +# not extension and isdir(join(directory, base))): +# try: +# module = load_module_from_file(join(directory, filename)) +# +# +# So, we need all the Python source in the ``checkers/`` and ``reporters/`` +# subdirectories, since these are run-time discovered and loaded. Therefore, +# these files are all data files. In addition, since this is a module, the +# pylint/__init__.py file must be included, since submodules must be children of +# a module. + +from PyInstaller.utils.hooks import ( + collect_data_files, collect_submodules, is_module_or_submodule, get_module_file_attribute +) + +datas = ( + [(get_module_file_attribute('pylint.__init__'), 'pylint')] + + collect_data_files('pylint.checkers', True) + + collect_data_files('pylint.reporters', True) +) + + +# Add imports from dynamically loaded modules, excluding pylint.test +# subpackage (pylint <= 2.3) and pylint.testutils submodule (pylint < 2.7) +# or subpackage (pylint >= 2.7) +def _filter_func(name): + return ( + not is_module_or_submodule(name, 'pylint.test') and + not is_module_or_submodule(name, 'pylint.testutils') + ) + + +hiddenimports = collect_submodules('pylint', _filter_func) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pylsl.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pylsl.py new file mode 100644 index 0000000..473d38b --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pylsl.py @@ -0,0 +1,41 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +import os +from PyInstaller.utils.hooks import logger, isolated + + +def find_library(): + try: + # the import will fail it the library cannot be found + from pylsl import pylsl + + # the find_liblsl_libraries() is a generator function that yields multiple possibilities + for libfile in pylsl.find_liblsl_libraries(): + if libfile: + break + except (ImportError, ModuleNotFoundError, RuntimeError) as error: + print(error) + libfile = None + return libfile + + +# whenever a hook needs to load a 3rd party library, it needs to be done in an isolated subprocess +libfile = isolated.call(find_library) + +if libfile: + # add the liblsl library to the binaries + # it gets packaged in pylsl/lib, which is where pylsl will look first + binaries = [(libfile, os.path.join('pylsl', 'lib'))] +else: + logger.warning("liblsl shared library not found - pylsl will likely fail to work!") + binaries = [] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pymediainfo.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pymediainfo.py new file mode 100644 index 0000000..6b39abc --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pymediainfo.py @@ -0,0 +1,44 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.compat import is_win, is_darwin +from PyInstaller.utils.hooks import collect_dynamic_libs, logger + +# Collect bundled mediainfo shared library (available in Windows and macOS wheels on PyPI). +binaries = collect_dynamic_libs("pymediainfo") + +# On linux, no wheels are available, and pymediainfo uses system shared library. +if not binaries and not (is_win or is_darwin): + + def _find_system_mediainfo_library(): + import os + import ctypes.util + from PyInstaller.depend.utils import _resolveCtypesImports + + libname = ctypes.util.find_library("mediainfo") + if libname is not None: + resolved_binary = _resolveCtypesImports([os.path.basename(libname)]) + if resolved_binary: + return resolved_binary[0][1] + + try: + mediainfo_lib = _find_system_mediainfo_library() + except Exception as e: + logger.warning("Error while trying to find system-installed MediaInfo library: %s", e) + mediainfo_lib = None + + if mediainfo_lib: + # Put the library into pymediainfo sub-directory, to keep layout consistent with that of wheels. + binaries += [(mediainfo_lib, 'pymediainfo')] + +if not binaries: + logger.warning("MediaInfo shared library not found - pymediainfo will likely fail to work!") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pymorphy3.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pymorphy3.py new file mode 100644 index 0000000..7282272 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pymorphy3.py @@ -0,0 +1,25 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import can_import_module, copy_metadata, collect_data_files + +datas = copy_metadata('pymorphy3_dicts_ru') +datas += collect_data_files('pymorphy3_dicts_ru') + +hiddenimports = ['pymorphy3_dicts_ru'] + +# Check if the Ukrainian model is installed +if can_import_module('pymorphy3_dicts_uk'): + datas += copy_metadata('pymorphy3_dicts_uk') + datas += collect_data_files('pymorphy3_dicts_uk') + + hiddenimports += ['pymorphy3_dicts_uk'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pymssql.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pymssql.py new file mode 100644 index 0000000..f3a3c96 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pymssql.py @@ -0,0 +1,20 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020-2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import is_module_satisfies + +hiddenimports = ["decimal"] +# In newer versions of pymssql, the _mssql was under pymssql +if is_module_satisfies("pymssql > 2.1.5"): + hiddenimports += ["pymssql._mssql", "uuid"] +else: + hiddenimports += ["_mssql"] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pynput.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pynput.py new file mode 100644 index 0000000..0776e1d --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pynput.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_submodules + +hiddenimports = collect_submodules("pynput") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyodbc.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyodbc.py new file mode 100644 index 0000000..bfa2f42 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyodbc.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import get_pyextension_imports + +# It's hard to detect imports of binary Python module without importing it. +# Let's try importing that module in a subprocess. +# TODO function get_pyextension_imports() is experimental and we need +# to evaluate its usage here and its suitability for other hooks. +hiddenimports = get_pyextension_imports('pyodbc') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyopencl.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyopencl.py new file mode 100644 index 0000000..9646426 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyopencl.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for the pyopencl module: https://github.com/pyopencl/pyopencl + +from PyInstaller.utils.hooks import copy_metadata, collect_data_files + +datas = copy_metadata('pyopencl') +datas += collect_data_files('pyopencl') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pypemicro.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pypemicro.py new file mode 100644 index 0000000..7a6e873 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pypemicro.py @@ -0,0 +1,43 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2022 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for the pypemicro module: https://github.com/nxpmicro/pypemicro + +import os +from PyInstaller.utils.hooks import get_package_paths, is_module_satisfies +from PyInstaller.log import logger +from PyInstaller.compat import is_darwin + +binaries = list() +if is_module_satisfies('pyinstaller >= 5.0'): + from PyInstaller import isolated + + @isolated.decorate + def get_safe_libs(): + from pypemicro import PyPemicro + libs = PyPemicro.get_pemicro_lib_list() + return libs + + pkg_base, pkg_dir = get_package_paths("pypemicro") + for lib in get_safe_libs(): + source_path = lib['path'] + source_name = lib['name'] + dest = os.path.relpath(source_path, pkg_base) + binaries.append((os.path.join(source_path, source_name), dest)) + if is_darwin: + libusb = os.path.join(source_path, 'libusb.dylib') + if os.path.exists(libusb): + binaries.append((libusb, dest)) + else: + logger.warning("libusb.dylib was not found for Mac OS, ignored") +else: + logger.warning("hook-pypemicro requires pyinstaller >= 5.0") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyphen.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyphen.py new file mode 100644 index 0000000..9f0be6f --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyphen.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('pyphen') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyppeteer.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyppeteer.py new file mode 100644 index 0000000..8c15c18 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyppeteer.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import copy_metadata + +# pyppeteer uses importlib.metadata to query its own version. +datas = copy_metadata("pyppeteer") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyproj.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyproj.py new file mode 100644 index 0000000..dab54c6 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyproj.py @@ -0,0 +1,72 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +import os +import sys +from PyInstaller.utils.hooks import collect_data_files, is_module_satisfies, copy_metadata +from PyInstaller.compat import is_win, is_conda + +hiddenimports = [ + "pyproj.datadir" +] + +binaries = [] + +# Versions prior to 2.3.0 also require pyproj._datadir +if not is_module_satisfies("pyproj >= 2.3.0"): + hiddenimports += ["pyproj._datadir"] + +# Starting with version 3.0.0, pyproj._compat is needed +if is_module_satisfies("pyproj >= 3.0.0"): + hiddenimports += ["pyproj._compat"] + # Linux and macOS also require distutils. + if not is_win: + hiddenimports += ["distutils.util"] + +# Data collection +datas = collect_data_files('pyproj') + +if hasattr(sys, 'real_prefix'): # check if in a virtual environment + root_path = sys.real_prefix +else: + root_path = sys.prefix + +# - conda-specific +if is_win: + tgt_proj_data = os.path.join('Library', 'share', 'proj') + src_proj_data = os.path.join(root_path, 'Library', 'share', 'proj') + +else: # both linux and darwin + tgt_proj_data = os.path.join('share', 'proj') + src_proj_data = os.path.join(root_path, 'share', 'proj') + +if is_conda: + if os.path.exists(src_proj_data): + datas.append((src_proj_data, tgt_proj_data)) + else: + from PyInstaller.utils.hooks import logger + logger.warning("Datas for pyproj not found at:\n{}".format(src_proj_data)) + # A runtime hook defines the path for `PROJ_LIB` + +# With pyproj 3.4.0, we need to collect package's metadata due to `importlib.metadata.version(__package__)` call in +# `__init__.py`. This change was reverted in subsequent releases of pyproj, so we collect metadata only for 3.4.0. +if is_module_satisfies("pyproj == 3.4.0"): + datas += copy_metadata("pyproj") + +# pyproj 3.4.0 was also the first release that used `delvewheel` for its Windows PyPI wheels. While contemporary +# PyInstaller versions automatically pick up DLLs from external `pyproj.libs` directory, this does not work on Anaconda +# python 3.8 and 3.9 due to defunct `os.add_dll_directory`, which forces `delvewheel` to use the old load-order file +# approach. So we need to explicitly ensure that load-order file as well as DLLs are collected. +if is_win and is_module_satisfies("pyproj >= 3.4.0"): + if is_module_satisfies("PyInstaller >= 5.6"): + from PyInstaller.utils.hooks import collect_delvewheel_libs_directory + datas, binaries = collect_delvewheel_libs_directory("pyproj", datas=datas, binaries=binaries) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pypsexec.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pypsexec.py new file mode 100644 index 0000000..c96a56e --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pypsexec.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2022 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# The bundled paexec.exe file needs to be collected (as data file; on any platform) +# because it is deployed to the remote side during execution. + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('pypsexec') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pypylon.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pypylon.py new file mode 100644 index 0000000..395aaf9 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pypylon.py @@ -0,0 +1,48 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# PyPylon is a tricky library to bundle. It encapsulates the pylon C++ SDK inside +# it with modified library references to make the module relocatable. +# PyInstaller is able to find those libraries and preserve the linkage for almost +# all of them. However - there is an additional linking step happening at runtime, +# when the library is creating the transport layer for the camera. This linking +# will fail with the library files modified by pyinstaller. +# As the module is already relocatable, we circumvent this issue by bundling +# pypylon as-is - for pyinstaller we treat the shared library files as just data. + +import os + +from PyInstaller.utils.hooks import ( + collect_data_files, + collect_dynamic_libs, + is_module_satisfies +) + +# Collect dynamic libs as data (to prevent pyinstaller from modifying them). +# NOTE: under PyInstaller 6.x, these files end up re-classified as binaries anyway. +datas = collect_dynamic_libs('pypylon') + +# Collect data files, looking for pypylon/pylonCXP/bin/ProducerCXP.cti, but other files may also be needed +datas += collect_data_files('pypylon') + +# NOTE: the part below is incompatible with PyInstaller 6.x, because `collect_data_files(..., include_py_files=True)` +# does not include binary extensions anymore. In addition, `pyinstaller/pyinstaller@ecc218c` in PyInstaller 6.2 fixed +# the module exclusion for relative imports, so the modules listed below actually end up excluded. Presumably this +# part was necessary with older PyInstaller versions, so we keep it around, but disable it for PyInstaller >= 6.0. +if is_module_satisfies('PyInstaller < 6.0'): + # Exclude the C++-extensions from automatic search, add them manually as data files + # their dependencies were already handled with collect_dynamic_libs + excludedimports = ['pypylon._pylon', 'pypylon._genicam'] + for filename, module in collect_data_files('pypylon', include_py_files=True): + if (os.path.basename(filename).startswith('_pylon.') + or os.path.basename(filename).startswith('_genicam.')): + datas += [(filename, module)] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyqtgraph.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyqtgraph.py new file mode 100644 index 0000000..0d8bf9c --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyqtgraph.py @@ -0,0 +1,56 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files, collect_submodules + +# Collect all data files, excluding the examples' data +datas = collect_data_files('pyqtgraph', excludes=['**/examples/*']) + +# pyqtgraph uses Qt-version-specific templates for the UI elements. +# There are templates for different versions of PySide and PyQt, e.g. +# +# - pyqtgraph.graphicsItems.ViewBox.axisCtrlTemplate_pyqt5 +# - pyqtgraph.graphicsItems.ViewBox.axisCtrlTemplate_pyqt6 +# - pyqtgraph.graphicsItems.ViewBox.axisCtrlTemplate_pyside2 +# - pyqtgraph.graphicsItems.ViewBox.axisCtrlTemplate_pyside6 +# - pyqtgraph.graphicsItems.PlotItem.plotConfigTemplate_pyqt5 +# - pyqtgraph.graphicsItems.PlotItem.plotConfigTemplate_pyqt6 +# - pyqtgraph.graphicsItems.PlotItem.plotConfigTemplate_pyside2 +# - pyqtgraph.graphicsItems.PlotItem.plotConfigTemplate_pyside6 +# +# To be future-proof, we collect all modules by +# using collect-submodules, and filtering the modules +# which appear to be templates. +# We need to avoid recursing into `pyqtgraph.examples`, because that +# triggers instantiation of `QApplication` (which requires X/Wayland +# session on linux). +# Tested with pyqtgraph master branch (commit c1900aa). +all_imports = collect_submodules("pyqtgraph", filter=lambda name: name != "pyqtgraph.examples") +hiddenimports = [name for name in all_imports if "Template" in name] + +# Collect the pyqtgraph/multiprocess/bootstrap.py as a module; this is required by our pyqtgraph.multiprocess runtime +# hook to handle the pyqtgraph's multiprocessing implementation. The pyqtgraph.multiprocess seems to be imported +# automatically on the import of pyqtgraph itself, so there is no point in creating a separate hook for this. +hiddenimports += ['pyqtgraph.multiprocess.bootstrap'] + +# Attempt to auto-select applicable Qt bindings and exclude extraneous Qt bindings. +# Available in PyInstaller >= 6.5, which has `PyInstaller.utils.hooks.qt.exclude_extraneous_qt_bindings` helper. +try: + from PyInstaller.utils.hooks.qt import exclude_extraneous_qt_bindings +except ImportError: + pass +else: + # Use the helper's default preference order, to keep it consistent across multiple hooks that use the same helper. + excludedimports = exclude_extraneous_qt_bindings( + hook_name="hook-pyqtgraph", + qt_bindings_order=None, + ) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyshark.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyshark.py new file mode 100644 index 0000000..46aae20 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyshark.py @@ -0,0 +1,25 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Python wrapper for pyshark(https://pypi.org/project/pyshark/) +# Tested with version 0.4.5 + +from PyInstaller.utils.hooks import collect_data_files, is_module_satisfies + +hiddenimports = ['pyshark.config'] + +if is_module_satisfies("pyshark < 0.6"): + hiddenimports += ['py._path.local', 'py._vendored_packages.iniconfig'] + if is_module_satisfies("pyshark >= 0.5"): + hiddenimports += ["py._io.terminalwriter", "py._builtin"] + +datas = collect_data_files('pyshark') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pysnmp.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pysnmp.py new file mode 100644 index 0000000..5824b58 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pysnmp.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_submodules, collect_data_files + +hiddenimports = collect_submodules('pysnmp.smi.mibs') +datas = collect_data_files('pysnmp.smi.mibs', include_py_files=True) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pystray.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pystray.py new file mode 100644 index 0000000..835b0be --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pystray.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_submodules +# https://github.com/moses-palmer/pystray/tree/feature-explicit-backends +# if this get merged then we don't need this hook +hiddenimports = collect_submodules("pystray") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pytest.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pytest.py new file mode 100644 index 0000000..080d2e7 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pytest.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Hook for http://pypi.python.org/pypi/pytest/ +""" + +import pytest + +hiddenimports = pytest.freeze_includes() diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pythainlp.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pythainlp.py new file mode 100644 index 0000000..d5bdcc5 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pythainlp.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('pythainlp') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pythoncom.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pythoncom.py new file mode 100644 index 0000000..05b0c1d --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pythoncom.py @@ -0,0 +1,31 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# pywin32 supports frozen mode; in that mode, it is looking at sys.path for pythoncomXY.dll. However, as of +# PyInstaller 5.4, we may collect that DLL into its original pywin32_system32 sub-directory as part of the +# binary dependency analysis (and add it to sys.path by means of a runtime hook). + +import pathlib + +from PyInstaller.utils.hooks import is_module_satisfies, get_pywin32_module_file_attribute + +dll_filename = get_pywin32_module_file_attribute('pythoncom') +dst_dir = '.' # Top-level application directory + +if is_module_satisfies('PyInstaller >= 5.4'): + # Try preserving the original pywin32_system directory, if applicable (it is not applicable in Anaconda, + # where the DLL is located in Library/bin). + dll_path = pathlib.Path(dll_filename) + if dll_path.parent.name == 'pywin32_system32': + dst_dir = 'pywin32_system32' + +binaries = [(dll_filename, dst_dir)] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyttsx.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyttsx.py new file mode 100644 index 0000000..36fceb2 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyttsx.py @@ -0,0 +1,23 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +pyttsx imports drivers module based on specific platform. +Found at http://mrmekon.tumblr.com/post/5272210442/pyinstaller-and-pyttsx +""" + +hiddenimports = [ + 'drivers', + 'drivers.dummy', + 'drivers.espeak', + 'drivers.nsss', + 'drivers.sapi5', +] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyttsx3.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyttsx3.py new file mode 100644 index 0000000..ac3edf8 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyttsx3.py @@ -0,0 +1,30 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# pyttsx3 conditionally imports drivers module based on specific platform. +# https://github.com/nateshmbhat/pyttsx3/blob/5a19376a94fdef6bfaef8795539e755b1f363fbf/pyttsx3/driver.py#L40-L50 + +import sys + +hiddenimports = ["pyttsx3.drivers", "pyttsx3.drivers.dummy"] + +# Take directly from the link above. +if sys.platform == 'darwin': + driverName = 'nsss' +elif sys.platform == 'win32': + driverName = 'sapi5' +else: + driverName = 'espeak' +# import driver module +name = 'pyttsx3.drivers.%s' % driverName + +hiddenimports.append(name) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyviz_comms.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyviz_comms.py new file mode 100644 index 0000000..5a882c9 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyviz_comms.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("pyviz_comms") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyvjoy.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyvjoy.py new file mode 100644 index 0000000..d72e13e --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pyvjoy.py @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +from PyInstaller.utils.hooks import collect_dynamic_libs + +binaries = collect_dynamic_libs("pyvjoy") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pywintypes.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pywintypes.py new file mode 100644 index 0000000..b452e93 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pywintypes.py @@ -0,0 +1,31 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# pywin32 supports frozen mode; in that mode, it is looking at sys.path for pywintypesXY.dll. However, as of +# PyInstaller 5.4, we may collect that DLL into its original pywin32_system32 sub-directory as part of the +# binary dependency analysis (and add it to sys.path by means of a runtime hook). + +import pathlib + +from PyInstaller.utils.hooks import is_module_satisfies, get_pywin32_module_file_attribute + +dll_filename = get_pywin32_module_file_attribute('pywintypes') +dst_dir = '.' # Top-level application directory + +if is_module_satisfies('PyInstaller >= 5.4'): + # Try preserving the original pywin32_system directory, if applicable (it is not applicable in Anaconda, + # where the DLL is located in Library/bin). + dll_path = pathlib.Path(dll_filename) + if dll_path.parent.name == 'pywin32_system32': + dst_dir = 'pywin32_system32' + +binaries = [(dll_filename, dst_dir)] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pywt.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pywt.py new file mode 100644 index 0000000..e1b5f36 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-pywt.py @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for https://github.com/PyWavelets/pywt + +hiddenimports = ['pywt._extensions._cwt'] + +# NOTE: There is another project `https://github.com/Knapstad/pywt installing +# a packagre `pywt`, too. This name clash is not much of a problem, even if +# this hook is picked up for the other package, since PyInstaller will simply +# skip any module added by this hook but acutally missing. If the other project +# requires a hook, too, simply add it to this file. diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-qtmodern.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-qtmodern.py new file mode 100644 index 0000000..2adb2b7 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-qtmodern.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("qtmodern", includes=["**/*.qss"]) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-radicale.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-radicale.py new file mode 100644 index 0000000..56b487a --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-radicale.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import copy_metadata, collect_data_files + +datas = copy_metadata('radicale') +datas += collect_data_files('radicale') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-raven.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-raven.py new file mode 100644 index 0000000..fe6f8e6 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-raven.py @@ -0,0 +1,13 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +hiddenimports = ['raven.events', 'raven.processors'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-rawpy.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-rawpy.py new file mode 100644 index 0000000..7daf325 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-rawpy.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Python wrapper for LibRaw (https://pypi.python.org/pypi/rawpy) +# Tested with version 0.3.5 + +hiddenimports = ['numpy', 'enum'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-rdflib.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-rdflib.py new file mode 100644 index 0000000..7fc6631 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-rdflib.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_submodules + +hiddenimports = collect_submodules('rdflib.plugins') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-redmine.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-redmine.py new file mode 100644 index 0000000..1291095 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-redmine.py @@ -0,0 +1,13 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +hiddenimports = ['redmine.resources'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-regex.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-regex.py new file mode 100644 index 0000000..e55764e --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-regex.py @@ -0,0 +1,13 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +hiddenimports = ['warnings'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-reportlab.lib.utils.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-reportlab.lib.utils.py new file mode 100644 index 0000000..eb3ce68 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-reportlab.lib.utils.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Needed for ReportLab 3 +hiddenimports = [ + 'reportlab.rl_settings', +] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-reportlab.pdfbase._fontdata.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-reportlab.pdfbase._fontdata.py new file mode 100644 index 0000000..e4e8e9a --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-reportlab.pdfbase._fontdata.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_submodules + +# Tested on Windows 7 x64 with Python 2.7.6 x32 using ReportLab 3.0 +# This has been observed to *not* work on ReportLab 2.7 +hiddenimports = collect_submodules('reportlab.pdfbase', + lambda name: name.startswith('reportlab.pdfbase._fontdata_')) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-resampy.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-resampy.py new file mode 100644 index 0000000..8b45d2c --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-resampy.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for resampy +from PyInstaller.utils.hooks import collect_data_files + +# resampy has two data files that need to be included. +datas = collect_data_files('resampy', False) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-rlp.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-rlp.py new file mode 100644 index 0000000..c59c1b6 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-rlp.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import is_module_satisfies, copy_metadata + +# Starting with v4.0.0, `rlp` queries its version from metadata. +if is_module_satisfies("rlp >= 4.0.0"): + datas = copy_metadata('rlp') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-rpy2.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-rpy2.py new file mode 100644 index 0000000..f37c2b6 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-rpy2.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +hiddenimports = [ + "rpy2", + "rpy2.robjects", + "rpy2.robjects.packages", + "rpy2.situation", +] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-rtree.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-rtree.py new file mode 100644 index 0000000..a5bbede --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-rtree.py @@ -0,0 +1,40 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +import pathlib + +from PyInstaller import compat +from PyInstaller.utils.hooks import collect_dynamic_libs, get_installer, get_package_paths + + +# Query the installer of the `rtree` package; in PyInstaller prior to 6.0, this might raise an exception, whereas in +# later versions, None is returned. +try: + package_installer = get_installer('rtree') +except Exception: + package_installer = None + +if package_installer == 'conda': + from PyInstaller.utils.hooks import conda + + # In Anaconda-packaged `rtree`, `libspatialindex` and `libspatialindex_c` shared libs are packaged in a separate + # `libspatialindex` package. Collect the libraries into `rtree/lib` sub-directory to simulate PyPI wheel layout. + binaries = conda.collect_dynamic_libs('libspatialindex', dest='rtree/lib', dependencies=False) +else: + # pip-installed package. The shared libs are usually placed in `rtree/lib` directory. + binaries = collect_dynamic_libs('rtree') + + # With rtree >= 1.1.0, Linux PyPI wheels place the shared library in a `Rtree.libs` top-level directory. + if compat.is_linux: + _, rtree_dir = get_package_paths('rtree') + rtree_libs_dir = pathlib.Path(rtree_dir).parent / 'Rtree.libs' + binaries += [(str(lib_file), 'Rtree.libs') for lib_file in rtree_libs_dir.glob("libspatialindex*.so*")] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-rubicon.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-rubicon.py new file mode 100644 index 0000000..68116a1 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-rubicon.py @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Prevent this package from pulling `setuptools_scm` into frozen application, as it makes no sense in that context. +excludedimports = ["setuptools_scm"] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sacremoses.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sacremoses.py new file mode 100644 index 0000000..23b00db --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sacremoses.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('sacremoses') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-saml2.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-saml2.py new file mode 100644 index 0000000..244944a --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-saml2.py @@ -0,0 +1,25 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for https://github.com/IdentityPython/pysaml2 +from PyInstaller.utils.hooks import collect_data_files, copy_metadata, collect_submodules + +datas = copy_metadata("pysaml2") + +# The library contains a bunch of XSD schemas that are loaded by the code: +# https://github.com/IdentityPython/pysaml2/blob/7cb4f09dce87a7e8098b9c7552ebab8bc77bc896/src/saml2/xml/schema/__init__.py#L23 +# On the other hand, runtime tools are not needed. +datas += collect_data_files("saml2", excludes=["**/tools"]) + +# Submodules are loaded dynamically by: +# https://github.com/IdentityPython/pysaml2/blob/7cb4f09dce87a7e8098b9c7552ebab8bc77bc896/src/saml2/attribute_converter.py#L52 +hiddenimports = collect_submodules("saml2.attributemaps") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-schwifty.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-schwifty.py new file mode 100644 index 0000000..a8b30ca --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-schwifty.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import copy_metadata, collect_data_files + +datas = copy_metadata('schwifty') +datas += collect_data_files('schwifty') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-seedir.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-seedir.py new file mode 100644 index 0000000..28ed6b5 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-seedir.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('seedir') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-selenium.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-selenium.py new file mode 100644 index 0000000..13a312a --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-selenium.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('selenium') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sentry_sdk.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sentry_sdk.py new file mode 100644 index 0000000..b7ee95c --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sentry_sdk.py @@ -0,0 +1,40 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +import json +from PyInstaller.utils.hooks import exec_statement + +hiddenimports = ["sentry_sdk.integrations.stdlib", + "sentry_sdk.integrations.excepthook", + "sentry_sdk.integrations.dedupe", + "sentry_sdk.integrations.atexit", + "sentry_sdk.integrations.modules", + "sentry_sdk.integrations.argv", + "sentry_sdk.integrations.logging", + "sentry_sdk.integrations.threading"] + +statement = """ +import json +import sentry_sdk.integrations as si + +integrations = [] +if hasattr(si, '_AUTO_ENABLING_INTEGRATIONS'): + # _AUTO_ENABLING_INTEGRATIONS is a list of strings with default enabled integrations + # https://github.com/getsentry/sentry-python/blob/c6b6f2086b58ffc674df5c25a600b8a615079fb5/sentry_sdk/integrations/__init__.py#L54-L66 + + def make_integration_name(integration_name: str): + return integration_name.rsplit(".", maxsplit=1)[0] + + integrations.extend(map(make_integration_name, si._AUTO_ENABLING_INTEGRATIONS)) +print(json.dumps(integrations)) +""" + +hiddenimports.extend(json.loads(exec_statement(statement))) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-setuptools_scm.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-setuptools_scm.py new file mode 100644 index 0000000..8e22d91 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-setuptools_scm.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import copy_metadata + +# Ensure `metadata of setuptools` dist is collected, to avoid run-time warning about unknown/incompatible `setuptools` +# version. +datas = copy_metadata('setuptools') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-shapely.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-shapely.py new file mode 100644 index 0000000..0a3b643 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-shapely.py @@ -0,0 +1,105 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +import os +from ctypes.util import find_library + +from PyInstaller.utils.hooks import get_package_paths +from PyInstaller.utils.hooks import is_module_satisfies +from PyInstaller import compat + +# Necessary when using the vectorized subpackage +hiddenimports = ['shapely.prepared'] + +if is_module_satisfies('shapely >= 2.0.0'): + # An import made in the `shapely.geometry_helpers` extension; both `shapely.geometry_helpers` and `shapely._geos` + # extensions were introduced in v2.0.0. + hiddenimports += ['shapely._geos'] + +pkg_base, pkg_dir = get_package_paths('shapely') + +binaries = [] +datas = [] +if compat.is_win: + geos_c_dll_found = False + + # Search conda directory if conda is active, then search standard + # directory. This is the same order of precidence used in shapely. + standard_path = os.path.join(pkg_dir, 'DLLs') + lib_paths = [standard_path, os.environ['PATH']] + if compat.is_conda: + conda_path = os.path.join(compat.base_prefix, 'Library', 'bin') + lib_paths.insert(0, conda_path) + original_path = os.environ['PATH'] + try: + os.environ['PATH'] = os.pathsep.join(lib_paths) + dll_path = find_library('geos_c') + finally: + os.environ['PATH'] = original_path + if dll_path is not None: + binaries += [(dll_path, '.')] + geos_c_dll_found = True + + # Starting with shapely 1.8.1, the DLLs shipped with PyPI wheels are stored in + # site-packages/Shapely.libs instead of sub-directory in site-packages/shapely. + if is_module_satisfies("shapely >= 1.8.1"): + lib_dir = os.path.join(pkg_base, "Shapely.libs") + if os.path.isdir(lib_dir): + # We collect DLLs as data files instead of binaries to suppress binary + # analysis, which would result in duplicates (because it collects a copy + # into the top-level directory instead of preserving the original layout). + # In addition to DLls, this also collects .load-order* file (required on + # python < 3.8), and ensures that Shapely.libs directory exists (required + # on python >= 3.8 due to os.add_dll_directory call). + datas += [ + (os.path.join(lib_dir, lib_file), 'Shapely.libs') + for lib_file in os.listdir(lib_dir) + ] + + geos_c_dll_found |= any([ + os.path.basename(lib_file).startswith("geos_c") + for lib_file, _ in datas + ]) + + if not geos_c_dll_found: + raise SystemExit( + "Error: geos_c.dll not found, required by hook-shapely.py.\n" + "Please check your installation or provide a pull request to " + "PyInstaller to update hook-shapely.py.") +elif compat.is_linux and is_module_satisfies('shapely < 1.7'): + # This duplicates the libgeos*.so* files in the build. PyInstaller will + # copy them into the root of the build by default, but shapely cannot load + # them from there in linux IF shapely was installed via a whl file. The + # whl bundles its own libgeos with a different name, something like + # libgeos_c-*.so.* but shapely tries to load libgeos_c.so if there isn't a + # ./libs directory under its package. + # + # The fix for this (https://github.com/Toblerity/Shapely/pull/485) has + # been available in shapely since version 1.7. + lib_dir = os.path.join(pkg_dir, '.libs') + dest_dir = os.path.join('shapely', '.libs') + + binaries += [(os.path.join(lib_dir, f), dest_dir) for f in os.listdir(lib_dir)] +elif compat.is_darwin and is_module_satisfies('shapely >= 1.8.1'): + # In shapely 1.8.1, the libgeos_c library bundled in macOS PyPI wheels is not + # called libgeos.1.dylib anymore, but rather has a fullly-versioned name + # (e.g., libgeos_c.1.16.0.dylib). + # Shapely fails to find such a library unless it is located in the .dylibs + # directory. So we need to ensure that the libraries are collected into + # .dylibs directory; however, this will result in duplication due to binary + # analysis of the python extensions that are linked against these libraries + # as well (as that will copy the libraries to top-level directory). + lib_dir = os.path.join(pkg_dir, '.dylibs') + dest_dir = os.path.join('shapely', '.dylibs') + + if os.path.isdir(lib_dir): + binaries += [(os.path.join(lib_dir, f), dest_dir) for f in os.listdir(lib_dir)] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-shotgun_api3.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-shotgun_api3.py new file mode 100644 index 0000000..3ccf68a --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-shotgun_api3.py @@ -0,0 +1,23 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +# Shotgun is using "six" to import these and +# PyInstaller does not seem to catch them correctly. +hiddenimports = ["xmlrpc", "xmlrpc.client"] + +# Collect the following files: +# /shotgun_api3/lib/httplib2/python2/cacerts.txt +# /shotgun_api3/lib/httplib2/python3/cacerts.txt +# /shotgun_api3/lib/certifi/cacert.pem +datas = collect_data_files("shotgun_api3") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-simplemma.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-simplemma.py new file mode 100644 index 0000000..a233c66 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-simplemma.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('simplemma') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.color.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.color.py new file mode 100644 index 0000000..d79f3fd --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.color.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import is_module_satisfies, collect_data_files, collect_submodules + +# As of scikit-image 0.21.0, we need to collect the __init__.pyi file for `lazy_loader`, as well as collect submodules +# due to lazy loading. +if is_module_satisfies("scikit-image >= 0.21.0"): + datas = collect_data_files("skimage.color", includes=["*.pyi"]) + hiddenimports = collect_submodules('skimage.color', filter=lambda name: name != 'skimage.color.tests') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.data.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.data.py new file mode 100644 index 0000000..8f59def --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.data.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import is_module_satisfies, collect_data_files, collect_submodules + +# As of scikit-image 0.20.0, we need to collect the __init__.pyi file for `lazy_loader`, as well as collect submodules +# due to lazy loading. +if is_module_satisfies('scikit-image >= 0.20.0'): + datas = collect_data_files("skimage.data", includes=["*.pyi"]) + hiddenimports = collect_submodules('skimage.data', filter=lambda name: name != 'skimage.data.tests') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.draw.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.draw.py new file mode 100644 index 0000000..e52d351 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.draw.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import is_module_satisfies, collect_data_files, collect_submodules + +# As of scikit-image 0.21.0, we need to collect the __init__.pyi file for `lazy_loader`, as well as collect submodules +# due to lazy loading. +if is_module_satisfies("scikit-image >= 0.21.0"): + datas = collect_data_files("skimage.draw", includes=["*.pyi"]) + hiddenimports = collect_submodules('skimage.draw', filter=lambda name: name != 'skimage.draw.tests') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.exposure.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.exposure.py new file mode 100644 index 0000000..e737efb --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.exposure.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import is_module_satisfies, collect_data_files, collect_submodules + +# As of scikit-image 0.21.0, we need to collect the __init__.pyi file for `lazy_loader`, as well as collect submodules +# due to lazy loading. +if is_module_satisfies("scikit-image >= 0.21.0"): + datas = collect_data_files("skimage.exposure", includes=["*.pyi"]) + hiddenimports = collect_submodules('skimage.exposure', filter=lambda name: name != 'skimage.exposure.tests') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.feature.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.feature.py new file mode 100644 index 0000000..29d376d --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.feature.py @@ -0,0 +1,26 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import is_module_satisfies, collect_data_files, collect_submodules + +# The following missing module prevents import of skimage.feature with skimage 0.17.x. +hiddenimports = ['skimage.feature._orb_descriptor_positions', ] + +# Collect the data file with ORB descriptor positions. In earlier versions of scikit-image, this file was in +# `skimage/data` directory, and it was moved to `skimage/feature` in v0.17.0. Collect if from wherever it is. +datas = collect_data_files('skimage', includes=['**/orb_descriptor_positions.txt']) + +# As of scikit-image 0.22.0, we need to collect the __init__.pyi file for `lazy_loader`, as well as collect submodules +# due to lazy loading. +if is_module_satisfies("scikit-image >= 0.22.0"): + datas += collect_data_files("skimage.feature", includes=["*.pyi"]) + hiddenimports = collect_submodules('skimage.feature', filter=lambda name: name != 'skimage.feature.tests') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.filters.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.filters.py new file mode 100644 index 0000000..e88726c --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.filters.py @@ -0,0 +1,24 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import is_module_satisfies, collect_data_files, collect_submodules + +if is_module_satisfies("scikit-image >= 0.19.0"): + # In scikit-image 0.19.x, `skimage.filters` switched to lazy module loading, so we need to collect all submodules. + hiddenimports = collect_submodules('skimage.filters', filter=lambda name: name != 'skimage.filters.tests') + + # In scikit-image 0.20.0, `lazy_loader` is used, so we need to collect `__init__.pyi` file. + if is_module_satisfies("scikit-image >= 0.20.0"): + datas = collect_data_files("skimage.filters", includes=["*.pyi"]) +elif is_module_satisfies("scikit-image >= 0.18.0"): + # The following missing module prevents import of skimage.feature with skimage 0.18.x. + hiddenimports = ['skimage.filters.rank.core_cy_3d', ] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.future.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.future.py new file mode 100644 index 0000000..41905d4 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.future.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import is_module_satisfies, collect_data_files, collect_submodules + +# As of scikit-image 0.21.0, we need to collect the __init__.pyi file for `lazy_loader`, as well as collect submodules +# due to lazy loading. +if is_module_satisfies("scikit-image >= 0.21.0"): + datas = collect_data_files("skimage.future", includes=["*.pyi"]) + hiddenimports = collect_submodules('skimage.future', filter=lambda name: name != 'skimage.future.tests') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.graph.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.graph.py new file mode 100644 index 0000000..2caffd4 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.graph.py @@ -0,0 +1,22 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import is_module_satisfies, collect_data_files, collect_submodules + +# The following missing module prevents import of skimage.graph with skimage 0.17.x. +hiddenimports = ['skimage.graph.heap', ] + +# As of scikit-image 0.22.0, we need to collect the __init__.pyi file for `lazy_loader`, as well as collect submodules +# due to lazy loading. +if is_module_satisfies("scikit-image >= 0.22.0"): + datas = collect_data_files("skimage.graph", includes=["*.pyi"]) + hiddenimports = collect_submodules('skimage.graph', filter=lambda name: name != 'skimage.graph.tests') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.io.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.io.py new file mode 100644 index 0000000..45d6663 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.io.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# This hook was tested with scikit-image (skimage) 0.14.1: +# https://scikit-image.org + +from PyInstaller.utils.hooks import collect_data_files, collect_submodules + +datas = collect_data_files("skimage.io._plugins") +hiddenimports = collect_submodules('skimage.io._plugins') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.measure.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.measure.py new file mode 100644 index 0000000..1cdaa2c --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.measure.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import is_module_satisfies, collect_data_files, collect_submodules + +# As of scikit-image 0.22.0, we need to collect the __init__.pyi file for `lazy_loader`, as well as collect submodules +# due to lazy loading. +if is_module_satisfies("scikit-image >= 0.22.0"): + datas = collect_data_files("skimage.measure", includes=["*.pyi"]) + hiddenimports = collect_submodules('skimage.measure', filter=lambda name: name != 'skimage.measure.tests') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.metrics.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.metrics.py new file mode 100644 index 0000000..7d575f5 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.metrics.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import is_module_satisfies, collect_data_files, collect_submodules + +# As of scikit-image 0.23.0, we need to collect the __init__.pyi file for `lazy_loader`, as well as collect submodules +# due to lazy loading. +if is_module_satisfies("scikit-image >= 0.23.0"): + datas = collect_data_files("skimage.metrics", includes=["*.pyi"]) + hiddenimports = collect_submodules('skimage.metrics', filter=lambda name: name != 'skimage.metrics.tests') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.morphology.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.morphology.py new file mode 100644 index 0000000..dc5c6c2 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.morphology.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files, is_module_satisfies + +# As of scikit-image 0.20.0, we need to collect .npy data files for `skimage.morphology` +if is_module_satisfies('scikit-image >= 0.20'): + datas = collect_data_files("skimage.morphology", includes=["*.npy"]) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.py new file mode 100644 index 0000000..03e3ec0 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files, is_module_satisfies + +# As of scikit-image 0.20.0, we need to collect the __init__.pyi file for `lazy_loader`. +if is_module_satisfies('scikit-image >= 0.20.0'): + datas = collect_data_files("skimage", includes=["*.pyi"]) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.registration.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.registration.py new file mode 100644 index 0000000..0ffeee8 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.registration.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import is_module_satisfies, collect_data_files, collect_submodules + +# As of scikit-image 0.22.0, we need to collect the __init__.pyi file for `lazy_loader`, as well as collect submodules +# due to lazy loading. +if is_module_satisfies("scikit-image >= 0.22.0"): + datas = collect_data_files("skimage.registration", includes=["*.pyi"]) + hiddenimports = collect_submodules('skimage.registration', filter=lambda name: name != 'skimage.registration.tests') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.restoration.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.restoration.py new file mode 100644 index 0000000..a048738 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.restoration.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import is_module_satisfies, collect_data_files, collect_submodules + +# As of scikit-image 0.22.0, we need to collect the __init__.pyi file for `lazy_loader`, as well as collect submodules +# due to lazy loading. +if is_module_satisfies("scikit-image >= 0.22.0"): + datas = collect_data_files("skimage.restoration", includes=["*.pyi"]) + hiddenimports = collect_submodules('skimage.restoration', filter=lambda name: name != 'skimage.restoration.tests') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.transform.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.transform.py new file mode 100644 index 0000000..3841a4e --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skimage.transform.py @@ -0,0 +1,24 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +from PyInstaller.utils.hooks import is_module_satisfies, collect_data_files, collect_submodules + +# Hook tested with scikit-image (skimage) 0.9.3 on Mac OS 10.9 and Windows 7 64-bit +hiddenimports = ['skimage.draw.draw', + 'skimage._shared.geometry', + 'skimage._shared.transform', + 'skimage.filters.rank.core_cy'] + +# As of scikit-image 0.22.0, we need to collect the __init__.pyi file for `lazy_loader`, as well as collect submodules +# due to lazy loading. +if is_module_satisfies("scikit-image >= 0.22.0"): + datas = collect_data_files("skimage.transform", includes=["*.pyi"]) + hiddenimports += collect_submodules('skimage.transform', filter=lambda name: name != 'skimage.transform.tests') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.cluster.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.cluster.py new file mode 100644 index 0000000..a855309 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.cluster.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import is_module_satisfies + +# sklearn.cluster in scikit-learn 0.23.x has a hidden import of +# threadpoolctl +if is_module_satisfies("scikit_learn >= 0.23"): + hiddenimports = ['threadpoolctl', ] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.linear_model.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.linear_model.py new file mode 100644 index 0000000..ce5a884 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.linear_model.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import is_module_satisfies + +# sklearn.linear_model in scikit-learn 0.24.x has a hidden import of +# sklearn.utils._weight_vector +if is_module_satisfies("scikit_learn >= 0.24"): + hiddenimports = ['sklearn.utils._weight_vector', ] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.metrics.cluster.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.metrics.cluster.py new file mode 100644 index 0000000..3cbeb64 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.metrics.cluster.py @@ -0,0 +1,27 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Required by scikit-learn 0.21 +from PyInstaller.utils.hooks import is_module_satisfies + +if is_module_satisfies("scikit-learn < 0.22"): + hiddenimports = [ + 'sklearn.utils.lgamma', + 'sklearn.utils.weight_vector' + ] +else: + # lgamma was removed and weight_vector privatised in 0.22. + # https://github.com/scikit-learn/scikit-learn/commit/58be9a671b0b8fcb4b75f4ae99f4469ca33a2158#diff-dbca16040fd2b85a499ba59833b37f1785c58e52d2e89ce5cdfc7fff164bd5f3 + # https://github.com/scikit-learn/scikit-learn/commit/150e82b52bf28c88c5a8b1a10f9777d0452b3ef2 + hiddenimports = [ + 'sklearn.utils._weight_vector' + ] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.metrics.pairwise.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.metrics.pairwise.py new file mode 100644 index 0000000..188c1af --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.metrics.pairwise.py @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2022 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Required by scikit-learn 1.1.0 +from PyInstaller.utils.hooks import is_module_satisfies + +if is_module_satisfies("scikit-learn >= 1.1.0"): + hiddenimports = [ + 'sklearn.utils._heap', + 'sklearn.utils._sorting', + 'sklearn.utils._vector_sentinel', + ] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.metrics.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.metrics.py new file mode 100644 index 0000000..8bdea5f --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.metrics.py @@ -0,0 +1,25 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2022 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import is_module_satisfies, collect_submodules + +hiddenimports = [] + +# Required by scikit-learn 1.0.0 +if is_module_satisfies("scikit-learn >= 1.0.0"): + hiddenimports += [ + 'sklearn.utils._typedefs', + ] + +# Required by scikit-learn 1.2.0 +if is_module_satisfies("scikit-learn >= 1.2.0"): + hiddenimports += collect_submodules("sklearn.metrics._pairwise_distances_reduction") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.neighbors.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.neighbors.py new file mode 100644 index 0000000..937fe75 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.neighbors.py @@ -0,0 +1,41 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import is_module_satisfies + +hiddenimports = [] + +if is_module_satisfies("scikit_learn > 1.0.1"): + # 1.0.2 and later + hiddenimports += [ + 'sklearn.neighbors._quad_tree', + ] +elif is_module_satisfies("scikit_learn < 0.22 "): + # 0.21 and below + hiddenimports += [ + 'sklearn.neighbors.typedefs', + 'sklearn.neighbors.quad_tree', + ] +else: + # between and including 0.22 and 1.0.1 + hiddenimports += [ + 'sklearn.neighbors._typedefs', + 'sklearn.neighbors._quad_tree', + ] + +# The following hidden import must be added here +# (as opposed to sklearn.tree) +hiddenimports += ['sklearn.tree._criterion'] + +# Additional hidden imports introduced in v1.0.0 +if is_module_satisfies("scikit_learn >= 1.0.0"): + hiddenimports += ["sklearn.neighbors._partition_nodes"] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.py new file mode 100644 index 0000000..25724f3 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Tested on Windows 10 64bit with python 3.7.1 + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('sklearn') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.tree.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.tree.py new file mode 100644 index 0000000..9ae4d7c --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.tree.py @@ -0,0 +1,13 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +hiddenimports = ['sklearn.tree._utils', ] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.utils.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.utils.py new file mode 100644 index 0000000..945d99b --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.utils.py @@ -0,0 +1,13 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +hiddenimports = ['sklearn.utils._cython_blas', ] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skyfield.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skyfield.py new file mode 100644 index 0000000..8394b34 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-skyfield.py @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files +datas = collect_data_files('skyfield') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-slixmpp.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-slixmpp.py new file mode 100644 index 0000000..93bd8a1 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-slixmpp.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_submodules + +hiddenimports = collect_submodules("slixmpp.features") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sound_lib.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sound_lib.py new file mode 100644 index 0000000..ed290ea --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sound_lib.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +sound_lib: http://hg.q-continuum.net/sound_lib +""" + +from PyInstaller.utils.hooks import collect_dynamic_libs + +binaries = collect_dynamic_libs('sound_lib') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sounddevice.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sounddevice.py new file mode 100644 index 0000000..6316b03 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sounddevice.py @@ -0,0 +1,62 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +sounddevice: +https://github.com/spatialaudio/python-sounddevice/ +""" + +import pathlib + +from PyInstaller.utils.hooks import get_module_file_attribute, logger + +binaries = [] +datas = [] + +# PyPI wheels for Windows and macOS ship the sndfile shared library in _sounddevice_data directory, +# located next to the sounddevice.py module file (i.e., in the site-packages directory). +module_dir = pathlib.Path(get_module_file_attribute('sounddevice')).parent +data_dir = module_dir / '_sounddevice_data' / 'portaudio-binaries' +if data_dir.is_dir(): + destdir = str(data_dir.relative_to(module_dir)) + + # Collect the shared library (known variants: libportaudio64bit.dll, libportaudio32bit.dll, libportaudio.dylib) + for lib_file in data_dir.glob("libportaudio*.*"): + binaries += [(str(lib_file), destdir)] + + # Collect the README.md file + readme_file = data_dir / "README.md" + if readme_file.is_file(): + datas += [(str(readme_file), destdir)] +else: + # On linux and in Anaconda in all OSes, the system-installed portaudio library needs to be collected. + def _find_system_portaudio_library(): + import os + import ctypes.util + from PyInstaller.depend.utils import _resolveCtypesImports + + libname = ctypes.util.find_library("portaudio") + if libname is not None: + resolved_binary = _resolveCtypesImports([os.path.basename(libname)]) + if resolved_binary: + return resolved_binary[0][1] + + try: + lib_file = _find_system_portaudio_library() + except Exception as e: + logger.warning("Error while trying to find system-installed portaudio library: %s", e) + lib_file = None + + if lib_file: + binaries += [(lib_file, '.')] + +if not binaries: + logger.warning("portaudio shared library not found - sounddevice will likely fail to work!") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-soundfile.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-soundfile.py new file mode 100644 index 0000000..f788c38 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-soundfile.py @@ -0,0 +1,62 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +pysoundfile: +https://github.com/bastibe/SoundFile +""" + +import pathlib + +from PyInstaller.utils.hooks import get_module_file_attribute, logger + +binaries = [] +datas = [] + +# PyPI wheels for Windows and macOS ship the sndfile shared library in _soundfile_data directory, +# located next to the soundfile.py module file (i.e., in the site-packages directory). +module_dir = pathlib.Path(get_module_file_attribute('soundfile')).parent +data_dir = module_dir / '_soundfile_data' +if data_dir.is_dir(): + destdir = str(data_dir.relative_to(module_dir)) + + # Collect the shared library (known variants: libsndfile64bit.dll, libsndfile32bit.dll, libsndfile.dylib) + for lib_file in data_dir.glob("libsndfile*.*"): + binaries += [(str(lib_file), destdir)] + + # Collect the COPYING file + copying_file = data_dir / "COPYING" + if copying_file.is_file(): + datas += [(str(copying_file), destdir)] +else: + # On linux and in Anaconda in all OSes, the system-installed sndfile library needs to be collected. + def _find_system_sndfile_library(): + import os + import ctypes.util + from PyInstaller.depend.utils import _resolveCtypesImports + + libname = ctypes.util.find_library("sndfile") + if libname is not None: + resolved_binary = _resolveCtypesImports([os.path.basename(libname)]) + if resolved_binary: + return resolved_binary[0][1] + + try: + lib_file = _find_system_sndfile_library() + except Exception as e: + logger.warning("Error while trying to find system-installed sndfile library: %s", e) + lib_file = None + + if lib_file: + binaries += [(lib_file, '.')] + +if not binaries: + logger.warning("sndfile shared library not found - soundfile will likely fail to work!") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-spacy.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-spacy.py new file mode 100644 index 0000000..25ee44e --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-spacy.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Spacy contains hidden imports and data files which are needed to import it +""" + +from PyInstaller.utils.hooks import collect_data_files, collect_submodules + +datas = collect_data_files("spacy") +hiddenimports = collect_submodules("spacy") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-speech_recognition.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-speech_recognition.py new file mode 100644 index 0000000..fb7d179 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-speech_recognition.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for speech_recognition: https://pypi.python.org/pypi/SpeechRecognition/ +# Tested on Windows 8.1 x64 with SpeechRecognition 1.5 + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("speech_recognition") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-spiceypy.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-spiceypy.py new file mode 100644 index 0000000..3444d93 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-spiceypy.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for spiceypy: https://pypi.org/project/spiceypy/ +# Tested on Ubuntu 20.04 with spiceypy 5.1.1 + +from PyInstaller.utils.hooks import collect_dynamic_libs + +binaries = collect_dynamic_libs("spiceypy") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-spnego.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-spnego.py new file mode 100644 index 0000000..b038573 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-spnego.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_submodules + +hiddenimports = collect_submodules('spnego') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-srsly.msgpack._packer.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-srsly.msgpack._packer.py new file mode 100644 index 0000000..519cd0b --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-srsly.msgpack._packer.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +srsly.msgpack._packer contains hidden imports which are needed to import it +This hook was created to make spacy work correctly. +""" + +hiddenimports = ['srsly.msgpack.util'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sspilib.raw.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sspilib.raw.py new file mode 100644 index 0000000..7fbd239 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sspilib.raw.py @@ -0,0 +1,20 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_submodules + +# This seems to be required in python <= 3.9; in later versions, the `dataclasses` module ends up included via a +# different import chain. But for the sake of consistency, keep the hiddenimport for all python versions. +hiddenimports = ['dataclasses'] + +# Collect submodules of `sspilib.raw` - most of which are cythonized extensions. +hiddenimports += collect_submodules('sspilib.raw') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-statsmodels.tsa.statespace.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-statsmodels.tsa.statespace.py new file mode 100644 index 0000000..547d706 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-statsmodels.tsa.statespace.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_submodules + +hiddenimports = collect_submodules('statsmodels.tsa.statespace._filters') \ + + collect_submodules('statsmodels.tsa.statespace._smoothers') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-stdnum.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-stdnum.py new file mode 100644 index 0000000..068e960 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-stdnum.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2022 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Collect data files that are required by some of the stdnum's sub-modules +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("stdnum") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-storm.database.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-storm.database.py new file mode 100644 index 0000000..1cde580 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-storm.database.py @@ -0,0 +1,20 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Hook for storm ORM. +""" + +hiddenimports = [ + 'storm.databases.sqlite', + 'storm.databases.postgres', + 'storm.databases.mysql' +] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sudachipy.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sudachipy.py new file mode 100644 index 0000000..1abb48e --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sudachipy.py @@ -0,0 +1,30 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import can_import_module, collect_data_files, is_module_satisfies + +datas = collect_data_files('sudachipy') +hiddenimports = [] + +# In v0.6.8, `sudachipy.config` and `sudachipy.errors` modules were added, and are referenced from binary extension. +if is_module_satisfies('sudachipy >= 0.6.8'): + hiddenimports += [ + 'sudachipy.config', + 'sudachipy.errors', + ] + +# Check which types of dictionary are installed +for sudachi_dict in ['sudachidict_small', 'sudachidict_core', 'sudachidict_full']: + if can_import_module(sudachi_dict): + datas += collect_data_files(sudachi_dict) + + hiddenimports += [sudachi_dict] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sunpy.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sunpy.py new file mode 100644 index 0000000..4a069e4 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sunpy.py @@ -0,0 +1,20 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files, collect_submodules, copy_metadata + +hiddenimports = collect_submodules("sunpy", filter=lambda x: "tests" not in x.split(".")) +datas = collect_data_files("sunpy", excludes=['**/tests/', '**/test/']) +datas += collect_data_files("drms") +datas += copy_metadata("sunpy") + +# Note : sunpy > 3.1.0 comes with it's own hook for running tests. diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sv_ttk.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sv_ttk.py new file mode 100644 index 0000000..0f37e32 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sv_ttk.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +# Collect all files in the sv_ttk package +datas = collect_data_files(package="sv_ttk") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-swagger_spec_validator.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-swagger_spec_validator.py new file mode 100644 index 0000000..bb4b4d1 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-swagger_spec_validator.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("swagger_spec_validator") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sympy.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sympy.py new file mode 100644 index 0000000..9e8ec10 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-sympy.py @@ -0,0 +1,22 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import logger, is_module_satisfies + +# With sympy 1.12, PyInstaller's modulegraph analysis hits the recursion limit. +# So, unless the user has already done so, increase it automatically. +if is_module_satisfies('sympy >= 1.12'): + import sys + new_limit = 5000 + if sys.getrecursionlimit() < new_limit: + logger.info("hook-sympy: raising recursion limit to %d", new_limit) + sys.setrecursionlimit(new_limit) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-tableauhyperapi.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-tableauhyperapi.py new file mode 100644 index 0000000..210daef --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-tableauhyperapi.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_dynamic_libs + +binaries = collect_dynamic_libs("tableauhyperapi") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-tables.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-tables.py new file mode 100644 index 0000000..440c6a1 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-tables.py @@ -0,0 +1,30 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.compat import is_win +from PyInstaller.utils.hooks import collect_dynamic_libs, is_module_satisfies + +# PyTables is a package for managing hierarchical datasets +hiddenimports = ["tables._comp_lzo", "tables._comp_bzip2"] + +# Collect the bundled copy of blosc2 shared library. +binaries = collect_dynamic_libs('tables') +datas = [] + +# tables 3.7.0 started using `delvewheel` for its Windows PyPI wheels. While contemporary PyInstaller versions +# automatically pick up DLLs from external `pyproj.libs` directory, this does not work on Anaconda python 3.8 and 3.9 +# due to defunct `os.add_dll_directory`, which forces `delvewheel` to use the old load-order file approach. So we need +# to explicitly ensure that load-order file as well as DLLs are collected. +if is_win and is_module_satisfies("tables >= 3.7.0"): + if is_module_satisfies("PyInstaller >= 5.6"): + from PyInstaller.utils.hooks import collect_delvewheel_libs_directory + datas, binaries = collect_delvewheel_libs_directory("tables", datas=datas, binaries=binaries) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-tcod.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-tcod.py new file mode 100644 index 0000000..d5b076e --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-tcod.py @@ -0,0 +1,20 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Hook for https://github.com/libtcod/python-tcod +""" +from PyInstaller.utils.hooks import collect_dynamic_libs + +hiddenimports = ['_cffi_backend'] + +# Install shared libraries to the working directory. +binaries = collect_dynamic_libs('tcod', destdir='.') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-tensorflow.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-tensorflow.py new file mode 100644 index 0000000..25c2fd5 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-tensorflow.py @@ -0,0 +1,198 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +import sys + +from _pyinstaller_hooks_contrib.compat import importlib_metadata +from packaging.version import Version + +from PyInstaller.compat import is_linux +from PyInstaller.utils.hooks import ( + collect_data_files, + collect_dynamic_libs, + collect_submodules, + get_module_attribute, + is_module_satisfies, + logger, +) + +# Automatically raise recursion limit to ensure it is at least 5000; this attempts to mitigate recursion limit errors +# caused by some import chains that involve tensorflow, but also depend on the build environment (i.e., other packages +# installed in it). +new_limit = 5000 +if sys.getrecursionlimit() < new_limit: + logger.info("hook-tensorflow: raising recursion limit to %d", new_limit) + sys.setrecursionlimit(new_limit) + +# Determine the name of `tensorflow` dist; this is available under different names (releases vs. nightly, plus build +# variants). We need to determine the dist that we are dealing with, so we can query its version and metadata. +_CANDIDATE_DIST_NAMES = ( + "tensorflow", + "tensorflow-cpu", + "tensorflow-gpu", + "tensorflow-intel", + "tensorflow-rocm", + "tensorflow-macos", + "tensorflow-aarch64", + "tensorflow-cpu-aws", + "tf-nightly", + "tf-nightly-cpu", + "tf-nightly-gpu", + "tf-nightly-rocm", + "intel-tensorflow", + "intel-tensorflow-avx512", +) +dist = None +for candidate_dist_name in _CANDIDATE_DIST_NAMES: + try: + dist = importlib_metadata.distribution(candidate_dist_name) + break + except importlib_metadata.PackageNotFoundError: + continue + +version = None +if dist is None: + logger.warning( + "hook-tensorflow: failed to determine tensorflow dist name! Reading version from tensorflow.__version__!" + ) + try: + version = get_module_attribute("tensorflow", "__version__") + except Exception as e: + raise Exception("Failed to read tensorflow.__version__") from e +else: + logger.info("hook-tensorflow: tensorflow dist name: %s", dist.name) + version = dist.version + +# Parse version +logger.info("hook-tensorflow: tensorflow version: %s", version) +try: + version = Version(version) +except Exception as e: + raise Exception("Failed to parse tensorflow version!") from e + +# Exclude from data collection: +# - development headers in include subdirectory +# - XLA AOT runtime sources +# - libtensorflow_framework and libtensorflow_cc (since TF 2.12) shared libraries (to avoid duplication) +# - import library (.lib) files (Windows-only) +data_excludes = [ + "include", + "xla_aot_runtime_src", + "libtensorflow_framework.*", + "libtensorflow_cc.*", + "**/*.lib", +] + +# Under tensorflow 2.3.0 (the most recent version at the time of writing), _pywrap_tensorflow_internal extension module +# ends up duplicated; once as an extension, and once as a shared library. In addition to increasing program size, this +# also causes problems on macOS, so we try to prevent the extension module "variant" from being picked up. +# +# See pyinstaller/pyinstaller-hooks-contrib#49 for details. +# +# With PyInstaller >= 6.0, this issue is alleviated, because the binary dependency analysis (which picks up the +# extension in question as a shared library that other extensions are linked against) now preserves the parent directory +# layout, and creates a symbolic link to the top-level application directory. +if is_module_satisfies('PyInstaller >= 6.0'): + excluded_submodules = [] +else: + excluded_submodules = ['tensorflow.python._pywrap_tensorflow_internal'] + + +def _submodules_filter(x): + return x not in excluded_submodules + + +if version < Version("1.15.0a0"): + # 1.14.x and earlier: collect everything from tensorflow + hiddenimports = collect_submodules('tensorflow', filter=_submodules_filter) + datas = collect_data_files('tensorflow', excludes=data_excludes) +elif version >= Version("1.15.0a0") and version < Version("2.2.0a0"): + # 1.15.x - 2.1.x: collect everything from tensorflow_core + hiddenimports = collect_submodules('tensorflow_core', filter=_submodules_filter) + datas = collect_data_files('tensorflow_core', excludes=data_excludes) + + # Under 1.15.x, we seem to fail collecting a specific submodule, and need to add it manually... + if version < Version("2.0.0a0"): + hiddenimports += ['tensorflow_core._api.v1.compat.v2.summary.experimental'] +else: + # 2.2.0 and newer: collect everything from tensorflow again + hiddenimports = collect_submodules('tensorflow', filter=_submodules_filter) + datas = collect_data_files('tensorflow', excludes=data_excludes) + + # From 2.6.0 on, we also need to explicitly collect keras (due to lazy mapping of tensorflow.keras.xyz -> keras.xyz) + if version >= Version("2.6.0a0"): + hiddenimports += collect_submodules('keras') + + # Starting with 2.14.0, we need `ml_dtypes` among hidden imports. + if version >= Version("2.14.0"): + hiddenimports += ['ml_dtypes'] + +binaries = [] +excludedimports = excluded_submodules + +# Suppress warnings for missing hidden imports generated by this hook. +# Requires PyInstaller > 5.1 (with pyinstaller/pyinstaller#6914 merged); no-op otherwise. +warn_on_missing_hiddenimports = False + +# Collect the AutoGraph part of `tensorflow` code, to avoid a run-time warning about AutoGraph being unavailable: +# `WARNING:tensorflow:AutoGraph is not available in this environment: functions lack code information. ...` +# The warning is emitted if source for `log` function from `tensorflow.python.autograph.utils.ag_logging` cannot be +# looked up. Not sure if we need sources for other parts of `tesnorflow`, though. +# Requires PyInstaller >= 5.3, no-op in older versions. +module_collection_mode = { + 'tensorflow.python.autograph': 'py+pyz', +} + +# Linux builds of tensorflow can optionally use CUDA from nvidia-* packages. If we managed to obtain dist, query the +# requirements from metadata (the `and-cuda` extra marker), and convert them to module names. +# +# NOTE: while the installation of nvidia-* packages via `and-cuda` extra marker is not gated by the OS version check, +# it is effectively available only on Linux (last Windows-native build that supported GPU is v2.10.0, and assumed that +# CUDA is externally available). +if is_linux and dist is not None: + def _infer_nvidia_hiddenimports(): + import packaging.requirements + from _pyinstaller_hooks_contrib.utils import nvidia_cuda as cudautils + + requirements = [packaging.requirements.Requirement(req) for req in dist.requires or []] + env = {'extra': 'and-cuda'} + requirements = [req.name for req in requirements if req.marker is None or req.marker.evaluate(env)] + + return cudautils.infer_hiddenimports_from_requirements(requirements) + + try: + nvidia_hiddenimports = _infer_nvidia_hiddenimports() + except Exception: + # Log the exception, but make it non-fatal + logger.warning("hook-tensorflow: failed to infer NVIDIA CUDA hidden imports!", exc_info=True) + nvidia_hiddenimports = [] + logger.info("hook-tensorflow: inferred hidden imports for CUDA libraries: %r", nvidia_hiddenimports) + hiddenimports += nvidia_hiddenimports + + +# Collect the tensorflow-plugins (pluggable device plugins) +hiddenimports += ['tensorflow-plugins'] +binaries += collect_dynamic_libs('tensorflow-plugins') + +# On Linux, prevent binary dependency analysis from generating symbolic links for libtensorflow_cc.so.2, +# libtensorflow_framework.so.2, and _pywrap_tensorflow_internal.so to the top-level application directory. These +# symbolic links seem to confuse tensorflow about its location (likely because code in one of the libraries looks up the +# library file's location, but does not fully resolve it), which in turn prevents it from finding the collected CUDA +# libraries in the nvidia/cu* package directories. +# +# The `bindepend_symlink_suppression` hook attribute requires PyInstaller >= 6.11, and is no-op in earlier versions. +if is_linux: + bindepend_symlink_suppression = [ + '**/libtensorflow_cc.so*', + '**/libtensorflow_framework.so*', + '**/_pywrap_tensorflow_internal.so', + ] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-text_unidecode.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-text_unidecode.py new file mode 100644 index 0000000..68902ca --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-text_unidecode.py @@ -0,0 +1,25 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +# ----------------------------------------------------------------------------- +""" +text-unidecode: +https://github.com/kmike/text-unidecode/ +""" + +import os +from PyInstaller.utils.hooks import get_package_paths + +package_path = get_package_paths("text_unidecode") +data_bin_path = os.path.join(package_path[1], "data.bin") + +if os.path.exists(data_bin_path): + datas = [(data_bin_path, 'text_unidecode')] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-textdistance.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-textdistance.py new file mode 100644 index 0000000..4859014 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-textdistance.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for textdistance: https://pypi.org/project/textdistance/4.1.3/ + +from PyInstaller.utils.hooks import collect_all + +datas, binaries, hiddenimports = collect_all('textdistance') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-thinc.backends.numpy_ops.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-thinc.backends.numpy_ops.py new file mode 100644 index 0000000..fcb3e88 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-thinc.backends.numpy_ops.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +thinc.banckends.numpy_ops contains hidden imports which are needed to import it +This hook was created to make spacy work correctly. +""" + +hiddenimports = ['cymem.cymem', 'preshed.maps', 'blis.py'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-thinc.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-thinc.py new file mode 100644 index 0000000..7623253 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-thinc.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Thinc contains data files and hidden imports. This hook was created to make spacy work correctly. +""" +from PyInstaller.utils.hooks import collect_data_files, collect_submodules + +datas = collect_data_files("thinc") +hiddenimports = collect_submodules("thinc") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-timezonefinder.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-timezonefinder.py new file mode 100644 index 0000000..e5cd309 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-timezonefinder.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('timezonefinder') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-timm.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-timm.py new file mode 100644 index 0000000..1ff1a61 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-timm.py @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Collect source .py files for JIT/torchscript. Requires PyInstaller >= 5.3, no-op in older versions. +module_collection_mode = 'pyz+py' diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-tinycss2.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-tinycss2.py new file mode 100644 index 0000000..d06ab79 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-tinycss2.py @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Hook for tinycss2. tinycss2 is a low-level CSS parser and generator. +https://github.com/Kozea/tinycss2 +""" +from PyInstaller.utils.hooks import collect_data_files + + +# Hook no longer required for tinycss2 >= 1.0.0 +def hook(hook_api): + hook_api.add_datas(collect_data_files(hook_api.__name__)) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-toga.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-toga.py new file mode 100644 index 0000000..ab79abb --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-toga.py @@ -0,0 +1,33 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller import compat +from PyInstaller.utils.hooks import copy_metadata + +# Select the platform-specific backend. +if compat.is_darwin: + backend = 'cocoa' +elif compat.is_linux: + backend = 'gtk' +elif compat.is_win: + backend = 'winforms' +else: + backend = None + +if backend is not None: + hiddenimports = [f'toga_{backend}', f'toga_{backend}.factory'] + +# Collect metadata for toga-core dist, which is used by toga module to determine its version. +datas = copy_metadata("toga-core") + +# Prevent `toga` from pulling `setuptools_scm` into frozen application, as it makes no sense in that context. +excludedimports = ["setuptools_scm"] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-toga_cocoa.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-toga_cocoa.py new file mode 100644 index 0000000..c6142f4 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-toga_cocoa.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files, copy_metadata + +# Collect icons from `resources`. +datas = collect_data_files('toga_cocoa') + +# Collect metadata so that the backend can be discovered via `toga.backends` entry-point. +datas += copy_metadata("toga-cocoa") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-toga_gtk.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-toga_gtk.py new file mode 100644 index 0000000..2e0353e --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-toga_gtk.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files, copy_metadata + +# Collect default icon from `resources`. +datas = collect_data_files('toga_gtk') + +# Collect metadata so that the backend can be discovered via `toga.backends` entry-point. +datas += copy_metadata("toga-gtk") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-toga_winforms.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-toga_winforms.py new file mode 100644 index 0000000..adebb9a --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-toga_winforms.py @@ -0,0 +1,40 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +import os + +from PyInstaller.utils.hooks import collect_data_files, copy_metadata + +# Collect default icon from `resources`, and license/readme file from `toga_winforms/libs/WebView2`. Use the same call +# to also collect bundled WebView2 DLLs from `toga_winforms/libs/WebView2`. +include_patterns = [ + 'resources/*', + 'libs/WebView2/*.md', + 'libs/WebView2/*.dll', +] + +# The package seems to bundle WebView2 runtimes for x86, x64, and arm64. We need to collect only the one for the +# running platform, which can be reliably identified by `PROCESSOR_ARCHITECTURE` environment variable, which properly +# reflects the processor architecture of running process (even if running x86 python on x64 machine, or x64 python on +# arm64 machine). +machine = os.environ["PROCESSOR_ARCHITECTURE"].lower() +if machine == 'x86': + include_patterns += ['libs/WebView2/runtimes/win-x86/*'] +elif machine == 'amd64': + include_patterns += ['libs/WebView2/runtimes/win-x64/*'] +elif machine == 'arm64': + include_patterns += ['libs/WebView2/runtimes/win-arm64/*'] + +datas = collect_data_files('toga_winforms', includes=include_patterns) + +# Collect metadata so that the backend can be discovered via `toga.backends` entry-point. +datas += copy_metadata("toga-winforms") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-torch.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-torch.py new file mode 100644 index 0000000..5d37889 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-torch.py @@ -0,0 +1,143 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +import os + +from PyInstaller.utils.hooks import ( + logger, + collect_data_files, + is_module_satisfies, + collect_dynamic_libs, + collect_submodules, + get_package_paths, +) + +if is_module_satisfies("PyInstaller >= 6.0"): + from PyInstaller.compat import is_linux, is_win + from PyInstaller.utils.hooks import PY_DYLIB_PATTERNS + + module_collection_mode = "pyz+py" + warn_on_missing_hiddenimports = False + + datas = collect_data_files( + "torch", + excludes=[ + "**/*.h", + "**/*.hpp", + "**/*.cuh", + "**/*.lib", + "**/*.cpp", + "**/*.pyi", + "**/*.cmake", + ], + ) + hiddenimports = collect_submodules("torch") + binaries = collect_dynamic_libs( + "torch", + # Ensure we pick up fully-versioned .so files as well + search_patterns=PY_DYLIB_PATTERNS + ['*.so.*'], + ) + + # On Linux, torch wheels built with non-default CUDA version bundle CUDA libraries themselves (and should be handled + # by the above `collect_dynamic_libs`). Wheels built with default CUDA version (which are available on PyPI), on the + # other hand, use CUDA libraries provided by nvidia-* packages. Due to all possible combinations (CUDA libs from + # nvidia-* packages, torch-bundled CUDA libs, CPU-only CUDA libs) we do not add hidden imports directly, but instead + # attempt to infer them from requirements listed in the `torch` metadata. + if is_linux: + def _infer_nvidia_hiddenimports(): + import packaging.requirements + from _pyinstaller_hooks_contrib.compat import importlib_metadata + from _pyinstaller_hooks_contrib.utils import nvidia_cuda as cudautils + + dist = importlib_metadata.distribution("torch") + requirements = [packaging.requirements.Requirement(req) for req in dist.requires or []] + requirements = [req.name for req in requirements if req.marker is None or req.marker.evaluate()] + + return cudautils.infer_hiddenimports_from_requirements(requirements) + + try: + nvidia_hiddenimports = _infer_nvidia_hiddenimports() + except Exception: + # Log the exception, but make it non-fatal + logger.warning("hook-torch: failed to infer NVIDIA CUDA hidden imports!", exc_info=True) + nvidia_hiddenimports = [] + logger.info("hook-torch: inferred hidden imports for CUDA libraries: %r", nvidia_hiddenimports) + hiddenimports += nvidia_hiddenimports + + # The Windows nightly build for torch 2.3.0 added dependency on MKL. The `mkl` distribution does not provide an + # importable package, but rather installs the DLLs in /Library/bin directory. Therefore, we cannot write a + # separate hook for it, and must collect the DLLs here. (Most of these DLLs are missed by PyInstaller's binary + # dependency analysis due to being dynamically loaded at run-time). + if is_win: + def _collect_mkl_dlls(): + import packaging.requirements + from _pyinstaller_hooks_contrib.compat import importlib_metadata + + # Check if torch depends on `mkl` + dist = importlib_metadata.distribution("torch") + requirements = [packaging.requirements.Requirement(req) for req in dist.requires or []] + requirements = [req.name for req in requirements if req.marker is None or req.marker.evaluate()] + if 'mkl' not in requirements: + logger.info('hook-torch: this torch build does not depend on MKL...') + return [] # This torch build does not depend on MKL + + # Find requirements of mkl - this should yield `intel-openmp` and `tbb`, which install DLLs in the same + # way as `mkl`. + try: + dist = importlib_metadata.distribution("mkl") + except importlib_metadata.PackageNotFoundError: + return [] # For some reason, `mkl` distribution is unavailable. + requirements = [packaging.requirements.Requirement(req) for req in dist.requires or []] + requirements = [req.name for req in requirements if req.marker is None or req.marker.evaluate()] + + requirements = ['mkl'] + requirements + + mkl_binaries = [] + logger.info('hook-torch: collecting DLLs from MKL and its dependencies: %r', requirements) + for requirement in requirements: + try: + dist = importlib_metadata.distribution(requirement) + except importlib_metadata.PackageNotFoundError: + continue + + # Go over files, and match DLLs in /Library/bin directory + for dist_file in dist.files: + if not dist_file.match('../../Library/bin/*.dll'): + continue + dll_file = dist.locate_file(dist_file).resolve() + mkl_binaries.append((str(dll_file), '.')) + + logger.info( + 'hook-torch: found MKL DLLs: %r', + sorted([os.path.basename(src_name) for src_name, dest_name in mkl_binaries]) + ) + return mkl_binaries + + try: + mkl_binaries = _collect_mkl_dlls() + except Exception: + # Log the exception, but make it non-fatal + logger.warning("hook-torch: failed to collect MKL DLLs!", exc_info=True) + mkl_binaries = [] + binaries += mkl_binaries +else: + datas = [(get_package_paths("torch")[1], "torch")] + +# With torch 2.0.0, PyInstaller's modulegraph analysis hits the recursion limit. +# So, unless the user has already done so, increase it automatically. +if is_module_satisfies("torch >= 2.0.0"): + import sys + + new_limit = 5000 + if sys.getrecursionlimit() < new_limit: + logger.info("hook-torch: raising recursion limit to %d", new_limit) + sys.setrecursionlimit(new_limit) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-torchaudio.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-torchaudio.py new file mode 100644 index 0000000..57e570e --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-torchaudio.py @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_dynamic_libs, collect_submodules + +# Collect dynamic extensions from torchaudio/lib - some of them are loaded dynamically, and are thus not automatically +# collected. +binaries = collect_dynamic_libs('torchaudio') +hiddenimports = collect_submodules('torchaudio.lib') + +# Collect source .py files for JIT/torchscript. Requires PyInstaller >= 5.3, no-op in older versions. +module_collection_mode = 'pyz+py' diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-torchtext.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-torchtext.py new file mode 100644 index 0000000..5ada443 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-torchtext.py @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_dynamic_libs, collect_submodules + +# Collect dynamic extensions from torchtext/lib - some of them are loaded dynamically, and are thus not automatically +# collected. +binaries = collect_dynamic_libs('torchtext') +hiddenimports = collect_submodules('torchtext.lib') + +# Collect source .py files for JIT/torchscript. Requires PyInstaller >= 5.3, no-op in older versions. +module_collection_mode = 'pyz+py' diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-torchvision.io.image.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-torchvision.io.image.py new file mode 100644 index 0000000..ba4a894 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-torchvision.io.image.py @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# torchivison.io.image attempts to dynamically load the torchvision.image extension. +hiddenimports = ['torchvision.image'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-torchvision.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-torchvision.py new file mode 100644 index 0000000..f0ce8e4 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-torchvision.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Functions from torchvision.ops.* modules require torchvision._C extension module, which PyInstaller fails to pick up +# automatically due to indirect load. +hiddenimports = ['torchvision._C'] + +# Collect source .py files for JIT/torchscript. Requires PyInstaller >= 5.3, no-op in older versions. +module_collection_mode = 'pyz+py' diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame.py new file mode 100644 index 0000000..404221a --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame.py @@ -0,0 +1,13 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +hiddenimports = ["pkgutil"] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_client.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_client.py new file mode 100644 index 0000000..c134034 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_client.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("trame_client", subdir="module") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_code.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_code.py new file mode 100644 index 0000000..333020b --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_code.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = [*collect_data_files("trame_code", subdir="module")] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_components.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_components.py new file mode 100644 index 0000000..d49cfb4 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_components.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("trame_components", subdir="module") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_datagrid.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_datagrid.py new file mode 100644 index 0000000..601481c --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_datagrid.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("trame_datagrid", subdir="module") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_deckgl.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_deckgl.py new file mode 100644 index 0000000..091566e --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_deckgl.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("trame_deckgl", subdir="module") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_formkit.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_formkit.py new file mode 100644 index 0000000..f677965 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_formkit.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = [*collect_data_files("trame_formkit", subdir="module")] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_grid.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_grid.py new file mode 100644 index 0000000..0373131 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_grid.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = [*collect_data_files("trame_grid", subdir="module")] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_iframe.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_iframe.py new file mode 100644 index 0000000..5ee77f7 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_iframe.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("trame_iframe", subdir="module") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_keycloak.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_keycloak.py new file mode 100644 index 0000000..89413a6 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_keycloak.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("trame_keycloak", subdir="module") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_leaflet.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_leaflet.py new file mode 100644 index 0000000..9e2f295 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_leaflet.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = [*collect_data_files("trame_leaflet", subdir="module")] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_markdown.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_markdown.py new file mode 100644 index 0000000..7107379 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_markdown.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = [*collect_data_files("trame_markdown", subdir="module")] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_matplotlib.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_matplotlib.py new file mode 100644 index 0000000..63e6e66 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_matplotlib.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = [*collect_data_files("trame_matplotlib", subdir="module")] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_mesh_streamer.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_mesh_streamer.py new file mode 100644 index 0000000..b782f7a --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_mesh_streamer.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +hiddenimports = ["vtk"] +datas = collect_data_files("trame_mesh_streamer", subdir="module") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_plotly.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_plotly.py new file mode 100644 index 0000000..eaa2ecd --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_plotly.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("trame_plotly", subdir="module") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_pvui.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_pvui.py new file mode 100644 index 0000000..209cd63 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_pvui.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("trame_pvui", subdir="module") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_quasar.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_quasar.py new file mode 100644 index 0000000..3dc1c26 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_quasar.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = [*collect_data_files("trame_quasar", subdir="module")] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_rca.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_rca.py new file mode 100644 index 0000000..b9e5da9 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_rca.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("trame_rca", subdir="module") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_router.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_router.py new file mode 100644 index 0000000..a756569 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_router.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("trame_router", subdir="module") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_simput.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_simput.py new file mode 100644 index 0000000..d80a7ec --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_simput.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("trame_simput", subdir="module") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_tauri.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_tauri.py new file mode 100644 index 0000000..af47491 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_tauri.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("trame_tauri", subdir="module") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_tweakpane.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_tweakpane.py new file mode 100644 index 0000000..81c9190 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_tweakpane.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = [*collect_data_files("trame_tweakpane", subdir="module")] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_vega.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_vega.py new file mode 100644 index 0000000..fe157d2 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_vega.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("trame_vega", subdir="module") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_vtk.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_vtk.py new file mode 100644 index 0000000..865cbd9 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_vtk.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = [ + *collect_data_files("trame_vtk", subdir="modules"), + *collect_data_files("trame_vtk", subdir="tools"), +] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_vtk3d.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_vtk3d.py new file mode 100644 index 0000000..1c85729 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_vtk3d.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("trame_vtk3d", subdir="module") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_vtklocal.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_vtklocal.py new file mode 100644 index 0000000..288e1e8 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_vtklocal.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +hiddenimports = ["vtk"] +datas = collect_data_files("trame_vtklocal", subdir="module") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_vuetify.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_vuetify.py new file mode 100644 index 0000000..4ea24fc --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_vuetify.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("trame_vuetify", subdir="module") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_xterm.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_xterm.py new file mode 100644 index 0000000..39c3a72 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trame_xterm.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("trame_xterm", subdir="module") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-transformers.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-transformers.py new file mode 100644 index 0000000..936733b --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-transformers.py @@ -0,0 +1,37 @@ +from PyInstaller.utils.hooks import ( + copy_metadata, + get_module_attribute, + is_module_satisfies, + logger, +) + +datas = [] + +# At run-time, `transformers` queries the metadata of several packages to check for their presence. The list of required +# (core) packages is stored as `transformers.dependency_versions_check.pkgs_to_check_at_runtime˙. However, there is more +# comprehensive list of dependencies and their versions available in `transformers.dependency_versions_table.deps`, +# which includes non-core dependencies. Unfortunately, we cannot foresee which of those the user will actually require, +# so we collect metadata for all listed dists that are available in the build environment, in order to make them visible +# to `transformers` at run-time. +try: + dependencies = get_module_attribute( + 'transformers.dependency_versions_table', + 'deps', + ) +except Exception: + logger.warning( + "hook-transformers: failed to query dependency table (transformers.dependency_versions_table.deps)!", + exc_info=True, + ) + dependencies = {} + +for dependency_name, dependency_req in dependencies.items(): + if not is_module_satisfies(dependency_req): + continue + try: + datas += copy_metadata(dependency_name) + except Exception: + pass + +# Collect source .py files for JIT/torchscript. Requires PyInstaller >= 5.3, no-op in older versions. +module_collection_mode = 'pyz+py' diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-travertino.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-travertino.py new file mode 100644 index 0000000..68116a1 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-travertino.py @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Prevent this package from pulling `setuptools_scm` into frozen application, as it makes no sense in that context. +excludedimports = ["setuptools_scm"] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trimesh.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trimesh.py new file mode 100644 index 0000000..90ebfda --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-trimesh.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +# Collect the *.json resource file. +# This issue is reported in here: https://github.com/mikedh/trimesh/issues/412 +datas = collect_data_files('trimesh') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-triton.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-triton.py new file mode 100644 index 0000000..f36315f --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-triton.py @@ -0,0 +1,32 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# --------------------------------------------------- + +from PyInstaller.utils.hooks import collect_data_files, collect_dynamic_libs + +# Ensure that triton/_C/libtriton.so is collected +binaries = collect_dynamic_libs('triton') + +# triton has a JIT module that requires its source .py files. For some god-forsaken reason, this JIT module +# (`triton.runtime.jit` attempts to directly read the contents of file pointed to by its `__file__` attribute (assuming +# it is a source file). Therefore, `triton.runtime.jit` must not be collected into PYZ. Same goes for `compiler` and +# `language` sub-packages. +module_collection_mode = { + 'triton': 'pyz+py', + 'triton.runtime.jit': 'py', + 'triton.compiler': 'py', + 'triton.language': 'py', +} + +# Collect ptxas compiler files from triton/third_party/cuda directory. Strictly speaking, the ptxas executable from bin +# directory should be collected as a binary, but in this case, it makes no difference (plus, PyInstaller >= 6.0 has +# automatic binary-vs-data reclassification). +datas = collect_data_files('triton.third_party.cuda') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-ttkthemes.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-ttkthemes.py new file mode 100644 index 0000000..87c731b --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-ttkthemes.py @@ -0,0 +1,56 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Hook for use with the ttkthemes package + +ttkthemes depends on a large set of image and Tcl-code files contained +within its package directory. These are not imported, and thus this hook +is required so they are copied. + +The file structure of the ttkthemes package folder is: +ttkthemes +├───advanced +| └───*.tcl +├───themes +| ├───theme1 +| | ├───theme1 +| | | └───*.gif +| | └───theme1.tcl +| ├───theme2 +| ├───... +| └───pkgIndex.tcl +├───png +└───gif + +The ``themes`` directory contains themes which only have a universal +image version (either base64 encoded in the theme files or GIF), while +``png`` and ``gif`` contain the PNG and GIF versions of the themes which +support both respectively. + +All of this must be copied, as the package expects all the data to be +present and only checks what themes to load at runtime. + +Tested hook on Linux (Ubuntu 18.04, Python 3.6 minimal venv) and on +Windows 7 (Python 3.7, minimal system-wide installation). + +>>> from tkinter import ttk +>>> from ttkthemes import ThemedTk +>>> +>>> +>>> if __name__ == '__main__': +>>> window = ThemedTk(theme="plastik") +>>> ttk.Button(window, text="Quit", command=window.destroy).pack() +>>> window.mainloop() +""" +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("ttkthemes") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-ttkwidgets.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-ttkwidgets.py new file mode 100644 index 0000000..94c65e3 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-ttkwidgets.py @@ -0,0 +1,38 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Hook for use with the ttkwidgets package + +ttkwidgets provides a set of cross-platform widgets for Tkinter/ttk, +some of which depend on image files in order to function properly. + +These images files are all provided in the `ttkwidgets/assets` folder, +which has to be copied by PyInstaller. + +This hook has been tested on Ubuntu 18.04 (Python 3.6.8 venv) and +Windows 7 (Python 3.5.4 system-wide). + +>>> import tkinter as tk +>>> from ttkwidgets import CheckboxTreeview +>>> +>>> window = tk.Tk() +>>> tree = CheckboxTreeview(window) +>>> tree.insert("", tk.END, "test", text="Hello World!") +>>> tree.insert("test", tk.END, "test2", text="Hello World again!") +>>> tree.insert("test", tk.END, "test3", text="Hello World again again!") +>>> tree.pack() +>>> window.mainloop() +""" + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files("ttkwidgets") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-tzdata.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-tzdata.py new file mode 100644 index 0000000..2f540db --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-tzdata.py @@ -0,0 +1,22 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files, collect_submodules + +# Collect timezone data files +datas = collect_data_files("tzdata") + +# Collect submodules; each data subdirectory is in fact a package +# (e.g., zoneinfo.Europe), so we need its __init__.py for data files +# (e.g., zoneinfo/Europe/Ljubljana) to be discoverable via +# importlib.resources +hiddenimports = collect_submodules("tzdata") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-tzwhere.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-tzwhere.py new file mode 100644 index 0000000..5c583af --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-tzwhere.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('tzwhere') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-u1db.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-u1db.py new file mode 100644 index 0000000..ddd32c9 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-u1db.py @@ -0,0 +1,31 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Pyinstaller hook for u1db module + +This hook was tested with: +- u1db 0.1.4 : https://launchpad.net/u1db +- Python 2.7.10 +- Linux Debian GNU/Linux unstable (sid) + +Test script used for testing: + + import u1db + db = u1db.open("mydb1.u1db", create=True) + doc = db.create_doc({"key": "value"}, doc_id="testdoc") + print doc.content + print doc.doc_id +""" + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('u1db') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-ultralytics.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-ultralytics.py new file mode 100644 index 0000000..c49eac3 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-ultralytics.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +# Collect config .yaml files from ultralytics/cfg directory. +datas = collect_data_files('ultralytics') + +# Collect source .py files for JIT/torchscript. Requires PyInstaller >= 5.3, no-op in older versions. +module_collection_mode = 'pyz+py' diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-umap.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-umap.py new file mode 100644 index 0000000..5ae0d4d --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-umap.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import copy_metadata + +datas = copy_metadata('umap-learn') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-unidecode.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-unidecode.py new file mode 100644 index 0000000..a51d89d --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-unidecode.py @@ -0,0 +1,20 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for the unidecode package: https://pypi.python.org/pypi/unidecode +# Tested with Unidecode 0.4.21 and Python 3.6.2, on Windows 10 x64. + +from PyInstaller.utils.hooks import collect_submodules + +# Unidecode dynamically imports modules with relevant character mappings. +# Non-ASCII characters are ignored if the mapping files are not found. +hiddenimports = collect_submodules('unidecode') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-uniseg.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-uniseg.py new file mode 100644 index 0000000..af28f0f --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-uniseg.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for the uniseg module: https://pypi.python.org/pypi/uniseg + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('uniseg') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-usb.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-usb.py new file mode 100644 index 0000000..2171c85 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-usb.py @@ -0,0 +1,87 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +import ctypes.util +import os + +from PyInstaller.depend.utils import _resolveCtypesImports +from PyInstaller.compat import is_cygwin, getenv +from PyInstaller.utils.hooks import logger + +# Include glob for library lookup in run-time hook. +hiddenimports = ['glob'] + +# https://github.com/walac/pyusb/blob/master/docs/faq.rst +# https://github.com/walac/pyusb/blob/master/docs/tutorial.rst + +binaries = [] + +# Running usb.core.find() in this script crashes Ubuntu 14.04LTS, +# let users circumvent pyusb discovery with an environment variable. +skip_pyusb_discovery = \ + bool(getenv('PYINSTALLER_USB_HOOK_SKIP_PYUSB_DISCOVERY')) + +# Try to use pyusb's library locator. +if not skip_pyusb_discovery: + import usb.core + import usb.backend + try: + # get the backend symbols before find + backend_contents_before_discovery = set(dir(usb.backend)) + # perform find, which will load a usb library if found + usb.core.find() + # get the backend symbols which have been added (loaded) + backends = set(dir(usb.backend)) - backend_contents_before_discovery + # gather the libraries from the loaded backends + backend_lib_basenames = [] + for usblib in [getattr(usb.backend, be)._lib for be in backends]: + if usblib is not None: + # OSX returns the full path, Linux only the filename. + # save the basename and reconstruct the path after gathering. + backend_lib_basenames.append(os.path.basename(usblib._name)) + # try to resolve the library names to absolute paths. + binaries = _resolveCtypesImports(backend_lib_basenames) + except (ValueError, usb.core.USBError) as exc: + logger.warning("%s", exc) + +# If pyusb didn't find a backend, manually search for usb libraries. +if not binaries: + # NOTE: Update these lists when adding further libs. + if is_cygwin: + libusb_candidates = ['cygusb-1.0-0.dll', 'cygusb0.dll'] + else: + libusb_candidates = [ + # libusb10 + 'usb-1.0', + 'usb', + 'libusb-1.0', + # libusb01 + 'usb-0.1', + 'libusb0', + # openusb + 'openusb', + ] + + backend_library_basenames = [] + for candidate in libusb_candidates: + libname = ctypes.util.find_library(candidate) + if libname is not None: + backend_library_basenames.append(os.path.basename(libname)) + if backend_library_basenames: + binaries = _resolveCtypesImports(backend_library_basenames) + +# Validate and normalize the first found usb library. +if binaries: + # `_resolveCtypesImports` returns a 3-tuple, but `binaries` are only + # 2-tuples, so remove the last element: + assert len(binaries[0]) == 3 + binaries = [(binaries[0][1], '.')] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-uvicorn.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-uvicorn.py new file mode 100644 index 0000000..0acdd3c --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-uvicorn.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_submodules + +hiddenimports = collect_submodules('uvicorn') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-uvloop.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-uvloop.py new file mode 100644 index 0000000..4c4280c --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-uvloop.py @@ -0,0 +1,19 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +# +# Hook for the uvloop package: https://pypi.python.org/pypi/uvloop +# +# Tested with uvloop 0.8.1 and Python 3.6.2, on Ubuntu 16.04.1 64bit. + +from PyInstaller.utils.hooks import collect_submodules + +hiddenimports = collect_submodules('uvloop') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-vaderSentiment.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-vaderSentiment.py new file mode 100644 index 0000000..0879fff --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-vaderSentiment.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('vaderSentiment') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-vtkpython.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-vtkpython.py new file mode 100644 index 0000000..76c1e60 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-vtkpython.py @@ -0,0 +1,25 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +import os +if os.name == 'posix': + hiddenimports = [ + 'libvtkCommonPython', 'libvtkFilteringPython', 'libvtkIOPython', + 'libvtkImagingPython', 'libvtkGraphicsPython', 'libvtkRenderingPython', + 'libvtkHybridPython', 'libvtkParallelPython', 'libvtkPatentedPython' + ] +else: + hiddenimports = [ + 'vtkCommonPython', 'vtkFilteringPython', 'vtkIOPython', + 'vtkImagingPython', 'vtkGraphicsPython', 'vtkRenderingPython', + 'vtkHybridPython', 'vtkParallelPython', 'vtkPatentedPython' + ] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-wavefile.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-wavefile.py new file mode 100644 index 0000000..11dc973 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-wavefile.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +python-wavefile: https://github.com/vokimon/python-wavefile +""" + +from PyInstaller.utils.hooks import collect_dynamic_libs + +binaries = collect_dynamic_libs('wavefile') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-weasyprint.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-weasyprint.py new file mode 100644 index 0000000..e0814ea --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-weasyprint.py @@ -0,0 +1,85 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for weasyprint: https://pypi.python.org/pypi/WeasyPrint +# Tested on version weasyprint 54.0 using Windows 10 and python 3.8 +# Note that weasyprint < 54.0 does not work on python 3.8 due to https://github.com/Kozea/WeasyPrint/issues/1435 +# For weasyprint < 53.0 the required libs are +# libs = [ +# 'gobject-2.0', 'libgobject-2.0-0', 'libgobject-2.0.so.0', 'libgobject-2.0.dylib', +# 'pango-1.0', 'libpango-1.0-0', 'libpango-1.0.so.0', 'libpango-1.0.dylib', +# 'pangocairo-1.0', 'libpangocairo-1.0-0', 'libpangocairo-1.0.so.0', 'libpangocairo-1.0.dylib', +# 'fontconfig', 'libfontconfig', 'libfontconfig-1.dll', 'libfontconfig.so.1', 'libfontconfig-1.dylib', +# 'pangoft2-1.0', 'libpangoft2-1.0-0', 'libpangoft2-1.0.so.0', 'libpangoft2-1.0.dylib' +# ] + +import ctypes.util +import os +from pathlib import Path + +from PyInstaller.compat import is_win +from PyInstaller.depend.utils import _resolveCtypesImports +from PyInstaller.utils.hooks import collect_data_files, logger + +datas = collect_data_files('weasyprint') +binaries = [] +fontconfig_config_dir_found = False + +# On Windows, a GTK3-installation provides fontconfig and the corresponding fontconfig conf files. We have to add these +# for weasyprint to correctly use fonts. +# NOTE: Update these lists if weasyprint requires more libraries +fontconfig_libs = [ + 'fontconfig-1', 'fontconfig', 'libfontconfig', 'libfontconfig-1.dll', 'libfontconfig.so.1', 'libfontconfig-1.dylib' +] +libs = [ + 'gobject-2.0-0', 'gobject-2.0', 'libgobject-2.0-0', 'libgobject-2.0.so.0', 'libgobject-2.0.dylib', + 'pango-1.0-0', 'pango-1.0', 'libpango-1.0-0', 'libpango-1.0.so.0', 'libpango-1.0.dylib', + 'harfbuzz', 'harfbuzz-0.0', 'libharfbuzz-0', 'libharfbuzz.so.0', 'libharfbuzz.so.0', 'libharfbuzz.0.dylib', + 'pangoft2-1.0-0', 'pangoft2-1.0', 'libpangoft2-1.0-0', 'libpangoft2-1.0.so.0', 'libpangoft2-1.0.dylib' +] + +try: + lib_basenames = [] + for lib in libs: + libname = ctypes.util.find_library(lib) + if libname is not None: + lib_basenames += [os.path.basename(libname)] + for lib in fontconfig_libs: + libname = ctypes.util.find_library(lib) + if libname is not None: + lib_basenames += [os.path.basename(libname)] + # Try to load fontconfig config files on Windows from a GTK-installation + if is_win: + fontconfig_config_dir = Path(libname).parent.parent / 'etc/fonts' + if fontconfig_config_dir.exists() and fontconfig_config_dir.is_dir(): + datas += [(str(fontconfig_config_dir), 'etc/fonts')] + fontconfig_config_dir_found = True + if lib_basenames: + resolved_libs = _resolveCtypesImports(lib_basenames) + for resolved_lib in resolved_libs: + binaries.append((resolved_lib[1], '.')) + # Try to load fontconfig config files on other OS + fontconfig_config_dir = Path('/etc/fonts') + if fontconfig_config_dir.exists() and fontconfig_config_dir.is_dir(): + datas += [(str(fontconfig_config_dir), 'etc/fonts')] + fontconfig_config_dir_found = True + +except Exception as e: + logger.warning('Error while trying to find system-installed depending libraries: %s', e) + +if not binaries: + logger.warning('Depending libraries not found - weasyprint will likely fail to work!') + +if not fontconfig_config_dir_found: + logger.warning( + 'Fontconfig configuration files not found - weasyprint will likely throw warnings and use default fonts!' + ) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-web3.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-web3.py new file mode 100644 index 0000000..bc5c97e --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-web3.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import copy_metadata + +datas = copy_metadata("web3") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-webassets.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-webassets.py new file mode 100644 index 0000000..8a4b983 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-webassets.py @@ -0,0 +1,14 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('webassets', include_py_files=True) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-webrtcvad.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-webrtcvad.py new file mode 100644 index 0000000..853ead1 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-webrtcvad.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import copy_metadata + +datas = copy_metadata('webrtcvad') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-websockets.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-websockets.py new file mode 100644 index 0000000..84e0ec2 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-websockets.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_submodules + +# Websockets lazily loads its submodules. +hiddenimports = collect_submodules("websockets") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-webview.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-webview.py new file mode 100644 index 0000000..e465a66 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-webview.py @@ -0,0 +1,20 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# hook for https://github.com/r0x0r/pywebview + +from PyInstaller.utils.hooks import collect_data_files, collect_dynamic_libs +from PyInstaller.compat import is_win + +if is_win: + datas = collect_data_files('webview', subdir='lib') + binaries = collect_dynamic_libs('webview') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-win32com.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-win32com.py new file mode 100644 index 0000000..346d133 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-win32com.py @@ -0,0 +1,20 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +hiddenimports = [ + # win32com client and server util + # modules could be hidden imports + # of some modules using win32com. + # Included for completeness. + 'win32com.client.util', + 'win32com.server.util', +] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-wordcloud.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-wordcloud.py new file mode 100644 index 0000000..831a3f6 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-wordcloud.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('wordcloud') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-workflow.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-workflow.py new file mode 100644 index 0000000..43de8d7 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-workflow.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import copy_metadata + +datas = copy_metadata('workflow') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-wx.lib.activex.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-wx.lib.activex.py new file mode 100644 index 0000000..1ca9cf9 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-wx.lib.activex.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import exec_statement + +# This needed because comtypes wx.lib.activex generates some stuff. +exec_statement("import wx.lib.activex") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-wx.lib.pubsub.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-wx.lib.pubsub.py new file mode 100644 index 0000000..c95f591 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-wx.lib.pubsub.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('wx.lib.pubsub', include_py_files=True, excludes=['*.txt', '**/__pycache__']) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-wx.xrc.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-wx.xrc.py new file mode 100644 index 0000000..10c86a3 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-wx.xrc.py @@ -0,0 +1,13 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +hiddenimports = ['wx._xml', 'wx'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-xarray.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-xarray.py new file mode 100644 index 0000000..79a1da5 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-xarray.py @@ -0,0 +1,30 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import copy_metadata, collect_entry_point + +datas = [] +hiddenimports = [] + +# Collect additional backend plugins that are registered via `xarray.backends` entry-point. +ep_datas, ep_hiddenimports = collect_entry_point('xarray.backends') +datas += ep_datas +hiddenimports += ep_hiddenimports + +# Similarly, collect chunk manager entry-points. +ep_datas, ep_hiddenimports = collect_entry_point('xarray.chunkmanagers') +datas += ep_datas +hiddenimports += ep_hiddenimports + +# `xarray` requires `numpy` metadata due to several calls to its `xarray.core.utils.module_available` with specified +# `minversion` argument, which end up calling `importlib.metadata.version`. +datas += copy_metadata('numpy') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-xml.dom.html.HTMLDocument.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-xml.dom.html.HTMLDocument.py new file mode 100644 index 0000000..97c7f4d --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-xml.dom.html.HTMLDocument.py @@ -0,0 +1,67 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# xml.dom.html.HTMLDocument +hiddenimports = ['xml.dom.html.HTMLAnchorElement', + 'xml.dom.html.HTMLAppletElement', + 'xml.dom.html.HTMLAreaElement', + 'xml.dom.html.HTMLBaseElement', + 'xml.dom.html.HTMLBaseFontElement', + 'xml.dom.html.HTMLBodyElement', + 'xml.dom.html.HTMLBRElement', + 'xml.dom.html.HTMLButtonElement', + 'xml.dom.html.HTMLDirectoryElement', + 'xml.dom.html.HTMLDivElement', + 'xml.dom.html.HTMLDListElement', + 'xml.dom.html.HTMLElement', + 'xml.dom.html.HTMLFieldSetElement', + 'xml.dom.html.HTMLFontElement', + 'xml.dom.html.HTMLFormElement', + 'xml.dom.html.HTMLFrameElement', + 'xml.dom.html.HTMLFrameSetElement', + 'xml.dom.html.HTMLHeadElement', + 'xml.dom.html.HTMLHeadingElement', + 'xml.dom.html.HTMLHRElement', + 'xml.dom.html.HTMLHtmlElement', + 'xml.dom.html.HTMLIFrameElement', + 'xml.dom.html.HTMLImageElement', + 'xml.dom.html.HTMLInputElement', + 'xml.dom.html.HTMLIsIndexElement', + 'xml.dom.html.HTMLLabelElement', + 'xml.dom.html.HTMLLegendElement', + 'xml.dom.html.HTMLLIElement', + 'xml.dom.html.HTMLLinkElement', + 'xml.dom.html.HTMLMapElement', + 'xml.dom.html.HTMLMenuElement', + 'xml.dom.html.HTMLMetaElement', + 'xml.dom.html.HTMLModElement', + 'xml.dom.html.HTMLObjectElement', + 'xml.dom.html.HTMLOListElement', + 'xml.dom.html.HTMLOptGroupElement', + 'xml.dom.html.HTMLOptionElement', + 'xml.dom.html.HTMLParagraphElement', + 'xml.dom.html.HTMLParamElement', + 'xml.dom.html.HTMLPreElement', + 'xml.dom.html.HTMLQuoteElement', + 'xml.dom.html.HTMLScriptElement', + 'xml.dom.html.HTMLSelectElement', + 'xml.dom.html.HTMLStyleElement', + 'xml.dom.html.HTMLTableCaptionElement', + 'xml.dom.html.HTMLTableCellElement', + 'xml.dom.html.HTMLTableColElement', + 'xml.dom.html.HTMLTableElement', + 'xml.dom.html.HTMLTableRowElement', + 'xml.dom.html.HTMLTableSectionElement', + 'xml.dom.html.HTMLTextAreaElement', + 'xml.dom.html.HTMLTitleElement', + 'xml.dom.html.HTMLUListElement', + ] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-xml.sax.saxexts.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-xml.sax.saxexts.py new file mode 100644 index 0000000..5be293b --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-xml.sax.saxexts.py @@ -0,0 +1,25 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# xml.sax.saxexts +hiddenimports = ["xml.sax.drivers2.drv_pyexpat", + "xml.sax.drivers.drv_xmltok", + 'xml.sax.drivers2.drv_xmlproc', + "xml.sax.drivers.drv_xmltoolkit", + "xml.sax.drivers.drv_xmllib", + "xml.sax.drivers.drv_xmldc", + 'xml.sax.drivers.drv_pyexpat', + 'xml.sax.drivers.drv_xmlproc_val', + 'xml.sax.drivers.drv_htmllib', + 'xml.sax.drivers.drv_sgmlop', + "xml.sax.drivers.drv_sgmllib", + ] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-xmldiff.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-xmldiff.py new file mode 100644 index 0000000..eb2b966 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-xmldiff.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +# Hook for https://github.com/Shoobx/xmldiff + +from PyInstaller.utils.hooks import copy_metadata + +datas = copy_metadata('xmldiff') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-xmlschema.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-xmlschema.py new file mode 100644 index 0000000..05a777c --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-xmlschema.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# hook for https://github.com/sissaschool/xmlschema +from PyInstaller.utils.hooks import collect_data_files + +# the library contains a bunch of XSD schemas which are loaded in run time +datas = collect_data_files("xmlschema") diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-xsge_gui.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-xsge_gui.py new file mode 100644 index 0000000..068781e --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-xsge_gui.py @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for the xsge_gui module: https://pypi.python.org/pypi/xsge_gui + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('xsge_gui') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-xyzservices.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-xyzservices.py new file mode 100644 index 0000000..d7b0ecf --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-xyzservices.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('xyzservices') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-yapf_third_party.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-yapf_third_party.py new file mode 100644 index 0000000..d138c53 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-yapf_third_party.py @@ -0,0 +1,15 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +datas = collect_data_files('yapf_third_party') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-z3c.rml.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-z3c.rml.py new file mode 100644 index 0000000..658e44f --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-z3c.rml.py @@ -0,0 +1,25 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.utils.hooks import collect_data_files + +# `z3c.rml` uses Bitstream Vera TTF fonts from the `reportlab` package. As that package can be used without the bundled +# fonts and as some of the bundled fonts have restrictive license (e.g., DarkGarden), we collect the required subset +# of fonts here, instead of collecting them all in a hook for `reportlab`. +datas = collect_data_files( + "reportlab", + includes=[ + "fonts/00readme.txt", + "fonts/bitstream-vera-license.txt", + "fonts/Vera*.ttf", + ], +) diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-zeep.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-zeep.py new file mode 100644 index 0000000..002e106 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-zeep.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +# Hook for the zeep module: https://pypi.python.org/pypi/zeep +# Tested with zeep 0.13.0, Python 2.7, Windows + +from PyInstaller.utils.hooks import copy_metadata + +datas = copy_metadata('zeep') diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-zmq.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-zmq.py new file mode 100644 index 0000000..5a9f833 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-zmq.py @@ -0,0 +1,63 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2020 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +""" +Hook for PyZMQ. Cython based Python bindings for messaging library ZeroMQ. +http://www.zeromq.org/ +""" +import os +import glob +from PyInstaller.utils.hooks import collect_submodules +from PyInstaller.utils.hooks import is_module_satisfies, get_module_file_attribute +from PyInstaller.compat import is_win + +binaries = [] +datas = [] +hiddenimports = ['zmq.utils.garbage'] + +# PyZMQ comes with two backends, cython and cffi. Calling collect_submodules() +# on zmq.backend seems to trigger attempt at compilation of C extension +# module for cffi backend, which will fail if ZeroMQ development files +# are not installed on the system. On non-English locales, the resulting +# localized error messages may cause UnicodeDecodeError. Collecting each +# backend individually, however, does not seem to cause any problems. +hiddenimports += ['zmq.backend'] + +# cython backend +hiddenimports += collect_submodules('zmq.backend.cython') + +# cffi backend: contains extra data that needs to be collected +# (e.g., _cdefs.h) +# +# NOTE: the cffi backend requires compilation of C extension at runtime, +# which appears to be broken in frozen program. So avoid collecting +# it altogether... +if False: + from PyInstaller.utils.hooks import collect_data_files + + hiddenimports += collect_submodules('zmq.backend.cffi') + datas += collect_data_files('zmq.backend.cffi', excludes=['**/__pycache__', ]) + +# Starting with pyzmq 22.0.0, the DLLs in Windows wheel are located in +# site-packages/pyzmq.libs directory along with a .load_order file. This +# file is required on python 3.7 and earlier. On later versions of python, +# the pyzmq.libs is required to exist. +if is_win and is_module_satisfies('pyzmq >= 22.0.0'): + zmq_root = os.path.dirname(get_module_file_attribute('zmq')) + libs_dir = os.path.join(zmq_root, os.path.pardir, 'pyzmq.libs') + # .load_order file (22.0.3 replaced underscore with dash and added + # version suffix on this file, hence the glob) + load_order_file = glob.glob(os.path.join(libs_dir, '.load*')) + datas += [(filename, 'pyzmq.libs') for filename in load_order_file] + # We need to collect DLLs into _MEIPASS, to avoid duplication due to + # subsequent binary analysis + dll_files = glob.glob(os.path.join(libs_dir, "*.dll")) + binaries += [(dll_file, '.') for dll_file in dll_files] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-zoneinfo.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-zoneinfo.py new file mode 100644 index 0000000..03a5e41 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/stdhooks/hook-zoneinfo.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2021 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +from PyInstaller.compat import is_win + +# On Windows, timezone data is provided by the tzdata package that is +# not directly loaded. +if is_win: + hiddenimports = ['tzdata'] diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/utils/__init__.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/utils/__init__.py new file mode 100644 index 0000000..792d600 --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/utils/__init__.py @@ -0,0 +1 @@ +# diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/utils/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/utils/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..a81a891 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/utils/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/utils/__pycache__/nvidia_cuda.cpython-311.pyc b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/utils/__pycache__/nvidia_cuda.cpython-311.pyc new file mode 100644 index 0000000..aada860 Binary files /dev/null and b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/utils/__pycache__/nvidia_cuda.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/_pyinstaller_hooks_contrib/utils/nvidia_cuda.py b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/utils/nvidia_cuda.py new file mode 100644 index 0000000..b93064a --- /dev/null +++ b/venv/Lib/site-packages/_pyinstaller_hooks_contrib/utils/nvidia_cuda.py @@ -0,0 +1,77 @@ +# ------------------------------------------------------------------ +# Copyright (c) 2023 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ + +import os +import re + +from PyInstaller import compat +from PyInstaller.utils.hooks import ( + logger, + is_module_satisfies, +) + + +# Helper for collecting shared libraries from NVIDIA CUDA packages on linux. +def collect_nvidia_cuda_binaries(hook_file): + # Find the module underlying this nvidia.something hook; i.e., change ``/path/to/hook-nvidia.something.py`` to + # ``nvidia.something``. + hook_name, hook_ext = os.path.splitext(os.path.basename(hook_file)) + assert hook_ext.startswith('.py') + assert hook_name.startswith('hook-') + module_name = hook_name[5:] + + # `search_patterns` was added to `collect_dynamic_libs` in PyInstaller 5.8, so that is the minimum required version. + binaries = [] + if is_module_satisfies('PyInstaller >= 5.8'): + from PyInstaller.utils.hooks import collect_dynamic_libs, PY_DYLIB_PATTERNS + binaries = collect_dynamic_libs( + module_name, + # Collect fully-versioned .so files (not included in default search patterns). + search_patterns=PY_DYLIB_PATTERNS + ["lib*.so.*"], + ) + else: + logger.warning("hook-%s: this hook requires PyInstaller >= 5.8!", module_name) + + return binaries + + +# Helper to turn list of requirements (e.g., ['nvidia-cublas-cu12', 'nvidia-nccl-cu12', 'nvidia-cudnn-cu12']) into +# list of corresponding nvidia.* module names (e.g., ['nvidia.cublas', 'nvidia.nccl', 'nvidia-cudnn']), while ignoring +# unrecognized requirements. Intended for use in hooks for frameworks, such as `torch` and `tensorflow`. +def infer_hiddenimports_from_requirements(requirements): + # All nvidia-* packages install to nvidia top-level package, so we cannot query top-level module via + # metadata. Instead, we manually translate them from dist name to package name. + _PATTERN = r'^nvidia-(?P.+)-cu[\d]+$' + nvidia_hiddenimports = [] + + for req in requirements: + m = re.match(_PATTERN, req) + if m is not None: + # Convert + package_name = "nvidia." + m.group('subpackage').replace('-', '_') + nvidia_hiddenimports.append(package_name) + + return nvidia_hiddenimports + + +def create_symlink_suppression_patterns(hook_file): + hook_name, hook_ext = os.path.splitext(os.path.basename(hook_file)) + assert hook_ext.startswith('.py') + assert hook_name.startswith('hook-') + module_name = hook_name[5:] + + # Applicable only to Linux + if not compat.is_linux: + return [] + + # Pattern: **/{module_dir}/lib/lib*.so* + return [os.path.join('**', *module_name.split('.'), 'lib', 'lib*.so*')] diff --git a/venv/Lib/site-packages/pip-24.2.dist-info/INSTALLER b/venv/Lib/site-packages/altgraph-0.17.4.dist-info/INSTALLER similarity index 100% rename from venv/Lib/site-packages/pip-24.2.dist-info/INSTALLER rename to venv/Lib/site-packages/altgraph-0.17.4.dist-info/INSTALLER diff --git a/venv/Lib/site-packages/altgraph-0.17.4.dist-info/LICENSE b/venv/Lib/site-packages/altgraph-0.17.4.dist-info/LICENSE new file mode 100644 index 0000000..6013a21 --- /dev/null +++ b/venv/Lib/site-packages/altgraph-0.17.4.dist-info/LICENSE @@ -0,0 +1,18 @@ +Copyright (c) 2004 Istvan Albert unless otherwise noted. +Copyright (c) 2006-2010 Bob Ippolito +Copyright (2) 2010-2020 Ronald Oussoren, et. al. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. diff --git a/venv/Lib/site-packages/altgraph-0.17.4.dist-info/METADATA b/venv/Lib/site-packages/altgraph-0.17.4.dist-info/METADATA new file mode 100644 index 0000000..589d1f5 --- /dev/null +++ b/venv/Lib/site-packages/altgraph-0.17.4.dist-info/METADATA @@ -0,0 +1,293 @@ +Metadata-Version: 2.1 +Name: altgraph +Version: 0.17.4 +Summary: Python graph (network) package +Home-page: https://altgraph.readthedocs.io +Download-URL: http://pypi.python.org/pypi/altgraph +Author: Ronald Oussoren +Author-email: ronaldoussoren@mac.com +Maintainer: Ronald Oussoren +Maintainer-email: ronaldoussoren@mac.com +License: MIT +Keywords: graph +Platform: any +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Scientific/Engineering :: Mathematics +Classifier: Topic :: Scientific/Engineering :: Visualization +Description-Content-Type: text/x-rst; charset=UTF-8 +License-File: LICENSE +Project-URL: Documentation, https://altgraph.readthedocs.io/en/latest/ +Project-URL: Issue tracker, https://github.com/ronaldoussoren/altgraph/issues +Project-URL: Repository, https://github.com/ronaldoussoren/altgraph + +altgraph is a fork of graphlib: a graph (network) package for constructing +graphs, BFS and DFS traversals, topological sort, shortest paths, etc. with +graphviz output. + +altgraph includes some additional usage of Python 2.6+ features and +enhancements related to modulegraph and macholib. + +Project links +------------- + +* `Documentation `_ + +* `Issue Tracker `_ + +* `Repository `_ + + +Release history +=============== + +0.17.3 +------ + +* Update classifiers for Python 3.11 + +0.17.2 +------ + +* Change in setup.py to fix the sidebar links on PyPI + +0.17.1 +------ + +* Explicitly mark Python 3.10 as supported in wheel metadata. + +0.17 +---- + +* Explicitly mark Python 3.8 as supported in wheel metadata. + +* Migrate from Bitbucket to GitHub + +* Run black on the entire repository + +0.16.1 +------ + +* Explicitly mark Python 3.7 as supported in wheel metadata. + +0.16 +---- + +* Add LICENSE file + +0.15 +---- + +* ``ObjectGraph.get_edges``, ``ObjectGraph.getEdgeData`` and ``ObjectGraph.updateEdgeData`` + accept *None* as the node to get and treat this as an alias for *self* (as other + methods already did). + +0.14 +---- + +- Issue #7: Remove use of ``iteritems`` in altgraph.GraphAlgo code + +0.13 +---- + +- Issue #4: Graph._bfs_subgraph and back_bfs_subgraph return subgraphs with reversed edges + + Fix by "pombredanne" on bitbucket. + + +0.12 +---- + +- Added ``ObjectGraph.edgeData`` to retrieve the edge data + from a specific edge. + +- Added ``AltGraph.update_edge_data`` and ``ObjectGraph.updateEdgeData`` + to update the data associated with a graph edge. + +0.11 +---- + +- Stabilize the order of elements in dot file exports, + patch from bitbucket user 'pombredanne'. + +- Tweak setup.py file to remove dependency on distribute (but + keep the dependency on setuptools) + + +0.10.2 +------ + +- There where no classifiers in the package metadata due to a bug + in setup.py + +0.10.1 +------ + +This is a bugfix release + +Bug fixes: + +- Issue #3: The source archive contains a README.txt + while the setup file refers to ReadMe.txt. + + This is caused by a misfeature in distutils, as a + workaround I've renamed ReadMe.txt to README.txt + in the source tree and setup file. + + +0.10 +----- + +This is a minor feature release + +Features: + +- Do not use "2to3" to support Python 3. + + As a side effect of this altgraph now supports + Python 2.6 and later, and no longer supports + earlier releases of Python. + +- The order of attributes in the Dot output + is now always alphabetical. + + With this change the output will be consistent + between runs and Python versions. + +0.9 +--- + +This is a minor bugfix release + +Features: + +- Added ``altgraph.ObjectGraph.ObjectGraph.nodes``, a method + yielding all nodes in an object graph. + +Bugfixes: + +- The 0.8 release didn't work with py2app when using + python 3.x. + + +0.8 +----- + +This is a minor feature release. The major new feature +is a extensive set of unittests, which explains almost +all other changes in this release. + +Bugfixes: + +- Installing failed with Python 2.5 due to using a distutils + class that isn't available in that version of Python + (issue #1 on the issue tracker) + +- ``altgraph.GraphStat.degree_dist`` now actually works + +- ``altgraph.Graph.add_edge(a, b, create_nodes=False)`` will + no longer create the edge when one of the nodes doesn't + exist. + +- ``altgraph.Graph.forw_topo_sort`` failed for some sparse graphs. + +- ``altgraph.Graph.back_topo_sort`` was completely broken in + previous releases. + +- ``altgraph.Graph.forw_bfs_subgraph`` now actually works. + +- ``altgraph.Graph.back_bfs_subgraph`` now actually works. + +- ``altgraph.Graph.iterdfs`` now returns the correct result + when the ``forward`` argument is ``False``. + +- ``altgraph.Graph.iterdata`` now returns the correct result + when the ``forward`` argument is ``False``. + + +Features: + +- The ``altgraph.Graph`` constructor now accepts an argument + that contains 2- and 3-tuples instead of requireing that + all items have the same size. The (optional) argument can now + also be any iterator. + +- ``altgraph.Graph.Graph.add_node`` has no effect when you + add a hidden node. + +- The private method ``altgraph.Graph._bfs`` is no longer + present. + +- The private method ``altgraph.Graph._dfs`` is no longer + present. + +- ``altgraph.ObjectGraph`` now has a ``__contains__`` methods, + which means you can use the ``in`` operator to check if a + node is part of a graph. + +- ``altgraph.GraphUtil.generate_random_graph`` will raise + ``GraphError`` instead of looping forever when it is + impossible to create the requested graph. + +- ``altgraph.Dot.edge_style`` raises ``GraphError`` when + one of the nodes is not present in the graph. The method + silently added the tail in the past, but without ensuring + a consistent graph state. + +- ``altgraph.Dot.save_img`` now works when the mode is + ``"neato"``. + +0.7.2 +----- + +This is a minor bugfix release + +Bugfixes: + +- distutils didn't include the documentation subtree + +0.7.1 +----- + +This is a minor feature release + +Features: + +- Documentation is now generated using `sphinx `_ + and can be viewed at . + +- The repository has moved to bitbucket + +- ``altgraph.GraphStat.avg_hops`` is no longer present, the function had no + implementation and no specified behaviour. + +- the module ``altgraph.compat`` is gone, which means altgraph will no + longer work with Python 2.3. + + +0.7.0 +----- + +This is a minor feature release. + +Features: + +- Support for Python 3 + +- It is now possible to run tests using 'python setup.py test' + + (The actual testsuite is still very minimal though) diff --git a/venv/Lib/site-packages/altgraph-0.17.4.dist-info/RECORD b/venv/Lib/site-packages/altgraph-0.17.4.dist-info/RECORD new file mode 100644 index 0000000..c2388c0 --- /dev/null +++ b/venv/Lib/site-packages/altgraph-0.17.4.dist-info/RECORD @@ -0,0 +1,21 @@ +altgraph-0.17.4.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +altgraph-0.17.4.dist-info/LICENSE,sha256=bBlNbbDGTUVTXRDJUUK5sM2nt9zH8d3uMCs9U289vkY,1002 +altgraph-0.17.4.dist-info/METADATA,sha256=aREWy2Dksd1VVAd4BJMv0CkDVxIPyZIfA9J2ZFJrEpU,7264 +altgraph-0.17.4.dist-info/RECORD,, +altgraph-0.17.4.dist-info/WHEEL,sha256=a-zpFRIJzOq5QfuhBzbhiA1eHTzNCJn8OdRvhdNX0Rk,110 +altgraph-0.17.4.dist-info/top_level.txt,sha256=HEBeRWf5ItVPc7Y9hW7hGlrLXZjPoL4by6CAhBV_BwA,9 +altgraph-0.17.4.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1 +altgraph/Dot.py,sha256=gKEp6Su_CoOWQYt5HIVs_7MBYK1BEOhKX0RLAAA-vQs,9929 +altgraph/Graph.py,sha256=6b6fSHLA5QSqMDnSHIO7_WJnBYIdq3K5Bt8VipRODwg,20788 +altgraph/GraphAlgo.py,sha256=Uu9aTjSKWi38iQ_e9ZrwCnzQaI1WWFDhJ6kfmu0jxAA,5645 +altgraph/GraphStat.py,sha256=LKya4BKXJ5GZi5-sNYU17aOBTLxqn_tVgbiw4sWGYIU,1888 +altgraph/GraphUtil.py,sha256=1T4DJc2bJn6EIU_Ct4m0oiKlXWkXvqcXE8CGL2K9en8,3990 +altgraph/ObjectGraph.py,sha256=o7fPJtyBEgJSXAkUjzvj35B-FOY4uKzfLGqSvTitx8c,6490 +altgraph/__init__.py,sha256=YtY-rHf6X_lYk8820da2uVZT-C-B9KGpGXvBg1oZ0Fc,5015 +altgraph/__pycache__/Dot.cpython-311.pyc,, +altgraph/__pycache__/Graph.cpython-311.pyc,, +altgraph/__pycache__/GraphAlgo.cpython-311.pyc,, +altgraph/__pycache__/GraphStat.cpython-311.pyc,, +altgraph/__pycache__/GraphUtil.cpython-311.pyc,, +altgraph/__pycache__/ObjectGraph.cpython-311.pyc,, +altgraph/__pycache__/__init__.cpython-311.pyc,, diff --git a/venv/Lib/site-packages/altgraph-0.17.4.dist-info/WHEEL b/venv/Lib/site-packages/altgraph-0.17.4.dist-info/WHEEL new file mode 100644 index 0000000..f771c29 --- /dev/null +++ b/venv/Lib/site-packages/altgraph-0.17.4.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.40.0) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/venv/Lib/site-packages/altgraph-0.17.4.dist-info/top_level.txt b/venv/Lib/site-packages/altgraph-0.17.4.dist-info/top_level.txt new file mode 100644 index 0000000..5ad6b8a --- /dev/null +++ b/venv/Lib/site-packages/altgraph-0.17.4.dist-info/top_level.txt @@ -0,0 +1 @@ +altgraph diff --git a/venv/Lib/site-packages/altgraph-0.17.4.dist-info/zip-safe b/venv/Lib/site-packages/altgraph-0.17.4.dist-info/zip-safe new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/venv/Lib/site-packages/altgraph-0.17.4.dist-info/zip-safe @@ -0,0 +1 @@ + diff --git a/venv/Lib/site-packages/altgraph/Dot.py b/venv/Lib/site-packages/altgraph/Dot.py new file mode 100644 index 0000000..1d19cb1 --- /dev/null +++ b/venv/Lib/site-packages/altgraph/Dot.py @@ -0,0 +1,321 @@ +""" +altgraph.Dot - Interface to the dot language +============================================ + +The :py:mod:`~altgraph.Dot` module provides a simple interface to the +file format used in the +`graphviz `_ +program. The module is intended to offload the most tedious part of the process +(the **dot** file generation) while transparently exposing most of its +features. + +To display the graphs or to generate image files the +`graphviz `_ +package needs to be installed on the system, moreover the :command:`dot` and +:command:`dotty` programs must be accesible in the program path so that they +can be ran from processes spawned within the module. + +Example usage +------------- + +Here is a typical usage:: + + from altgraph import Graph, Dot + + # create a graph + edges = [ (1,2), (1,3), (3,4), (3,5), (4,5), (5,4) ] + graph = Graph.Graph(edges) + + # create a dot representation of the graph + dot = Dot.Dot(graph) + + # display the graph + dot.display() + + # save the dot representation into the mydot.dot file + dot.save_dot(file_name='mydot.dot') + + # save dot file as gif image into the graph.gif file + dot.save_img(file_name='graph', file_type='gif') + +Directed graph and non-directed graph +------------------------------------- + +Dot class can use for both directed graph and non-directed graph +by passing ``graphtype`` parameter. + +Example:: + + # create directed graph(default) + dot = Dot.Dot(graph, graphtype="digraph") + + # create non-directed graph + dot = Dot.Dot(graph, graphtype="graph") + +Customizing the output +---------------------- + +The graph drawing process may be customized by passing +valid :command:`dot` parameters for the nodes and edges. For a list of all +parameters see the `graphviz `_ +documentation. + +Example:: + + # customizing the way the overall graph is drawn + dot.style(size='10,10', rankdir='RL', page='5, 5' , ranksep=0.75) + + # customizing node drawing + dot.node_style(1, label='BASE_NODE',shape='box', color='blue' ) + dot.node_style(2, style='filled', fillcolor='red') + + # customizing edge drawing + dot.edge_style(1, 2, style='dotted') + dot.edge_style(3, 5, arrowhead='dot', label='binds', labelangle='90') + dot.edge_style(4, 5, arrowsize=2, style='bold') + + +.. note:: + + dotty (invoked via :py:func:`~altgraph.Dot.display`) may not be able to + display all graphics styles. To verify the output save it to an image file + and look at it that way. + +Valid attributes +---------------- + + - dot styles, passed via the :py:meth:`Dot.style` method:: + + rankdir = 'LR' (draws the graph horizontally, left to right) + ranksep = number (rank separation in inches) + + - node attributes, passed via the :py:meth:`Dot.node_style` method:: + + style = 'filled' | 'invisible' | 'diagonals' | 'rounded' + shape = 'box' | 'ellipse' | 'circle' | 'point' | 'triangle' + + - edge attributes, passed via the :py:meth:`Dot.edge_style` method:: + + style = 'dashed' | 'dotted' | 'solid' | 'invis' | 'bold' + arrowhead = 'box' | 'crow' | 'diamond' | 'dot' | 'inv' | 'none' + | 'tee' | 'vee' + weight = number (the larger the number the closer the nodes will be) + + - valid `graphviz colors + `_ + + - for more details on how to control the graph drawing process see the + `graphviz reference + `_. +""" +import os +import warnings + +from altgraph import GraphError + + +class Dot(object): + """ + A class providing a **graphviz** (dot language) representation + allowing a fine grained control over how the graph is being + displayed. + + If the :command:`dot` and :command:`dotty` programs are not in the current + system path their location needs to be specified in the contructor. + """ + + def __init__( + self, + graph=None, + nodes=None, + edgefn=None, + nodevisitor=None, + edgevisitor=None, + name="G", + dot="dot", + dotty="dotty", + neato="neato", + graphtype="digraph", + ): + """ + Initialization. + """ + self.name, self.attr = name, {} + + assert graphtype in ["graph", "digraph"] + self.type = graphtype + + self.temp_dot = "tmp_dot.dot" + self.temp_neo = "tmp_neo.dot" + + self.dot, self.dotty, self.neato = dot, dotty, neato + + # self.nodes: node styles + # self.edges: edge styles + self.nodes, self.edges = {}, {} + + if graph is not None and nodes is None: + nodes = graph + if graph is not None and edgefn is None: + + def edgefn(node, graph=graph): + return graph.out_nbrs(node) + + if nodes is None: + nodes = () + + seen = set() + for node in nodes: + if nodevisitor is None: + style = {} + else: + style = nodevisitor(node) + if style is not None: + self.nodes[node] = {} + self.node_style(node, **style) + seen.add(node) + if edgefn is not None: + for head in seen: + for tail in (n for n in edgefn(head) if n in seen): + if edgevisitor is None: + edgestyle = {} + else: + edgestyle = edgevisitor(head, tail) + if edgestyle is not None: + if head not in self.edges: + self.edges[head] = {} + self.edges[head][tail] = {} + self.edge_style(head, tail, **edgestyle) + + def style(self, **attr): + """ + Changes the overall style + """ + self.attr = attr + + def display(self, mode="dot"): + """ + Displays the current graph via dotty + """ + + if mode == "neato": + self.save_dot(self.temp_neo) + neato_cmd = "%s -o %s %s" % (self.neato, self.temp_dot, self.temp_neo) + os.system(neato_cmd) + else: + self.save_dot(self.temp_dot) + + plot_cmd = "%s %s" % (self.dotty, self.temp_dot) + os.system(plot_cmd) + + def node_style(self, node, **kwargs): + """ + Modifies a node style to the dot representation. + """ + if node not in self.edges: + self.edges[node] = {} + self.nodes[node] = kwargs + + def all_node_style(self, **kwargs): + """ + Modifies all node styles + """ + for node in self.nodes: + self.node_style(node, **kwargs) + + def edge_style(self, head, tail, **kwargs): + """ + Modifies an edge style to the dot representation. + """ + if tail not in self.nodes: + raise GraphError("invalid node %s" % (tail,)) + + try: + if tail not in self.edges[head]: + self.edges[head][tail] = {} + self.edges[head][tail] = kwargs + except KeyError: + raise GraphError("invalid edge %s -> %s " % (head, tail)) + + def iterdot(self): + # write graph title + if self.type == "digraph": + yield "digraph %s {\n" % (self.name,) + elif self.type == "graph": + yield "graph %s {\n" % (self.name,) + + else: + raise GraphError("unsupported graphtype %s" % (self.type,)) + + # write overall graph attributes + for attr_name, attr_value in sorted(self.attr.items()): + yield '%s="%s";' % (attr_name, attr_value) + yield "\n" + + # some reusable patterns + cpatt = '%s="%s",' # to separate attributes + epatt = "];\n" # to end attributes + + # write node attributes + for node_name, node_attr in sorted(self.nodes.items()): + yield '\t"%s" [' % (node_name,) + for attr_name, attr_value in sorted(node_attr.items()): + yield cpatt % (attr_name, attr_value) + yield epatt + + # write edge attributes + for head in sorted(self.edges): + for tail in sorted(self.edges[head]): + if self.type == "digraph": + yield '\t"%s" -> "%s" [' % (head, tail) + else: + yield '\t"%s" -- "%s" [' % (head, tail) + for attr_name, attr_value in sorted(self.edges[head][tail].items()): + yield cpatt % (attr_name, attr_value) + yield epatt + + # finish file + yield "}\n" + + def __iter__(self): + return self.iterdot() + + def save_dot(self, file_name=None): + """ + Saves the current graph representation into a file + """ + + if not file_name: + warnings.warn(DeprecationWarning, "always pass a file_name", stacklevel=2) + file_name = self.temp_dot + + with open(file_name, "w") as fp: + for chunk in self.iterdot(): + fp.write(chunk) + + def save_img(self, file_name=None, file_type="gif", mode="dot"): + """ + Saves the dot file as an image file + """ + + if not file_name: + warnings.warn(DeprecationWarning, "always pass a file_name", stacklevel=2) + file_name = "out" + + if mode == "neato": + self.save_dot(self.temp_neo) + neato_cmd = "%s -o %s %s" % (self.neato, self.temp_dot, self.temp_neo) + os.system(neato_cmd) + plot_cmd = self.dot + else: + self.save_dot(self.temp_dot) + plot_cmd = self.dot + + file_name = "%s.%s" % (file_name, file_type) + create_cmd = "%s -T%s %s -o %s" % ( + plot_cmd, + file_type, + self.temp_dot, + file_name, + ) + os.system(create_cmd) diff --git a/venv/Lib/site-packages/altgraph/Graph.py b/venv/Lib/site-packages/altgraph/Graph.py new file mode 100644 index 0000000..8088007 --- /dev/null +++ b/venv/Lib/site-packages/altgraph/Graph.py @@ -0,0 +1,682 @@ +""" +altgraph.Graph - Base Graph class +================================= + +.. + #--Version 2.1 + #--Bob Ippolito October, 2004 + + #--Version 2.0 + #--Istvan Albert June, 2004 + + #--Version 1.0 + #--Nathan Denny, May 27, 1999 +""" + +from collections import deque + +from altgraph import GraphError + + +class Graph(object): + """ + The Graph class represents a directed graph with *N* nodes and *E* edges. + + Naming conventions: + + - the prefixes such as *out*, *inc* and *all* will refer to methods + that operate on the outgoing, incoming or all edges of that node. + + For example: :py:meth:`inc_degree` will refer to the degree of the node + computed over the incoming edges (the number of neighbours linking to + the node). + + - the prefixes such as *forw* and *back* will refer to the + orientation of the edges used in the method with respect to the node. + + For example: :py:meth:`forw_bfs` will start at the node then use the + outgoing edges to traverse the graph (goes forward). + """ + + def __init__(self, edges=None): + """ + Initialization + """ + + self.next_edge = 0 + self.nodes, self.edges = {}, {} + self.hidden_edges, self.hidden_nodes = {}, {} + + if edges is not None: + for item in edges: + if len(item) == 2: + head, tail = item + self.add_edge(head, tail) + elif len(item) == 3: + head, tail, data = item + self.add_edge(head, tail, data) + else: + raise GraphError("Cannot create edge from %s" % (item,)) + + def __repr__(self): + return "" % ( + self.number_of_nodes(), + self.number_of_edges(), + ) + + def add_node(self, node, node_data=None): + """ + Adds a new node to the graph. Arbitrary data can be attached to the + node via the node_data parameter. Adding the same node twice will be + silently ignored. + + The node must be a hashable value. + """ + # + # the nodes will contain tuples that will store incoming edges, + # outgoing edges and data + # + # index 0 -> incoming edges + # index 1 -> outgoing edges + + if node in self.hidden_nodes: + # Node is present, but hidden + return + + if node not in self.nodes: + self.nodes[node] = ([], [], node_data) + + def add_edge(self, head_id, tail_id, edge_data=1, create_nodes=True): + """ + Adds a directed edge going from head_id to tail_id. + Arbitrary data can be attached to the edge via edge_data. + It may create the nodes if adding edges between nonexisting ones. + + :param head_id: head node + :param tail_id: tail node + :param edge_data: (optional) data attached to the edge + :param create_nodes: (optional) creates the head_id or tail_id + node in case they did not exist + """ + # shorcut + edge = self.next_edge + + # add nodes if on automatic node creation + if create_nodes: + self.add_node(head_id) + self.add_node(tail_id) + + # update the corresponding incoming and outgoing lists in the nodes + # index 0 -> incoming edges + # index 1 -> outgoing edges + + try: + self.nodes[tail_id][0].append(edge) + self.nodes[head_id][1].append(edge) + except KeyError: + raise GraphError("Invalid nodes %s -> %s" % (head_id, tail_id)) + + # store edge information + self.edges[edge] = (head_id, tail_id, edge_data) + + self.next_edge += 1 + + def hide_edge(self, edge): + """ + Hides an edge from the graph. The edge may be unhidden at some later + time. + """ + try: + head_id, tail_id, edge_data = self.hidden_edges[edge] = self.edges[edge] + self.nodes[tail_id][0].remove(edge) + self.nodes[head_id][1].remove(edge) + del self.edges[edge] + except KeyError: + raise GraphError("Invalid edge %s" % edge) + + def hide_node(self, node): + """ + Hides a node from the graph. The incoming and outgoing edges of the + node will also be hidden. The node may be unhidden at some later time. + """ + try: + all_edges = self.all_edges(node) + self.hidden_nodes[node] = (self.nodes[node], all_edges) + for edge in all_edges: + self.hide_edge(edge) + del self.nodes[node] + except KeyError: + raise GraphError("Invalid node %s" % node) + + def restore_node(self, node): + """ + Restores a previously hidden node back into the graph and restores + all of its incoming and outgoing edges. + """ + try: + self.nodes[node], all_edges = self.hidden_nodes[node] + for edge in all_edges: + self.restore_edge(edge) + del self.hidden_nodes[node] + except KeyError: + raise GraphError("Invalid node %s" % node) + + def restore_edge(self, edge): + """ + Restores a previously hidden edge back into the graph. + """ + try: + head_id, tail_id, data = self.hidden_edges[edge] + self.nodes[tail_id][0].append(edge) + self.nodes[head_id][1].append(edge) + self.edges[edge] = head_id, tail_id, data + del self.hidden_edges[edge] + except KeyError: + raise GraphError("Invalid edge %s" % edge) + + def restore_all_edges(self): + """ + Restores all hidden edges. + """ + for edge in list(self.hidden_edges.keys()): + try: + self.restore_edge(edge) + except GraphError: + pass + + def restore_all_nodes(self): + """ + Restores all hidden nodes. + """ + for node in list(self.hidden_nodes.keys()): + self.restore_node(node) + + def __contains__(self, node): + """ + Test whether a node is in the graph + """ + return node in self.nodes + + def edge_by_id(self, edge): + """ + Returns the edge that connects the head_id and tail_id nodes + """ + try: + head, tail, data = self.edges[edge] + except KeyError: + head, tail = None, None + raise GraphError("Invalid edge %s" % edge) + + return (head, tail) + + def edge_by_node(self, head, tail): + """ + Returns the edge that connects the head_id and tail_id nodes + """ + for edge in self.out_edges(head): + if self.tail(edge) == tail: + return edge + return None + + def number_of_nodes(self): + """ + Returns the number of nodes + """ + return len(self.nodes) + + def number_of_edges(self): + """ + Returns the number of edges + """ + return len(self.edges) + + def __iter__(self): + """ + Iterates over all nodes in the graph + """ + return iter(self.nodes) + + def node_list(self): + """ + Return a list of the node ids for all visible nodes in the graph. + """ + return list(self.nodes.keys()) + + def edge_list(self): + """ + Returns an iterator for all visible nodes in the graph. + """ + return list(self.edges.keys()) + + def number_of_hidden_edges(self): + """ + Returns the number of hidden edges + """ + return len(self.hidden_edges) + + def number_of_hidden_nodes(self): + """ + Returns the number of hidden nodes + """ + return len(self.hidden_nodes) + + def hidden_node_list(self): + """ + Returns the list with the hidden nodes + """ + return list(self.hidden_nodes.keys()) + + def hidden_edge_list(self): + """ + Returns a list with the hidden edges + """ + return list(self.hidden_edges.keys()) + + def describe_node(self, node): + """ + return node, node data, outgoing edges, incoming edges for node + """ + incoming, outgoing, data = self.nodes[node] + return node, data, outgoing, incoming + + def describe_edge(self, edge): + """ + return edge, edge data, head, tail for edge + """ + head, tail, data = self.edges[edge] + return edge, data, head, tail + + def node_data(self, node): + """ + Returns the data associated with a node + """ + return self.nodes[node][2] + + def edge_data(self, edge): + """ + Returns the data associated with an edge + """ + return self.edges[edge][2] + + def update_edge_data(self, edge, edge_data): + """ + Replace the edge data for a specific edge + """ + self.edges[edge] = self.edges[edge][0:2] + (edge_data,) + + def head(self, edge): + """ + Returns the node of the head of the edge. + """ + return self.edges[edge][0] + + def tail(self, edge): + """ + Returns node of the tail of the edge. + """ + return self.edges[edge][1] + + def out_nbrs(self, node): + """ + List of nodes connected by outgoing edges + """ + return [self.tail(n) for n in self.out_edges(node)] + + def inc_nbrs(self, node): + """ + List of nodes connected by incoming edges + """ + return [self.head(n) for n in self.inc_edges(node)] + + def all_nbrs(self, node): + """ + List of nodes connected by incoming and outgoing edges + """ + return list(dict.fromkeys(self.inc_nbrs(node) + self.out_nbrs(node))) + + def out_edges(self, node): + """ + Returns a list of the outgoing edges + """ + try: + return list(self.nodes[node][1]) + except KeyError: + raise GraphError("Invalid node %s" % node) + + def inc_edges(self, node): + """ + Returns a list of the incoming edges + """ + try: + return list(self.nodes[node][0]) + except KeyError: + raise GraphError("Invalid node %s" % node) + + def all_edges(self, node): + """ + Returns a list of incoming and outging edges. + """ + return set(self.inc_edges(node) + self.out_edges(node)) + + def out_degree(self, node): + """ + Returns the number of outgoing edges + """ + return len(self.out_edges(node)) + + def inc_degree(self, node): + """ + Returns the number of incoming edges + """ + return len(self.inc_edges(node)) + + def all_degree(self, node): + """ + The total degree of a node + """ + return self.inc_degree(node) + self.out_degree(node) + + def _topo_sort(self, forward=True): + """ + Topological sort. + + Returns a list of nodes where the successors (based on outgoing and + incoming edges selected by the forward parameter) of any given node + appear in the sequence after that node. + """ + topo_list = [] + queue = deque() + indeg = {} + + # select the operation that will be performed + if forward: + get_edges = self.out_edges + get_degree = self.inc_degree + get_next = self.tail + else: + get_edges = self.inc_edges + get_degree = self.out_degree + get_next = self.head + + for node in self.node_list(): + degree = get_degree(node) + if degree: + indeg[node] = degree + else: + queue.append(node) + + while queue: + curr_node = queue.popleft() + topo_list.append(curr_node) + for edge in get_edges(curr_node): + tail_id = get_next(edge) + if tail_id in indeg: + indeg[tail_id] -= 1 + if indeg[tail_id] == 0: + queue.append(tail_id) + + if len(topo_list) == len(self.node_list()): + valid = True + else: + # the graph has cycles, invalid topological sort + valid = False + + return (valid, topo_list) + + def forw_topo_sort(self): + """ + Topological sort. + + Returns a list of nodes where the successors (based on outgoing edges) + of any given node appear in the sequence after that node. + """ + return self._topo_sort(forward=True) + + def back_topo_sort(self): + """ + Reverse topological sort. + + Returns a list of nodes where the successors (based on incoming edges) + of any given node appear in the sequence after that node. + """ + return self._topo_sort(forward=False) + + def _bfs_subgraph(self, start_id, forward=True): + """ + Private method creates a subgraph in a bfs order. + + The forward parameter specifies whether it is a forward or backward + traversal. + """ + if forward: + get_bfs = self.forw_bfs + get_nbrs = self.out_nbrs + else: + get_bfs = self.back_bfs + get_nbrs = self.inc_nbrs + + g = Graph() + bfs_list = get_bfs(start_id) + for node in bfs_list: + g.add_node(node) + + for node in bfs_list: + for nbr_id in get_nbrs(node): + if forward: + g.add_edge(node, nbr_id) + else: + g.add_edge(nbr_id, node) + + return g + + def forw_bfs_subgraph(self, start_id): + """ + Creates and returns a subgraph consisting of the breadth first + reachable nodes based on their outgoing edges. + """ + return self._bfs_subgraph(start_id, forward=True) + + def back_bfs_subgraph(self, start_id): + """ + Creates and returns a subgraph consisting of the breadth first + reachable nodes based on the incoming edges. + """ + return self._bfs_subgraph(start_id, forward=False) + + def iterdfs(self, start, end=None, forward=True): + """ + Collecting nodes in some depth first traversal. + + The forward parameter specifies whether it is a forward or backward + traversal. + """ + visited, stack = {start}, deque([start]) + + if forward: + get_edges = self.out_edges + get_next = self.tail + else: + get_edges = self.inc_edges + get_next = self.head + + while stack: + curr_node = stack.pop() + yield curr_node + if curr_node == end: + break + for edge in sorted(get_edges(curr_node)): + tail = get_next(edge) + if tail not in visited: + visited.add(tail) + stack.append(tail) + + def iterdata(self, start, end=None, forward=True, condition=None): + """ + Perform a depth-first walk of the graph (as ``iterdfs``) + and yield the item data of every node where condition matches. The + condition callback is only called when node_data is not None. + """ + + visited, stack = {start}, deque([start]) + + if forward: + get_edges = self.out_edges + get_next = self.tail + else: + get_edges = self.inc_edges + get_next = self.head + + get_data = self.node_data + + while stack: + curr_node = stack.pop() + curr_data = get_data(curr_node) + if curr_data is not None: + if condition is not None and not condition(curr_data): + continue + yield curr_data + if curr_node == end: + break + for edge in get_edges(curr_node): + tail = get_next(edge) + if tail not in visited: + visited.add(tail) + stack.append(tail) + + def _iterbfs(self, start, end=None, forward=True): + """ + The forward parameter specifies whether it is a forward or backward + traversal. Returns a list of tuples where the first value is the hop + value the second value is the node id. + """ + queue, visited = deque([(start, 0)]), {start} + + # the direction of the bfs depends on the edges that are sampled + if forward: + get_edges = self.out_edges + get_next = self.tail + else: + get_edges = self.inc_edges + get_next = self.head + + while queue: + curr_node, curr_step = queue.popleft() + yield (curr_node, curr_step) + if curr_node == end: + break + for edge in get_edges(curr_node): + tail = get_next(edge) + if tail not in visited: + visited.add(tail) + queue.append((tail, curr_step + 1)) + + def forw_bfs(self, start, end=None): + """ + Returns a list of nodes in some forward BFS order. + + Starting from the start node the breadth first search proceeds along + outgoing edges. + """ + return [node for node, step in self._iterbfs(start, end, forward=True)] + + def back_bfs(self, start, end=None): + """ + Returns a list of nodes in some backward BFS order. + + Starting from the start node the breadth first search proceeds along + incoming edges. + """ + return [node for node, _ in self._iterbfs(start, end, forward=False)] + + def forw_dfs(self, start, end=None): + """ + Returns a list of nodes in some forward DFS order. + + Starting with the start node the depth first search proceeds along + outgoing edges. + """ + return list(self.iterdfs(start, end, forward=True)) + + def back_dfs(self, start, end=None): + """ + Returns a list of nodes in some backward DFS order. + + Starting from the start node the depth first search proceeds along + incoming edges. + """ + return list(self.iterdfs(start, end, forward=False)) + + def connected(self): + """ + Returns :py:data:`True` if the graph's every node can be reached from + every other node. + """ + node_list = self.node_list() + for node in node_list: + bfs_list = self.forw_bfs(node) + if len(bfs_list) != len(node_list): + return False + return True + + def clust_coef(self, node): + """ + Computes and returns the local clustering coefficient of node. + + The local cluster coefficient is proportion of the actual number of + edges between neighbours of node and the maximum number of edges + between those neighbours. + + See "Local Clustering Coefficient" on + + for a formal definition. + """ + num = 0 + nbr_set = set(self.out_nbrs(node)) + + if node in nbr_set: + nbr_set.remove(node) # loop defense + + for nbr in nbr_set: + sec_set = set(self.out_nbrs(nbr)) + if nbr in sec_set: + sec_set.remove(nbr) # loop defense + num += len(nbr_set & sec_set) + + nbr_num = len(nbr_set) + if nbr_num: + clust_coef = float(num) / (nbr_num * (nbr_num - 1)) + else: + clust_coef = 0.0 + return clust_coef + + def get_hops(self, start, end=None, forward=True): + """ + Computes the hop distance to all nodes centered around a node. + + First order neighbours are at hop 1, their neigbours are at hop 2 etc. + Uses :py:meth:`forw_bfs` or :py:meth:`back_bfs` depending on the value + of the forward parameter. If the distance between all neighbouring + nodes is 1 the hop number corresponds to the shortest distance between + the nodes. + + :param start: the starting node + :param end: ending node (optional). When not specified will search the + whole graph. + :param forward: directionality parameter (optional). + If C{True} (default) it uses L{forw_bfs} otherwise L{back_bfs}. + :return: returns a list of tuples where each tuple contains the + node and the hop. + + Typical usage:: + + >>> print (graph.get_hops(1, 8)) + >>> [(1, 0), (2, 1), (3, 1), (4, 2), (5, 3), (7, 4), (8, 5)] + # node 1 is at 0 hops + # node 2 is at 1 hop + # ... + # node 8 is at 5 hops + """ + if forward: + return list(self._iterbfs(start=start, end=end, forward=True)) + else: + return list(self._iterbfs(start=start, end=end, forward=False)) diff --git a/venv/Lib/site-packages/altgraph/GraphAlgo.py b/venv/Lib/site-packages/altgraph/GraphAlgo.py new file mode 100644 index 0000000..f93e73d --- /dev/null +++ b/venv/Lib/site-packages/altgraph/GraphAlgo.py @@ -0,0 +1,171 @@ +""" +altgraph.GraphAlgo - Graph algorithms +===================================== +""" +from altgraph import GraphError + + +def dijkstra(graph, start, end=None): + """ + Dijkstra's algorithm for shortest paths + + `David Eppstein, UC Irvine, 4 April 2002 + `_ + + `Python Cookbook Recipe + `_ + + Find shortest paths from the start node to all nodes nearer than or + equal to the end node. + + Dijkstra's algorithm is only guaranteed to work correctly when all edge + lengths are positive. This code does not verify this property for all + edges (only the edges examined until the end vertex is reached), but will + correctly compute shortest paths even for some graphs with negative edges, + and will raise an exception if it discovers that a negative edge has + caused it to make a mistake. + + Adapted to altgraph by Istvan Albert, Pennsylvania State University - + June, 9 2004 + """ + D = {} # dictionary of final distances + P = {} # dictionary of predecessors + Q = _priorityDictionary() # estimated distances of non-final vertices + Q[start] = 0 + + for v in Q: + D[v] = Q[v] + if v == end: + break + + for w in graph.out_nbrs(v): + edge_id = graph.edge_by_node(v, w) + vwLength = D[v] + graph.edge_data(edge_id) + if w in D: + if vwLength < D[w]: + raise GraphError( + "Dijkstra: found better path to already-final vertex" + ) + elif w not in Q or vwLength < Q[w]: + Q[w] = vwLength + P[w] = v + + return (D, P) + + +def shortest_path(graph, start, end): + """ + Find a single shortest path from the *start* node to the *end* node. + The input has the same conventions as dijkstra(). The output is a list of + the nodes in order along the shortest path. + + **Note that the distances must be stored in the edge data as numeric data** + """ + + D, P = dijkstra(graph, start, end) + Path = [] + while 1: + Path.append(end) + if end == start: + break + end = P[end] + Path.reverse() + return Path + + +# +# Utility classes and functions +# +class _priorityDictionary(dict): + """ + Priority dictionary using binary heaps (internal use only) + + David Eppstein, UC Irvine, 8 Mar 2002 + + Implements a data structure that acts almost like a dictionary, with + two modifications: + + 1. D.smallest() returns the value x minimizing D[x]. For this to + work correctly, all values D[x] stored in the dictionary must be + comparable. + + 2. iterating "for x in D" finds and removes the items from D in sorted + order. Each item is not removed until the next item is requested, + so D[x] will still return a useful value until the next iteration + of the for-loop. Each operation takes logarithmic amortized time. + """ + + def __init__(self): + """ + Initialize priorityDictionary by creating binary heap of pairs + (value,key). Note that changing or removing a dict entry will not + remove the old pair from the heap until it is found by smallest() + or until the heap is rebuilt. + """ + self.__heap = [] + dict.__init__(self) + + def smallest(self): + """ + Find smallest item after removing deleted items from front of heap. + """ + if len(self) == 0: + raise IndexError("smallest of empty priorityDictionary") + heap = self.__heap + while heap[0][1] not in self or self[heap[0][1]] != heap[0][0]: + lastItem = heap.pop() + insertionPoint = 0 + while 1: + smallChild = 2 * insertionPoint + 1 + if ( + smallChild + 1 < len(heap) + and heap[smallChild] > heap[smallChild + 1] + ): + smallChild += 1 + if smallChild >= len(heap) or lastItem <= heap[smallChild]: + heap[insertionPoint] = lastItem + break + heap[insertionPoint] = heap[smallChild] + insertionPoint = smallChild + return heap[0][1] + + def __iter__(self): + """ + Create destructive sorted iterator of priorityDictionary. + """ + + def iterfn(): + while len(self) > 0: + x = self.smallest() + yield x + del self[x] + + return iterfn() + + def __setitem__(self, key, val): + """ + Change value stored in dictionary and add corresponding pair to heap. + Rebuilds the heap if the number of deleted items gets large, to avoid + memory leakage. + """ + dict.__setitem__(self, key, val) + heap = self.__heap + if len(heap) > 2 * len(self): + self.__heap = [(v, k) for k, v in self.items()] + self.__heap.sort() + else: + newPair = (val, key) + insertionPoint = len(heap) + heap.append(None) + while insertionPoint > 0 and newPair < heap[(insertionPoint - 1) // 2]: + heap[insertionPoint] = heap[(insertionPoint - 1) // 2] + insertionPoint = (insertionPoint - 1) // 2 + heap[insertionPoint] = newPair + + def setdefault(self, key, val): + """ + Reimplement setdefault to pass through our customized __setitem__. + """ + if key not in self: + self[key] = val + return self[key] diff --git a/venv/Lib/site-packages/altgraph/GraphStat.py b/venv/Lib/site-packages/altgraph/GraphStat.py new file mode 100644 index 0000000..cccc66d --- /dev/null +++ b/venv/Lib/site-packages/altgraph/GraphStat.py @@ -0,0 +1,73 @@ +""" +altgraph.GraphStat - Functions providing various graph statistics +================================================================= +""" + + +def degree_dist(graph, limits=(0, 0), bin_num=10, mode="out"): + """ + Computes the degree distribution for a graph. + + Returns a list of tuples where the first element of the tuple is the + center of the bin representing a range of degrees and the second element + of the tuple are the number of nodes with the degree falling in the range. + + Example:: + + .... + """ + + deg = [] + if mode == "inc": + get_deg = graph.inc_degree + else: + get_deg = graph.out_degree + + for node in graph: + deg.append(get_deg(node)) + + if not deg: + return [] + + results = _binning(values=deg, limits=limits, bin_num=bin_num) + + return results + + +_EPS = 1.0 / (2.0**32) + + +def _binning(values, limits=(0, 0), bin_num=10): + """ + Bins data that falls between certain limits, if the limits are (0, 0) the + minimum and maximum values are used. + + Returns a list of tuples where the first element of the tuple is the + center of the bin and the second element of the tuple are the counts. + """ + if limits == (0, 0): + min_val, max_val = min(values) - _EPS, max(values) + _EPS + else: + min_val, max_val = limits + + # get bin size + bin_size = (max_val - min_val) / float(bin_num) + bins = [0] * (bin_num) + + # will ignore these outliers for now + for value in values: + try: + if (value - min_val) >= 0: + index = int((value - min_val) / float(bin_size)) + bins[index] += 1 + except IndexError: + pass + + # make it ready for an x,y plot + result = [] + center = (bin_size / 2) + min_val + for i, y in enumerate(bins): + x = center + bin_size * i + result.append((x, y)) + + return result diff --git a/venv/Lib/site-packages/altgraph/GraphUtil.py b/venv/Lib/site-packages/altgraph/GraphUtil.py new file mode 100644 index 0000000..cfd6a34 --- /dev/null +++ b/venv/Lib/site-packages/altgraph/GraphUtil.py @@ -0,0 +1,139 @@ +""" +altgraph.GraphUtil - Utility classes and functions +================================================== +""" + +import random +from collections import deque + +from altgraph import Graph, GraphError + + +def generate_random_graph(node_num, edge_num, self_loops=False, multi_edges=False): + """ + Generates and returns a :py:class:`~altgraph.Graph.Graph` instance with + *node_num* nodes randomly connected by *edge_num* edges. + """ + g = Graph.Graph() + + if not multi_edges: + if self_loops: + max_edges = node_num * node_num + else: + max_edges = node_num * (node_num - 1) + + if edge_num > max_edges: + raise GraphError("inconsistent arguments to 'generate_random_graph'") + + nodes = range(node_num) + + for node in nodes: + g.add_node(node) + + while 1: + head = random.choice(nodes) + tail = random.choice(nodes) + + # loop defense + if head == tail and not self_loops: + continue + + # multiple edge defense + if g.edge_by_node(head, tail) is not None and not multi_edges: + continue + + # add the edge + g.add_edge(head, tail) + if g.number_of_edges() >= edge_num: + break + + return g + + +def generate_scale_free_graph(steps, growth_num, self_loops=False, multi_edges=False): + """ + Generates and returns a :py:class:`~altgraph.Graph.Graph` instance that + will have *steps* \\* *growth_num* nodes and a scale free (powerlaw) + connectivity. Starting with a fully connected graph with *growth_num* + nodes at every step *growth_num* nodes are added to the graph and are + connected to existing nodes with a probability proportional to the degree + of these existing nodes. + """ + # The code doesn't seem to do what the documentation claims. + graph = Graph.Graph() + + # initialize the graph + store = [] + for i in range(growth_num): + for j in range(i + 1, growth_num): + store.append(i) + store.append(j) + graph.add_edge(i, j) + + # generate + for node in range(growth_num, steps * growth_num): + graph.add_node(node) + while graph.out_degree(node) < growth_num: + nbr = random.choice(store) + + # loop defense + if node == nbr and not self_loops: + continue + + # multi edge defense + if graph.edge_by_node(node, nbr) and not multi_edges: + continue + + graph.add_edge(node, nbr) + + for nbr in graph.out_nbrs(node): + store.append(node) + store.append(nbr) + + return graph + + +def filter_stack(graph, head, filters): + """ + Perform a walk in a depth-first order starting + at *head*. + + Returns (visited, removes, orphans). + + * visited: the set of visited nodes + * removes: the list of nodes where the node + data does not all *filters* + * orphans: tuples of (last_good, node), + where node is not in removes, is directly + reachable from a node in *removes* and + *last_good* is the closest upstream node that is not + in *removes*. + """ + + visited, removes, orphans = {head}, set(), set() + stack = deque([(head, head)]) + get_data = graph.node_data + get_edges = graph.out_edges + get_tail = graph.tail + + while stack: + last_good, node = stack.pop() + data = get_data(node) + if data is not None: + for filtfunc in filters: + if not filtfunc(data): + removes.add(node) + break + else: + last_good = node + for edge in get_edges(node): + tail = get_tail(edge) + if last_good is not node: + orphans.add((last_good, tail)) + if tail not in visited: + visited.add(tail) + stack.append((last_good, tail)) + + orphans = [(lg, tl) for (lg, tl) in orphans if tl not in removes] + + return visited, removes, orphans diff --git a/venv/Lib/site-packages/altgraph/ObjectGraph.py b/venv/Lib/site-packages/altgraph/ObjectGraph.py new file mode 100644 index 0000000..379b05b --- /dev/null +++ b/venv/Lib/site-packages/altgraph/ObjectGraph.py @@ -0,0 +1,212 @@ +""" +altgraph.ObjectGraph - Graph of objects with an identifier +========================================================== + +A graph of objects that have a "graphident" attribute. +graphident is the key for the object in the graph +""" + +from altgraph import GraphError +from altgraph.Graph import Graph +from altgraph.GraphUtil import filter_stack + + +class ObjectGraph(object): + """ + A graph of objects that have a "graphident" attribute. + graphident is the key for the object in the graph + """ + + def __init__(self, graph=None, debug=0): + if graph is None: + graph = Graph() + self.graphident = self + self.graph = graph + self.debug = debug + self.indent = 0 + graph.add_node(self, None) + + def __repr__(self): + return "<%s>" % (type(self).__name__,) + + def flatten(self, condition=None, start=None): + """ + Iterate over the subgraph that is entirely reachable by condition + starting from the given start node or the ObjectGraph root + """ + if start is None: + start = self + start = self.getRawIdent(start) + return self.graph.iterdata(start=start, condition=condition) + + def nodes(self): + for ident in self.graph: + node = self.graph.node_data(ident) + if node is not None: + yield self.graph.node_data(ident) + + def get_edges(self, node): + if node is None: + node = self + start = self.getRawIdent(node) + _, _, outraw, incraw = self.graph.describe_node(start) + + def iter_edges(lst, n): + seen = set() + for tpl in (self.graph.describe_edge(e) for e in lst): + ident = tpl[n] + if ident not in seen: + yield self.findNode(ident) + seen.add(ident) + + return iter_edges(outraw, 3), iter_edges(incraw, 2) + + def edgeData(self, fromNode, toNode): + if fromNode is None: + fromNode = self + start = self.getRawIdent(fromNode) + stop = self.getRawIdent(toNode) + edge = self.graph.edge_by_node(start, stop) + return self.graph.edge_data(edge) + + def updateEdgeData(self, fromNode, toNode, edgeData): + if fromNode is None: + fromNode = self + start = self.getRawIdent(fromNode) + stop = self.getRawIdent(toNode) + edge = self.graph.edge_by_node(start, stop) + self.graph.update_edge_data(edge, edgeData) + + def filterStack(self, filters): + """ + Filter the ObjectGraph in-place by removing all edges to nodes that + do not match every filter in the given filter list + + Returns a tuple containing the number of: + (nodes_visited, nodes_removed, nodes_orphaned) + """ + visited, removes, orphans = filter_stack(self.graph, self, filters) + + for last_good, tail in orphans: + self.graph.add_edge(last_good, tail, edge_data="orphan") + + for node in removes: + self.graph.hide_node(node) + + return len(visited) - 1, len(removes), len(orphans) + + def removeNode(self, node): + """ + Remove the given node from the graph if it exists + """ + ident = self.getIdent(node) + if ident is not None: + self.graph.hide_node(ident) + + def removeReference(self, fromnode, tonode): + """ + Remove all edges from fromnode to tonode + """ + if fromnode is None: + fromnode = self + fromident = self.getIdent(fromnode) + toident = self.getIdent(tonode) + if fromident is not None and toident is not None: + while True: + edge = self.graph.edge_by_node(fromident, toident) + if edge is None: + break + self.graph.hide_edge(edge) + + def getIdent(self, node): + """ + Get the graph identifier for a node + """ + ident = self.getRawIdent(node) + if ident is not None: + return ident + node = self.findNode(node) + if node is None: + return None + return node.graphident + + def getRawIdent(self, node): + """ + Get the identifier for a node object + """ + if node is self: + return node + ident = getattr(node, "graphident", None) + return ident + + def __contains__(self, node): + return self.findNode(node) is not None + + def findNode(self, node): + """ + Find the node on the graph + """ + ident = self.getRawIdent(node) + if ident is None: + ident = node + try: + return self.graph.node_data(ident) + except KeyError: + return None + + def addNode(self, node): + """ + Add a node to the graph referenced by the root + """ + self.msg(4, "addNode", node) + + try: + self.graph.restore_node(node.graphident) + except GraphError: + self.graph.add_node(node.graphident, node) + + def createReference(self, fromnode, tonode, edge_data=None): + """ + Create a reference from fromnode to tonode + """ + if fromnode is None: + fromnode = self + fromident, toident = self.getIdent(fromnode), self.getIdent(tonode) + if fromident is None or toident is None: + return + self.msg(4, "createReference", fromnode, tonode, edge_data) + self.graph.add_edge(fromident, toident, edge_data=edge_data) + + def createNode(self, cls, name, *args, **kw): + """ + Add a node of type cls to the graph if it does not already exist + by the given name + """ + m = self.findNode(name) + if m is None: + m = cls(name, *args, **kw) + self.addNode(m) + return m + + def msg(self, level, s, *args): + """ + Print a debug message with the given level + """ + if s and level <= self.debug: + print("%s%s %s" % (" " * self.indent, s, " ".join(map(repr, args)))) + + def msgin(self, level, s, *args): + """ + Print a debug message and indent + """ + if level <= self.debug: + self.msg(level, s, *args) + self.indent = self.indent + 1 + + def msgout(self, level, s, *args): + """ + Dedent and print a debug message + """ + if level <= self.debug: + self.indent = self.indent - 1 + self.msg(level, s, *args) diff --git a/venv/Lib/site-packages/altgraph/__init__.py b/venv/Lib/site-packages/altgraph/__init__.py new file mode 100644 index 0000000..a563424 --- /dev/null +++ b/venv/Lib/site-packages/altgraph/__init__.py @@ -0,0 +1,148 @@ +""" +altgraph - a python graph library +================================= + +altgraph is a fork of `graphlib `_ tailored +to use newer Python 2.3+ features, including additional support used by the +py2app suite (modulegraph and macholib, specifically). + +altgraph is a python based graph (network) representation and manipulation +package. It has started out as an extension to the +`graph_lib module +`_ +written by Nathan Denny it has been significantly optimized and expanded. + +The :class:`altgraph.Graph.Graph` class is loosely modeled after the +`LEDA `_ +(Library of Efficient Datatypes) representation. The library +includes methods for constructing graphs, BFS and DFS traversals, +topological sort, finding connected components, shortest paths as well as a +number graph statistics functions. The library can also visualize graphs +via `graphviz `_. + +The package contains the following modules: + + - the :py:mod:`altgraph.Graph` module contains the + :class:`~altgraph.Graph.Graph` class that stores the graph data + + - the :py:mod:`altgraph.GraphAlgo` module implements graph algorithms + operating on graphs (:py:class:`~altgraph.Graph.Graph`} instances) + + - the :py:mod:`altgraph.GraphStat` module contains functions for + computing statistical measures on graphs + + - the :py:mod:`altgraph.GraphUtil` module contains functions for + generating, reading and saving graphs + + - the :py:mod:`altgraph.Dot` module contains functions for displaying + graphs via `graphviz `_ + + - the :py:mod:`altgraph.ObjectGraph` module implements a graph of + objects with a unique identifier + +Installation +------------ + +Download and unpack the archive then type:: + + python setup.py install + +This will install the library in the default location. For instructions on +how to customize the install procedure read the output of:: + + python setup.py --help install + +To verify that the code works run the test suite:: + + python setup.py test + +Example usage +------------- + +Lets assume that we want to analyze the graph below (links to the full picture) +GRAPH_IMG. Our script then might look the following way:: + + from altgraph import Graph, GraphAlgo, Dot + + # these are the edges + edges = [ (1,2), (2,4), (1,3), (2,4), (3,4), (4,5), (6,5), + (6,14), (14,15), (6, 15), (5,7), (7, 8), (7,13), (12,8), + (8,13), (11,12), (11,9), (13,11), (9,13), (13,10) ] + + # creates the graph + graph = Graph.Graph() + for head, tail in edges: + graph.add_edge(head, tail) + + # do a forward bfs from 1 at most to 20 + print(graph.forw_bfs(1)) + +This will print the nodes in some breadth first order:: + + [1, 2, 3, 4, 5, 7, 8, 13, 11, 10, 12, 9] + +If we wanted to get the hop-distance from node 1 to node 8 +we coud write:: + + print(graph.get_hops(1, 8)) + +This will print the following:: + + [(1, 0), (2, 1), (3, 1), (4, 2), (5, 3), (7, 4), (8, 5)] + +Node 1 is at 0 hops since it is the starting node, nodes 2,3 are 1 hop away ... +node 8 is 5 hops away. To find the shortest distance between two nodes you +can use:: + + print(GraphAlgo.shortest_path(graph, 1, 12)) + +It will print the nodes on one (if there are more) the shortest paths:: + + [1, 2, 4, 5, 7, 13, 11, 12] + +To display the graph we can use the GraphViz backend:: + + dot = Dot.Dot(graph) + + # display the graph on the monitor + dot.display() + + # save it in an image file + dot.save_img(file_name='graph', file_type='gif') + + + +.. + @author: U{Istvan Albert} + + @license: MIT License + + Copyright (c) 2004 Istvan Albert unless otherwise noted. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. + @requires: Python 2.3 or higher + + @newfield contributor: Contributors: + @contributor: U{Reka Albert } + +""" +import pkg_resources + +__version__ = pkg_resources.require("altgraph")[0].version + + +class GraphError(ValueError): + pass diff --git a/venv/Lib/site-packages/altgraph/__pycache__/Dot.cpython-311.pyc b/venv/Lib/site-packages/altgraph/__pycache__/Dot.cpython-311.pyc new file mode 100644 index 0000000..1a1f397 Binary files /dev/null and b/venv/Lib/site-packages/altgraph/__pycache__/Dot.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/altgraph/__pycache__/Graph.cpython-311.pyc b/venv/Lib/site-packages/altgraph/__pycache__/Graph.cpython-311.pyc new file mode 100644 index 0000000..3a1ebab Binary files /dev/null and b/venv/Lib/site-packages/altgraph/__pycache__/Graph.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/altgraph/__pycache__/GraphAlgo.cpython-311.pyc b/venv/Lib/site-packages/altgraph/__pycache__/GraphAlgo.cpython-311.pyc new file mode 100644 index 0000000..7036d27 Binary files /dev/null and b/venv/Lib/site-packages/altgraph/__pycache__/GraphAlgo.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/altgraph/__pycache__/GraphStat.cpython-311.pyc b/venv/Lib/site-packages/altgraph/__pycache__/GraphStat.cpython-311.pyc new file mode 100644 index 0000000..e7f4677 Binary files /dev/null and b/venv/Lib/site-packages/altgraph/__pycache__/GraphStat.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/altgraph/__pycache__/GraphUtil.cpython-311.pyc b/venv/Lib/site-packages/altgraph/__pycache__/GraphUtil.cpython-311.pyc new file mode 100644 index 0000000..4e144d3 Binary files /dev/null and b/venv/Lib/site-packages/altgraph/__pycache__/GraphUtil.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/altgraph/__pycache__/ObjectGraph.cpython-311.pyc b/venv/Lib/site-packages/altgraph/__pycache__/ObjectGraph.cpython-311.pyc new file mode 100644 index 0000000..bd23bc3 Binary files /dev/null and b/venv/Lib/site-packages/altgraph/__pycache__/ObjectGraph.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/altgraph/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/altgraph/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..585cbf3 Binary files /dev/null and b/venv/Lib/site-packages/altgraph/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/ordlookup/__init__.py b/venv/Lib/site-packages/ordlookup/__init__.py new file mode 100644 index 0000000..8841d74 --- /dev/null +++ b/venv/Lib/site-packages/ordlookup/__init__.py @@ -0,0 +1,34 @@ +from . import ws2_32 +from . import oleaut32 + +""" +A small module for keeping a database of ordinal to symbol +mappings for DLLs which frequently get linked without symbolic +infoz. +""" + +ords = { + b"ws2_32.dll": ws2_32.ord_names, + b"wsock32.dll": ws2_32.ord_names, + b"oleaut32.dll": oleaut32.ord_names, +} + + +def formatOrdString(ord_val): + return "ord{}".format(ord_val).encode() + + +def ordLookup(libname, ord_val, make_name=False): + """ + Lookup a name for the given ordinal if it's in our + database. + """ + names = ords.get(libname.lower()) + if names is None: + if make_name is True: + return formatOrdString(ord_val) + return None + name = names.get(ord_val) + if name is None: + return formatOrdString(ord_val) + return name diff --git a/venv/Lib/site-packages/ordlookup/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/ordlookup/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..8879386 Binary files /dev/null and b/venv/Lib/site-packages/ordlookup/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/ordlookup/__pycache__/oleaut32.cpython-311.pyc b/venv/Lib/site-packages/ordlookup/__pycache__/oleaut32.cpython-311.pyc new file mode 100644 index 0000000..e2a9491 Binary files /dev/null and b/venv/Lib/site-packages/ordlookup/__pycache__/oleaut32.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/ordlookup/__pycache__/ws2_32.cpython-311.pyc b/venv/Lib/site-packages/ordlookup/__pycache__/ws2_32.cpython-311.pyc new file mode 100644 index 0000000..ab7bc92 Binary files /dev/null and b/venv/Lib/site-packages/ordlookup/__pycache__/ws2_32.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/ordlookup/oleaut32.py b/venv/Lib/site-packages/ordlookup/oleaut32.py new file mode 100644 index 0000000..9b49b1d --- /dev/null +++ b/venv/Lib/site-packages/ordlookup/oleaut32.py @@ -0,0 +1,400 @@ +ord_names = { + 2: b"SysAllocString", + 3: b"SysReAllocString", + 4: b"SysAllocStringLen", + 5: b"SysReAllocStringLen", + 6: b"SysFreeString", + 7: b"SysStringLen", + 8: b"VariantInit", + 9: b"VariantClear", + 10: b"VariantCopy", + 11: b"VariantCopyInd", + 12: b"VariantChangeType", + 13: b"VariantTimeToDosDateTime", + 14: b"DosDateTimeToVariantTime", + 15: b"SafeArrayCreate", + 16: b"SafeArrayDestroy", + 17: b"SafeArrayGetDim", + 18: b"SafeArrayGetElemsize", + 19: b"SafeArrayGetUBound", + 20: b"SafeArrayGetLBound", + 21: b"SafeArrayLock", + 22: b"SafeArrayUnlock", + 23: b"SafeArrayAccessData", + 24: b"SafeArrayUnaccessData", + 25: b"SafeArrayGetElement", + 26: b"SafeArrayPutElement", + 27: b"SafeArrayCopy", + 28: b"DispGetParam", + 29: b"DispGetIDsOfNames", + 30: b"DispInvoke", + 31: b"CreateDispTypeInfo", + 32: b"CreateStdDispatch", + 33: b"RegisterActiveObject", + 34: b"RevokeActiveObject", + 35: b"GetActiveObject", + 36: b"SafeArrayAllocDescriptor", + 37: b"SafeArrayAllocData", + 38: b"SafeArrayDestroyDescriptor", + 39: b"SafeArrayDestroyData", + 40: b"SafeArrayRedim", + 41: b"SafeArrayAllocDescriptorEx", + 42: b"SafeArrayCreateEx", + 43: b"SafeArrayCreateVectorEx", + 44: b"SafeArraySetRecordInfo", + 45: b"SafeArrayGetRecordInfo", + 46: b"VarParseNumFromStr", + 47: b"VarNumFromParseNum", + 48: b"VarI2FromUI1", + 49: b"VarI2FromI4", + 50: b"VarI2FromR4", + 51: b"VarI2FromR8", + 52: b"VarI2FromCy", + 53: b"VarI2FromDate", + 54: b"VarI2FromStr", + 55: b"VarI2FromDisp", + 56: b"VarI2FromBool", + 57: b"SafeArraySetIID", + 58: b"VarI4FromUI1", + 59: b"VarI4FromI2", + 60: b"VarI4FromR4", + 61: b"VarI4FromR8", + 62: b"VarI4FromCy", + 63: b"VarI4FromDate", + 64: b"VarI4FromStr", + 65: b"VarI4FromDisp", + 66: b"VarI4FromBool", + 67: b"SafeArrayGetIID", + 68: b"VarR4FromUI1", + 69: b"VarR4FromI2", + 70: b"VarR4FromI4", + 71: b"VarR4FromR8", + 72: b"VarR4FromCy", + 73: b"VarR4FromDate", + 74: b"VarR4FromStr", + 75: b"VarR4FromDisp", + 76: b"VarR4FromBool", + 77: b"SafeArrayGetVartype", + 78: b"VarR8FromUI1", + 79: b"VarR8FromI2", + 80: b"VarR8FromI4", + 81: b"VarR8FromR4", + 82: b"VarR8FromCy", + 83: b"VarR8FromDate", + 84: b"VarR8FromStr", + 85: b"VarR8FromDisp", + 86: b"VarR8FromBool", + 87: b"VarFormat", + 88: b"VarDateFromUI1", + 89: b"VarDateFromI2", + 90: b"VarDateFromI4", + 91: b"VarDateFromR4", + 92: b"VarDateFromR8", + 93: b"VarDateFromCy", + 94: b"VarDateFromStr", + 95: b"VarDateFromDisp", + 96: b"VarDateFromBool", + 97: b"VarFormatDateTime", + 98: b"VarCyFromUI1", + 99: b"VarCyFromI2", + 100: b"VarCyFromI4", + 101: b"VarCyFromR4", + 102: b"VarCyFromR8", + 103: b"VarCyFromDate", + 104: b"VarCyFromStr", + 105: b"VarCyFromDisp", + 106: b"VarCyFromBool", + 107: b"VarFormatNumber", + 108: b"VarBstrFromUI1", + 109: b"VarBstrFromI2", + 110: b"VarBstrFromI4", + 111: b"VarBstrFromR4", + 112: b"VarBstrFromR8", + 113: b"VarBstrFromCy", + 114: b"VarBstrFromDate", + 115: b"VarBstrFromDisp", + 116: b"VarBstrFromBool", + 117: b"VarFormatPercent", + 118: b"VarBoolFromUI1", + 119: b"VarBoolFromI2", + 120: b"VarBoolFromI4", + 121: b"VarBoolFromR4", + 122: b"VarBoolFromR8", + 123: b"VarBoolFromDate", + 124: b"VarBoolFromCy", + 125: b"VarBoolFromStr", + 126: b"VarBoolFromDisp", + 127: b"VarFormatCurrency", + 128: b"VarWeekdayName", + 129: b"VarMonthName", + 130: b"VarUI1FromI2", + 131: b"VarUI1FromI4", + 132: b"VarUI1FromR4", + 133: b"VarUI1FromR8", + 134: b"VarUI1FromCy", + 135: b"VarUI1FromDate", + 136: b"VarUI1FromStr", + 137: b"VarUI1FromDisp", + 138: b"VarUI1FromBool", + 139: b"VarFormatFromTokens", + 140: b"VarTokenizeFormatString", + 141: b"VarAdd", + 142: b"VarAnd", + 143: b"VarDiv", + 144: b"DllCanUnloadNow", + 145: b"DllGetClassObject", + 146: b"DispCallFunc", + 147: b"VariantChangeTypeEx", + 148: b"SafeArrayPtrOfIndex", + 149: b"SysStringByteLen", + 150: b"SysAllocStringByteLen", + 151: b"DllRegisterServer", + 152: b"VarEqv", + 153: b"VarIdiv", + 154: b"VarImp", + 155: b"VarMod", + 156: b"VarMul", + 157: b"VarOr", + 158: b"VarPow", + 159: b"VarSub", + 160: b"CreateTypeLib", + 161: b"LoadTypeLib", + 162: b"LoadRegTypeLib", + 163: b"RegisterTypeLib", + 164: b"QueryPathOfRegTypeLib", + 165: b"LHashValOfNameSys", + 166: b"LHashValOfNameSysA", + 167: b"VarXor", + 168: b"VarAbs", + 169: b"VarFix", + 170: b"OaBuildVersion", + 171: b"ClearCustData", + 172: b"VarInt", + 173: b"VarNeg", + 174: b"VarNot", + 175: b"VarRound", + 176: b"VarCmp", + 177: b"VarDecAdd", + 178: b"VarDecDiv", + 179: b"VarDecMul", + 180: b"CreateTypeLib2", + 181: b"VarDecSub", + 182: b"VarDecAbs", + 183: b"LoadTypeLibEx", + 184: b"SystemTimeToVariantTime", + 185: b"VariantTimeToSystemTime", + 186: b"UnRegisterTypeLib", + 187: b"VarDecFix", + 188: b"VarDecInt", + 189: b"VarDecNeg", + 190: b"VarDecFromUI1", + 191: b"VarDecFromI2", + 192: b"VarDecFromI4", + 193: b"VarDecFromR4", + 194: b"VarDecFromR8", + 195: b"VarDecFromDate", + 196: b"VarDecFromCy", + 197: b"VarDecFromStr", + 198: b"VarDecFromDisp", + 199: b"VarDecFromBool", + 200: b"GetErrorInfo", + 201: b"SetErrorInfo", + 202: b"CreateErrorInfo", + 203: b"VarDecRound", + 204: b"VarDecCmp", + 205: b"VarI2FromI1", + 206: b"VarI2FromUI2", + 207: b"VarI2FromUI4", + 208: b"VarI2FromDec", + 209: b"VarI4FromI1", + 210: b"VarI4FromUI2", + 211: b"VarI4FromUI4", + 212: b"VarI4FromDec", + 213: b"VarR4FromI1", + 214: b"VarR4FromUI2", + 215: b"VarR4FromUI4", + 216: b"VarR4FromDec", + 217: b"VarR8FromI1", + 218: b"VarR8FromUI2", + 219: b"VarR8FromUI4", + 220: b"VarR8FromDec", + 221: b"VarDateFromI1", + 222: b"VarDateFromUI2", + 223: b"VarDateFromUI4", + 224: b"VarDateFromDec", + 225: b"VarCyFromI1", + 226: b"VarCyFromUI2", + 227: b"VarCyFromUI4", + 228: b"VarCyFromDec", + 229: b"VarBstrFromI1", + 230: b"VarBstrFromUI2", + 231: b"VarBstrFromUI4", + 232: b"VarBstrFromDec", + 233: b"VarBoolFromI1", + 234: b"VarBoolFromUI2", + 235: b"VarBoolFromUI4", + 236: b"VarBoolFromDec", + 237: b"VarUI1FromI1", + 238: b"VarUI1FromUI2", + 239: b"VarUI1FromUI4", + 240: b"VarUI1FromDec", + 241: b"VarDecFromI1", + 242: b"VarDecFromUI2", + 243: b"VarDecFromUI4", + 244: b"VarI1FromUI1", + 245: b"VarI1FromI2", + 246: b"VarI1FromI4", + 247: b"VarI1FromR4", + 248: b"VarI1FromR8", + 249: b"VarI1FromDate", + 250: b"VarI1FromCy", + 251: b"VarI1FromStr", + 252: b"VarI1FromDisp", + 253: b"VarI1FromBool", + 254: b"VarI1FromUI2", + 255: b"VarI1FromUI4", + 256: b"VarI1FromDec", + 257: b"VarUI2FromUI1", + 258: b"VarUI2FromI2", + 259: b"VarUI2FromI4", + 260: b"VarUI2FromR4", + 261: b"VarUI2FromR8", + 262: b"VarUI2FromDate", + 263: b"VarUI2FromCy", + 264: b"VarUI2FromStr", + 265: b"VarUI2FromDisp", + 266: b"VarUI2FromBool", + 267: b"VarUI2FromI1", + 268: b"VarUI2FromUI4", + 269: b"VarUI2FromDec", + 270: b"VarUI4FromUI1", + 271: b"VarUI4FromI2", + 272: b"VarUI4FromI4", + 273: b"VarUI4FromR4", + 274: b"VarUI4FromR8", + 275: b"VarUI4FromDate", + 276: b"VarUI4FromCy", + 277: b"VarUI4FromStr", + 278: b"VarUI4FromDisp", + 279: b"VarUI4FromBool", + 280: b"VarUI4FromI1", + 281: b"VarUI4FromUI2", + 282: b"VarUI4FromDec", + 283: b"BSTR_UserSize", + 284: b"BSTR_UserMarshal", + 285: b"BSTR_UserUnmarshal", + 286: b"BSTR_UserFree", + 287: b"VARIANT_UserSize", + 288: b"VARIANT_UserMarshal", + 289: b"VARIANT_UserUnmarshal", + 290: b"VARIANT_UserFree", + 291: b"LPSAFEARRAY_UserSize", + 292: b"LPSAFEARRAY_UserMarshal", + 293: b"LPSAFEARRAY_UserUnmarshal", + 294: b"LPSAFEARRAY_UserFree", + 295: b"LPSAFEARRAY_Size", + 296: b"LPSAFEARRAY_Marshal", + 297: b"LPSAFEARRAY_Unmarshal", + 298: b"VarDecCmpR8", + 299: b"VarCyAdd", + 300: b"DllUnregisterServer", + 301: b"OACreateTypeLib2", + 303: b"VarCyMul", + 304: b"VarCyMulI4", + 305: b"VarCySub", + 306: b"VarCyAbs", + 307: b"VarCyFix", + 308: b"VarCyInt", + 309: b"VarCyNeg", + 310: b"VarCyRound", + 311: b"VarCyCmp", + 312: b"VarCyCmpR8", + 313: b"VarBstrCat", + 314: b"VarBstrCmp", + 315: b"VarR8Pow", + 316: b"VarR4CmpR8", + 317: b"VarR8Round", + 318: b"VarCat", + 319: b"VarDateFromUdateEx", + 322: b"GetRecordInfoFromGuids", + 323: b"GetRecordInfoFromTypeInfo", + 325: b"SetVarConversionLocaleSetting", + 326: b"GetVarConversionLocaleSetting", + 327: b"SetOaNoCache", + 329: b"VarCyMulI8", + 330: b"VarDateFromUdate", + 331: b"VarUdateFromDate", + 332: b"GetAltMonthNames", + 333: b"VarI8FromUI1", + 334: b"VarI8FromI2", + 335: b"VarI8FromR4", + 336: b"VarI8FromR8", + 337: b"VarI8FromCy", + 338: b"VarI8FromDate", + 339: b"VarI8FromStr", + 340: b"VarI8FromDisp", + 341: b"VarI8FromBool", + 342: b"VarI8FromI1", + 343: b"VarI8FromUI2", + 344: b"VarI8FromUI4", + 345: b"VarI8FromDec", + 346: b"VarI2FromI8", + 347: b"VarI2FromUI8", + 348: b"VarI4FromI8", + 349: b"VarI4FromUI8", + 360: b"VarR4FromI8", + 361: b"VarR4FromUI8", + 362: b"VarR8FromI8", + 363: b"VarR8FromUI8", + 364: b"VarDateFromI8", + 365: b"VarDateFromUI8", + 366: b"VarCyFromI8", + 367: b"VarCyFromUI8", + 368: b"VarBstrFromI8", + 369: b"VarBstrFromUI8", + 370: b"VarBoolFromI8", + 371: b"VarBoolFromUI8", + 372: b"VarUI1FromI8", + 373: b"VarUI1FromUI8", + 374: b"VarDecFromI8", + 375: b"VarDecFromUI8", + 376: b"VarI1FromI8", + 377: b"VarI1FromUI8", + 378: b"VarUI2FromI8", + 379: b"VarUI2FromUI8", + 401: b"OleLoadPictureEx", + 402: b"OleLoadPictureFileEx", + 411: b"SafeArrayCreateVector", + 412: b"SafeArrayCopyData", + 413: b"VectorFromBstr", + 414: b"BstrFromVector", + 415: b"OleIconToCursor", + 416: b"OleCreatePropertyFrameIndirect", + 417: b"OleCreatePropertyFrame", + 418: b"OleLoadPicture", + 419: b"OleCreatePictureIndirect", + 420: b"OleCreateFontIndirect", + 421: b"OleTranslateColor", + 422: b"OleLoadPictureFile", + 423: b"OleSavePictureFile", + 424: b"OleLoadPicturePath", + 425: b"VarUI4FromI8", + 426: b"VarUI4FromUI8", + 427: b"VarI8FromUI8", + 428: b"VarUI8FromI8", + 429: b"VarUI8FromUI1", + 430: b"VarUI8FromI2", + 431: b"VarUI8FromR4", + 432: b"VarUI8FromR8", + 433: b"VarUI8FromCy", + 434: b"VarUI8FromDate", + 435: b"VarUI8FromStr", + 436: b"VarUI8FromDisp", + 437: b"VarUI8FromBool", + 438: b"VarUI8FromI1", + 439: b"VarUI8FromUI2", + 440: b"VarUI8FromUI4", + 441: b"VarUI8FromDec", + 442: b"RegisterTypeLibForUser", + 443: b"UnRegisterTypeLibForUser", +} diff --git a/venv/Lib/site-packages/ordlookup/ws2_32.py b/venv/Lib/site-packages/ordlookup/ws2_32.py new file mode 100644 index 0000000..a655e0d --- /dev/null +++ b/venv/Lib/site-packages/ordlookup/ws2_32.py @@ -0,0 +1,119 @@ +ord_names = { + 1: b"accept", + 2: b"bind", + 3: b"closesocket", + 4: b"connect", + 5: b"getpeername", + 6: b"getsockname", + 7: b"getsockopt", + 8: b"htonl", + 9: b"htons", + 10: b"ioctlsocket", + 11: b"inet_addr", + 12: b"inet_ntoa", + 13: b"listen", + 14: b"ntohl", + 15: b"ntohs", + 16: b"recv", + 17: b"recvfrom", + 18: b"select", + 19: b"send", + 20: b"sendto", + 21: b"setsockopt", + 22: b"shutdown", + 23: b"socket", + 24: b"GetAddrInfoW", + 25: b"GetNameInfoW", + 26: b"WSApSetPostRoutine", + 27: b"FreeAddrInfoW", + 28: b"WPUCompleteOverlappedRequest", + 29: b"WSAAccept", + 30: b"WSAAddressToStringA", + 31: b"WSAAddressToStringW", + 32: b"WSACloseEvent", + 33: b"WSAConnect", + 34: b"WSACreateEvent", + 35: b"WSADuplicateSocketA", + 36: b"WSADuplicateSocketW", + 37: b"WSAEnumNameSpaceProvidersA", + 38: b"WSAEnumNameSpaceProvidersW", + 39: b"WSAEnumNetworkEvents", + 40: b"WSAEnumProtocolsA", + 41: b"WSAEnumProtocolsW", + 42: b"WSAEventSelect", + 43: b"WSAGetOverlappedResult", + 44: b"WSAGetQOSByName", + 45: b"WSAGetServiceClassInfoA", + 46: b"WSAGetServiceClassInfoW", + 47: b"WSAGetServiceClassNameByClassIdA", + 48: b"WSAGetServiceClassNameByClassIdW", + 49: b"WSAHtonl", + 50: b"WSAHtons", + 51: b"gethostbyaddr", + 52: b"gethostbyname", + 53: b"getprotobyname", + 54: b"getprotobynumber", + 55: b"getservbyname", + 56: b"getservbyport", + 57: b"gethostname", + 58: b"WSAInstallServiceClassA", + 59: b"WSAInstallServiceClassW", + 60: b"WSAIoctl", + 61: b"WSAJoinLeaf", + 62: b"WSALookupServiceBeginA", + 63: b"WSALookupServiceBeginW", + 64: b"WSALookupServiceEnd", + 65: b"WSALookupServiceNextA", + 66: b"WSALookupServiceNextW", + 67: b"WSANSPIoctl", + 68: b"WSANtohl", + 69: b"WSANtohs", + 70: b"WSAProviderConfigChange", + 71: b"WSARecv", + 72: b"WSARecvDisconnect", + 73: b"WSARecvFrom", + 74: b"WSARemoveServiceClass", + 75: b"WSAResetEvent", + 76: b"WSASend", + 77: b"WSASendDisconnect", + 78: b"WSASendTo", + 79: b"WSASetEvent", + 80: b"WSASetServiceA", + 81: b"WSASetServiceW", + 82: b"WSASocketA", + 83: b"WSASocketW", + 84: b"WSAStringToAddressA", + 85: b"WSAStringToAddressW", + 86: b"WSAWaitForMultipleEvents", + 87: b"WSCDeinstallProvider", + 88: b"WSCEnableNSProvider", + 89: b"WSCEnumProtocols", + 90: b"WSCGetProviderPath", + 91: b"WSCInstallNameSpace", + 92: b"WSCInstallProvider", + 93: b"WSCUnInstallNameSpace", + 94: b"WSCUpdateProvider", + 95: b"WSCWriteNameSpaceOrder", + 96: b"WSCWriteProviderOrder", + 97: b"freeaddrinfo", + 98: b"getaddrinfo", + 99: b"getnameinfo", + 101: b"WSAAsyncSelect", + 102: b"WSAAsyncGetHostByAddr", + 103: b"WSAAsyncGetHostByName", + 104: b"WSAAsyncGetProtoByNumber", + 105: b"WSAAsyncGetProtoByName", + 106: b"WSAAsyncGetServByPort", + 107: b"WSAAsyncGetServByName", + 108: b"WSACancelAsyncRequest", + 109: b"WSASetBlockingHook", + 110: b"WSAUnhookBlockingHook", + 111: b"WSAGetLastError", + 112: b"WSASetLastError", + 113: b"WSACancelBlockingCall", + 114: b"WSAIsBlocking", + 115: b"WSAStartup", + 116: b"WSACleanup", + 151: b"__WSAFDIsSet", + 500: b"WEP", +} diff --git a/venv/Lib/site-packages/pip-24.2.dist-info/top_level.txt b/venv/Lib/site-packages/packaging-24.2.dist-info/INSTALLER similarity index 100% rename from venv/Lib/site-packages/pip-24.2.dist-info/top_level.txt rename to venv/Lib/site-packages/packaging-24.2.dist-info/INSTALLER diff --git a/venv/Lib/site-packages/packaging-24.2.dist-info/LICENSE b/venv/Lib/site-packages/packaging-24.2.dist-info/LICENSE new file mode 100644 index 0000000..6f62d44 --- /dev/null +++ b/venv/Lib/site-packages/packaging-24.2.dist-info/LICENSE @@ -0,0 +1,3 @@ +This software is made available under the terms of *either* of the licenses +found in LICENSE.APACHE or LICENSE.BSD. Contributions to this software is made +under the terms of *both* these licenses. diff --git a/venv/Lib/site-packages/packaging-24.2.dist-info/LICENSE.APACHE b/venv/Lib/site-packages/packaging-24.2.dist-info/LICENSE.APACHE new file mode 100644 index 0000000..f433b1a --- /dev/null +++ b/venv/Lib/site-packages/packaging-24.2.dist-info/LICENSE.APACHE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/venv/Lib/site-packages/packaging-24.2.dist-info/LICENSE.BSD b/venv/Lib/site-packages/packaging-24.2.dist-info/LICENSE.BSD new file mode 100644 index 0000000..42ce7b7 --- /dev/null +++ b/venv/Lib/site-packages/packaging-24.2.dist-info/LICENSE.BSD @@ -0,0 +1,23 @@ +Copyright (c) Donald Stufft and individual contributors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/venv/Lib/site-packages/packaging-24.2.dist-info/METADATA b/venv/Lib/site-packages/packaging-24.2.dist-info/METADATA new file mode 100644 index 0000000..1479c86 --- /dev/null +++ b/venv/Lib/site-packages/packaging-24.2.dist-info/METADATA @@ -0,0 +1,102 @@ +Metadata-Version: 2.3 +Name: packaging +Version: 24.2 +Summary: Core utilities for Python packages +Author-email: Donald Stufft +Requires-Python: >=3.8 +Description-Content-Type: text/x-rst +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: Apache Software License +Classifier: License :: OSI Approved :: BSD License +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Programming Language :: Python :: 3.13 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Typing :: Typed +Project-URL: Documentation, https://packaging.pypa.io/ +Project-URL: Source, https://github.com/pypa/packaging + +packaging +========= + +.. start-intro + +Reusable core utilities for various Python Packaging +`interoperability specifications `_. + +This library provides utilities that implement the interoperability +specifications which have clearly one correct behaviour (eg: :pep:`440`) +or benefit greatly from having a single shared implementation (eg: :pep:`425`). + +.. end-intro + +The ``packaging`` project includes the following: version handling, specifiers, +markers, requirements, tags, utilities. + +Documentation +------------- + +The `documentation`_ provides information and the API for the following: + +- Version Handling +- Specifiers +- Markers +- Requirements +- Tags +- Utilities + +Installation +------------ + +Use ``pip`` to install these utilities:: + + pip install packaging + +The ``packaging`` library uses calendar-based versioning (``YY.N``). + +Discussion +---------- + +If you run into bugs, you can file them in our `issue tracker`_. + +You can also join ``#pypa`` on Freenode to ask questions or get involved. + + +.. _`documentation`: https://packaging.pypa.io/ +.. _`issue tracker`: https://github.com/pypa/packaging/issues + + +Code of Conduct +--------------- + +Everyone interacting in the packaging project's codebases, issue trackers, chat +rooms, and mailing lists is expected to follow the `PSF Code of Conduct`_. + +.. _PSF Code of Conduct: https://github.com/pypa/.github/blob/main/CODE_OF_CONDUCT.md + +Contributing +------------ + +The ``CONTRIBUTING.rst`` file outlines how to contribute to this project as +well as how to report a potential security issue. The documentation for this +project also covers information about `project development`_ and `security`_. + +.. _`project development`: https://packaging.pypa.io/en/latest/development/ +.. _`security`: https://packaging.pypa.io/en/latest/security/ + +Project History +--------------- + +Please review the ``CHANGELOG.rst`` file or the `Changelog documentation`_ for +recent changes and project history. + +.. _`Changelog documentation`: https://packaging.pypa.io/en/latest/changelog/ + diff --git a/venv/Lib/site-packages/packaging-24.2.dist-info/RECORD b/venv/Lib/site-packages/packaging-24.2.dist-info/RECORD new file mode 100644 index 0000000..6c07ab0 --- /dev/null +++ b/venv/Lib/site-packages/packaging-24.2.dist-info/RECORD @@ -0,0 +1,40 @@ +packaging-24.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +packaging-24.2.dist-info/LICENSE,sha256=ytHvW9NA1z4HS6YU0m996spceUDD2MNIUuZcSQlobEg,197 +packaging-24.2.dist-info/LICENSE.APACHE,sha256=DVQuDIgE45qn836wDaWnYhSdxoLXgpRRKH4RuTjpRZQ,10174 +packaging-24.2.dist-info/LICENSE.BSD,sha256=tw5-m3QvHMb5SLNMFqo5_-zpQZY2S8iP8NIYDwAo-sU,1344 +packaging-24.2.dist-info/METADATA,sha256=ohH86s6k5mIfQxY2TS0LcSfADeOFa4BiCC-bxZV-pNs,3204 +packaging-24.2.dist-info/RECORD,, +packaging-24.2.dist-info/WHEEL,sha256=CpUCUxeHQbRN5UGRQHYRJorO5Af-Qy_fHMctcQ8DSGI,82 +packaging/__init__.py,sha256=dk4Ta_vmdVJxYHDcfyhvQNw8V3PgSBomKNXqg-D2JDY,494 +packaging/__pycache__/__init__.cpython-311.pyc,, +packaging/__pycache__/_elffile.cpython-311.pyc,, +packaging/__pycache__/_manylinux.cpython-311.pyc,, +packaging/__pycache__/_musllinux.cpython-311.pyc,, +packaging/__pycache__/_parser.cpython-311.pyc,, +packaging/__pycache__/_structures.cpython-311.pyc,, +packaging/__pycache__/_tokenizer.cpython-311.pyc,, +packaging/__pycache__/markers.cpython-311.pyc,, +packaging/__pycache__/metadata.cpython-311.pyc,, +packaging/__pycache__/requirements.cpython-311.pyc,, +packaging/__pycache__/specifiers.cpython-311.pyc,, +packaging/__pycache__/tags.cpython-311.pyc,, +packaging/__pycache__/utils.cpython-311.pyc,, +packaging/__pycache__/version.cpython-311.pyc,, +packaging/_elffile.py,sha256=cflAQAkE25tzhYmq_aCi72QfbT_tn891tPzfpbeHOwE,3306 +packaging/_manylinux.py,sha256=vl5OCoz4kx80H5rwXKeXWjl9WNISGmr4ZgTpTP9lU9c,9612 +packaging/_musllinux.py,sha256=p9ZqNYiOItGee8KcZFeHF_YcdhVwGHdK6r-8lgixvGQ,2694 +packaging/_parser.py,sha256=s_TvTvDNK0NrM2QB3VKThdWFM4Nc0P6JnkObkl3MjpM,10236 +packaging/_structures.py,sha256=q3eVNmbWJGG_S0Dit_S3Ao8qQqz_5PYTXFAKBZe5yr4,1431 +packaging/_tokenizer.py,sha256=J6v5H7Jzvb-g81xp_2QACKwO7LxHQA6ikryMU7zXwN8,5273 +packaging/licenses/__init__.py,sha256=1x5M1nEYjcgwEbLt0dXwz2ukjr18DiCzC0sraQqJ-Ww,5715 +packaging/licenses/__pycache__/__init__.cpython-311.pyc,, +packaging/licenses/__pycache__/_spdx.cpython-311.pyc,, +packaging/licenses/_spdx.py,sha256=oAm1ztPFwlsmCKe7lAAsv_OIOfS1cWDu9bNBkeu-2ns,48398 +packaging/markers.py,sha256=c89TNzB7ZdGYhkovm6PYmqGyHxXlYVaLW591PHUNKD8,10561 +packaging/metadata.py,sha256=YJibM7GYe4re8-0a3OlXmGS-XDgTEoO4tlBt2q25Bng,34762 +packaging/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +packaging/requirements.py,sha256=gYyRSAdbrIyKDY66ugIDUQjRMvxkH2ALioTmX3tnL6o,2947 +packaging/specifiers.py,sha256=GG1wPNMcL0fMJO68vF53wKMdwnfehDcaI-r9NpTfilA,40074 +packaging/tags.py,sha256=CFqrJzAzc2XNGexerH__T-Y5Iwq7WbsYXsiLERLWxY0,21014 +packaging/utils.py,sha256=0F3Hh9OFuRgrhTgGZUl5K22Fv1YP2tZl1z_2gO6kJiA,5050 +packaging/version.py,sha256=olfyuk_DPbflNkJ4wBWetXQ17c74x3DB501degUv7DY,16676 diff --git a/venv/Lib/site-packages/packaging-24.2.dist-info/WHEEL b/venv/Lib/site-packages/packaging-24.2.dist-info/WHEEL new file mode 100644 index 0000000..e3c6fee --- /dev/null +++ b/venv/Lib/site-packages/packaging-24.2.dist-info/WHEEL @@ -0,0 +1,4 @@ +Wheel-Version: 1.0 +Generator: flit 3.10.1 +Root-Is-Purelib: true +Tag: py3-none-any diff --git a/venv/Lib/site-packages/packaging/__init__.py b/venv/Lib/site-packages/packaging/__init__.py new file mode 100644 index 0000000..d79f73c --- /dev/null +++ b/venv/Lib/site-packages/packaging/__init__.py @@ -0,0 +1,15 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +__title__ = "packaging" +__summary__ = "Core utilities for Python packages" +__uri__ = "https://github.com/pypa/packaging" + +__version__ = "24.2" + +__author__ = "Donald Stufft and individual contributors" +__email__ = "donald@stufft.io" + +__license__ = "BSD-2-Clause or Apache-2.0" +__copyright__ = f"2014 {__author__}" diff --git a/venv/Lib/site-packages/packaging/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/packaging/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..d3d6347 Binary files /dev/null and b/venv/Lib/site-packages/packaging/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/packaging/__pycache__/_elffile.cpython-311.pyc b/venv/Lib/site-packages/packaging/__pycache__/_elffile.cpython-311.pyc new file mode 100644 index 0000000..7b88a47 Binary files /dev/null and b/venv/Lib/site-packages/packaging/__pycache__/_elffile.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/packaging/__pycache__/_manylinux.cpython-311.pyc b/venv/Lib/site-packages/packaging/__pycache__/_manylinux.cpython-311.pyc new file mode 100644 index 0000000..d0eb767 Binary files /dev/null and b/venv/Lib/site-packages/packaging/__pycache__/_manylinux.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/packaging/__pycache__/_musllinux.cpython-311.pyc b/venv/Lib/site-packages/packaging/__pycache__/_musllinux.cpython-311.pyc new file mode 100644 index 0000000..c386764 Binary files /dev/null and b/venv/Lib/site-packages/packaging/__pycache__/_musllinux.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/packaging/__pycache__/_parser.cpython-311.pyc b/venv/Lib/site-packages/packaging/__pycache__/_parser.cpython-311.pyc new file mode 100644 index 0000000..2dd5bf3 Binary files /dev/null and b/venv/Lib/site-packages/packaging/__pycache__/_parser.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/packaging/__pycache__/_structures.cpython-311.pyc b/venv/Lib/site-packages/packaging/__pycache__/_structures.cpython-311.pyc new file mode 100644 index 0000000..a918929 Binary files /dev/null and b/venv/Lib/site-packages/packaging/__pycache__/_structures.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/packaging/__pycache__/_tokenizer.cpython-311.pyc b/venv/Lib/site-packages/packaging/__pycache__/_tokenizer.cpython-311.pyc new file mode 100644 index 0000000..7026790 Binary files /dev/null and b/venv/Lib/site-packages/packaging/__pycache__/_tokenizer.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/packaging/__pycache__/markers.cpython-311.pyc b/venv/Lib/site-packages/packaging/__pycache__/markers.cpython-311.pyc new file mode 100644 index 0000000..c456711 Binary files /dev/null and b/venv/Lib/site-packages/packaging/__pycache__/markers.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/packaging/__pycache__/metadata.cpython-311.pyc b/venv/Lib/site-packages/packaging/__pycache__/metadata.cpython-311.pyc new file mode 100644 index 0000000..b1115ae Binary files /dev/null and b/venv/Lib/site-packages/packaging/__pycache__/metadata.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/packaging/__pycache__/requirements.cpython-311.pyc b/venv/Lib/site-packages/packaging/__pycache__/requirements.cpython-311.pyc new file mode 100644 index 0000000..06ead2a Binary files /dev/null and b/venv/Lib/site-packages/packaging/__pycache__/requirements.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/packaging/__pycache__/specifiers.cpython-311.pyc b/venv/Lib/site-packages/packaging/__pycache__/specifiers.cpython-311.pyc new file mode 100644 index 0000000..9f908b3 Binary files /dev/null and b/venv/Lib/site-packages/packaging/__pycache__/specifiers.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/packaging/__pycache__/tags.cpython-311.pyc b/venv/Lib/site-packages/packaging/__pycache__/tags.cpython-311.pyc new file mode 100644 index 0000000..04b2796 Binary files /dev/null and b/venv/Lib/site-packages/packaging/__pycache__/tags.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/packaging/__pycache__/utils.cpython-311.pyc b/venv/Lib/site-packages/packaging/__pycache__/utils.cpython-311.pyc new file mode 100644 index 0000000..142524d Binary files /dev/null and b/venv/Lib/site-packages/packaging/__pycache__/utils.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/packaging/__pycache__/version.cpython-311.pyc b/venv/Lib/site-packages/packaging/__pycache__/version.cpython-311.pyc new file mode 100644 index 0000000..cc6a260 Binary files /dev/null and b/venv/Lib/site-packages/packaging/__pycache__/version.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/packaging/_elffile.py b/venv/Lib/site-packages/packaging/_elffile.py new file mode 100644 index 0000000..25f4282 --- /dev/null +++ b/venv/Lib/site-packages/packaging/_elffile.py @@ -0,0 +1,110 @@ +""" +ELF file parser. + +This provides a class ``ELFFile`` that parses an ELF executable in a similar +interface to ``ZipFile``. Only the read interface is implemented. + +Based on: https://gist.github.com/lyssdod/f51579ae8d93c8657a5564aefc2ffbca +ELF header: https://refspecs.linuxfoundation.org/elf/gabi4+/ch4.eheader.html +""" + +from __future__ import annotations + +import enum +import os +import struct +from typing import IO + + +class ELFInvalid(ValueError): + pass + + +class EIClass(enum.IntEnum): + C32 = 1 + C64 = 2 + + +class EIData(enum.IntEnum): + Lsb = 1 + Msb = 2 + + +class EMachine(enum.IntEnum): + I386 = 3 + S390 = 22 + Arm = 40 + X8664 = 62 + AArc64 = 183 + + +class ELFFile: + """ + Representation of an ELF executable. + """ + + def __init__(self, f: IO[bytes]) -> None: + self._f = f + + try: + ident = self._read("16B") + except struct.error as e: + raise ELFInvalid("unable to parse identification") from e + magic = bytes(ident[:4]) + if magic != b"\x7fELF": + raise ELFInvalid(f"invalid magic: {magic!r}") + + self.capacity = ident[4] # Format for program header (bitness). + self.encoding = ident[5] # Data structure encoding (endianness). + + try: + # e_fmt: Format for program header. + # p_fmt: Format for section header. + # p_idx: Indexes to find p_type, p_offset, and p_filesz. + e_fmt, self._p_fmt, self._p_idx = { + (1, 1): ("HHIIIIIHHH", ">IIIIIIII", (0, 1, 4)), # 32-bit MSB. + (2, 1): ("HHIQQQIHHH", ">IIQQQQQQ", (0, 2, 5)), # 64-bit MSB. + }[(self.capacity, self.encoding)] + except KeyError as e: + raise ELFInvalid( + f"unrecognized capacity ({self.capacity}) or " + f"encoding ({self.encoding})" + ) from e + + try: + ( + _, + self.machine, # Architecture type. + _, + _, + self._e_phoff, # Offset of program header. + _, + self.flags, # Processor-specific flags. + _, + self._e_phentsize, # Size of section. + self._e_phnum, # Number of sections. + ) = self._read(e_fmt) + except struct.error as e: + raise ELFInvalid("unable to parse machine and section information") from e + + def _read(self, fmt: str) -> tuple[int, ...]: + return struct.unpack(fmt, self._f.read(struct.calcsize(fmt))) + + @property + def interpreter(self) -> str | None: + """ + The path recorded in the ``PT_INTERP`` section header. + """ + for index in range(self._e_phnum): + self._f.seek(self._e_phoff + self._e_phentsize * index) + try: + data = self._read(self._p_fmt) + except struct.error: + continue + if data[self._p_idx[0]] != 3: # Not PT_INTERP. + continue + self._f.seek(data[self._p_idx[1]]) + return os.fsdecode(self._f.read(data[self._p_idx[2]])).strip("\0") + return None diff --git a/venv/Lib/site-packages/packaging/_manylinux.py b/venv/Lib/site-packages/packaging/_manylinux.py new file mode 100644 index 0000000..61339a6 --- /dev/null +++ b/venv/Lib/site-packages/packaging/_manylinux.py @@ -0,0 +1,263 @@ +from __future__ import annotations + +import collections +import contextlib +import functools +import os +import re +import sys +import warnings +from typing import Generator, Iterator, NamedTuple, Sequence + +from ._elffile import EIClass, EIData, ELFFile, EMachine + +EF_ARM_ABIMASK = 0xFF000000 +EF_ARM_ABI_VER5 = 0x05000000 +EF_ARM_ABI_FLOAT_HARD = 0x00000400 + + +# `os.PathLike` not a generic type until Python 3.9, so sticking with `str` +# as the type for `path` until then. +@contextlib.contextmanager +def _parse_elf(path: str) -> Generator[ELFFile | None, None, None]: + try: + with open(path, "rb") as f: + yield ELFFile(f) + except (OSError, TypeError, ValueError): + yield None + + +def _is_linux_armhf(executable: str) -> bool: + # hard-float ABI can be detected from the ELF header of the running + # process + # https://static.docs.arm.com/ihi0044/g/aaelf32.pdf + with _parse_elf(executable) as f: + return ( + f is not None + and f.capacity == EIClass.C32 + and f.encoding == EIData.Lsb + and f.machine == EMachine.Arm + and f.flags & EF_ARM_ABIMASK == EF_ARM_ABI_VER5 + and f.flags & EF_ARM_ABI_FLOAT_HARD == EF_ARM_ABI_FLOAT_HARD + ) + + +def _is_linux_i686(executable: str) -> bool: + with _parse_elf(executable) as f: + return ( + f is not None + and f.capacity == EIClass.C32 + and f.encoding == EIData.Lsb + and f.machine == EMachine.I386 + ) + + +def _have_compatible_abi(executable: str, archs: Sequence[str]) -> bool: + if "armv7l" in archs: + return _is_linux_armhf(executable) + if "i686" in archs: + return _is_linux_i686(executable) + allowed_archs = { + "x86_64", + "aarch64", + "ppc64", + "ppc64le", + "s390x", + "loongarch64", + "riscv64", + } + return any(arch in allowed_archs for arch in archs) + + +# If glibc ever changes its major version, we need to know what the last +# minor version was, so we can build the complete list of all versions. +# For now, guess what the highest minor version might be, assume it will +# be 50 for testing. Once this actually happens, update the dictionary +# with the actual value. +_LAST_GLIBC_MINOR: dict[int, int] = collections.defaultdict(lambda: 50) + + +class _GLibCVersion(NamedTuple): + major: int + minor: int + + +def _glibc_version_string_confstr() -> str | None: + """ + Primary implementation of glibc_version_string using os.confstr. + """ + # os.confstr is quite a bit faster than ctypes.DLL. It's also less likely + # to be broken or missing. This strategy is used in the standard library + # platform module. + # https://github.com/python/cpython/blob/fcf1d003bf4f0100c/Lib/platform.py#L175-L183 + try: + # Should be a string like "glibc 2.17". + version_string: str | None = os.confstr("CS_GNU_LIBC_VERSION") + assert version_string is not None + _, version = version_string.rsplit() + except (AssertionError, AttributeError, OSError, ValueError): + # os.confstr() or CS_GNU_LIBC_VERSION not available (or a bad value)... + return None + return version + + +def _glibc_version_string_ctypes() -> str | None: + """ + Fallback implementation of glibc_version_string using ctypes. + """ + try: + import ctypes + except ImportError: + return None + + # ctypes.CDLL(None) internally calls dlopen(NULL), and as the dlopen + # manpage says, "If filename is NULL, then the returned handle is for the + # main program". This way we can let the linker do the work to figure out + # which libc our process is actually using. + # + # We must also handle the special case where the executable is not a + # dynamically linked executable. This can occur when using musl libc, + # for example. In this situation, dlopen() will error, leading to an + # OSError. Interestingly, at least in the case of musl, there is no + # errno set on the OSError. The single string argument used to construct + # OSError comes from libc itself and is therefore not portable to + # hard code here. In any case, failure to call dlopen() means we + # can proceed, so we bail on our attempt. + try: + process_namespace = ctypes.CDLL(None) + except OSError: + return None + + try: + gnu_get_libc_version = process_namespace.gnu_get_libc_version + except AttributeError: + # Symbol doesn't exist -> therefore, we are not linked to + # glibc. + return None + + # Call gnu_get_libc_version, which returns a string like "2.5" + gnu_get_libc_version.restype = ctypes.c_char_p + version_str: str = gnu_get_libc_version() + # py2 / py3 compatibility: + if not isinstance(version_str, str): + version_str = version_str.decode("ascii") + + return version_str + + +def _glibc_version_string() -> str | None: + """Returns glibc version string, or None if not using glibc.""" + return _glibc_version_string_confstr() or _glibc_version_string_ctypes() + + +def _parse_glibc_version(version_str: str) -> tuple[int, int]: + """Parse glibc version. + + We use a regexp instead of str.split because we want to discard any + random junk that might come after the minor version -- this might happen + in patched/forked versions of glibc (e.g. Linaro's version of glibc + uses version strings like "2.20-2014.11"). See gh-3588. + """ + m = re.match(r"(?P[0-9]+)\.(?P[0-9]+)", version_str) + if not m: + warnings.warn( + f"Expected glibc version with 2 components major.minor," + f" got: {version_str}", + RuntimeWarning, + stacklevel=2, + ) + return -1, -1 + return int(m.group("major")), int(m.group("minor")) + + +@functools.lru_cache +def _get_glibc_version() -> tuple[int, int]: + version_str = _glibc_version_string() + if version_str is None: + return (-1, -1) + return _parse_glibc_version(version_str) + + +# From PEP 513, PEP 600 +def _is_compatible(arch: str, version: _GLibCVersion) -> bool: + sys_glibc = _get_glibc_version() + if sys_glibc < version: + return False + # Check for presence of _manylinux module. + try: + import _manylinux + except ImportError: + return True + if hasattr(_manylinux, "manylinux_compatible"): + result = _manylinux.manylinux_compatible(version[0], version[1], arch) + if result is not None: + return bool(result) + return True + if version == _GLibCVersion(2, 5): + if hasattr(_manylinux, "manylinux1_compatible"): + return bool(_manylinux.manylinux1_compatible) + if version == _GLibCVersion(2, 12): + if hasattr(_manylinux, "manylinux2010_compatible"): + return bool(_manylinux.manylinux2010_compatible) + if version == _GLibCVersion(2, 17): + if hasattr(_manylinux, "manylinux2014_compatible"): + return bool(_manylinux.manylinux2014_compatible) + return True + + +_LEGACY_MANYLINUX_MAP = { + # CentOS 7 w/ glibc 2.17 (PEP 599) + (2, 17): "manylinux2014", + # CentOS 6 w/ glibc 2.12 (PEP 571) + (2, 12): "manylinux2010", + # CentOS 5 w/ glibc 2.5 (PEP 513) + (2, 5): "manylinux1", +} + + +def platform_tags(archs: Sequence[str]) -> Iterator[str]: + """Generate manylinux tags compatible to the current platform. + + :param archs: Sequence of compatible architectures. + The first one shall be the closest to the actual architecture and be the part of + platform tag after the ``linux_`` prefix, e.g. ``x86_64``. + The ``linux_`` prefix is assumed as a prerequisite for the current platform to + be manylinux-compatible. + + :returns: An iterator of compatible manylinux tags. + """ + if not _have_compatible_abi(sys.executable, archs): + return + # Oldest glibc to be supported regardless of architecture is (2, 17). + too_old_glibc2 = _GLibCVersion(2, 16) + if set(archs) & {"x86_64", "i686"}: + # On x86/i686 also oldest glibc to be supported is (2, 5). + too_old_glibc2 = _GLibCVersion(2, 4) + current_glibc = _GLibCVersion(*_get_glibc_version()) + glibc_max_list = [current_glibc] + # We can assume compatibility across glibc major versions. + # https://sourceware.org/bugzilla/show_bug.cgi?id=24636 + # + # Build a list of maximum glibc versions so that we can + # output the canonical list of all glibc from current_glibc + # down to too_old_glibc2, including all intermediary versions. + for glibc_major in range(current_glibc.major - 1, 1, -1): + glibc_minor = _LAST_GLIBC_MINOR[glibc_major] + glibc_max_list.append(_GLibCVersion(glibc_major, glibc_minor)) + for arch in archs: + for glibc_max in glibc_max_list: + if glibc_max.major == too_old_glibc2.major: + min_minor = too_old_glibc2.minor + else: + # For other glibc major versions oldest supported is (x, 0). + min_minor = -1 + for glibc_minor in range(glibc_max.minor, min_minor, -1): + glibc_version = _GLibCVersion(glibc_max.major, glibc_minor) + tag = "manylinux_{}_{}".format(*glibc_version) + if _is_compatible(arch, glibc_version): + yield f"{tag}_{arch}" + # Handle the legacy manylinux1, manylinux2010, manylinux2014 tags. + if glibc_version in _LEGACY_MANYLINUX_MAP: + legacy_tag = _LEGACY_MANYLINUX_MAP[glibc_version] + if _is_compatible(arch, glibc_version): + yield f"{legacy_tag}_{arch}" diff --git a/venv/Lib/site-packages/packaging/_musllinux.py b/venv/Lib/site-packages/packaging/_musllinux.py new file mode 100644 index 0000000..d2bf30b --- /dev/null +++ b/venv/Lib/site-packages/packaging/_musllinux.py @@ -0,0 +1,85 @@ +"""PEP 656 support. + +This module implements logic to detect if the currently running Python is +linked against musl, and what musl version is used. +""" + +from __future__ import annotations + +import functools +import re +import subprocess +import sys +from typing import Iterator, NamedTuple, Sequence + +from ._elffile import ELFFile + + +class _MuslVersion(NamedTuple): + major: int + minor: int + + +def _parse_musl_version(output: str) -> _MuslVersion | None: + lines = [n for n in (n.strip() for n in output.splitlines()) if n] + if len(lines) < 2 or lines[0][:4] != "musl": + return None + m = re.match(r"Version (\d+)\.(\d+)", lines[1]) + if not m: + return None + return _MuslVersion(major=int(m.group(1)), minor=int(m.group(2))) + + +@functools.lru_cache +def _get_musl_version(executable: str) -> _MuslVersion | None: + """Detect currently-running musl runtime version. + + This is done by checking the specified executable's dynamic linking + information, and invoking the loader to parse its output for a version + string. If the loader is musl, the output would be something like:: + + musl libc (x86_64) + Version 1.2.2 + Dynamic Program Loader + """ + try: + with open(executable, "rb") as f: + ld = ELFFile(f).interpreter + except (OSError, TypeError, ValueError): + return None + if ld is None or "musl" not in ld: + return None + proc = subprocess.run([ld], stderr=subprocess.PIPE, text=True) + return _parse_musl_version(proc.stderr) + + +def platform_tags(archs: Sequence[str]) -> Iterator[str]: + """Generate musllinux tags compatible to the current platform. + + :param archs: Sequence of compatible architectures. + The first one shall be the closest to the actual architecture and be the part of + platform tag after the ``linux_`` prefix, e.g. ``x86_64``. + The ``linux_`` prefix is assumed as a prerequisite for the current platform to + be musllinux-compatible. + + :returns: An iterator of compatible musllinux tags. + """ + sys_musl = _get_musl_version(sys.executable) + if sys_musl is None: # Python not dynamically linked against musl. + return + for arch in archs: + for minor in range(sys_musl.minor, -1, -1): + yield f"musllinux_{sys_musl.major}_{minor}_{arch}" + + +if __name__ == "__main__": # pragma: no cover + import sysconfig + + plat = sysconfig.get_platform() + assert plat.startswith("linux-"), "not linux" + + print("plat:", plat) + print("musl:", _get_musl_version(sys.executable)) + print("tags:", end=" ") + for t in platform_tags(re.sub(r"[.-]", "_", plat.split("-", 1)[-1])): + print(t, end="\n ") diff --git a/venv/Lib/site-packages/packaging/_parser.py b/venv/Lib/site-packages/packaging/_parser.py new file mode 100644 index 0000000..c1238c0 --- /dev/null +++ b/venv/Lib/site-packages/packaging/_parser.py @@ -0,0 +1,354 @@ +"""Handwritten parser of dependency specifiers. + +The docstring for each __parse_* function contains EBNF-inspired grammar representing +the implementation. +""" + +from __future__ import annotations + +import ast +from typing import NamedTuple, Sequence, Tuple, Union + +from ._tokenizer import DEFAULT_RULES, Tokenizer + + +class Node: + def __init__(self, value: str) -> None: + self.value = value + + def __str__(self) -> str: + return self.value + + def __repr__(self) -> str: + return f"<{self.__class__.__name__}('{self}')>" + + def serialize(self) -> str: + raise NotImplementedError + + +class Variable(Node): + def serialize(self) -> str: + return str(self) + + +class Value(Node): + def serialize(self) -> str: + return f'"{self}"' + + +class Op(Node): + def serialize(self) -> str: + return str(self) + + +MarkerVar = Union[Variable, Value] +MarkerItem = Tuple[MarkerVar, Op, MarkerVar] +MarkerAtom = Union[MarkerItem, Sequence["MarkerAtom"]] +MarkerList = Sequence[Union["MarkerList", MarkerAtom, str]] + + +class ParsedRequirement(NamedTuple): + name: str + url: str + extras: list[str] + specifier: str + marker: MarkerList | None + + +# -------------------------------------------------------------------------------------- +# Recursive descent parser for dependency specifier +# -------------------------------------------------------------------------------------- +def parse_requirement(source: str) -> ParsedRequirement: + return _parse_requirement(Tokenizer(source, rules=DEFAULT_RULES)) + + +def _parse_requirement(tokenizer: Tokenizer) -> ParsedRequirement: + """ + requirement = WS? IDENTIFIER WS? extras WS? requirement_details + """ + tokenizer.consume("WS") + + name_token = tokenizer.expect( + "IDENTIFIER", expected="package name at the start of dependency specifier" + ) + name = name_token.text + tokenizer.consume("WS") + + extras = _parse_extras(tokenizer) + tokenizer.consume("WS") + + url, specifier, marker = _parse_requirement_details(tokenizer) + tokenizer.expect("END", expected="end of dependency specifier") + + return ParsedRequirement(name, url, extras, specifier, marker) + + +def _parse_requirement_details( + tokenizer: Tokenizer, +) -> tuple[str, str, MarkerList | None]: + """ + requirement_details = AT URL (WS requirement_marker?)? + | specifier WS? (requirement_marker)? + """ + + specifier = "" + url = "" + marker = None + + if tokenizer.check("AT"): + tokenizer.read() + tokenizer.consume("WS") + + url_start = tokenizer.position + url = tokenizer.expect("URL", expected="URL after @").text + if tokenizer.check("END", peek=True): + return (url, specifier, marker) + + tokenizer.expect("WS", expected="whitespace after URL") + + # The input might end after whitespace. + if tokenizer.check("END", peek=True): + return (url, specifier, marker) + + marker = _parse_requirement_marker( + tokenizer, span_start=url_start, after="URL and whitespace" + ) + else: + specifier_start = tokenizer.position + specifier = _parse_specifier(tokenizer) + tokenizer.consume("WS") + + if tokenizer.check("END", peek=True): + return (url, specifier, marker) + + marker = _parse_requirement_marker( + tokenizer, + span_start=specifier_start, + after=( + "version specifier" + if specifier + else "name and no valid version specifier" + ), + ) + + return (url, specifier, marker) + + +def _parse_requirement_marker( + tokenizer: Tokenizer, *, span_start: int, after: str +) -> MarkerList: + """ + requirement_marker = SEMICOLON marker WS? + """ + + if not tokenizer.check("SEMICOLON"): + tokenizer.raise_syntax_error( + f"Expected end or semicolon (after {after})", + span_start=span_start, + ) + tokenizer.read() + + marker = _parse_marker(tokenizer) + tokenizer.consume("WS") + + return marker + + +def _parse_extras(tokenizer: Tokenizer) -> list[str]: + """ + extras = (LEFT_BRACKET wsp* extras_list? wsp* RIGHT_BRACKET)? + """ + if not tokenizer.check("LEFT_BRACKET", peek=True): + return [] + + with tokenizer.enclosing_tokens( + "LEFT_BRACKET", + "RIGHT_BRACKET", + around="extras", + ): + tokenizer.consume("WS") + extras = _parse_extras_list(tokenizer) + tokenizer.consume("WS") + + return extras + + +def _parse_extras_list(tokenizer: Tokenizer) -> list[str]: + """ + extras_list = identifier (wsp* ',' wsp* identifier)* + """ + extras: list[str] = [] + + if not tokenizer.check("IDENTIFIER"): + return extras + + extras.append(tokenizer.read().text) + + while True: + tokenizer.consume("WS") + if tokenizer.check("IDENTIFIER", peek=True): + tokenizer.raise_syntax_error("Expected comma between extra names") + elif not tokenizer.check("COMMA"): + break + + tokenizer.read() + tokenizer.consume("WS") + + extra_token = tokenizer.expect("IDENTIFIER", expected="extra name after comma") + extras.append(extra_token.text) + + return extras + + +def _parse_specifier(tokenizer: Tokenizer) -> str: + """ + specifier = LEFT_PARENTHESIS WS? version_many WS? RIGHT_PARENTHESIS + | WS? version_many WS? + """ + with tokenizer.enclosing_tokens( + "LEFT_PARENTHESIS", + "RIGHT_PARENTHESIS", + around="version specifier", + ): + tokenizer.consume("WS") + parsed_specifiers = _parse_version_many(tokenizer) + tokenizer.consume("WS") + + return parsed_specifiers + + +def _parse_version_many(tokenizer: Tokenizer) -> str: + """ + version_many = (SPECIFIER (WS? COMMA WS? SPECIFIER)*)? + """ + parsed_specifiers = "" + while tokenizer.check("SPECIFIER"): + span_start = tokenizer.position + parsed_specifiers += tokenizer.read().text + if tokenizer.check("VERSION_PREFIX_TRAIL", peek=True): + tokenizer.raise_syntax_error( + ".* suffix can only be used with `==` or `!=` operators", + span_start=span_start, + span_end=tokenizer.position + 1, + ) + if tokenizer.check("VERSION_LOCAL_LABEL_TRAIL", peek=True): + tokenizer.raise_syntax_error( + "Local version label can only be used with `==` or `!=` operators", + span_start=span_start, + span_end=tokenizer.position, + ) + tokenizer.consume("WS") + if not tokenizer.check("COMMA"): + break + parsed_specifiers += tokenizer.read().text + tokenizer.consume("WS") + + return parsed_specifiers + + +# -------------------------------------------------------------------------------------- +# Recursive descent parser for marker expression +# -------------------------------------------------------------------------------------- +def parse_marker(source: str) -> MarkerList: + return _parse_full_marker(Tokenizer(source, rules=DEFAULT_RULES)) + + +def _parse_full_marker(tokenizer: Tokenizer) -> MarkerList: + retval = _parse_marker(tokenizer) + tokenizer.expect("END", expected="end of marker expression") + return retval + + +def _parse_marker(tokenizer: Tokenizer) -> MarkerList: + """ + marker = marker_atom (BOOLOP marker_atom)+ + """ + expression = [_parse_marker_atom(tokenizer)] + while tokenizer.check("BOOLOP"): + token = tokenizer.read() + expr_right = _parse_marker_atom(tokenizer) + expression.extend((token.text, expr_right)) + return expression + + +def _parse_marker_atom(tokenizer: Tokenizer) -> MarkerAtom: + """ + marker_atom = WS? LEFT_PARENTHESIS WS? marker WS? RIGHT_PARENTHESIS WS? + | WS? marker_item WS? + """ + + tokenizer.consume("WS") + if tokenizer.check("LEFT_PARENTHESIS", peek=True): + with tokenizer.enclosing_tokens( + "LEFT_PARENTHESIS", + "RIGHT_PARENTHESIS", + around="marker expression", + ): + tokenizer.consume("WS") + marker: MarkerAtom = _parse_marker(tokenizer) + tokenizer.consume("WS") + else: + marker = _parse_marker_item(tokenizer) + tokenizer.consume("WS") + return marker + + +def _parse_marker_item(tokenizer: Tokenizer) -> MarkerItem: + """ + marker_item = WS? marker_var WS? marker_op WS? marker_var WS? + """ + tokenizer.consume("WS") + marker_var_left = _parse_marker_var(tokenizer) + tokenizer.consume("WS") + marker_op = _parse_marker_op(tokenizer) + tokenizer.consume("WS") + marker_var_right = _parse_marker_var(tokenizer) + tokenizer.consume("WS") + return (marker_var_left, marker_op, marker_var_right) + + +def _parse_marker_var(tokenizer: Tokenizer) -> MarkerVar: + """ + marker_var = VARIABLE | QUOTED_STRING + """ + if tokenizer.check("VARIABLE"): + return process_env_var(tokenizer.read().text.replace(".", "_")) + elif tokenizer.check("QUOTED_STRING"): + return process_python_str(tokenizer.read().text) + else: + tokenizer.raise_syntax_error( + message="Expected a marker variable or quoted string" + ) + + +def process_env_var(env_var: str) -> Variable: + if env_var in ("platform_python_implementation", "python_implementation"): + return Variable("platform_python_implementation") + else: + return Variable(env_var) + + +def process_python_str(python_str: str) -> Value: + value = ast.literal_eval(python_str) + return Value(str(value)) + + +def _parse_marker_op(tokenizer: Tokenizer) -> Op: + """ + marker_op = IN | NOT IN | OP + """ + if tokenizer.check("IN"): + tokenizer.read() + return Op("in") + elif tokenizer.check("NOT"): + tokenizer.read() + tokenizer.expect("WS", expected="whitespace after 'not'") + tokenizer.expect("IN", expected="'in' after 'not'") + return Op("not in") + elif tokenizer.check("OP"): + return Op(tokenizer.read().text) + else: + return tokenizer.raise_syntax_error( + "Expected marker operator, one of " + "<=, <, !=, ==, >=, >, ~=, ===, in, not in" + ) diff --git a/venv/Lib/site-packages/packaging/_structures.py b/venv/Lib/site-packages/packaging/_structures.py new file mode 100644 index 0000000..90a6465 --- /dev/null +++ b/venv/Lib/site-packages/packaging/_structures.py @@ -0,0 +1,61 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +class InfinityType: + def __repr__(self) -> str: + return "Infinity" + + def __hash__(self) -> int: + return hash(repr(self)) + + def __lt__(self, other: object) -> bool: + return False + + def __le__(self, other: object) -> bool: + return False + + def __eq__(self, other: object) -> bool: + return isinstance(other, self.__class__) + + def __gt__(self, other: object) -> bool: + return True + + def __ge__(self, other: object) -> bool: + return True + + def __neg__(self: object) -> "NegativeInfinityType": + return NegativeInfinity + + +Infinity = InfinityType() + + +class NegativeInfinityType: + def __repr__(self) -> str: + return "-Infinity" + + def __hash__(self) -> int: + return hash(repr(self)) + + def __lt__(self, other: object) -> bool: + return True + + def __le__(self, other: object) -> bool: + return True + + def __eq__(self, other: object) -> bool: + return isinstance(other, self.__class__) + + def __gt__(self, other: object) -> bool: + return False + + def __ge__(self, other: object) -> bool: + return False + + def __neg__(self: object) -> InfinityType: + return Infinity + + +NegativeInfinity = NegativeInfinityType() diff --git a/venv/Lib/site-packages/packaging/_tokenizer.py b/venv/Lib/site-packages/packaging/_tokenizer.py new file mode 100644 index 0000000..89d0416 --- /dev/null +++ b/venv/Lib/site-packages/packaging/_tokenizer.py @@ -0,0 +1,194 @@ +from __future__ import annotations + +import contextlib +import re +from dataclasses import dataclass +from typing import Iterator, NoReturn + +from .specifiers import Specifier + + +@dataclass +class Token: + name: str + text: str + position: int + + +class ParserSyntaxError(Exception): + """The provided source text could not be parsed correctly.""" + + def __init__( + self, + message: str, + *, + source: str, + span: tuple[int, int], + ) -> None: + self.span = span + self.message = message + self.source = source + + super().__init__() + + def __str__(self) -> str: + marker = " " * self.span[0] + "~" * (self.span[1] - self.span[0]) + "^" + return "\n ".join([self.message, self.source, marker]) + + +DEFAULT_RULES: dict[str, str | re.Pattern[str]] = { + "LEFT_PARENTHESIS": r"\(", + "RIGHT_PARENTHESIS": r"\)", + "LEFT_BRACKET": r"\[", + "RIGHT_BRACKET": r"\]", + "SEMICOLON": r";", + "COMMA": r",", + "QUOTED_STRING": re.compile( + r""" + ( + ('[^']*') + | + ("[^"]*") + ) + """, + re.VERBOSE, + ), + "OP": r"(===|==|~=|!=|<=|>=|<|>)", + "BOOLOP": r"\b(or|and)\b", + "IN": r"\bin\b", + "NOT": r"\bnot\b", + "VARIABLE": re.compile( + r""" + \b( + python_version + |python_full_version + |os[._]name + |sys[._]platform + |platform_(release|system) + |platform[._](version|machine|python_implementation) + |python_implementation + |implementation_(name|version) + |extra + )\b + """, + re.VERBOSE, + ), + "SPECIFIER": re.compile( + Specifier._operator_regex_str + Specifier._version_regex_str, + re.VERBOSE | re.IGNORECASE, + ), + "AT": r"\@", + "URL": r"[^ \t]+", + "IDENTIFIER": r"\b[a-zA-Z0-9][a-zA-Z0-9._-]*\b", + "VERSION_PREFIX_TRAIL": r"\.\*", + "VERSION_LOCAL_LABEL_TRAIL": r"\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*", + "WS": r"[ \t]+", + "END": r"$", +} + + +class Tokenizer: + """Context-sensitive token parsing. + + Provides methods to examine the input stream to check whether the next token + matches. + """ + + def __init__( + self, + source: str, + *, + rules: dict[str, str | re.Pattern[str]], + ) -> None: + self.source = source + self.rules: dict[str, re.Pattern[str]] = { + name: re.compile(pattern) for name, pattern in rules.items() + } + self.next_token: Token | None = None + self.position = 0 + + def consume(self, name: str) -> None: + """Move beyond provided token name, if at current position.""" + if self.check(name): + self.read() + + def check(self, name: str, *, peek: bool = False) -> bool: + """Check whether the next token has the provided name. + + By default, if the check succeeds, the token *must* be read before + another check. If `peek` is set to `True`, the token is not loaded and + would need to be checked again. + """ + assert ( + self.next_token is None + ), f"Cannot check for {name!r}, already have {self.next_token!r}" + assert name in self.rules, f"Unknown token name: {name!r}" + + expression = self.rules[name] + + match = expression.match(self.source, self.position) + if match is None: + return False + if not peek: + self.next_token = Token(name, match[0], self.position) + return True + + def expect(self, name: str, *, expected: str) -> Token: + """Expect a certain token name next, failing with a syntax error otherwise. + + The token is *not* read. + """ + if not self.check(name): + raise self.raise_syntax_error(f"Expected {expected}") + return self.read() + + def read(self) -> Token: + """Consume the next token and return it.""" + token = self.next_token + assert token is not None + + self.position += len(token.text) + self.next_token = None + + return token + + def raise_syntax_error( + self, + message: str, + *, + span_start: int | None = None, + span_end: int | None = None, + ) -> NoReturn: + """Raise ParserSyntaxError at the given position.""" + span = ( + self.position if span_start is None else span_start, + self.position if span_end is None else span_end, + ) + raise ParserSyntaxError( + message, + source=self.source, + span=span, + ) + + @contextlib.contextmanager + def enclosing_tokens( + self, open_token: str, close_token: str, *, around: str + ) -> Iterator[None]: + if self.check(open_token): + open_position = self.position + self.read() + else: + open_position = None + + yield + + if open_position is None: + return + + if not self.check(close_token): + self.raise_syntax_error( + f"Expected matching {close_token} for {open_token}, after {around}", + span_start=open_position, + ) + + self.read() diff --git a/venv/Lib/site-packages/packaging/licenses/__init__.py b/venv/Lib/site-packages/packaging/licenses/__init__.py new file mode 100644 index 0000000..569156d --- /dev/null +++ b/venv/Lib/site-packages/packaging/licenses/__init__.py @@ -0,0 +1,145 @@ +####################################################################################### +# +# Adapted from: +# https://github.com/pypa/hatch/blob/5352e44/backend/src/hatchling/licenses/parse.py +# +# MIT License +# +# Copyright (c) 2017-present Ofek Lev +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this +# software and associated documentation files (the "Software"), to deal in the Software +# without restriction, including without limitation the rights to use, copy, modify, +# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to the following +# conditions: +# +# The above copyright notice and this permission notice shall be included in all copies +# or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE +# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# +# With additional allowance of arbitrary `LicenseRef-` identifiers, not just +# `LicenseRef-Public-Domain` and `LicenseRef-Proprietary`. +# +####################################################################################### +from __future__ import annotations + +import re +from typing import NewType, cast + +from packaging.licenses._spdx import EXCEPTIONS, LICENSES + +__all__ = [ + "NormalizedLicenseExpression", + "InvalidLicenseExpression", + "canonicalize_license_expression", +] + +license_ref_allowed = re.compile("^[A-Za-z0-9.-]*$") + +NormalizedLicenseExpression = NewType("NormalizedLicenseExpression", str) + + +class InvalidLicenseExpression(ValueError): + """Raised when a license-expression string is invalid + + >>> canonicalize_license_expression("invalid") + Traceback (most recent call last): + ... + packaging.licenses.InvalidLicenseExpression: Invalid license expression: 'invalid' + """ + + +def canonicalize_license_expression( + raw_license_expression: str, +) -> NormalizedLicenseExpression: + if not raw_license_expression: + message = f"Invalid license expression: {raw_license_expression!r}" + raise InvalidLicenseExpression(message) + + # Pad any parentheses so tokenization can be achieved by merely splitting on + # whitespace. + license_expression = raw_license_expression.replace("(", " ( ").replace(")", " ) ") + licenseref_prefix = "LicenseRef-" + license_refs = { + ref.lower(): "LicenseRef-" + ref[len(licenseref_prefix) :] + for ref in license_expression.split() + if ref.lower().startswith(licenseref_prefix.lower()) + } + + # Normalize to lower case so we can look up licenses/exceptions + # and so boolean operators are Python-compatible. + license_expression = license_expression.lower() + + tokens = license_expression.split() + + # Rather than implementing boolean logic, we create an expression that Python can + # parse. Everything that is not involved with the grammar itself is treated as + # `False` and the expression should evaluate as such. + python_tokens = [] + for token in tokens: + if token not in {"or", "and", "with", "(", ")"}: + python_tokens.append("False") + elif token == "with": + python_tokens.append("or") + elif token == "(" and python_tokens and python_tokens[-1] not in {"or", "and"}: + message = f"Invalid license expression: {raw_license_expression!r}" + raise InvalidLicenseExpression(message) + else: + python_tokens.append(token) + + python_expression = " ".join(python_tokens) + try: + invalid = eval(python_expression, globals(), locals()) + except Exception: + invalid = True + + if invalid is not False: + message = f"Invalid license expression: {raw_license_expression!r}" + raise InvalidLicenseExpression(message) from None + + # Take a final pass to check for unknown licenses/exceptions. + normalized_tokens = [] + for token in tokens: + if token in {"or", "and", "with", "(", ")"}: + normalized_tokens.append(token.upper()) + continue + + if normalized_tokens and normalized_tokens[-1] == "WITH": + if token not in EXCEPTIONS: + message = f"Unknown license exception: {token!r}" + raise InvalidLicenseExpression(message) + + normalized_tokens.append(EXCEPTIONS[token]["id"]) + else: + if token.endswith("+"): + final_token = token[:-1] + suffix = "+" + else: + final_token = token + suffix = "" + + if final_token.startswith("licenseref-"): + if not license_ref_allowed.match(final_token): + message = f"Invalid licenseref: {final_token!r}" + raise InvalidLicenseExpression(message) + normalized_tokens.append(license_refs[final_token] + suffix) + else: + if final_token not in LICENSES: + message = f"Unknown license: {final_token!r}" + raise InvalidLicenseExpression(message) + normalized_tokens.append(LICENSES[final_token]["id"] + suffix) + + normalized_expression = " ".join(normalized_tokens) + + return cast( + NormalizedLicenseExpression, + normalized_expression.replace("( ", "(").replace(" )", ")"), + ) diff --git a/venv/Lib/site-packages/packaging/licenses/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/packaging/licenses/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..36a061c Binary files /dev/null and b/venv/Lib/site-packages/packaging/licenses/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/packaging/licenses/__pycache__/_spdx.cpython-311.pyc b/venv/Lib/site-packages/packaging/licenses/__pycache__/_spdx.cpython-311.pyc new file mode 100644 index 0000000..4ede5f7 Binary files /dev/null and b/venv/Lib/site-packages/packaging/licenses/__pycache__/_spdx.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/packaging/licenses/_spdx.py b/venv/Lib/site-packages/packaging/licenses/_spdx.py new file mode 100644 index 0000000..eac2227 --- /dev/null +++ b/venv/Lib/site-packages/packaging/licenses/_spdx.py @@ -0,0 +1,759 @@ + +from __future__ import annotations + +from typing import TypedDict + +class SPDXLicense(TypedDict): + id: str + deprecated: bool + +class SPDXException(TypedDict): + id: str + deprecated: bool + + +VERSION = '3.25.0' + +LICENSES: dict[str, SPDXLicense] = { + '0bsd': {'id': '0BSD', 'deprecated': False}, + '3d-slicer-1.0': {'id': '3D-Slicer-1.0', 'deprecated': False}, + 'aal': {'id': 'AAL', 'deprecated': False}, + 'abstyles': {'id': 'Abstyles', 'deprecated': False}, + 'adacore-doc': {'id': 'AdaCore-doc', 'deprecated': False}, + 'adobe-2006': {'id': 'Adobe-2006', 'deprecated': False}, + 'adobe-display-postscript': {'id': 'Adobe-Display-PostScript', 'deprecated': False}, + 'adobe-glyph': {'id': 'Adobe-Glyph', 'deprecated': False}, + 'adobe-utopia': {'id': 'Adobe-Utopia', 'deprecated': False}, + 'adsl': {'id': 'ADSL', 'deprecated': False}, + 'afl-1.1': {'id': 'AFL-1.1', 'deprecated': False}, + 'afl-1.2': {'id': 'AFL-1.2', 'deprecated': False}, + 'afl-2.0': {'id': 'AFL-2.0', 'deprecated': False}, + 'afl-2.1': {'id': 'AFL-2.1', 'deprecated': False}, + 'afl-3.0': {'id': 'AFL-3.0', 'deprecated': False}, + 'afmparse': {'id': 'Afmparse', 'deprecated': False}, + 'agpl-1.0': {'id': 'AGPL-1.0', 'deprecated': True}, + 'agpl-1.0-only': {'id': 'AGPL-1.0-only', 'deprecated': False}, + 'agpl-1.0-or-later': {'id': 'AGPL-1.0-or-later', 'deprecated': False}, + 'agpl-3.0': {'id': 'AGPL-3.0', 'deprecated': True}, + 'agpl-3.0-only': {'id': 'AGPL-3.0-only', 'deprecated': False}, + 'agpl-3.0-or-later': {'id': 'AGPL-3.0-or-later', 'deprecated': False}, + 'aladdin': {'id': 'Aladdin', 'deprecated': False}, + 'amd-newlib': {'id': 'AMD-newlib', 'deprecated': False}, + 'amdplpa': {'id': 'AMDPLPA', 'deprecated': False}, + 'aml': {'id': 'AML', 'deprecated': False}, + 'aml-glslang': {'id': 'AML-glslang', 'deprecated': False}, + 'ampas': {'id': 'AMPAS', 'deprecated': False}, + 'antlr-pd': {'id': 'ANTLR-PD', 'deprecated': False}, + 'antlr-pd-fallback': {'id': 'ANTLR-PD-fallback', 'deprecated': False}, + 'any-osi': {'id': 'any-OSI', 'deprecated': False}, + 'apache-1.0': {'id': 'Apache-1.0', 'deprecated': False}, + 'apache-1.1': {'id': 'Apache-1.1', 'deprecated': False}, + 'apache-2.0': {'id': 'Apache-2.0', 'deprecated': False}, + 'apafml': {'id': 'APAFML', 'deprecated': False}, + 'apl-1.0': {'id': 'APL-1.0', 'deprecated': False}, + 'app-s2p': {'id': 'App-s2p', 'deprecated': False}, + 'apsl-1.0': {'id': 'APSL-1.0', 'deprecated': False}, + 'apsl-1.1': {'id': 'APSL-1.1', 'deprecated': False}, + 'apsl-1.2': {'id': 'APSL-1.2', 'deprecated': False}, + 'apsl-2.0': {'id': 'APSL-2.0', 'deprecated': False}, + 'arphic-1999': {'id': 'Arphic-1999', 'deprecated': False}, + 'artistic-1.0': {'id': 'Artistic-1.0', 'deprecated': False}, + 'artistic-1.0-cl8': {'id': 'Artistic-1.0-cl8', 'deprecated': False}, + 'artistic-1.0-perl': {'id': 'Artistic-1.0-Perl', 'deprecated': False}, + 'artistic-2.0': {'id': 'Artistic-2.0', 'deprecated': False}, + 'aswf-digital-assets-1.0': {'id': 'ASWF-Digital-Assets-1.0', 'deprecated': False}, + 'aswf-digital-assets-1.1': {'id': 'ASWF-Digital-Assets-1.1', 'deprecated': False}, + 'baekmuk': {'id': 'Baekmuk', 'deprecated': False}, + 'bahyph': {'id': 'Bahyph', 'deprecated': False}, + 'barr': {'id': 'Barr', 'deprecated': False}, + 'bcrypt-solar-designer': {'id': 'bcrypt-Solar-Designer', 'deprecated': False}, + 'beerware': {'id': 'Beerware', 'deprecated': False}, + 'bitstream-charter': {'id': 'Bitstream-Charter', 'deprecated': False}, + 'bitstream-vera': {'id': 'Bitstream-Vera', 'deprecated': False}, + 'bittorrent-1.0': {'id': 'BitTorrent-1.0', 'deprecated': False}, + 'bittorrent-1.1': {'id': 'BitTorrent-1.1', 'deprecated': False}, + 'blessing': {'id': 'blessing', 'deprecated': False}, + 'blueoak-1.0.0': {'id': 'BlueOak-1.0.0', 'deprecated': False}, + 'boehm-gc': {'id': 'Boehm-GC', 'deprecated': False}, + 'borceux': {'id': 'Borceux', 'deprecated': False}, + 'brian-gladman-2-clause': {'id': 'Brian-Gladman-2-Clause', 'deprecated': False}, + 'brian-gladman-3-clause': {'id': 'Brian-Gladman-3-Clause', 'deprecated': False}, + 'bsd-1-clause': {'id': 'BSD-1-Clause', 'deprecated': False}, + 'bsd-2-clause': {'id': 'BSD-2-Clause', 'deprecated': False}, + 'bsd-2-clause-darwin': {'id': 'BSD-2-Clause-Darwin', 'deprecated': False}, + 'bsd-2-clause-first-lines': {'id': 'BSD-2-Clause-first-lines', 'deprecated': False}, + 'bsd-2-clause-freebsd': {'id': 'BSD-2-Clause-FreeBSD', 'deprecated': True}, + 'bsd-2-clause-netbsd': {'id': 'BSD-2-Clause-NetBSD', 'deprecated': True}, + 'bsd-2-clause-patent': {'id': 'BSD-2-Clause-Patent', 'deprecated': False}, + 'bsd-2-clause-views': {'id': 'BSD-2-Clause-Views', 'deprecated': False}, + 'bsd-3-clause': {'id': 'BSD-3-Clause', 'deprecated': False}, + 'bsd-3-clause-acpica': {'id': 'BSD-3-Clause-acpica', 'deprecated': False}, + 'bsd-3-clause-attribution': {'id': 'BSD-3-Clause-Attribution', 'deprecated': False}, + 'bsd-3-clause-clear': {'id': 'BSD-3-Clause-Clear', 'deprecated': False}, + 'bsd-3-clause-flex': {'id': 'BSD-3-Clause-flex', 'deprecated': False}, + 'bsd-3-clause-hp': {'id': 'BSD-3-Clause-HP', 'deprecated': False}, + 'bsd-3-clause-lbnl': {'id': 'BSD-3-Clause-LBNL', 'deprecated': False}, + 'bsd-3-clause-modification': {'id': 'BSD-3-Clause-Modification', 'deprecated': False}, + 'bsd-3-clause-no-military-license': {'id': 'BSD-3-Clause-No-Military-License', 'deprecated': False}, + 'bsd-3-clause-no-nuclear-license': {'id': 'BSD-3-Clause-No-Nuclear-License', 'deprecated': False}, + 'bsd-3-clause-no-nuclear-license-2014': {'id': 'BSD-3-Clause-No-Nuclear-License-2014', 'deprecated': False}, + 'bsd-3-clause-no-nuclear-warranty': {'id': 'BSD-3-Clause-No-Nuclear-Warranty', 'deprecated': False}, + 'bsd-3-clause-open-mpi': {'id': 'BSD-3-Clause-Open-MPI', 'deprecated': False}, + 'bsd-3-clause-sun': {'id': 'BSD-3-Clause-Sun', 'deprecated': False}, + 'bsd-4-clause': {'id': 'BSD-4-Clause', 'deprecated': False}, + 'bsd-4-clause-shortened': {'id': 'BSD-4-Clause-Shortened', 'deprecated': False}, + 'bsd-4-clause-uc': {'id': 'BSD-4-Clause-UC', 'deprecated': False}, + 'bsd-4.3reno': {'id': 'BSD-4.3RENO', 'deprecated': False}, + 'bsd-4.3tahoe': {'id': 'BSD-4.3TAHOE', 'deprecated': False}, + 'bsd-advertising-acknowledgement': {'id': 'BSD-Advertising-Acknowledgement', 'deprecated': False}, + 'bsd-attribution-hpnd-disclaimer': {'id': 'BSD-Attribution-HPND-disclaimer', 'deprecated': False}, + 'bsd-inferno-nettverk': {'id': 'BSD-Inferno-Nettverk', 'deprecated': False}, + 'bsd-protection': {'id': 'BSD-Protection', 'deprecated': False}, + 'bsd-source-beginning-file': {'id': 'BSD-Source-beginning-file', 'deprecated': False}, + 'bsd-source-code': {'id': 'BSD-Source-Code', 'deprecated': False}, + 'bsd-systemics': {'id': 'BSD-Systemics', 'deprecated': False}, + 'bsd-systemics-w3works': {'id': 'BSD-Systemics-W3Works', 'deprecated': False}, + 'bsl-1.0': {'id': 'BSL-1.0', 'deprecated': False}, + 'busl-1.1': {'id': 'BUSL-1.1', 'deprecated': False}, + 'bzip2-1.0.5': {'id': 'bzip2-1.0.5', 'deprecated': True}, + 'bzip2-1.0.6': {'id': 'bzip2-1.0.6', 'deprecated': False}, + 'c-uda-1.0': {'id': 'C-UDA-1.0', 'deprecated': False}, + 'cal-1.0': {'id': 'CAL-1.0', 'deprecated': False}, + 'cal-1.0-combined-work-exception': {'id': 'CAL-1.0-Combined-Work-Exception', 'deprecated': False}, + 'caldera': {'id': 'Caldera', 'deprecated': False}, + 'caldera-no-preamble': {'id': 'Caldera-no-preamble', 'deprecated': False}, + 'catharon': {'id': 'Catharon', 'deprecated': False}, + 'catosl-1.1': {'id': 'CATOSL-1.1', 'deprecated': False}, + 'cc-by-1.0': {'id': 'CC-BY-1.0', 'deprecated': False}, + 'cc-by-2.0': {'id': 'CC-BY-2.0', 'deprecated': False}, + 'cc-by-2.5': {'id': 'CC-BY-2.5', 'deprecated': False}, + 'cc-by-2.5-au': {'id': 'CC-BY-2.5-AU', 'deprecated': False}, + 'cc-by-3.0': {'id': 'CC-BY-3.0', 'deprecated': False}, + 'cc-by-3.0-at': {'id': 'CC-BY-3.0-AT', 'deprecated': False}, + 'cc-by-3.0-au': {'id': 'CC-BY-3.0-AU', 'deprecated': False}, + 'cc-by-3.0-de': {'id': 'CC-BY-3.0-DE', 'deprecated': False}, + 'cc-by-3.0-igo': {'id': 'CC-BY-3.0-IGO', 'deprecated': False}, + 'cc-by-3.0-nl': {'id': 'CC-BY-3.0-NL', 'deprecated': False}, + 'cc-by-3.0-us': {'id': 'CC-BY-3.0-US', 'deprecated': False}, + 'cc-by-4.0': {'id': 'CC-BY-4.0', 'deprecated': False}, + 'cc-by-nc-1.0': {'id': 'CC-BY-NC-1.0', 'deprecated': False}, + 'cc-by-nc-2.0': {'id': 'CC-BY-NC-2.0', 'deprecated': False}, + 'cc-by-nc-2.5': {'id': 'CC-BY-NC-2.5', 'deprecated': False}, + 'cc-by-nc-3.0': {'id': 'CC-BY-NC-3.0', 'deprecated': False}, + 'cc-by-nc-3.0-de': {'id': 'CC-BY-NC-3.0-DE', 'deprecated': False}, + 'cc-by-nc-4.0': {'id': 'CC-BY-NC-4.0', 'deprecated': False}, + 'cc-by-nc-nd-1.0': {'id': 'CC-BY-NC-ND-1.0', 'deprecated': False}, + 'cc-by-nc-nd-2.0': {'id': 'CC-BY-NC-ND-2.0', 'deprecated': False}, + 'cc-by-nc-nd-2.5': {'id': 'CC-BY-NC-ND-2.5', 'deprecated': False}, + 'cc-by-nc-nd-3.0': {'id': 'CC-BY-NC-ND-3.0', 'deprecated': False}, + 'cc-by-nc-nd-3.0-de': {'id': 'CC-BY-NC-ND-3.0-DE', 'deprecated': False}, + 'cc-by-nc-nd-3.0-igo': {'id': 'CC-BY-NC-ND-3.0-IGO', 'deprecated': False}, + 'cc-by-nc-nd-4.0': {'id': 'CC-BY-NC-ND-4.0', 'deprecated': False}, + 'cc-by-nc-sa-1.0': {'id': 'CC-BY-NC-SA-1.0', 'deprecated': False}, + 'cc-by-nc-sa-2.0': {'id': 'CC-BY-NC-SA-2.0', 'deprecated': False}, + 'cc-by-nc-sa-2.0-de': {'id': 'CC-BY-NC-SA-2.0-DE', 'deprecated': False}, + 'cc-by-nc-sa-2.0-fr': {'id': 'CC-BY-NC-SA-2.0-FR', 'deprecated': False}, + 'cc-by-nc-sa-2.0-uk': {'id': 'CC-BY-NC-SA-2.0-UK', 'deprecated': False}, + 'cc-by-nc-sa-2.5': {'id': 'CC-BY-NC-SA-2.5', 'deprecated': False}, + 'cc-by-nc-sa-3.0': {'id': 'CC-BY-NC-SA-3.0', 'deprecated': False}, + 'cc-by-nc-sa-3.0-de': {'id': 'CC-BY-NC-SA-3.0-DE', 'deprecated': False}, + 'cc-by-nc-sa-3.0-igo': {'id': 'CC-BY-NC-SA-3.0-IGO', 'deprecated': False}, + 'cc-by-nc-sa-4.0': {'id': 'CC-BY-NC-SA-4.0', 'deprecated': False}, + 'cc-by-nd-1.0': {'id': 'CC-BY-ND-1.0', 'deprecated': False}, + 'cc-by-nd-2.0': {'id': 'CC-BY-ND-2.0', 'deprecated': False}, + 'cc-by-nd-2.5': {'id': 'CC-BY-ND-2.5', 'deprecated': False}, + 'cc-by-nd-3.0': {'id': 'CC-BY-ND-3.0', 'deprecated': False}, + 'cc-by-nd-3.0-de': {'id': 'CC-BY-ND-3.0-DE', 'deprecated': False}, + 'cc-by-nd-4.0': {'id': 'CC-BY-ND-4.0', 'deprecated': False}, + 'cc-by-sa-1.0': {'id': 'CC-BY-SA-1.0', 'deprecated': False}, + 'cc-by-sa-2.0': {'id': 'CC-BY-SA-2.0', 'deprecated': False}, + 'cc-by-sa-2.0-uk': {'id': 'CC-BY-SA-2.0-UK', 'deprecated': False}, + 'cc-by-sa-2.1-jp': {'id': 'CC-BY-SA-2.1-JP', 'deprecated': False}, + 'cc-by-sa-2.5': {'id': 'CC-BY-SA-2.5', 'deprecated': False}, + 'cc-by-sa-3.0': {'id': 'CC-BY-SA-3.0', 'deprecated': False}, + 'cc-by-sa-3.0-at': {'id': 'CC-BY-SA-3.0-AT', 'deprecated': False}, + 'cc-by-sa-3.0-de': {'id': 'CC-BY-SA-3.0-DE', 'deprecated': False}, + 'cc-by-sa-3.0-igo': {'id': 'CC-BY-SA-3.0-IGO', 'deprecated': False}, + 'cc-by-sa-4.0': {'id': 'CC-BY-SA-4.0', 'deprecated': False}, + 'cc-pddc': {'id': 'CC-PDDC', 'deprecated': False}, + 'cc0-1.0': {'id': 'CC0-1.0', 'deprecated': False}, + 'cddl-1.0': {'id': 'CDDL-1.0', 'deprecated': False}, + 'cddl-1.1': {'id': 'CDDL-1.1', 'deprecated': False}, + 'cdl-1.0': {'id': 'CDL-1.0', 'deprecated': False}, + 'cdla-permissive-1.0': {'id': 'CDLA-Permissive-1.0', 'deprecated': False}, + 'cdla-permissive-2.0': {'id': 'CDLA-Permissive-2.0', 'deprecated': False}, + 'cdla-sharing-1.0': {'id': 'CDLA-Sharing-1.0', 'deprecated': False}, + 'cecill-1.0': {'id': 'CECILL-1.0', 'deprecated': False}, + 'cecill-1.1': {'id': 'CECILL-1.1', 'deprecated': False}, + 'cecill-2.0': {'id': 'CECILL-2.0', 'deprecated': False}, + 'cecill-2.1': {'id': 'CECILL-2.1', 'deprecated': False}, + 'cecill-b': {'id': 'CECILL-B', 'deprecated': False}, + 'cecill-c': {'id': 'CECILL-C', 'deprecated': False}, + 'cern-ohl-1.1': {'id': 'CERN-OHL-1.1', 'deprecated': False}, + 'cern-ohl-1.2': {'id': 'CERN-OHL-1.2', 'deprecated': False}, + 'cern-ohl-p-2.0': {'id': 'CERN-OHL-P-2.0', 'deprecated': False}, + 'cern-ohl-s-2.0': {'id': 'CERN-OHL-S-2.0', 'deprecated': False}, + 'cern-ohl-w-2.0': {'id': 'CERN-OHL-W-2.0', 'deprecated': False}, + 'cfitsio': {'id': 'CFITSIO', 'deprecated': False}, + 'check-cvs': {'id': 'check-cvs', 'deprecated': False}, + 'checkmk': {'id': 'checkmk', 'deprecated': False}, + 'clartistic': {'id': 'ClArtistic', 'deprecated': False}, + 'clips': {'id': 'Clips', 'deprecated': False}, + 'cmu-mach': {'id': 'CMU-Mach', 'deprecated': False}, + 'cmu-mach-nodoc': {'id': 'CMU-Mach-nodoc', 'deprecated': False}, + 'cnri-jython': {'id': 'CNRI-Jython', 'deprecated': False}, + 'cnri-python': {'id': 'CNRI-Python', 'deprecated': False}, + 'cnri-python-gpl-compatible': {'id': 'CNRI-Python-GPL-Compatible', 'deprecated': False}, + 'coil-1.0': {'id': 'COIL-1.0', 'deprecated': False}, + 'community-spec-1.0': {'id': 'Community-Spec-1.0', 'deprecated': False}, + 'condor-1.1': {'id': 'Condor-1.1', 'deprecated': False}, + 'copyleft-next-0.3.0': {'id': 'copyleft-next-0.3.0', 'deprecated': False}, + 'copyleft-next-0.3.1': {'id': 'copyleft-next-0.3.1', 'deprecated': False}, + 'cornell-lossless-jpeg': {'id': 'Cornell-Lossless-JPEG', 'deprecated': False}, + 'cpal-1.0': {'id': 'CPAL-1.0', 'deprecated': False}, + 'cpl-1.0': {'id': 'CPL-1.0', 'deprecated': False}, + 'cpol-1.02': {'id': 'CPOL-1.02', 'deprecated': False}, + 'cronyx': {'id': 'Cronyx', 'deprecated': False}, + 'crossword': {'id': 'Crossword', 'deprecated': False}, + 'crystalstacker': {'id': 'CrystalStacker', 'deprecated': False}, + 'cua-opl-1.0': {'id': 'CUA-OPL-1.0', 'deprecated': False}, + 'cube': {'id': 'Cube', 'deprecated': False}, + 'curl': {'id': 'curl', 'deprecated': False}, + 'cve-tou': {'id': 'cve-tou', 'deprecated': False}, + 'd-fsl-1.0': {'id': 'D-FSL-1.0', 'deprecated': False}, + 'dec-3-clause': {'id': 'DEC-3-Clause', 'deprecated': False}, + 'diffmark': {'id': 'diffmark', 'deprecated': False}, + 'dl-de-by-2.0': {'id': 'DL-DE-BY-2.0', 'deprecated': False}, + 'dl-de-zero-2.0': {'id': 'DL-DE-ZERO-2.0', 'deprecated': False}, + 'doc': {'id': 'DOC', 'deprecated': False}, + 'docbook-schema': {'id': 'DocBook-Schema', 'deprecated': False}, + 'docbook-xml': {'id': 'DocBook-XML', 'deprecated': False}, + 'dotseqn': {'id': 'Dotseqn', 'deprecated': False}, + 'drl-1.0': {'id': 'DRL-1.0', 'deprecated': False}, + 'drl-1.1': {'id': 'DRL-1.1', 'deprecated': False}, + 'dsdp': {'id': 'DSDP', 'deprecated': False}, + 'dtoa': {'id': 'dtoa', 'deprecated': False}, + 'dvipdfm': {'id': 'dvipdfm', 'deprecated': False}, + 'ecl-1.0': {'id': 'ECL-1.0', 'deprecated': False}, + 'ecl-2.0': {'id': 'ECL-2.0', 'deprecated': False}, + 'ecos-2.0': {'id': 'eCos-2.0', 'deprecated': True}, + 'efl-1.0': {'id': 'EFL-1.0', 'deprecated': False}, + 'efl-2.0': {'id': 'EFL-2.0', 'deprecated': False}, + 'egenix': {'id': 'eGenix', 'deprecated': False}, + 'elastic-2.0': {'id': 'Elastic-2.0', 'deprecated': False}, + 'entessa': {'id': 'Entessa', 'deprecated': False}, + 'epics': {'id': 'EPICS', 'deprecated': False}, + 'epl-1.0': {'id': 'EPL-1.0', 'deprecated': False}, + 'epl-2.0': {'id': 'EPL-2.0', 'deprecated': False}, + 'erlpl-1.1': {'id': 'ErlPL-1.1', 'deprecated': False}, + 'etalab-2.0': {'id': 'etalab-2.0', 'deprecated': False}, + 'eudatagrid': {'id': 'EUDatagrid', 'deprecated': False}, + 'eupl-1.0': {'id': 'EUPL-1.0', 'deprecated': False}, + 'eupl-1.1': {'id': 'EUPL-1.1', 'deprecated': False}, + 'eupl-1.2': {'id': 'EUPL-1.2', 'deprecated': False}, + 'eurosym': {'id': 'Eurosym', 'deprecated': False}, + 'fair': {'id': 'Fair', 'deprecated': False}, + 'fbm': {'id': 'FBM', 'deprecated': False}, + 'fdk-aac': {'id': 'FDK-AAC', 'deprecated': False}, + 'ferguson-twofish': {'id': 'Ferguson-Twofish', 'deprecated': False}, + 'frameworx-1.0': {'id': 'Frameworx-1.0', 'deprecated': False}, + 'freebsd-doc': {'id': 'FreeBSD-DOC', 'deprecated': False}, + 'freeimage': {'id': 'FreeImage', 'deprecated': False}, + 'fsfap': {'id': 'FSFAP', 'deprecated': False}, + 'fsfap-no-warranty-disclaimer': {'id': 'FSFAP-no-warranty-disclaimer', 'deprecated': False}, + 'fsful': {'id': 'FSFUL', 'deprecated': False}, + 'fsfullr': {'id': 'FSFULLR', 'deprecated': False}, + 'fsfullrwd': {'id': 'FSFULLRWD', 'deprecated': False}, + 'ftl': {'id': 'FTL', 'deprecated': False}, + 'furuseth': {'id': 'Furuseth', 'deprecated': False}, + 'fwlw': {'id': 'fwlw', 'deprecated': False}, + 'gcr-docs': {'id': 'GCR-docs', 'deprecated': False}, + 'gd': {'id': 'GD', 'deprecated': False}, + 'gfdl-1.1': {'id': 'GFDL-1.1', 'deprecated': True}, + 'gfdl-1.1-invariants-only': {'id': 'GFDL-1.1-invariants-only', 'deprecated': False}, + 'gfdl-1.1-invariants-or-later': {'id': 'GFDL-1.1-invariants-or-later', 'deprecated': False}, + 'gfdl-1.1-no-invariants-only': {'id': 'GFDL-1.1-no-invariants-only', 'deprecated': False}, + 'gfdl-1.1-no-invariants-or-later': {'id': 'GFDL-1.1-no-invariants-or-later', 'deprecated': False}, + 'gfdl-1.1-only': {'id': 'GFDL-1.1-only', 'deprecated': False}, + 'gfdl-1.1-or-later': {'id': 'GFDL-1.1-or-later', 'deprecated': False}, + 'gfdl-1.2': {'id': 'GFDL-1.2', 'deprecated': True}, + 'gfdl-1.2-invariants-only': {'id': 'GFDL-1.2-invariants-only', 'deprecated': False}, + 'gfdl-1.2-invariants-or-later': {'id': 'GFDL-1.2-invariants-or-later', 'deprecated': False}, + 'gfdl-1.2-no-invariants-only': {'id': 'GFDL-1.2-no-invariants-only', 'deprecated': False}, + 'gfdl-1.2-no-invariants-or-later': {'id': 'GFDL-1.2-no-invariants-or-later', 'deprecated': False}, + 'gfdl-1.2-only': {'id': 'GFDL-1.2-only', 'deprecated': False}, + 'gfdl-1.2-or-later': {'id': 'GFDL-1.2-or-later', 'deprecated': False}, + 'gfdl-1.3': {'id': 'GFDL-1.3', 'deprecated': True}, + 'gfdl-1.3-invariants-only': {'id': 'GFDL-1.3-invariants-only', 'deprecated': False}, + 'gfdl-1.3-invariants-or-later': {'id': 'GFDL-1.3-invariants-or-later', 'deprecated': False}, + 'gfdl-1.3-no-invariants-only': {'id': 'GFDL-1.3-no-invariants-only', 'deprecated': False}, + 'gfdl-1.3-no-invariants-or-later': {'id': 'GFDL-1.3-no-invariants-or-later', 'deprecated': False}, + 'gfdl-1.3-only': {'id': 'GFDL-1.3-only', 'deprecated': False}, + 'gfdl-1.3-or-later': {'id': 'GFDL-1.3-or-later', 'deprecated': False}, + 'giftware': {'id': 'Giftware', 'deprecated': False}, + 'gl2ps': {'id': 'GL2PS', 'deprecated': False}, + 'glide': {'id': 'Glide', 'deprecated': False}, + 'glulxe': {'id': 'Glulxe', 'deprecated': False}, + 'glwtpl': {'id': 'GLWTPL', 'deprecated': False}, + 'gnuplot': {'id': 'gnuplot', 'deprecated': False}, + 'gpl-1.0': {'id': 'GPL-1.0', 'deprecated': True}, + 'gpl-1.0+': {'id': 'GPL-1.0+', 'deprecated': True}, + 'gpl-1.0-only': {'id': 'GPL-1.0-only', 'deprecated': False}, + 'gpl-1.0-or-later': {'id': 'GPL-1.0-or-later', 'deprecated': False}, + 'gpl-2.0': {'id': 'GPL-2.0', 'deprecated': True}, + 'gpl-2.0+': {'id': 'GPL-2.0+', 'deprecated': True}, + 'gpl-2.0-only': {'id': 'GPL-2.0-only', 'deprecated': False}, + 'gpl-2.0-or-later': {'id': 'GPL-2.0-or-later', 'deprecated': False}, + 'gpl-2.0-with-autoconf-exception': {'id': 'GPL-2.0-with-autoconf-exception', 'deprecated': True}, + 'gpl-2.0-with-bison-exception': {'id': 'GPL-2.0-with-bison-exception', 'deprecated': True}, + 'gpl-2.0-with-classpath-exception': {'id': 'GPL-2.0-with-classpath-exception', 'deprecated': True}, + 'gpl-2.0-with-font-exception': {'id': 'GPL-2.0-with-font-exception', 'deprecated': True}, + 'gpl-2.0-with-gcc-exception': {'id': 'GPL-2.0-with-GCC-exception', 'deprecated': True}, + 'gpl-3.0': {'id': 'GPL-3.0', 'deprecated': True}, + 'gpl-3.0+': {'id': 'GPL-3.0+', 'deprecated': True}, + 'gpl-3.0-only': {'id': 'GPL-3.0-only', 'deprecated': False}, + 'gpl-3.0-or-later': {'id': 'GPL-3.0-or-later', 'deprecated': False}, + 'gpl-3.0-with-autoconf-exception': {'id': 'GPL-3.0-with-autoconf-exception', 'deprecated': True}, + 'gpl-3.0-with-gcc-exception': {'id': 'GPL-3.0-with-GCC-exception', 'deprecated': True}, + 'graphics-gems': {'id': 'Graphics-Gems', 'deprecated': False}, + 'gsoap-1.3b': {'id': 'gSOAP-1.3b', 'deprecated': False}, + 'gtkbook': {'id': 'gtkbook', 'deprecated': False}, + 'gutmann': {'id': 'Gutmann', 'deprecated': False}, + 'haskellreport': {'id': 'HaskellReport', 'deprecated': False}, + 'hdparm': {'id': 'hdparm', 'deprecated': False}, + 'hidapi': {'id': 'HIDAPI', 'deprecated': False}, + 'hippocratic-2.1': {'id': 'Hippocratic-2.1', 'deprecated': False}, + 'hp-1986': {'id': 'HP-1986', 'deprecated': False}, + 'hp-1989': {'id': 'HP-1989', 'deprecated': False}, + 'hpnd': {'id': 'HPND', 'deprecated': False}, + 'hpnd-dec': {'id': 'HPND-DEC', 'deprecated': False}, + 'hpnd-doc': {'id': 'HPND-doc', 'deprecated': False}, + 'hpnd-doc-sell': {'id': 'HPND-doc-sell', 'deprecated': False}, + 'hpnd-export-us': {'id': 'HPND-export-US', 'deprecated': False}, + 'hpnd-export-us-acknowledgement': {'id': 'HPND-export-US-acknowledgement', 'deprecated': False}, + 'hpnd-export-us-modify': {'id': 'HPND-export-US-modify', 'deprecated': False}, + 'hpnd-export2-us': {'id': 'HPND-export2-US', 'deprecated': False}, + 'hpnd-fenneberg-livingston': {'id': 'HPND-Fenneberg-Livingston', 'deprecated': False}, + 'hpnd-inria-imag': {'id': 'HPND-INRIA-IMAG', 'deprecated': False}, + 'hpnd-intel': {'id': 'HPND-Intel', 'deprecated': False}, + 'hpnd-kevlin-henney': {'id': 'HPND-Kevlin-Henney', 'deprecated': False}, + 'hpnd-markus-kuhn': {'id': 'HPND-Markus-Kuhn', 'deprecated': False}, + 'hpnd-merchantability-variant': {'id': 'HPND-merchantability-variant', 'deprecated': False}, + 'hpnd-mit-disclaimer': {'id': 'HPND-MIT-disclaimer', 'deprecated': False}, + 'hpnd-netrek': {'id': 'HPND-Netrek', 'deprecated': False}, + 'hpnd-pbmplus': {'id': 'HPND-Pbmplus', 'deprecated': False}, + 'hpnd-sell-mit-disclaimer-xserver': {'id': 'HPND-sell-MIT-disclaimer-xserver', 'deprecated': False}, + 'hpnd-sell-regexpr': {'id': 'HPND-sell-regexpr', 'deprecated': False}, + 'hpnd-sell-variant': {'id': 'HPND-sell-variant', 'deprecated': False}, + 'hpnd-sell-variant-mit-disclaimer': {'id': 'HPND-sell-variant-MIT-disclaimer', 'deprecated': False}, + 'hpnd-sell-variant-mit-disclaimer-rev': {'id': 'HPND-sell-variant-MIT-disclaimer-rev', 'deprecated': False}, + 'hpnd-uc': {'id': 'HPND-UC', 'deprecated': False}, + 'hpnd-uc-export-us': {'id': 'HPND-UC-export-US', 'deprecated': False}, + 'htmltidy': {'id': 'HTMLTIDY', 'deprecated': False}, + 'ibm-pibs': {'id': 'IBM-pibs', 'deprecated': False}, + 'icu': {'id': 'ICU', 'deprecated': False}, + 'iec-code-components-eula': {'id': 'IEC-Code-Components-EULA', 'deprecated': False}, + 'ijg': {'id': 'IJG', 'deprecated': False}, + 'ijg-short': {'id': 'IJG-short', 'deprecated': False}, + 'imagemagick': {'id': 'ImageMagick', 'deprecated': False}, + 'imatix': {'id': 'iMatix', 'deprecated': False}, + 'imlib2': {'id': 'Imlib2', 'deprecated': False}, + 'info-zip': {'id': 'Info-ZIP', 'deprecated': False}, + 'inner-net-2.0': {'id': 'Inner-Net-2.0', 'deprecated': False}, + 'intel': {'id': 'Intel', 'deprecated': False}, + 'intel-acpi': {'id': 'Intel-ACPI', 'deprecated': False}, + 'interbase-1.0': {'id': 'Interbase-1.0', 'deprecated': False}, + 'ipa': {'id': 'IPA', 'deprecated': False}, + 'ipl-1.0': {'id': 'IPL-1.0', 'deprecated': False}, + 'isc': {'id': 'ISC', 'deprecated': False}, + 'isc-veillard': {'id': 'ISC-Veillard', 'deprecated': False}, + 'jam': {'id': 'Jam', 'deprecated': False}, + 'jasper-2.0': {'id': 'JasPer-2.0', 'deprecated': False}, + 'jpl-image': {'id': 'JPL-image', 'deprecated': False}, + 'jpnic': {'id': 'JPNIC', 'deprecated': False}, + 'json': {'id': 'JSON', 'deprecated': False}, + 'kastrup': {'id': 'Kastrup', 'deprecated': False}, + 'kazlib': {'id': 'Kazlib', 'deprecated': False}, + 'knuth-ctan': {'id': 'Knuth-CTAN', 'deprecated': False}, + 'lal-1.2': {'id': 'LAL-1.2', 'deprecated': False}, + 'lal-1.3': {'id': 'LAL-1.3', 'deprecated': False}, + 'latex2e': {'id': 'Latex2e', 'deprecated': False}, + 'latex2e-translated-notice': {'id': 'Latex2e-translated-notice', 'deprecated': False}, + 'leptonica': {'id': 'Leptonica', 'deprecated': False}, + 'lgpl-2.0': {'id': 'LGPL-2.0', 'deprecated': True}, + 'lgpl-2.0+': {'id': 'LGPL-2.0+', 'deprecated': True}, + 'lgpl-2.0-only': {'id': 'LGPL-2.0-only', 'deprecated': False}, + 'lgpl-2.0-or-later': {'id': 'LGPL-2.0-or-later', 'deprecated': False}, + 'lgpl-2.1': {'id': 'LGPL-2.1', 'deprecated': True}, + 'lgpl-2.1+': {'id': 'LGPL-2.1+', 'deprecated': True}, + 'lgpl-2.1-only': {'id': 'LGPL-2.1-only', 'deprecated': False}, + 'lgpl-2.1-or-later': {'id': 'LGPL-2.1-or-later', 'deprecated': False}, + 'lgpl-3.0': {'id': 'LGPL-3.0', 'deprecated': True}, + 'lgpl-3.0+': {'id': 'LGPL-3.0+', 'deprecated': True}, + 'lgpl-3.0-only': {'id': 'LGPL-3.0-only', 'deprecated': False}, + 'lgpl-3.0-or-later': {'id': 'LGPL-3.0-or-later', 'deprecated': False}, + 'lgpllr': {'id': 'LGPLLR', 'deprecated': False}, + 'libpng': {'id': 'Libpng', 'deprecated': False}, + 'libpng-2.0': {'id': 'libpng-2.0', 'deprecated': False}, + 'libselinux-1.0': {'id': 'libselinux-1.0', 'deprecated': False}, + 'libtiff': {'id': 'libtiff', 'deprecated': False}, + 'libutil-david-nugent': {'id': 'libutil-David-Nugent', 'deprecated': False}, + 'liliq-p-1.1': {'id': 'LiLiQ-P-1.1', 'deprecated': False}, + 'liliq-r-1.1': {'id': 'LiLiQ-R-1.1', 'deprecated': False}, + 'liliq-rplus-1.1': {'id': 'LiLiQ-Rplus-1.1', 'deprecated': False}, + 'linux-man-pages-1-para': {'id': 'Linux-man-pages-1-para', 'deprecated': False}, + 'linux-man-pages-copyleft': {'id': 'Linux-man-pages-copyleft', 'deprecated': False}, + 'linux-man-pages-copyleft-2-para': {'id': 'Linux-man-pages-copyleft-2-para', 'deprecated': False}, + 'linux-man-pages-copyleft-var': {'id': 'Linux-man-pages-copyleft-var', 'deprecated': False}, + 'linux-openib': {'id': 'Linux-OpenIB', 'deprecated': False}, + 'loop': {'id': 'LOOP', 'deprecated': False}, + 'lpd-document': {'id': 'LPD-document', 'deprecated': False}, + 'lpl-1.0': {'id': 'LPL-1.0', 'deprecated': False}, + 'lpl-1.02': {'id': 'LPL-1.02', 'deprecated': False}, + 'lppl-1.0': {'id': 'LPPL-1.0', 'deprecated': False}, + 'lppl-1.1': {'id': 'LPPL-1.1', 'deprecated': False}, + 'lppl-1.2': {'id': 'LPPL-1.2', 'deprecated': False}, + 'lppl-1.3a': {'id': 'LPPL-1.3a', 'deprecated': False}, + 'lppl-1.3c': {'id': 'LPPL-1.3c', 'deprecated': False}, + 'lsof': {'id': 'lsof', 'deprecated': False}, + 'lucida-bitmap-fonts': {'id': 'Lucida-Bitmap-Fonts', 'deprecated': False}, + 'lzma-sdk-9.11-to-9.20': {'id': 'LZMA-SDK-9.11-to-9.20', 'deprecated': False}, + 'lzma-sdk-9.22': {'id': 'LZMA-SDK-9.22', 'deprecated': False}, + 'mackerras-3-clause': {'id': 'Mackerras-3-Clause', 'deprecated': False}, + 'mackerras-3-clause-acknowledgment': {'id': 'Mackerras-3-Clause-acknowledgment', 'deprecated': False}, + 'magaz': {'id': 'magaz', 'deprecated': False}, + 'mailprio': {'id': 'mailprio', 'deprecated': False}, + 'makeindex': {'id': 'MakeIndex', 'deprecated': False}, + 'martin-birgmeier': {'id': 'Martin-Birgmeier', 'deprecated': False}, + 'mcphee-slideshow': {'id': 'McPhee-slideshow', 'deprecated': False}, + 'metamail': {'id': 'metamail', 'deprecated': False}, + 'minpack': {'id': 'Minpack', 'deprecated': False}, + 'miros': {'id': 'MirOS', 'deprecated': False}, + 'mit': {'id': 'MIT', 'deprecated': False}, + 'mit-0': {'id': 'MIT-0', 'deprecated': False}, + 'mit-advertising': {'id': 'MIT-advertising', 'deprecated': False}, + 'mit-cmu': {'id': 'MIT-CMU', 'deprecated': False}, + 'mit-enna': {'id': 'MIT-enna', 'deprecated': False}, + 'mit-feh': {'id': 'MIT-feh', 'deprecated': False}, + 'mit-festival': {'id': 'MIT-Festival', 'deprecated': False}, + 'mit-khronos-old': {'id': 'MIT-Khronos-old', 'deprecated': False}, + 'mit-modern-variant': {'id': 'MIT-Modern-Variant', 'deprecated': False}, + 'mit-open-group': {'id': 'MIT-open-group', 'deprecated': False}, + 'mit-testregex': {'id': 'MIT-testregex', 'deprecated': False}, + 'mit-wu': {'id': 'MIT-Wu', 'deprecated': False}, + 'mitnfa': {'id': 'MITNFA', 'deprecated': False}, + 'mmixware': {'id': 'MMIXware', 'deprecated': False}, + 'motosoto': {'id': 'Motosoto', 'deprecated': False}, + 'mpeg-ssg': {'id': 'MPEG-SSG', 'deprecated': False}, + 'mpi-permissive': {'id': 'mpi-permissive', 'deprecated': False}, + 'mpich2': {'id': 'mpich2', 'deprecated': False}, + 'mpl-1.0': {'id': 'MPL-1.0', 'deprecated': False}, + 'mpl-1.1': {'id': 'MPL-1.1', 'deprecated': False}, + 'mpl-2.0': {'id': 'MPL-2.0', 'deprecated': False}, + 'mpl-2.0-no-copyleft-exception': {'id': 'MPL-2.0-no-copyleft-exception', 'deprecated': False}, + 'mplus': {'id': 'mplus', 'deprecated': False}, + 'ms-lpl': {'id': 'MS-LPL', 'deprecated': False}, + 'ms-pl': {'id': 'MS-PL', 'deprecated': False}, + 'ms-rl': {'id': 'MS-RL', 'deprecated': False}, + 'mtll': {'id': 'MTLL', 'deprecated': False}, + 'mulanpsl-1.0': {'id': 'MulanPSL-1.0', 'deprecated': False}, + 'mulanpsl-2.0': {'id': 'MulanPSL-2.0', 'deprecated': False}, + 'multics': {'id': 'Multics', 'deprecated': False}, + 'mup': {'id': 'Mup', 'deprecated': False}, + 'naist-2003': {'id': 'NAIST-2003', 'deprecated': False}, + 'nasa-1.3': {'id': 'NASA-1.3', 'deprecated': False}, + 'naumen': {'id': 'Naumen', 'deprecated': False}, + 'nbpl-1.0': {'id': 'NBPL-1.0', 'deprecated': False}, + 'ncbi-pd': {'id': 'NCBI-PD', 'deprecated': False}, + 'ncgl-uk-2.0': {'id': 'NCGL-UK-2.0', 'deprecated': False}, + 'ncl': {'id': 'NCL', 'deprecated': False}, + 'ncsa': {'id': 'NCSA', 'deprecated': False}, + 'net-snmp': {'id': 'Net-SNMP', 'deprecated': True}, + 'netcdf': {'id': 'NetCDF', 'deprecated': False}, + 'newsletr': {'id': 'Newsletr', 'deprecated': False}, + 'ngpl': {'id': 'NGPL', 'deprecated': False}, + 'nicta-1.0': {'id': 'NICTA-1.0', 'deprecated': False}, + 'nist-pd': {'id': 'NIST-PD', 'deprecated': False}, + 'nist-pd-fallback': {'id': 'NIST-PD-fallback', 'deprecated': False}, + 'nist-software': {'id': 'NIST-Software', 'deprecated': False}, + 'nlod-1.0': {'id': 'NLOD-1.0', 'deprecated': False}, + 'nlod-2.0': {'id': 'NLOD-2.0', 'deprecated': False}, + 'nlpl': {'id': 'NLPL', 'deprecated': False}, + 'nokia': {'id': 'Nokia', 'deprecated': False}, + 'nosl': {'id': 'NOSL', 'deprecated': False}, + 'noweb': {'id': 'Noweb', 'deprecated': False}, + 'npl-1.0': {'id': 'NPL-1.0', 'deprecated': False}, + 'npl-1.1': {'id': 'NPL-1.1', 'deprecated': False}, + 'nposl-3.0': {'id': 'NPOSL-3.0', 'deprecated': False}, + 'nrl': {'id': 'NRL', 'deprecated': False}, + 'ntp': {'id': 'NTP', 'deprecated': False}, + 'ntp-0': {'id': 'NTP-0', 'deprecated': False}, + 'nunit': {'id': 'Nunit', 'deprecated': True}, + 'o-uda-1.0': {'id': 'O-UDA-1.0', 'deprecated': False}, + 'oar': {'id': 'OAR', 'deprecated': False}, + 'occt-pl': {'id': 'OCCT-PL', 'deprecated': False}, + 'oclc-2.0': {'id': 'OCLC-2.0', 'deprecated': False}, + 'odbl-1.0': {'id': 'ODbL-1.0', 'deprecated': False}, + 'odc-by-1.0': {'id': 'ODC-By-1.0', 'deprecated': False}, + 'offis': {'id': 'OFFIS', 'deprecated': False}, + 'ofl-1.0': {'id': 'OFL-1.0', 'deprecated': False}, + 'ofl-1.0-no-rfn': {'id': 'OFL-1.0-no-RFN', 'deprecated': False}, + 'ofl-1.0-rfn': {'id': 'OFL-1.0-RFN', 'deprecated': False}, + 'ofl-1.1': {'id': 'OFL-1.1', 'deprecated': False}, + 'ofl-1.1-no-rfn': {'id': 'OFL-1.1-no-RFN', 'deprecated': False}, + 'ofl-1.1-rfn': {'id': 'OFL-1.1-RFN', 'deprecated': False}, + 'ogc-1.0': {'id': 'OGC-1.0', 'deprecated': False}, + 'ogdl-taiwan-1.0': {'id': 'OGDL-Taiwan-1.0', 'deprecated': False}, + 'ogl-canada-2.0': {'id': 'OGL-Canada-2.0', 'deprecated': False}, + 'ogl-uk-1.0': {'id': 'OGL-UK-1.0', 'deprecated': False}, + 'ogl-uk-2.0': {'id': 'OGL-UK-2.0', 'deprecated': False}, + 'ogl-uk-3.0': {'id': 'OGL-UK-3.0', 'deprecated': False}, + 'ogtsl': {'id': 'OGTSL', 'deprecated': False}, + 'oldap-1.1': {'id': 'OLDAP-1.1', 'deprecated': False}, + 'oldap-1.2': {'id': 'OLDAP-1.2', 'deprecated': False}, + 'oldap-1.3': {'id': 'OLDAP-1.3', 'deprecated': False}, + 'oldap-1.4': {'id': 'OLDAP-1.4', 'deprecated': False}, + 'oldap-2.0': {'id': 'OLDAP-2.0', 'deprecated': False}, + 'oldap-2.0.1': {'id': 'OLDAP-2.0.1', 'deprecated': False}, + 'oldap-2.1': {'id': 'OLDAP-2.1', 'deprecated': False}, + 'oldap-2.2': {'id': 'OLDAP-2.2', 'deprecated': False}, + 'oldap-2.2.1': {'id': 'OLDAP-2.2.1', 'deprecated': False}, + 'oldap-2.2.2': {'id': 'OLDAP-2.2.2', 'deprecated': False}, + 'oldap-2.3': {'id': 'OLDAP-2.3', 'deprecated': False}, + 'oldap-2.4': {'id': 'OLDAP-2.4', 'deprecated': False}, + 'oldap-2.5': {'id': 'OLDAP-2.5', 'deprecated': False}, + 'oldap-2.6': {'id': 'OLDAP-2.6', 'deprecated': False}, + 'oldap-2.7': {'id': 'OLDAP-2.7', 'deprecated': False}, + 'oldap-2.8': {'id': 'OLDAP-2.8', 'deprecated': False}, + 'olfl-1.3': {'id': 'OLFL-1.3', 'deprecated': False}, + 'oml': {'id': 'OML', 'deprecated': False}, + 'openpbs-2.3': {'id': 'OpenPBS-2.3', 'deprecated': False}, + 'openssl': {'id': 'OpenSSL', 'deprecated': False}, + 'openssl-standalone': {'id': 'OpenSSL-standalone', 'deprecated': False}, + 'openvision': {'id': 'OpenVision', 'deprecated': False}, + 'opl-1.0': {'id': 'OPL-1.0', 'deprecated': False}, + 'opl-uk-3.0': {'id': 'OPL-UK-3.0', 'deprecated': False}, + 'opubl-1.0': {'id': 'OPUBL-1.0', 'deprecated': False}, + 'oset-pl-2.1': {'id': 'OSET-PL-2.1', 'deprecated': False}, + 'osl-1.0': {'id': 'OSL-1.0', 'deprecated': False}, + 'osl-1.1': {'id': 'OSL-1.1', 'deprecated': False}, + 'osl-2.0': {'id': 'OSL-2.0', 'deprecated': False}, + 'osl-2.1': {'id': 'OSL-2.1', 'deprecated': False}, + 'osl-3.0': {'id': 'OSL-3.0', 'deprecated': False}, + 'padl': {'id': 'PADL', 'deprecated': False}, + 'parity-6.0.0': {'id': 'Parity-6.0.0', 'deprecated': False}, + 'parity-7.0.0': {'id': 'Parity-7.0.0', 'deprecated': False}, + 'pddl-1.0': {'id': 'PDDL-1.0', 'deprecated': False}, + 'php-3.0': {'id': 'PHP-3.0', 'deprecated': False}, + 'php-3.01': {'id': 'PHP-3.01', 'deprecated': False}, + 'pixar': {'id': 'Pixar', 'deprecated': False}, + 'pkgconf': {'id': 'pkgconf', 'deprecated': False}, + 'plexus': {'id': 'Plexus', 'deprecated': False}, + 'pnmstitch': {'id': 'pnmstitch', 'deprecated': False}, + 'polyform-noncommercial-1.0.0': {'id': 'PolyForm-Noncommercial-1.0.0', 'deprecated': False}, + 'polyform-small-business-1.0.0': {'id': 'PolyForm-Small-Business-1.0.0', 'deprecated': False}, + 'postgresql': {'id': 'PostgreSQL', 'deprecated': False}, + 'ppl': {'id': 'PPL', 'deprecated': False}, + 'psf-2.0': {'id': 'PSF-2.0', 'deprecated': False}, + 'psfrag': {'id': 'psfrag', 'deprecated': False}, + 'psutils': {'id': 'psutils', 'deprecated': False}, + 'python-2.0': {'id': 'Python-2.0', 'deprecated': False}, + 'python-2.0.1': {'id': 'Python-2.0.1', 'deprecated': False}, + 'python-ldap': {'id': 'python-ldap', 'deprecated': False}, + 'qhull': {'id': 'Qhull', 'deprecated': False}, + 'qpl-1.0': {'id': 'QPL-1.0', 'deprecated': False}, + 'qpl-1.0-inria-2004': {'id': 'QPL-1.0-INRIA-2004', 'deprecated': False}, + 'radvd': {'id': 'radvd', 'deprecated': False}, + 'rdisc': {'id': 'Rdisc', 'deprecated': False}, + 'rhecos-1.1': {'id': 'RHeCos-1.1', 'deprecated': False}, + 'rpl-1.1': {'id': 'RPL-1.1', 'deprecated': False}, + 'rpl-1.5': {'id': 'RPL-1.5', 'deprecated': False}, + 'rpsl-1.0': {'id': 'RPSL-1.0', 'deprecated': False}, + 'rsa-md': {'id': 'RSA-MD', 'deprecated': False}, + 'rscpl': {'id': 'RSCPL', 'deprecated': False}, + 'ruby': {'id': 'Ruby', 'deprecated': False}, + 'ruby-pty': {'id': 'Ruby-pty', 'deprecated': False}, + 'sax-pd': {'id': 'SAX-PD', 'deprecated': False}, + 'sax-pd-2.0': {'id': 'SAX-PD-2.0', 'deprecated': False}, + 'saxpath': {'id': 'Saxpath', 'deprecated': False}, + 'scea': {'id': 'SCEA', 'deprecated': False}, + 'schemereport': {'id': 'SchemeReport', 'deprecated': False}, + 'sendmail': {'id': 'Sendmail', 'deprecated': False}, + 'sendmail-8.23': {'id': 'Sendmail-8.23', 'deprecated': False}, + 'sgi-b-1.0': {'id': 'SGI-B-1.0', 'deprecated': False}, + 'sgi-b-1.1': {'id': 'SGI-B-1.1', 'deprecated': False}, + 'sgi-b-2.0': {'id': 'SGI-B-2.0', 'deprecated': False}, + 'sgi-opengl': {'id': 'SGI-OpenGL', 'deprecated': False}, + 'sgp4': {'id': 'SGP4', 'deprecated': False}, + 'shl-0.5': {'id': 'SHL-0.5', 'deprecated': False}, + 'shl-0.51': {'id': 'SHL-0.51', 'deprecated': False}, + 'simpl-2.0': {'id': 'SimPL-2.0', 'deprecated': False}, + 'sissl': {'id': 'SISSL', 'deprecated': False}, + 'sissl-1.2': {'id': 'SISSL-1.2', 'deprecated': False}, + 'sl': {'id': 'SL', 'deprecated': False}, + 'sleepycat': {'id': 'Sleepycat', 'deprecated': False}, + 'smlnj': {'id': 'SMLNJ', 'deprecated': False}, + 'smppl': {'id': 'SMPPL', 'deprecated': False}, + 'snia': {'id': 'SNIA', 'deprecated': False}, + 'snprintf': {'id': 'snprintf', 'deprecated': False}, + 'softsurfer': {'id': 'softSurfer', 'deprecated': False}, + 'soundex': {'id': 'Soundex', 'deprecated': False}, + 'spencer-86': {'id': 'Spencer-86', 'deprecated': False}, + 'spencer-94': {'id': 'Spencer-94', 'deprecated': False}, + 'spencer-99': {'id': 'Spencer-99', 'deprecated': False}, + 'spl-1.0': {'id': 'SPL-1.0', 'deprecated': False}, + 'ssh-keyscan': {'id': 'ssh-keyscan', 'deprecated': False}, + 'ssh-openssh': {'id': 'SSH-OpenSSH', 'deprecated': False}, + 'ssh-short': {'id': 'SSH-short', 'deprecated': False}, + 'ssleay-standalone': {'id': 'SSLeay-standalone', 'deprecated': False}, + 'sspl-1.0': {'id': 'SSPL-1.0', 'deprecated': False}, + 'standardml-nj': {'id': 'StandardML-NJ', 'deprecated': True}, + 'sugarcrm-1.1.3': {'id': 'SugarCRM-1.1.3', 'deprecated': False}, + 'sun-ppp': {'id': 'Sun-PPP', 'deprecated': False}, + 'sun-ppp-2000': {'id': 'Sun-PPP-2000', 'deprecated': False}, + 'sunpro': {'id': 'SunPro', 'deprecated': False}, + 'swl': {'id': 'SWL', 'deprecated': False}, + 'swrule': {'id': 'swrule', 'deprecated': False}, + 'symlinks': {'id': 'Symlinks', 'deprecated': False}, + 'tapr-ohl-1.0': {'id': 'TAPR-OHL-1.0', 'deprecated': False}, + 'tcl': {'id': 'TCL', 'deprecated': False}, + 'tcp-wrappers': {'id': 'TCP-wrappers', 'deprecated': False}, + 'termreadkey': {'id': 'TermReadKey', 'deprecated': False}, + 'tgppl-1.0': {'id': 'TGPPL-1.0', 'deprecated': False}, + 'threeparttable': {'id': 'threeparttable', 'deprecated': False}, + 'tmate': {'id': 'TMate', 'deprecated': False}, + 'torque-1.1': {'id': 'TORQUE-1.1', 'deprecated': False}, + 'tosl': {'id': 'TOSL', 'deprecated': False}, + 'tpdl': {'id': 'TPDL', 'deprecated': False}, + 'tpl-1.0': {'id': 'TPL-1.0', 'deprecated': False}, + 'ttwl': {'id': 'TTWL', 'deprecated': False}, + 'ttyp0': {'id': 'TTYP0', 'deprecated': False}, + 'tu-berlin-1.0': {'id': 'TU-Berlin-1.0', 'deprecated': False}, + 'tu-berlin-2.0': {'id': 'TU-Berlin-2.0', 'deprecated': False}, + 'ubuntu-font-1.0': {'id': 'Ubuntu-font-1.0', 'deprecated': False}, + 'ucar': {'id': 'UCAR', 'deprecated': False}, + 'ucl-1.0': {'id': 'UCL-1.0', 'deprecated': False}, + 'ulem': {'id': 'ulem', 'deprecated': False}, + 'umich-merit': {'id': 'UMich-Merit', 'deprecated': False}, + 'unicode-3.0': {'id': 'Unicode-3.0', 'deprecated': False}, + 'unicode-dfs-2015': {'id': 'Unicode-DFS-2015', 'deprecated': False}, + 'unicode-dfs-2016': {'id': 'Unicode-DFS-2016', 'deprecated': False}, + 'unicode-tou': {'id': 'Unicode-TOU', 'deprecated': False}, + 'unixcrypt': {'id': 'UnixCrypt', 'deprecated': False}, + 'unlicense': {'id': 'Unlicense', 'deprecated': False}, + 'upl-1.0': {'id': 'UPL-1.0', 'deprecated': False}, + 'urt-rle': {'id': 'URT-RLE', 'deprecated': False}, + 'vim': {'id': 'Vim', 'deprecated': False}, + 'vostrom': {'id': 'VOSTROM', 'deprecated': False}, + 'vsl-1.0': {'id': 'VSL-1.0', 'deprecated': False}, + 'w3c': {'id': 'W3C', 'deprecated': False}, + 'w3c-19980720': {'id': 'W3C-19980720', 'deprecated': False}, + 'w3c-20150513': {'id': 'W3C-20150513', 'deprecated': False}, + 'w3m': {'id': 'w3m', 'deprecated': False}, + 'watcom-1.0': {'id': 'Watcom-1.0', 'deprecated': False}, + 'widget-workshop': {'id': 'Widget-Workshop', 'deprecated': False}, + 'wsuipa': {'id': 'Wsuipa', 'deprecated': False}, + 'wtfpl': {'id': 'WTFPL', 'deprecated': False}, + 'wxwindows': {'id': 'wxWindows', 'deprecated': True}, + 'x11': {'id': 'X11', 'deprecated': False}, + 'x11-distribute-modifications-variant': {'id': 'X11-distribute-modifications-variant', 'deprecated': False}, + 'x11-swapped': {'id': 'X11-swapped', 'deprecated': False}, + 'xdebug-1.03': {'id': 'Xdebug-1.03', 'deprecated': False}, + 'xerox': {'id': 'Xerox', 'deprecated': False}, + 'xfig': {'id': 'Xfig', 'deprecated': False}, + 'xfree86-1.1': {'id': 'XFree86-1.1', 'deprecated': False}, + 'xinetd': {'id': 'xinetd', 'deprecated': False}, + 'xkeyboard-config-zinoviev': {'id': 'xkeyboard-config-Zinoviev', 'deprecated': False}, + 'xlock': {'id': 'xlock', 'deprecated': False}, + 'xnet': {'id': 'Xnet', 'deprecated': False}, + 'xpp': {'id': 'xpp', 'deprecated': False}, + 'xskat': {'id': 'XSkat', 'deprecated': False}, + 'xzoom': {'id': 'xzoom', 'deprecated': False}, + 'ypl-1.0': {'id': 'YPL-1.0', 'deprecated': False}, + 'ypl-1.1': {'id': 'YPL-1.1', 'deprecated': False}, + 'zed': {'id': 'Zed', 'deprecated': False}, + 'zeeff': {'id': 'Zeeff', 'deprecated': False}, + 'zend-2.0': {'id': 'Zend-2.0', 'deprecated': False}, + 'zimbra-1.3': {'id': 'Zimbra-1.3', 'deprecated': False}, + 'zimbra-1.4': {'id': 'Zimbra-1.4', 'deprecated': False}, + 'zlib': {'id': 'Zlib', 'deprecated': False}, + 'zlib-acknowledgement': {'id': 'zlib-acknowledgement', 'deprecated': False}, + 'zpl-1.1': {'id': 'ZPL-1.1', 'deprecated': False}, + 'zpl-2.0': {'id': 'ZPL-2.0', 'deprecated': False}, + 'zpl-2.1': {'id': 'ZPL-2.1', 'deprecated': False}, +} + +EXCEPTIONS: dict[str, SPDXException] = { + '389-exception': {'id': '389-exception', 'deprecated': False}, + 'asterisk-exception': {'id': 'Asterisk-exception', 'deprecated': False}, + 'asterisk-linking-protocols-exception': {'id': 'Asterisk-linking-protocols-exception', 'deprecated': False}, + 'autoconf-exception-2.0': {'id': 'Autoconf-exception-2.0', 'deprecated': False}, + 'autoconf-exception-3.0': {'id': 'Autoconf-exception-3.0', 'deprecated': False}, + 'autoconf-exception-generic': {'id': 'Autoconf-exception-generic', 'deprecated': False}, + 'autoconf-exception-generic-3.0': {'id': 'Autoconf-exception-generic-3.0', 'deprecated': False}, + 'autoconf-exception-macro': {'id': 'Autoconf-exception-macro', 'deprecated': False}, + 'bison-exception-1.24': {'id': 'Bison-exception-1.24', 'deprecated': False}, + 'bison-exception-2.2': {'id': 'Bison-exception-2.2', 'deprecated': False}, + 'bootloader-exception': {'id': 'Bootloader-exception', 'deprecated': False}, + 'classpath-exception-2.0': {'id': 'Classpath-exception-2.0', 'deprecated': False}, + 'clisp-exception-2.0': {'id': 'CLISP-exception-2.0', 'deprecated': False}, + 'cryptsetup-openssl-exception': {'id': 'cryptsetup-OpenSSL-exception', 'deprecated': False}, + 'digirule-foss-exception': {'id': 'DigiRule-FOSS-exception', 'deprecated': False}, + 'ecos-exception-2.0': {'id': 'eCos-exception-2.0', 'deprecated': False}, + 'erlang-otp-linking-exception': {'id': 'erlang-otp-linking-exception', 'deprecated': False}, + 'fawkes-runtime-exception': {'id': 'Fawkes-Runtime-exception', 'deprecated': False}, + 'fltk-exception': {'id': 'FLTK-exception', 'deprecated': False}, + 'fmt-exception': {'id': 'fmt-exception', 'deprecated': False}, + 'font-exception-2.0': {'id': 'Font-exception-2.0', 'deprecated': False}, + 'freertos-exception-2.0': {'id': 'freertos-exception-2.0', 'deprecated': False}, + 'gcc-exception-2.0': {'id': 'GCC-exception-2.0', 'deprecated': False}, + 'gcc-exception-2.0-note': {'id': 'GCC-exception-2.0-note', 'deprecated': False}, + 'gcc-exception-3.1': {'id': 'GCC-exception-3.1', 'deprecated': False}, + 'gmsh-exception': {'id': 'Gmsh-exception', 'deprecated': False}, + 'gnat-exception': {'id': 'GNAT-exception', 'deprecated': False}, + 'gnome-examples-exception': {'id': 'GNOME-examples-exception', 'deprecated': False}, + 'gnu-compiler-exception': {'id': 'GNU-compiler-exception', 'deprecated': False}, + 'gnu-javamail-exception': {'id': 'gnu-javamail-exception', 'deprecated': False}, + 'gpl-3.0-interface-exception': {'id': 'GPL-3.0-interface-exception', 'deprecated': False}, + 'gpl-3.0-linking-exception': {'id': 'GPL-3.0-linking-exception', 'deprecated': False}, + 'gpl-3.0-linking-source-exception': {'id': 'GPL-3.0-linking-source-exception', 'deprecated': False}, + 'gpl-cc-1.0': {'id': 'GPL-CC-1.0', 'deprecated': False}, + 'gstreamer-exception-2005': {'id': 'GStreamer-exception-2005', 'deprecated': False}, + 'gstreamer-exception-2008': {'id': 'GStreamer-exception-2008', 'deprecated': False}, + 'i2p-gpl-java-exception': {'id': 'i2p-gpl-java-exception', 'deprecated': False}, + 'kicad-libraries-exception': {'id': 'KiCad-libraries-exception', 'deprecated': False}, + 'lgpl-3.0-linking-exception': {'id': 'LGPL-3.0-linking-exception', 'deprecated': False}, + 'libpri-openh323-exception': {'id': 'libpri-OpenH323-exception', 'deprecated': False}, + 'libtool-exception': {'id': 'Libtool-exception', 'deprecated': False}, + 'linux-syscall-note': {'id': 'Linux-syscall-note', 'deprecated': False}, + 'llgpl': {'id': 'LLGPL', 'deprecated': False}, + 'llvm-exception': {'id': 'LLVM-exception', 'deprecated': False}, + 'lzma-exception': {'id': 'LZMA-exception', 'deprecated': False}, + 'mif-exception': {'id': 'mif-exception', 'deprecated': False}, + 'nokia-qt-exception-1.1': {'id': 'Nokia-Qt-exception-1.1', 'deprecated': True}, + 'ocaml-lgpl-linking-exception': {'id': 'OCaml-LGPL-linking-exception', 'deprecated': False}, + 'occt-exception-1.0': {'id': 'OCCT-exception-1.0', 'deprecated': False}, + 'openjdk-assembly-exception-1.0': {'id': 'OpenJDK-assembly-exception-1.0', 'deprecated': False}, + 'openvpn-openssl-exception': {'id': 'openvpn-openssl-exception', 'deprecated': False}, + 'pcre2-exception': {'id': 'PCRE2-exception', 'deprecated': False}, + 'ps-or-pdf-font-exception-20170817': {'id': 'PS-or-PDF-font-exception-20170817', 'deprecated': False}, + 'qpl-1.0-inria-2004-exception': {'id': 'QPL-1.0-INRIA-2004-exception', 'deprecated': False}, + 'qt-gpl-exception-1.0': {'id': 'Qt-GPL-exception-1.0', 'deprecated': False}, + 'qt-lgpl-exception-1.1': {'id': 'Qt-LGPL-exception-1.1', 'deprecated': False}, + 'qwt-exception-1.0': {'id': 'Qwt-exception-1.0', 'deprecated': False}, + 'romic-exception': {'id': 'romic-exception', 'deprecated': False}, + 'rrdtool-floss-exception-2.0': {'id': 'RRDtool-FLOSS-exception-2.0', 'deprecated': False}, + 'sane-exception': {'id': 'SANE-exception', 'deprecated': False}, + 'shl-2.0': {'id': 'SHL-2.0', 'deprecated': False}, + 'shl-2.1': {'id': 'SHL-2.1', 'deprecated': False}, + 'stunnel-exception': {'id': 'stunnel-exception', 'deprecated': False}, + 'swi-exception': {'id': 'SWI-exception', 'deprecated': False}, + 'swift-exception': {'id': 'Swift-exception', 'deprecated': False}, + 'texinfo-exception': {'id': 'Texinfo-exception', 'deprecated': False}, + 'u-boot-exception-2.0': {'id': 'u-boot-exception-2.0', 'deprecated': False}, + 'ubdl-exception': {'id': 'UBDL-exception', 'deprecated': False}, + 'universal-foss-exception-1.0': {'id': 'Universal-FOSS-exception-1.0', 'deprecated': False}, + 'vsftpd-openssl-exception': {'id': 'vsftpd-openssl-exception', 'deprecated': False}, + 'wxwindows-exception-3.1': {'id': 'WxWindows-exception-3.1', 'deprecated': False}, + 'x11vnc-openssl-exception': {'id': 'x11vnc-openssl-exception', 'deprecated': False}, +} diff --git a/venv/Lib/site-packages/packaging/markers.py b/venv/Lib/site-packages/packaging/markers.py new file mode 100644 index 0000000..fb7f49c --- /dev/null +++ b/venv/Lib/site-packages/packaging/markers.py @@ -0,0 +1,331 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import operator +import os +import platform +import sys +from typing import Any, Callable, TypedDict, cast + +from ._parser import MarkerAtom, MarkerList, Op, Value, Variable +from ._parser import parse_marker as _parse_marker +from ._tokenizer import ParserSyntaxError +from .specifiers import InvalidSpecifier, Specifier +from .utils import canonicalize_name + +__all__ = [ + "InvalidMarker", + "Marker", + "UndefinedComparison", + "UndefinedEnvironmentName", + "default_environment", +] + +Operator = Callable[[str, str], bool] + + +class InvalidMarker(ValueError): + """ + An invalid marker was found, users should refer to PEP 508. + """ + + +class UndefinedComparison(ValueError): + """ + An invalid operation was attempted on a value that doesn't support it. + """ + + +class UndefinedEnvironmentName(ValueError): + """ + A name was attempted to be used that does not exist inside of the + environment. + """ + + +class Environment(TypedDict): + implementation_name: str + """The implementation's identifier, e.g. ``'cpython'``.""" + + implementation_version: str + """ + The implementation's version, e.g. ``'3.13.0a2'`` for CPython 3.13.0a2, or + ``'7.3.13'`` for PyPy3.10 v7.3.13. + """ + + os_name: str + """ + The value of :py:data:`os.name`. The name of the operating system dependent module + imported, e.g. ``'posix'``. + """ + + platform_machine: str + """ + Returns the machine type, e.g. ``'i386'``. + + An empty string if the value cannot be determined. + """ + + platform_release: str + """ + The system's release, e.g. ``'2.2.0'`` or ``'NT'``. + + An empty string if the value cannot be determined. + """ + + platform_system: str + """ + The system/OS name, e.g. ``'Linux'``, ``'Windows'`` or ``'Java'``. + + An empty string if the value cannot be determined. + """ + + platform_version: str + """ + The system's release version, e.g. ``'#3 on degas'``. + + An empty string if the value cannot be determined. + """ + + python_full_version: str + """ + The Python version as string ``'major.minor.patchlevel'``. + + Note that unlike the Python :py:data:`sys.version`, this value will always include + the patchlevel (it defaults to 0). + """ + + platform_python_implementation: str + """ + A string identifying the Python implementation, e.g. ``'CPython'``. + """ + + python_version: str + """The Python version as string ``'major.minor'``.""" + + sys_platform: str + """ + This string contains a platform identifier that can be used to append + platform-specific components to :py:data:`sys.path`, for instance. + + For Unix systems, except on Linux and AIX, this is the lowercased OS name as + returned by ``uname -s`` with the first part of the version as returned by + ``uname -r`` appended, e.g. ``'sunos5'`` or ``'freebsd8'``, at the time when Python + was built. + """ + + +def _normalize_extra_values(results: Any) -> Any: + """ + Normalize extra values. + """ + if isinstance(results[0], tuple): + lhs, op, rhs = results[0] + if isinstance(lhs, Variable) and lhs.value == "extra": + normalized_extra = canonicalize_name(rhs.value) + rhs = Value(normalized_extra) + elif isinstance(rhs, Variable) and rhs.value == "extra": + normalized_extra = canonicalize_name(lhs.value) + lhs = Value(normalized_extra) + results[0] = lhs, op, rhs + return results + + +def _format_marker( + marker: list[str] | MarkerAtom | str, first: bool | None = True +) -> str: + assert isinstance(marker, (list, tuple, str)) + + # Sometimes we have a structure like [[...]] which is a single item list + # where the single item is itself it's own list. In that case we want skip + # the rest of this function so that we don't get extraneous () on the + # outside. + if ( + isinstance(marker, list) + and len(marker) == 1 + and isinstance(marker[0], (list, tuple)) + ): + return _format_marker(marker[0]) + + if isinstance(marker, list): + inner = (_format_marker(m, first=False) for m in marker) + if first: + return " ".join(inner) + else: + return "(" + " ".join(inner) + ")" + elif isinstance(marker, tuple): + return " ".join([m.serialize() for m in marker]) + else: + return marker + + +_operators: dict[str, Operator] = { + "in": lambda lhs, rhs: lhs in rhs, + "not in": lambda lhs, rhs: lhs not in rhs, + "<": operator.lt, + "<=": operator.le, + "==": operator.eq, + "!=": operator.ne, + ">=": operator.ge, + ">": operator.gt, +} + + +def _eval_op(lhs: str, op: Op, rhs: str) -> bool: + try: + spec = Specifier("".join([op.serialize(), rhs])) + except InvalidSpecifier: + pass + else: + return spec.contains(lhs, prereleases=True) + + oper: Operator | None = _operators.get(op.serialize()) + if oper is None: + raise UndefinedComparison(f"Undefined {op!r} on {lhs!r} and {rhs!r}.") + + return oper(lhs, rhs) + + +def _normalize(*values: str, key: str) -> tuple[str, ...]: + # PEP 685 – Comparison of extra names for optional distribution dependencies + # https://peps.python.org/pep-0685/ + # > When comparing extra names, tools MUST normalize the names being + # > compared using the semantics outlined in PEP 503 for names + if key == "extra": + return tuple(canonicalize_name(v) for v in values) + + # other environment markers don't have such standards + return values + + +def _evaluate_markers(markers: MarkerList, environment: dict[str, str]) -> bool: + groups: list[list[bool]] = [[]] + + for marker in markers: + assert isinstance(marker, (list, tuple, str)) + + if isinstance(marker, list): + groups[-1].append(_evaluate_markers(marker, environment)) + elif isinstance(marker, tuple): + lhs, op, rhs = marker + + if isinstance(lhs, Variable): + environment_key = lhs.value + lhs_value = environment[environment_key] + rhs_value = rhs.value + else: + lhs_value = lhs.value + environment_key = rhs.value + rhs_value = environment[environment_key] + + lhs_value, rhs_value = _normalize(lhs_value, rhs_value, key=environment_key) + groups[-1].append(_eval_op(lhs_value, op, rhs_value)) + else: + assert marker in ["and", "or"] + if marker == "or": + groups.append([]) + + return any(all(item) for item in groups) + + +def format_full_version(info: sys._version_info) -> str: + version = f"{info.major}.{info.minor}.{info.micro}" + kind = info.releaselevel + if kind != "final": + version += kind[0] + str(info.serial) + return version + + +def default_environment() -> Environment: + iver = format_full_version(sys.implementation.version) + implementation_name = sys.implementation.name + return { + "implementation_name": implementation_name, + "implementation_version": iver, + "os_name": os.name, + "platform_machine": platform.machine(), + "platform_release": platform.release(), + "platform_system": platform.system(), + "platform_version": platform.version(), + "python_full_version": platform.python_version(), + "platform_python_implementation": platform.python_implementation(), + "python_version": ".".join(platform.python_version_tuple()[:2]), + "sys_platform": sys.platform, + } + + +class Marker: + def __init__(self, marker: str) -> None: + # Note: We create a Marker object without calling this constructor in + # packaging.requirements.Requirement. If any additional logic is + # added here, make sure to mirror/adapt Requirement. + try: + self._markers = _normalize_extra_values(_parse_marker(marker)) + # The attribute `_markers` can be described in terms of a recursive type: + # MarkerList = List[Union[Tuple[Node, ...], str, MarkerList]] + # + # For example, the following expression: + # python_version > "3.6" or (python_version == "3.6" and os_name == "unix") + # + # is parsed into: + # [ + # (, ')>, ), + # 'and', + # [ + # (, , ), + # 'or', + # (, , ) + # ] + # ] + except ParserSyntaxError as e: + raise InvalidMarker(str(e)) from e + + def __str__(self) -> str: + return _format_marker(self._markers) + + def __repr__(self) -> str: + return f"" + + def __hash__(self) -> int: + return hash((self.__class__.__name__, str(self))) + + def __eq__(self, other: Any) -> bool: + if not isinstance(other, Marker): + return NotImplemented + + return str(self) == str(other) + + def evaluate(self, environment: dict[str, str] | None = None) -> bool: + """Evaluate a marker. + + Return the boolean from evaluating the given marker against the + environment. environment is an optional argument to override all or + part of the determined environment. + + The environment is determined from the current Python process. + """ + current_environment = cast("dict[str, str]", default_environment()) + current_environment["extra"] = "" + if environment is not None: + current_environment.update(environment) + # The API used to allow setting extra to None. We need to handle this + # case for backwards compatibility. + if current_environment["extra"] is None: + current_environment["extra"] = "" + + return _evaluate_markers( + self._markers, _repair_python_full_version(current_environment) + ) + + +def _repair_python_full_version(env: dict[str, str]) -> dict[str, str]: + """ + Work around platform.python_version() returning something that is not PEP 440 + compliant for non-tagged Python builds. + """ + if env["python_full_version"].endswith("+"): + env["python_full_version"] += "local" + return env diff --git a/venv/Lib/site-packages/packaging/metadata.py b/venv/Lib/site-packages/packaging/metadata.py new file mode 100644 index 0000000..721f411 --- /dev/null +++ b/venv/Lib/site-packages/packaging/metadata.py @@ -0,0 +1,863 @@ +from __future__ import annotations + +import email.feedparser +import email.header +import email.message +import email.parser +import email.policy +import pathlib +import sys +import typing +from typing import ( + Any, + Callable, + Generic, + Literal, + TypedDict, + cast, +) + +from . import licenses, requirements, specifiers, utils +from . import version as version_module +from .licenses import NormalizedLicenseExpression + +T = typing.TypeVar("T") + + +if sys.version_info >= (3, 11): # pragma: no cover + ExceptionGroup = ExceptionGroup +else: # pragma: no cover + + class ExceptionGroup(Exception): + """A minimal implementation of :external:exc:`ExceptionGroup` from Python 3.11. + + If :external:exc:`ExceptionGroup` is already defined by Python itself, + that version is used instead. + """ + + message: str + exceptions: list[Exception] + + def __init__(self, message: str, exceptions: list[Exception]) -> None: + self.message = message + self.exceptions = exceptions + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({self.message!r}, {self.exceptions!r})" + + +class InvalidMetadata(ValueError): + """A metadata field contains invalid data.""" + + field: str + """The name of the field that contains invalid data.""" + + def __init__(self, field: str, message: str) -> None: + self.field = field + super().__init__(message) + + +# The RawMetadata class attempts to make as few assumptions about the underlying +# serialization formats as possible. The idea is that as long as a serialization +# formats offer some very basic primitives in *some* way then we can support +# serializing to and from that format. +class RawMetadata(TypedDict, total=False): + """A dictionary of raw core metadata. + + Each field in core metadata maps to a key of this dictionary (when data is + provided). The key is lower-case and underscores are used instead of dashes + compared to the equivalent core metadata field. Any core metadata field that + can be specified multiple times or can hold multiple values in a single + field have a key with a plural name. See :class:`Metadata` whose attributes + match the keys of this dictionary. + + Core metadata fields that can be specified multiple times are stored as a + list or dict depending on which is appropriate for the field. Any fields + which hold multiple values in a single field are stored as a list. + + """ + + # Metadata 1.0 - PEP 241 + metadata_version: str + name: str + version: str + platforms: list[str] + summary: str + description: str + keywords: list[str] + home_page: str + author: str + author_email: str + license: str + + # Metadata 1.1 - PEP 314 + supported_platforms: list[str] + download_url: str + classifiers: list[str] + requires: list[str] + provides: list[str] + obsoletes: list[str] + + # Metadata 1.2 - PEP 345 + maintainer: str + maintainer_email: str + requires_dist: list[str] + provides_dist: list[str] + obsoletes_dist: list[str] + requires_python: str + requires_external: list[str] + project_urls: dict[str, str] + + # Metadata 2.0 + # PEP 426 attempted to completely revamp the metadata format + # but got stuck without ever being able to build consensus on + # it and ultimately ended up withdrawn. + # + # However, a number of tools had started emitting METADATA with + # `2.0` Metadata-Version, so for historical reasons, this version + # was skipped. + + # Metadata 2.1 - PEP 566 + description_content_type: str + provides_extra: list[str] + + # Metadata 2.2 - PEP 643 + dynamic: list[str] + + # Metadata 2.3 - PEP 685 + # No new fields were added in PEP 685, just some edge case were + # tightened up to provide better interoptability. + + # Metadata 2.4 - PEP 639 + license_expression: str + license_files: list[str] + + +_STRING_FIELDS = { + "author", + "author_email", + "description", + "description_content_type", + "download_url", + "home_page", + "license", + "license_expression", + "maintainer", + "maintainer_email", + "metadata_version", + "name", + "requires_python", + "summary", + "version", +} + +_LIST_FIELDS = { + "classifiers", + "dynamic", + "license_files", + "obsoletes", + "obsoletes_dist", + "platforms", + "provides", + "provides_dist", + "provides_extra", + "requires", + "requires_dist", + "requires_external", + "supported_platforms", +} + +_DICT_FIELDS = { + "project_urls", +} + + +def _parse_keywords(data: str) -> list[str]: + """Split a string of comma-separated keywords into a list of keywords.""" + return [k.strip() for k in data.split(",")] + + +def _parse_project_urls(data: list[str]) -> dict[str, str]: + """Parse a list of label/URL string pairings separated by a comma.""" + urls = {} + for pair in data: + # Our logic is slightly tricky here as we want to try and do + # *something* reasonable with malformed data. + # + # The main thing that we have to worry about, is data that does + # not have a ',' at all to split the label from the Value. There + # isn't a singular right answer here, and we will fail validation + # later on (if the caller is validating) so it doesn't *really* + # matter, but since the missing value has to be an empty str + # and our return value is dict[str, str], if we let the key + # be the missing value, then they'd have multiple '' values that + # overwrite each other in a accumulating dict. + # + # The other potentional issue is that it's possible to have the + # same label multiple times in the metadata, with no solid "right" + # answer with what to do in that case. As such, we'll do the only + # thing we can, which is treat the field as unparseable and add it + # to our list of unparsed fields. + parts = [p.strip() for p in pair.split(",", 1)] + parts.extend([""] * (max(0, 2 - len(parts)))) # Ensure 2 items + + # TODO: The spec doesn't say anything about if the keys should be + # considered case sensitive or not... logically they should + # be case-preserving and case-insensitive, but doing that + # would open up more cases where we might have duplicate + # entries. + label, url = parts + if label in urls: + # The label already exists in our set of urls, so this field + # is unparseable, and we can just add the whole thing to our + # unparseable data and stop processing it. + raise KeyError("duplicate labels in project urls") + urls[label] = url + + return urls + + +def _get_payload(msg: email.message.Message, source: bytes | str) -> str: + """Get the body of the message.""" + # If our source is a str, then our caller has managed encodings for us, + # and we don't need to deal with it. + if isinstance(source, str): + payload = msg.get_payload() + assert isinstance(payload, str) + return payload + # If our source is a bytes, then we're managing the encoding and we need + # to deal with it. + else: + bpayload = msg.get_payload(decode=True) + assert isinstance(bpayload, bytes) + try: + return bpayload.decode("utf8", "strict") + except UnicodeDecodeError as exc: + raise ValueError("payload in an invalid encoding") from exc + + +# The various parse_FORMAT functions here are intended to be as lenient as +# possible in their parsing, while still returning a correctly typed +# RawMetadata. +# +# To aid in this, we also generally want to do as little touching of the +# data as possible, except where there are possibly some historic holdovers +# that make valid data awkward to work with. +# +# While this is a lower level, intermediate format than our ``Metadata`` +# class, some light touch ups can make a massive difference in usability. + +# Map METADATA fields to RawMetadata. +_EMAIL_TO_RAW_MAPPING = { + "author": "author", + "author-email": "author_email", + "classifier": "classifiers", + "description": "description", + "description-content-type": "description_content_type", + "download-url": "download_url", + "dynamic": "dynamic", + "home-page": "home_page", + "keywords": "keywords", + "license": "license", + "license-expression": "license_expression", + "license-file": "license_files", + "maintainer": "maintainer", + "maintainer-email": "maintainer_email", + "metadata-version": "metadata_version", + "name": "name", + "obsoletes": "obsoletes", + "obsoletes-dist": "obsoletes_dist", + "platform": "platforms", + "project-url": "project_urls", + "provides": "provides", + "provides-dist": "provides_dist", + "provides-extra": "provides_extra", + "requires": "requires", + "requires-dist": "requires_dist", + "requires-external": "requires_external", + "requires-python": "requires_python", + "summary": "summary", + "supported-platform": "supported_platforms", + "version": "version", +} +_RAW_TO_EMAIL_MAPPING = {raw: email for email, raw in _EMAIL_TO_RAW_MAPPING.items()} + + +def parse_email(data: bytes | str) -> tuple[RawMetadata, dict[str, list[str]]]: + """Parse a distribution's metadata stored as email headers (e.g. from ``METADATA``). + + This function returns a two-item tuple of dicts. The first dict is of + recognized fields from the core metadata specification. Fields that can be + parsed and translated into Python's built-in types are converted + appropriately. All other fields are left as-is. Fields that are allowed to + appear multiple times are stored as lists. + + The second dict contains all other fields from the metadata. This includes + any unrecognized fields. It also includes any fields which are expected to + be parsed into a built-in type but were not formatted appropriately. Finally, + any fields that are expected to appear only once but are repeated are + included in this dict. + + """ + raw: dict[str, str | list[str] | dict[str, str]] = {} + unparsed: dict[str, list[str]] = {} + + if isinstance(data, str): + parsed = email.parser.Parser(policy=email.policy.compat32).parsestr(data) + else: + parsed = email.parser.BytesParser(policy=email.policy.compat32).parsebytes(data) + + # We have to wrap parsed.keys() in a set, because in the case of multiple + # values for a key (a list), the key will appear multiple times in the + # list of keys, but we're avoiding that by using get_all(). + for name in frozenset(parsed.keys()): + # Header names in RFC are case insensitive, so we'll normalize to all + # lower case to make comparisons easier. + name = name.lower() + + # We use get_all() here, even for fields that aren't multiple use, + # because otherwise someone could have e.g. two Name fields, and we + # would just silently ignore it rather than doing something about it. + headers = parsed.get_all(name) or [] + + # The way the email module works when parsing bytes is that it + # unconditionally decodes the bytes as ascii using the surrogateescape + # handler. When you pull that data back out (such as with get_all() ), + # it looks to see if the str has any surrogate escapes, and if it does + # it wraps it in a Header object instead of returning the string. + # + # As such, we'll look for those Header objects, and fix up the encoding. + value = [] + # Flag if we have run into any issues processing the headers, thus + # signalling that the data belongs in 'unparsed'. + valid_encoding = True + for h in headers: + # It's unclear if this can return more types than just a Header or + # a str, so we'll just assert here to make sure. + assert isinstance(h, (email.header.Header, str)) + + # If it's a header object, we need to do our little dance to get + # the real data out of it. In cases where there is invalid data + # we're going to end up with mojibake, but there's no obvious, good + # way around that without reimplementing parts of the Header object + # ourselves. + # + # That should be fine since, if mojibacked happens, this key is + # going into the unparsed dict anyways. + if isinstance(h, email.header.Header): + # The Header object stores it's data as chunks, and each chunk + # can be independently encoded, so we'll need to check each + # of them. + chunks: list[tuple[bytes, str | None]] = [] + for bin, encoding in email.header.decode_header(h): + try: + bin.decode("utf8", "strict") + except UnicodeDecodeError: + # Enable mojibake. + encoding = "latin1" + valid_encoding = False + else: + encoding = "utf8" + chunks.append((bin, encoding)) + + # Turn our chunks back into a Header object, then let that + # Header object do the right thing to turn them into a + # string for us. + value.append(str(email.header.make_header(chunks))) + # This is already a string, so just add it. + else: + value.append(h) + + # We've processed all of our values to get them into a list of str, + # but we may have mojibake data, in which case this is an unparsed + # field. + if not valid_encoding: + unparsed[name] = value + continue + + raw_name = _EMAIL_TO_RAW_MAPPING.get(name) + if raw_name is None: + # This is a bit of a weird situation, we've encountered a key that + # we don't know what it means, so we don't know whether it's meant + # to be a list or not. + # + # Since we can't really tell one way or another, we'll just leave it + # as a list, even though it may be a single item list, because that's + # what makes the most sense for email headers. + unparsed[name] = value + continue + + # If this is one of our string fields, then we'll check to see if our + # value is a list of a single item. If it is then we'll assume that + # it was emitted as a single string, and unwrap the str from inside + # the list. + # + # If it's any other kind of data, then we haven't the faintest clue + # what we should parse it as, and we have to just add it to our list + # of unparsed stuff. + if raw_name in _STRING_FIELDS and len(value) == 1: + raw[raw_name] = value[0] + # If this is one of our list of string fields, then we can just assign + # the value, since email *only* has strings, and our get_all() call + # above ensures that this is a list. + elif raw_name in _LIST_FIELDS: + raw[raw_name] = value + # Special Case: Keywords + # The keywords field is implemented in the metadata spec as a str, + # but it conceptually is a list of strings, and is serialized using + # ", ".join(keywords), so we'll do some light data massaging to turn + # this into what it logically is. + elif raw_name == "keywords" and len(value) == 1: + raw[raw_name] = _parse_keywords(value[0]) + # Special Case: Project-URL + # The project urls is implemented in the metadata spec as a list of + # specially-formatted strings that represent a key and a value, which + # is fundamentally a mapping, however the email format doesn't support + # mappings in a sane way, so it was crammed into a list of strings + # instead. + # + # We will do a little light data massaging to turn this into a map as + # it logically should be. + elif raw_name == "project_urls": + try: + raw[raw_name] = _parse_project_urls(value) + except KeyError: + unparsed[name] = value + # Nothing that we've done has managed to parse this, so it'll just + # throw it in our unparseable data and move on. + else: + unparsed[name] = value + + # We need to support getting the Description from the message payload in + # addition to getting it from the the headers. This does mean, though, there + # is the possibility of it being set both ways, in which case we put both + # in 'unparsed' since we don't know which is right. + try: + payload = _get_payload(parsed, data) + except ValueError: + unparsed.setdefault("description", []).append( + parsed.get_payload(decode=isinstance(data, bytes)) # type: ignore[call-overload] + ) + else: + if payload: + # Check to see if we've already got a description, if so then both + # it, and this body move to unparseable. + if "description" in raw: + description_header = cast(str, raw.pop("description")) + unparsed.setdefault("description", []).extend( + [description_header, payload] + ) + elif "description" in unparsed: + unparsed["description"].append(payload) + else: + raw["description"] = payload + + # We need to cast our `raw` to a metadata, because a TypedDict only support + # literal key names, but we're computing our key names on purpose, but the + # way this function is implemented, our `TypedDict` can only have valid key + # names. + return cast(RawMetadata, raw), unparsed + + +_NOT_FOUND = object() + + +# Keep the two values in sync. +_VALID_METADATA_VERSIONS = ["1.0", "1.1", "1.2", "2.1", "2.2", "2.3", "2.4"] +_MetadataVersion = Literal["1.0", "1.1", "1.2", "2.1", "2.2", "2.3", "2.4"] + +_REQUIRED_ATTRS = frozenset(["metadata_version", "name", "version"]) + + +class _Validator(Generic[T]): + """Validate a metadata field. + + All _process_*() methods correspond to a core metadata field. The method is + called with the field's raw value. If the raw value is valid it is returned + in its "enriched" form (e.g. ``version.Version`` for the ``Version`` field). + If the raw value is invalid, :exc:`InvalidMetadata` is raised (with a cause + as appropriate). + """ + + name: str + raw_name: str + added: _MetadataVersion + + def __init__( + self, + *, + added: _MetadataVersion = "1.0", + ) -> None: + self.added = added + + def __set_name__(self, _owner: Metadata, name: str) -> None: + self.name = name + self.raw_name = _RAW_TO_EMAIL_MAPPING[name] + + def __get__(self, instance: Metadata, _owner: type[Metadata]) -> T: + # With Python 3.8, the caching can be replaced with functools.cached_property(). + # No need to check the cache as attribute lookup will resolve into the + # instance's __dict__ before __get__ is called. + cache = instance.__dict__ + value = instance._raw.get(self.name) + + # To make the _process_* methods easier, we'll check if the value is None + # and if this field is NOT a required attribute, and if both of those + # things are true, we'll skip the the converter. This will mean that the + # converters never have to deal with the None union. + if self.name in _REQUIRED_ATTRS or value is not None: + try: + converter: Callable[[Any], T] = getattr(self, f"_process_{self.name}") + except AttributeError: + pass + else: + value = converter(value) + + cache[self.name] = value + try: + del instance._raw[self.name] # type: ignore[misc] + except KeyError: + pass + + return cast(T, value) + + def _invalid_metadata( + self, msg: str, cause: Exception | None = None + ) -> InvalidMetadata: + exc = InvalidMetadata( + self.raw_name, msg.format_map({"field": repr(self.raw_name)}) + ) + exc.__cause__ = cause + return exc + + def _process_metadata_version(self, value: str) -> _MetadataVersion: + # Implicitly makes Metadata-Version required. + if value not in _VALID_METADATA_VERSIONS: + raise self._invalid_metadata(f"{value!r} is not a valid metadata version") + return cast(_MetadataVersion, value) + + def _process_name(self, value: str) -> str: + if not value: + raise self._invalid_metadata("{field} is a required field") + # Validate the name as a side-effect. + try: + utils.canonicalize_name(value, validate=True) + except utils.InvalidName as exc: + raise self._invalid_metadata( + f"{value!r} is invalid for {{field}}", cause=exc + ) from exc + else: + return value + + def _process_version(self, value: str) -> version_module.Version: + if not value: + raise self._invalid_metadata("{field} is a required field") + try: + return version_module.parse(value) + except version_module.InvalidVersion as exc: + raise self._invalid_metadata( + f"{value!r} is invalid for {{field}}", cause=exc + ) from exc + + def _process_summary(self, value: str) -> str: + """Check the field contains no newlines.""" + if "\n" in value: + raise self._invalid_metadata("{field} must be a single line") + return value + + def _process_description_content_type(self, value: str) -> str: + content_types = {"text/plain", "text/x-rst", "text/markdown"} + message = email.message.EmailMessage() + message["content-type"] = value + + content_type, parameters = ( + # Defaults to `text/plain` if parsing failed. + message.get_content_type().lower(), + message["content-type"].params, + ) + # Check if content-type is valid or defaulted to `text/plain` and thus was + # not parseable. + if content_type not in content_types or content_type not in value.lower(): + raise self._invalid_metadata( + f"{{field}} must be one of {list(content_types)}, not {value!r}" + ) + + charset = parameters.get("charset", "UTF-8") + if charset != "UTF-8": + raise self._invalid_metadata( + f"{{field}} can only specify the UTF-8 charset, not {list(charset)}" + ) + + markdown_variants = {"GFM", "CommonMark"} + variant = parameters.get("variant", "GFM") # Use an acceptable default. + if content_type == "text/markdown" and variant not in markdown_variants: + raise self._invalid_metadata( + f"valid Markdown variants for {{field}} are {list(markdown_variants)}, " + f"not {variant!r}", + ) + return value + + def _process_dynamic(self, value: list[str]) -> list[str]: + for dynamic_field in map(str.lower, value): + if dynamic_field in {"name", "version", "metadata-version"}: + raise self._invalid_metadata( + f"{dynamic_field!r} is not allowed as a dynamic field" + ) + elif dynamic_field not in _EMAIL_TO_RAW_MAPPING: + raise self._invalid_metadata( + f"{dynamic_field!r} is not a valid dynamic field" + ) + return list(map(str.lower, value)) + + def _process_provides_extra( + self, + value: list[str], + ) -> list[utils.NormalizedName]: + normalized_names = [] + try: + for name in value: + normalized_names.append(utils.canonicalize_name(name, validate=True)) + except utils.InvalidName as exc: + raise self._invalid_metadata( + f"{name!r} is invalid for {{field}}", cause=exc + ) from exc + else: + return normalized_names + + def _process_requires_python(self, value: str) -> specifiers.SpecifierSet: + try: + return specifiers.SpecifierSet(value) + except specifiers.InvalidSpecifier as exc: + raise self._invalid_metadata( + f"{value!r} is invalid for {{field}}", cause=exc + ) from exc + + def _process_requires_dist( + self, + value: list[str], + ) -> list[requirements.Requirement]: + reqs = [] + try: + for req in value: + reqs.append(requirements.Requirement(req)) + except requirements.InvalidRequirement as exc: + raise self._invalid_metadata( + f"{req!r} is invalid for {{field}}", cause=exc + ) from exc + else: + return reqs + + def _process_license_expression( + self, value: str + ) -> NormalizedLicenseExpression | None: + try: + return licenses.canonicalize_license_expression(value) + except ValueError as exc: + raise self._invalid_metadata( + f"{value!r} is invalid for {{field}}", cause=exc + ) from exc + + def _process_license_files(self, value: list[str]) -> list[str]: + paths = [] + for path in value: + if ".." in path: + raise self._invalid_metadata( + f"{path!r} is invalid for {{field}}, " + "parent directory indicators are not allowed" + ) + if "*" in path: + raise self._invalid_metadata( + f"{path!r} is invalid for {{field}}, paths must be resolved" + ) + if ( + pathlib.PurePosixPath(path).is_absolute() + or pathlib.PureWindowsPath(path).is_absolute() + ): + raise self._invalid_metadata( + f"{path!r} is invalid for {{field}}, paths must be relative" + ) + if pathlib.PureWindowsPath(path).as_posix() != path: + raise self._invalid_metadata( + f"{path!r} is invalid for {{field}}, " + "paths must use '/' delimiter" + ) + paths.append(path) + return paths + + +class Metadata: + """Representation of distribution metadata. + + Compared to :class:`RawMetadata`, this class provides objects representing + metadata fields instead of only using built-in types. Any invalid metadata + will cause :exc:`InvalidMetadata` to be raised (with a + :py:attr:`~BaseException.__cause__` attribute as appropriate). + """ + + _raw: RawMetadata + + @classmethod + def from_raw(cls, data: RawMetadata, *, validate: bool = True) -> Metadata: + """Create an instance from :class:`RawMetadata`. + + If *validate* is true, all metadata will be validated. All exceptions + related to validation will be gathered and raised as an :class:`ExceptionGroup`. + """ + ins = cls() + ins._raw = data.copy() # Mutations occur due to caching enriched values. + + if validate: + exceptions: list[Exception] = [] + try: + metadata_version = ins.metadata_version + metadata_age = _VALID_METADATA_VERSIONS.index(metadata_version) + except InvalidMetadata as metadata_version_exc: + exceptions.append(metadata_version_exc) + metadata_version = None + + # Make sure to check for the fields that are present, the required + # fields (so their absence can be reported). + fields_to_check = frozenset(ins._raw) | _REQUIRED_ATTRS + # Remove fields that have already been checked. + fields_to_check -= {"metadata_version"} + + for key in fields_to_check: + try: + if metadata_version: + # Can't use getattr() as that triggers descriptor protocol which + # will fail due to no value for the instance argument. + try: + field_metadata_version = cls.__dict__[key].added + except KeyError: + exc = InvalidMetadata(key, f"unrecognized field: {key!r}") + exceptions.append(exc) + continue + field_age = _VALID_METADATA_VERSIONS.index( + field_metadata_version + ) + if field_age > metadata_age: + field = _RAW_TO_EMAIL_MAPPING[key] + exc = InvalidMetadata( + field, + f"{field} introduced in metadata version " + f"{field_metadata_version}, not {metadata_version}", + ) + exceptions.append(exc) + continue + getattr(ins, key) + except InvalidMetadata as exc: + exceptions.append(exc) + + if exceptions: + raise ExceptionGroup("invalid metadata", exceptions) + + return ins + + @classmethod + def from_email(cls, data: bytes | str, *, validate: bool = True) -> Metadata: + """Parse metadata from email headers. + + If *validate* is true, the metadata will be validated. All exceptions + related to validation will be gathered and raised as an :class:`ExceptionGroup`. + """ + raw, unparsed = parse_email(data) + + if validate: + exceptions: list[Exception] = [] + for unparsed_key in unparsed: + if unparsed_key in _EMAIL_TO_RAW_MAPPING: + message = f"{unparsed_key!r} has invalid data" + else: + message = f"unrecognized field: {unparsed_key!r}" + exceptions.append(InvalidMetadata(unparsed_key, message)) + + if exceptions: + raise ExceptionGroup("unparsed", exceptions) + + try: + return cls.from_raw(raw, validate=validate) + except ExceptionGroup as exc_group: + raise ExceptionGroup( + "invalid or unparsed metadata", exc_group.exceptions + ) from None + + metadata_version: _Validator[_MetadataVersion] = _Validator() + """:external:ref:`core-metadata-metadata-version` + (required; validated to be a valid metadata version)""" + # `name` is not normalized/typed to NormalizedName so as to provide access to + # the original/raw name. + name: _Validator[str] = _Validator() + """:external:ref:`core-metadata-name` + (required; validated using :func:`~packaging.utils.canonicalize_name` and its + *validate* parameter)""" + version: _Validator[version_module.Version] = _Validator() + """:external:ref:`core-metadata-version` (required)""" + dynamic: _Validator[list[str] | None] = _Validator( + added="2.2", + ) + """:external:ref:`core-metadata-dynamic` + (validated against core metadata field names and lowercased)""" + platforms: _Validator[list[str] | None] = _Validator() + """:external:ref:`core-metadata-platform`""" + supported_platforms: _Validator[list[str] | None] = _Validator(added="1.1") + """:external:ref:`core-metadata-supported-platform`""" + summary: _Validator[str | None] = _Validator() + """:external:ref:`core-metadata-summary` (validated to contain no newlines)""" + description: _Validator[str | None] = _Validator() # TODO 2.1: can be in body + """:external:ref:`core-metadata-description`""" + description_content_type: _Validator[str | None] = _Validator(added="2.1") + """:external:ref:`core-metadata-description-content-type` (validated)""" + keywords: _Validator[list[str] | None] = _Validator() + """:external:ref:`core-metadata-keywords`""" + home_page: _Validator[str | None] = _Validator() + """:external:ref:`core-metadata-home-page`""" + download_url: _Validator[str | None] = _Validator(added="1.1") + """:external:ref:`core-metadata-download-url`""" + author: _Validator[str | None] = _Validator() + """:external:ref:`core-metadata-author`""" + author_email: _Validator[str | None] = _Validator() + """:external:ref:`core-metadata-author-email`""" + maintainer: _Validator[str | None] = _Validator(added="1.2") + """:external:ref:`core-metadata-maintainer`""" + maintainer_email: _Validator[str | None] = _Validator(added="1.2") + """:external:ref:`core-metadata-maintainer-email`""" + license: _Validator[str | None] = _Validator() + """:external:ref:`core-metadata-license`""" + license_expression: _Validator[NormalizedLicenseExpression | None] = _Validator( + added="2.4" + ) + """:external:ref:`core-metadata-license-expression`""" + license_files: _Validator[list[str] | None] = _Validator(added="2.4") + """:external:ref:`core-metadata-license-file`""" + classifiers: _Validator[list[str] | None] = _Validator(added="1.1") + """:external:ref:`core-metadata-classifier`""" + requires_dist: _Validator[list[requirements.Requirement] | None] = _Validator( + added="1.2" + ) + """:external:ref:`core-metadata-requires-dist`""" + requires_python: _Validator[specifiers.SpecifierSet | None] = _Validator( + added="1.2" + ) + """:external:ref:`core-metadata-requires-python`""" + # Because `Requires-External` allows for non-PEP 440 version specifiers, we + # don't do any processing on the values. + requires_external: _Validator[list[str] | None] = _Validator(added="1.2") + """:external:ref:`core-metadata-requires-external`""" + project_urls: _Validator[dict[str, str] | None] = _Validator(added="1.2") + """:external:ref:`core-metadata-project-url`""" + # PEP 685 lets us raise an error if an extra doesn't pass `Name` validation + # regardless of metadata version. + provides_extra: _Validator[list[utils.NormalizedName] | None] = _Validator( + added="2.1", + ) + """:external:ref:`core-metadata-provides-extra`""" + provides_dist: _Validator[list[str] | None] = _Validator(added="1.2") + """:external:ref:`core-metadata-provides-dist`""" + obsoletes_dist: _Validator[list[str] | None] = _Validator(added="1.2") + """:external:ref:`core-metadata-obsoletes-dist`""" + requires: _Validator[list[str] | None] = _Validator(added="1.1") + """``Requires`` (deprecated)""" + provides: _Validator[list[str] | None] = _Validator(added="1.1") + """``Provides`` (deprecated)""" + obsoletes: _Validator[list[str] | None] = _Validator(added="1.1") + """``Obsoletes`` (deprecated)""" diff --git a/venv/Lib/site-packages/pip-24.2.dist-info/REQUESTED b/venv/Lib/site-packages/packaging/py.typed similarity index 100% rename from venv/Lib/site-packages/pip-24.2.dist-info/REQUESTED rename to venv/Lib/site-packages/packaging/py.typed diff --git a/venv/Lib/site-packages/packaging/requirements.py b/venv/Lib/site-packages/packaging/requirements.py new file mode 100644 index 0000000..4e068c9 --- /dev/null +++ b/venv/Lib/site-packages/packaging/requirements.py @@ -0,0 +1,91 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +from __future__ import annotations + +from typing import Any, Iterator + +from ._parser import parse_requirement as _parse_requirement +from ._tokenizer import ParserSyntaxError +from .markers import Marker, _normalize_extra_values +from .specifiers import SpecifierSet +from .utils import canonicalize_name + + +class InvalidRequirement(ValueError): + """ + An invalid requirement was found, users should refer to PEP 508. + """ + + +class Requirement: + """Parse a requirement. + + Parse a given requirement string into its parts, such as name, specifier, + URL, and extras. Raises InvalidRequirement on a badly-formed requirement + string. + """ + + # TODO: Can we test whether something is contained within a requirement? + # If so how do we do that? Do we need to test against the _name_ of + # the thing as well as the version? What about the markers? + # TODO: Can we normalize the name and extra name? + + def __init__(self, requirement_string: str) -> None: + try: + parsed = _parse_requirement(requirement_string) + except ParserSyntaxError as e: + raise InvalidRequirement(str(e)) from e + + self.name: str = parsed.name + self.url: str | None = parsed.url or None + self.extras: set[str] = set(parsed.extras or []) + self.specifier: SpecifierSet = SpecifierSet(parsed.specifier) + self.marker: Marker | None = None + if parsed.marker is not None: + self.marker = Marker.__new__(Marker) + self.marker._markers = _normalize_extra_values(parsed.marker) + + def _iter_parts(self, name: str) -> Iterator[str]: + yield name + + if self.extras: + formatted_extras = ",".join(sorted(self.extras)) + yield f"[{formatted_extras}]" + + if self.specifier: + yield str(self.specifier) + + if self.url: + yield f"@ {self.url}" + if self.marker: + yield " " + + if self.marker: + yield f"; {self.marker}" + + def __str__(self) -> str: + return "".join(self._iter_parts(self.name)) + + def __repr__(self) -> str: + return f"" + + def __hash__(self) -> int: + return hash( + ( + self.__class__.__name__, + *self._iter_parts(canonicalize_name(self.name)), + ) + ) + + def __eq__(self, other: Any) -> bool: + if not isinstance(other, Requirement): + return NotImplemented + + return ( + canonicalize_name(self.name) == canonicalize_name(other.name) + and self.extras == other.extras + and self.specifier == other.specifier + and self.url == other.url + and self.marker == other.marker + ) diff --git a/venv/Lib/site-packages/packaging/specifiers.py b/venv/Lib/site-packages/packaging/specifiers.py new file mode 100644 index 0000000..b30926a --- /dev/null +++ b/venv/Lib/site-packages/packaging/specifiers.py @@ -0,0 +1,1020 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +""" +.. testsetup:: + + from packaging.specifiers import Specifier, SpecifierSet, InvalidSpecifier + from packaging.version import Version +""" + +from __future__ import annotations + +import abc +import itertools +import re +from typing import Callable, Iterable, Iterator, TypeVar, Union + +from .utils import canonicalize_version +from .version import Version + +UnparsedVersion = Union[Version, str] +UnparsedVersionVar = TypeVar("UnparsedVersionVar", bound=UnparsedVersion) +CallableOperator = Callable[[Version, str], bool] + + +def _coerce_version(version: UnparsedVersion) -> Version: + if not isinstance(version, Version): + version = Version(version) + return version + + +class InvalidSpecifier(ValueError): + """ + Raised when attempting to create a :class:`Specifier` with a specifier + string that is invalid. + + >>> Specifier("lolwat") + Traceback (most recent call last): + ... + packaging.specifiers.InvalidSpecifier: Invalid specifier: 'lolwat' + """ + + +class BaseSpecifier(metaclass=abc.ABCMeta): + @abc.abstractmethod + def __str__(self) -> str: + """ + Returns the str representation of this Specifier-like object. This + should be representative of the Specifier itself. + """ + + @abc.abstractmethod + def __hash__(self) -> int: + """ + Returns a hash value for this Specifier-like object. + """ + + @abc.abstractmethod + def __eq__(self, other: object) -> bool: + """ + Returns a boolean representing whether or not the two Specifier-like + objects are equal. + + :param other: The other object to check against. + """ + + @property + @abc.abstractmethod + def prereleases(self) -> bool | None: + """Whether or not pre-releases as a whole are allowed. + + This can be set to either ``True`` or ``False`` to explicitly enable or disable + prereleases or it can be set to ``None`` (the default) to use default semantics. + """ + + @prereleases.setter + def prereleases(self, value: bool) -> None: + """Setter for :attr:`prereleases`. + + :param value: The value to set. + """ + + @abc.abstractmethod + def contains(self, item: str, prereleases: bool | None = None) -> bool: + """ + Determines if the given item is contained within this specifier. + """ + + @abc.abstractmethod + def filter( + self, iterable: Iterable[UnparsedVersionVar], prereleases: bool | None = None + ) -> Iterator[UnparsedVersionVar]: + """ + Takes an iterable of items and filters them so that only items which + are contained within this specifier are allowed in it. + """ + + +class Specifier(BaseSpecifier): + """This class abstracts handling of version specifiers. + + .. tip:: + + It is generally not required to instantiate this manually. You should instead + prefer to work with :class:`SpecifierSet` instead, which can parse + comma-separated version specifiers (which is what package metadata contains). + """ + + _operator_regex_str = r""" + (?P(~=|==|!=|<=|>=|<|>|===)) + """ + _version_regex_str = r""" + (?P + (?: + # The identity operators allow for an escape hatch that will + # do an exact string match of the version you wish to install. + # This will not be parsed by PEP 440 and we cannot determine + # any semantic meaning from it. This operator is discouraged + # but included entirely as an escape hatch. + (?<====) # Only match for the identity operator + \s* + [^\s;)]* # The arbitrary version can be just about anything, + # we match everything except for whitespace, a + # semi-colon for marker support, and a closing paren + # since versions can be enclosed in them. + ) + | + (?: + # The (non)equality operators allow for wild card and local + # versions to be specified so we have to define these two + # operators separately to enable that. + (?<===|!=) # Only match for equals and not equals + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)* # release + + # You cannot use a wild card and a pre-release, post-release, a dev or + # local version together so group them with a | and make them optional. + (?: + \.\* # Wild card syntax of .* + | + (?: # pre release + [-_\.]? + (alpha|beta|preview|pre|a|b|c|rc) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + (?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local + )? + ) + | + (?: + # The compatible operator requires at least two digits in the + # release segment. + (?<=~=) # Only match for the compatible operator + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)+ # release (We have a + instead of a *) + (?: # pre release + [-_\.]? + (alpha|beta|preview|pre|a|b|c|rc) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + ) + | + (?: + # All other operators only allow a sub set of what the + # (non)equality operators do. Specifically they do not allow + # local versions to be specified nor do they allow the prefix + # matching wild cards. + (?=": "greater_than_equal", + "<": "less_than", + ">": "greater_than", + "===": "arbitrary", + } + + def __init__(self, spec: str = "", prereleases: bool | None = None) -> None: + """Initialize a Specifier instance. + + :param spec: + The string representation of a specifier which will be parsed and + normalized before use. + :param prereleases: + This tells the specifier if it should accept prerelease versions if + applicable or not. The default of ``None`` will autodetect it from the + given specifiers. + :raises InvalidSpecifier: + If the given specifier is invalid (i.e. bad syntax). + """ + match = self._regex.search(spec) + if not match: + raise InvalidSpecifier(f"Invalid specifier: {spec!r}") + + self._spec: tuple[str, str] = ( + match.group("operator").strip(), + match.group("version").strip(), + ) + + # Store whether or not this Specifier should accept prereleases + self._prereleases = prereleases + + # https://github.com/python/mypy/pull/13475#pullrequestreview-1079784515 + @property # type: ignore[override] + def prereleases(self) -> bool: + # If there is an explicit prereleases set for this, then we'll just + # blindly use that. + if self._prereleases is not None: + return self._prereleases + + # Look at all of our specifiers and determine if they are inclusive + # operators, and if they are if they are including an explicit + # prerelease. + operator, version = self._spec + if operator in ["==", ">=", "<=", "~=", "===", ">", "<"]: + # The == specifier can include a trailing .*, if it does we + # want to remove before parsing. + if operator == "==" and version.endswith(".*"): + version = version[:-2] + + # Parse the version, and if it is a pre-release than this + # specifier allows pre-releases. + if Version(version).is_prerelease: + return True + + return False + + @prereleases.setter + def prereleases(self, value: bool) -> None: + self._prereleases = value + + @property + def operator(self) -> str: + """The operator of this specifier. + + >>> Specifier("==1.2.3").operator + '==' + """ + return self._spec[0] + + @property + def version(self) -> str: + """The version of this specifier. + + >>> Specifier("==1.2.3").version + '1.2.3' + """ + return self._spec[1] + + def __repr__(self) -> str: + """A representation of the Specifier that shows all internal state. + + >>> Specifier('>=1.0.0') + =1.0.0')> + >>> Specifier('>=1.0.0', prereleases=False) + =1.0.0', prereleases=False)> + >>> Specifier('>=1.0.0', prereleases=True) + =1.0.0', prereleases=True)> + """ + pre = ( + f", prereleases={self.prereleases!r}" + if self._prereleases is not None + else "" + ) + + return f"<{self.__class__.__name__}({str(self)!r}{pre})>" + + def __str__(self) -> str: + """A string representation of the Specifier that can be round-tripped. + + >>> str(Specifier('>=1.0.0')) + '>=1.0.0' + >>> str(Specifier('>=1.0.0', prereleases=False)) + '>=1.0.0' + """ + return "{}{}".format(*self._spec) + + @property + def _canonical_spec(self) -> tuple[str, str]: + canonical_version = canonicalize_version( + self._spec[1], + strip_trailing_zero=(self._spec[0] != "~="), + ) + return self._spec[0], canonical_version + + def __hash__(self) -> int: + return hash(self._canonical_spec) + + def __eq__(self, other: object) -> bool: + """Whether or not the two Specifier-like objects are equal. + + :param other: The other object to check against. + + The value of :attr:`prereleases` is ignored. + + >>> Specifier("==1.2.3") == Specifier("== 1.2.3.0") + True + >>> (Specifier("==1.2.3", prereleases=False) == + ... Specifier("==1.2.3", prereleases=True)) + True + >>> Specifier("==1.2.3") == "==1.2.3" + True + >>> Specifier("==1.2.3") == Specifier("==1.2.4") + False + >>> Specifier("==1.2.3") == Specifier("~=1.2.3") + False + """ + if isinstance(other, str): + try: + other = self.__class__(str(other)) + except InvalidSpecifier: + return NotImplemented + elif not isinstance(other, self.__class__): + return NotImplemented + + return self._canonical_spec == other._canonical_spec + + def _get_operator(self, op: str) -> CallableOperator: + operator_callable: CallableOperator = getattr( + self, f"_compare_{self._operators[op]}" + ) + return operator_callable + + def _compare_compatible(self, prospective: Version, spec: str) -> bool: + # Compatible releases have an equivalent combination of >= and ==. That + # is that ~=2.2 is equivalent to >=2.2,==2.*. This allows us to + # implement this in terms of the other specifiers instead of + # implementing it ourselves. The only thing we need to do is construct + # the other specifiers. + + # We want everything but the last item in the version, but we want to + # ignore suffix segments. + prefix = _version_join( + list(itertools.takewhile(_is_not_suffix, _version_split(spec)))[:-1] + ) + + # Add the prefix notation to the end of our string + prefix += ".*" + + return self._get_operator(">=")(prospective, spec) and self._get_operator("==")( + prospective, prefix + ) + + def _compare_equal(self, prospective: Version, spec: str) -> bool: + # We need special logic to handle prefix matching + if spec.endswith(".*"): + # In the case of prefix matching we want to ignore local segment. + normalized_prospective = canonicalize_version( + prospective.public, strip_trailing_zero=False + ) + # Get the normalized version string ignoring the trailing .* + normalized_spec = canonicalize_version(spec[:-2], strip_trailing_zero=False) + # Split the spec out by bangs and dots, and pretend that there is + # an implicit dot in between a release segment and a pre-release segment. + split_spec = _version_split(normalized_spec) + + # Split the prospective version out by bangs and dots, and pretend + # that there is an implicit dot in between a release segment and + # a pre-release segment. + split_prospective = _version_split(normalized_prospective) + + # 0-pad the prospective version before shortening it to get the correct + # shortened version. + padded_prospective, _ = _pad_version(split_prospective, split_spec) + + # Shorten the prospective version to be the same length as the spec + # so that we can determine if the specifier is a prefix of the + # prospective version or not. + shortened_prospective = padded_prospective[: len(split_spec)] + + return shortened_prospective == split_spec + else: + # Convert our spec string into a Version + spec_version = Version(spec) + + # If the specifier does not have a local segment, then we want to + # act as if the prospective version also does not have a local + # segment. + if not spec_version.local: + prospective = Version(prospective.public) + + return prospective == spec_version + + def _compare_not_equal(self, prospective: Version, spec: str) -> bool: + return not self._compare_equal(prospective, spec) + + def _compare_less_than_equal(self, prospective: Version, spec: str) -> bool: + # NB: Local version identifiers are NOT permitted in the version + # specifier, so local version labels can be universally removed from + # the prospective version. + return Version(prospective.public) <= Version(spec) + + def _compare_greater_than_equal(self, prospective: Version, spec: str) -> bool: + # NB: Local version identifiers are NOT permitted in the version + # specifier, so local version labels can be universally removed from + # the prospective version. + return Version(prospective.public) >= Version(spec) + + def _compare_less_than(self, prospective: Version, spec_str: str) -> bool: + # Convert our spec to a Version instance, since we'll want to work with + # it as a version. + spec = Version(spec_str) + + # Check to see if the prospective version is less than the spec + # version. If it's not we can short circuit and just return False now + # instead of doing extra unneeded work. + if not prospective < spec: + return False + + # This special case is here so that, unless the specifier itself + # includes is a pre-release version, that we do not accept pre-release + # versions for the version mentioned in the specifier (e.g. <3.1 should + # not match 3.1.dev0, but should match 3.0.dev0). + if not spec.is_prerelease and prospective.is_prerelease: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # If we've gotten to here, it means that prospective version is both + # less than the spec version *and* it's not a pre-release of the same + # version in the spec. + return True + + def _compare_greater_than(self, prospective: Version, spec_str: str) -> bool: + # Convert our spec to a Version instance, since we'll want to work with + # it as a version. + spec = Version(spec_str) + + # Check to see if the prospective version is greater than the spec + # version. If it's not we can short circuit and just return False now + # instead of doing extra unneeded work. + if not prospective > spec: + return False + + # This special case is here so that, unless the specifier itself + # includes is a post-release version, that we do not accept + # post-release versions for the version mentioned in the specifier + # (e.g. >3.1 should not match 3.0.post0, but should match 3.2.post0). + if not spec.is_postrelease and prospective.is_postrelease: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # Ensure that we do not allow a local version of the version mentioned + # in the specifier, which is technically greater than, to match. + if prospective.local is not None: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # If we've gotten to here, it means that prospective version is both + # greater than the spec version *and* it's not a pre-release of the + # same version in the spec. + return True + + def _compare_arbitrary(self, prospective: Version, spec: str) -> bool: + return str(prospective).lower() == str(spec).lower() + + def __contains__(self, item: str | Version) -> bool: + """Return whether or not the item is contained in this specifier. + + :param item: The item to check for. + + This is used for the ``in`` operator and behaves the same as + :meth:`contains` with no ``prereleases`` argument passed. + + >>> "1.2.3" in Specifier(">=1.2.3") + True + >>> Version("1.2.3") in Specifier(">=1.2.3") + True + >>> "1.0.0" in Specifier(">=1.2.3") + False + >>> "1.3.0a1" in Specifier(">=1.2.3") + False + >>> "1.3.0a1" in Specifier(">=1.2.3", prereleases=True) + True + """ + return self.contains(item) + + def contains(self, item: UnparsedVersion, prereleases: bool | None = None) -> bool: + """Return whether or not the item is contained in this specifier. + + :param item: + The item to check for, which can be a version string or a + :class:`Version` instance. + :param prereleases: + Whether or not to match prereleases with this Specifier. If set to + ``None`` (the default), it uses :attr:`prereleases` to determine + whether or not prereleases are allowed. + + >>> Specifier(">=1.2.3").contains("1.2.3") + True + >>> Specifier(">=1.2.3").contains(Version("1.2.3")) + True + >>> Specifier(">=1.2.3").contains("1.0.0") + False + >>> Specifier(">=1.2.3").contains("1.3.0a1") + False + >>> Specifier(">=1.2.3", prereleases=True).contains("1.3.0a1") + True + >>> Specifier(">=1.2.3").contains("1.3.0a1", prereleases=True) + True + """ + + # Determine if prereleases are to be allowed or not. + if prereleases is None: + prereleases = self.prereleases + + # Normalize item to a Version, this allows us to have a shortcut for + # "2.0" in Specifier(">=2") + normalized_item = _coerce_version(item) + + # Determine if we should be supporting prereleases in this specifier + # or not, if we do not support prereleases than we can short circuit + # logic if this version is a prereleases. + if normalized_item.is_prerelease and not prereleases: + return False + + # Actually do the comparison to determine if this item is contained + # within this Specifier or not. + operator_callable: CallableOperator = self._get_operator(self.operator) + return operator_callable(normalized_item, self.version) + + def filter( + self, iterable: Iterable[UnparsedVersionVar], prereleases: bool | None = None + ) -> Iterator[UnparsedVersionVar]: + """Filter items in the given iterable, that match the specifier. + + :param iterable: + An iterable that can contain version strings and :class:`Version` instances. + The items in the iterable will be filtered according to the specifier. + :param prereleases: + Whether or not to allow prereleases in the returned iterator. If set to + ``None`` (the default), it will be intelligently decide whether to allow + prereleases or not (based on the :attr:`prereleases` attribute, and + whether the only versions matching are prereleases). + + This method is smarter than just ``filter(Specifier().contains, [...])`` + because it implements the rule from :pep:`440` that a prerelease item + SHOULD be accepted if no other versions match the given specifier. + + >>> list(Specifier(">=1.2.3").filter(["1.2", "1.3", "1.5a1"])) + ['1.3'] + >>> list(Specifier(">=1.2.3").filter(["1.2", "1.2.3", "1.3", Version("1.4")])) + ['1.2.3', '1.3', ] + >>> list(Specifier(">=1.2.3").filter(["1.2", "1.5a1"])) + ['1.5a1'] + >>> list(Specifier(">=1.2.3").filter(["1.3", "1.5a1"], prereleases=True)) + ['1.3', '1.5a1'] + >>> list(Specifier(">=1.2.3", prereleases=True).filter(["1.3", "1.5a1"])) + ['1.3', '1.5a1'] + """ + + yielded = False + found_prereleases = [] + + kw = {"prereleases": prereleases if prereleases is not None else True} + + # Attempt to iterate over all the values in the iterable and if any of + # them match, yield them. + for version in iterable: + parsed_version = _coerce_version(version) + + if self.contains(parsed_version, **kw): + # If our version is a prerelease, and we were not set to allow + # prereleases, then we'll store it for later in case nothing + # else matches this specifier. + if parsed_version.is_prerelease and not ( + prereleases or self.prereleases + ): + found_prereleases.append(version) + # Either this is not a prerelease, or we should have been + # accepting prereleases from the beginning. + else: + yielded = True + yield version + + # Now that we've iterated over everything, determine if we've yielded + # any values, and if we have not and we have any prereleases stored up + # then we will go ahead and yield the prereleases. + if not yielded and found_prereleases: + for version in found_prereleases: + yield version + + +_prefix_regex = re.compile(r"^([0-9]+)((?:a|b|c|rc)[0-9]+)$") + + +def _version_split(version: str) -> list[str]: + """Split version into components. + + The split components are intended for version comparison. The logic does + not attempt to retain the original version string, so joining the + components back with :func:`_version_join` may not produce the original + version string. + """ + result: list[str] = [] + + epoch, _, rest = version.rpartition("!") + result.append(epoch or "0") + + for item in rest.split("."): + match = _prefix_regex.search(item) + if match: + result.extend(match.groups()) + else: + result.append(item) + return result + + +def _version_join(components: list[str]) -> str: + """Join split version components into a version string. + + This function assumes the input came from :func:`_version_split`, where the + first component must be the epoch (either empty or numeric), and all other + components numeric. + """ + epoch, *rest = components + return f"{epoch}!{'.'.join(rest)}" + + +def _is_not_suffix(segment: str) -> bool: + return not any( + segment.startswith(prefix) for prefix in ("dev", "a", "b", "rc", "post") + ) + + +def _pad_version(left: list[str], right: list[str]) -> tuple[list[str], list[str]]: + left_split, right_split = [], [] + + # Get the release segment of our versions + left_split.append(list(itertools.takewhile(lambda x: x.isdigit(), left))) + right_split.append(list(itertools.takewhile(lambda x: x.isdigit(), right))) + + # Get the rest of our versions + left_split.append(left[len(left_split[0]) :]) + right_split.append(right[len(right_split[0]) :]) + + # Insert our padding + left_split.insert(1, ["0"] * max(0, len(right_split[0]) - len(left_split[0]))) + right_split.insert(1, ["0"] * max(0, len(left_split[0]) - len(right_split[0]))) + + return ( + list(itertools.chain.from_iterable(left_split)), + list(itertools.chain.from_iterable(right_split)), + ) + + +class SpecifierSet(BaseSpecifier): + """This class abstracts handling of a set of version specifiers. + + It can be passed a single specifier (``>=3.0``), a comma-separated list of + specifiers (``>=3.0,!=3.1``), or no specifier at all. + """ + + def __init__( + self, + specifiers: str | Iterable[Specifier] = "", + prereleases: bool | None = None, + ) -> None: + """Initialize a SpecifierSet instance. + + :param specifiers: + The string representation of a specifier or a comma-separated list of + specifiers which will be parsed and normalized before use. + May also be an iterable of ``Specifier`` instances, which will be used + as is. + :param prereleases: + This tells the SpecifierSet if it should accept prerelease versions if + applicable or not. The default of ``None`` will autodetect it from the + given specifiers. + + :raises InvalidSpecifier: + If the given ``specifiers`` are not parseable than this exception will be + raised. + """ + + if isinstance(specifiers, str): + # Split on `,` to break each individual specifier into its own item, and + # strip each item to remove leading/trailing whitespace. + split_specifiers = [s.strip() for s in specifiers.split(",") if s.strip()] + + # Make each individual specifier a Specifier and save in a frozen set + # for later. + self._specs = frozenset(map(Specifier, split_specifiers)) + else: + # Save the supplied specifiers in a frozen set. + self._specs = frozenset(specifiers) + + # Store our prereleases value so we can use it later to determine if + # we accept prereleases or not. + self._prereleases = prereleases + + @property + def prereleases(self) -> bool | None: + # If we have been given an explicit prerelease modifier, then we'll + # pass that through here. + if self._prereleases is not None: + return self._prereleases + + # If we don't have any specifiers, and we don't have a forced value, + # then we'll just return None since we don't know if this should have + # pre-releases or not. + if not self._specs: + return None + + # Otherwise we'll see if any of the given specifiers accept + # prereleases, if any of them do we'll return True, otherwise False. + return any(s.prereleases for s in self._specs) + + @prereleases.setter + def prereleases(self, value: bool) -> None: + self._prereleases = value + + def __repr__(self) -> str: + """A representation of the specifier set that shows all internal state. + + Note that the ordering of the individual specifiers within the set may not + match the input string. + + >>> SpecifierSet('>=1.0.0,!=2.0.0') + =1.0.0')> + >>> SpecifierSet('>=1.0.0,!=2.0.0', prereleases=False) + =1.0.0', prereleases=False)> + >>> SpecifierSet('>=1.0.0,!=2.0.0', prereleases=True) + =1.0.0', prereleases=True)> + """ + pre = ( + f", prereleases={self.prereleases!r}" + if self._prereleases is not None + else "" + ) + + return f"" + + def __str__(self) -> str: + """A string representation of the specifier set that can be round-tripped. + + Note that the ordering of the individual specifiers within the set may not + match the input string. + + >>> str(SpecifierSet(">=1.0.0,!=1.0.1")) + '!=1.0.1,>=1.0.0' + >>> str(SpecifierSet(">=1.0.0,!=1.0.1", prereleases=False)) + '!=1.0.1,>=1.0.0' + """ + return ",".join(sorted(str(s) for s in self._specs)) + + def __hash__(self) -> int: + return hash(self._specs) + + def __and__(self, other: SpecifierSet | str) -> SpecifierSet: + """Return a SpecifierSet which is a combination of the two sets. + + :param other: The other object to combine with. + + >>> SpecifierSet(">=1.0.0,!=1.0.1") & '<=2.0.0,!=2.0.1' + =1.0.0')> + >>> SpecifierSet(">=1.0.0,!=1.0.1") & SpecifierSet('<=2.0.0,!=2.0.1') + =1.0.0')> + """ + if isinstance(other, str): + other = SpecifierSet(other) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + specifier = SpecifierSet() + specifier._specs = frozenset(self._specs | other._specs) + + if self._prereleases is None and other._prereleases is not None: + specifier._prereleases = other._prereleases + elif self._prereleases is not None and other._prereleases is None: + specifier._prereleases = self._prereleases + elif self._prereleases == other._prereleases: + specifier._prereleases = self._prereleases + else: + raise ValueError( + "Cannot combine SpecifierSets with True and False prerelease " + "overrides." + ) + + return specifier + + def __eq__(self, other: object) -> bool: + """Whether or not the two SpecifierSet-like objects are equal. + + :param other: The other object to check against. + + The value of :attr:`prereleases` is ignored. + + >>> SpecifierSet(">=1.0.0,!=1.0.1") == SpecifierSet(">=1.0.0,!=1.0.1") + True + >>> (SpecifierSet(">=1.0.0,!=1.0.1", prereleases=False) == + ... SpecifierSet(">=1.0.0,!=1.0.1", prereleases=True)) + True + >>> SpecifierSet(">=1.0.0,!=1.0.1") == ">=1.0.0,!=1.0.1" + True + >>> SpecifierSet(">=1.0.0,!=1.0.1") == SpecifierSet(">=1.0.0") + False + >>> SpecifierSet(">=1.0.0,!=1.0.1") == SpecifierSet(">=1.0.0,!=1.0.2") + False + """ + if isinstance(other, (str, Specifier)): + other = SpecifierSet(str(other)) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + return self._specs == other._specs + + def __len__(self) -> int: + """Returns the number of specifiers in this specifier set.""" + return len(self._specs) + + def __iter__(self) -> Iterator[Specifier]: + """ + Returns an iterator over all the underlying :class:`Specifier` instances + in this specifier set. + + >>> sorted(SpecifierSet(">=1.0.0,!=1.0.1"), key=str) + [, =1.0.0')>] + """ + return iter(self._specs) + + def __contains__(self, item: UnparsedVersion) -> bool: + """Return whether or not the item is contained in this specifier. + + :param item: The item to check for. + + This is used for the ``in`` operator and behaves the same as + :meth:`contains` with no ``prereleases`` argument passed. + + >>> "1.2.3" in SpecifierSet(">=1.0.0,!=1.0.1") + True + >>> Version("1.2.3") in SpecifierSet(">=1.0.0,!=1.0.1") + True + >>> "1.0.1" in SpecifierSet(">=1.0.0,!=1.0.1") + False + >>> "1.3.0a1" in SpecifierSet(">=1.0.0,!=1.0.1") + False + >>> "1.3.0a1" in SpecifierSet(">=1.0.0,!=1.0.1", prereleases=True) + True + """ + return self.contains(item) + + def contains( + self, + item: UnparsedVersion, + prereleases: bool | None = None, + installed: bool | None = None, + ) -> bool: + """Return whether or not the item is contained in this SpecifierSet. + + :param item: + The item to check for, which can be a version string or a + :class:`Version` instance. + :param prereleases: + Whether or not to match prereleases with this SpecifierSet. If set to + ``None`` (the default), it uses :attr:`prereleases` to determine + whether or not prereleases are allowed. + + >>> SpecifierSet(">=1.0.0,!=1.0.1").contains("1.2.3") + True + >>> SpecifierSet(">=1.0.0,!=1.0.1").contains(Version("1.2.3")) + True + >>> SpecifierSet(">=1.0.0,!=1.0.1").contains("1.0.1") + False + >>> SpecifierSet(">=1.0.0,!=1.0.1").contains("1.3.0a1") + False + >>> SpecifierSet(">=1.0.0,!=1.0.1", prereleases=True).contains("1.3.0a1") + True + >>> SpecifierSet(">=1.0.0,!=1.0.1").contains("1.3.0a1", prereleases=True) + True + """ + # Ensure that our item is a Version instance. + if not isinstance(item, Version): + item = Version(item) + + # Determine if we're forcing a prerelease or not, if we're not forcing + # one for this particular filter call, then we'll use whatever the + # SpecifierSet thinks for whether or not we should support prereleases. + if prereleases is None: + prereleases = self.prereleases + + # We can determine if we're going to allow pre-releases by looking to + # see if any of the underlying items supports them. If none of them do + # and this item is a pre-release then we do not allow it and we can + # short circuit that here. + # Note: This means that 1.0.dev1 would not be contained in something + # like >=1.0.devabc however it would be in >=1.0.debabc,>0.0.dev0 + if not prereleases and item.is_prerelease: + return False + + if installed and item.is_prerelease: + item = Version(item.base_version) + + # We simply dispatch to the underlying specs here to make sure that the + # given version is contained within all of them. + # Note: This use of all() here means that an empty set of specifiers + # will always return True, this is an explicit design decision. + return all(s.contains(item, prereleases=prereleases) for s in self._specs) + + def filter( + self, iterable: Iterable[UnparsedVersionVar], prereleases: bool | None = None + ) -> Iterator[UnparsedVersionVar]: + """Filter items in the given iterable, that match the specifiers in this set. + + :param iterable: + An iterable that can contain version strings and :class:`Version` instances. + The items in the iterable will be filtered according to the specifier. + :param prereleases: + Whether or not to allow prereleases in the returned iterator. If set to + ``None`` (the default), it will be intelligently decide whether to allow + prereleases or not (based on the :attr:`prereleases` attribute, and + whether the only versions matching are prereleases). + + This method is smarter than just ``filter(SpecifierSet(...).contains, [...])`` + because it implements the rule from :pep:`440` that a prerelease item + SHOULD be accepted if no other versions match the given specifier. + + >>> list(SpecifierSet(">=1.2.3").filter(["1.2", "1.3", "1.5a1"])) + ['1.3'] + >>> list(SpecifierSet(">=1.2.3").filter(["1.2", "1.3", Version("1.4")])) + ['1.3', ] + >>> list(SpecifierSet(">=1.2.3").filter(["1.2", "1.5a1"])) + [] + >>> list(SpecifierSet(">=1.2.3").filter(["1.3", "1.5a1"], prereleases=True)) + ['1.3', '1.5a1'] + >>> list(SpecifierSet(">=1.2.3", prereleases=True).filter(["1.3", "1.5a1"])) + ['1.3', '1.5a1'] + + An "empty" SpecifierSet will filter items based on the presence of prerelease + versions in the set. + + >>> list(SpecifierSet("").filter(["1.3", "1.5a1"])) + ['1.3'] + >>> list(SpecifierSet("").filter(["1.5a1"])) + ['1.5a1'] + >>> list(SpecifierSet("", prereleases=True).filter(["1.3", "1.5a1"])) + ['1.3', '1.5a1'] + >>> list(SpecifierSet("").filter(["1.3", "1.5a1"], prereleases=True)) + ['1.3', '1.5a1'] + """ + # Determine if we're forcing a prerelease or not, if we're not forcing + # one for this particular filter call, then we'll use whatever the + # SpecifierSet thinks for whether or not we should support prereleases. + if prereleases is None: + prereleases = self.prereleases + + # If we have any specifiers, then we want to wrap our iterable in the + # filter method for each one, this will act as a logical AND amongst + # each specifier. + if self._specs: + for spec in self._specs: + iterable = spec.filter(iterable, prereleases=bool(prereleases)) + return iter(iterable) + # If we do not have any specifiers, then we need to have a rough filter + # which will filter out any pre-releases, unless there are no final + # releases. + else: + filtered: list[UnparsedVersionVar] = [] + found_prereleases: list[UnparsedVersionVar] = [] + + for item in iterable: + parsed_version = _coerce_version(item) + + # Store any item which is a pre-release for later unless we've + # already found a final version or we are accepting prereleases + if parsed_version.is_prerelease and not prereleases: + if not filtered: + found_prereleases.append(item) + else: + filtered.append(item) + + # If we've found no items except for pre-releases, then we'll go + # ahead and use the pre-releases + if not filtered and found_prereleases and prereleases is None: + return iter(found_prereleases) + + return iter(filtered) diff --git a/venv/Lib/site-packages/packaging/tags.py b/venv/Lib/site-packages/packaging/tags.py new file mode 100644 index 0000000..f590340 --- /dev/null +++ b/venv/Lib/site-packages/packaging/tags.py @@ -0,0 +1,617 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import logging +import platform +import re +import struct +import subprocess +import sys +import sysconfig +from importlib.machinery import EXTENSION_SUFFIXES +from typing import ( + Iterable, + Iterator, + Sequence, + Tuple, + cast, +) + +from . import _manylinux, _musllinux + +logger = logging.getLogger(__name__) + +PythonVersion = Sequence[int] +AppleVersion = Tuple[int, int] + +INTERPRETER_SHORT_NAMES: dict[str, str] = { + "python": "py", # Generic. + "cpython": "cp", + "pypy": "pp", + "ironpython": "ip", + "jython": "jy", +} + + +_32_BIT_INTERPRETER = struct.calcsize("P") == 4 + + +class Tag: + """ + A representation of the tag triple for a wheel. + + Instances are considered immutable and thus are hashable. Equality checking + is also supported. + """ + + __slots__ = ["_abi", "_hash", "_interpreter", "_platform"] + + def __init__(self, interpreter: str, abi: str, platform: str) -> None: + self._interpreter = interpreter.lower() + self._abi = abi.lower() + self._platform = platform.lower() + # The __hash__ of every single element in a Set[Tag] will be evaluated each time + # that a set calls its `.disjoint()` method, which may be called hundreds of + # times when scanning a page of links for packages with tags matching that + # Set[Tag]. Pre-computing the value here produces significant speedups for + # downstream consumers. + self._hash = hash((self._interpreter, self._abi, self._platform)) + + @property + def interpreter(self) -> str: + return self._interpreter + + @property + def abi(self) -> str: + return self._abi + + @property + def platform(self) -> str: + return self._platform + + def __eq__(self, other: object) -> bool: + if not isinstance(other, Tag): + return NotImplemented + + return ( + (self._hash == other._hash) # Short-circuit ASAP for perf reasons. + and (self._platform == other._platform) + and (self._abi == other._abi) + and (self._interpreter == other._interpreter) + ) + + def __hash__(self) -> int: + return self._hash + + def __str__(self) -> str: + return f"{self._interpreter}-{self._abi}-{self._platform}" + + def __repr__(self) -> str: + return f"<{self} @ {id(self)}>" + + +def parse_tag(tag: str) -> frozenset[Tag]: + """ + Parses the provided tag (e.g. `py3-none-any`) into a frozenset of Tag instances. + + Returning a set is required due to the possibility that the tag is a + compressed tag set. + """ + tags = set() + interpreters, abis, platforms = tag.split("-") + for interpreter in interpreters.split("."): + for abi in abis.split("."): + for platform_ in platforms.split("."): + tags.add(Tag(interpreter, abi, platform_)) + return frozenset(tags) + + +def _get_config_var(name: str, warn: bool = False) -> int | str | None: + value: int | str | None = sysconfig.get_config_var(name) + if value is None and warn: + logger.debug( + "Config variable '%s' is unset, Python ABI tag may be incorrect", name + ) + return value + + +def _normalize_string(string: str) -> str: + return string.replace(".", "_").replace("-", "_").replace(" ", "_") + + +def _is_threaded_cpython(abis: list[str]) -> bool: + """ + Determine if the ABI corresponds to a threaded (`--disable-gil`) build. + + The threaded builds are indicated by a "t" in the abiflags. + """ + if len(abis) == 0: + return False + # expect e.g., cp313 + m = re.match(r"cp\d+(.*)", abis[0]) + if not m: + return False + abiflags = m.group(1) + return "t" in abiflags + + +def _abi3_applies(python_version: PythonVersion, threading: bool) -> bool: + """ + Determine if the Python version supports abi3. + + PEP 384 was first implemented in Python 3.2. The threaded (`--disable-gil`) + builds do not support abi3. + """ + return len(python_version) > 1 and tuple(python_version) >= (3, 2) and not threading + + +def _cpython_abis(py_version: PythonVersion, warn: bool = False) -> list[str]: + py_version = tuple(py_version) # To allow for version comparison. + abis = [] + version = _version_nodot(py_version[:2]) + threading = debug = pymalloc = ucs4 = "" + with_debug = _get_config_var("Py_DEBUG", warn) + has_refcount = hasattr(sys, "gettotalrefcount") + # Windows doesn't set Py_DEBUG, so checking for support of debug-compiled + # extension modules is the best option. + # https://github.com/pypa/pip/issues/3383#issuecomment-173267692 + has_ext = "_d.pyd" in EXTENSION_SUFFIXES + if with_debug or (with_debug is None and (has_refcount or has_ext)): + debug = "d" + if py_version >= (3, 13) and _get_config_var("Py_GIL_DISABLED", warn): + threading = "t" + if py_version < (3, 8): + with_pymalloc = _get_config_var("WITH_PYMALLOC", warn) + if with_pymalloc or with_pymalloc is None: + pymalloc = "m" + if py_version < (3, 3): + unicode_size = _get_config_var("Py_UNICODE_SIZE", warn) + if unicode_size == 4 or ( + unicode_size is None and sys.maxunicode == 0x10FFFF + ): + ucs4 = "u" + elif debug: + # Debug builds can also load "normal" extension modules. + # We can also assume no UCS-4 or pymalloc requirement. + abis.append(f"cp{version}{threading}") + abis.insert(0, f"cp{version}{threading}{debug}{pymalloc}{ucs4}") + return abis + + +def cpython_tags( + python_version: PythonVersion | None = None, + abis: Iterable[str] | None = None, + platforms: Iterable[str] | None = None, + *, + warn: bool = False, +) -> Iterator[Tag]: + """ + Yields the tags for a CPython interpreter. + + The tags consist of: + - cp-- + - cp-abi3- + - cp-none- + - cp-abi3- # Older Python versions down to 3.2. + + If python_version only specifies a major version then user-provided ABIs and + the 'none' ABItag will be used. + + If 'abi3' or 'none' are specified in 'abis' then they will be yielded at + their normal position and not at the beginning. + """ + if not python_version: + python_version = sys.version_info[:2] + + interpreter = f"cp{_version_nodot(python_version[:2])}" + + if abis is None: + if len(python_version) > 1: + abis = _cpython_abis(python_version, warn) + else: + abis = [] + abis = list(abis) + # 'abi3' and 'none' are explicitly handled later. + for explicit_abi in ("abi3", "none"): + try: + abis.remove(explicit_abi) + except ValueError: + pass + + platforms = list(platforms or platform_tags()) + for abi in abis: + for platform_ in platforms: + yield Tag(interpreter, abi, platform_) + + threading = _is_threaded_cpython(abis) + use_abi3 = _abi3_applies(python_version, threading) + if use_abi3: + yield from (Tag(interpreter, "abi3", platform_) for platform_ in platforms) + yield from (Tag(interpreter, "none", platform_) for platform_ in platforms) + + if use_abi3: + for minor_version in range(python_version[1] - 1, 1, -1): + for platform_ in platforms: + version = _version_nodot((python_version[0], minor_version)) + interpreter = f"cp{version}" + yield Tag(interpreter, "abi3", platform_) + + +def _generic_abi() -> list[str]: + """ + Return the ABI tag based on EXT_SUFFIX. + """ + # The following are examples of `EXT_SUFFIX`. + # We want to keep the parts which are related to the ABI and remove the + # parts which are related to the platform: + # - linux: '.cpython-310-x86_64-linux-gnu.so' => cp310 + # - mac: '.cpython-310-darwin.so' => cp310 + # - win: '.cp310-win_amd64.pyd' => cp310 + # - win: '.pyd' => cp37 (uses _cpython_abis()) + # - pypy: '.pypy38-pp73-x86_64-linux-gnu.so' => pypy38_pp73 + # - graalpy: '.graalpy-38-native-x86_64-darwin.dylib' + # => graalpy_38_native + + ext_suffix = _get_config_var("EXT_SUFFIX", warn=True) + if not isinstance(ext_suffix, str) or ext_suffix[0] != ".": + raise SystemError("invalid sysconfig.get_config_var('EXT_SUFFIX')") + parts = ext_suffix.split(".") + if len(parts) < 3: + # CPython3.7 and earlier uses ".pyd" on Windows. + return _cpython_abis(sys.version_info[:2]) + soabi = parts[1] + if soabi.startswith("cpython"): + # non-windows + abi = "cp" + soabi.split("-")[1] + elif soabi.startswith("cp"): + # windows + abi = soabi.split("-")[0] + elif soabi.startswith("pypy"): + abi = "-".join(soabi.split("-")[:2]) + elif soabi.startswith("graalpy"): + abi = "-".join(soabi.split("-")[:3]) + elif soabi: + # pyston, ironpython, others? + abi = soabi + else: + return [] + return [_normalize_string(abi)] + + +def generic_tags( + interpreter: str | None = None, + abis: Iterable[str] | None = None, + platforms: Iterable[str] | None = None, + *, + warn: bool = False, +) -> Iterator[Tag]: + """ + Yields the tags for a generic interpreter. + + The tags consist of: + - -- + + The "none" ABI will be added if it was not explicitly provided. + """ + if not interpreter: + interp_name = interpreter_name() + interp_version = interpreter_version(warn=warn) + interpreter = "".join([interp_name, interp_version]) + if abis is None: + abis = _generic_abi() + else: + abis = list(abis) + platforms = list(platforms or platform_tags()) + if "none" not in abis: + abis.append("none") + for abi in abis: + for platform_ in platforms: + yield Tag(interpreter, abi, platform_) + + +def _py_interpreter_range(py_version: PythonVersion) -> Iterator[str]: + """ + Yields Python versions in descending order. + + After the latest version, the major-only version will be yielded, and then + all previous versions of that major version. + """ + if len(py_version) > 1: + yield f"py{_version_nodot(py_version[:2])}" + yield f"py{py_version[0]}" + if len(py_version) > 1: + for minor in range(py_version[1] - 1, -1, -1): + yield f"py{_version_nodot((py_version[0], minor))}" + + +def compatible_tags( + python_version: PythonVersion | None = None, + interpreter: str | None = None, + platforms: Iterable[str] | None = None, +) -> Iterator[Tag]: + """ + Yields the sequence of tags that are compatible with a specific version of Python. + + The tags consist of: + - py*-none- + - -none-any # ... if `interpreter` is provided. + - py*-none-any + """ + if not python_version: + python_version = sys.version_info[:2] + platforms = list(platforms or platform_tags()) + for version in _py_interpreter_range(python_version): + for platform_ in platforms: + yield Tag(version, "none", platform_) + if interpreter: + yield Tag(interpreter, "none", "any") + for version in _py_interpreter_range(python_version): + yield Tag(version, "none", "any") + + +def _mac_arch(arch: str, is_32bit: bool = _32_BIT_INTERPRETER) -> str: + if not is_32bit: + return arch + + if arch.startswith("ppc"): + return "ppc" + + return "i386" + + +def _mac_binary_formats(version: AppleVersion, cpu_arch: str) -> list[str]: + formats = [cpu_arch] + if cpu_arch == "x86_64": + if version < (10, 4): + return [] + formats.extend(["intel", "fat64", "fat32"]) + + elif cpu_arch == "i386": + if version < (10, 4): + return [] + formats.extend(["intel", "fat32", "fat"]) + + elif cpu_arch == "ppc64": + # TODO: Need to care about 32-bit PPC for ppc64 through 10.2? + if version > (10, 5) or version < (10, 4): + return [] + formats.append("fat64") + + elif cpu_arch == "ppc": + if version > (10, 6): + return [] + formats.extend(["fat32", "fat"]) + + if cpu_arch in {"arm64", "x86_64"}: + formats.append("universal2") + + if cpu_arch in {"x86_64", "i386", "ppc64", "ppc", "intel"}: + formats.append("universal") + + return formats + + +def mac_platforms( + version: AppleVersion | None = None, arch: str | None = None +) -> Iterator[str]: + """ + Yields the platform tags for a macOS system. + + The `version` parameter is a two-item tuple specifying the macOS version to + generate platform tags for. The `arch` parameter is the CPU architecture to + generate platform tags for. Both parameters default to the appropriate value + for the current system. + """ + version_str, _, cpu_arch = platform.mac_ver() + if version is None: + version = cast("AppleVersion", tuple(map(int, version_str.split(".")[:2]))) + if version == (10, 16): + # When built against an older macOS SDK, Python will report macOS 10.16 + # instead of the real version. + version_str = subprocess.run( + [ + sys.executable, + "-sS", + "-c", + "import platform; print(platform.mac_ver()[0])", + ], + check=True, + env={"SYSTEM_VERSION_COMPAT": "0"}, + stdout=subprocess.PIPE, + text=True, + ).stdout + version = cast("AppleVersion", tuple(map(int, version_str.split(".")[:2]))) + else: + version = version + if arch is None: + arch = _mac_arch(cpu_arch) + else: + arch = arch + + if (10, 0) <= version and version < (11, 0): + # Prior to Mac OS 11, each yearly release of Mac OS bumped the + # "minor" version number. The major version was always 10. + major_version = 10 + for minor_version in range(version[1], -1, -1): + compat_version = major_version, minor_version + binary_formats = _mac_binary_formats(compat_version, arch) + for binary_format in binary_formats: + yield f"macosx_{major_version}_{minor_version}_{binary_format}" + + if version >= (11, 0): + # Starting with Mac OS 11, each yearly release bumps the major version + # number. The minor versions are now the midyear updates. + minor_version = 0 + for major_version in range(version[0], 10, -1): + compat_version = major_version, minor_version + binary_formats = _mac_binary_formats(compat_version, arch) + for binary_format in binary_formats: + yield f"macosx_{major_version}_{minor_version}_{binary_format}" + + if version >= (11, 0): + # Mac OS 11 on x86_64 is compatible with binaries from previous releases. + # Arm64 support was introduced in 11.0, so no Arm binaries from previous + # releases exist. + # + # However, the "universal2" binary format can have a + # macOS version earlier than 11.0 when the x86_64 part of the binary supports + # that version of macOS. + major_version = 10 + if arch == "x86_64": + for minor_version in range(16, 3, -1): + compat_version = major_version, minor_version + binary_formats = _mac_binary_formats(compat_version, arch) + for binary_format in binary_formats: + yield f"macosx_{major_version}_{minor_version}_{binary_format}" + else: + for minor_version in range(16, 3, -1): + compat_version = major_version, minor_version + binary_format = "universal2" + yield f"macosx_{major_version}_{minor_version}_{binary_format}" + + +def ios_platforms( + version: AppleVersion | None = None, multiarch: str | None = None +) -> Iterator[str]: + """ + Yields the platform tags for an iOS system. + + :param version: A two-item tuple specifying the iOS version to generate + platform tags for. Defaults to the current iOS version. + :param multiarch: The CPU architecture+ABI to generate platform tags for - + (the value used by `sys.implementation._multiarch` e.g., + `arm64_iphoneos` or `x84_64_iphonesimulator`). Defaults to the current + multiarch value. + """ + if version is None: + # if iOS is the current platform, ios_ver *must* be defined. However, + # it won't exist for CPython versions before 3.13, which causes a mypy + # error. + _, release, _, _ = platform.ios_ver() # type: ignore[attr-defined, unused-ignore] + version = cast("AppleVersion", tuple(map(int, release.split(".")[:2]))) + + if multiarch is None: + multiarch = sys.implementation._multiarch + multiarch = multiarch.replace("-", "_") + + ios_platform_template = "ios_{major}_{minor}_{multiarch}" + + # Consider any iOS major.minor version from the version requested, down to + # 12.0. 12.0 is the first iOS version that is known to have enough features + # to support CPython. Consider every possible minor release up to X.9. There + # highest the minor has ever gone is 8 (14.8 and 15.8) but having some extra + # candidates that won't ever match doesn't really hurt, and it saves us from + # having to keep an explicit list of known iOS versions in the code. Return + # the results descending order of version number. + + # If the requested major version is less than 12, there won't be any matches. + if version[0] < 12: + return + + # Consider the actual X.Y version that was requested. + yield ios_platform_template.format( + major=version[0], minor=version[1], multiarch=multiarch + ) + + # Consider every minor version from X.0 to the minor version prior to the + # version requested by the platform. + for minor in range(version[1] - 1, -1, -1): + yield ios_platform_template.format( + major=version[0], minor=minor, multiarch=multiarch + ) + + for major in range(version[0] - 1, 11, -1): + for minor in range(9, -1, -1): + yield ios_platform_template.format( + major=major, minor=minor, multiarch=multiarch + ) + + +def _linux_platforms(is_32bit: bool = _32_BIT_INTERPRETER) -> Iterator[str]: + linux = _normalize_string(sysconfig.get_platform()) + if not linux.startswith("linux_"): + # we should never be here, just yield the sysconfig one and return + yield linux + return + if is_32bit: + if linux == "linux_x86_64": + linux = "linux_i686" + elif linux == "linux_aarch64": + linux = "linux_armv8l" + _, arch = linux.split("_", 1) + archs = {"armv8l": ["armv8l", "armv7l"]}.get(arch, [arch]) + yield from _manylinux.platform_tags(archs) + yield from _musllinux.platform_tags(archs) + for arch in archs: + yield f"linux_{arch}" + + +def _generic_platforms() -> Iterator[str]: + yield _normalize_string(sysconfig.get_platform()) + + +def platform_tags() -> Iterator[str]: + """ + Provides the platform tags for this installation. + """ + if platform.system() == "Darwin": + return mac_platforms() + elif platform.system() == "iOS": + return ios_platforms() + elif platform.system() == "Linux": + return _linux_platforms() + else: + return _generic_platforms() + + +def interpreter_name() -> str: + """ + Returns the name of the running interpreter. + + Some implementations have a reserved, two-letter abbreviation which will + be returned when appropriate. + """ + name = sys.implementation.name + return INTERPRETER_SHORT_NAMES.get(name) or name + + +def interpreter_version(*, warn: bool = False) -> str: + """ + Returns the version of the running interpreter. + """ + version = _get_config_var("py_version_nodot", warn=warn) + if version: + version = str(version) + else: + version = _version_nodot(sys.version_info[:2]) + return version + + +def _version_nodot(version: PythonVersion) -> str: + return "".join(map(str, version)) + + +def sys_tags(*, warn: bool = False) -> Iterator[Tag]: + """ + Returns the sequence of tag triples for the running interpreter. + + The order of the sequence corresponds to priority order for the + interpreter, from most to least important. + """ + + interp_name = interpreter_name() + if interp_name == "cp": + yield from cpython_tags(warn=warn) + else: + yield from generic_tags() + + if interp_name == "pp": + interp = "pp3" + elif interp_name == "cp": + interp = "cp" + interpreter_version(warn=warn) + else: + interp = None + yield from compatible_tags(interpreter=interp) diff --git a/venv/Lib/site-packages/packaging/utils.py b/venv/Lib/site-packages/packaging/utils.py new file mode 100644 index 0000000..2345095 --- /dev/null +++ b/venv/Lib/site-packages/packaging/utils.py @@ -0,0 +1,163 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from __future__ import annotations + +import functools +import re +from typing import NewType, Tuple, Union, cast + +from .tags import Tag, parse_tag +from .version import InvalidVersion, Version, _TrimmedRelease + +BuildTag = Union[Tuple[()], Tuple[int, str]] +NormalizedName = NewType("NormalizedName", str) + + +class InvalidName(ValueError): + """ + An invalid distribution name; users should refer to the packaging user guide. + """ + + +class InvalidWheelFilename(ValueError): + """ + An invalid wheel filename was found, users should refer to PEP 427. + """ + + +class InvalidSdistFilename(ValueError): + """ + An invalid sdist filename was found, users should refer to the packaging user guide. + """ + + +# Core metadata spec for `Name` +_validate_regex = re.compile( + r"^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$", re.IGNORECASE +) +_canonicalize_regex = re.compile(r"[-_.]+") +_normalized_regex = re.compile(r"^([a-z0-9]|[a-z0-9]([a-z0-9-](?!--))*[a-z0-9])$") +# PEP 427: The build number must start with a digit. +_build_tag_regex = re.compile(r"(\d+)(.*)") + + +def canonicalize_name(name: str, *, validate: bool = False) -> NormalizedName: + if validate and not _validate_regex.match(name): + raise InvalidName(f"name is invalid: {name!r}") + # This is taken from PEP 503. + value = _canonicalize_regex.sub("-", name).lower() + return cast(NormalizedName, value) + + +def is_normalized_name(name: str) -> bool: + return _normalized_regex.match(name) is not None + + +@functools.singledispatch +def canonicalize_version( + version: Version | str, *, strip_trailing_zero: bool = True +) -> str: + """ + Return a canonical form of a version as a string. + + >>> canonicalize_version('1.0.1') + '1.0.1' + + Per PEP 625, versions may have multiple canonical forms, differing + only by trailing zeros. + + >>> canonicalize_version('1.0.0') + '1' + >>> canonicalize_version('1.0.0', strip_trailing_zero=False) + '1.0.0' + + Invalid versions are returned unaltered. + + >>> canonicalize_version('foo bar baz') + 'foo bar baz' + """ + return str(_TrimmedRelease(str(version)) if strip_trailing_zero else version) + + +@canonicalize_version.register +def _(version: str, *, strip_trailing_zero: bool = True) -> str: + try: + parsed = Version(version) + except InvalidVersion: + # Legacy versions cannot be normalized + return version + return canonicalize_version(parsed, strip_trailing_zero=strip_trailing_zero) + + +def parse_wheel_filename( + filename: str, +) -> tuple[NormalizedName, Version, BuildTag, frozenset[Tag]]: + if not filename.endswith(".whl"): + raise InvalidWheelFilename( + f"Invalid wheel filename (extension must be '.whl'): {filename!r}" + ) + + filename = filename[:-4] + dashes = filename.count("-") + if dashes not in (4, 5): + raise InvalidWheelFilename( + f"Invalid wheel filename (wrong number of parts): {filename!r}" + ) + + parts = filename.split("-", dashes - 2) + name_part = parts[0] + # See PEP 427 for the rules on escaping the project name. + if "__" in name_part or re.match(r"^[\w\d._]*$", name_part, re.UNICODE) is None: + raise InvalidWheelFilename(f"Invalid project name: {filename!r}") + name = canonicalize_name(name_part) + + try: + version = Version(parts[1]) + except InvalidVersion as e: + raise InvalidWheelFilename( + f"Invalid wheel filename (invalid version): {filename!r}" + ) from e + + if dashes == 5: + build_part = parts[2] + build_match = _build_tag_regex.match(build_part) + if build_match is None: + raise InvalidWheelFilename( + f"Invalid build number: {build_part} in {filename!r}" + ) + build = cast(BuildTag, (int(build_match.group(1)), build_match.group(2))) + else: + build = () + tags = parse_tag(parts[-1]) + return (name, version, build, tags) + + +def parse_sdist_filename(filename: str) -> tuple[NormalizedName, Version]: + if filename.endswith(".tar.gz"): + file_stem = filename[: -len(".tar.gz")] + elif filename.endswith(".zip"): + file_stem = filename[: -len(".zip")] + else: + raise InvalidSdistFilename( + f"Invalid sdist filename (extension must be '.tar.gz' or '.zip'):" + f" {filename!r}" + ) + + # We are requiring a PEP 440 version, which cannot contain dashes, + # so we split on the last dash. + name_part, sep, version_part = file_stem.rpartition("-") + if not sep: + raise InvalidSdistFilename(f"Invalid sdist filename: {filename!r}") + + name = canonicalize_name(name_part) + + try: + version = Version(version_part) + except InvalidVersion as e: + raise InvalidSdistFilename( + f"Invalid sdist filename (invalid version): {filename!r}" + ) from e + + return (name, version) diff --git a/venv/Lib/site-packages/packaging/version.py b/venv/Lib/site-packages/packaging/version.py new file mode 100644 index 0000000..c9bbda2 --- /dev/null +++ b/venv/Lib/site-packages/packaging/version.py @@ -0,0 +1,582 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. +""" +.. testsetup:: + + from packaging.version import parse, Version +""" + +from __future__ import annotations + +import itertools +import re +from typing import Any, Callable, NamedTuple, SupportsInt, Tuple, Union + +from ._structures import Infinity, InfinityType, NegativeInfinity, NegativeInfinityType + +__all__ = ["VERSION_PATTERN", "InvalidVersion", "Version", "parse"] + +LocalType = Tuple[Union[int, str], ...] + +CmpPrePostDevType = Union[InfinityType, NegativeInfinityType, Tuple[str, int]] +CmpLocalType = Union[ + NegativeInfinityType, + Tuple[Union[Tuple[int, str], Tuple[NegativeInfinityType, Union[int, str]]], ...], +] +CmpKey = Tuple[ + int, + Tuple[int, ...], + CmpPrePostDevType, + CmpPrePostDevType, + CmpPrePostDevType, + CmpLocalType, +] +VersionComparisonMethod = Callable[[CmpKey, CmpKey], bool] + + +class _Version(NamedTuple): + epoch: int + release: tuple[int, ...] + dev: tuple[str, int] | None + pre: tuple[str, int] | None + post: tuple[str, int] | None + local: LocalType | None + + +def parse(version: str) -> Version: + """Parse the given version string. + + >>> parse('1.0.dev1') + + + :param version: The version string to parse. + :raises InvalidVersion: When the version string is not a valid version. + """ + return Version(version) + + +class InvalidVersion(ValueError): + """Raised when a version string is not a valid version. + + >>> Version("invalid") + Traceback (most recent call last): + ... + packaging.version.InvalidVersion: Invalid version: 'invalid' + """ + + +class _BaseVersion: + _key: tuple[Any, ...] + + def __hash__(self) -> int: + return hash(self._key) + + # Please keep the duplicated `isinstance` check + # in the six comparisons hereunder + # unless you find a way to avoid adding overhead function calls. + def __lt__(self, other: _BaseVersion) -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key < other._key + + def __le__(self, other: _BaseVersion) -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key <= other._key + + def __eq__(self, other: object) -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key == other._key + + def __ge__(self, other: _BaseVersion) -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key >= other._key + + def __gt__(self, other: _BaseVersion) -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key > other._key + + def __ne__(self, other: object) -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key != other._key + + +# Deliberately not anchored to the start and end of the string, to make it +# easier for 3rd party code to reuse +_VERSION_PATTERN = r""" + v? + (?: + (?:(?P[0-9]+)!)? # epoch + (?P[0-9]+(?:\.[0-9]+)*) # release segment + (?P
                                          # pre-release
+            [-_\.]?
+            (?Palpha|a|beta|b|preview|pre|c|rc)
+            [-_\.]?
+            (?P[0-9]+)?
+        )?
+        (?P                                         # post release
+            (?:-(?P[0-9]+))
+            |
+            (?:
+                [-_\.]?
+                (?Ppost|rev|r)
+                [-_\.]?
+                (?P[0-9]+)?
+            )
+        )?
+        (?P                                          # dev release
+            [-_\.]?
+            (?Pdev)
+            [-_\.]?
+            (?P[0-9]+)?
+        )?
+    )
+    (?:\+(?P[a-z0-9]+(?:[-_\.][a-z0-9]+)*))?       # local version
+"""
+
+VERSION_PATTERN = _VERSION_PATTERN
+"""
+A string containing the regular expression used to match a valid version.
+
+The pattern is not anchored at either end, and is intended for embedding in larger
+expressions (for example, matching a version number as part of a file name). The
+regular expression should be compiled with the ``re.VERBOSE`` and ``re.IGNORECASE``
+flags set.
+
+:meta hide-value:
+"""
+
+
+class Version(_BaseVersion):
+    """This class abstracts handling of a project's versions.
+
+    A :class:`Version` instance is comparison aware and can be compared and
+    sorted using the standard Python interfaces.
+
+    >>> v1 = Version("1.0a5")
+    >>> v2 = Version("1.0")
+    >>> v1
+    
+    >>> v2
+    
+    >>> v1 < v2
+    True
+    >>> v1 == v2
+    False
+    >>> v1 > v2
+    False
+    >>> v1 >= v2
+    False
+    >>> v1 <= v2
+    True
+    """
+
+    _regex = re.compile(r"^\s*" + VERSION_PATTERN + r"\s*$", re.VERBOSE | re.IGNORECASE)
+    _key: CmpKey
+
+    def __init__(self, version: str) -> None:
+        """Initialize a Version object.
+
+        :param version:
+            The string representation of a version which will be parsed and normalized
+            before use.
+        :raises InvalidVersion:
+            If the ``version`` does not conform to PEP 440 in any way then this
+            exception will be raised.
+        """
+
+        # Validate the version and parse it into pieces
+        match = self._regex.search(version)
+        if not match:
+            raise InvalidVersion(f"Invalid version: {version!r}")
+
+        # Store the parsed out pieces of the version
+        self._version = _Version(
+            epoch=int(match.group("epoch")) if match.group("epoch") else 0,
+            release=tuple(int(i) for i in match.group("release").split(".")),
+            pre=_parse_letter_version(match.group("pre_l"), match.group("pre_n")),
+            post=_parse_letter_version(
+                match.group("post_l"), match.group("post_n1") or match.group("post_n2")
+            ),
+            dev=_parse_letter_version(match.group("dev_l"), match.group("dev_n")),
+            local=_parse_local_version(match.group("local")),
+        )
+
+        # Generate a key which will be used for sorting
+        self._key = _cmpkey(
+            self._version.epoch,
+            self._version.release,
+            self._version.pre,
+            self._version.post,
+            self._version.dev,
+            self._version.local,
+        )
+
+    def __repr__(self) -> str:
+        """A representation of the Version that shows all internal state.
+
+        >>> Version('1.0.0')
+        
+        """
+        return f""
+
+    def __str__(self) -> str:
+        """A string representation of the version that can be round-tripped.
+
+        >>> str(Version("1.0a5"))
+        '1.0a5'
+        """
+        parts = []
+
+        # Epoch
+        if self.epoch != 0:
+            parts.append(f"{self.epoch}!")
+
+        # Release segment
+        parts.append(".".join(str(x) for x in self.release))
+
+        # Pre-release
+        if self.pre is not None:
+            parts.append("".join(str(x) for x in self.pre))
+
+        # Post-release
+        if self.post is not None:
+            parts.append(f".post{self.post}")
+
+        # Development release
+        if self.dev is not None:
+            parts.append(f".dev{self.dev}")
+
+        # Local version segment
+        if self.local is not None:
+            parts.append(f"+{self.local}")
+
+        return "".join(parts)
+
+    @property
+    def epoch(self) -> int:
+        """The epoch of the version.
+
+        >>> Version("2.0.0").epoch
+        0
+        >>> Version("1!2.0.0").epoch
+        1
+        """
+        return self._version.epoch
+
+    @property
+    def release(self) -> tuple[int, ...]:
+        """The components of the "release" segment of the version.
+
+        >>> Version("1.2.3").release
+        (1, 2, 3)
+        >>> Version("2.0.0").release
+        (2, 0, 0)
+        >>> Version("1!2.0.0.post0").release
+        (2, 0, 0)
+
+        Includes trailing zeroes but not the epoch or any pre-release / development /
+        post-release suffixes.
+        """
+        return self._version.release
+
+    @property
+    def pre(self) -> tuple[str, int] | None:
+        """The pre-release segment of the version.
+
+        >>> print(Version("1.2.3").pre)
+        None
+        >>> Version("1.2.3a1").pre
+        ('a', 1)
+        >>> Version("1.2.3b1").pre
+        ('b', 1)
+        >>> Version("1.2.3rc1").pre
+        ('rc', 1)
+        """
+        return self._version.pre
+
+    @property
+    def post(self) -> int | None:
+        """The post-release number of the version.
+
+        >>> print(Version("1.2.3").post)
+        None
+        >>> Version("1.2.3.post1").post
+        1
+        """
+        return self._version.post[1] if self._version.post else None
+
+    @property
+    def dev(self) -> int | None:
+        """The development number of the version.
+
+        >>> print(Version("1.2.3").dev)
+        None
+        >>> Version("1.2.3.dev1").dev
+        1
+        """
+        return self._version.dev[1] if self._version.dev else None
+
+    @property
+    def local(self) -> str | None:
+        """The local version segment of the version.
+
+        >>> print(Version("1.2.3").local)
+        None
+        >>> Version("1.2.3+abc").local
+        'abc'
+        """
+        if self._version.local:
+            return ".".join(str(x) for x in self._version.local)
+        else:
+            return None
+
+    @property
+    def public(self) -> str:
+        """The public portion of the version.
+
+        >>> Version("1.2.3").public
+        '1.2.3'
+        >>> Version("1.2.3+abc").public
+        '1.2.3'
+        >>> Version("1!1.2.3dev1+abc").public
+        '1!1.2.3.dev1'
+        """
+        return str(self).split("+", 1)[0]
+
+    @property
+    def base_version(self) -> str:
+        """The "base version" of the version.
+
+        >>> Version("1.2.3").base_version
+        '1.2.3'
+        >>> Version("1.2.3+abc").base_version
+        '1.2.3'
+        >>> Version("1!1.2.3dev1+abc").base_version
+        '1!1.2.3'
+
+        The "base version" is the public version of the project without any pre or post
+        release markers.
+        """
+        parts = []
+
+        # Epoch
+        if self.epoch != 0:
+            parts.append(f"{self.epoch}!")
+
+        # Release segment
+        parts.append(".".join(str(x) for x in self.release))
+
+        return "".join(parts)
+
+    @property
+    def is_prerelease(self) -> bool:
+        """Whether this version is a pre-release.
+
+        >>> Version("1.2.3").is_prerelease
+        False
+        >>> Version("1.2.3a1").is_prerelease
+        True
+        >>> Version("1.2.3b1").is_prerelease
+        True
+        >>> Version("1.2.3rc1").is_prerelease
+        True
+        >>> Version("1.2.3dev1").is_prerelease
+        True
+        """
+        return self.dev is not None or self.pre is not None
+
+    @property
+    def is_postrelease(self) -> bool:
+        """Whether this version is a post-release.
+
+        >>> Version("1.2.3").is_postrelease
+        False
+        >>> Version("1.2.3.post1").is_postrelease
+        True
+        """
+        return self.post is not None
+
+    @property
+    def is_devrelease(self) -> bool:
+        """Whether this version is a development release.
+
+        >>> Version("1.2.3").is_devrelease
+        False
+        >>> Version("1.2.3.dev1").is_devrelease
+        True
+        """
+        return self.dev is not None
+
+    @property
+    def major(self) -> int:
+        """The first item of :attr:`release` or ``0`` if unavailable.
+
+        >>> Version("1.2.3").major
+        1
+        """
+        return self.release[0] if len(self.release) >= 1 else 0
+
+    @property
+    def minor(self) -> int:
+        """The second item of :attr:`release` or ``0`` if unavailable.
+
+        >>> Version("1.2.3").minor
+        2
+        >>> Version("1").minor
+        0
+        """
+        return self.release[1] if len(self.release) >= 2 else 0
+
+    @property
+    def micro(self) -> int:
+        """The third item of :attr:`release` or ``0`` if unavailable.
+
+        >>> Version("1.2.3").micro
+        3
+        >>> Version("1").micro
+        0
+        """
+        return self.release[2] if len(self.release) >= 3 else 0
+
+
+class _TrimmedRelease(Version):
+    @property
+    def release(self) -> tuple[int, ...]:
+        """
+        Release segment without any trailing zeros.
+
+        >>> _TrimmedRelease('1.0.0').release
+        (1,)
+        >>> _TrimmedRelease('0.0').release
+        (0,)
+        """
+        rel = super().release
+        nonzeros = (index for index, val in enumerate(rel) if val)
+        last_nonzero = max(nonzeros, default=0)
+        return rel[: last_nonzero + 1]
+
+
+def _parse_letter_version(
+    letter: str | None, number: str | bytes | SupportsInt | None
+) -> tuple[str, int] | None:
+    if letter:
+        # We consider there to be an implicit 0 in a pre-release if there is
+        # not a numeral associated with it.
+        if number is None:
+            number = 0
+
+        # We normalize any letters to their lower case form
+        letter = letter.lower()
+
+        # We consider some words to be alternate spellings of other words and
+        # in those cases we want to normalize the spellings to our preferred
+        # spelling.
+        if letter == "alpha":
+            letter = "a"
+        elif letter == "beta":
+            letter = "b"
+        elif letter in ["c", "pre", "preview"]:
+            letter = "rc"
+        elif letter in ["rev", "r"]:
+            letter = "post"
+
+        return letter, int(number)
+
+    assert not letter
+    if number:
+        # We assume if we are given a number, but we are not given a letter
+        # then this is using the implicit post release syntax (e.g. 1.0-1)
+        letter = "post"
+
+        return letter, int(number)
+
+    return None
+
+
+_local_version_separators = re.compile(r"[\._-]")
+
+
+def _parse_local_version(local: str | None) -> LocalType | None:
+    """
+    Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").
+    """
+    if local is not None:
+        return tuple(
+            part.lower() if not part.isdigit() else int(part)
+            for part in _local_version_separators.split(local)
+        )
+    return None
+
+
+def _cmpkey(
+    epoch: int,
+    release: tuple[int, ...],
+    pre: tuple[str, int] | None,
+    post: tuple[str, int] | None,
+    dev: tuple[str, int] | None,
+    local: LocalType | None,
+) -> CmpKey:
+    # When we compare a release version, we want to compare it with all of the
+    # trailing zeros removed. So we'll use a reverse the list, drop all the now
+    # leading zeros until we come to something non zero, then take the rest
+    # re-reverse it back into the correct order and make it a tuple and use
+    # that for our sorting key.
+    _release = tuple(
+        reversed(list(itertools.dropwhile(lambda x: x == 0, reversed(release))))
+    )
+
+    # We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0.
+    # We'll do this by abusing the pre segment, but we _only_ want to do this
+    # if there is not a pre or a post segment. If we have one of those then
+    # the normal sorting rules will handle this case correctly.
+    if pre is None and post is None and dev is not None:
+        _pre: CmpPrePostDevType = NegativeInfinity
+    # Versions without a pre-release (except as noted above) should sort after
+    # those with one.
+    elif pre is None:
+        _pre = Infinity
+    else:
+        _pre = pre
+
+    # Versions without a post segment should sort before those with one.
+    if post is None:
+        _post: CmpPrePostDevType = NegativeInfinity
+
+    else:
+        _post = post
+
+    # Versions without a development segment should sort after those with one.
+    if dev is None:
+        _dev: CmpPrePostDevType = Infinity
+
+    else:
+        _dev = dev
+
+    if local is None:
+        # Versions without a local segment should sort before those with one.
+        _local: CmpLocalType = NegativeInfinity
+    else:
+        # Versions with a local segment need that segment parsed to implement
+        # the sorting rules in PEP440.
+        # - Alpha numeric segments sort before numeric segments
+        # - Alpha numeric segments sort lexicographically
+        # - Numeric segments sort numerically
+        # - Shorter versions sort before longer versions when the prefixes
+        #   match exactly
+        _local = tuple(
+            (i, "") if isinstance(i, int) else (NegativeInfinity, i) for i in local
+        )
+
+    return epoch, _release, _pre, _post, _dev, _local
diff --git a/venv/Lib/site-packages/pefile-2023.2.7.dist-info/INSTALLER b/venv/Lib/site-packages/pefile-2023.2.7.dist-info/INSTALLER
new file mode 100644
index 0000000..a1b589e
--- /dev/null
+++ b/venv/Lib/site-packages/pefile-2023.2.7.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/venv/Lib/site-packages/pefile-2023.2.7.dist-info/LICENSE b/venv/Lib/site-packages/pefile-2023.2.7.dist-info/LICENSE
new file mode 100644
index 0000000..ddd7342
--- /dev/null
+++ b/venv/Lib/site-packages/pefile-2023.2.7.dist-info/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2004-2023 Ero Carrera
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/venv/Lib/site-packages/pefile-2023.2.7.dist-info/METADATA b/venv/Lib/site-packages/pefile-2023.2.7.dist-info/METADATA
new file mode 100644
index 0000000..fefd6a3
--- /dev/null
+++ b/venv/Lib/site-packages/pefile-2023.2.7.dist-info/METADATA
@@ -0,0 +1,34 @@
+Metadata-Version: 2.1
+Name: pefile
+Version: 2023.2.7
+Summary: Python PE parsing module
+Home-page: https://github.com/erocarrera/pefile
+Download-URL: https://github.com/erocarrera/pefile/releases/download/v2023.2.7/pefile-2023.2.7.tar.gz
+Author: Ero Carrera
+Author-email: ero.carrera@gmail.com
+License: MIT
+Keywords: pe,exe,dll,pefile,pecoff
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: Intended Audience :: Science/Research
+Classifier: Natural Language :: English
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Requires-Python: >=3.6.0
+License-File: LICENSE
+
+pefile, Portable Executable reader module
+
+All the PE file basic structures are available with their default names as
+attributes of the instance returned.
+
+Processed elements such as the import table are made available with lowercase
+names, to differentiate them from the upper case basic structure names.
+
+pefile has been tested against many edge cases such as corrupted and malformed
+PEs as well as malware, which often attempts to abuse the format way beyond its
+standard use. To the best of my knowledge most of the abuse is handled
+gracefully.
+
+Copyright (c) 2005-2023 Ero Carrera 
diff --git a/venv/Lib/site-packages/pefile-2023.2.7.dist-info/RECORD b/venv/Lib/site-packages/pefile-2023.2.7.dist-info/RECORD
new file mode 100644
index 0000000..acc4d8e
--- /dev/null
+++ b/venv/Lib/site-packages/pefile-2023.2.7.dist-info/RECORD
@@ -0,0 +1,16 @@
+__pycache__/pefile.cpython-311.pyc,,
+__pycache__/peutils.cpython-311.pyc,,
+ordlookup/__init__.py,sha256=qV325Dvqk9HYGlF2BXkjSAU8NiAqGk9wg6bcGA7DMCY,784
+ordlookup/__pycache__/__init__.cpython-311.pyc,,
+ordlookup/__pycache__/oleaut32.cpython-311.pyc,,
+ordlookup/__pycache__/ws2_32.cpython-311.pyc,,
+ordlookup/oleaut32.py,sha256=g0bNcHLRuH_nW75xqZbtZZNWTrOVBbdEV8W7vxz0Ouc,10877
+ordlookup/ws2_32.py,sha256=gy-Vnrt6yVmzN8sbqLQESaNwFnZ2ojh4LsiAq5IDruA,3265
+pefile-2023.2.7.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+pefile-2023.2.7.dist-info/LICENSE,sha256=v9S15PipnJYf1vlNcI44OWzBRr_o-8XSqG5jqin7Qgg,1083
+pefile-2023.2.7.dist-info/METADATA,sha256=Nj9cLDBVi_AkWhZ26GqGr5QYbkgh4f6azj7_HX75EgQ,1352
+pefile-2023.2.7.dist-info/RECORD,,
+pefile-2023.2.7.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
+pefile-2023.2.7.dist-info/top_level.txt,sha256=e_EleSuZUOQKcXHJLs2sSeGkxG4OZghULcCc_v6kQbo,25
+pefile.py,sha256=-ZRoz-0ZMOjpA2pL9Py5sjrLKMTlQh4hXONSpczcgR8,292005
+peutils.py,sha256=KmQ2JO3osgXgugJRGM__CdwNVcM3X6xzhuHucI_5v0g,18361
diff --git a/venv/Lib/site-packages/pefile-2023.2.7.dist-info/WHEEL b/venv/Lib/site-packages/pefile-2023.2.7.dist-info/WHEEL
new file mode 100644
index 0000000..becc9a6
--- /dev/null
+++ b/venv/Lib/site-packages/pefile-2023.2.7.dist-info/WHEEL
@@ -0,0 +1,5 @@
+Wheel-Version: 1.0
+Generator: bdist_wheel (0.37.1)
+Root-Is-Purelib: true
+Tag: py3-none-any
+
diff --git a/venv/Lib/site-packages/pefile-2023.2.7.dist-info/top_level.txt b/venv/Lib/site-packages/pefile-2023.2.7.dist-info/top_level.txt
new file mode 100644
index 0000000..a9ab08d
--- /dev/null
+++ b/venv/Lib/site-packages/pefile-2023.2.7.dist-info/top_level.txt
@@ -0,0 +1,3 @@
+ordlookup
+pefile
+peutils
diff --git a/venv/Lib/site-packages/pefile.py b/venv/Lib/site-packages/pefile.py
new file mode 100644
index 0000000..f3052aa
--- /dev/null
+++ b/venv/Lib/site-packages/pefile.py
@@ -0,0 +1,7853 @@
+#!/usr/bin/python
+
+"""pefile, Portable Executable reader module
+
+All the PE file basic structures are available with their default names as
+attributes of the instance returned.
+
+Processed elements such as the import table are made available with lowercase
+names, to differentiate them from the upper case basic structure names.
+
+pefile has been tested against many edge cases such as corrupted and malformed
+PEs as well as malware, which often attempts to abuse the format way beyond its
+standard use. To the best of my knowledge most of the abuse is handled
+gracefully.
+
+Copyright (c) 2005-2023 Ero Carrera 
+"""
+
+__author__ = "Ero Carrera"
+__version__ = "2023.2.7"
+__contact__ = "ero.carrera@gmail.com"
+
+import collections
+import os
+import struct
+import codecs
+import time
+import math
+import string
+import mmap
+import uuid
+
+from collections import Counter
+from typing import Union
+from hashlib import sha1
+from hashlib import sha256
+from hashlib import sha512
+from hashlib import md5
+
+import functools
+import copy as copymod
+
+import ordlookup
+
+codecs.register_error("backslashreplace_", codecs.lookup_error("backslashreplace"))
+
+long = int
+# lru_cache with a shallow copy of the objects returned (list, dicts, ..)
+# we don't use deepcopy as it's _really_ slow and the data we retrieved using
+# this is enough with copy.copy taken from
+# https://stackoverflow.com/questions/54909357
+def lru_cache(maxsize=128, typed=False, copy=False):
+    if not copy:
+        return functools.lru_cache(maxsize, typed)
+
+    def decorator(f):
+        cached_func = functools.lru_cache(maxsize, typed)(f)
+
+        @functools.wraps(f)
+        def wrapper(*args, **kwargs):
+            # return copymod.deepcopy(cached_func(*args, **kwargs))
+            return copymod.copy(cached_func(*args, **kwargs))
+
+        return wrapper
+
+    return decorator
+
+
+@lru_cache(maxsize=2048)
+def cache_adjust_FileAlignment(val, file_alignment):
+    if file_alignment < FILE_ALIGNMENT_HARDCODED_VALUE:
+        return val
+    return (int(val / 0x200)) * 0x200
+
+
+@lru_cache(maxsize=2048)
+def cache_adjust_SectionAlignment(val, section_alignment, file_alignment):
+    if section_alignment < 0x1000:  # page size
+        section_alignment = file_alignment
+
+    # 0x200 is the minimum valid FileAlignment according to the documentation
+    # although ntoskrnl.exe has an alignment of 0x80 in some Windows versions
+    #
+    # elif section_alignment < 0x80:
+    #    section_alignment = 0x80
+
+    if section_alignment and val % section_alignment:
+        return section_alignment * (int(val / section_alignment))
+    return val
+
+
+def count_zeroes(data):
+    return data.count(0)
+
+
+fast_load = False
+
+# This will set a maximum length of a string to be retrieved from the file.
+# It's there to prevent loading massive amounts of data from memory mapped
+# files. Strings longer than 1MB should be rather rare.
+MAX_STRING_LENGTH = 0x100000  # 2^20
+
+# Maximum number of imports to parse.
+MAX_IMPORT_SYMBOLS = 0x2000
+
+# Limit maximum length for specific string types separately
+MAX_IMPORT_NAME_LENGTH = 0x200
+MAX_DLL_LENGTH = 0x200
+MAX_SYMBOL_NAME_LENGTH = 0x200
+
+# Limit maximum number of sections before processing of sections will stop
+MAX_SECTIONS = 0x800
+
+# The global maximum number of resource entries to parse per file
+MAX_RESOURCE_ENTRIES = 0x8000
+
+# The maximum depth of nested resource tables
+MAX_RESOURCE_DEPTH = 32
+
+# Limit number of exported symbols
+MAX_SYMBOL_EXPORT_COUNT = 0x2000
+
+IMAGE_DOS_SIGNATURE = 0x5A4D
+IMAGE_DOSZM_SIGNATURE = 0x4D5A
+IMAGE_NE_SIGNATURE = 0x454E
+IMAGE_LE_SIGNATURE = 0x454C
+IMAGE_LX_SIGNATURE = 0x584C
+IMAGE_TE_SIGNATURE = 0x5A56  # Terse Executables have a 'VZ' signature
+
+IMAGE_NT_SIGNATURE = 0x00004550
+IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16
+IMAGE_ORDINAL_FLAG = 0x80000000
+IMAGE_ORDINAL_FLAG64 = 0x8000000000000000
+OPTIONAL_HEADER_MAGIC_PE = 0x10B
+OPTIONAL_HEADER_MAGIC_PE_PLUS = 0x20B
+
+
+def two_way_dict(pairs):
+    return dict([(e[1], e[0]) for e in pairs] + pairs)
+
+
+directory_entry_types = [
+    ("IMAGE_DIRECTORY_ENTRY_EXPORT", 0),
+    ("IMAGE_DIRECTORY_ENTRY_IMPORT", 1),
+    ("IMAGE_DIRECTORY_ENTRY_RESOURCE", 2),
+    ("IMAGE_DIRECTORY_ENTRY_EXCEPTION", 3),
+    ("IMAGE_DIRECTORY_ENTRY_SECURITY", 4),
+    ("IMAGE_DIRECTORY_ENTRY_BASERELOC", 5),
+    ("IMAGE_DIRECTORY_ENTRY_DEBUG", 6),
+    # Architecture on non-x86 platforms
+    ("IMAGE_DIRECTORY_ENTRY_COPYRIGHT", 7),
+    ("IMAGE_DIRECTORY_ENTRY_GLOBALPTR", 8),
+    ("IMAGE_DIRECTORY_ENTRY_TLS", 9),
+    ("IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG", 10),
+    ("IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT", 11),
+    ("IMAGE_DIRECTORY_ENTRY_IAT", 12),
+    ("IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT", 13),
+    ("IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR", 14),
+    ("IMAGE_DIRECTORY_ENTRY_RESERVED", 15),
+]
+
+DIRECTORY_ENTRY = two_way_dict(directory_entry_types)
+
+image_characteristics = [
+    ("IMAGE_FILE_RELOCS_STRIPPED", 0x0001),
+    ("IMAGE_FILE_EXECUTABLE_IMAGE", 0x0002),
+    ("IMAGE_FILE_LINE_NUMS_STRIPPED", 0x0004),
+    ("IMAGE_FILE_LOCAL_SYMS_STRIPPED", 0x0008),
+    ("IMAGE_FILE_AGGRESIVE_WS_TRIM", 0x0010),
+    ("IMAGE_FILE_LARGE_ADDRESS_AWARE", 0x0020),
+    ("IMAGE_FILE_16BIT_MACHINE", 0x0040),
+    ("IMAGE_FILE_BYTES_REVERSED_LO", 0x0080),
+    ("IMAGE_FILE_32BIT_MACHINE", 0x0100),
+    ("IMAGE_FILE_DEBUG_STRIPPED", 0x0200),
+    ("IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP", 0x0400),
+    ("IMAGE_FILE_NET_RUN_FROM_SWAP", 0x0800),
+    ("IMAGE_FILE_SYSTEM", 0x1000),
+    ("IMAGE_FILE_DLL", 0x2000),
+    ("IMAGE_FILE_UP_SYSTEM_ONLY", 0x4000),
+    ("IMAGE_FILE_BYTES_REVERSED_HI", 0x8000),
+]
+
+IMAGE_CHARACTERISTICS = two_way_dict(image_characteristics)
+
+
+section_characteristics = [
+    ("IMAGE_SCN_TYPE_REG", 0x00000000),  # reserved
+    ("IMAGE_SCN_TYPE_DSECT", 0x00000001),  # reserved
+    ("IMAGE_SCN_TYPE_NOLOAD", 0x00000002),  # reserved
+    ("IMAGE_SCN_TYPE_GROUP", 0x00000004),  # reserved
+    ("IMAGE_SCN_TYPE_NO_PAD", 0x00000008),  # reserved
+    ("IMAGE_SCN_TYPE_COPY", 0x00000010),  # reserved
+    ("IMAGE_SCN_CNT_CODE", 0x00000020),
+    ("IMAGE_SCN_CNT_INITIALIZED_DATA", 0x00000040),
+    ("IMAGE_SCN_CNT_UNINITIALIZED_DATA", 0x00000080),
+    ("IMAGE_SCN_LNK_OTHER", 0x00000100),
+    ("IMAGE_SCN_LNK_INFO", 0x00000200),
+    ("IMAGE_SCN_LNK_OVER", 0x00000400),  # reserved
+    ("IMAGE_SCN_LNK_REMOVE", 0x00000800),
+    ("IMAGE_SCN_LNK_COMDAT", 0x00001000),
+    ("IMAGE_SCN_MEM_PROTECTED", 0x00004000),  # obsolete
+    ("IMAGE_SCN_NO_DEFER_SPEC_EXC", 0x00004000),
+    ("IMAGE_SCN_GPREL", 0x00008000),
+    ("IMAGE_SCN_MEM_FARDATA", 0x00008000),
+    ("IMAGE_SCN_MEM_SYSHEAP", 0x00010000),  # obsolete
+    ("IMAGE_SCN_MEM_PURGEABLE", 0x00020000),
+    ("IMAGE_SCN_MEM_16BIT", 0x00020000),
+    ("IMAGE_SCN_MEM_LOCKED", 0x00040000),
+    ("IMAGE_SCN_MEM_PRELOAD", 0x00080000),
+    ("IMAGE_SCN_ALIGN_1BYTES", 0x00100000),
+    ("IMAGE_SCN_ALIGN_2BYTES", 0x00200000),
+    ("IMAGE_SCN_ALIGN_4BYTES", 0x00300000),
+    ("IMAGE_SCN_ALIGN_8BYTES", 0x00400000),
+    ("IMAGE_SCN_ALIGN_16BYTES", 0x00500000),  # default alignment
+    ("IMAGE_SCN_ALIGN_32BYTES", 0x00600000),
+    ("IMAGE_SCN_ALIGN_64BYTES", 0x00700000),
+    ("IMAGE_SCN_ALIGN_128BYTES", 0x00800000),
+    ("IMAGE_SCN_ALIGN_256BYTES", 0x00900000),
+    ("IMAGE_SCN_ALIGN_512BYTES", 0x00A00000),
+    ("IMAGE_SCN_ALIGN_1024BYTES", 0x00B00000),
+    ("IMAGE_SCN_ALIGN_2048BYTES", 0x00C00000),
+    ("IMAGE_SCN_ALIGN_4096BYTES", 0x00D00000),
+    ("IMAGE_SCN_ALIGN_8192BYTES", 0x00E00000),
+    ("IMAGE_SCN_ALIGN_MASK", 0x00F00000),
+    ("IMAGE_SCN_LNK_NRELOC_OVFL", 0x01000000),
+    ("IMAGE_SCN_MEM_DISCARDABLE", 0x02000000),
+    ("IMAGE_SCN_MEM_NOT_CACHED", 0x04000000),
+    ("IMAGE_SCN_MEM_NOT_PAGED", 0x08000000),
+    ("IMAGE_SCN_MEM_SHARED", 0x10000000),
+    ("IMAGE_SCN_MEM_EXECUTE", 0x20000000),
+    ("IMAGE_SCN_MEM_READ", 0x40000000),
+    ("IMAGE_SCN_MEM_WRITE", 0x80000000),
+]
+
+SECTION_CHARACTERISTICS = two_way_dict(section_characteristics)
+
+
+debug_types = [
+    ("IMAGE_DEBUG_TYPE_UNKNOWN", 0),
+    ("IMAGE_DEBUG_TYPE_COFF", 1),
+    ("IMAGE_DEBUG_TYPE_CODEVIEW", 2),
+    ("IMAGE_DEBUG_TYPE_FPO", 3),
+    ("IMAGE_DEBUG_TYPE_MISC", 4),
+    ("IMAGE_DEBUG_TYPE_EXCEPTION", 5),
+    ("IMAGE_DEBUG_TYPE_FIXUP", 6),
+    ("IMAGE_DEBUG_TYPE_OMAP_TO_SRC", 7),
+    ("IMAGE_DEBUG_TYPE_OMAP_FROM_SRC", 8),
+    ("IMAGE_DEBUG_TYPE_BORLAND", 9),
+    ("IMAGE_DEBUG_TYPE_RESERVED10", 10),
+    ("IMAGE_DEBUG_TYPE_CLSID", 11),
+    ("IMAGE_DEBUG_TYPE_VC_FEATURE", 12),
+    ("IMAGE_DEBUG_TYPE_POGO", 13),
+    ("IMAGE_DEBUG_TYPE_ILTCG", 14),
+    ("IMAGE_DEBUG_TYPE_MPX", 15),
+    ("IMAGE_DEBUG_TYPE_REPRO", 16),
+    ("IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS", 20),
+]
+
+DEBUG_TYPE = two_way_dict(debug_types)
+
+
+subsystem_types = [
+    ("IMAGE_SUBSYSTEM_UNKNOWN", 0),
+    ("IMAGE_SUBSYSTEM_NATIVE", 1),
+    ("IMAGE_SUBSYSTEM_WINDOWS_GUI", 2),
+    ("IMAGE_SUBSYSTEM_WINDOWS_CUI", 3),
+    ("IMAGE_SUBSYSTEM_OS2_CUI", 5),
+    ("IMAGE_SUBSYSTEM_POSIX_CUI", 7),
+    ("IMAGE_SUBSYSTEM_NATIVE_WINDOWS", 8),
+    ("IMAGE_SUBSYSTEM_WINDOWS_CE_GUI", 9),
+    ("IMAGE_SUBSYSTEM_EFI_APPLICATION", 10),
+    ("IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER", 11),
+    ("IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER", 12),
+    ("IMAGE_SUBSYSTEM_EFI_ROM", 13),
+    ("IMAGE_SUBSYSTEM_XBOX", 14),
+    ("IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION", 16),
+]
+
+SUBSYSTEM_TYPE = two_way_dict(subsystem_types)
+
+
+machine_types = [
+    ("IMAGE_FILE_MACHINE_UNKNOWN", 0x0),
+    ("IMAGE_FILE_MACHINE_I386", 0x014C),
+    ("IMAGE_FILE_MACHINE_R3000", 0x0162),
+    ("IMAGE_FILE_MACHINE_R4000", 0x0166),
+    ("IMAGE_FILE_MACHINE_R10000", 0x0168),
+    ("IMAGE_FILE_MACHINE_WCEMIPSV2", 0x0169),
+    ("IMAGE_FILE_MACHINE_ALPHA", 0x0184),
+    ("IMAGE_FILE_MACHINE_SH3", 0x01A2),
+    ("IMAGE_FILE_MACHINE_SH3DSP", 0x01A3),
+    ("IMAGE_FILE_MACHINE_SH3E", 0x01A4),
+    ("IMAGE_FILE_MACHINE_SH4", 0x01A6),
+    ("IMAGE_FILE_MACHINE_SH5", 0x01A8),
+    ("IMAGE_FILE_MACHINE_ARM", 0x01C0),
+    ("IMAGE_FILE_MACHINE_THUMB", 0x01C2),
+    ("IMAGE_FILE_MACHINE_ARMNT", 0x01C4),
+    ("IMAGE_FILE_MACHINE_AM33", 0x01D3),
+    ("IMAGE_FILE_MACHINE_POWERPC", 0x01F0),
+    ("IMAGE_FILE_MACHINE_POWERPCFP", 0x01F1),
+    ("IMAGE_FILE_MACHINE_IA64", 0x0200),
+    ("IMAGE_FILE_MACHINE_MIPS16", 0x0266),
+    ("IMAGE_FILE_MACHINE_ALPHA64", 0x0284),
+    ("IMAGE_FILE_MACHINE_AXP64", 0x0284),  # same
+    ("IMAGE_FILE_MACHINE_MIPSFPU", 0x0366),
+    ("IMAGE_FILE_MACHINE_MIPSFPU16", 0x0466),
+    ("IMAGE_FILE_MACHINE_TRICORE", 0x0520),
+    ("IMAGE_FILE_MACHINE_CEF", 0x0CEF),
+    ("IMAGE_FILE_MACHINE_EBC", 0x0EBC),
+    ("IMAGE_FILE_MACHINE_RISCV32", 0x5032),
+    ("IMAGE_FILE_MACHINE_RISCV64", 0x5064),
+    ("IMAGE_FILE_MACHINE_RISCV128", 0x5128),
+    ("IMAGE_FILE_MACHINE_LOONGARCH32", 0x6232),
+    ("IMAGE_FILE_MACHINE_LOONGARCH64", 0x6264),
+    ("IMAGE_FILE_MACHINE_AMD64", 0x8664),
+    ("IMAGE_FILE_MACHINE_M32R", 0x9041),
+    ("IMAGE_FILE_MACHINE_ARM64", 0xAA64),
+    ("IMAGE_FILE_MACHINE_CEE", 0xC0EE),
+]
+
+MACHINE_TYPE = two_way_dict(machine_types)
+
+
+relocation_types = [
+    ("IMAGE_REL_BASED_ABSOLUTE", 0),
+    ("IMAGE_REL_BASED_HIGH", 1),
+    ("IMAGE_REL_BASED_LOW", 2),
+    ("IMAGE_REL_BASED_HIGHLOW", 3),
+    ("IMAGE_REL_BASED_HIGHADJ", 4),
+    ("IMAGE_REL_BASED_MIPS_JMPADDR", 5),
+    ("IMAGE_REL_BASED_SECTION", 6),
+    ("IMAGE_REL_BASED_REL", 7),
+    ("IMAGE_REL_BASED_MIPS_JMPADDR16", 9),
+    ("IMAGE_REL_BASED_IA64_IMM64", 9),
+    ("IMAGE_REL_BASED_DIR64", 10),
+    ("IMAGE_REL_BASED_HIGH3ADJ", 11),
+]
+
+RELOCATION_TYPE = two_way_dict(relocation_types)
+
+
+dll_characteristics = [
+    ("IMAGE_LIBRARY_PROCESS_INIT", 0x0001),  # reserved
+    ("IMAGE_LIBRARY_PROCESS_TERM", 0x0002),  # reserved
+    ("IMAGE_LIBRARY_THREAD_INIT", 0x0004),  # reserved
+    ("IMAGE_LIBRARY_THREAD_TERM", 0x0008),  # reserved
+    ("IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA", 0x0020),
+    ("IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE", 0x0040),
+    ("IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY", 0x0080),
+    ("IMAGE_DLLCHARACTERISTICS_NX_COMPAT", 0x0100),
+    ("IMAGE_DLLCHARACTERISTICS_NO_ISOLATION", 0x0200),
+    ("IMAGE_DLLCHARACTERISTICS_NO_SEH", 0x0400),
+    ("IMAGE_DLLCHARACTERISTICS_NO_BIND", 0x0800),
+    ("IMAGE_DLLCHARACTERISTICS_APPCONTAINER", 0x1000),
+    ("IMAGE_DLLCHARACTERISTICS_WDM_DRIVER", 0x2000),
+    ("IMAGE_DLLCHARACTERISTICS_GUARD_CF", 0x4000),
+    ("IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE", 0x8000),
+]
+
+DLL_CHARACTERISTICS = two_way_dict(dll_characteristics)
+
+FILE_ALIGNMENT_HARDCODED_VALUE = 0x200
+
+
+# Unwind info-related enums
+
+unwind_info_flags = [
+    ("UNW_FLAG_EHANDLER", 0x01),
+    ("UNW_FLAG_UHANDLER", 0x02),
+    ("UNW_FLAG_CHAININFO", 0x04),
+]
+
+UNWIND_INFO_FLAGS = two_way_dict(unwind_info_flags)
+
+registers = [
+    ("RAX", 0),
+    ("RCX", 1),
+    ("RDX", 2),
+    ("RBX", 3),
+    ("RSP", 4),
+    ("RBP", 5),
+    ("RSI", 6),
+    ("RDI", 7),
+    ("R8", 8),
+    ("R9", 9),
+    ("R10", 10),
+    ("R11", 11),
+    ("R12", 12),
+    ("R13", 13),
+    ("R14", 14),
+    ("R15", 15),
+]
+
+REGISTERS = two_way_dict(registers)
+
+# enum _UNWIND_OP_CODES
+UWOP_PUSH_NONVOL = 0
+UWOP_ALLOC_LARGE = 1
+UWOP_ALLOC_SMALL = 2
+UWOP_SET_FPREG = 3
+UWOP_SAVE_NONVOL = 4
+UWOP_SAVE_NONVOL_FAR = 5
+UWOP_EPILOG = 6
+UWOP_SAVE_XMM128 = 8
+UWOP_SAVE_XMM128_FAR = 9
+UWOP_PUSH_MACHFRAME = 10
+
+
+# Resource types
+resource_type = [
+    ("RT_CURSOR", 1),
+    ("RT_BITMAP", 2),
+    ("RT_ICON", 3),
+    ("RT_MENU", 4),
+    ("RT_DIALOG", 5),
+    ("RT_STRING", 6),
+    ("RT_FONTDIR", 7),
+    ("RT_FONT", 8),
+    ("RT_ACCELERATOR", 9),
+    ("RT_RCDATA", 10),
+    ("RT_MESSAGETABLE", 11),
+    ("RT_GROUP_CURSOR", 12),
+    ("RT_GROUP_ICON", 14),
+    ("RT_VERSION", 16),
+    ("RT_DLGINCLUDE", 17),
+    ("RT_PLUGPLAY", 19),
+    ("RT_VXD", 20),
+    ("RT_ANICURSOR", 21),
+    ("RT_ANIICON", 22),
+    ("RT_HTML", 23),
+    ("RT_MANIFEST", 24),
+]
+
+RESOURCE_TYPE = two_way_dict(resource_type)
+
+
+# Language definitions
+lang = [
+    ("LANG_NEUTRAL", 0x00),
+    ("LANG_INVARIANT", 0x7F),
+    ("LANG_AFRIKAANS", 0x36),
+    ("LANG_ALBANIAN", 0x1C),
+    ("LANG_ARABIC", 0x01),
+    ("LANG_ARMENIAN", 0x2B),
+    ("LANG_ASSAMESE", 0x4D),
+    ("LANG_AZERI", 0x2C),
+    ("LANG_BASQUE", 0x2D),
+    ("LANG_BELARUSIAN", 0x23),
+    ("LANG_BENGALI", 0x45),
+    ("LANG_BULGARIAN", 0x02),
+    ("LANG_CATALAN", 0x03),
+    ("LANG_CHINESE", 0x04),
+    ("LANG_CROATIAN", 0x1A),
+    ("LANG_CZECH", 0x05),
+    ("LANG_DANISH", 0x06),
+    ("LANG_DIVEHI", 0x65),
+    ("LANG_DUTCH", 0x13),
+    ("LANG_ENGLISH", 0x09),
+    ("LANG_ESTONIAN", 0x25),
+    ("LANG_FAEROESE", 0x38),
+    ("LANG_FARSI", 0x29),
+    ("LANG_FINNISH", 0x0B),
+    ("LANG_FRENCH", 0x0C),
+    ("LANG_GALICIAN", 0x56),
+    ("LANG_GEORGIAN", 0x37),
+    ("LANG_GERMAN", 0x07),
+    ("LANG_GREEK", 0x08),
+    ("LANG_GUJARATI", 0x47),
+    ("LANG_HEBREW", 0x0D),
+    ("LANG_HINDI", 0x39),
+    ("LANG_HUNGARIAN", 0x0E),
+    ("LANG_ICELANDIC", 0x0F),
+    ("LANG_INDONESIAN", 0x21),
+    ("LANG_ITALIAN", 0x10),
+    ("LANG_JAPANESE", 0x11),
+    ("LANG_KANNADA", 0x4B),
+    ("LANG_KASHMIRI", 0x60),
+    ("LANG_KAZAK", 0x3F),
+    ("LANG_KONKANI", 0x57),
+    ("LANG_KOREAN", 0x12),
+    ("LANG_KYRGYZ", 0x40),
+    ("LANG_LATVIAN", 0x26),
+    ("LANG_LITHUANIAN", 0x27),
+    ("LANG_MACEDONIAN", 0x2F),
+    ("LANG_MALAY", 0x3E),
+    ("LANG_MALAYALAM", 0x4C),
+    ("LANG_MANIPURI", 0x58),
+    ("LANG_MARATHI", 0x4E),
+    ("LANG_MONGOLIAN", 0x50),
+    ("LANG_NEPALI", 0x61),
+    ("LANG_NORWEGIAN", 0x14),
+    ("LANG_ORIYA", 0x48),
+    ("LANG_POLISH", 0x15),
+    ("LANG_PORTUGUESE", 0x16),
+    ("LANG_PUNJABI", 0x46),
+    ("LANG_ROMANIAN", 0x18),
+    ("LANG_RUSSIAN", 0x19),
+    ("LANG_SANSKRIT", 0x4F),
+    ("LANG_SERBIAN", 0x1A),
+    ("LANG_SINDHI", 0x59),
+    ("LANG_SLOVAK", 0x1B),
+    ("LANG_SLOVENIAN", 0x24),
+    ("LANG_SPANISH", 0x0A),
+    ("LANG_SWAHILI", 0x41),
+    ("LANG_SWEDISH", 0x1D),
+    ("LANG_SYRIAC", 0x5A),
+    ("LANG_TAMIL", 0x49),
+    ("LANG_TATAR", 0x44),
+    ("LANG_TELUGU", 0x4A),
+    ("LANG_THAI", 0x1E),
+    ("LANG_TURKISH", 0x1F),
+    ("LANG_UKRAINIAN", 0x22),
+    ("LANG_URDU", 0x20),
+    ("LANG_UZBEK", 0x43),
+    ("LANG_VIETNAMESE", 0x2A),
+    ("LANG_GAELIC", 0x3C),
+    ("LANG_MALTESE", 0x3A),
+    ("LANG_MAORI", 0x28),
+    ("LANG_RHAETO_ROMANCE", 0x17),
+    ("LANG_SAAMI", 0x3B),
+    ("LANG_SORBIAN", 0x2E),
+    ("LANG_SUTU", 0x30),
+    ("LANG_TSONGA", 0x31),
+    ("LANG_TSWANA", 0x32),
+    ("LANG_VENDA", 0x33),
+    ("LANG_XHOSA", 0x34),
+    ("LANG_ZULU", 0x35),
+    ("LANG_ESPERANTO", 0x8F),
+    ("LANG_WALON", 0x90),
+    ("LANG_CORNISH", 0x91),
+    ("LANG_WELSH", 0x92),
+    ("LANG_BRETON", 0x93),
+]
+
+LANG = two_way_dict(lang)
+
+
+# Sublanguage definitions
+sublang = [
+    ("SUBLANG_NEUTRAL", 0x00),
+    ("SUBLANG_DEFAULT", 0x01),
+    ("SUBLANG_SYS_DEFAULT", 0x02),
+    ("SUBLANG_ARABIC_SAUDI_ARABIA", 0x01),
+    ("SUBLANG_ARABIC_IRAQ", 0x02),
+    ("SUBLANG_ARABIC_EGYPT", 0x03),
+    ("SUBLANG_ARABIC_LIBYA", 0x04),
+    ("SUBLANG_ARABIC_ALGERIA", 0x05),
+    ("SUBLANG_ARABIC_MOROCCO", 0x06),
+    ("SUBLANG_ARABIC_TUNISIA", 0x07),
+    ("SUBLANG_ARABIC_OMAN", 0x08),
+    ("SUBLANG_ARABIC_YEMEN", 0x09),
+    ("SUBLANG_ARABIC_SYRIA", 0x0A),
+    ("SUBLANG_ARABIC_JORDAN", 0x0B),
+    ("SUBLANG_ARABIC_LEBANON", 0x0C),
+    ("SUBLANG_ARABIC_KUWAIT", 0x0D),
+    ("SUBLANG_ARABIC_UAE", 0x0E),
+    ("SUBLANG_ARABIC_BAHRAIN", 0x0F),
+    ("SUBLANG_ARABIC_QATAR", 0x10),
+    ("SUBLANG_AZERI_LATIN", 0x01),
+    ("SUBLANG_AZERI_CYRILLIC", 0x02),
+    ("SUBLANG_CHINESE_TRADITIONAL", 0x01),
+    ("SUBLANG_CHINESE_SIMPLIFIED", 0x02),
+    ("SUBLANG_CHINESE_HONGKONG", 0x03),
+    ("SUBLANG_CHINESE_SINGAPORE", 0x04),
+    ("SUBLANG_CHINESE_MACAU", 0x05),
+    ("SUBLANG_DUTCH", 0x01),
+    ("SUBLANG_DUTCH_BELGIAN", 0x02),
+    ("SUBLANG_ENGLISH_US", 0x01),
+    ("SUBLANG_ENGLISH_UK", 0x02),
+    ("SUBLANG_ENGLISH_AUS", 0x03),
+    ("SUBLANG_ENGLISH_CAN", 0x04),
+    ("SUBLANG_ENGLISH_NZ", 0x05),
+    ("SUBLANG_ENGLISH_EIRE", 0x06),
+    ("SUBLANG_ENGLISH_SOUTH_AFRICA", 0x07),
+    ("SUBLANG_ENGLISH_JAMAICA", 0x08),
+    ("SUBLANG_ENGLISH_CARIBBEAN", 0x09),
+    ("SUBLANG_ENGLISH_BELIZE", 0x0A),
+    ("SUBLANG_ENGLISH_TRINIDAD", 0x0B),
+    ("SUBLANG_ENGLISH_ZIMBABWE", 0x0C),
+    ("SUBLANG_ENGLISH_PHILIPPINES", 0x0D),
+    ("SUBLANG_FRENCH", 0x01),
+    ("SUBLANG_FRENCH_BELGIAN", 0x02),
+    ("SUBLANG_FRENCH_CANADIAN", 0x03),
+    ("SUBLANG_FRENCH_SWISS", 0x04),
+    ("SUBLANG_FRENCH_LUXEMBOURG", 0x05),
+    ("SUBLANG_FRENCH_MONACO", 0x06),
+    ("SUBLANG_GERMAN", 0x01),
+    ("SUBLANG_GERMAN_SWISS", 0x02),
+    ("SUBLANG_GERMAN_AUSTRIAN", 0x03),
+    ("SUBLANG_GERMAN_LUXEMBOURG", 0x04),
+    ("SUBLANG_GERMAN_LIECHTENSTEIN", 0x05),
+    ("SUBLANG_ITALIAN", 0x01),
+    ("SUBLANG_ITALIAN_SWISS", 0x02),
+    ("SUBLANG_KASHMIRI_SASIA", 0x02),
+    ("SUBLANG_KASHMIRI_INDIA", 0x02),
+    ("SUBLANG_KOREAN", 0x01),
+    ("SUBLANG_LITHUANIAN", 0x01),
+    ("SUBLANG_MALAY_MALAYSIA", 0x01),
+    ("SUBLANG_MALAY_BRUNEI_DARUSSALAM", 0x02),
+    ("SUBLANG_NEPALI_INDIA", 0x02),
+    ("SUBLANG_NORWEGIAN_BOKMAL", 0x01),
+    ("SUBLANG_NORWEGIAN_NYNORSK", 0x02),
+    ("SUBLANG_PORTUGUESE", 0x02),
+    ("SUBLANG_PORTUGUESE_BRAZILIAN", 0x01),
+    ("SUBLANG_SERBIAN_LATIN", 0x02),
+    ("SUBLANG_SERBIAN_CYRILLIC", 0x03),
+    ("SUBLANG_SPANISH", 0x01),
+    ("SUBLANG_SPANISH_MEXICAN", 0x02),
+    ("SUBLANG_SPANISH_MODERN", 0x03),
+    ("SUBLANG_SPANISH_GUATEMALA", 0x04),
+    ("SUBLANG_SPANISH_COSTA_RICA", 0x05),
+    ("SUBLANG_SPANISH_PANAMA", 0x06),
+    ("SUBLANG_SPANISH_DOMINICAN_REPUBLIC", 0x07),
+    ("SUBLANG_SPANISH_VENEZUELA", 0x08),
+    ("SUBLANG_SPANISH_COLOMBIA", 0x09),
+    ("SUBLANG_SPANISH_PERU", 0x0A),
+    ("SUBLANG_SPANISH_ARGENTINA", 0x0B),
+    ("SUBLANG_SPANISH_ECUADOR", 0x0C),
+    ("SUBLANG_SPANISH_CHILE", 0x0D),
+    ("SUBLANG_SPANISH_URUGUAY", 0x0E),
+    ("SUBLANG_SPANISH_PARAGUAY", 0x0F),
+    ("SUBLANG_SPANISH_BOLIVIA", 0x10),
+    ("SUBLANG_SPANISH_EL_SALVADOR", 0x11),
+    ("SUBLANG_SPANISH_HONDURAS", 0x12),
+    ("SUBLANG_SPANISH_NICARAGUA", 0x13),
+    ("SUBLANG_SPANISH_PUERTO_RICO", 0x14),
+    ("SUBLANG_SWEDISH", 0x01),
+    ("SUBLANG_SWEDISH_FINLAND", 0x02),
+    ("SUBLANG_URDU_PAKISTAN", 0x01),
+    ("SUBLANG_URDU_INDIA", 0x02),
+    ("SUBLANG_UZBEK_LATIN", 0x01),
+    ("SUBLANG_UZBEK_CYRILLIC", 0x02),
+    ("SUBLANG_DUTCH_SURINAM", 0x03),
+    ("SUBLANG_ROMANIAN", 0x01),
+    ("SUBLANG_ROMANIAN_MOLDAVIA", 0x02),
+    ("SUBLANG_RUSSIAN", 0x01),
+    ("SUBLANG_RUSSIAN_MOLDAVIA", 0x02),
+    ("SUBLANG_CROATIAN", 0x01),
+    ("SUBLANG_LITHUANIAN_CLASSIC", 0x02),
+    ("SUBLANG_GAELIC", 0x01),
+    ("SUBLANG_GAELIC_SCOTTISH", 0x02),
+    ("SUBLANG_GAELIC_MANX", 0x03),
+]
+
+SUBLANG = two_way_dict(sublang)
+
+# Initialize the dictionary with all the name->value pairs
+SUBLANG = dict(sublang)
+# Now add all the value->name information, handling duplicates appropriately
+for sublang_name, sublang_value in sublang:
+    if sublang_value in SUBLANG:
+        SUBLANG[sublang_value].append(sublang_name)
+    else:
+        SUBLANG[sublang_value] = [sublang_name]
+
+# Resolve a sublang name given the main lang name
+#
+def get_sublang_name_for_lang(lang_value, sublang_value):
+    lang_name = LANG.get(lang_value, "*unknown*")
+    for sublang_name in SUBLANG.get(sublang_value, []):
+        # if the main language is a substring of sublang's name, then
+        # return that
+        if lang_name in sublang_name:
+            return sublang_name
+    # otherwise return the first sublang name
+    return SUBLANG.get(sublang_value, ["*unknown*"])[0]
+
+
+# Ange Albertini's code to process resources' strings
+#
+def parse_strings(data, counter, l):
+    i = 0
+    error_count = 0
+    while i < len(data):
+
+        data_slice = data[i : i + 2]
+        if len(data_slice) < 2:
+            break
+
+        len_ = struct.unpack("= 3:
+                break
+            i += len_ * 2
+        counter += 1
+
+
+def retrieve_flags(flag_dict, flag_filter):
+    """Read the flags from a dictionary and return them in a usable form.
+
+    Will return a list of (flag, value) for all flags in "flag_dict"
+    matching the filter "flag_filter".
+    """
+
+    return [
+        (flag, flag_dict[flag])
+        for flag in flag_dict.keys()
+        if isinstance(flag, (str, bytes)) and flag.startswith(flag_filter)
+    ]
+
+
+def set_flags(obj, flag_field, flags):
+    """Will process the flags and set attributes in the object accordingly.
+
+    The object "obj" will gain attributes named after the flags provided in
+    "flags" and valued True/False, matching the results of applying each
+    flag value from "flags" to flag_field.
+    """
+
+    for flag, value in flags:
+        if value & flag_field:
+            obj.__dict__[flag] = True
+        else:
+            obj.__dict__[flag] = False
+
+
+def power_of_two(val):
+    return val != 0 and (val & (val - 1)) == 0
+
+
+def b(x):
+    if isinstance(x, bytes):
+        return x
+    elif isinstance(x, bytearray):
+        return bytes(x)
+    else:
+        return codecs.encode(x, "cp1252")
+
+
+class AddressSet(set):
+    def __init__(self):
+        super().__init__()
+        self.min = None
+        self.max = None
+
+    def add(self, value):
+        super().add(value)
+        self.min = value if self.min is None else min(self.min, value)
+        self.max = value if self.max is None else max(self.max, value)
+
+    def diff(self):
+        return 0 if self.min is None or self.max is None else self.max - self.min
+
+
+class UnicodeStringWrapperPostProcessor:
+    """This class attempts to help the process of identifying strings
+    that might be plain Unicode or Pascal. A list of strings will be
+    wrapped on it with the hope the overlappings will help make the
+    decision about their type."""
+
+    def __init__(self, pe, rva_ptr):
+        self.pe = pe
+        self.rva_ptr = rva_ptr
+        self.string = None
+
+    def get_rva(self):
+        """Get the RVA of the string."""
+        return self.rva_ptr
+
+    def __str__(self):
+        """Return the escaped UTF-8 representation of the string."""
+        return self.decode("utf-8", "backslashreplace_")
+
+    def decode(self, *args):
+        if not self.string:
+            return ""
+        return self.string.decode(*args)
+
+    def invalidate(self):
+        """Make this instance None, to express it's no known string type."""
+        self = None
+
+    def render_pascal_16(self):
+        try:
+            self.string = self.pe.get_string_u_at_rva(
+                self.rva_ptr + 2, max_length=self.get_pascal_16_length()
+            )
+        except PEFormatError:
+            self.pe.get_warnings().append(
+                "Failed rendering pascal string, "
+                "attempting to read from RVA 0x{0:x}".format(self.rva_ptr + 2)
+            )
+
+    def get_pascal_16_length(self):
+        return self.__get_word_value_at_rva(self.rva_ptr)
+
+    def __get_word_value_at_rva(self, rva):
+        try:
+            data = self.pe.get_data(rva, 2)
+        except PEFormatError:
+            return False
+
+        if len(data) < 2:
+            return False
+
+        return struct.unpack(" str:
+        return self.__format_str__
+
+    def get_field_absolute_offset(self, field_name):
+        """Return the offset within the field for the requested field in the structure."""
+        return self.__file_offset__ + self.__field_offsets__[field_name]
+
+    def get_field_relative_offset(self, field_name):
+        """Return the offset within the structure for the requested field."""
+        return self.__field_offsets__[field_name]
+
+    def get_file_offset(self):
+        return self.__file_offset__
+
+    def set_file_offset(self, offset):
+        self.__file_offset__ = offset
+
+    def all_zeroes(self):
+        """Returns true is the unpacked data is all zeros."""
+
+        return self.__all_zeroes__
+
+    def sizeof(self):
+        """Return size of the structure."""
+
+        return self.__format_length__
+
+    def __unpack__(self, data):
+
+        data = b(data)
+
+        if len(data) > self.__format_length__:
+            data = data[: self.__format_length__]
+
+        # OC Patch:
+        # Some malware have incorrect header lengths.
+        # Fail gracefully if this occurs
+        # Buggy malware: a29b0118af8b7408444df81701ad5a7f
+        #
+        elif len(data) < self.__format_length__:
+            raise PEFormatError("Data length less than expected header length.")
+
+        if count_zeroes(data) == len(data):
+            self.__all_zeroes__ = True
+
+        self.__unpacked_data_elms__ = struct.unpack(self.__format_str__, data)
+        for idx, val in enumerate(self.__unpacked_data_elms__):
+            for key in self.__keys__[idx]:
+                setattr(self, key, val)
+
+    def __pack__(self):
+
+        new_values = []
+
+        for idx, val in enumerate(self.__unpacked_data_elms__):
+            new_val = None
+            for key in self.__keys__[idx]:
+                new_val = getattr(self, key)
+                # In the case of unions, when the first changed value
+                # is picked the loop is exited
+                if new_val != val:
+                    break
+            new_values.append(new_val)
+
+        return struct.pack(self.__format_str__, *new_values)
+
+    def __str__(self):
+        return "\n".join(self.dump())
+
+    def __repr__(self):
+        return "" % (
+            " ".join([" ".join(s.split()) for s in self.dump()])
+        )
+
+    def dump(self, indentation=0):
+        """Returns a string representation of the structure."""
+
+        dump = []
+
+        dump.append("[{0}]".format(self.name))
+
+        printable_bytes = [
+            ord(i) for i in string.printable if i not in string.whitespace
+        ]
+
+        # Refer to the __set_format__ method for an explanation
+        # of the following construct.
+        for keys in self.__keys__:
+            for key in keys:
+
+                val = getattr(self, key)
+                if isinstance(val, (int, long)):
+                    if key.startswith("Signature_"):
+                        val_str = "{:<8X}".format(val)
+                    else:
+                        val_str = "0x{:<8X}".format(val)
+                    if key == "TimeDateStamp" or key == "dwTimeStamp":
+                        try:
+                            val_str += " [%s UTC]" % time.asctime(time.gmtime(val))
+                        except ValueError:
+                            val_str += " [INVALID TIME]"
+                else:
+                    val_str = bytearray(val)
+                    if key.startswith("Signature"):
+                        val_str = "".join(
+                            ["{:02X}".format(i) for i in val_str.rstrip(b"\x00")]
+                        )
+                    else:
+                        val_str = "".join(
+                            [
+                                chr(i)
+                                if (i in printable_bytes)
+                                else "\\x{0:02x}".format(i)
+                                for i in val_str.rstrip(b"\x00")
+                            ]
+                        )
+
+                dump.append(
+                    "0x%-8X 0x%-3X %-30s %s"
+                    % (
+                        self.__field_offsets__[key] + self.__file_offset__,
+                        self.__field_offsets__[key],
+                        key + ":",
+                        val_str,
+                    )
+                )
+
+        return dump
+
+    def dump_dict(self):
+        """Returns a dictionary representation of the structure."""
+
+        dump_dict = {}
+
+        dump_dict["Structure"] = self.name
+
+        # Refer to the __set_format__ method for an explanation
+        # of the following construct.
+        for keys in self.__keys__:
+            for key in keys:
+
+                val = getattr(self, key)
+                if isinstance(val, (int, long)):
+                    if key == "TimeDateStamp" or key == "dwTimeStamp":
+                        try:
+                            val = "0x%-8X [%s UTC]" % (
+                                val,
+                                time.asctime(time.gmtime(val)),
+                            )
+                        except ValueError:
+                            val = "0x%-8X [INVALID TIME]" % val
+                else:
+                    val = "".join(
+                        chr(d) if chr(d) in string.printable else "\\x%02x" % d
+                        for d in [ord(c) if not isinstance(c, int) else c for c in val]
+                    )
+
+                dump_dict[key] = {
+                    "FileOffset": self.__field_offsets__[key] + self.__file_offset__,
+                    "Offset": self.__field_offsets__[key],
+                    "Value": val,
+                }
+
+        return dump_dict
+
+
+class SectionStructure(Structure):
+    """Convenience section handling class."""
+
+    def __init__(self, *argl, **argd):
+        if "pe" in argd:
+            self.pe = argd["pe"]
+            del argd["pe"]
+
+        self.PointerToRawData = None
+        self.VirtualAddress = None
+        self.SizeOfRawData = None
+        self.Misc_VirtualSize = None
+        Structure.__init__(self, *argl, **argd)
+        self.PointerToRawData_adj = None
+        self.VirtualAddress_adj = None
+        self.section_min_addr = None
+        self.section_max_addr = None
+
+    def get_PointerToRawData_adj(self):
+        if self.PointerToRawData_adj is None:
+            if self.PointerToRawData is not None:
+                self.PointerToRawData_adj = self.pe.adjust_FileAlignment(
+                    self.PointerToRawData, self.pe.OPTIONAL_HEADER.FileAlignment
+                )
+        return self.PointerToRawData_adj
+
+    def get_VirtualAddress_adj(self):
+        if self.VirtualAddress_adj is None:
+            if self.VirtualAddress is not None:
+                self.VirtualAddress_adj = self.pe.adjust_SectionAlignment(
+                    self.VirtualAddress,
+                    self.pe.OPTIONAL_HEADER.SectionAlignment,
+                    self.pe.OPTIONAL_HEADER.FileAlignment,
+                )
+        return self.VirtualAddress_adj
+
+    def get_data(self, start=None, length=None, ignore_padding=False):
+        """Get data chunk from a section.
+
+        Allows to query data from the section by passing the
+        addresses where the PE file would be loaded by default.
+        It is then possible to retrieve code and data by their real
+        addresses as they would be if loaded.
+
+        Note that sections on disk can include padding that would
+        not be loaded to memory. That is the case if `section.SizeOfRawData`
+        is greater than `section.Misc_VirtualSize`, and that means
+        that data past `section.Misc_VirtualSize` is padding.
+        In case you are not interested in this padding, passing
+        `ignore_padding=True` will truncate the result in order
+        not to return the padding (if any).
+
+        Returns bytes() under Python 3.x and set() under Python 2.7
+        """
+
+        if start is None:
+            offset = self.get_PointerToRawData_adj()
+        else:
+            offset = (
+                start - self.get_VirtualAddress_adj()
+            ) + self.get_PointerToRawData_adj()
+
+        if length is not None:
+            end = offset + length
+        elif self.SizeOfRawData is not None:
+            end = offset + self.SizeOfRawData
+        else:
+            end = offset
+
+        if ignore_padding and end is not None and offset is not None:
+            end = min(end, offset + self.Misc_VirtualSize)
+
+        # PointerToRawData is not adjusted here as we might want to read any possible
+        # extra bytes that might get cut off by aligning the start (and hence cutting
+        # something off the end)
+        if self.PointerToRawData is not None and self.SizeOfRawData is not None:
+            if end > self.PointerToRawData + self.SizeOfRawData:
+                end = self.PointerToRawData + self.SizeOfRawData
+        return self.pe.__data__[offset:end]
+
+    def __setattr__(self, name, val):
+
+        if name == "Characteristics":
+            section_flags = retrieve_flags(SECTION_CHARACTERISTICS, "IMAGE_SCN_")
+
+            # Set the section's flags according to the Characteristics member
+            set_flags(self, val, section_flags)
+
+        elif "IMAGE_SCN_" in name and hasattr(self, name):
+            if val:
+                self.__dict__["Characteristics"] |= SECTION_CHARACTERISTICS[name]
+            else:
+                self.__dict__["Characteristics"] ^= SECTION_CHARACTERISTICS[name]
+
+        self.__dict__[name] = val
+
+    def get_rva_from_offset(self, offset):
+        return offset - self.get_PointerToRawData_adj() + self.get_VirtualAddress_adj()
+
+    def get_offset_from_rva(self, rva):
+        return rva - self.get_VirtualAddress_adj() + self.get_PointerToRawData_adj()
+
+    def contains_offset(self, offset):
+        """Check whether the section contains the file offset provided."""
+
+        if self.PointerToRawData is None:
+            # bss and other sections containing only uninitialized data must have 0
+            # and do not take space in the file
+            return False
+        PointerToRawData_adj = self.get_PointerToRawData_adj()
+        return (
+            PointerToRawData_adj <= offset < PointerToRawData_adj + self.SizeOfRawData
+        )
+
+    def contains_rva(self, rva):
+        """Check whether the section contains the address provided."""
+
+        # speedup
+        if self.section_min_addr is not None and self.section_max_addr is not None:
+            return self.section_min_addr <= rva < self.section_max_addr
+
+        VirtualAddress_adj = self.get_VirtualAddress_adj()
+        # Check if the SizeOfRawData is realistic. If it's bigger than the size of
+        # the whole PE file minus the start address of the section it could be
+        # either truncated or the SizeOfRawData contains a misleading value.
+        # In either of those cases we take the VirtualSize
+        #
+        if len(self.pe.__data__) - self.get_PointerToRawData_adj() < self.SizeOfRawData:
+            # PECOFF documentation v8 says:
+            # VirtualSize: The total size of the section when loaded into memory.
+            # If this value is greater than SizeOfRawData, the section is zero-padded.
+            # This field is valid only for executable images and should be set to zero
+            # for object files.
+            #
+            size = self.Misc_VirtualSize
+        else:
+            size = max(self.SizeOfRawData, self.Misc_VirtualSize)
+
+        # Check whether there's any section after the current one that starts before
+        # the calculated end for the current one. If so, cut the current section's size
+        # to fit in the range up to where the next section starts.
+        if (
+            self.next_section_virtual_address is not None
+            and self.next_section_virtual_address > self.VirtualAddress
+            and VirtualAddress_adj + size > self.next_section_virtual_address
+        ):
+            size = self.next_section_virtual_address - VirtualAddress_adj
+
+        self.section_min_addr = VirtualAddress_adj
+        self.section_max_addr = VirtualAddress_adj + size
+        return VirtualAddress_adj <= rva < VirtualAddress_adj + size
+
+    def contains(self, rva):
+        return self.contains_rva(rva)
+
+    def get_entropy(self):
+        """Calculate and return the entropy for the section."""
+
+        return self.entropy_H(self.get_data())
+
+    def get_hash_sha1(self):
+        """Get the SHA-1 hex-digest of the section's data."""
+
+        if sha1 is not None:
+            return sha1(self.get_data()).hexdigest()
+
+    def get_hash_sha256(self):
+        """Get the SHA-256 hex-digest of the section's data."""
+
+        if sha256 is not None:
+            return sha256(self.get_data()).hexdigest()
+
+    def get_hash_sha512(self):
+        """Get the SHA-512 hex-digest of the section's data."""
+
+        if sha512 is not None:
+            return sha512(self.get_data()).hexdigest()
+
+    def get_hash_md5(self):
+        """Get the MD5 hex-digest of the section's data."""
+
+        if md5 is not None:
+            return md5(self.get_data()).hexdigest()
+
+    def entropy_H(self, data):
+        """Calculate the entropy of a chunk of data."""
+
+        if not data:
+            return 0.0
+
+        occurences = Counter(bytearray(data))
+
+        entropy = 0
+        for x in occurences.values():
+            p_x = float(x) / len(data)
+            entropy -= p_x * math.log(p_x, 2)
+
+        return entropy
+
+
+@lru_cache(maxsize=2048, copy=False)
+def set_bitfields_format(format):
+    class Accumulator:
+        def __init__(self, fmt, comp_fields):
+            self._subfields = []
+            # add a prefix to distinguish the artificially created compoud field
+            # from regular fields
+            self._name = "~"
+            self._type = None
+            self._bits_left = 0
+            self._comp_fields = comp_fields
+            self._format = fmt
+
+        def wrap_up(self):
+            if self._type is None:
+                return
+            self._format.append(self._type + "," + self._name)
+            self._comp_fields[len(self._format) - 1] = (self._type, self._subfields)
+            self._name = "~"
+            self._type = None
+            self._subfields = []
+
+        def new_type(self, tp):
+            self._bits_left = STRUCT_SIZEOF_TYPES[tp] * 8
+            self._type = tp
+
+        def add_subfield(self, name, bitcnt):
+            self._name += name
+            self._bits_left -= bitcnt
+            self._subfields.append((name, bitcnt))
+
+        def get_type(self):
+            return self._type
+
+        def get_name(self):
+            return self._name
+
+        def get_bits_left(self):
+            return self._bits_left
+
+    old_fmt = []
+    comp_fields = {}
+    ac = Accumulator(old_fmt, comp_fields)
+
+    for elm in format[1]:
+        if not ":" in elm:
+            ac.wrap_up()
+            old_fmt.append(elm)
+            continue
+
+        elm_type, elm_name = elm.split(",", 1)
+
+        if "," in elm_name:
+            raise NotImplementedError(
+                "Structures with bitfields do not support unions yet"
+            )
+
+        elm_type, elm_bits = elm_type.split(":", 1)
+        elm_bits = int(elm_bits)
+        if elm_type != ac.get_type() or elm_bits > ac.get_bits_left():
+            ac.wrap_up()
+            ac.new_type(elm_type)
+
+        ac.add_subfield(elm_name, elm_bits)
+    ac.wrap_up()
+
+    format_str, _, field_offsets, keys, format_length = set_format(tuple(old_fmt))
+
+    extended_keys = []
+    for idx, val in enumerate(keys):
+        if not idx in comp_fields:
+            extended_keys.append(val)
+            continue
+        _, sbf = comp_fields[idx]
+        bf_names = [[f[StructureWithBitfields.BTF_NAME_IDX]] for f in sbf]
+        extended_keys.extend(bf_names)
+        for n in bf_names:
+            field_offsets[n[0]] = field_offsets[val[0]]
+
+    return (format_str, format_length, field_offsets, keys, extended_keys, comp_fields)
+
+
+class StructureWithBitfields(Structure):
+    """
+    Extends Structure's functionality with support for bitfields such as:
+        ('B:4,LowerHalf', 'B:4,UpperHalf')
+    To this end, two lists are maintained:
+        * self.__keys__ that contains compound fields, for example
+          ('B,~LowerHalfUpperHalf'), and is used during packing/unpaking
+        * self.__keys_ext__ containing a separate key for each field (ex., LowerHalf,
+          UpperHalf) to simplify implementation of dump()
+    This way the implementation of unpacking/packing and dump() from Structure can be
+    reused.
+
+    In addition, we create a dictionary:
+         -->
+            (data type, [ (subfield name, length in bits)+ ] )
+    that facilitates bitfield paking and unpacking.
+
+    With lru_cache() creating only once instance per format string, the memory
+    overhead is negligible.
+    """
+
+    BTF_NAME_IDX = 0
+    BTF_BITCNT_IDX = 1
+    CF_TYPE_IDX = 0
+    CF_SUBFLD_IDX = 1
+
+    def __init__(self, format, name=None, file_offset=None):
+        (
+            self.__format_str__,
+            self.__format_length__,
+            self.__field_offsets__,
+            self.__keys__,
+            self.__keys_ext__,
+            self.__compound_fields__,
+        ) = set_bitfields_format(format)
+        # create our own unpacked_data_elms to ensure they are not shared among
+        # StructureWithBitfields instances with the same format string
+        self.__unpacked_data_elms__ = [None for i in range(self.__format_length__)]
+        self.__all_zeroes__ = False
+        self.__file_offset__ = file_offset
+        self.name = name if name != None else format[0]
+
+    def __unpack__(self, data):
+        # calling the original routine to deal with special cases/spurious data
+        # structures
+        super(StructureWithBitfields, self).__unpack__(data)
+        self._unpack_bitfield_attributes()
+
+    def __pack__(self):
+        self._pack_bitfield_attributes()
+        try:
+            data = super(StructureWithBitfields, self).__pack__()
+        finally:
+            self._unpack_bitfield_attributes()
+        return data
+
+    def dump(self, indentation=0):
+        tk = self.__keys__
+        self.__keys__ = self.__keys_ext__
+        try:
+            ret = super(StructureWithBitfields, self).dump(indentation)
+        finally:
+            self.__keys__ = tk
+        return ret
+
+    def dump_dict(self):
+        tk = self.__keys__
+        self.__keys__ = self.__keys_ext__
+        try:
+            ret = super(StructureWithBitfields, self).dump_dict()
+        finally:
+            self.__keys__ = tk
+        return ret
+
+    def _unpack_bitfield_attributes(self):
+        """Replace compound attributes corresponding to bitfields with separate
+        sub-fields.
+        """
+        for i in self.__compound_fields__.keys():
+            cf_name = self.__keys__[i][0]
+            cval = getattr(self, cf_name)
+            delattr(self, cf_name)
+            offst = 0
+            for sf in self.__compound_fields__[i][StructureWithBitfields.CF_SUBFLD_IDX]:
+                mask = (1 << sf[StructureWithBitfields.BTF_BITCNT_IDX]) - 1
+                mask <<= offst
+                setattr(
+                    self,
+                    sf[StructureWithBitfields.BTF_NAME_IDX],
+                    (cval & mask) >> offst,
+                )
+                offst += sf[StructureWithBitfields.BTF_BITCNT_IDX]
+
+    def _pack_bitfield_attributes(self):
+        """Pack attributes into a compound bitfield"""
+        for i in self.__compound_fields__.keys():
+            cf_name = self.__keys__[i][0]
+            offst, acc_val = 0, 0
+            for sf in self.__compound_fields__[i][StructureWithBitfields.CF_SUBFLD_IDX]:
+                mask = (1 << sf[StructureWithBitfields.BTF_BITCNT_IDX]) - 1
+                field_val = (
+                    getattr(self, sf[StructureWithBitfields.BTF_NAME_IDX]) & mask
+                )
+                acc_val |= field_val << offst
+                offst += sf[StructureWithBitfields.BTF_BITCNT_IDX]
+            setattr(self, cf_name, acc_val)
+
+
+class DataContainer:
+    """Generic data container."""
+
+    def __init__(self, **args):
+        bare_setattr = super(DataContainer, self).__setattr__
+        for key, value in args.items():
+            bare_setattr(key, value)
+
+
+class ImportDescData(DataContainer):
+    """Holds import descriptor information.
+
+    dll:        name of the imported DLL
+    imports:    list of imported symbols (ImportData instances)
+    struct:     IMAGE_IMPORT_DESCRIPTOR structure
+    """
+
+
+class ImportData(DataContainer):
+    """Holds imported symbol's information.
+
+    ordinal:    Ordinal of the symbol
+    name:       Name of the symbol
+    bound:      If the symbol is bound, this contains
+                the address.
+    """
+
+    def __setattr__(self, name, val):
+
+        # If the instance doesn't yet have an ordinal attribute
+        # it's not fully initialized so can't do any of the
+        # following
+        #
+        if (
+            hasattr(self, "ordinal")
+            and hasattr(self, "bound")
+            and hasattr(self, "name")
+        ):
+
+            if name == "ordinal":
+
+                if self.pe.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE:
+                    ordinal_flag = IMAGE_ORDINAL_FLAG
+                elif self.pe.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE_PLUS:
+                    ordinal_flag = IMAGE_ORDINAL_FLAG64
+
+                # Set the ordinal and flag the entry as importing by ordinal
+                self.struct_table.Ordinal = ordinal_flag | (val & 0xFFFF)
+                self.struct_table.AddressOfData = self.struct_table.Ordinal
+                self.struct_table.Function = self.struct_table.Ordinal
+                self.struct_table.ForwarderString = self.struct_table.Ordinal
+            elif name == "bound":
+                if self.struct_iat is not None:
+                    self.struct_iat.AddressOfData = val
+                    self.struct_iat.AddressOfData = self.struct_iat.AddressOfData
+                    self.struct_iat.Function = self.struct_iat.AddressOfData
+                    self.struct_iat.ForwarderString = self.struct_iat.AddressOfData
+            elif name == "address":
+                self.struct_table.AddressOfData = val
+                self.struct_table.Ordinal = self.struct_table.AddressOfData
+                self.struct_table.Function = self.struct_table.AddressOfData
+                self.struct_table.ForwarderString = self.struct_table.AddressOfData
+            elif name == "name":
+                # Make sure we reset the entry in case the import had been set to
+                # import by ordinal
+                if self.name_offset:
+
+                    name_rva = self.pe.get_rva_from_offset(self.name_offset)
+                    self.pe.set_dword_at_offset(
+                        self.ordinal_offset, (0 << 31) | name_rva
+                    )
+
+                    # Complain if the length of the new name is longer than the
+                    # existing one
+                    if len(val) > len(self.name):
+                        raise PEFormatError(
+                            "The export name provided is longer than the existing one."
+                        )
+                        pass
+                    self.pe.set_bytes_at_offset(self.name_offset, val)
+
+        self.__dict__[name] = val
+
+
+class ExportDirData(DataContainer):
+    """Holds export directory information.
+
+    struct:     IMAGE_EXPORT_DIRECTORY structure
+    symbols:    list of exported symbols (ExportData instances)"""
+
+
+class ExportData(DataContainer):
+    """Holds exported symbols' information.
+
+    ordinal:    ordinal of the symbol
+    address:    address of the symbol
+    name:       name of the symbol (None if the symbol is
+                exported by ordinal only)
+    forwarder:  if the symbol is forwarded it will
+                contain the name of the target symbol,
+                None otherwise.
+    """
+
+    def __setattr__(self, name, val):
+
+        # If the instance doesn't yet have an ordinal attribute
+        # it's not fully initialized so can't do any of the
+        # following
+        #
+        if (
+            hasattr(self, "ordinal")
+            and hasattr(self, "address")
+            and hasattr(self, "forwarder")
+            and hasattr(self, "name")
+        ):
+
+            if name == "ordinal":
+                self.pe.set_word_at_offset(self.ordinal_offset, val)
+            elif name == "address":
+                self.pe.set_dword_at_offset(self.address_offset, val)
+            elif name == "name":
+                # Complain if the length of the new name is longer than the
+                # existing one
+                if len(val) > len(self.name):
+                    raise PEFormatError(
+                        "The export name provided is longer than the existing one."
+                    )
+                self.pe.set_bytes_at_offset(self.name_offset, val)
+            elif name == "forwarder":
+                # Complain if the length of the new name is longer than the
+                # existing one
+                if len(val) > len(self.forwarder):
+                    raise PEFormatError(
+                        "The forwarder name provided is longer than the existing one."
+                    )
+                self.pe.set_bytes_at_offset(self.forwarder_offset, val)
+
+        self.__dict__[name] = val
+
+
+class ResourceDirData(DataContainer):
+    """Holds resource directory information.
+
+    struct:     IMAGE_RESOURCE_DIRECTORY structure
+    entries:    list of entries (ResourceDirEntryData instances)
+    """
+
+
+class ResourceDirEntryData(DataContainer):
+    """Holds resource directory entry data.
+
+    struct:     IMAGE_RESOURCE_DIRECTORY_ENTRY structure
+    name:       If the resource is identified by name this
+                attribute will contain the name string. None
+                otherwise. If identified by id, the id is
+                available at 'struct.Id'
+    id:         the id, also in struct.Id
+    directory:  If this entry has a lower level directory
+                this attribute will point to the
+                ResourceDirData instance representing it.
+    data:       If this entry has no further lower directories
+                and points to the actual resource data, this
+                attribute will reference the corresponding
+                ResourceDataEntryData instance.
+    (Either of the 'directory' or 'data' attribute will exist,
+    but not both.)
+    """
+
+
+class ResourceDataEntryData(DataContainer):
+    """Holds resource data entry information.
+
+    struct:     IMAGE_RESOURCE_DATA_ENTRY structure
+    lang:       Primary language ID
+    sublang:    Sublanguage ID
+    """
+
+
+class DebugData(DataContainer):
+    """Holds debug information.
+
+    struct:     IMAGE_DEBUG_DIRECTORY structure
+    entries:    list of entries (IMAGE_DEBUG_TYPE instances)
+    """
+
+
+class DynamicRelocationData(DataContainer):
+    """Holds dynamic relocation information.
+
+    struct:        IMAGE_DYNAMIC_RELOCATION structure
+    symbol:        Symbol to which dynamic relocations must be applied
+    relocations:   List of dynamic relocations for this symbol (BaseRelocationData instances)
+    """
+
+
+class BaseRelocationData(DataContainer):
+    """Holds base relocation information.
+
+    struct:     IMAGE_BASE_RELOCATION structure
+    entries:    list of relocation data (RelocationData instances)
+    """
+
+
+class RelocationData(DataContainer):
+    """Holds relocation information.
+
+    type:       Type of relocation
+                The type string can be obtained by
+                RELOCATION_TYPE[type]
+    rva:        RVA of the relocation
+    """
+
+    def __setattr__(self, name, val):
+
+        # If the instance doesn't yet have a struct attribute
+        # it's not fully initialized so can't do any of the
+        # following
+        #
+        if hasattr(self, "struct"):
+            # Get the word containing the type and data
+            #
+            word = self.struct.Data
+
+            if name == "type":
+                word = (val << 12) | (word & 0xFFF)
+            elif name == "rva":
+                offset = max(val - self.base_rva, 0)
+                word = (word & 0xF000) | (offset & 0xFFF)
+
+            # Store the modified data
+            #
+            self.struct.Data = word
+
+        self.__dict__[name] = val
+
+
+class TlsData(DataContainer):
+    """Holds TLS information.
+
+    struct:     IMAGE_TLS_DIRECTORY structure
+    """
+
+
+class BoundImportDescData(DataContainer):
+    """Holds bound import descriptor data.
+
+    This directory entry will provide information on the
+    DLLs this PE file has been bound to (if bound at all).
+    The structure will contain the name and timestamp of the
+    DLL at the time of binding so that the loader can know
+    whether it differs from the one currently present in the
+    system and must, therefore, re-bind the PE's imports.
+
+    struct:     IMAGE_BOUND_IMPORT_DESCRIPTOR structure
+    name:       DLL name
+    entries:    list of entries (BoundImportRefData instances)
+                the entries will exist if this DLL has forwarded
+                symbols. If so, the destination DLL will have an
+                entry in this list.
+    """
+
+
+class LoadConfigData(DataContainer):
+    """Holds Load Config data.
+
+    struct:     IMAGE_LOAD_CONFIG_DIRECTORY structure
+    name:       dll name
+    dynamic_relocations: dynamic relocation information, if present
+    """
+
+
+class BoundImportRefData(DataContainer):
+    """Holds bound import forwarder reference data.
+
+    Contains the same information as the bound descriptor but
+    for forwarded DLLs, if any.
+
+    struct:     IMAGE_BOUND_FORWARDER_REF structure
+    name:       dll name
+    """
+
+
+class ExceptionsDirEntryData(DataContainer):
+    """Holds the data related to SEH (and stack unwinding, in particular)
+
+    struct      an instance of RUNTIME_FUNTION
+    unwindinfo  an instance of UNWIND_INFO
+    """
+
+
+class UnwindInfo(StructureWithBitfields):
+    """Handles the complexities of UNWIND_INFO structure:
+    * variable number of UWIND_CODEs
+    * optional ExceptionHandler and FunctionEntry fields
+    """
+
+    def __init__(self, file_offset=0):
+        super(UnwindInfo, self).__init__(
+            (
+                "UNWIND_INFO",
+                (
+                    "B:3,Version",
+                    "B:5,Flags",
+                    "B,SizeOfProlog",
+                    "B,CountOfCodes",
+                    "B:4,FrameRegister",
+                    "B:4,FrameOffset",
+                ),
+            ),
+            file_offset=file_offset,
+        )
+        self._full_size = super(UnwindInfo, self).sizeof()
+        self._opt_field_name = None
+        self._code_info = StructureWithBitfields(
+            ("UNWIND_CODE", ("B,CodeOffset", "B:4,UnwindOp", "B:4,OpInfo")),
+            file_offset=0,
+        )
+        self._chained_entry = None
+        self._finished_unpacking = False
+
+    def unpack_in_stages(self, data):
+        """Unpacks the UNWIND_INFO "in two calls", with the first call establishing
+        a full size of the structure and the second, performing the actual unpacking.
+        """
+        if self._finished_unpacking:
+            return None
+
+        super(UnwindInfo, self).__unpack__(data)
+        codes_cnt_max = (self.CountOfCodes + 1) & ~1
+        hdlr_offset = (
+            super(UnwindInfo, self).sizeof() + codes_cnt_max * self._code_info.sizeof()
+        )
+        self._full_size = hdlr_offset + (
+            0 if self.Flags == 0 else STRUCT_SIZEOF_TYPES["I"]
+        )
+
+        if len(data) < self._full_size:
+            return None
+
+        if self.Version != 1 and self.Version != 2:
+            return "Unsupported version of UNWIND_INFO at " + hex(self.__file_offset__)
+
+        self.UnwindCodes = []
+        ro = super(UnwindInfo, self).sizeof()
+        codes_left = self.CountOfCodes
+        while codes_left > 0:
+            self._code_info.__unpack__(data[ro : ro + self._code_info.sizeof()])
+            ucode = PrologEpilogOpsFactory.create(self._code_info)
+            if ucode is None:
+                return "Unknown UNWIND_CODE at " + hex(self.__file_offset__ + ro)
+
+            len_in_codes = ucode.length_in_code_structures(self._code_info, self)
+            opc_size = self._code_info.sizeof() * len_in_codes
+            ucode.initialize(
+                self._code_info,
+                data[ro : ro + opc_size],
+                self,
+                self.__file_offset__ + ro,
+            )
+            ro += opc_size
+            codes_left -= len_in_codes
+            self.UnwindCodes.append(ucode)
+
+        if self.UNW_FLAG_EHANDLER or self.UNW_FLAG_UHANDLER:
+            self._opt_field_name = "ExceptionHandler"
+
+        if self.UNW_FLAG_CHAININFO:
+            self._opt_field_name = "FunctionEntry"
+
+        if self._opt_field_name != None:
+            setattr(
+                self,
+                self._opt_field_name,
+                struct.unpack(
+                    " self._full_size:
+                break
+            data[cur_offset : cur_offset + uc.struct.sizeof()] = uc.struct.__pack__()
+            cur_offset += uc.struct.sizeof()
+
+        if self._opt_field_name != None:
+            data[
+                self._full_size - STRUCT_SIZEOF_TYPES["I"] : self._full_size
+            ] = struct.pack("" if self.struct.OpInfo else "")
+
+
+class PrologEpilogOpEpilogMarker(PrologEpilogOp):
+    """UWOP_EPILOG"""
+
+    def initialize(self, unw_code, data, unw_info, file_offset):
+        self._long_offst = True
+        self._first = not hasattr(unw_info, "SizeOfEpilog")
+        super(PrologEpilogOpEpilogMarker, self).initialize(
+            unw_code, data, unw_info, file_offset
+        )
+        if self._first:
+            setattr(unw_info, "SizeOfEpilog", self.struct.Size)
+            self._long_offst = unw_code.OpInfo & 1 == 0
+        self._epilog_size = unw_info.SizeOfEpilog
+
+    def _get_format(self, unw_code):
+        # check if it is the first epilog code among encountered; then its record
+        # will contain size of the epilog
+        if self._first:
+            return (
+                "UNWIND_CODE_EPILOG",
+                ("B,OffsetLow,Size", "B:4,UnwindOp", "B:4,Flags")
+                if unw_code.OpInfo & 1 == 1
+                else (
+                    "B,Size",
+                    "B:4,UnwindOp",
+                    "B:4,Flags",
+                    "B,OffsetLow",
+                    "B:4,Unused",
+                    "B:4,OffsetHigh",
+                ),
+            )
+        else:
+            return (
+                "UNWIND_CODE_EPILOG",
+                ("B,OffsetLow", "B:4,UnwindOp", "B:4,OffsetHigh"),
+            )
+
+    def length_in_code_structures(self, unw_code, unw_info):
+        return (
+            2
+            if not hasattr(unw_info, "SizeOfEpilog") and (unw_code.OpInfo & 1) == 0
+            else 1
+        )
+
+    def get_offset(self):
+        return self.struct.OffsetLow | (
+            self.struct.OffsetHigh << 8 if self._long_offst else 0
+        )
+
+    def is_valid(self):
+        return self.get_offset() > 0
+
+    def __str__(self):
+        # the EPILOG sequence may have a terminating all-zeros entry
+        return (
+            "EPILOG: size="
+            + hex(self._epilog_size)
+            + ", offset from the end=-"
+            + hex(self.get_offset())
+            if self.get_offset() > 0
+            else ""
+        )
+
+
+class PrologEpilogOpsFactory:
+    """A factory for creating unwind codes based on the value of UnwindOp"""
+
+    _class_dict = {
+        UWOP_PUSH_NONVOL: PrologEpilogOpPushReg,
+        UWOP_ALLOC_LARGE: PrologEpilogOpAllocLarge,
+        UWOP_ALLOC_SMALL: PrologEpilogOpAllocSmall,
+        UWOP_SET_FPREG: PrologEpilogOpSetFP,
+        UWOP_SAVE_NONVOL: PrologEpilogOpSaveReg,
+        UWOP_SAVE_NONVOL_FAR: PrologEpilogOpSaveRegFar,
+        UWOP_SAVE_XMM128: PrologEpilogOpSaveXMM,
+        UWOP_SAVE_XMM128_FAR: PrologEpilogOpSaveXMMFar,
+        UWOP_PUSH_MACHFRAME: PrologEpilogOpPushFrame,
+        UWOP_EPILOG: PrologEpilogOpEpilogMarker,
+    }
+
+    @staticmethod
+    def create(unwcode):
+        code = unwcode.UnwindOp
+        return (
+            PrologEpilogOpsFactory._class_dict[code]()
+            if code in PrologEpilogOpsFactory._class_dict
+            else None
+        )
+
+
+# Valid FAT32 8.3 short filename characters according to:
+#  http://en.wikipedia.org/wiki/8.3_filename
+# This will help decide whether DLL ASCII names are likely
+# to be valid or otherwise corrupt data
+#
+# The filename length is not checked because the DLLs filename
+# can be longer that the 8.3
+
+allowed_filename = b(
+    string.ascii_lowercase
+    + string.ascii_uppercase
+    + string.digits
+    + "!#$%&'()-@^_`{}~+,.;=[]"
+)
+
+
+def is_valid_dos_filename(s):
+    if s is None or not isinstance(s, (str, bytes, bytearray)):
+        return False
+    # Allow path separators as import names can contain directories.
+    allowed = allowed_filename + b"\\/"
+    return all(c in allowed for c in set(s))
+
+
+# Check if an imported name uses the valid accepted characters expected in
+# mangled function names. If the symbol's characters don't fall within this
+# charset we will assume the name is invalid.
+# The dot "." character comes from: https://github.com/erocarrera/pefile/pull/346
+# All other symbols can be inserted by adding a name with that symbol to a .def file,
+# and passing it to link.exe (See export_test.py)
+allowed_function_name = b(
+    string.ascii_lowercase + string.ascii_uppercase + string.digits
+)
+
+
+@lru_cache(maxsize=2048)
+def is_valid_function_name(
+    s: Union[str, bytes, bytearray], relax_allowed_characters: bool = False
+) -> bool:
+    allowed_extra = b"._?@$()<>"
+    if relax_allowed_characters:
+        allowed_extra = b"!\"#$%&'()*+,-./:<>?[\\]^_`{|}~@"
+    return (
+        s is not None
+        and isinstance(s, (str, bytes, bytearray))
+        and all((c in allowed_function_name or c in allowed_extra) for c in set(s))
+    )
+
+
+class PE:
+    """A Portable Executable representation.
+
+    This class provides access to most of the information in a PE file.
+
+    It expects to be supplied the name of the file to load or PE data
+    to process and an optional argument 'fast_load' (False by default)
+    which controls whether to load all the directories information,
+    which can be quite time consuming.
+
+    pe = pefile.PE('module.dll')
+    pe = pefile.PE(name='module.dll')
+
+    would load 'module.dll' and process it. If the data is already
+    available in a buffer the same can be achieved with:
+
+    pe = pefile.PE(data=module_dll_data)
+
+    The "fast_load" can be set to a default by setting its value in the
+    module itself by means, for instance, of a "pefile.fast_load = True".
+    That will make all the subsequent instances not to load the
+    whole PE structure. The "full_load" method can be used to parse
+    the missing data at a later stage.
+
+    Basic headers information will be available in the attributes:
+
+    DOS_HEADER
+    NT_HEADERS
+    FILE_HEADER
+    OPTIONAL_HEADER
+
+    All of them will contain among their attributes the members of the
+    corresponding structures as defined in WINNT.H
+
+    The raw data corresponding to the header (from the beginning of the
+    file up to the start of the first section) will be available in the
+    instance's attribute 'header' as a string.
+
+    The sections will be available as a list in the 'sections' attribute.
+    Each entry will contain as attributes all the structure's members.
+
+    Directory entries will be available as attributes (if they exist):
+    (no other entries are processed at this point)
+
+    DIRECTORY_ENTRY_IMPORT (list of ImportDescData instances)
+    DIRECTORY_ENTRY_EXPORT (ExportDirData instance)
+    DIRECTORY_ENTRY_RESOURCE (ResourceDirData instance)
+    DIRECTORY_ENTRY_DEBUG (list of DebugData instances)
+    DIRECTORY_ENTRY_BASERELOC (list of BaseRelocationData instances)
+    DIRECTORY_ENTRY_TLS
+    DIRECTORY_ENTRY_BOUND_IMPORT (list of BoundImportData instances)
+
+    The following dictionary attributes provide ways of mapping different
+    constants. They will accept the numeric value and return the string
+    representation and the opposite, feed in the string and get the
+    numeric constant:
+
+    DIRECTORY_ENTRY
+    IMAGE_CHARACTERISTICS
+    SECTION_CHARACTERISTICS
+    DEBUG_TYPE
+    SUBSYSTEM_TYPE
+    MACHINE_TYPE
+    RELOCATION_TYPE
+    RESOURCE_TYPE
+    LANG
+    SUBLANG
+    """
+
+    #
+    # Format specifications for PE structures.
+    #
+
+    __IMAGE_DOS_HEADER_format__ = (
+        "IMAGE_DOS_HEADER",
+        (
+            "H,e_magic",
+            "H,e_cblp",
+            "H,e_cp",
+            "H,e_crlc",
+            "H,e_cparhdr",
+            "H,e_minalloc",
+            "H,e_maxalloc",
+            "H,e_ss",
+            "H,e_sp",
+            "H,e_csum",
+            "H,e_ip",
+            "H,e_cs",
+            "H,e_lfarlc",
+            "H,e_ovno",
+            "8s,e_res",
+            "H,e_oemid",
+            "H,e_oeminfo",
+            "20s,e_res2",
+            "I,e_lfanew",
+        ),
+    )
+
+    __IMAGE_FILE_HEADER_format__ = (
+        "IMAGE_FILE_HEADER",
+        (
+            "H,Machine",
+            "H,NumberOfSections",
+            "I,TimeDateStamp",
+            "I,PointerToSymbolTable",
+            "I,NumberOfSymbols",
+            "H,SizeOfOptionalHeader",
+            "H,Characteristics",
+        ),
+    )
+
+    __IMAGE_DATA_DIRECTORY_format__ = (
+        "IMAGE_DATA_DIRECTORY",
+        ("I,VirtualAddress", "I,Size"),
+    )
+
+    __IMAGE_OPTIONAL_HEADER_format__ = (
+        "IMAGE_OPTIONAL_HEADER",
+        (
+            "H,Magic",
+            "B,MajorLinkerVersion",
+            "B,MinorLinkerVersion",
+            "I,SizeOfCode",
+            "I,SizeOfInitializedData",
+            "I,SizeOfUninitializedData",
+            "I,AddressOfEntryPoint",
+            "I,BaseOfCode",
+            "I,BaseOfData",
+            "I,ImageBase",
+            "I,SectionAlignment",
+            "I,FileAlignment",
+            "H,MajorOperatingSystemVersion",
+            "H,MinorOperatingSystemVersion",
+            "H,MajorImageVersion",
+            "H,MinorImageVersion",
+            "H,MajorSubsystemVersion",
+            "H,MinorSubsystemVersion",
+            "I,Reserved1",
+            "I,SizeOfImage",
+            "I,SizeOfHeaders",
+            "I,CheckSum",
+            "H,Subsystem",
+            "H,DllCharacteristics",
+            "I,SizeOfStackReserve",
+            "I,SizeOfStackCommit",
+            "I,SizeOfHeapReserve",
+            "I,SizeOfHeapCommit",
+            "I,LoaderFlags",
+            "I,NumberOfRvaAndSizes",
+        ),
+    )
+
+    __IMAGE_OPTIONAL_HEADER64_format__ = (
+        "IMAGE_OPTIONAL_HEADER64",
+        (
+            "H,Magic",
+            "B,MajorLinkerVersion",
+            "B,MinorLinkerVersion",
+            "I,SizeOfCode",
+            "I,SizeOfInitializedData",
+            "I,SizeOfUninitializedData",
+            "I,AddressOfEntryPoint",
+            "I,BaseOfCode",
+            "Q,ImageBase",
+            "I,SectionAlignment",
+            "I,FileAlignment",
+            "H,MajorOperatingSystemVersion",
+            "H,MinorOperatingSystemVersion",
+            "H,MajorImageVersion",
+            "H,MinorImageVersion",
+            "H,MajorSubsystemVersion",
+            "H,MinorSubsystemVersion",
+            "I,Reserved1",
+            "I,SizeOfImage",
+            "I,SizeOfHeaders",
+            "I,CheckSum",
+            "H,Subsystem",
+            "H,DllCharacteristics",
+            "Q,SizeOfStackReserve",
+            "Q,SizeOfStackCommit",
+            "Q,SizeOfHeapReserve",
+            "Q,SizeOfHeapCommit",
+            "I,LoaderFlags",
+            "I,NumberOfRvaAndSizes",
+        ),
+    )
+
+    __IMAGE_NT_HEADERS_format__ = ("IMAGE_NT_HEADERS", ("I,Signature",))
+
+    __IMAGE_SECTION_HEADER_format__ = (
+        "IMAGE_SECTION_HEADER",
+        (
+            "8s,Name",
+            "I,Misc,Misc_PhysicalAddress,Misc_VirtualSize",
+            "I,VirtualAddress",
+            "I,SizeOfRawData",
+            "I,PointerToRawData",
+            "I,PointerToRelocations",
+            "I,PointerToLinenumbers",
+            "H,NumberOfRelocations",
+            "H,NumberOfLinenumbers",
+            "I,Characteristics",
+        ),
+    )
+
+    __IMAGE_DELAY_IMPORT_DESCRIPTOR_format__ = (
+        "IMAGE_DELAY_IMPORT_DESCRIPTOR",
+        (
+            "I,grAttrs",
+            "I,szName",
+            "I,phmod",
+            "I,pIAT",
+            "I,pINT",
+            "I,pBoundIAT",
+            "I,pUnloadIAT",
+            "I,dwTimeStamp",
+        ),
+    )
+
+    __IMAGE_IMPORT_DESCRIPTOR_format__ = (
+        "IMAGE_IMPORT_DESCRIPTOR",
+        (
+            "I,OriginalFirstThunk,Characteristics",
+            "I,TimeDateStamp",
+            "I,ForwarderChain",
+            "I,Name",
+            "I,FirstThunk",
+        ),
+    )
+
+    __IMAGE_EXPORT_DIRECTORY_format__ = (
+        "IMAGE_EXPORT_DIRECTORY",
+        (
+            "I,Characteristics",
+            "I,TimeDateStamp",
+            "H,MajorVersion",
+            "H,MinorVersion",
+            "I,Name",
+            "I,Base",
+            "I,NumberOfFunctions",
+            "I,NumberOfNames",
+            "I,AddressOfFunctions",
+            "I,AddressOfNames",
+            "I,AddressOfNameOrdinals",
+        ),
+    )
+
+    __IMAGE_RESOURCE_DIRECTORY_format__ = (
+        "IMAGE_RESOURCE_DIRECTORY",
+        (
+            "I,Characteristics",
+            "I,TimeDateStamp",
+            "H,MajorVersion",
+            "H,MinorVersion",
+            "H,NumberOfNamedEntries",
+            "H,NumberOfIdEntries",
+        ),
+    )
+
+    __IMAGE_RESOURCE_DIRECTORY_ENTRY_format__ = (
+        "IMAGE_RESOURCE_DIRECTORY_ENTRY",
+        ("I,Name", "I,OffsetToData"),
+    )
+
+    __IMAGE_RESOURCE_DATA_ENTRY_format__ = (
+        "IMAGE_RESOURCE_DATA_ENTRY",
+        ("I,OffsetToData", "I,Size", "I,CodePage", "I,Reserved"),
+    )
+
+    __VS_VERSIONINFO_format__ = (
+        "VS_VERSIONINFO",
+        ("H,Length", "H,ValueLength", "H,Type"),
+    )
+
+    __VS_FIXEDFILEINFO_format__ = (
+        "VS_FIXEDFILEINFO",
+        (
+            "I,Signature",
+            "I,StrucVersion",
+            "I,FileVersionMS",
+            "I,FileVersionLS",
+            "I,ProductVersionMS",
+            "I,ProductVersionLS",
+            "I,FileFlagsMask",
+            "I,FileFlags",
+            "I,FileOS",
+            "I,FileType",
+            "I,FileSubtype",
+            "I,FileDateMS",
+            "I,FileDateLS",
+        ),
+    )
+
+    __StringFileInfo_format__ = (
+        "StringFileInfo",
+        ("H,Length", "H,ValueLength", "H,Type"),
+    )
+
+    __StringTable_format__ = ("StringTable", ("H,Length", "H,ValueLength", "H,Type"))
+
+    __String_format__ = ("String", ("H,Length", "H,ValueLength", "H,Type"))
+
+    __Var_format__ = ("Var", ("H,Length", "H,ValueLength", "H,Type"))
+
+    __IMAGE_THUNK_DATA_format__ = (
+        "IMAGE_THUNK_DATA",
+        ("I,ForwarderString,Function,Ordinal,AddressOfData",),
+    )
+
+    __IMAGE_THUNK_DATA64_format__ = (
+        "IMAGE_THUNK_DATA",
+        ("Q,ForwarderString,Function,Ordinal,AddressOfData",),
+    )
+
+    __IMAGE_DEBUG_DIRECTORY_format__ = (
+        "IMAGE_DEBUG_DIRECTORY",
+        (
+            "I,Characteristics",
+            "I,TimeDateStamp",
+            "H,MajorVersion",
+            "H,MinorVersion",
+            "I,Type",
+            "I,SizeOfData",
+            "I,AddressOfRawData",
+            "I,PointerToRawData",
+        ),
+    )
+
+    __IMAGE_BASE_RELOCATION_format__ = (
+        "IMAGE_BASE_RELOCATION",
+        ("I,VirtualAddress", "I,SizeOfBlock"),
+    )
+
+    __IMAGE_BASE_RELOCATION_ENTRY_format__ = (
+        "IMAGE_BASE_RELOCATION_ENTRY",
+        ("H,Data",),
+    )
+
+    __IMAGE_IMPORT_CONTROL_TRANSFER_DYNAMIC_RELOCATION_format__ = (
+        "IMAGE_IMPORT_CONTROL_TRANSFER_DYNAMIC_RELOCATION",
+        ("I:12,PageRelativeOffset", "I:1,IndirectCall", "I:19,IATIndex"),
+    )
+
+    __IMAGE_INDIR_CONTROL_TRANSFER_DYNAMIC_RELOCATION_format__ = (
+        "IMAGE_INDIR_CONTROL_TRANSFER_DYNAMIC_RELOCATION",
+        (
+            "I:12,PageRelativeOffset",
+            "I:1,IndirectCall",
+            "I:1,RexWPrefix",
+            "I:1,CfgCheck",
+            "I:1,Reserved",
+        ),
+    )
+
+    __IMAGE_SWITCHTABLE_BRANCH_DYNAMIC_RELOCATION_format__ = (
+        "IMAGE_SWITCHTABLE_BRANCH_DYNAMIC_RELOCATION",
+        ("I:12,PageRelativeOffset", "I:4,RegisterNumber"),
+    )
+
+    __IMAGE_TLS_DIRECTORY_format__ = (
+        "IMAGE_TLS_DIRECTORY",
+        (
+            "I,StartAddressOfRawData",
+            "I,EndAddressOfRawData",
+            "I,AddressOfIndex",
+            "I,AddressOfCallBacks",
+            "I,SizeOfZeroFill",
+            "I,Characteristics",
+        ),
+    )
+
+    __IMAGE_TLS_DIRECTORY64_format__ = (
+        "IMAGE_TLS_DIRECTORY",
+        (
+            "Q,StartAddressOfRawData",
+            "Q,EndAddressOfRawData",
+            "Q,AddressOfIndex",
+            "Q,AddressOfCallBacks",
+            "I,SizeOfZeroFill",
+            "I,Characteristics",
+        ),
+    )
+
+    __IMAGE_LOAD_CONFIG_DIRECTORY_format__ = (
+        "IMAGE_LOAD_CONFIG_DIRECTORY",
+        (
+            "I,Size",
+            "I,TimeDateStamp",
+            "H,MajorVersion",
+            "H,MinorVersion",
+            "I,GlobalFlagsClear",
+            "I,GlobalFlagsSet",
+            "I,CriticalSectionDefaultTimeout",
+            "I,DeCommitFreeBlockThreshold",
+            "I,DeCommitTotalFreeThreshold",
+            "I,LockPrefixTable",
+            "I,MaximumAllocationSize",
+            "I,VirtualMemoryThreshold",
+            "I,ProcessHeapFlags",
+            "I,ProcessAffinityMask",
+            "H,CSDVersion",
+            "H,Reserved1",
+            "I,EditList",
+            "I,SecurityCookie",
+            "I,SEHandlerTable",
+            "I,SEHandlerCount",
+            "I,GuardCFCheckFunctionPointer",
+            "I,GuardCFDispatchFunctionPointer",
+            "I,GuardCFFunctionTable",
+            "I,GuardCFFunctionCount",
+            "I,GuardFlags",
+            "H,CodeIntegrityFlags",
+            "H,CodeIntegrityCatalog",
+            "I,CodeIntegrityCatalogOffset",
+            "I,CodeIntegrityReserved",
+            "I,GuardAddressTakenIatEntryTable",
+            "I,GuardAddressTakenIatEntryCount",
+            "I,GuardLongJumpTargetTable",
+            "I,GuardLongJumpTargetCount",
+            "I,DynamicValueRelocTable",
+            "I,CHPEMetadataPointer",
+            "I,GuardRFFailureRoutine",
+            "I,GuardRFFailureRoutineFunctionPointer",
+            "I,DynamicValueRelocTableOffset",
+            "H,DynamicValueRelocTableSection",
+            "H,Reserved2",
+            "I,GuardRFVerifyStackPointerFunctionPointer" "I,HotPatchTableOffset",
+            "I,Reserved3",
+            "I,EnclaveConfigurationPointer",
+        ),
+    )
+
+    __IMAGE_LOAD_CONFIG_DIRECTORY64_format__ = (
+        "IMAGE_LOAD_CONFIG_DIRECTORY",
+        (
+            "I,Size",
+            "I,TimeDateStamp",
+            "H,MajorVersion",
+            "H,MinorVersion",
+            "I,GlobalFlagsClear",
+            "I,GlobalFlagsSet",
+            "I,CriticalSectionDefaultTimeout",
+            "Q,DeCommitFreeBlockThreshold",
+            "Q,DeCommitTotalFreeThreshold",
+            "Q,LockPrefixTable",
+            "Q,MaximumAllocationSize",
+            "Q,VirtualMemoryThreshold",
+            "Q,ProcessAffinityMask",
+            "I,ProcessHeapFlags",
+            "H,CSDVersion",
+            "H,Reserved1",
+            "Q,EditList",
+            "Q,SecurityCookie",
+            "Q,SEHandlerTable",
+            "Q,SEHandlerCount",
+            "Q,GuardCFCheckFunctionPointer",
+            "Q,GuardCFDispatchFunctionPointer",
+            "Q,GuardCFFunctionTable",
+            "Q,GuardCFFunctionCount",
+            "I,GuardFlags",
+            "H,CodeIntegrityFlags",
+            "H,CodeIntegrityCatalog",
+            "I,CodeIntegrityCatalogOffset",
+            "I,CodeIntegrityReserved",
+            "Q,GuardAddressTakenIatEntryTable",
+            "Q,GuardAddressTakenIatEntryCount",
+            "Q,GuardLongJumpTargetTable",
+            "Q,GuardLongJumpTargetCount",
+            "Q,DynamicValueRelocTable",
+            "Q,CHPEMetadataPointer",
+            "Q,GuardRFFailureRoutine",
+            "Q,GuardRFFailureRoutineFunctionPointer",
+            "I,DynamicValueRelocTableOffset",
+            "H,DynamicValueRelocTableSection",
+            "H,Reserved2",
+            "Q,GuardRFVerifyStackPointerFunctionPointer",
+            "I,HotPatchTableOffset",
+            "I,Reserved3",
+            "Q,EnclaveConfigurationPointer",
+        ),
+    )
+
+    __IMAGE_DYNAMIC_RELOCATION_TABLE_format__ = (
+        "IMAGE_DYNAMIC_RELOCATION_TABLE",
+        ("I,Version", "I,Size"),
+    )
+
+    __IMAGE_DYNAMIC_RELOCATION_format__ = (
+        "IMAGE_DYNAMIC_RELOCATION",
+        ("I,Symbol", "I,BaseRelocSize"),
+    )
+
+    __IMAGE_DYNAMIC_RELOCATION64_format__ = (
+        "IMAGE_DYNAMIC_RELOCATION64",
+        ("Q,Symbol", "I,BaseRelocSize"),
+    )
+
+    __IMAGE_DYNAMIC_RELOCATION_V2_format__ = (
+        "IMAGE_DYNAMIC_RELOCATION_V2",
+        ("I,HeaderSize", "I,FixupInfoSize", "I,Symbol", "I,SymbolGroup", "I,Flags"),
+    )
+
+    __IMAGE_DYNAMIC_RELOCATION64_V2_format__ = (
+        "IMAGE_DYNAMIC_RELOCATION64_V2",
+        ("I,HeaderSize", "I,FixupInfoSize", "Q,Symbol", "I,SymbolGroup", "I,Flags"),
+    )
+
+    __IMAGE_BOUND_IMPORT_DESCRIPTOR_format__ = (
+        "IMAGE_BOUND_IMPORT_DESCRIPTOR",
+        ("I,TimeDateStamp", "H,OffsetModuleName", "H,NumberOfModuleForwarderRefs"),
+    )
+
+    __IMAGE_BOUND_FORWARDER_REF_format__ = (
+        "IMAGE_BOUND_FORWARDER_REF",
+        ("I,TimeDateStamp", "H,OffsetModuleName", "H,Reserved"),
+    )
+
+    __RUNTIME_FUNCTION_format__ = (
+        "RUNTIME_FUNCTION",
+        ("I,BeginAddress", "I,EndAddress", "I,UnwindData"),
+    )
+
+    def __init__(
+        self,
+        name=None,
+        data=None,
+        fast_load=None,
+        max_symbol_exports=MAX_SYMBOL_EXPORT_COUNT,
+        max_repeated_symbol=120,
+    ):
+
+        self.max_symbol_exports = max_symbol_exports
+        self.max_repeated_symbol = max_repeated_symbol
+
+        self._get_section_by_rva_last_used = None
+
+        self.sections = []
+
+        self.__warnings = []
+
+        self.PE_TYPE = None
+
+        if name is None and data is None:
+            raise ValueError("Must supply either name or data")
+
+        # This list will keep track of all the structures created.
+        # That will allow for an easy iteration through the list
+        # in order to save the modifications made
+        self.__structures__ = []
+        self.__from_file = None
+
+        # We only want to print these warnings once
+        self.FileAlignment_Warning = False
+        self.SectionAlignment_Warning = False
+
+        # Count of total resource entries across nested tables
+        self.__total_resource_entries_count = 0
+        # Sum of the size of all resource entries parsed, which should not
+        # exceed the file size.
+        self.__total_resource_bytes = 0
+        # The number of imports parsed in this file
+        self.__total_import_symbols = 0
+
+        self.dynamic_relocation_format_by_symbol = {
+            3: PE.__IMAGE_IMPORT_CONTROL_TRANSFER_DYNAMIC_RELOCATION_format__,
+            4: PE.__IMAGE_INDIR_CONTROL_TRANSFER_DYNAMIC_RELOCATION_format__,
+            5: PE.__IMAGE_SWITCHTABLE_BRANCH_DYNAMIC_RELOCATION_format__,
+        }
+
+        fast_load = fast_load if fast_load is not None else globals()["fast_load"]
+        try:
+            self.__parse__(name, data, fast_load)
+        except:
+            self.close()
+            raise
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, type, value, traceback):
+        self.close()
+
+    def close(self):
+        if (
+            self.__from_file is True
+            and hasattr(self, "__data__")
+            and (
+                (isinstance(mmap.mmap, type) and isinstance(self.__data__, mmap.mmap))
+                or "mmap.mmap" in repr(type(self.__data__))
+            )
+        ):
+            self.__data__.close()
+            del self.__data__
+
+    def __unpack_data__(self, format, data, file_offset):
+        """Apply structure format to raw data.
+
+        Returns an unpacked structure object if successful, None otherwise.
+        """
+
+        structure = Structure(format, file_offset=file_offset)
+
+        try:
+            structure.__unpack__(data)
+        except PEFormatError as err:
+            self.__warnings.append(
+                'Corrupt header "{0}" at file offset {1}. Exception: {2}'.format(
+                    format[0], file_offset, err
+                )
+            )
+            return None
+
+        self.__structures__.append(structure)
+
+        return structure
+
+    def __unpack_data_with_bitfields__(self, format, data, file_offset):
+        """Apply structure format to raw data.
+
+        Returns an unpacked structure object if successful, None otherwise.
+        """
+
+        structure = StructureWithBitfields(format, file_offset=file_offset)
+
+        try:
+            structure.__unpack__(data)
+        except PEFormatError as err:
+            self.__warnings.append(
+                'Corrupt header "{0}" at file offset {1}. Exception: {2}'.format(
+                    format[0], file_offset, err
+                )
+            )
+            return None
+
+        self.__structures__.append(structure)
+
+        return structure
+
+    def __parse__(self, fname, data, fast_load):
+        """Parse a Portable Executable file.
+
+        Loads a PE file, parsing all its structures and making them available
+        through the instance's attributes.
+        """
+
+        if fname is not None:
+            stat = os.stat(fname)
+            if stat.st_size == 0:
+                raise PEFormatError("The file is empty")
+            fd = None
+            try:
+                fd = open(fname, "rb")
+                self.fileno = fd.fileno()
+                if hasattr(mmap, "MAP_PRIVATE"):
+                    # Unix
+                    self.__data__ = mmap.mmap(self.fileno, 0, mmap.MAP_PRIVATE)
+                else:
+                    # Windows
+                    self.__data__ = mmap.mmap(self.fileno, 0, access=mmap.ACCESS_READ)
+                self.__from_file = True
+            except IOError as excp:
+                exception_msg = "{0}".format(excp)
+                exception_msg = exception_msg and (": %s" % exception_msg)
+                raise Exception(
+                    "Unable to access file '{0}'{1}".format(fname, exception_msg)
+                )
+            finally:
+                if fd is not None:
+                    fd.close()
+        elif data is not None:
+            self.__data__ = data
+            self.__from_file = False
+
+        # Resources should not overlap each other, so they should not exceed the
+        # file size.
+        self.__resource_size_limit_upperbounds = len(self.__data__)
+        self.__resource_size_limit_reached = False
+
+        if not fast_load:
+            for byte, byte_count in Counter(bytearray(self.__data__)).items():
+                # Only report the cases where a byte makes up for more than 50% (if
+                # zero) or 15% (if non-zero) of the file's contents. There are
+                # legitimate PEs where 0x00 bytes are close to 50% of the whole
+                # file's contents.
+                if (byte == 0 and byte_count / len(self.__data__) > 0.5) or (
+                    byte != 0 and byte_count / len(self.__data__) > 0.15
+                ):
+                    self.__warnings.append(
+                        (
+                            "Byte 0x{0:02x} makes up {1:.4f}% of the file's contents."
+                            " This may indicate truncation / malformation."
+                        ).format(byte, 100.0 * byte_count / len(self.__data__))
+                    )
+
+        dos_header_data = self.__data__[:64]
+        if len(dos_header_data) != 64:
+            raise PEFormatError(
+                "Unable to read the DOS Header, possibly a truncated file."
+            )
+
+        self.DOS_HEADER = self.__unpack_data__(
+            self.__IMAGE_DOS_HEADER_format__, dos_header_data, file_offset=0
+        )
+
+        if self.DOS_HEADER.e_magic == IMAGE_DOSZM_SIGNATURE:
+            raise PEFormatError("Probably a ZM Executable (not a PE file).")
+        if not self.DOS_HEADER or self.DOS_HEADER.e_magic != IMAGE_DOS_SIGNATURE:
+            raise PEFormatError("DOS Header magic not found.")
+
+        # OC Patch:
+        # Check for sane value in e_lfanew
+        #
+        if self.DOS_HEADER.e_lfanew > len(self.__data__):
+            raise PEFormatError("Invalid e_lfanew value, probably not a PE file")
+
+        nt_headers_offset = self.DOS_HEADER.e_lfanew
+
+        self.NT_HEADERS = self.__unpack_data__(
+            self.__IMAGE_NT_HEADERS_format__,
+            self.__data__[nt_headers_offset : nt_headers_offset + 8],
+            file_offset=nt_headers_offset,
+        )
+
+        # We better check the signature right here, before the file screws
+        # around with sections:
+        # OC Patch:
+        # Some malware will cause the Signature value to not exist at all
+        if not self.NT_HEADERS or not self.NT_HEADERS.Signature:
+            raise PEFormatError("NT Headers not found.")
+
+        if (0xFFFF & self.NT_HEADERS.Signature) == IMAGE_NE_SIGNATURE:
+            raise PEFormatError("Invalid NT Headers signature. Probably a NE file")
+        if (0xFFFF & self.NT_HEADERS.Signature) == IMAGE_LE_SIGNATURE:
+            raise PEFormatError("Invalid NT Headers signature. Probably a LE file")
+        if (0xFFFF & self.NT_HEADERS.Signature) == IMAGE_LX_SIGNATURE:
+            raise PEFormatError("Invalid NT Headers signature. Probably a LX file")
+        if (0xFFFF & self.NT_HEADERS.Signature) == IMAGE_TE_SIGNATURE:
+            raise PEFormatError("Invalid NT Headers signature. Probably a TE file")
+        if self.NT_HEADERS.Signature != IMAGE_NT_SIGNATURE:
+            raise PEFormatError("Invalid NT Headers signature.")
+
+        self.FILE_HEADER = self.__unpack_data__(
+            self.__IMAGE_FILE_HEADER_format__,
+            self.__data__[nt_headers_offset + 4 : nt_headers_offset + 4 + 32],
+            file_offset=nt_headers_offset + 4,
+        )
+        image_flags = retrieve_flags(IMAGE_CHARACTERISTICS, "IMAGE_FILE_")
+
+        if not self.FILE_HEADER:
+            raise PEFormatError("File Header missing")
+
+        # Set the image's flags according the the Characteristics member
+        set_flags(self.FILE_HEADER, self.FILE_HEADER.Characteristics, image_flags)
+
+        optional_header_offset = nt_headers_offset + 4 + self.FILE_HEADER.sizeof()
+
+        # Note: location of sections can be controlled from PE header:
+        sections_offset = optional_header_offset + self.FILE_HEADER.SizeOfOptionalHeader
+
+        self.OPTIONAL_HEADER = self.__unpack_data__(
+            self.__IMAGE_OPTIONAL_HEADER_format__,
+            # Read up to 256 bytes to allow creating a copy of too much data
+            self.__data__[optional_header_offset : optional_header_offset + 256],
+            file_offset=optional_header_offset,
+        )
+
+        # According to solardesigner's findings for his
+        # Tiny PE project, the optional header does not
+        # need fields beyond "Subsystem" in order to be
+        # loadable by the Windows loader (given that zeros
+        # are acceptable values and the header is loaded
+        # in a zeroed memory page)
+        # If trying to parse a full Optional Header fails
+        # we try to parse it again with some 0 padding
+        #
+        MINIMUM_VALID_OPTIONAL_HEADER_RAW_SIZE = 69
+
+        if (
+            self.OPTIONAL_HEADER is None
+            and len(
+                self.__data__[optional_header_offset : optional_header_offset + 0x200]
+            )
+            >= MINIMUM_VALID_OPTIONAL_HEADER_RAW_SIZE
+        ):
+
+            # Add enough zeros to make up for the unused fields
+            #
+            padding_length = 128
+
+            # Create padding
+            #
+            padded_data = self.__data__[
+                optional_header_offset : optional_header_offset + 0x200
+            ] + (b"\0" * padding_length)
+
+            self.OPTIONAL_HEADER = self.__unpack_data__(
+                self.__IMAGE_OPTIONAL_HEADER_format__,
+                padded_data,
+                file_offset=optional_header_offset,
+            )
+
+        # Check the Magic in the OPTIONAL_HEADER and set the PE file
+        # type accordingly
+        #
+        if self.OPTIONAL_HEADER is not None:
+
+            if self.OPTIONAL_HEADER.Magic == OPTIONAL_HEADER_MAGIC_PE:
+
+                self.PE_TYPE = OPTIONAL_HEADER_MAGIC_PE
+
+            elif self.OPTIONAL_HEADER.Magic == OPTIONAL_HEADER_MAGIC_PE_PLUS:
+
+                self.PE_TYPE = OPTIONAL_HEADER_MAGIC_PE_PLUS
+
+                self.OPTIONAL_HEADER = self.__unpack_data__(
+                    self.__IMAGE_OPTIONAL_HEADER64_format__,
+                    self.__data__[
+                        optional_header_offset : optional_header_offset + 0x200
+                    ],
+                    file_offset=optional_header_offset,
+                )
+
+                # Again, as explained above, we try to parse
+                # a reduced form of the Optional Header which
+                # is still valid despite not including all
+                # structure members
+                #
+                MINIMUM_VALID_OPTIONAL_HEADER_RAW_SIZE = 69 + 4
+
+                if (
+                    self.OPTIONAL_HEADER is None
+                    and len(
+                        self.__data__[
+                            optional_header_offset : optional_header_offset + 0x200
+                        ]
+                    )
+                    >= MINIMUM_VALID_OPTIONAL_HEADER_RAW_SIZE
+                ):
+
+                    padding_length = 128
+                    padded_data = self.__data__[
+                        optional_header_offset : optional_header_offset + 0x200
+                    ] + (b"\0" * padding_length)
+                    self.OPTIONAL_HEADER = self.__unpack_data__(
+                        self.__IMAGE_OPTIONAL_HEADER64_format__,
+                        padded_data,
+                        file_offset=optional_header_offset,
+                    )
+
+        if not self.FILE_HEADER:
+            raise PEFormatError("File Header missing")
+
+        # OC Patch:
+        # Die gracefully if there is no OPTIONAL_HEADER field
+        # 975440f5ad5e2e4a92c4d9a5f22f75c1
+        if self.OPTIONAL_HEADER is None:
+            raise PEFormatError("No Optional Header found, invalid PE32 or PE32+ file.")
+        if self.PE_TYPE is None:
+            self.__warnings.append(
+                "Invalid type 0x{0:04x} in Optional Header.".format(
+                    self.OPTIONAL_HEADER.Magic
+                )
+            )
+
+        dll_characteristics_flags = retrieve_flags(
+            DLL_CHARACTERISTICS, "IMAGE_DLLCHARACTERISTICS_"
+        )
+
+        # Set the Dll Characteristics flags according the the DllCharacteristics member
+        set_flags(
+            self.OPTIONAL_HEADER,
+            self.OPTIONAL_HEADER.DllCharacteristics,
+            dll_characteristics_flags,
+        )
+
+        self.OPTIONAL_HEADER.DATA_DIRECTORY = []
+        # offset = (optional_header_offset + self.FILE_HEADER.SizeOfOptionalHeader)
+        offset = optional_header_offset + self.OPTIONAL_HEADER.sizeof()
+
+        self.NT_HEADERS.FILE_HEADER = self.FILE_HEADER
+        self.NT_HEADERS.OPTIONAL_HEADER = self.OPTIONAL_HEADER
+
+        # Windows 8 specific check
+        #
+        if (
+            self.OPTIONAL_HEADER.AddressOfEntryPoint
+            < self.OPTIONAL_HEADER.SizeOfHeaders
+        ):
+            self.__warnings.append(
+                "SizeOfHeaders is smaller than AddressOfEntryPoint: this file "
+                "cannot run under Windows 8."
+            )
+
+        # The NumberOfRvaAndSizes is sanitized to stay within
+        # reasonable limits so can be casted to an int
+        #
+        if self.OPTIONAL_HEADER.NumberOfRvaAndSizes > 0x10:
+            self.__warnings.append(
+                "Suspicious NumberOfRvaAndSizes in the Optional Header. "
+                "Normal values are never larger than 0x10, the value is: 0x%x"
+                % self.OPTIONAL_HEADER.NumberOfRvaAndSizes
+            )
+
+        MAX_ASSUMED_VALID_NUMBER_OF_RVA_AND_SIZES = 0x100
+        for i in range(int(0x7FFFFFFF & self.OPTIONAL_HEADER.NumberOfRvaAndSizes)):
+
+            if len(self.__data__) - offset == 0:
+                break
+
+            if len(self.__data__) - offset < 8:
+                data = self.__data__[offset:] + b"\0" * 8
+            else:
+                data = self.__data__[
+                    offset : offset + MAX_ASSUMED_VALID_NUMBER_OF_RVA_AND_SIZES
+                ]
+
+            dir_entry = self.__unpack_data__(
+                self.__IMAGE_DATA_DIRECTORY_format__, data, file_offset=offset
+            )
+
+            if dir_entry is None:
+                break
+
+            # Would fail if missing an entry
+            # 1d4937b2fa4d84ad1bce0309857e70ca offending sample
+            try:
+                dir_entry.name = DIRECTORY_ENTRY[i]
+            except (KeyError, AttributeError):
+                break
+
+            offset += dir_entry.sizeof()
+
+            self.OPTIONAL_HEADER.DATA_DIRECTORY.append(dir_entry)
+
+            # If the offset goes outside the optional header,
+            # the loop is broken, regardless of how many directories
+            # NumberOfRvaAndSizes says there are
+            #
+            # We assume a normally sized optional header, hence that we do
+            # a sizeof() instead of reading SizeOfOptionalHeader.
+            # Then we add a default number of directories times their size,
+            # if we go beyond that, we assume the number of directories
+            # is wrong and stop processing
+            if offset >= (
+                optional_header_offset + self.OPTIONAL_HEADER.sizeof() + 8 * 16
+            ):
+
+                break
+
+        offset = self.parse_sections(sections_offset)
+
+        # OC Patch:
+        # There could be a problem if there are no raw data sections
+        # greater than 0
+        # fc91013eb72529da005110a3403541b6 example
+        # Should this throw an exception in the minimum header offset
+        # can't be found?
+        #
+        rawDataPointers = [
+            self.adjust_FileAlignment(
+                s.PointerToRawData, self.OPTIONAL_HEADER.FileAlignment
+            )
+            for s in self.sections
+            if s.PointerToRawData > 0
+        ]
+
+        if len(rawDataPointers) > 0:
+            lowest_section_offset = min(rawDataPointers)
+        else:
+            lowest_section_offset = None
+
+        if not lowest_section_offset or lowest_section_offset < offset:
+            self.header = self.__data__[:offset]
+        else:
+            self.header = self.__data__[:lowest_section_offset]
+
+        # Check whether the entry point lies within a section
+        #
+        if (
+            self.get_section_by_rva(self.OPTIONAL_HEADER.AddressOfEntryPoint)
+            is not None
+        ):
+
+            # Check whether the entry point lies within the file
+            #
+            ep_offset = self.get_offset_from_rva(
+                self.OPTIONAL_HEADER.AddressOfEntryPoint
+            )
+            if ep_offset > len(self.__data__):
+
+                self.__warnings.append(
+                    "Possibly corrupt file. AddressOfEntryPoint lies outside the"
+                    " file. AddressOfEntryPoint: 0x%x"
+                    % self.OPTIONAL_HEADER.AddressOfEntryPoint
+                )
+
+        else:
+
+            self.__warnings.append(
+                "AddressOfEntryPoint lies outside the sections' boundaries. "
+                "AddressOfEntryPoint: 0x%x" % self.OPTIONAL_HEADER.AddressOfEntryPoint
+            )
+
+        if not fast_load:
+            self.full_load()
+
+    def parse_rich_header(self):
+        """Parses the rich header
+        see http://www.ntcore.com/files/richsign.htm for more information
+
+        Structure:
+        00 DanS ^ checksum, checksum, checksum, checksum
+        10 Symbol RVA ^ checksum, Symbol size ^ checksum...
+        ...
+        XX Rich, checksum, 0, 0,...
+        """
+
+        # Rich Header constants
+        #
+        DANS = 0x536E6144  # 'DanS' as dword
+        RICH = 0x68636952  # 'Rich' as dword
+
+        rich_index = self.__data__.find(
+            b"Rich", 0x80, self.OPTIONAL_HEADER.get_file_offset()
+        )
+        if rich_index == -1:
+            return None
+
+        # Read a block of data
+        try:
+            # The end of the structure is 8 bytes after the start of the Rich
+            # string.
+            rich_data = self.__data__[0x80 : rich_index + 8]
+            # Make the data have length a multiple of 4, otherwise the
+            # subsequent parsing will fail. It's not impossible that we retrieve
+            # truncated data that it's not a multiple.
+            rich_data = rich_data[: 4 * int(len(rich_data) / 4)]
+            data = list(
+                struct.unpack("<{0}I".format(int(len(rich_data) / 4)), rich_data)
+            )
+            if RICH not in data:
+                return None
+        except PEFormatError:
+            return None
+
+        # get key, raw_data and clear_data
+        key = struct.pack("", warning)
+
+    def full_load(self):
+        """Process the data directories.
+
+        This method will load the data directories which might not have
+        been loaded if the "fast_load" option was used.
+        """
+
+        self.parse_data_directories()
+
+        class RichHeader:
+            pass
+
+        rich_header = self.parse_rich_header()
+        if rich_header:
+            self.RICH_HEADER = RichHeader()
+            self.RICH_HEADER.checksum = rich_header.get("checksum", None)
+            self.RICH_HEADER.values = rich_header.get("values", None)
+            self.RICH_HEADER.key = rich_header.get("key", None)
+            self.RICH_HEADER.raw_data = rich_header.get("raw_data", None)
+            self.RICH_HEADER.clear_data = rich_header.get("clear_data", None)
+        else:
+            self.RICH_HEADER = None
+
+    def write(self, filename=None):
+        """Write the PE file.
+
+        This function will process all headers and components
+        of the PE file and include all changes made (by just
+        assigning to attributes in the PE objects) and write
+        the changes back to a file whose name is provided as
+        an argument. The filename is optional, if not
+        provided the data will be returned as a 'str' object.
+        """
+
+        file_data = bytearray(self.__data__)
+
+        for structure in self.__structures__:
+            struct_data = bytearray(structure.__pack__())
+            offset = structure.get_file_offset()
+            file_data[offset : offset + len(struct_data)] = struct_data
+
+        if hasattr(self, "VS_VERSIONINFO"):
+            if hasattr(self, "FileInfo"):
+                for finfo in self.FileInfo:
+                    for entry in finfo:
+                        if hasattr(entry, "StringTable"):
+                            for st_entry in entry.StringTable:
+                                for key, entry in list(st_entry.entries.items()):
+
+                                    # Offsets and lengths of the keys and values.
+                                    # Each value in the dictionary is a tuple:
+                                    #  (key length, value length)
+                                    # The lengths are in characters, not in bytes.
+                                    offsets = st_entry.entries_offsets[key]
+                                    lengths = st_entry.entries_lengths[key]
+
+                                    if len(entry) > lengths[1]:
+                                        l = entry.decode("utf-8").encode("utf-16le")
+                                        file_data[
+                                            offsets[1] : offsets[1] + lengths[1] * 2
+                                        ] = l[: lengths[1] * 2]
+                                    else:
+                                        encoded_data = entry.decode("utf-8").encode(
+                                            "utf-16le"
+                                        )
+                                        file_data[
+                                            offsets[1] : offsets[1] + len(encoded_data)
+                                        ] = encoded_data
+
+        new_file_data = file_data
+        if not filename:
+            return new_file_data
+
+        f = open(filename, "wb+")
+        f.write(new_file_data)
+        f.close()
+        return
+
+    def parse_sections(self, offset):
+        """Fetch the PE file sections.
+
+        The sections will be readily available in the "sections" attribute.
+        Its attributes will contain all the section information plus "data"
+        a buffer containing the section's data.
+
+        The "Characteristics" member will be processed and attributes
+        representing the section characteristics (with the 'IMAGE_SCN_'
+        string trimmed from the constant's names) will be added to the
+        section instance.
+
+        Refer to the SectionStructure class for additional info.
+        """
+
+        self.sections = []
+        MAX_SIMULTANEOUS_ERRORS = 3
+        for i in range(self.FILE_HEADER.NumberOfSections):
+            if i >= MAX_SECTIONS:
+                self.__warnings.append(
+                    "Too many sections {0} (>={1})".format(
+                        self.FILE_HEADER.NumberOfSections, MAX_SECTIONS
+                    )
+                )
+                break
+            simultaneous_errors = 0
+            section = SectionStructure(self.__IMAGE_SECTION_HEADER_format__, pe=self)
+            if not section:
+                break
+            section_offset = offset + section.sizeof() * i
+            section.set_file_offset(section_offset)
+            section_data = self.__data__[
+                section_offset : section_offset + section.sizeof()
+            ]
+            # Check if the section is all nulls and stop if so.
+            if count_zeroes(section_data) == section.sizeof():
+                self.__warnings.append(f"Invalid section {i}. Contents are null-bytes.")
+                break
+            if not section_data:
+                self.__warnings.append(
+                    f"Invalid section {i}. No data in the file (is this corkami's "
+                    "virtsectblXP?)."
+                )
+                break
+            section.__unpack__(section_data)
+            self.__structures__.append(section)
+
+            if section.SizeOfRawData + section.PointerToRawData > len(self.__data__):
+                simultaneous_errors += 1
+                self.__warnings.append(
+                    f"Error parsing section {i}. SizeOfRawData is larger than file."
+                )
+
+            if self.adjust_FileAlignment(
+                section.PointerToRawData, self.OPTIONAL_HEADER.FileAlignment
+            ) > len(self.__data__):
+                simultaneous_errors += 1
+                self.__warnings.append(
+                    f"Error parsing section {i}. PointerToRawData points beyond "
+                    "the end of the file."
+                )
+
+            if section.Misc_VirtualSize > 0x10000000:
+                simultaneous_errors += 1
+                self.__warnings.append(
+                    f"Suspicious value found parsing section {i}. VirtualSize is "
+                    "extremely large > 256MiB."
+                )
+
+            if (
+                self.adjust_SectionAlignment(
+                    section.VirtualAddress,
+                    self.OPTIONAL_HEADER.SectionAlignment,
+                    self.OPTIONAL_HEADER.FileAlignment,
+                )
+                > 0x10000000
+            ):
+                simultaneous_errors += 1
+                self.__warnings.append(
+                    f"Suspicious value found parsing section {i}. VirtualAddress is "
+                    "beyond 0x10000000."
+                )
+
+            if (
+                self.OPTIONAL_HEADER.FileAlignment != 0
+                and (section.PointerToRawData % self.OPTIONAL_HEADER.FileAlignment) != 0
+            ):
+                simultaneous_errors += 1
+                self.__warnings.append(
+                    (
+                        f"Error parsing section {i}. "
+                        "PointerToRawData should normally be "
+                        "a multiple of FileAlignment, this might imply the file "
+                        "is trying to confuse tools which parse this incorrectly."
+                    )
+                )
+
+            if simultaneous_errors >= MAX_SIMULTANEOUS_ERRORS:
+                self.__warnings.append("Too many warnings parsing section. Aborting.")
+                break
+
+            section_flags = retrieve_flags(SECTION_CHARACTERISTICS, "IMAGE_SCN_")
+
+            # Set the section's flags according the the Characteristics member
+            set_flags(section, section.Characteristics, section_flags)
+
+            if section.__dict__.get(
+                "IMAGE_SCN_MEM_WRITE", False
+            ) and section.__dict__.get("IMAGE_SCN_MEM_EXECUTE", False):
+
+                if section.Name.rstrip(b"\x00") == b"PAGE" and self.is_driver():
+                    # Drivers can have a PAGE section with those flags set without
+                    # implying that it is malicious
+                    pass
+                else:
+                    self.__warnings.append(
+                        f"Suspicious flags set for section {i}. "
+                        "Both IMAGE_SCN_MEM_WRITE and IMAGE_SCN_MEM_EXECUTE are set. "
+                        "This might indicate a packed executable."
+                    )
+
+            self.sections.append(section)
+
+        # Sort the sections by their VirtualAddress and add a field to each of them
+        # with the VirtualAddress of the next section. This will allow to check
+        # for potentially overlapping sections in badly constructed PEs.
+        self.sections.sort(key=lambda a: a.VirtualAddress)
+        for idx, section in enumerate(self.sections):
+            if idx == len(self.sections) - 1:
+                section.next_section_virtual_address = None
+            else:
+                section.next_section_virtual_address = self.sections[
+                    idx + 1
+                ].VirtualAddress
+
+        if self.FILE_HEADER.NumberOfSections > 0 and self.sections:
+            return (
+                offset + self.sections[0].sizeof() * self.FILE_HEADER.NumberOfSections
+            )
+        else:
+            return offset
+
+    def parse_data_directories(
+        self, directories=None, forwarded_exports_only=False, import_dllnames_only=False
+    ):
+        """Parse and process the PE file's data directories.
+
+        If the optional argument 'directories' is given, only
+        the directories at the specified indexes will be parsed.
+        Such functionality allows parsing of areas of interest
+        without the burden of having to parse all others.
+        The directories can then be specified as:
+
+        For export / import only:
+
+          directories = [ 0, 1 ]
+
+        or (more verbosely):
+
+          directories = [ DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_IMPORT'],
+            DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_EXPORT'] ]
+
+        If 'directories' is a list, the ones that are processed will be removed,
+        leaving only the ones that are not present in the image.
+
+        If `forwarded_exports_only` is True, the IMAGE_DIRECTORY_ENTRY_EXPORT
+        attribute will only contain exports that are forwarded to another DLL.
+
+        If `import_dllnames_only` is True, symbols will not be parsed from
+        the import table and the entries in the IMAGE_DIRECTORY_ENTRY_IMPORT
+        attribute will not have a `symbols` attribute.
+        """
+
+        directory_parsing = (
+            ("IMAGE_DIRECTORY_ENTRY_IMPORT", self.parse_import_directory),
+            ("IMAGE_DIRECTORY_ENTRY_EXPORT", self.parse_export_directory),
+            ("IMAGE_DIRECTORY_ENTRY_RESOURCE", self.parse_resources_directory),
+            ("IMAGE_DIRECTORY_ENTRY_DEBUG", self.parse_debug_directory),
+            ("IMAGE_DIRECTORY_ENTRY_BASERELOC", self.parse_relocations_directory),
+            ("IMAGE_DIRECTORY_ENTRY_TLS", self.parse_directory_tls),
+            ("IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG", self.parse_directory_load_config),
+            ("IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT", self.parse_delay_import_directory),
+            ("IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT", self.parse_directory_bound_imports),
+            ("IMAGE_DIRECTORY_ENTRY_EXCEPTION", self.parse_exceptions_directory),
+        )
+
+        if directories is not None:
+            if not isinstance(directories, (tuple, list)):
+                directories = [directories]
+
+        for entry in directory_parsing:
+            # OC Patch:
+            #
+            try:
+                directory_index = DIRECTORY_ENTRY[entry[0]]
+                dir_entry = self.OPTIONAL_HEADER.DATA_DIRECTORY[directory_index]
+            except IndexError:
+                break
+
+            # Only process all the directories if no individual ones have
+            # been chosen
+            #
+            if directories is None or directory_index in directories:
+
+                value = None
+                if dir_entry.VirtualAddress:
+                    if (
+                        forwarded_exports_only
+                        and entry[0] == "IMAGE_DIRECTORY_ENTRY_EXPORT"
+                    ):
+                        value = entry[1](
+                            dir_entry.VirtualAddress,
+                            dir_entry.Size,
+                            forwarded_only=True,
+                        )
+                    elif (
+                        import_dllnames_only
+                        and entry[0] == "IMAGE_DIRECTORY_ENTRY_IMPORT"
+                    ):
+                        value = entry[1](
+                            dir_entry.VirtualAddress, dir_entry.Size, dllnames_only=True
+                        )
+
+                    else:
+                        try:
+                            value = entry[1](dir_entry.VirtualAddress, dir_entry.Size)
+                        except PEFormatError as excp:
+                            self.__warnings.append(
+                                f'Failed to process directoty "{entry[0]}": {excp}'
+                            )
+                    if value:
+                        setattr(self, entry[0][6:], value)
+
+            if (
+                (directories is not None)
+                and isinstance(directories, list)
+                and (entry[0] in directories)
+            ):
+                directories.remove(directory_index)
+
+    def parse_exceptions_directory(self, rva, size):
+        """Parses exception directory
+
+        All the code related to handling exception directories is documented in
+        https://auscitte.github.io/systems%20blog/Exception-Directory-pefile#implementation-details
+        """
+
+        # "For x64 and Itanium platforms; the format is different for other platforms"
+        if (
+            self.FILE_HEADER.Machine != MACHINE_TYPE["IMAGE_FILE_MACHINE_AMD64"]
+            and self.FILE_HEADER.Machine != MACHINE_TYPE["IMAGE_FILE_MACHINE_IA64"]
+        ):
+            return None
+
+        rf = Structure(self.__RUNTIME_FUNCTION_format__)
+        rf_size = rf.sizeof()
+        rva2rt = {}
+        rt_funcs = []
+        rva2infos = {}
+        for _ in range(size // rf_size):
+            rf = self.__unpack_data__(
+                self.__RUNTIME_FUNCTION_format__,
+                self.get_data(rva, rf_size),
+                file_offset=self.get_offset_from_rva(rva),
+            )
+
+            if rf is None:
+                break
+
+            ui = None
+
+            if (rf.UnwindData & 0x1) == 0:
+                # according to "Improving Automated Analysis of Windows x64 Binaries",
+                # if the lowest bit is set, (UnwindData & ~0x1) should point to the
+                # chained RUNTIME_FUNCTION instead of UNWIND_INFO
+
+                if (
+                    rf.UnwindData in rva2infos
+                ):  # unwind info data structures can be shared among functions
+                    ui = rva2infos[rf.UnwindData]
+                else:
+                    ui = UnwindInfo(file_offset=self.get_offset_from_rva(rf.UnwindData))
+                    rva2infos[rf.UnwindData] = ui
+
+                ws = ui.unpack_in_stages(self.get_data(rf.UnwindData, ui.sizeof()))
+                if ws != None:
+                    self.__warnings.append(ws)
+                    break
+                ws = ui.unpack_in_stages(self.get_data(rf.UnwindData, ui.sizeof()))
+                if ws != None:
+                    self.__warnings.append(ws)
+                    break
+
+                self.__structures__.append(ui)
+
+            entry = ExceptionsDirEntryData(struct=rf, unwindinfo=ui)
+            rt_funcs.append(entry)
+
+            rva2rt[rf.BeginAddress] = entry
+            rva += rf_size
+
+        # each chained function entry holds a reference to the function first in chain
+        for rf in rt_funcs:
+            if rf.unwindinfo is None:
+                # TODO: have not encountered such a binary yet;
+                # in theory, (UnwindData & ~0x1) should point to the chained
+                # RUNTIME_FUNCTION which could be used to locate the corresponding
+                # ExceptionsDirEntryData and set_chained_function_entry()
+                continue
+            if not hasattr(rf.unwindinfo, "FunctionEntry"):
+                continue
+            if not rf.unwindinfo.FunctionEntry in rva2rt:
+                self.__warnings.append(
+                    f"FunctionEntry of UNWIND_INFO at {rf.struct.get_file_offset():x}"
+                    " points to an entry that does not exist"
+                )
+                continue
+            try:
+                rf.unwindinfo.set_chained_function_entry(
+                    rva2rt[rf.unwindinfo.FunctionEntry]
+                )
+            except PEFormatError as excp:
+                self.__warnings.append(
+                    "Failed parsing FunctionEntry of UNWIND_INFO at "
+                    f"{rf.struct.get_file_offset():x}: {excp}"
+                )
+                continue
+
+        return rt_funcs
+
+    def parse_directory_bound_imports(self, rva, size):
+        """"""
+
+        bnd_descr = Structure(self.__IMAGE_BOUND_IMPORT_DESCRIPTOR_format__)
+        bnd_descr_size = bnd_descr.sizeof()
+        start = rva
+
+        bound_imports = []
+        while True:
+            bnd_descr = self.__unpack_data__(
+                self.__IMAGE_BOUND_IMPORT_DESCRIPTOR_format__,
+                self.__data__[rva : rva + bnd_descr_size],
+                file_offset=rva,
+            )
+            if bnd_descr is None:
+                # If can't parse directory then silently return.
+                # This directory does not necessarily have to be valid to
+                # still have a valid PE file
+
+                self.__warnings.append(
+                    "The Bound Imports directory exists but can't be parsed."
+                )
+
+                return
+
+            if bnd_descr.all_zeroes():
+                break
+
+            rva += bnd_descr.sizeof()
+
+            section = self.get_section_by_offset(rva)
+            file_offset = self.get_offset_from_rva(rva)
+            if section is None:
+                safety_boundary = len(self.__data__) - file_offset
+                sections_after_offset = [
+                    s.PointerToRawData
+                    for s in self.sections
+                    if s.PointerToRawData > file_offset
+                ]
+                if sections_after_offset:
+                    # Find the first section starting at a later offset than that
+                    # specified by 'rva'
+                    first_section_after_offset = min(sections_after_offset)
+                    section = self.get_section_by_offset(first_section_after_offset)
+                    if section is not None:
+                        safety_boundary = section.PointerToRawData - file_offset
+            else:
+                safety_boundary = (
+                    section.PointerToRawData + len(section.get_data()) - file_offset
+                )
+            if not section:
+                self.__warnings.append(
+                    (
+                        "RVA of IMAGE_BOUND_IMPORT_DESCRIPTOR points "
+                        "to an invalid address: {0:x}"
+                    ).format(rva)
+                )
+                return
+
+            forwarder_refs = []
+            # 8 is the size of __IMAGE_BOUND_IMPORT_DESCRIPTOR_format__
+            for _ in range(
+                min(bnd_descr.NumberOfModuleForwarderRefs, int(safety_boundary / 8))
+            ):
+                # Both structures IMAGE_BOUND_IMPORT_DESCRIPTOR and
+                # IMAGE_BOUND_FORWARDER_REF have the same size.
+                bnd_frwd_ref = self.__unpack_data__(
+                    self.__IMAGE_BOUND_FORWARDER_REF_format__,
+                    self.__data__[rva : rva + bnd_descr_size],
+                    file_offset=rva,
+                )
+                # OC Patch:
+                if not bnd_frwd_ref:
+                    raise PEFormatError("IMAGE_BOUND_FORWARDER_REF cannot be read")
+                rva += bnd_frwd_ref.sizeof()
+
+                offset = start + bnd_frwd_ref.OffsetModuleName
+                name_str = self.get_string_from_data(
+                    0, self.__data__[offset : offset + MAX_STRING_LENGTH]
+                )
+
+                # OffsetModuleName points to a DLL name. These shouldn't be too long.
+                # Anything longer than a safety length of 128 will be taken to indicate
+                # a corrupt entry and abort the processing of these entries.
+                # Names shorter than 4 characters will be taken as invalid as well.
+
+                if name_str:
+                    invalid_chars = [
+                        c for c in bytearray(name_str) if chr(c) not in string.printable
+                    ]
+                    if len(name_str) > 256 or invalid_chars:
+                        break
+
+                forwarder_refs.append(
+                    BoundImportRefData(struct=bnd_frwd_ref, name=name_str)
+                )
+
+            offset = start + bnd_descr.OffsetModuleName
+            name_str = self.get_string_from_data(
+                0, self.__data__[offset : offset + MAX_STRING_LENGTH]
+            )
+
+            if name_str:
+                invalid_chars = [
+                    c for c in bytearray(name_str) if chr(c) not in string.printable
+                ]
+                if len(name_str) > 256 or invalid_chars:
+                    break
+
+            if not name_str:
+                break
+            bound_imports.append(
+                BoundImportDescData(
+                    struct=bnd_descr, name=name_str, entries=forwarder_refs
+                )
+            )
+
+        return bound_imports
+
+    def parse_directory_tls(self, rva, size):
+        """"""
+
+        # By default let's pretend the format is a 32-bit PE. It may help
+        # produce some output for files where the Magic in the Optional Header
+        # is incorrect.
+        format = self.__IMAGE_TLS_DIRECTORY_format__
+
+        if self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE_PLUS:
+            format = self.__IMAGE_TLS_DIRECTORY64_format__
+
+        try:
+            tls_struct = self.__unpack_data__(
+                format,
+                self.get_data(rva, Structure(format).sizeof()),
+                file_offset=self.get_offset_from_rva(rva),
+            )
+        except PEFormatError:
+            self.__warnings.append(
+                "Invalid TLS information. Can't read " "data at RVA: 0x%x" % rva
+            )
+            tls_struct = None
+
+        if not tls_struct:
+            return None
+
+        return TlsData(struct=tls_struct)
+
+    def parse_directory_load_config(self, rva, size):
+        """"""
+
+        if self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE:
+            load_config_dir_sz = self.get_dword_at_rva(rva)
+            format = self.__IMAGE_LOAD_CONFIG_DIRECTORY_format__
+        elif self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE_PLUS:
+            load_config_dir_sz = self.get_dword_at_rva(rva)
+            format = self.__IMAGE_LOAD_CONFIG_DIRECTORY64_format__
+        else:
+            self.__warnings.append(
+                "Don't know how to parse LOAD_CONFIG information for non-PE32/"
+                "PE32+ file"
+            )
+            return None
+
+        # load config directory size can be less than represented by 'format' variable,
+        # generate truncated format which correspond load config directory size
+        fields_counter = 0
+        cumulative_sz = 0
+        for field in format[1]:
+            fields_counter += 1
+            cumulative_sz += STRUCT_SIZEOF_TYPES[field.split(",")[0]]
+            if cumulative_sz == load_config_dir_sz:
+                break
+        format = (format[0], format[1][:fields_counter])
+
+        load_config_struct = None
+        try:
+            load_config_struct = self.__unpack_data__(
+                format,
+                self.get_data(rva, Structure(format).sizeof()),
+                file_offset=self.get_offset_from_rva(rva),
+            )
+        except PEFormatError:
+            self.__warnings.append(
+                "Invalid LOAD_CONFIG information. Can't read " "data at RVA: 0x%x" % rva
+            )
+
+        if not load_config_struct:
+            return None
+
+        dynamic_relocations = None
+        if fields_counter > 35:
+            dynamic_relocations = self.parse_dynamic_relocations(
+                load_config_struct.DynamicValueRelocTableOffset,
+                load_config_struct.DynamicValueRelocTableSection,
+            )
+
+        return LoadConfigData(
+            struct=load_config_struct, dynamic_relocations=dynamic_relocations
+        )
+
+    def parse_dynamic_relocations(
+        self, dynamic_value_reloc_table_offset, dynamic_value_reloc_table_section
+    ):
+        if not dynamic_value_reloc_table_offset:
+            return None
+        if not dynamic_value_reloc_table_section:
+            return None
+
+        if dynamic_value_reloc_table_section > len(self.sections):
+            return None
+
+        section = self.sections[dynamic_value_reloc_table_section - 1]
+        rva = section.VirtualAddress + dynamic_value_reloc_table_offset
+        image_dynamic_reloc_table_struct = None
+        reloc_table_size = Structure(
+            self.__IMAGE_DYNAMIC_RELOCATION_TABLE_format__
+        ).sizeof()
+        try:
+            image_dynamic_reloc_table_struct = self.__unpack_data__(
+                self.__IMAGE_DYNAMIC_RELOCATION_TABLE_format__,
+                self.get_data(rva, reloc_table_size),
+                file_offset=self.get_offset_from_rva(rva),
+            )
+        except PEFormatError:
+            self.__warnings.append(
+                "Invalid IMAGE_DYNAMIC_RELOCATION_TABLE information. Can't read "
+                "data at RVA: 0x%x" % rva
+            )
+
+        if image_dynamic_reloc_table_struct.Version != 1:
+            self.__warnings.append(
+                "No pasring available for IMAGE_DYNAMIC_RELOCATION_TABLE.Version = %d",
+                image_dynamic_reloc_table_struct.Version,
+            )
+            return None
+
+        rva += reloc_table_size
+        end = rva + image_dynamic_reloc_table_struct.Size
+        dynamic_relocations = []
+
+        while rva < end:
+            format = self.__IMAGE_DYNAMIC_RELOCATION_format__
+
+            if self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE_PLUS:
+                format = self.__IMAGE_DYNAMIC_RELOCATION64_format__
+
+            rlc_size = Structure(format).sizeof()
+
+            try:
+                dynamic_rlc = self.__unpack_data__(
+                    format,
+                    self.get_data(rva, rlc_size),
+                    file_offset=self.get_offset_from_rva(rva),
+                )
+            except PEFormatError:
+                self.__warnings.append(
+                    "Invalid relocation information. Can't read "
+                    "data at RVA: 0x%x" % rva
+                )
+                dynamic_rlc = None
+
+            if not dynamic_rlc:
+                break
+
+            rva += rlc_size
+            symbol = dynamic_rlc.Symbol
+            size = dynamic_rlc.BaseRelocSize
+
+            if 3 <= symbol <= 5:
+                relocations = self.parse_image_base_relocation_list(
+                    rva, size, self.dynamic_relocation_format_by_symbol[symbol]
+                )
+                dynamic_relocations.append(
+                    DynamicRelocationData(
+                        struct=dynamic_rlc, symbol=symbol, relocations=relocations
+                    )
+                )
+
+            if symbol > 5:
+                relocations = self.parse_image_base_relocation_list(rva, size)
+                dynamic_relocations.append(
+                    DynamicRelocationData(
+                        struct=dynamic_rlc, symbol=symbol, relocations=relocations
+                    )
+                )
+
+            rva += size
+
+        return dynamic_relocations
+
+    def parse_relocations_directory(self, rva, size):
+        """"""
+
+        return self.parse_image_base_relocation_list(rva, size)
+
+    def parse_image_base_relocation_list(self, rva, size, fmt=None):
+        rlc_size = Structure(self.__IMAGE_BASE_RELOCATION_format__).sizeof()
+        end = rva + size
+
+        relocations = []
+        while rva < end:
+
+            # OC Patch:
+            # Malware that has bad RVA entries will cause an error.
+            # Just continue on after an exception
+            #
+            try:
+                rlc = self.__unpack_data__(
+                    self.__IMAGE_BASE_RELOCATION_format__,
+                    self.get_data(rva, rlc_size),
+                    file_offset=self.get_offset_from_rva(rva),
+                )
+            except PEFormatError:
+                self.__warnings.append(
+                    "Invalid relocation information. Can't read "
+                    "data at RVA: 0x%x" % rva
+                )
+                rlc = None
+
+            if not rlc:
+                break
+
+            # rlc.VirtualAddress must lie within the Image
+            if rlc.VirtualAddress > self.OPTIONAL_HEADER.SizeOfImage:
+                self.__warnings.append(
+                    "Invalid relocation information. VirtualAddress outside"
+                    " of Image: 0x%x" % rlc.VirtualAddress
+                )
+                break
+
+            # rlc.SizeOfBlock must be less or equal than the size of the image
+            # (It's a rather loose sanity test)
+            if rlc.SizeOfBlock > self.OPTIONAL_HEADER.SizeOfImage:
+                self.__warnings.append(
+                    "Invalid relocation information. SizeOfBlock too large"
+                    ": %d" % rlc.SizeOfBlock
+                )
+                break
+
+            if fmt is None:
+                reloc_entries = self.parse_relocations(
+                    rva + rlc_size, rlc.VirtualAddress, rlc.SizeOfBlock - rlc_size
+                )
+            else:
+                reloc_entries = self.parse_relocations_with_format(
+                    rva + rlc_size, rlc.VirtualAddress, rlc.SizeOfBlock - rlc_size, fmt
+                )
+
+            relocations.append(BaseRelocationData(struct=rlc, entries=reloc_entries))
+
+            if not rlc.SizeOfBlock:
+                break
+            rva += rlc.SizeOfBlock
+
+        return relocations
+
+    def parse_relocations(self, data_rva, rva, size):
+        """"""
+
+        try:
+            data = self.get_data(data_rva, size)
+            file_offset = self.get_offset_from_rva(data_rva)
+        except PEFormatError:
+            self.__warnings.append(f"Bad RVA in relocation data: 0x{data_rva:x}")
+            return []
+
+        entries = []
+        offsets_and_type = set()
+        for idx in range(int(len(data) / 2)):
+
+            entry = self.__unpack_data__(
+                self.__IMAGE_BASE_RELOCATION_ENTRY_format__,
+                data[idx * 2 : (idx + 1) * 2],
+                file_offset=file_offset,
+            )
+
+            if not entry:
+                break
+            word = entry.Data
+
+            reloc_type = word >> 12
+            reloc_offset = word & 0x0FFF
+            if (reloc_offset, reloc_type) in offsets_and_type:
+                self.__warnings.append(
+                    "Overlapping offsets in relocation data "
+                    "at RVA: 0x%x" % (reloc_offset + rva)
+                )
+                break
+
+            offsets_and_type.add((reloc_offset, reloc_type))
+
+            entries.append(
+                RelocationData(
+                    struct=entry, type=reloc_type, base_rva=rva, rva=reloc_offset + rva
+                )
+            )
+            file_offset += entry.sizeof()
+
+        return entries
+
+    def parse_relocations_with_format(self, data_rva, rva, size, format):
+        """"""
+
+        try:
+            data = self.get_data(data_rva, size)
+            file_offset = self.get_offset_from_rva(data_rva)
+        except PEFormatError:
+            self.__warnings.append(f"Bad RVA in relocation data: 0x{data_rva:x}")
+            return []
+
+        entry_size = StructureWithBitfields(format).sizeof()
+        entries = []
+        offsets = set()
+        for idx in range(int(len(data) / entry_size)):
+
+            entry = self.__unpack_data_with_bitfields__(
+                format,
+                data[idx * entry_size : (idx + 1) * entry_size],
+                file_offset=file_offset,
+            )
+
+            if not entry:
+                break
+
+            reloc_offset = entry.PageRelativeOffset
+            if reloc_offset in offsets:
+                self.__warnings.append(
+                    "Overlapping offsets in relocation data "
+                    "at RVA: 0x%x" % (reloc_offset + rva)
+                )
+                break
+            offsets.add(reloc_offset)
+
+            entries.append(
+                RelocationData(struct=entry, base_rva=rva, rva=reloc_offset + rva)
+            )
+            file_offset += entry_size
+
+        return entries
+
+    def parse_debug_directory(self, rva, size):
+        """"""
+
+        dbg_size = Structure(self.__IMAGE_DEBUG_DIRECTORY_format__).sizeof()
+
+        debug = []
+        for idx in range(int(size / dbg_size)):
+            try:
+                data = self.get_data(rva + dbg_size * idx, dbg_size)
+            except PEFormatError:
+                self.__warnings.append(
+                    "Invalid debug information. Can't read " "data at RVA: 0x%x" % rva
+                )
+                return None
+
+            dbg = self.__unpack_data__(
+                self.__IMAGE_DEBUG_DIRECTORY_format__,
+                data,
+                file_offset=self.get_offset_from_rva(rva + dbg_size * idx),
+            )
+
+            if not dbg:
+                return None
+
+            # apply structure according to DEBUG_TYPE
+            # http://www.debuginfo.com/articles/debuginfomatch.html
+            #
+            dbg_type = None
+
+            if dbg.Type == 1:
+                # IMAGE_DEBUG_TYPE_COFF
+                pass
+
+            elif dbg.Type == 2:
+                # if IMAGE_DEBUG_TYPE_CODEVIEW
+                dbg_type_offset = dbg.PointerToRawData
+                dbg_type_size = dbg.SizeOfData
+                dbg_type_data = self.__data__[
+                    dbg_type_offset : dbg_type_offset + dbg_type_size
+                ]
+
+                if dbg_type_data[:4] == b"RSDS":
+                    # pdb7.0
+                    __CV_INFO_PDB70_format__ = [
+                        "CV_INFO_PDB70",
+                        [
+                            "4s,CvSignature",
+                            "I,Signature_Data1",  # Signature is of GUID type
+                            "H,Signature_Data2",
+                            "H,Signature_Data3",
+                            "B,Signature_Data4",
+                            "B,Signature_Data5",
+                            "6s,Signature_Data6",
+                            "I,Age",
+                        ],
+                    ]
+                    pdbFileName_size = (
+                        dbg_type_size - Structure(__CV_INFO_PDB70_format__).sizeof()
+                    )
+
+                    # pdbFileName_size can be negative here, as seen in the malware
+                    # sample with hash
+                    # MD5: 7c297600870d026c014d42596bb9b5fd
+                    # SHA256:
+                    #   83f4e63681fcba8a9d7bbb1688c71981b1837446514a1773597e0192bba9fac3
+                    # Checking for positive size here to ensure proper parsing.
+                    if pdbFileName_size > 0:
+                        __CV_INFO_PDB70_format__[1].append(
+                            "{0}s,PdbFileName".format(pdbFileName_size)
+                        )
+                    dbg_type = self.__unpack_data__(
+                        __CV_INFO_PDB70_format__, dbg_type_data, dbg_type_offset
+                    )
+                    if dbg_type is not None:
+                        dbg_type.Signature_Data6_value = struct.unpack(
+                            ">Q", b"\0\0" + dbg_type.Signature_Data6
+                        )[0]
+                        dbg_type.Signature_String = (
+                            str(
+                                uuid.UUID(
+                                    fields=(
+                                        dbg_type.Signature_Data1,
+                                        dbg_type.Signature_Data2,
+                                        dbg_type.Signature_Data3,
+                                        dbg_type.Signature_Data4,
+                                        dbg_type.Signature_Data5,
+                                        dbg_type.Signature_Data6_value,
+                                    )
+                                )
+                            )
+                            .replace("-", "")
+                            .upper()
+                            + f"{dbg_type.Age:X}"
+                        )
+
+                elif dbg_type_data[:4] == b"NB10":
+                    # pdb2.0
+                    __CV_INFO_PDB20_format__ = [
+                        "CV_INFO_PDB20",
+                        [
+                            "I,CvHeaderSignature",
+                            "I,CvHeaderOffset",
+                            "I,Signature",
+                            "I,Age",
+                        ],
+                    ]
+                    pdbFileName_size = (
+                        dbg_type_size - Structure(__CV_INFO_PDB20_format__).sizeof()
+                    )
+
+                    # As with the PDB 7.0 case, ensuring a positive size for
+                    # pdbFileName_size to ensure proper parsing.
+                    if pdbFileName_size > 0:
+                        # Add the last variable-length string field.
+                        __CV_INFO_PDB20_format__[1].append(
+                            "{0}s,PdbFileName".format(pdbFileName_size)
+                        )
+                    dbg_type = self.__unpack_data__(
+                        __CV_INFO_PDB20_format__, dbg_type_data, dbg_type_offset
+                    )
+
+            elif dbg.Type == 4:
+                # IMAGE_DEBUG_TYPE_MISC
+                dbg_type_offset = dbg.PointerToRawData
+                dbg_type_size = dbg.SizeOfData
+                dbg_type_data = self.__data__[
+                    dbg_type_offset : dbg_type_offset + dbg_type_size
+                ]
+                ___IMAGE_DEBUG_MISC_format__ = [
+                    "IMAGE_DEBUG_MISC",
+                    [
+                        "I,DataType",
+                        "I,Length",
+                        "B,Unicode",
+                        "B,Reserved1",
+                        "H,Reserved2",
+                    ],
+                ]
+                dbg_type_partial = self.__unpack_data__(
+                    ___IMAGE_DEBUG_MISC_format__, dbg_type_data, dbg_type_offset
+                )
+
+                # Need to check that dbg_type_partial contains a correctly unpacked data
+                # structure, as the malware sample with the following hash
+                # MD5:    5e7d6707d693108de5a303045c17d95b
+                # SHA256:
+                #  5dd94a95025f3b6e3dd440d52f7c6d2964fdd1aa119e0ee92e38c7bf83829e5c
+                # contains a value of None for dbg_type_partial after unpacking,
+                # presumably due to a malformed DEBUG entry.
+                if dbg_type_partial:
+                    # The Unicode bool should be set to 0 or 1.
+                    if dbg_type_partial.Unicode in (0, 1):
+                        data_size = (
+                            dbg_type_size
+                            - Structure(___IMAGE_DEBUG_MISC_format__).sizeof()
+                        )
+
+                        # As with the PDB case, ensuring a positive size for data_size
+                        # here to ensure proper parsing.
+                        if data_size > 0:
+                            ___IMAGE_DEBUG_MISC_format__[1].append(
+                                "{0}s,Data".format(data_size)
+                            )
+                        dbg_type = self.__unpack_data__(
+                            ___IMAGE_DEBUG_MISC_format__, dbg_type_data, dbg_type_offset
+                        )
+
+            debug.append(DebugData(struct=dbg, entry=dbg_type))
+
+        return debug
+
+    def parse_resources_directory(self, rva, size=0, base_rva=None, level=0, dirs=None):
+        """Parse the resources directory.
+
+        Given the RVA of the resources directory, it will process all
+        its entries.
+
+        The root will have the corresponding member of its structure,
+        IMAGE_RESOURCE_DIRECTORY plus 'entries', a list of all the
+        entries in the directory.
+
+        Those entries will have, correspondingly, all the structure's
+        members (IMAGE_RESOURCE_DIRECTORY_ENTRY) and an additional one,
+        "directory", pointing to the IMAGE_RESOURCE_DIRECTORY structure
+        representing upper layers of the tree. This one will also have
+        an 'entries' attribute, pointing to the 3rd, and last, level.
+        Another directory with more entries. Those last entries will
+        have a new attribute (both 'leaf' or 'data_entry' can be used to
+        access it). This structure finally points to the resource data.
+        All the members of this structure, IMAGE_RESOURCE_DATA_ENTRY,
+        are available as its attributes.
+        """
+
+        # OC Patch:
+        if dirs is None:
+            dirs = [rva]
+
+        if base_rva is None:
+            base_rva = rva
+
+        if level > MAX_RESOURCE_DEPTH:
+            self.__warnings.append(
+                "Error parsing the resources directory. "
+                "Excessively nested table depth %d (>%s)" % (level, MAX_RESOURCE_DEPTH)
+            )
+            return None
+
+        try:
+            # If the RVA is invalid all would blow up. Some EXEs seem to be
+            # specially nasty and have an invalid RVA.
+            data = self.get_data(
+                rva, Structure(self.__IMAGE_RESOURCE_DIRECTORY_format__).sizeof()
+            )
+        except PEFormatError:
+            self.__warnings.append(
+                "Invalid resources directory. Can't read "
+                "directory data at RVA: 0x%x" % rva
+            )
+            return None
+
+        # Get the resource directory structure, that is, the header
+        # of the table preceding the actual entries
+        #
+        resource_dir = self.__unpack_data__(
+            self.__IMAGE_RESOURCE_DIRECTORY_format__,
+            data,
+            file_offset=self.get_offset_from_rva(rva),
+        )
+        if resource_dir is None:
+            # If we can't parse resources directory then silently return.
+            # This directory does not necessarily have to be valid to
+            # still have a valid PE file
+            self.__warnings.append(
+                "Invalid resources directory. Can't parse "
+                "directory data at RVA: 0x%x" % rva
+            )
+            return None
+
+        dir_entries = []
+
+        # Advance the RVA to the position immediately following the directory
+        # table header and pointing to the first entry in the table
+        #
+        rva += resource_dir.sizeof()
+
+        number_of_entries = (
+            resource_dir.NumberOfNamedEntries + resource_dir.NumberOfIdEntries
+        )
+
+        # Set a hard limit on the maximum reasonable number of entries
+        MAX_ALLOWED_ENTRIES = 4096
+        if number_of_entries > MAX_ALLOWED_ENTRIES:
+            self.__warnings.append(
+                "Error parsing the resources directory. "
+                "The directory contains %d entries (>%s)"
+                % (number_of_entries, MAX_ALLOWED_ENTRIES)
+            )
+            return None
+
+        self.__total_resource_entries_count += number_of_entries
+        if self.__total_resource_entries_count > MAX_RESOURCE_ENTRIES:
+            self.__warnings.append(
+                "Error parsing the resources directory. "
+                "The file contains at least %d entries (>%d)"
+                % (self.__total_resource_entries_count, MAX_RESOURCE_ENTRIES)
+            )
+            return None
+
+        strings_to_postprocess = []
+
+        # Keep track of the last name's start and end offsets in order
+        # to be able to detect overlapping entries that might suggest
+        # and invalid or corrupt directory.
+        last_name_begin_end = None
+        for idx in range(number_of_entries):
+            if (
+                not self.__resource_size_limit_reached
+                and self.__total_resource_bytes > self.__resource_size_limit_upperbounds
+            ):
+
+                self.__resource_size_limit_reached = True
+                self.__warnings.append(
+                    "Resource size 0x%x exceeds file size 0x%x, overlapping "
+                    "resources found."
+                    % (
+                        self.__total_resource_bytes,
+                        self.__resource_size_limit_upperbounds,
+                    )
+                )
+
+            res = self.parse_resource_entry(rva)
+            if res is None:
+                self.__warnings.append(
+                    "Error parsing the resources directory, "
+                    "Entry %d is invalid, RVA = 0x%x. " % (idx, rva)
+                )
+                break
+
+            entry_name = None
+            entry_id = None
+
+            name_is_string = (res.Name & 0x80000000) >> 31
+            if not name_is_string:
+                entry_id = res.Name
+            else:
+                ustr_offset = base_rva + res.NameOffset
+                try:
+                    entry_name = UnicodeStringWrapperPostProcessor(self, ustr_offset)
+                    self.__total_resource_bytes += entry_name.get_pascal_16_length()
+                    # If the last entry's offset points before the current's but its end
+                    # is past the current's beginning, assume the overlap indicates a
+                    # corrupt name.
+                    if last_name_begin_end and (
+                        last_name_begin_end[0] < ustr_offset
+                        and last_name_begin_end[1] >= ustr_offset
+                    ):
+                        # Remove the previous overlapping entry as it's likely to be
+                        # already corrupt data.
+                        strings_to_postprocess.pop()
+                        self.__warnings.append(
+                            "Error parsing the resources directory, "
+                            "attempting to read entry name. "
+                            "Entry names overlap 0x%x" % (ustr_offset)
+                        )
+                        break
+
+                    last_name_begin_end = (
+                        ustr_offset,
+                        ustr_offset + entry_name.get_pascal_16_length(),
+                    )
+
+                    strings_to_postprocess.append(entry_name)
+
+                except PEFormatError:
+                    self.__warnings.append(
+                        "Error parsing the resources directory, "
+                        "attempting to read entry name. "
+                        "Can't read unicode string at offset 0x%x" % (ustr_offset)
+                    )
+
+            if res.DataIsDirectory:
+                # OC Patch:
+                #
+                # One trick malware can do is to recursively reference
+                # the next directory. This causes hilarity to ensue when
+                # trying to parse everything correctly.
+                # If the original RVA given to this function is equal to
+                # the next one to parse, we assume that it's a trick.
+                # Instead of raising a PEFormatError this would skip some
+                # reasonable data so we just break.
+                #
+                # 9ee4d0a0caf095314fd7041a3e4404dc is the offending sample
+                if base_rva + res.OffsetToDirectory in dirs:
+                    break
+
+                entry_directory = self.parse_resources_directory(
+                    base_rva + res.OffsetToDirectory,
+                    size - (rva - base_rva),  # size
+                    base_rva=base_rva,
+                    level=level + 1,
+                    dirs=dirs + [base_rva + res.OffsetToDirectory],
+                )
+
+                if not entry_directory:
+                    break
+
+                # Ange Albertini's code to process resources' strings
+                #
+                strings = None
+                if entry_id == RESOURCE_TYPE["RT_STRING"]:
+                    strings = {}
+                    for resource_id in entry_directory.entries:
+                        if hasattr(resource_id, "directory"):
+
+                            resource_strings = {}
+
+                            for resource_lang in resource_id.directory.entries:
+
+                                if (
+                                    resource_lang is None
+                                    or not hasattr(resource_lang, "data")
+                                    or resource_lang.data.struct.Size is None
+                                    or resource_id.id is None
+                                ):
+                                    continue
+
+                                string_entry_rva = (
+                                    resource_lang.data.struct.OffsetToData
+                                )
+                                string_entry_size = resource_lang.data.struct.Size
+                                string_entry_id = resource_id.id
+
+                                # XXX: has been raising exceptions preventing parsing
+                                try:
+                                    string_entry_data = self.get_data(
+                                        string_entry_rva, string_entry_size
+                                    )
+                                except PEFormatError:
+                                    self.__warnings.append(
+                                        f"Error parsing resource of type RT_STRING at "
+                                        f"RVA 0x{string_entry_rva:x} with "
+                                        f"size {string_entry_size}"
+                                    )
+                                    continue
+
+                                parse_strings(
+                                    string_entry_data,
+                                    (int(string_entry_id) - 1) * 16,
+                                    resource_strings,
+                                )
+                                strings.update(resource_strings)
+
+                            resource_id.directory.strings = resource_strings
+
+                dir_entries.append(
+                    ResourceDirEntryData(
+                        struct=res,
+                        name=entry_name,
+                        id=entry_id,
+                        directory=entry_directory,
+                    )
+                )
+
+            else:
+                struct = self.parse_resource_data_entry(
+                    base_rva + res.OffsetToDirectory
+                )
+
+                if struct:
+                    self.__total_resource_bytes += struct.Size
+                    entry_data = ResourceDataEntryData(
+                        struct=struct, lang=res.Name & 0x3FF, sublang=res.Name >> 10
+                    )
+
+                    dir_entries.append(
+                        ResourceDirEntryData(
+                            struct=res, name=entry_name, id=entry_id, data=entry_data
+                        )
+                    )
+
+                else:
+                    break
+
+            # Check if this entry contains version information
+            #
+            if level == 0 and res.Id == RESOURCE_TYPE["RT_VERSION"]:
+                if dir_entries:
+                    last_entry = dir_entries[-1]
+
+                try:
+                    version_entries = last_entry.directory.entries[0].directory.entries
+                except:
+                    # Maybe a malformed directory structure...?
+                    # Let's ignore it
+                    pass
+                else:
+                    for version_entry in version_entries:
+                        rt_version_struct = None
+                        try:
+                            rt_version_struct = version_entry.data.struct
+                        except:
+                            # Maybe a malformed directory structure...?
+                            # Let's ignore it
+                            pass
+
+                        if rt_version_struct is not None:
+                            self.parse_version_information(rt_version_struct)
+
+            rva += res.sizeof()
+
+        string_rvas = [s.get_rva() for s in strings_to_postprocess]
+        string_rvas.sort()
+
+        for idx, s in enumerate(strings_to_postprocess):
+            s.render_pascal_16()
+
+        resource_directory_data = ResourceDirData(
+            struct=resource_dir, entries=dir_entries
+        )
+
+        return resource_directory_data
+
+    def parse_resource_data_entry(self, rva):
+        """Parse a data entry from the resources directory."""
+
+        try:
+            # If the RVA is invalid all would blow up. Some EXEs seem to be
+            # specially nasty and have an invalid RVA.
+            data = self.get_data(
+                rva, Structure(self.__IMAGE_RESOURCE_DATA_ENTRY_format__).sizeof()
+            )
+        except PEFormatError:
+            self.__warnings.append(
+                "Error parsing a resource directory data entry, "
+                "the RVA is invalid: 0x%x" % (rva)
+            )
+            return None
+
+        data_entry = self.__unpack_data__(
+            self.__IMAGE_RESOURCE_DATA_ENTRY_format__,
+            data,
+            file_offset=self.get_offset_from_rva(rva),
+        )
+
+        return data_entry
+
+    def parse_resource_entry(self, rva):
+        """Parse a directory entry from the resources directory."""
+
+        try:
+            data = self.get_data(
+                rva, Structure(self.__IMAGE_RESOURCE_DIRECTORY_ENTRY_format__).sizeof()
+            )
+        except PEFormatError:
+            # A warning will be added by the caller if this method returns None
+            return None
+
+        resource = self.__unpack_data__(
+            self.__IMAGE_RESOURCE_DIRECTORY_ENTRY_format__,
+            data,
+            file_offset=self.get_offset_from_rva(rva),
+        )
+
+        if resource is None:
+            return None
+
+        # resource.NameIsString = (resource.Name & 0x80000000L) >> 31
+        resource.NameOffset = resource.Name & 0x7FFFFFFF
+
+        resource.__pad = resource.Name & 0xFFFF0000
+        resource.Id = resource.Name & 0x0000FFFF
+
+        resource.DataIsDirectory = (resource.OffsetToData & 0x80000000) >> 31
+        resource.OffsetToDirectory = resource.OffsetToData & 0x7FFFFFFF
+
+        return resource
+
+    def parse_version_information(self, version_struct):
+        """Parse version information structure.
+
+        The date will be made available in three attributes of the PE object.
+
+        VS_VERSIONINFO   will contain the first three fields of the main structure:
+            'Length', 'ValueLength', and 'Type'
+
+        VS_FIXEDFILEINFO will hold the rest of the fields, accessible as sub-attributes:
+            'Signature', 'StrucVersion', 'FileVersionMS', 'FileVersionLS',
+            'ProductVersionMS', 'ProductVersionLS', 'FileFlagsMask', 'FileFlags',
+            'FileOS', 'FileType', 'FileSubtype', 'FileDateMS', 'FileDateLS'
+
+        FileInfo    is a list of all StringFileInfo and VarFileInfo structures.
+
+        StringFileInfo structures will have a list as an attribute named 'StringTable'
+        containing all the StringTable structures. Each of those structures contains a
+        dictionary 'entries' with all the key / value version information string pairs.
+
+        VarFileInfo structures will have a list as an attribute named 'Var' containing
+        all Var structures. Each Var structure will have a dictionary as an attribute
+        named 'entry' which will contain the name and value of the Var.
+        """
+
+        # Retrieve the data for the version info resource
+        #
+        try:
+            start_offset = self.get_offset_from_rva(version_struct.OffsetToData)
+        except PEFormatError:
+            self.__warnings.append(
+                "Error parsing the version information, "
+                "attempting to read OffsetToData with RVA: 0x{:x}".format(
+                    version_struct.OffsetToData
+                )
+            )
+            return
+        raw_data = self.__data__[start_offset : start_offset + version_struct.Size]
+
+        # Map the main structure and the subsequent string
+        #
+        versioninfo_struct = self.__unpack_data__(
+            self.__VS_VERSIONINFO_format__, raw_data, file_offset=start_offset
+        )
+
+        if versioninfo_struct is None:
+            return
+
+        ustr_offset = version_struct.OffsetToData + versioninfo_struct.sizeof()
+        section = self.get_section_by_rva(ustr_offset)
+        section_end = None
+        if section:
+            section_end = section.VirtualAddress + max(
+                section.SizeOfRawData, section.Misc_VirtualSize
+            )
+
+        versioninfo_string = None
+        # These should return 'ascii' decoded data. For the case when it's
+        # garbled data the ascii string will retain the byte values while
+        # encoding it to something else may yield values that don't match the
+        # file's contents.
+        try:
+            if section_end is None:
+                versioninfo_string = self.get_string_u_at_rva(
+                    ustr_offset, encoding="ascii"
+                )
+            else:
+                versioninfo_string = self.get_string_u_at_rva(
+                    ustr_offset, (section_end - ustr_offset) >> 1, encoding="ascii"
+                )
+        except PEFormatError:
+            self.__warnings.append(
+                "Error parsing the version information, "
+                "attempting to read VS_VERSION_INFO string. Can't "
+                "read unicode string at offset 0x%x" % (ustr_offset)
+            )
+
+        if versioninfo_string is None:
+            self.__warnings.append(
+                "Invalid VS_VERSION_INFO block: {0}".format(versioninfo_string)
+            )
+            return
+
+        # If the structure does not contain the expected name, it's assumed to
+        # be invalid
+        if versioninfo_string is not None and versioninfo_string != b"VS_VERSION_INFO":
+            if len(versioninfo_string) > 128:
+                excerpt = versioninfo_string[:128].decode("ascii")
+                # Don't leave any half-escaped characters
+                excerpt = excerpt[: excerpt.rfind("\\u")]
+                versioninfo_string = b(
+                    "{0} ... ({1} bytes, too long to display)".format(
+                        excerpt, len(versioninfo_string)
+                    )
+                )
+            self.__warnings.append(
+                "Invalid VS_VERSION_INFO block: {0}".format(
+                    versioninfo_string.decode("ascii").replace("\00", "\\00")
+                )
+            )
+            return
+
+        if not hasattr(self, "VS_VERSIONINFO"):
+            self.VS_VERSIONINFO = []
+
+        # Set the PE object's VS_VERSIONINFO to this one
+        vinfo = versioninfo_struct
+
+        # Set the Key attribute to point to the unicode string identifying the structure
+        vinfo.Key = versioninfo_string
+
+        self.VS_VERSIONINFO.append(vinfo)
+
+        if versioninfo_string is None:
+            versioninfo_string = ""
+        # Process the fixed version information, get the offset and structure
+        fixedfileinfo_offset = self.dword_align(
+            versioninfo_struct.sizeof() + 2 * (len(versioninfo_string) + 1),
+            version_struct.OffsetToData,
+        )
+        fixedfileinfo_struct = self.__unpack_data__(
+            self.__VS_FIXEDFILEINFO_format__,
+            raw_data[fixedfileinfo_offset:],
+            file_offset=start_offset + fixedfileinfo_offset,
+        )
+
+        if not fixedfileinfo_struct:
+            return
+
+        if not hasattr(self, "VS_FIXEDFILEINFO"):
+            self.VS_FIXEDFILEINFO = []
+
+        # Set the PE object's VS_FIXEDFILEINFO to this one
+        self.VS_FIXEDFILEINFO.append(fixedfileinfo_struct)
+
+        # Start parsing all the StringFileInfo and VarFileInfo structures
+
+        # Get the first one
+        stringfileinfo_offset = self.dword_align(
+            fixedfileinfo_offset + fixedfileinfo_struct.sizeof(),
+            version_struct.OffsetToData,
+        )
+
+        # Set the PE object's attribute that will contain them all.
+        if not hasattr(self, "FileInfo"):
+            self.FileInfo = []
+
+        finfo = []
+        while True:
+
+            # Process the StringFileInfo/VarFileInfo structure
+            stringfileinfo_struct = self.__unpack_data__(
+                self.__StringFileInfo_format__,
+                raw_data[stringfileinfo_offset:],
+                file_offset=start_offset + stringfileinfo_offset,
+            )
+
+            if stringfileinfo_struct is None:
+                self.__warnings.append(
+                    "Error parsing StringFileInfo/VarFileInfo struct"
+                )
+                return None
+
+            # Get the subsequent string defining the structure.
+            ustr_offset = (
+                version_struct.OffsetToData
+                + stringfileinfo_offset
+                + versioninfo_struct.sizeof()
+            )
+            try:
+                stringfileinfo_string = self.get_string_u_at_rva(ustr_offset)
+            except PEFormatError:
+                self.__warnings.append(
+                    "Error parsing the version information, "
+                    "attempting to read StringFileInfo string. Can't "
+                    "read unicode string at offset 0x{0:x}".format(ustr_offset)
+                )
+                break
+
+            # Set such string as the Key attribute
+            stringfileinfo_struct.Key = stringfileinfo_string
+
+            # Append the structure to the PE object's list
+            finfo.append(stringfileinfo_struct)
+
+            # Parse a StringFileInfo entry
+            if stringfileinfo_string and stringfileinfo_string.startswith(
+                b"StringFileInfo"
+            ):
+
+                if (
+                    stringfileinfo_struct.Type in (0, 1)
+                    and stringfileinfo_struct.ValueLength == 0
+                ):
+
+                    stringtable_offset = self.dword_align(
+                        stringfileinfo_offset
+                        + stringfileinfo_struct.sizeof()
+                        + 2 * (len(stringfileinfo_string) + 1),
+                        version_struct.OffsetToData,
+                    )
+
+                    stringfileinfo_struct.StringTable = []
+
+                    # Process the String Table entries
+                    while True:
+
+                        stringtable_struct = self.__unpack_data__(
+                            self.__StringTable_format__,
+                            raw_data[stringtable_offset:],
+                            file_offset=start_offset + stringtable_offset,
+                        )
+
+                        if not stringtable_struct:
+                            break
+
+                        ustr_offset = (
+                            version_struct.OffsetToData
+                            + stringtable_offset
+                            + stringtable_struct.sizeof()
+                        )
+                        try:
+                            stringtable_string = self.get_string_u_at_rva(ustr_offset)
+                        except PEFormatError:
+                            self.__warnings.append(
+                                "Error parsing the version information, "
+                                "attempting to read StringTable string. Can't "
+                                "read unicode string at offset 0x{0:x}".format(
+                                    ustr_offset
+                                )
+                            )
+                            break
+
+                        stringtable_struct.LangID = stringtable_string
+                        stringtable_struct.entries = {}
+                        stringtable_struct.entries_offsets = {}
+                        stringtable_struct.entries_lengths = {}
+                        stringfileinfo_struct.StringTable.append(stringtable_struct)
+
+                        entry_offset = self.dword_align(
+                            stringtable_offset
+                            + stringtable_struct.sizeof()
+                            + 2 * (len(stringtable_string) + 1),
+                            version_struct.OffsetToData,
+                        )
+
+                        # Process all entries in the string table
+
+                        while (
+                            entry_offset
+                            < stringtable_offset + stringtable_struct.Length
+                        ):
+
+                            string_struct = self.__unpack_data__(
+                                self.__String_format__,
+                                raw_data[entry_offset:],
+                                file_offset=start_offset + entry_offset,
+                            )
+
+                            if not string_struct:
+                                break
+
+                            ustr_offset = (
+                                version_struct.OffsetToData
+                                + entry_offset
+                                + string_struct.sizeof()
+                            )
+                            try:
+                                key = self.get_string_u_at_rva(ustr_offset)
+                                key_offset = self.get_offset_from_rva(ustr_offset)
+                            except PEFormatError:
+                                self.__warnings.append(
+                                    "Error parsing the version information, "
+                                    "attempting to read StringTable Key string. Can't "
+                                    "read unicode string at offset 0x{0:x}".format(
+                                        ustr_offset
+                                    )
+                                )
+                                break
+
+                            value_offset = self.dword_align(
+                                2 * (len(key) + 1)
+                                + entry_offset
+                                + string_struct.sizeof(),
+                                version_struct.OffsetToData,
+                            )
+
+                            ustr_offset = version_struct.OffsetToData + value_offset
+                            try:
+                                value = self.get_string_u_at_rva(
+                                    ustr_offset, max_length=string_struct.ValueLength
+                                )
+                                value_offset = self.get_offset_from_rva(ustr_offset)
+                            except PEFormatError:
+                                self.__warnings.append(
+                                    "Error parsing the version information, attempting "
+                                    "to read StringTable Value string. Can't read "
+                                    f"unicode string at offset 0x{ustr_offset:x}"
+                                )
+                                break
+
+                            if string_struct.Length == 0:
+                                entry_offset = (
+                                    stringtable_offset + stringtable_struct.Length
+                                )
+                            else:
+                                entry_offset = self.dword_align(
+                                    string_struct.Length + entry_offset,
+                                    version_struct.OffsetToData,
+                                )
+
+                            stringtable_struct.entries[key] = value
+                            stringtable_struct.entries_offsets[key] = (
+                                key_offset,
+                                value_offset,
+                            )
+                            stringtable_struct.entries_lengths[key] = (
+                                len(key),
+                                len(value),
+                            )
+
+                        new_stringtable_offset = self.dword_align(
+                            stringtable_struct.Length + stringtable_offset,
+                            version_struct.OffsetToData,
+                        )
+
+                        # Check if the entry is crafted in a way that would lead
+                        # to an infinite loop and break if so.
+                        if new_stringtable_offset == stringtable_offset:
+                            break
+                        stringtable_offset = new_stringtable_offset
+
+                        if stringtable_offset >= stringfileinfo_struct.Length:
+                            break
+
+            # Parse a VarFileInfo entry
+            elif stringfileinfo_string and stringfileinfo_string.startswith(
+                b"VarFileInfo"
+            ):
+
+                varfileinfo_struct = stringfileinfo_struct
+                varfileinfo_struct.name = "VarFileInfo"
+
+                if (
+                    varfileinfo_struct.Type in (0, 1)
+                    and varfileinfo_struct.ValueLength == 0
+                ):
+
+                    var_offset = self.dword_align(
+                        stringfileinfo_offset
+                        + varfileinfo_struct.sizeof()
+                        + 2 * (len(stringfileinfo_string) + 1),
+                        version_struct.OffsetToData,
+                    )
+
+                    varfileinfo_struct.Var = []
+
+                    # Process all entries
+
+                    while True:
+                        var_struct = self.__unpack_data__(
+                            self.__Var_format__,
+                            raw_data[var_offset:],
+                            file_offset=start_offset + var_offset,
+                        )
+
+                        if not var_struct:
+                            break
+
+                        ustr_offset = (
+                            version_struct.OffsetToData
+                            + var_offset
+                            + var_struct.sizeof()
+                        )
+                        try:
+                            var_string = self.get_string_u_at_rva(ustr_offset)
+                        except PEFormatError:
+                            self.__warnings.append(
+                                "Error parsing the version information, "
+                                "attempting to read VarFileInfo Var string. "
+                                "Can't read unicode string at offset 0x{0:x}".format(
+                                    ustr_offset
+                                )
+                            )
+                            break
+
+                        if var_string is None:
+                            break
+
+                        varfileinfo_struct.Var.append(var_struct)
+
+                        varword_offset = self.dword_align(
+                            2 * (len(var_string) + 1)
+                            + var_offset
+                            + var_struct.sizeof(),
+                            version_struct.OffsetToData,
+                        )
+                        orig_varword_offset = varword_offset
+
+                        while (
+                            varword_offset
+                            < orig_varword_offset + var_struct.ValueLength
+                        ):
+                            word1 = self.get_word_from_data(
+                                raw_data[varword_offset : varword_offset + 2], 0
+                            )
+                            word2 = self.get_word_from_data(
+                                raw_data[varword_offset + 2 : varword_offset + 4], 0
+                            )
+                            varword_offset += 4
+
+                            if isinstance(word1, int) and isinstance(word2, int):
+                                var_struct.entry = {
+                                    var_string: "0x%04x 0x%04x" % (word1, word2)
+                                }
+
+                        var_offset = self.dword_align(
+                            var_offset + var_struct.Length, version_struct.OffsetToData
+                        )
+
+                        if var_offset <= var_offset + var_struct.Length:
+                            break
+
+            # Increment and align the offset
+            stringfileinfo_offset = self.dword_align(
+                stringfileinfo_struct.Length + stringfileinfo_offset,
+                version_struct.OffsetToData,
+            )
+
+            # Check if all the StringFileInfo and VarFileInfo items have been processed
+            if (
+                stringfileinfo_struct.Length == 0
+                or stringfileinfo_offset >= versioninfo_struct.Length
+            ):
+                break
+
+        self.FileInfo.append(finfo)
+
+    def parse_export_directory(self, rva, size, forwarded_only=False):
+        """Parse the export directory.
+
+        Given the RVA of the export directory, it will process all
+        its entries.
+
+        The exports will be made available as a list of ExportData
+        instances in the 'IMAGE_DIRECTORY_ENTRY_EXPORT' PE attribute.
+        """
+
+        try:
+            export_dir = self.__unpack_data__(
+                self.__IMAGE_EXPORT_DIRECTORY_format__,
+                self.get_data(
+                    rva, Structure(self.__IMAGE_EXPORT_DIRECTORY_format__).sizeof()
+                ),
+                file_offset=self.get_offset_from_rva(rva),
+            )
+        except PEFormatError:
+            self.__warnings.append(
+                "Error parsing export directory at RVA: 0x%x" % (rva)
+            )
+            return
+
+        if not export_dir:
+            return
+
+        # We keep track of the bytes left in the file and use it to set a upper
+        # bound in the number of items that can be read from the different
+        # arrays.
+        def length_until_eof(rva):
+            return len(self.__data__) - self.get_offset_from_rva(rva)
+
+        try:
+            address_of_names = self.get_data(
+                export_dir.AddressOfNames,
+                min(
+                    length_until_eof(export_dir.AddressOfNames),
+                    export_dir.NumberOfNames * 4,
+                ),
+            )
+            address_of_name_ordinals = self.get_data(
+                export_dir.AddressOfNameOrdinals,
+                min(
+                    length_until_eof(export_dir.AddressOfNameOrdinals),
+                    export_dir.NumberOfNames * 4,
+                ),
+            )
+            address_of_functions = self.get_data(
+                export_dir.AddressOfFunctions,
+                min(
+                    length_until_eof(export_dir.AddressOfFunctions),
+                    export_dir.NumberOfFunctions * 4,
+                ),
+            )
+        except PEFormatError:
+            self.__warnings.append(
+                "Error parsing export directory at RVA: 0x%x" % (rva)
+            )
+            return
+
+        exports = []
+
+        max_failed_entries_before_giving_up = 10
+
+        section = self.get_section_by_rva(export_dir.AddressOfNames)
+        # Overly generous upper bound
+        safety_boundary = len(self.__data__)
+        if section:
+            safety_boundary = (
+                section.VirtualAddress
+                + len(section.get_data())
+                - export_dir.AddressOfNames
+            )
+
+        symbol_counts = collections.defaultdict(int)
+        export_parsing_loop_completed_normally = True
+        for i in range(min(export_dir.NumberOfNames, int(safety_boundary / 4))):
+            symbol_ordinal = self.get_word_from_data(address_of_name_ordinals, i)
+
+            if symbol_ordinal is not None and symbol_ordinal * 4 < len(
+                address_of_functions
+            ):
+                symbol_address = self.get_dword_from_data(
+                    address_of_functions, symbol_ordinal
+                )
+            else:
+                # Corrupt? a bad pointer... we assume it's all
+                # useless, no exports
+                return None
+            if symbol_address is None or symbol_address == 0:
+                continue
+
+            # If the function's RVA points within the export directory
+            # it will point to a string with the forwarded symbol's string
+            # instead of pointing the the function start address.
+            if symbol_address >= rva and symbol_address < rva + size:
+                forwarder_str = self.get_string_at_rva(symbol_address)
+                try:
+                    forwarder_offset = self.get_offset_from_rva(symbol_address)
+                except PEFormatError:
+                    continue
+            else:
+                if forwarded_only:
+                    continue
+                forwarder_str = None
+                forwarder_offset = None
+
+            symbol_name_address = self.get_dword_from_data(address_of_names, i)
+            if symbol_name_address is None:
+                max_failed_entries_before_giving_up -= 1
+                if max_failed_entries_before_giving_up <= 0:
+                    export_parsing_loop_completed_normally = False
+                    break
+
+            symbol_name = self.get_string_at_rva(
+                symbol_name_address, MAX_SYMBOL_NAME_LENGTH
+            )
+            if not is_valid_function_name(symbol_name, relax_allowed_characters=True):
+                export_parsing_loop_completed_normally = False
+                break
+            try:
+                symbol_name_offset = self.get_offset_from_rva(symbol_name_address)
+            except PEFormatError:
+                max_failed_entries_before_giving_up -= 1
+                if max_failed_entries_before_giving_up <= 0:
+                    export_parsing_loop_completed_normally = False
+                    break
+                try:
+                    symbol_name_offset = self.get_offset_from_rva(symbol_name_address)
+                except PEFormatError:
+                    max_failed_entries_before_giving_up -= 1
+                    if max_failed_entries_before_giving_up <= 0:
+                        export_parsing_loop_completed_normally = False
+                        break
+                    continue
+
+            # File 0b1d3d3664915577ab9a32188d29bbf3542b86c7b9ce333e245496c3018819f1
+            # was being parsed as potentially containing millions of exports.
+            # Checking for duplicates addresses the issue.
+            symbol_counts[(symbol_name, symbol_address)] += 1
+            if symbol_counts[(symbol_name, symbol_address)] > 10:
+                self.__warnings.append(
+                    f"Export directory contains more than 10 repeated entries "
+                    f"({symbol_name}, {symbol_address:#02x}). Assuming corrupt."
+                )
+                break
+            elif len(symbol_counts) > self.max_symbol_exports:
+                self.__warnings.append(
+                    "Export directory contains more than {} symbol entries. "
+                    "Assuming corrupt.".format(self.max_symbol_exports)
+                )
+                break
+
+            exports.append(
+                ExportData(
+                    pe=self,
+                    ordinal=export_dir.Base + symbol_ordinal,
+                    ordinal_offset=self.get_offset_from_rva(
+                        export_dir.AddressOfNameOrdinals + 2 * i
+                    ),
+                    address=symbol_address,
+                    address_offset=self.get_offset_from_rva(
+                        export_dir.AddressOfFunctions + 4 * symbol_ordinal
+                    ),
+                    name=symbol_name,
+                    name_offset=symbol_name_offset,
+                    forwarder=forwarder_str,
+                    forwarder_offset=forwarder_offset,
+                )
+            )
+
+        if not export_parsing_loop_completed_normally:
+            self.__warnings.append(
+                f"RVA AddressOfNames in the export directory points to an invalid "
+                f"address: {export_dir.AddressOfNames:x}"
+            )
+
+        ordinals = {exp.ordinal for exp in exports}
+
+        max_failed_entries_before_giving_up = 10
+
+        section = self.get_section_by_rva(export_dir.AddressOfFunctions)
+        # Overly generous upper bound
+        safety_boundary = len(self.__data__)
+        if section:
+            safety_boundary = (
+                section.VirtualAddress
+                + len(section.get_data())
+                - export_dir.AddressOfFunctions
+            )
+
+        symbol_counts = collections.defaultdict(int)
+        export_parsing_loop_completed_normally = True
+        for idx in range(min(export_dir.NumberOfFunctions, int(safety_boundary / 4))):
+
+            if not idx + export_dir.Base in ordinals:
+                try:
+                    symbol_address = self.get_dword_from_data(address_of_functions, idx)
+                except PEFormatError:
+                    symbol_address = None
+
+                if symbol_address is None:
+                    max_failed_entries_before_giving_up -= 1
+                    if max_failed_entries_before_giving_up <= 0:
+                        export_parsing_loop_completed_normally = False
+                        break
+
+                if symbol_address == 0:
+                    continue
+
+                # Checking for forwarder again.
+                if (
+                    symbol_address is not None
+                    and symbol_address >= rva
+                    and symbol_address < rva + size
+                ):
+                    forwarder_str = self.get_string_at_rva(symbol_address)
+                else:
+                    forwarder_str = None
+
+                # File 0b1d3d3664915577ab9a32188d29bbf3542b86c7b9ce333e245496c3018819f1
+                # was being parsed as potentially containing millions of exports.
+                # Checking for duplicates addresses the issue.
+                symbol_counts[symbol_address] += 1
+                if symbol_counts[symbol_address] > self.max_repeated_symbol:
+                    # if most_common and most_common[0][1] > 10:
+                    self.__warnings.append(
+                        "Export directory contains more than {} repeated "
+                        "ordinal entries (0x{:x}). Assuming corrupt.".format(
+                            self.max_repeated_symbol, symbol_address
+                        )
+                    )
+                    break
+                elif len(symbol_counts) > self.max_symbol_exports:
+                    self.__warnings.append(
+                        "Export directory contains more than "
+                        f"{self.max_symbol_exports} ordinal entries. Assuming corrupt."
+                    )
+                    break
+
+                exports.append(
+                    ExportData(
+                        ordinal=export_dir.Base + idx,
+                        address=symbol_address,
+                        name=None,
+                        forwarder=forwarder_str,
+                    )
+                )
+
+        if not export_parsing_loop_completed_normally:
+            self.__warnings.append(
+                "RVA AddressOfFunctions in the export directory points to an invalid "
+                f"address: {export_dir.AddressOfFunctions:x}"
+            )
+            return
+
+        if not exports and export_dir.all_zeroes():
+            return None
+        return ExportDirData(
+            struct=export_dir,
+            symbols=exports,
+            name=self.get_string_at_rva(export_dir.Name),
+        )
+
+    def dword_align(self, offset, base):
+        return ((offset + base + 3) & 0xFFFFFFFC) - (base & 0xFFFFFFFC)
+
+    def normalize_import_va(self, va):
+
+        # Setup image range
+        begin_of_image = self.OPTIONAL_HEADER.ImageBase
+        end_of_image = self.OPTIONAL_HEADER.ImageBase + self.OPTIONAL_HEADER.SizeOfImage
+
+        # Try to avoid bogus VAs, which are out of the image.
+        # This also filters out entries that are zero
+        if begin_of_image <= va and va < end_of_image:
+            va -= begin_of_image
+        return va
+
+    def parse_delay_import_directory(self, rva, size):
+        """Walk and parse the delay import directory."""
+
+        import_descs = []
+        error_count = 0
+        while True:
+            try:
+                # If the RVA is invalid all would blow up. Some PEs seem to be
+                # specially nasty and have an invalid RVA.
+                data = self.get_data(
+                    rva,
+                    Structure(self.__IMAGE_DELAY_IMPORT_DESCRIPTOR_format__).sizeof(),
+                )
+            except PEFormatError:
+                self.__warnings.append(
+                    "Error parsing the Delay import directory at RVA: 0x%x" % (rva)
+                )
+                break
+
+            file_offset = self.get_offset_from_rva(rva)
+            import_desc = self.__unpack_data__(
+                self.__IMAGE_DELAY_IMPORT_DESCRIPTOR_format__,
+                data,
+                file_offset=file_offset,
+            )
+
+            # If the structure is all zeros, we reached the end of the list
+            if not import_desc or import_desc.all_zeroes():
+                break
+            contains_addresses = False
+
+            # Handle old import descriptor that has Virtual Addresses instead of RVAs
+            # This version of import descriptor is created by old Visual Studio versions
+            # (pre 6.0)
+            # Can only be present in 32-bit binaries (no 64-bit compiler existed at the
+            # time)
+            # Sample: e8d3bff0c1a9a6955993f7a441121a2692261421e82fdfadaaded45d3bea9980
+            if (
+                import_desc.grAttrs == 0
+                and self.FILE_HEADER.Machine == MACHINE_TYPE["IMAGE_FILE_MACHINE_I386"]
+            ):
+                import_desc.pBoundIAT = self.normalize_import_va(import_desc.pBoundIAT)
+                import_desc.pIAT = self.normalize_import_va(import_desc.pIAT)
+                import_desc.pINT = self.normalize_import_va(import_desc.pINT)
+                import_desc.pUnloadIAT = self.normalize_import_va(
+                    import_desc.pUnloadIAT
+                )
+                import_desc.phmod = self.normalize_import_va(import_desc.pUnloadIAT)
+                import_desc.szName = self.normalize_import_va(import_desc.szName)
+                contains_addresses = True
+
+            rva += import_desc.sizeof()
+
+            # If the array of thunks is somewhere earlier than the import
+            # descriptor we can set a maximum length for the array. Otherwise
+            # just set a maximum length of the size of the file
+            max_len = len(self.__data__) - file_offset
+            if rva > import_desc.pINT or rva > import_desc.pIAT:
+                max_len = max(rva - import_desc.pINT, rva - import_desc.pIAT)
+
+            import_data = []
+            try:
+                import_data = self.parse_imports(
+                    import_desc.pINT,
+                    import_desc.pIAT,
+                    None,
+                    max_len,
+                    contains_addresses,
+                )
+            except PEFormatError as excp:
+                self.__warnings.append(
+                    "Error parsing the Delay import directory. "
+                    "Invalid import data at RVA: 0x{0:x} ({1})".format(rva, excp.value)
+                )
+
+            if error_count > 5:
+                self.__warnings.append(
+                    "Too many errors parsing the Delay import directory. "
+                    "Invalid import data at RVA: 0x{0:x}".format(rva)
+                )
+                break
+
+            if not import_data:
+                error_count += 1
+                continue
+
+            if self.__total_import_symbols > MAX_IMPORT_SYMBOLS:
+                self.__warnings.append(
+                    "Error, too many imported symbols %d (>%s)"
+                    % (self.__total_import_symbols, MAX_IMPORT_SYMBOLS)
+                )
+                break
+
+            dll = self.get_string_at_rva(import_desc.szName, MAX_DLL_LENGTH)
+            if not is_valid_dos_filename(dll):
+                dll = b("*invalid*")
+
+            if dll:
+                for symbol in import_data:
+                    if symbol.name is None:
+                        funcname = ordlookup.ordLookup(dll.lower(), symbol.ordinal)
+                        if funcname:
+                            symbol.name = funcname
+                import_descs.append(
+                    ImportDescData(struct=import_desc, imports=import_data, dll=dll)
+                )
+
+        return import_descs
+
+    def get_rich_header_hash(self, algorithm="md5"):
+        if not hasattr(self, "RICH_HEADER") or self.RICH_HEADER is None:
+            return ""
+
+        if algorithm == "md5":
+            return md5(self.RICH_HEADER.clear_data).hexdigest()
+        elif algorithm == "sha1":
+            return sha1(self.RICH_HEADER.clear_data).hexdigest()
+        elif algorithm == "sha256":
+            return sha256(self.RICH_HEADER.clear_data).hexdigest()
+        elif algorithm == "sha512":
+            return sha512(self.RICH_HEADER.clear_data).hexdigest()
+
+        raise Exception("Invalid hashing algorithm specified")
+
+    def get_imphash(self):
+        """Return the imphash of the PE file.
+
+        Creates a hash based on imported symbol names and their specific order within
+        the executable:
+        https://www.mandiant.com/resources/blog/tracking-malware-import-hashing
+
+        Returns:
+            the hexdigest of the MD5 hash of the exported symbols.
+        """
+
+        impstrs = []
+        exts = ["ocx", "sys", "dll"]
+        if not hasattr(self, "DIRECTORY_ENTRY_IMPORT"):
+            return ""
+        for entry in self.DIRECTORY_ENTRY_IMPORT:
+            if isinstance(entry.dll, bytes):
+                libname = entry.dll.decode().lower()
+            else:
+                libname = entry.dll.lower()
+            parts = libname.rsplit(".", 1)
+
+            if len(parts) > 1 and parts[1] in exts:
+                libname = parts[0]
+
+            entry_dll_lower = entry.dll.lower()
+            for imp in entry.imports:
+                funcname = None
+                if not imp.name:
+                    funcname = ordlookup.ordLookup(
+                        entry_dll_lower, imp.ordinal, make_name=True
+                    )
+                    if not funcname:
+                        raise PEFormatError(
+                            f"Unable to look up ordinal {entry.dll}:{imp.ordinal:04x}"
+                        )
+                else:
+                    funcname = imp.name
+
+                if not funcname:
+                    continue
+
+                if isinstance(funcname, bytes):
+                    funcname = funcname.decode()
+                impstrs.append("%s.%s" % (libname.lower(), funcname.lower()))
+
+        return md5(",".join(impstrs).encode()).hexdigest()
+
+    def get_exphash(self):
+        """Return the exphash of the PE file.
+
+        Similar to imphash, but based on exported symbol names and their specific order.
+
+        Returns:
+            the hexdigest of the SHA256 hash of the exported symbols.
+        """
+
+        if not hasattr(self, "DIRECTORY_ENTRY_EXPORT"):
+            return ""
+
+        if not hasattr(self.DIRECTORY_ENTRY_EXPORT, "symbols"):
+            return ""
+
+        export_list = [
+            e.name.decode().lower()
+            for e in self.DIRECTORY_ENTRY_EXPORT.symbols
+            if e and e.name is not None
+        ]
+        if len(export_list) == 0:
+            return ""
+
+        return sha256(",".join(export_list).encode()).hexdigest()
+
+    def parse_import_directory(self, rva, size, dllnames_only=False):
+        """Walk and parse the import directory."""
+
+        import_descs = []
+        error_count = 0
+        image_import_descriptor_size = Structure(
+            self.__IMAGE_IMPORT_DESCRIPTOR_format__
+        ).sizeof()
+        while True:
+            try:
+                # If the RVA is invalid all would blow up. Some EXEs seem to be
+                # specially nasty and have an invalid RVA.
+                data = self.get_data(rva, image_import_descriptor_size)
+            except PEFormatError:
+                self.__warnings.append(
+                    f"Error parsing the import directory at RVA: 0x{rva:x}"
+                )
+                break
+
+            file_offset = self.get_offset_from_rva(rva)
+            import_desc = self.__unpack_data__(
+                self.__IMAGE_IMPORT_DESCRIPTOR_format__, data, file_offset=file_offset
+            )
+
+            # If the structure is all zeros, we reached the end of the list
+            if not import_desc or import_desc.all_zeroes():
+                break
+
+            rva += import_desc.sizeof()
+
+            # If the array of thunks is somewhere earlier than the import
+            # descriptor we can set a maximum length for the array. Otherwise
+            # just set a maximum length of the size of the file
+            max_len = len(self.__data__) - file_offset
+            if rva > import_desc.OriginalFirstThunk or rva > import_desc.FirstThunk:
+                max_len = max(
+                    rva - import_desc.OriginalFirstThunk, rva - import_desc.FirstThunk
+                )
+
+            import_data = []
+            if not dllnames_only:
+                try:
+                    import_data = self.parse_imports(
+                        import_desc.OriginalFirstThunk,
+                        import_desc.FirstThunk,
+                        import_desc.ForwarderChain,
+                        max_length=max_len,
+                    )
+                except PEFormatError as e:
+                    self.__warnings.append(
+                        "Error parsing the import directory. "
+                        f"Invalid Import data at RVA: 0x{rva:x} ({e.value})"
+                    )
+
+                if error_count > 5:
+                    self.__warnings.append(
+                        "Too many errors parsing the import directory. "
+                        f"Invalid import data at RVA: 0x{rva:x}"
+                    )
+                    break
+
+                if not import_data:
+                    error_count += 1
+                    # TODO: do not continue here
+                    continue
+
+            dll = self.get_string_at_rva(import_desc.Name, MAX_DLL_LENGTH)
+            if not is_valid_dos_filename(dll):
+                dll = b("*invalid*")
+
+            if dll:
+                for symbol in import_data:
+                    if symbol.name is None:
+                        funcname = ordlookup.ordLookup(dll.lower(), symbol.ordinal)
+                        if funcname:
+                            symbol.name = funcname
+                import_descs.append(
+                    ImportDescData(struct=import_desc, imports=import_data, dll=dll)
+                )
+
+        if not dllnames_only:
+            suspicious_imports = set(["LoadLibrary", "GetProcAddress"])
+            suspicious_imports_count = 0
+            total_symbols = 0
+            for imp_dll in import_descs:
+                for symbol in imp_dll.imports:
+                    for suspicious_symbol in suspicious_imports:
+                        if not symbol or not symbol.name:
+                            continue
+                        name = symbol.name
+                        if type(symbol.name) == bytes:
+                            name = symbol.name.decode("utf-8")
+                        if name.startswith(suspicious_symbol):
+                            suspicious_imports_count += 1
+                            break
+                    total_symbols += 1
+            if (
+                suspicious_imports_count == len(suspicious_imports)
+                and total_symbols < 20
+            ):
+                self.__warnings.append(
+                    "Imported symbols contain entries typical of packed executables."
+                )
+
+        return import_descs
+
+    def parse_imports(
+        self,
+        original_first_thunk,
+        first_thunk,
+        forwarder_chain,
+        max_length=None,
+        contains_addresses=False,
+    ):
+        """Parse the imported symbols.
+
+        It will fill a list, which will be available as the dictionary
+        attribute "imports". Its keys will be the DLL names and the values
+        of all the symbols imported from that object.
+        """
+
+        imported_symbols = []
+
+        # Import Lookup Table. Contains ordinals or pointers to strings.
+        ilt = self.get_import_table(
+            original_first_thunk, max_length, contains_addresses
+        )
+        # Import Address Table. May have identical content to ILT if
+        # PE file is not bound. It will contain the address of the
+        # imported symbols once the binary is loaded or if it is already
+        # bound.
+        iat = self.get_import_table(first_thunk, max_length, contains_addresses)
+
+        # OC Patch:
+        # Would crash if IAT or ILT had None type
+        if (not iat or len(iat) == 0) and (not ilt or len(ilt) == 0):
+            self.__warnings.append(
+                "Damaged Import Table information. "
+                "ILT and/or IAT appear to be broken. "
+                f"OriginalFirstThunk: 0x{original_first_thunk:x} "
+                f"FirstThunk: 0x{first_thunk:x}"
+            )
+            return []
+
+        table = None
+        if ilt:
+            table = ilt
+        elif iat:
+            table = iat
+        else:
+            return None
+
+        imp_offset = 4
+        address_mask = 0x7FFFFFFF
+        if self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE:
+            ordinal_flag = IMAGE_ORDINAL_FLAG
+        elif self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE_PLUS:
+            ordinal_flag = IMAGE_ORDINAL_FLAG64
+            imp_offset = 8
+            address_mask = 0x7FFFFFFFFFFFFFFF
+        else:
+            # Some PEs may have an invalid value in the Magic field of the
+            # Optional Header. Just in case the remaining file is parseable
+            # let's pretend it's a 32bit PE32 by default.
+            ordinal_flag = IMAGE_ORDINAL_FLAG
+
+        num_invalid = 0
+        for idx, tbl_entry in enumerate(table):
+            imp_ord = None
+            imp_hint = None
+            imp_name = None
+            name_offset = None
+            hint_name_table_rva = None
+            import_by_ordinal = False  # declare it here first
+
+            if tbl_entry.AddressOfData:
+                # If imported by ordinal, we will append the ordinal number
+                #
+                if tbl_entry.AddressOfData & ordinal_flag:
+                    import_by_ordinal = True
+                    imp_ord = tbl_entry.AddressOfData & 0xFFFF
+                    imp_name = None
+                    name_offset = None
+                else:
+                    import_by_ordinal = False
+                    try:
+                        hint_name_table_rva = tbl_entry.AddressOfData & address_mask
+                        data = self.get_data(hint_name_table_rva, 2)
+                        # Get the Hint
+                        imp_hint = self.get_word_from_data(data, 0)
+                        imp_name = self.get_string_at_rva(
+                            tbl_entry.AddressOfData + 2, MAX_IMPORT_NAME_LENGTH
+                        )
+                        if not is_valid_function_name(imp_name):
+                            imp_name = b("*invalid*")
+
+                        name_offset = self.get_offset_from_rva(
+                            tbl_entry.AddressOfData + 2
+                        )
+                    except PEFormatError:
+                        pass
+
+                # by nriva: we want the ThunkRVA and ThunkOffset
+                thunk_offset = tbl_entry.get_file_offset()
+                thunk_rva = self.get_rva_from_offset(thunk_offset)
+
+            imp_address = (
+                first_thunk + self.OPTIONAL_HEADER.ImageBase + idx * imp_offset
+            )
+
+            struct_iat = None
+            try:
+                if iat and ilt and ilt[idx].AddressOfData != iat[idx].AddressOfData:
+                    imp_bound = iat[idx].AddressOfData
+                    struct_iat = iat[idx]
+                else:
+                    imp_bound = None
+            except IndexError:
+                imp_bound = None
+
+            # The file with hashes:
+            #
+            # MD5: bfe97192e8107d52dd7b4010d12b2924
+            # SHA256: 3d22f8b001423cb460811ab4f4789f277b35838d45c62ec0454c877e7c82c7f5
+            #
+            # has an invalid table built in a way that it's parseable but contains
+            # invalid entries that lead pefile to take extremely long amounts of time to
+            # parse. It also leads to extreme memory consumption.
+            # To prevent similar cases, if invalid entries are found in the middle of a
+            # table the parsing will be aborted
+            #
+            if imp_ord is None and imp_name is None:
+                raise PEFormatError("Invalid entries, aborting parsing.")
+
+            # Some PEs appear to interleave valid and invalid imports. Instead of
+            # aborting the parsing altogether we will simply skip the invalid entries.
+            # Although if we see 1000 invalid entries and no legit ones, we abort.
+            if imp_name == b("*invalid*"):
+                if num_invalid > 1000 and num_invalid == idx:
+                    raise PEFormatError("Too many invalid names, aborting parsing.")
+                num_invalid += 1
+                continue
+
+            if imp_ord or imp_name:
+                imported_symbols.append(
+                    ImportData(
+                        pe=self,
+                        struct_table=tbl_entry,
+                        struct_iat=struct_iat,  # for bound imports if any
+                        import_by_ordinal=import_by_ordinal,
+                        ordinal=imp_ord,
+                        ordinal_offset=tbl_entry.get_file_offset(),
+                        hint=imp_hint,
+                        name=imp_name,
+                        name_offset=name_offset,
+                        bound=imp_bound,
+                        address=imp_address,
+                        hint_name_table_rva=hint_name_table_rva,
+                        thunk_offset=thunk_offset,
+                        thunk_rva=thunk_rva,
+                    )
+                )
+
+        return imported_symbols
+
+    def get_import_table(self, rva, max_length=None, contains_addresses=False):
+
+        table = []
+
+        # We need the ordinal flag for a simple heuristic
+        # we're implementing within the loop
+        #
+        if self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE:
+            ordinal_flag = IMAGE_ORDINAL_FLAG
+            format = self.__IMAGE_THUNK_DATA_format__
+        elif self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE_PLUS:
+            ordinal_flag = IMAGE_ORDINAL_FLAG64
+            format = self.__IMAGE_THUNK_DATA64_format__
+        else:
+            # Some PEs may have an invalid value in the Magic field of the
+            # Optional Header. Just in case the remaining file is parseable
+            # let's pretend it's a 32bit PE32 by default.
+            ordinal_flag = IMAGE_ORDINAL_FLAG
+            format = self.__IMAGE_THUNK_DATA_format__
+
+        expected_size = Structure(format).sizeof()
+        MAX_ADDRESS_SPREAD = 128 * 2**20  # 128 MB
+        ADDR_4GB = 2**32
+        MAX_REPEATED_ADDRESSES = 15
+        repeated_address = 0
+        addresses_of_data_set_64 = AddressSet()
+        addresses_of_data_set_32 = AddressSet()
+        start_rva = rva
+        while rva:
+            if max_length is not None and rva >= start_rva + max_length:
+                self.__warnings.append(
+                    "Error parsing the import table. Entries go beyond bounds."
+                )
+                break
+            # Enforce an upper bounds on import symbols.
+            if self.__total_import_symbols > MAX_IMPORT_SYMBOLS:
+                self.__warnings.append(
+                    "Excessive number of imports %d (>%s)"
+                    % (self.__total_import_symbols, MAX_IMPORT_SYMBOLS)
+                )
+                break
+
+            self.__total_import_symbols += 1
+
+            # if we see too many times the same entry we assume it could be
+            # a table containing bogus data (with malicious intent or otherwise)
+            if repeated_address >= MAX_REPEATED_ADDRESSES:
+                return []
+
+            # if the addresses point somewhere but the difference between the highest
+            # and lowest address is larger than MAX_ADDRESS_SPREAD we assume a bogus
+            # table as the addresses should be contained within a module
+            if addresses_of_data_set_32.diff() > MAX_ADDRESS_SPREAD:
+                return []
+            if addresses_of_data_set_64.diff() > MAX_ADDRESS_SPREAD:
+                return []
+
+            failed = False
+            try:
+                data = self.get_data(rva, expected_size)
+            except PEFormatError:
+                failed = True
+
+            if failed or len(data) != expected_size:
+                self.__warnings.append(
+                    "Error parsing the import table. " "Invalid data at RVA: 0x%x" % rva
+                )
+                return None
+
+            thunk_data = self.__unpack_data__(
+                format, data, file_offset=self.get_offset_from_rva(rva)
+            )
+
+            # If the thunk data contains VAs instead of RVAs, we need to normalize them
+            if contains_addresses:
+                thunk_data.AddressOfData = self.normalize_import_va(
+                    thunk_data.AddressOfData
+                )
+                thunk_data.ForwarderString = self.normalize_import_va(
+                    thunk_data.ForwarderString
+                )
+                thunk_data.Function = self.normalize_import_va(thunk_data.Function)
+                thunk_data.Ordinal = self.normalize_import_va(thunk_data.Ordinal)
+
+            # Check if the AddressOfData lies within the range of RVAs that it's
+            # being scanned, abort if that is the case, as it is very unlikely
+            # to be legitimate data.
+            # Seen in PE with SHA256:
+            # 5945bb6f0ac879ddf61b1c284f3b8d20c06b228e75ae4f571fa87f5b9512902c
+            if (
+                thunk_data
+                and thunk_data.AddressOfData >= start_rva
+                and thunk_data.AddressOfData <= rva
+            ):
+                self.__warnings.append(
+                    "Error parsing the import table. "
+                    "AddressOfData overlaps with THUNK_DATA for "
+                    "THUNK at RVA 0x%x" % (rva)
+                )
+                break
+
+            if thunk_data and thunk_data.AddressOfData:
+                addr_of_data = thunk_data.AddressOfData
+                # If the entry looks like could be an ordinal...
+                if addr_of_data & ordinal_flag:
+                    # but its value is beyond 2^16, we will assume it's a
+                    # corrupted and ignore it altogether
+                    if addr_of_data & 0x7FFFFFFF > 0xFFFF:
+                        return []
+                # and if it looks like it should be an RVA
+                else:
+                    # keep track of the RVAs seen and store them to study their
+                    # properties. When certain non-standard features are detected
+                    # the parsing will be aborted
+                    if addr_of_data >= ADDR_4GB:
+                        the_set = addresses_of_data_set_64
+                    else:
+                        the_set = addresses_of_data_set_32
+
+                    if addr_of_data in the_set:
+                        repeated_address += 1
+                    the_set.add(addr_of_data)
+
+            if not thunk_data or thunk_data.all_zeroes():
+                break
+
+            rva += thunk_data.sizeof()
+
+            table.append(thunk_data)
+
+        return table
+
+    def get_memory_mapped_image(self, max_virtual_address=0x10000000, ImageBase=None):
+        """Returns the data corresponding to the memory layout of the PE file.
+
+        The data includes the PE header and the sections loaded at offsets
+        corresponding to their relative virtual addresses. (the VirtualAddress
+        section header member).
+        Any offset in this data corresponds to the absolute memory address
+        ImageBase+offset.
+
+        The optional argument 'max_virtual_address' provides with means of limiting
+        which sections are processed.
+        Any section with their VirtualAddress beyond this value will be skipped.
+        Normally, sections with values beyond this range are just there to confuse
+        tools. It's a common trick to see in packed executables.
+
+        If the 'ImageBase' optional argument is supplied, the file's relocations
+        will be applied to the image by calling the 'relocate_image()' method. Beware
+        that the relocation information is applied permanently.
+        """
+
+        # Rebase if requested
+        #
+        if ImageBase is not None:
+
+            # Keep a copy of the image's data before modifying it by rebasing it
+            #
+            original_data = self.__data__
+
+            self.relocate_image(ImageBase)
+
+        # Collect all sections in one code block
+        mapped_data = self.__data__[:]
+        for section in self.sections:
+
+            # Miscellaneous integrity tests.
+            # Some packer will set these to bogus values to make tools go nuts.
+            if section.Misc_VirtualSize == 0 and section.SizeOfRawData == 0:
+                continue
+
+            srd = section.SizeOfRawData
+            prd = self.adjust_FileAlignment(
+                section.PointerToRawData, self.OPTIONAL_HEADER.FileAlignment
+            )
+            VirtualAddress_adj = self.adjust_SectionAlignment(
+                section.VirtualAddress,
+                self.OPTIONAL_HEADER.SectionAlignment,
+                self.OPTIONAL_HEADER.FileAlignment,
+            )
+
+            if (
+                srd > len(self.__data__)
+                or prd > len(self.__data__)
+                or srd + prd > len(self.__data__)
+                or VirtualAddress_adj >= max_virtual_address
+            ):
+                continue
+
+            padding_length = VirtualAddress_adj - len(mapped_data)
+
+            if padding_length > 0:
+                mapped_data += b"\0" * padding_length
+            elif padding_length < 0:
+                mapped_data = mapped_data[:padding_length]
+
+            mapped_data += section.get_data()
+
+        # If the image was rebased, restore it to its original form
+        #
+        if ImageBase is not None:
+            self.__data__ = original_data
+
+        return mapped_data
+
+    def get_resources_strings(self):
+        """Returns a list of all the strings found withing the resources (if any).
+
+        This method will scan all entries in the resources directory of the PE, if
+        there is one, and will return a [] with the strings.
+
+        An empty list will be returned otherwise.
+        """
+
+        resources_strings = []
+
+        if hasattr(self, "DIRECTORY_ENTRY_RESOURCE"):
+
+            for res_type in self.DIRECTORY_ENTRY_RESOURCE.entries:
+                if hasattr(res_type, "directory"):
+                    for resource_id in res_type.directory.entries:
+                        if hasattr(resource_id, "directory"):
+                            if (
+                                hasattr(resource_id.directory, "strings")
+                                and resource_id.directory.strings
+                            ):
+                                for res_string in list(
+                                    resource_id.directory.strings.values()
+                                ):
+                                    resources_strings.append(res_string)
+
+        return resources_strings
+
+    def get_data(self, rva=0, length=None):
+        """Get data regardless of the section where it lies on.
+
+        Given a RVA and the size of the chunk to retrieve, this method
+        will find the section where the data lies and return the data.
+        """
+
+        s = self.get_section_by_rva(rva)
+
+        if length:
+            end = rva + length
+        else:
+            end = None
+
+        if not s:
+            if rva < len(self.header):
+                return self.header[rva:end]
+
+            # Before we give up we check whether the file might
+            # contain the data anyway. There are cases of PE files
+            # without sections that rely on windows loading the first
+            # 8291 bytes into memory and assume the data will be
+            # there
+            # A functional file with these characteristics is:
+            # MD5: 0008892cdfbc3bda5ce047c565e52295
+            # SHA-1: c7116b9ff950f86af256defb95b5d4859d4752a9
+            #
+            if rva < len(self.__data__):
+                return self.__data__[rva:end]
+
+            raise PEFormatError("data at RVA can't be fetched. Corrupt header?")
+
+        return s.get_data(rva, length)
+
+    def get_rva_from_offset(self, offset):
+        """Get the RVA corresponding to this file offset."""
+
+        s = self.get_section_by_offset(offset)
+        if not s:
+            if self.sections:
+                lowest_rva = min(
+                    [
+                        self.adjust_SectionAlignment(
+                            s.VirtualAddress,
+                            self.OPTIONAL_HEADER.SectionAlignment,
+                            self.OPTIONAL_HEADER.FileAlignment,
+                        )
+                        for s in self.sections
+                    ]
+                )
+                if offset < lowest_rva:
+                    # We will assume that the offset lies within the headers, or
+                    # at least points before where the earliest section starts
+                    # and we will simply return the offset as the RVA
+                    #
+                    # The case illustrating this behavior can be found at:
+                    # http://corkami.blogspot.com/2010/01/hey-hey-hey-whats-in-your-head.html
+                    # where the import table is not contained by any section
+                    # hence the RVA needs to be resolved to a raw offset
+                    return offset
+                return None
+            else:
+                return offset
+        return s.get_rva_from_offset(offset)
+
+    def get_offset_from_rva(self, rva):
+        """Get the file offset corresponding to this RVA.
+
+        Given a RVA , this method will find the section where the
+        data lies and return the offset within the file.
+        """
+
+        s = self.get_section_by_rva(rva)
+        if not s:
+
+            # If not found within a section assume it might
+            # point to overlay data or otherwise data present
+            # but not contained in any section. In those
+            # cases the RVA should equal the offset
+            if rva < len(self.__data__):
+                return rva
+
+            raise PEFormatError(f"data at RVA 0x{rva:x} can't be fetched")
+
+        return s.get_offset_from_rva(rva)
+
+    def get_string_at_rva(self, rva, max_length=MAX_STRING_LENGTH):
+        """Get an ASCII string located at the given address."""
+
+        if rva is None:
+            return None
+
+        s = self.get_section_by_rva(rva)
+        if not s:
+            return self.get_string_from_data(0, self.__data__[rva : rva + max_length])
+        return self.get_string_from_data(0, s.get_data(rva, length=max_length))
+
+    def get_bytes_from_data(self, offset, data):
+        """."""
+        if offset > len(data):
+            return b""
+        d = data[offset:]
+        if isinstance(d, bytearray):
+            return bytes(d)
+        return d
+
+    def get_string_from_data(self, offset, data):
+        """Get an ASCII string from data."""
+        s = self.get_bytes_from_data(offset, data)
+        end = s.find(b"\0")
+        if end >= 0:
+            s = s[:end]
+        return s
+
+    def get_string_u_at_rva(self, rva, max_length=2**16, encoding=None):
+        """Get an Unicode string located at the given address."""
+
+        if max_length == 0:
+            return b""
+
+        # If the RVA is invalid let the exception reach the callers. All
+        # call-sites of get_string_u_at_rva() will handle it.
+        data = self.get_data(rva, 2)
+        # max_length is the maximum count of 16bit characters needs to be
+        # doubled to get size in bytes
+        max_length <<= 1
+
+        requested = min(max_length, 256)
+        data = self.get_data(rva, requested)
+        # try to find null-termination
+        null_index = -1
+        while True:
+            null_index = data.find(b"\x00\x00", null_index + 1)
+            if null_index == -1:
+                data_length = len(data)
+                if data_length < requested or data_length == max_length:
+                    null_index = len(data) >> 1
+                    break
+
+                # Request remaining part of data limited by max_length
+                data += self.get_data(rva + data_length, max_length - data_length)
+                null_index = requested - 1
+                requested = max_length
+
+            elif null_index % 2 == 0:
+                null_index >>= 1
+                break
+
+        # convert selected part of the string to unicode
+        uchrs = struct.unpack("<{:d}H".format(null_index), data[: null_index * 2])
+        s = "".join(map(chr, uchrs))
+
+        if encoding:
+            return b(s.encode(encoding, "backslashreplace_"))
+
+        return b(s.encode("utf-8", "backslashreplace_"))
+
+    def get_section_by_offset(self, offset):
+        """Get the section containing the given file offset."""
+
+        for section in self.sections:
+            if section.contains_offset(offset):
+                return section
+
+        return None
+
+    def get_section_by_rva(self, rva):
+        """Get the section containing the given address."""
+
+        # if we look a lot of times at RVA in the same section, "cache" the last used section
+        # to speedup lookups (very useful when parsing import table)
+        if self._get_section_by_rva_last_used is not None:
+            if self._get_section_by_rva_last_used.contains_rva(rva):
+                return self._get_section_by_rva_last_used
+
+        for section in self.sections:
+            if section.contains_rva(rva):
+                self._get_section_by_rva_last_used = section
+                return section
+
+        return None
+
+    def __str__(self):
+        return self.dump_info()
+
+    def has_relocs(self):
+        """Checks if the PE file has relocation directory"""
+        return hasattr(self, "DIRECTORY_ENTRY_BASERELOC")
+
+    def has_dynamic_relocs(self):
+        if hasattr(self, "DIRECTORY_ENTRY_LOAD_CONFIG"):
+            if self.DIRECTORY_ENTRY_LOAD_CONFIG.dynamic_relocations:
+                return True
+
+        return False
+
+    def print_info(self, encoding="utf-8"):
+        """Print all the PE header information in a human readable from."""
+        print(self.dump_info(encoding=encoding))
+
+    def dump_info(self, dump=None, encoding="ascii"):
+        """Dump all the PE header information into human readable string."""
+
+        if dump is None:
+            dump = Dump()
+
+        warnings = self.get_warnings()
+        if warnings:
+            dump.add_header("Parsing Warnings")
+            for warning in warnings:
+                dump.add_line(warning)
+                dump.add_newline()
+
+        dump.add_header("DOS_HEADER")
+        dump.add_lines(self.DOS_HEADER.dump())
+        dump.add_newline()
+
+        dump.add_header("NT_HEADERS")
+        dump.add_lines(self.NT_HEADERS.dump())
+        dump.add_newline()
+
+        dump.add_header("FILE_HEADER")
+        dump.add_lines(self.FILE_HEADER.dump())
+
+        image_flags = retrieve_flags(IMAGE_CHARACTERISTICS, "IMAGE_FILE_")
+
+        dump.add("Flags: ")
+        flags = []
+        for flag in sorted(image_flags):
+            if getattr(self.FILE_HEADER, flag[0]):
+                flags.append(flag[0])
+        dump.add_line(", ".join(flags))
+        dump.add_newline()
+
+        if hasattr(self, "OPTIONAL_HEADER") and self.OPTIONAL_HEADER is not None:
+            dump.add_header("OPTIONAL_HEADER")
+            dump.add_lines(self.OPTIONAL_HEADER.dump())
+
+        dll_characteristics_flags = retrieve_flags(
+            DLL_CHARACTERISTICS, "IMAGE_DLLCHARACTERISTICS_"
+        )
+
+        dump.add("DllCharacteristics: ")
+        flags = []
+        for flag in sorted(dll_characteristics_flags):
+            if getattr(self.OPTIONAL_HEADER, flag[0]):
+                flags.append(flag[0])
+        dump.add_line(", ".join(flags))
+        dump.add_newline()
+
+        dump.add_header("PE Sections")
+
+        section_flags = retrieve_flags(SECTION_CHARACTERISTICS, "IMAGE_SCN_")
+
+        for section in self.sections:
+            dump.add_lines(section.dump())
+            dump.add("Flags: ")
+            flags = []
+            for flag in sorted(section_flags):
+                if getattr(section, flag[0]):
+                    flags.append(flag[0])
+            dump.add_line(", ".join(flags))
+            dump.add_line(
+                "Entropy: {0:f} (Min=0.0, Max=8.0)".format(section.get_entropy())
+            )
+            if md5 is not None:
+                dump.add_line("MD5     hash: {0}".format(section.get_hash_md5()))
+            if sha1 is not None:
+                dump.add_line("SHA-1   hash: %s" % section.get_hash_sha1())
+            if sha256 is not None:
+                dump.add_line("SHA-256 hash: %s" % section.get_hash_sha256())
+            if sha512 is not None:
+                dump.add_line("SHA-512 hash: %s" % section.get_hash_sha512())
+            dump.add_newline()
+
+        if hasattr(self, "OPTIONAL_HEADER") and hasattr(
+            self.OPTIONAL_HEADER, "DATA_DIRECTORY"
+        ):
+
+            dump.add_header("Directories")
+            for directory in self.OPTIONAL_HEADER.DATA_DIRECTORY:
+                if directory is not None:
+                    dump.add_lines(directory.dump())
+            dump.add_newline()
+
+        if hasattr(self, "VS_VERSIONINFO"):
+            for idx, vinfo_entry in enumerate(self.VS_VERSIONINFO):
+                if len(self.VS_VERSIONINFO) > 1:
+                    dump.add_header(f"Version Information {idx + 1}")
+                else:
+                    dump.add_header("Version Information")
+                if vinfo_entry is not None:
+                    dump.add_lines(vinfo_entry.dump())
+                dump.add_newline()
+
+                if hasattr(self, "VS_FIXEDFILEINFO"):
+                    dump.add_lines(self.VS_FIXEDFILEINFO[idx].dump())
+                    dump.add_newline()
+
+                if hasattr(self, "FileInfo") and len(self.FileInfo) > idx:
+                    for entry in self.FileInfo[idx]:
+                        dump.add_lines(entry.dump())
+                        dump.add_newline()
+
+                        if hasattr(entry, "StringTable"):
+                            for st_entry in entry.StringTable:
+                                [dump.add_line("  " + line) for line in st_entry.dump()]
+                                dump.add_line(
+                                    "  LangID: {0}".format(
+                                        st_entry.LangID.decode(
+                                            encoding, "backslashreplace_"
+                                        )
+                                    )
+                                )
+                                dump.add_newline()
+                                for str_entry in sorted(list(st_entry.entries.items())):
+                                    # try:
+                                    dump.add_line(
+                                        "    {0}: {1}".format(
+                                            str_entry[0].decode(
+                                                encoding, "backslashreplace_"
+                                            ),
+                                            str_entry[1].decode(
+                                                encoding, "backslashreplace_"
+                                            ),
+                                        )
+                                    )
+
+                            dump.add_newline()
+
+                        elif hasattr(entry, "Var"):
+                            for var_entry in entry.Var:
+                                if hasattr(var_entry, "entry"):
+                                    [
+                                        dump.add_line("  " + line)
+                                        for line in var_entry.dump()
+                                    ]
+                                    dump.add_line(
+                                        "    {0}: {1}".format(
+                                            list(var_entry.entry.keys())[0].decode(
+                                                "utf-8", "backslashreplace_"
+                                            ),
+                                            list(var_entry.entry.values())[0],
+                                        )
+                                    )
+
+                            dump.add_newline()
+
+        if hasattr(self, "DIRECTORY_ENTRY_EXPORT"):
+            dump.add_header("Exported symbols")
+            dump.add_lines(self.DIRECTORY_ENTRY_EXPORT.struct.dump())
+            dump.add_newline()
+            dump.add_line("%-10s   %-10s  %s" % ("Ordinal", "RVA", "Name"))
+            for export in self.DIRECTORY_ENTRY_EXPORT.symbols:
+                if export.address is not None:
+                    name = b("None")
+                    if export.name:
+                        name = export.name
+                    dump.add(
+                        "%-10d 0x%08X    %s"
+                        % (export.ordinal, export.address, name.decode(encoding))
+                    )
+                    if export.forwarder:
+                        dump.add_line(
+                            " forwarder: {0}".format(
+                                export.forwarder.decode(encoding, "backslashreplace_")
+                            )
+                        )
+                    else:
+                        dump.add_newline()
+
+            dump.add_newline()
+
+        if hasattr(self, "DIRECTORY_ENTRY_IMPORT"):
+            dump.add_header("Imported symbols")
+            for module in self.DIRECTORY_ENTRY_IMPORT:
+                dump.add_lines(module.struct.dump())
+                # Print the name of the DLL if there are no imports.
+                if not module.imports:
+                    dump.add(
+                        "  Name -> {0}".format(
+                            self.get_string_at_rva(module.struct.Name).decode(
+                                encoding, "backslashreplace_"
+                            )
+                        )
+                    )
+                    dump.add_newline()
+                dump.add_newline()
+                for symbol in module.imports:
+                    if symbol.import_by_ordinal is True:
+                        if symbol.name is not None:
+                            dump.add(
+                                "{0}.{1} Ordinal[{2}] (Imported by Ordinal)".format(
+                                    module.dll.decode("utf-8"),
+                                    symbol.name.decode("utf-8"),
+                                    symbol.ordinal,
+                                )
+                            )
+                        else:
+                            dump.add(
+                                "{0} Ordinal[{1}] (Imported by Ordinal)".format(
+                                    module.dll.decode("utf-8"), symbol.ordinal
+                                )
+                            )
+                    else:
+                        dump.add(
+                            "{0}.{1} Hint[{2:d}]".format(
+                                module.dll.decode(encoding, "backslashreplace_"),
+                                symbol.name.decode(encoding, "backslashreplace_"),
+                                symbol.hint,
+                            )
+                        )
+
+                    if symbol.bound:
+                        dump.add_line(" Bound: 0x{0:08X}".format(symbol.bound))
+                    else:
+                        dump.add_newline()
+                dump.add_newline()
+
+        if hasattr(self, "DIRECTORY_ENTRY_BOUND_IMPORT"):
+            dump.add_header("Bound imports")
+            for bound_imp_desc in self.DIRECTORY_ENTRY_BOUND_IMPORT:
+
+                dump.add_lines(bound_imp_desc.struct.dump())
+                dump.add_line(
+                    "DLL: {0}".format(
+                        bound_imp_desc.name.decode(encoding, "backslashreplace_")
+                    )
+                )
+                dump.add_newline()
+
+                for bound_imp_ref in bound_imp_desc.entries:
+                    dump.add_lines(bound_imp_ref.struct.dump(), 4)
+                    dump.add_line(
+                        "DLL: {0}".format(
+                            bound_imp_ref.name.decode(encoding, "backslashreplace_")
+                        ),
+                        4,
+                    )
+                    dump.add_newline()
+
+        if hasattr(self, "DIRECTORY_ENTRY_DELAY_IMPORT"):
+            dump.add_header("Delay Imported symbols")
+            for module in self.DIRECTORY_ENTRY_DELAY_IMPORT:
+
+                dump.add_lines(module.struct.dump())
+                dump.add_newline()
+
+                for symbol in module.imports:
+                    if symbol.import_by_ordinal is True:
+                        dump.add(
+                            "{0} Ordinal[{1:d}] (Imported by Ordinal)".format(
+                                module.dll.decode(encoding, "backslashreplace_"),
+                                symbol.ordinal,
+                            )
+                        )
+                    else:
+                        dump.add(
+                            "{0}.{1} Hint[{2}]".format(
+                                module.dll.decode(encoding, "backslashreplace_"),
+                                symbol.name.decode(encoding, "backslashreplace_"),
+                                symbol.hint,
+                            )
+                        )
+
+                    if symbol.bound:
+                        dump.add_line(" Bound: 0x{0:08X}".format(symbol.bound))
+                    else:
+                        dump.add_newline()
+                dump.add_newline()
+
+        if hasattr(self, "DIRECTORY_ENTRY_RESOURCE"):
+            dump.add_header("Resource directory")
+
+            dump.add_lines(self.DIRECTORY_ENTRY_RESOURCE.struct.dump())
+
+            for res_type in self.DIRECTORY_ENTRY_RESOURCE.entries:
+
+                if res_type.name is not None:
+                    name = res_type.name.decode(encoding, "backslashreplace_")
+                    dump.add_line(
+                        f"Name: [{name}]",
+                        2,
+                    )
+                else:
+                    res_type_id = RESOURCE_TYPE.get(res_type.struct.Id, "-")
+                    dump.add_line(
+                        f"Id: [0x{res_type.struct.Id:X}] ({res_type_id})",
+                        2,
+                    )
+
+                dump.add_lines(res_type.struct.dump(), 2)
+
+                if hasattr(res_type, "directory"):
+
+                    dump.add_lines(res_type.directory.struct.dump(), 4)
+
+                    for resource_id in res_type.directory.entries:
+
+                        if resource_id.name is not None:
+                            name = resource_id.name.decode("utf-8", "backslashreplace_")
+                            dump.add_line(
+                                f"Name: [{name}]",
+                                6,
+                            )
+                        else:
+                            dump.add_line(f"Id: [0x{resource_id.struct.Id:X}]", 6)
+
+                        dump.add_lines(resource_id.struct.dump(), 6)
+
+                        if hasattr(resource_id, "directory"):
+                            dump.add_lines(resource_id.directory.struct.dump(), 8)
+
+                            for resource_lang in resource_id.directory.entries:
+                                if hasattr(resource_lang, "data"):
+                                    dump.add_line(
+                                        "\\--- LANG [%d,%d][%s,%s]"
+                                        % (
+                                            resource_lang.data.lang,
+                                            resource_lang.data.sublang,
+                                            LANG.get(
+                                                resource_lang.data.lang, "*unknown*"
+                                            ),
+                                            get_sublang_name_for_lang(
+                                                resource_lang.data.lang,
+                                                resource_lang.data.sublang,
+                                            ),
+                                        ),
+                                        8,
+                                    )
+                                    dump.add_lines(resource_lang.struct.dump(), 10)
+                                    dump.add_lines(resource_lang.data.struct.dump(), 12)
+                            if (
+                                hasattr(resource_id.directory, "strings")
+                                and resource_id.directory.strings
+                            ):
+                                dump.add_line("[STRINGS]", 10)
+                                for idx, res_string in list(
+                                    sorted(resource_id.directory.strings.items())
+                                ):
+                                    dump.add_line(
+                                        "{0:6d}: {1}".format(
+                                            idx,
+                                            res_string.encode(
+                                                "unicode-escape", "backslashreplace"
+                                            ).decode("ascii"),
+                                        ),
+                                        12,
+                                    )
+
+                dump.add_newline()
+
+            dump.add_newline()
+
+        if (
+            hasattr(self, "DIRECTORY_ENTRY_TLS")
+            and self.DIRECTORY_ENTRY_TLS
+            and self.DIRECTORY_ENTRY_TLS.struct
+        ):
+
+            dump.add_header("TLS")
+            dump.add_lines(self.DIRECTORY_ENTRY_TLS.struct.dump())
+            dump.add_newline()
+
+        if (
+            hasattr(self, "DIRECTORY_ENTRY_LOAD_CONFIG")
+            and self.DIRECTORY_ENTRY_LOAD_CONFIG
+            and self.DIRECTORY_ENTRY_LOAD_CONFIG.struct
+        ):
+
+            dump.add_header("LOAD_CONFIG")
+            dump.add_lines(self.DIRECTORY_ENTRY_LOAD_CONFIG.struct.dump())
+            dump.add_newline()
+
+        if hasattr(self, "DIRECTORY_ENTRY_DEBUG"):
+            dump.add_header("Debug information")
+            for dbg in self.DIRECTORY_ENTRY_DEBUG:
+                dump.add_lines(dbg.struct.dump())
+                try:
+                    dump.add_line("Type: " + DEBUG_TYPE[dbg.struct.Type])
+                except KeyError:
+                    dump.add_line("Type: 0x{0:x}(Unknown)".format(dbg.struct.Type))
+                dump.add_newline()
+                if dbg.entry:
+                    dump.add_lines(dbg.entry.dump(), 4)
+                    dump.add_newline()
+
+        if self.has_relocs():
+            dump.add_header("Base relocations")
+            for base_reloc in self.DIRECTORY_ENTRY_BASERELOC:
+                dump.add_lines(base_reloc.struct.dump())
+                for reloc in base_reloc.entries:
+                    try:
+                        dump.add_line(
+                            "%08Xh %s" % (reloc.rva, RELOCATION_TYPE[reloc.type][16:]),
+                            4,
+                        )
+                    except KeyError:
+                        dump.add_line(
+                            "0x%08X 0x%x(Unknown)" % (reloc.rva, reloc.type), 4
+                        )
+                dump.add_newline()
+
+        if (
+            hasattr(self, "DIRECTORY_ENTRY_EXCEPTION")
+            and len(self.DIRECTORY_ENTRY_EXCEPTION) > 0
+        ):
+            dump.add_header("Unwind data for exception handling")
+            for rf in self.DIRECTORY_ENTRY_EXCEPTION:
+                dump.add_lines(rf.struct.dump())
+                if hasattr(rf, "unwindinfo") and rf.unwindinfo is not None:
+                    dump.add_lines(rf.unwindinfo.dump(), 4)
+
+        return dump.get_text()
+
+    def dump_dict(self):
+        """Dump all the PE header information into a dictionary."""
+
+        dump_dict = {}
+
+        warnings = self.get_warnings()
+        if warnings:
+            dump_dict["Parsing Warnings"] = warnings
+
+        dump_dict["DOS_HEADER"] = self.DOS_HEADER.dump_dict()
+        dump_dict["NT_HEADERS"] = self.NT_HEADERS.dump_dict()
+        dump_dict["FILE_HEADER"] = self.FILE_HEADER.dump_dict()
+
+        image_flags = retrieve_flags(IMAGE_CHARACTERISTICS, "IMAGE_FILE_")
+
+        dump_dict["Flags"] = []
+        for flag in image_flags:
+            if getattr(self.FILE_HEADER, flag[0]):
+                dump_dict["Flags"].append(flag[0])
+
+        if hasattr(self, "OPTIONAL_HEADER") and self.OPTIONAL_HEADER is not None:
+            dump_dict["OPTIONAL_HEADER"] = self.OPTIONAL_HEADER.dump_dict()
+
+        dll_characteristics_flags = retrieve_flags(
+            DLL_CHARACTERISTICS, "IMAGE_DLLCHARACTERISTICS_"
+        )
+
+        dump_dict["DllCharacteristics"] = []
+        for flag in dll_characteristics_flags:
+            if getattr(self.OPTIONAL_HEADER, flag[0]):
+                dump_dict["DllCharacteristics"].append(flag[0])
+
+        dump_dict["PE Sections"] = []
+
+        section_flags = retrieve_flags(SECTION_CHARACTERISTICS, "IMAGE_SCN_")
+        for section in self.sections:
+            section_dict = section.dump_dict()
+            dump_dict["PE Sections"].append(section_dict)
+            section_dict["Flags"] = []
+            for flag in section_flags:
+                if getattr(section, flag[0]):
+                    section_dict["Flags"].append(flag[0])
+
+            section_dict["Entropy"] = section.get_entropy()
+            if md5 is not None:
+                section_dict["MD5"] = section.get_hash_md5()
+            if sha1 is not None:
+                section_dict["SHA1"] = section.get_hash_sha1()
+            if sha256 is not None:
+                section_dict["SHA256"] = section.get_hash_sha256()
+            if sha512 is not None:
+                section_dict["SHA512"] = section.get_hash_sha512()
+
+        if hasattr(self, "OPTIONAL_HEADER") and hasattr(
+            self.OPTIONAL_HEADER, "DATA_DIRECTORY"
+        ):
+
+            dump_dict["Directories"] = []
+
+            for idx, directory in enumerate(self.OPTIONAL_HEADER.DATA_DIRECTORY):
+                if directory is not None:
+                    dump_dict["Directories"].append(directory.dump_dict())
+
+        if hasattr(self, "VS_VERSIONINFO"):
+            dump_dict["Version Information"] = []
+            for idx, vs_vinfo in enumerate(self.VS_VERSIONINFO):
+                version_info_list = []
+                version_info_list.append(vs_vinfo.dump_dict())
+
+                if hasattr(self, "VS_FIXEDFILEINFO"):
+                    version_info_list.append(self.VS_FIXEDFILEINFO[idx].dump_dict())
+
+                if hasattr(self, "FileInfo") and len(self.FileInfo) > idx:
+                    fileinfo_list = []
+                    version_info_list.append(fileinfo_list)
+                    for entry in self.FileInfo[idx]:
+                        fileinfo_list.append(entry.dump_dict())
+
+                        if hasattr(entry, "StringTable"):
+                            stringtable_dict = {}
+                            for st_entry in entry.StringTable:
+                                fileinfo_list.extend(st_entry.dump_dict())
+                                stringtable_dict["LangID"] = st_entry.LangID
+                                for str_entry in list(st_entry.entries.items()):
+                                    stringtable_dict[str_entry[0]] = str_entry[1]
+                            fileinfo_list.append(stringtable_dict)
+
+                        elif hasattr(entry, "Var"):
+                            for var_entry in entry.Var:
+                                var_dict = {}
+                                if hasattr(var_entry, "entry"):
+                                    fileinfo_list.extend(var_entry.dump_dict())
+                                    var_dict[list(var_entry.entry.keys())[0]] = list(
+                                        var_entry.entry.values()
+                                    )[0]
+                                    fileinfo_list.append(var_dict)
+
+                dump_dict["Version Information"].append(version_info_list)
+
+        if hasattr(self, "DIRECTORY_ENTRY_EXPORT"):
+            dump_dict["Exported symbols"] = []
+            dump_dict["Exported symbols"].append(
+                self.DIRECTORY_ENTRY_EXPORT.struct.dump_dict()
+            )
+            for export in self.DIRECTORY_ENTRY_EXPORT.symbols:
+                export_dict = {}
+                if export.address is not None:
+                    export_dict.update(
+                        {
+                            "Ordinal": export.ordinal,
+                            "RVA": export.address,
+                            "Name": export.name,
+                        }
+                    )
+                    if export.forwarder:
+                        export_dict["forwarder"] = export.forwarder
+                dump_dict["Exported symbols"].append(export_dict)
+
+        if hasattr(self, "DIRECTORY_ENTRY_IMPORT"):
+            dump_dict["Imported symbols"] = []
+            for module in self.DIRECTORY_ENTRY_IMPORT:
+                import_list = []
+                dump_dict["Imported symbols"].append(import_list)
+                import_list.append(module.struct.dump_dict())
+                for symbol in module.imports:
+                    symbol_dict = {}
+                    if symbol.import_by_ordinal is True:
+                        symbol_dict["DLL"] = module.dll
+                        symbol_dict["Ordinal"] = symbol.ordinal
+                    else:
+                        symbol_dict["DLL"] = module.dll
+                        symbol_dict["Name"] = symbol.name
+                        symbol_dict["Hint"] = symbol.hint
+
+                    if symbol.bound:
+                        symbol_dict["Bound"] = symbol.bound
+                    import_list.append(symbol_dict)
+
+        if hasattr(self, "DIRECTORY_ENTRY_BOUND_IMPORT"):
+            dump_dict["Bound imports"] = []
+            for bound_imp_desc in self.DIRECTORY_ENTRY_BOUND_IMPORT:
+                bound_imp_desc_dict = {}
+                dump_dict["Bound imports"].append(bound_imp_desc_dict)
+
+                bound_imp_desc_dict.update(bound_imp_desc.struct.dump_dict())
+                bound_imp_desc_dict["DLL"] = bound_imp_desc.name
+
+                for bound_imp_ref in bound_imp_desc.entries:
+                    bound_imp_ref_dict = {}
+                    bound_imp_ref_dict.update(bound_imp_ref.struct.dump_dict())
+                    bound_imp_ref_dict["DLL"] = bound_imp_ref.name
+
+        if hasattr(self, "DIRECTORY_ENTRY_DELAY_IMPORT"):
+            dump_dict["Delay Imported symbols"] = []
+            for module in self.DIRECTORY_ENTRY_DELAY_IMPORT:
+                module_list = []
+                dump_dict["Delay Imported symbols"].append(module_list)
+                module_list.append(module.struct.dump_dict())
+
+                for symbol in module.imports:
+                    symbol_dict = {}
+                    if symbol.import_by_ordinal is True:
+                        symbol_dict["DLL"] = module.dll
+                        symbol_dict["Ordinal"] = symbol.ordinal
+                    else:
+                        symbol_dict["DLL"] = module.dll
+                        symbol_dict["Name"] = symbol.name
+                        symbol_dict["Hint"] = symbol.hint
+
+                    if symbol.bound:
+                        symbol_dict["Bound"] = symbol.bound
+                    module_list.append(symbol_dict)
+
+        if hasattr(self, "DIRECTORY_ENTRY_RESOURCE"):
+            dump_dict["Resource directory"] = []
+            dump_dict["Resource directory"].append(
+                self.DIRECTORY_ENTRY_RESOURCE.struct.dump_dict()
+            )
+
+            for res_type in self.DIRECTORY_ENTRY_RESOURCE.entries:
+                resource_type_dict = {}
+
+                if res_type.name is not None:
+                    resource_type_dict["Name"] = res_type.name
+                else:
+                    resource_type_dict["Id"] = (
+                        res_type.struct.Id,
+                        RESOURCE_TYPE.get(res_type.struct.Id, "-"),
+                    )
+
+                resource_type_dict.update(res_type.struct.dump_dict())
+                dump_dict["Resource directory"].append(resource_type_dict)
+
+                if hasattr(res_type, "directory"):
+                    directory_list = []
+                    directory_list.append(res_type.directory.struct.dump_dict())
+                    dump_dict["Resource directory"].append(directory_list)
+
+                    for resource_id in res_type.directory.entries:
+                        resource_id_dict = {}
+
+                        if resource_id.name is not None:
+                            resource_id_dict["Name"] = resource_id.name
+                        else:
+                            resource_id_dict["Id"] = resource_id.struct.Id
+
+                        resource_id_dict.update(resource_id.struct.dump_dict())
+                        directory_list.append(resource_id_dict)
+
+                        if hasattr(resource_id, "directory"):
+                            resource_id_list = []
+                            resource_id_list.append(
+                                resource_id.directory.struct.dump_dict()
+                            )
+                            directory_list.append(resource_id_list)
+
+                            for resource_lang in resource_id.directory.entries:
+                                if hasattr(resource_lang, "data"):
+                                    resource_lang_dict = {}
+                                    resource_lang_dict["LANG"] = resource_lang.data.lang
+                                    resource_lang_dict[
+                                        "SUBLANG"
+                                    ] = resource_lang.data.sublang
+                                    resource_lang_dict["LANG_NAME"] = LANG.get(
+                                        resource_lang.data.lang, "*unknown*"
+                                    )
+                                    resource_lang_dict[
+                                        "SUBLANG_NAME"
+                                    ] = get_sublang_name_for_lang(
+                                        resource_lang.data.lang,
+                                        resource_lang.data.sublang,
+                                    )
+                                    resource_lang_dict.update(
+                                        resource_lang.struct.dump_dict()
+                                    )
+                                    resource_lang_dict.update(
+                                        resource_lang.data.struct.dump_dict()
+                                    )
+                                    resource_id_list.append(resource_lang_dict)
+                            if (
+                                hasattr(resource_id.directory, "strings")
+                                and resource_id.directory.strings
+                            ):
+                                for idx, res_string in list(
+                                    resource_id.directory.strings.items()
+                                ):
+                                    resource_id_list.append(
+                                        res_string.encode(
+                                            "unicode-escape", "backslashreplace"
+                                        ).decode("ascii")
+                                    )
+
+        if (
+            hasattr(self, "DIRECTORY_ENTRY_TLS")
+            and self.DIRECTORY_ENTRY_TLS
+            and self.DIRECTORY_ENTRY_TLS.struct
+        ):
+            dump_dict["TLS"] = self.DIRECTORY_ENTRY_TLS.struct.dump_dict()
+
+        if (
+            hasattr(self, "DIRECTORY_ENTRY_LOAD_CONFIG")
+            and self.DIRECTORY_ENTRY_LOAD_CONFIG
+            and self.DIRECTORY_ENTRY_LOAD_CONFIG.struct
+        ):
+            dump_dict[
+                "LOAD_CONFIG"
+            ] = self.DIRECTORY_ENTRY_LOAD_CONFIG.struct.dump_dict()
+
+        if hasattr(self, "DIRECTORY_ENTRY_DEBUG"):
+            dump_dict["Debug information"] = []
+            for dbg in self.DIRECTORY_ENTRY_DEBUG:
+                dbg_dict = {}
+                dump_dict["Debug information"].append(dbg_dict)
+                dbg_dict.update(dbg.struct.dump_dict())
+                dbg_dict["Type"] = DEBUG_TYPE.get(dbg.struct.Type, dbg.struct.Type)
+
+        if self.has_relocs():
+            dump_dict["Base relocations"] = []
+            for base_reloc in self.DIRECTORY_ENTRY_BASERELOC:
+                base_reloc_list = []
+                dump_dict["Base relocations"].append(base_reloc_list)
+                base_reloc_list.append(base_reloc.struct.dump_dict())
+                for reloc in base_reloc.entries:
+                    reloc_dict = {}
+                    base_reloc_list.append(reloc_dict)
+                    reloc_dict["RVA"] = reloc.rva
+                    try:
+                        reloc_dict["Type"] = RELOCATION_TYPE[reloc.type][16:]
+                    except KeyError:
+                        reloc_dict["Type"] = reloc.type
+
+        return dump_dict
+
+    # OC Patch
+    def get_physical_by_rva(self, rva):
+        """Gets the physical address in the PE file from an RVA value."""
+        try:
+            return self.get_offset_from_rva(rva)
+        except Exception:
+            return None
+
+    ##
+    # Double-Word get / set
+    ##
+
+    def get_data_from_dword(self, dword):
+        """Return a four byte string representing the double word value (little endian)."""
+        return struct.pack(" len(data):
+            return None
+
+        return struct.unpack(" len(self.__data__):
+            return None
+
+        return self.get_dword_from_data(self.__data__[offset : offset + 4], 0)
+
+    def set_dword_at_rva(self, rva, dword):
+        """Set the double word value at the file offset corresponding to the given RVA."""
+        return self.set_bytes_at_rva(rva, self.get_data_from_dword(dword))
+
+    def set_dword_at_offset(self, offset, dword):
+        """Set the double word value at the given file offset."""
+        return self.set_bytes_at_offset(offset, self.get_data_from_dword(dword))
+
+    ##
+    # Word get / set
+    ##
+
+    def get_data_from_word(self, word):
+        """Return a two byte string representing the word value. (little endian)."""
+        return struct.pack(" len(data):
+            return None
+
+        return struct.unpack(" len(self.__data__):
+            return None
+
+        return self.get_word_from_data(self.__data__[offset : offset + 2], 0)
+
+    def set_word_at_rva(self, rva, word):
+        """Set the word value at the file offset corresponding to the given RVA."""
+        return self.set_bytes_at_rva(rva, self.get_data_from_word(word))
+
+    def set_word_at_offset(self, offset, word):
+        """Set the word value at the given file offset."""
+        return self.set_bytes_at_offset(offset, self.get_data_from_word(word))
+
+    ##
+    # Quad-Word get / set
+    ##
+
+    def get_data_from_qword(self, word):
+        """Return an eight byte string representing the quad-word value (little endian)."""
+        return struct.pack(" len(data):
+            return None
+
+        return struct.unpack(" len(self.__data__):
+            return None
+
+        return self.get_qword_from_data(self.__data__[offset : offset + 8], 0)
+
+    def set_qword_at_rva(self, rva, qword):
+        """Set the quad-word value at the file offset corresponding to the given RVA."""
+        return self.set_bytes_at_rva(rva, self.get_data_from_qword(qword))
+
+    def set_qword_at_offset(self, offset, qword):
+        """Set the quad-word value at the given file offset."""
+        return self.set_bytes_at_offset(offset, self.get_data_from_qword(qword))
+
+    ##
+    # Set bytes
+    ##
+
+    def set_bytes_at_rva(self, rva, data):
+        """Overwrite, with the given string, the bytes at the file offset corresponding
+        to the given RVA.
+
+        Return True if successful, False otherwise. It can fail if the
+        offset is outside the file's boundaries.
+        """
+
+        if not isinstance(data, bytes):
+            raise TypeError("data should be of type: bytes")
+
+        offset = self.get_physical_by_rva(rva)
+        if not offset:
+            return False
+
+        return self.set_bytes_at_offset(offset, data)
+
+    def set_bytes_at_offset(self, offset, data):
+        """Overwrite the bytes at the given file offset with the given string.
+
+        Return True if successful, False otherwise. It can fail if the
+        offset is outside the file's boundaries.
+        """
+
+        if not isinstance(data, bytes):
+            raise TypeError("data should be of type: bytes")
+
+        if 0 <= offset < len(self.__data__):
+            self.set_data_bytes(offset, data)
+        else:
+            return False
+
+        return True
+
+    def set_data_bytes(self, offset: int, data: bytes):
+        if not isinstance(self.__data__, bytearray):
+            self.__data__ = bytearray(self.__data__)
+
+        self.__data__[offset : offset + len(data)] = data
+
+    def merge_modified_section_data(self):
+        """Update the PE image content with any individual section data that has been
+        modified.
+        """
+
+        for section in self.sections:
+            section_data_start = self.adjust_FileAlignment(
+                section.PointerToRawData, self.OPTIONAL_HEADER.FileAlignment
+            )
+            section_data_end = section_data_start + section.SizeOfRawData
+            if section_data_start < len(self.__data__) and section_data_end < len(
+                self.__data__
+            ):
+                self.set_data_bytes(section_data_start, section.get_data())
+
+    def relocate_image(self, new_ImageBase):
+        """Apply the relocation information to the image using the provided image base.
+
+        This method will apply the relocation information to the image. Given the new
+        base, all the relocations will be processed and both the raw data and the
+        section's data will be fixed accordingly.
+        The resulting image can be retrieved as well through the method:
+
+            get_memory_mapped_image()
+
+        In order to get something that would more closely match what could be found in
+        memory once the Windows loader finished its work.
+        """
+
+        relocation_difference = new_ImageBase - self.OPTIONAL_HEADER.ImageBase
+
+        if (
+            len(self.OPTIONAL_HEADER.DATA_DIRECTORY) >= 6
+            and self.OPTIONAL_HEADER.DATA_DIRECTORY[5].Size
+        ):
+            if not hasattr(self, "DIRECTORY_ENTRY_BASERELOC"):
+                self.parse_data_directories(
+                    directories=[DIRECTORY_ENTRY["IMAGE_DIRECTORY_ENTRY_BASERELOC"]]
+                )
+            if not hasattr(self, "DIRECTORY_ENTRY_BASERELOC"):
+                self.__warnings.append(
+                    "Relocating image but PE does not have (or pefile cannot "
+                    "parse) a DIRECTORY_ENTRY_BASERELOC"
+                )
+            else:
+                for reloc in self.DIRECTORY_ENTRY_BASERELOC:
+
+                    # We iterate with an index because if the relocation is of type
+                    # IMAGE_REL_BASED_HIGHADJ we need to also process the next entry
+                    # at once and skip it for the next iteration
+                    #
+                    entry_idx = 0
+                    while entry_idx < len(reloc.entries):
+
+                        entry = reloc.entries[entry_idx]
+                        entry_idx += 1
+
+                        if entry.type == RELOCATION_TYPE["IMAGE_REL_BASED_ABSOLUTE"]:
+                            # Nothing to do for this type of relocation
+                            pass
+
+                        elif entry.type == RELOCATION_TYPE["IMAGE_REL_BASED_HIGH"]:
+                            # Fix the high 16-bits of a relocation
+                            #
+                            # Add high 16-bits of relocation_difference to the
+                            # 16-bit value at RVA=entry.rva
+
+                            self.set_word_at_rva(
+                                entry.rva,
+                                (
+                                    self.get_word_at_rva(entry.rva)
+                                    + relocation_difference
+                                    >> 16
+                                )
+                                & 0xFFFF,
+                            )
+
+                        elif entry.type == RELOCATION_TYPE["IMAGE_REL_BASED_LOW"]:
+                            # Fix the low 16-bits of a relocation
+                            #
+                            # Add low 16 bits of relocation_difference to the 16-bit
+                            # value at RVA=entry.rva
+
+                            self.set_word_at_rva(
+                                entry.rva,
+                                (
+                                    self.get_word_at_rva(entry.rva)
+                                    + relocation_difference
+                                )
+                                & 0xFFFF,
+                            )
+
+                        elif entry.type == RELOCATION_TYPE["IMAGE_REL_BASED_HIGHLOW"]:
+                            # Handle all high and low parts of a 32-bit relocation
+                            #
+                            # Add relocation_difference to the value at RVA=entry.rva
+
+                            self.set_dword_at_rva(
+                                entry.rva,
+                                self.get_dword_at_rva(entry.rva)
+                                + relocation_difference,
+                            )
+
+                        elif entry.type == RELOCATION_TYPE["IMAGE_REL_BASED_HIGHADJ"]:
+                            # Fix the high 16-bits of a relocation and adjust
+                            #
+                            # Add high 16-bits of relocation_difference to the 32-bit
+                            # value composed from the (16-bit value at
+                            # RVA=entry.rva)<<16 plus the 16-bit value at the next
+                            # relocation entry.
+
+                            # If the next entry is beyond the array's limits,
+                            # abort... the table is corrupt
+                            if entry_idx == len(reloc.entries):
+                                break
+
+                            next_entry = reloc.entries[entry_idx]
+                            entry_idx += 1
+                            self.set_word_at_rva(
+                                entry.rva,
+                                (
+                                    (self.get_word_at_rva(entry.rva) << 16)
+                                    + next_entry.rva
+                                    + relocation_difference
+                                    & 0xFFFF0000
+                                )
+                                >> 16,
+                            )
+
+                        elif entry.type == RELOCATION_TYPE["IMAGE_REL_BASED_DIR64"]:
+                            # Apply the difference to the 64-bit value at the offset
+                            # RVA=entry.rva
+
+                            self.set_qword_at_rva(
+                                entry.rva,
+                                self.get_qword_at_rva(entry.rva)
+                                + relocation_difference,
+                            )
+
+            self.OPTIONAL_HEADER.ImageBase = new_ImageBase
+
+            # correct VAs(virtual addresses) occurrences in directory information
+            if hasattr(self, "DIRECTORY_ENTRY_IMPORT"):
+                for dll in self.DIRECTORY_ENTRY_IMPORT:
+                    for func in dll.imports:
+                        func.address += relocation_difference
+            if hasattr(self, "DIRECTORY_ENTRY_TLS"):
+                self.DIRECTORY_ENTRY_TLS.struct.StartAddressOfRawData += (
+                    relocation_difference
+                )
+                self.DIRECTORY_ENTRY_TLS.struct.EndAddressOfRawData += (
+                    relocation_difference
+                )
+                self.DIRECTORY_ENTRY_TLS.struct.AddressOfIndex += relocation_difference
+                self.DIRECTORY_ENTRY_TLS.struct.AddressOfCallBacks += (
+                    relocation_difference
+                )
+            if hasattr(self, "DIRECTORY_ENTRY_LOAD_CONFIG"):
+                load_config = self.DIRECTORY_ENTRY_LOAD_CONFIG.struct
+                if (
+                    hasattr(load_config, "LockPrefixTable")
+                    and load_config.LockPrefixTable
+                ):
+                    load_config.LockPrefixTable += relocation_difference
+                if hasattr(load_config, "EditList") and load_config.EditList:
+                    load_config.EditList += relocation_difference
+                if (
+                    hasattr(load_config, "SecurityCookie")
+                    and load_config.SecurityCookie
+                ):
+                    load_config.SecurityCookie += relocation_difference
+                if (
+                    hasattr(load_config, "SEHandlerTable")
+                    and load_config.SEHandlerTable
+                ):
+                    load_config.SEHandlerTable += relocation_difference
+                if (
+                    hasattr(load_config, "GuardCFCheckFunctionPointer")
+                    and load_config.GuardCFCheckFunctionPointer
+                ):
+                    load_config.GuardCFCheckFunctionPointer += relocation_difference
+                if (
+                    hasattr(load_config, "GuardCFDispatchFunctionPointer")
+                    and load_config.GuardCFDispatchFunctionPointer
+                ):
+                    load_config.GuardCFDispatchFunctionPointer += relocation_difference
+                if (
+                    hasattr(load_config, "GuardCFFunctionTable")
+                    and load_config.GuardCFFunctionTable
+                ):
+                    load_config.GuardCFFunctionTable += relocation_difference
+                if (
+                    hasattr(load_config, "GuardAddressTakenIatEntryTable")
+                    and load_config.GuardAddressTakenIatEntryTable
+                ):
+                    load_config.GuardAddressTakenIatEntryTable += relocation_difference
+                if (
+                    hasattr(load_config, "GuardLongJumpTargetTable")
+                    and load_config.GuardLongJumpTargetTable
+                ):
+                    load_config.GuardLongJumpTargetTable += relocation_difference
+                if (
+                    hasattr(load_config, "DynamicValueRelocTable")
+                    and load_config.DynamicValueRelocTable
+                ):
+                    load_config.DynamicValueRelocTable += relocation_difference
+                if (
+                    self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE_PLUS
+                    and hasattr(load_config, "CHPEMetadataPointer")
+                    and load_config.CHPEMetadataPointer
+                ):
+                    load_config.CHPEMetadataPointer += relocation_difference
+                if (
+                    hasattr(load_config, "GuardRFFailureRoutine")
+                    and load_config.GuardRFFailureRoutine
+                ):
+                    load_config.GuardRFFailureRoutine += relocation_difference
+                if (
+                    hasattr(load_config, "GuardRFFailureRoutineFunctionPointer")
+                    and load_config.GuardRFFailureRoutineFunctionPointer
+                ):
+                    load_config.GuardRFVerifyStackPointerFunctionPointer += (
+                        relocation_difference
+                    )
+                if (
+                    hasattr(load_config, "GuardRFVerifyStackPointerFunctionPointer")
+                    and load_config.GuardRFVerifyStackPointerFunctionPointer
+                ):
+                    load_config.GuardRFVerifyStackPointerFunctionPointer += (
+                        relocation_difference
+                    )
+                if (
+                    hasattr(load_config, "EnclaveConfigurationPointer")
+                    and load_config.EnclaveConfigurationPointer
+                ):
+                    load_config.EnclaveConfigurationPointer += relocation_difference
+
+    def verify_checksum(self):
+
+        return self.OPTIONAL_HEADER.CheckSum == self.generate_checksum()
+
+    def generate_checksum(self):
+        # This will make sure that the data representing the PE image
+        # is updated with any changes that might have been made by
+        # assigning values to header fields as those are not automatically
+        # updated upon assignment.
+        #
+        # data = self.write()
+        # print('{0}'.format(len(data)))
+        # for idx, b in enumerate(data):
+        #     if b != ord(self.__data__[idx]) or (idx > 1244440 and idx < 1244460):
+        #         print('Idx: {0} G {1:02x} {3} B {2:02x}'.format(
+        #             idx, ord(self.__data__[idx]), b,
+        #             self.__data__[idx], chr(b)))
+        self.__data__ = self.write()
+
+        # Get the offset to the CheckSum field in the OptionalHeader
+        # (The offset is the same in PE32 and PE32+)
+        checksum_offset = self.OPTIONAL_HEADER.get_file_offset() + 0x40  # 64
+
+        checksum = 0
+        # Verify the data is dword-aligned. Add padding if needed
+        #
+        remainder = len(self.__data__) % 4
+        data_len = len(self.__data__) + ((4 - remainder) * (remainder != 0))
+
+        for i in range(int(data_len / 4)):
+            # Skip the checksum field
+            if i == int(checksum_offset / 4):
+                continue
+            if i + 1 == (int(data_len / 4)) and remainder:
+                dword = struct.unpack(
+                    "I", self.__data__[i * 4 :] + (b"\0" * (4 - remainder))
+                )[0]
+            else:
+                dword = struct.unpack("I", self.__data__[i * 4 : i * 4 + 4])[0]
+            # Optimized the calculation (thanks to Emmanuel Bourg for pointing it out!)
+            checksum += dword
+            if checksum >= 2**32:
+                checksum = (checksum & 0xFFFFFFFF) + (checksum >> 32)
+
+        checksum = (checksum & 0xFFFF) + (checksum >> 16)
+        checksum = (checksum) + (checksum >> 16)
+        checksum = checksum & 0xFFFF
+
+        # The length is the one of the original data, not the padded one
+        #
+        return checksum + len(self.__data__)
+
+    def is_exe(self):
+        """Check whether the file is a standard executable.
+
+        This will return true only if the file has the IMAGE_FILE_EXECUTABLE_IMAGE flag
+        set and the IMAGE_FILE_DLL not set and the file does not appear to be a driver
+        either.
+        """
+
+        EXE_flag = IMAGE_CHARACTERISTICS["IMAGE_FILE_EXECUTABLE_IMAGE"]
+
+        if (
+            (not self.is_dll())
+            and (not self.is_driver())
+            and (EXE_flag & self.FILE_HEADER.Characteristics) == EXE_flag
+        ):
+            return True
+
+        return False
+
+    def is_dll(self):
+        """Check whether the file is a standard DLL.
+
+        This will return true only if the image has the IMAGE_FILE_DLL flag set.
+        """
+
+        DLL_flag = IMAGE_CHARACTERISTICS["IMAGE_FILE_DLL"]
+
+        if (DLL_flag & self.FILE_HEADER.Characteristics) == DLL_flag:
+            return True
+
+        return False
+
+    def is_driver(self):
+        """Check whether the file is a Windows driver.
+
+        This will return true only if there are reliable indicators of the image
+        being a driver.
+        """
+
+        # Checking that the ImageBase field of the OptionalHeader is above or
+        # equal to 0x80000000 (that is, whether it lies in the upper 2GB of
+        # the address space, normally belonging to the kernel) is not a
+        # reliable enough indicator.  For instance, PEs that play the invalid
+        # ImageBase trick to get relocated could be incorrectly assumed to be
+        # drivers.
+
+        # This is not reliable either...
+        #
+        # if any((section.Characteristics &
+        #           SECTION_CHARACTERISTICS['IMAGE_SCN_MEM_NOT_PAGED']) for
+        #        section in self.sections ):
+        #    return True
+
+        # If the import directory was not parsed (fast_load = True); do it now.
+        if not hasattr(self, "DIRECTORY_ENTRY_IMPORT"):
+            self.parse_data_directories(
+                directories=[DIRECTORY_ENTRY["IMAGE_DIRECTORY_ENTRY_IMPORT"]]
+            )
+
+        # If there's still no import directory (the PE doesn't have one or it's
+        # malformed), give up.
+        if not hasattr(self, "DIRECTORY_ENTRY_IMPORT"):
+            return False
+
+        # self.DIRECTORY_ENTRY_IMPORT will now exist, although it may be empty.
+        # If it imports from "ntoskrnl.exe" or other kernel components it should
+        # be a driver
+        #
+        system_DLLs = set(
+            (b"ntoskrnl.exe", b"hal.dll", b"ndis.sys", b"bootvid.dll", b"kdcom.dll")
+        )
+        if system_DLLs.intersection(
+            [imp.dll.lower() for imp in self.DIRECTORY_ENTRY_IMPORT]
+        ):
+            return True
+
+        driver_like_section_names = set((b"page", b"paged"))
+        if driver_like_section_names.intersection(
+            [section.Name.lower().rstrip(b"\x00") for section in self.sections]
+        ) and (
+            self.OPTIONAL_HEADER.Subsystem
+            in (
+                SUBSYSTEM_TYPE["IMAGE_SUBSYSTEM_NATIVE"],
+                SUBSYSTEM_TYPE["IMAGE_SUBSYSTEM_NATIVE_WINDOWS"],
+            )
+        ):
+            return True
+
+        return False
+
+    def get_overlay_data_start_offset(self):
+        """Get the offset of data appended to the file and not contained within
+        the area described in the headers."""
+
+        largest_offset_and_size = (0, 0)
+
+        def update_if_sum_is_larger_and_within_file(
+            offset_and_size, file_size=len(self.__data__)
+        ):
+            if sum(offset_and_size) <= file_size and sum(offset_and_size) > sum(
+                largest_offset_and_size
+            ):
+                return offset_and_size
+            return largest_offset_and_size
+
+        if hasattr(self, "OPTIONAL_HEADER"):
+            largest_offset_and_size = update_if_sum_is_larger_and_within_file(
+                (
+                    self.OPTIONAL_HEADER.get_file_offset(),
+                    self.FILE_HEADER.SizeOfOptionalHeader,
+                )
+            )
+
+        for section in self.sections:
+            largest_offset_and_size = update_if_sum_is_larger_and_within_file(
+                (section.PointerToRawData, section.SizeOfRawData)
+            )
+
+        skip_directories = [DIRECTORY_ENTRY["IMAGE_DIRECTORY_ENTRY_SECURITY"]]
+
+        for idx, directory in enumerate(self.OPTIONAL_HEADER.DATA_DIRECTORY):
+            if idx in skip_directories:
+                continue
+            try:
+                largest_offset_and_size = update_if_sum_is_larger_and_within_file(
+                    (self.get_offset_from_rva(directory.VirtualAddress), directory.Size)
+                )
+            # Ignore directories with RVA out of file
+            except PEFormatError:
+                continue
+
+        if len(self.__data__) > sum(largest_offset_and_size):
+            return sum(largest_offset_and_size)
+
+        return None
+
+    def get_overlay(self):
+        """Get the data appended to the file and not contained within the area described
+        in the headers."""
+
+        overlay_data_offset = self.get_overlay_data_start_offset()
+
+        if overlay_data_offset is not None:
+            return self.__data__[overlay_data_offset:]
+
+        return None
+
+    def trim(self):
+        """Return the just data defined by the PE headers, removing any overlaid data."""
+
+        overlay_data_offset = self.get_overlay_data_start_offset()
+
+        if overlay_data_offset is not None:
+            return self.__data__[:overlay_data_offset]
+
+        return self.__data__[:]
+
+    # According to http://corkami.blogspot.com/2010/01/parce-que-la-planche-aura-brule.html
+    # if PointerToRawData is less that 0x200 it's rounded to zero. Loading the test file
+    # in a debugger it's easy to verify that the PointerToRawData value of 1 is rounded
+    # to zero. Hence we reproduce the behavior
+    #
+    # According to the document:
+    # [ Microsoft Portable Executable and Common Object File Format Specification ]
+    # "The alignment factor (in bytes) that is used to align the raw data of sections in
+    #  the image file. The value should be a power of 2 between 512 and 64 K, inclusive.
+    #  The default is 512. If the SectionAlignment is less than the architecture's page
+    #  size, then FileAlignment must match SectionAlignment."
+    #
+    # The following is a hard-coded constant if the Windows loader
+    def adjust_FileAlignment(self, val, file_alignment):
+        if file_alignment > FILE_ALIGNMENT_HARDCODED_VALUE:
+            # If it's not a power of two, report it:
+            if self.FileAlignment_Warning is False and not power_of_two(file_alignment):
+                self.__warnings.append(
+                    "If FileAlignment > 0x200 it should be a power of 2. Value: %x"
+                    % (file_alignment)
+                )
+                self.FileAlignment_Warning = True
+
+        return cache_adjust_FileAlignment(val, file_alignment)
+
+    # According to the document:
+    # [ Microsoft Portable Executable and Common Object File Format Specification ]
+    # "The alignment (in bytes) of sections when they are loaded into memory. It must be
+    #  greater than or equal to FileAlignment. The default is the page size for the
+    #  architecture."
+    #
+    def adjust_SectionAlignment(self, val, section_alignment, file_alignment):
+        if file_alignment < FILE_ALIGNMENT_HARDCODED_VALUE:
+            if (
+                file_alignment != section_alignment
+                and self.SectionAlignment_Warning is False
+            ):
+                self.__warnings.append(
+                    "If FileAlignment(%x) < 0x200 it should equal SectionAlignment(%x)"
+                    % (file_alignment, section_alignment)
+                )
+                self.SectionAlignment_Warning = True
+
+        return cache_adjust_SectionAlignment(val, section_alignment, file_alignment)
+
+
+def main():
+    import sys
+
+    usage = """\
+pefile.py 
+pefile.py exports """
+
+    if not sys.argv[1:]:
+        print(usage)
+    elif sys.argv[1] == "exports":
+        if not sys.argv[2:]:
+            sys.exit("error:  required")
+        pe = PE(sys.argv[2])
+        for exp in pe.DIRECTORY_ENTRY_EXPORT.symbols:
+            print(
+                hex(pe.OPTIONAL_HEADER.ImageBase + exp.address), exp.name, exp.ordinal
+            )
+    else:
+        print(PE(sys.argv[1]).dump_info())
+
+
+if __name__ == "__main__":
+    main()
diff --git a/venv/Lib/site-packages/peutils.py b/venv/Lib/site-packages/peutils.py
new file mode 100644
index 0000000..9170cb9
--- /dev/null
+++ b/venv/Lib/site-packages/peutils.py
@@ -0,0 +1,585 @@
+
+"""peutils, Portable Executable utilities module
+
+
+Copyright (c) 2005-2023 Ero Carrera 
+
+All rights reserved.
+"""
+import os
+import re
+import string
+import urllib.request, urllib.parse, urllib.error
+import pefile
+
+__author__ = "Ero Carrera"
+__version__ = pefile.__version__
+__contact__ = "ero.carrera@gmail.com"
+
+
+class SignatureDatabase(object):
+    """This class loads and keeps a parsed PEiD signature database.
+
+    Usage:
+
+        sig_db = SignatureDatabase('/path/to/signature/file')
+
+    and/or
+
+        sig_db = SignatureDatabase()
+        sig_db.load('/path/to/signature/file')
+
+    Signature databases can be combined by performing multiple loads.
+
+    The filename parameter can be a URL too. In that case the
+    signature database will be downloaded from that location.
+    """
+
+    def __init__(self, filename=None, data=None):
+
+        # RegExp to match a signature block
+        #
+        self.parse_sig = re.compile(
+            "\[(.*?)\]\s+?signature\s*=\s*(.*?)(\s+\?\?)*\s*ep_only\s*=\s*(\w+)(?:\s*section_start_only\s*=\s*(\w+)|)",
+            re.S,
+        )
+
+        # Signature information
+        #
+        # Signatures are stored as trees using dictionaries
+        # The keys are the byte values while the values for
+        # each key are either:
+        #
+        # - Other dictionaries of the same form for further
+        #   bytes in the signature
+        #
+        # - A dictionary with a string as a key (packer name)
+        #   and None as value to indicate a full signature
+        #
+        self.signature_tree_eponly_true = dict()
+        self.signature_count_eponly_true = 0
+        self.signature_tree_eponly_false = dict()
+        self.signature_count_eponly_false = 0
+        self.signature_tree_section_start = dict()
+        self.signature_count_section_start = 0
+
+        # The depth (length) of the longest signature
+        #
+        self.max_depth = 0
+
+        self.__load(filename=filename, data=data)
+
+    def generate_section_signatures(self, pe, name, sig_length=512):
+        """Generates signatures for all the sections in a PE file.
+
+        If the section contains any data a signature will be created
+        for it. The signature name will be a combination of the
+        parameter 'name' and the section number and its name.
+        """
+
+        section_signatures = list()
+
+        for idx, section in enumerate(pe.sections):
+
+            if section.SizeOfRawData < sig_length:
+                continue
+
+            # offset = pe.get_offset_from_rva(section.VirtualAddress)
+            offset = section.PointerToRawData
+
+            sig_name = "%s Section(%d/%d,%s)" % (
+                name,
+                idx + 1,
+                len(pe.sections),
+                "".join([c for c in section.Name if c in string.printable]),
+            )
+
+            section_signatures.append(
+                self.__generate_signature(
+                    pe,
+                    offset,
+                    sig_name,
+                    ep_only=False,
+                    section_start_only=True,
+                    sig_length=sig_length,
+                )
+            )
+
+        return "\n".join(section_signatures) + "\n"
+
+    def generate_ep_signature(self, pe, name, sig_length=512):
+        """Generate signatures for the entry point of a PE file.
+
+        Creates a signature whose name will be the parameter 'name'
+        and the section number and its name.
+        """
+
+        offset = pe.get_offset_from_rva(pe.OPTIONAL_HEADER.AddressOfEntryPoint)
+
+        return self.__generate_signature(
+            pe, offset, name, ep_only=True, sig_length=sig_length
+        )
+
+    def __generate_signature(
+        self, pe, offset, name, ep_only=False, section_start_only=False, sig_length=512
+    ):
+
+        data = pe.__data__[offset : offset + sig_length]
+
+        signature_bytes = " ".join(["%02x" % ord(c) for c in data])
+
+        if ep_only == True:
+            ep_only = "true"
+        else:
+            ep_only = "false"
+
+        if section_start_only == True:
+            section_start_only = "true"
+        else:
+            section_start_only = "false"
+
+        signature = "[%s]\nsignature = %s\nep_only = %s\nsection_start_only = %s\n" % (
+            name,
+            signature_bytes,
+            ep_only,
+            section_start_only,
+        )
+
+        return signature
+
+    def match(self, pe, ep_only=True, section_start_only=False):
+        """Matches and returns the exact match(es).
+
+        If ep_only is True the result will be a string with
+        the packer name. Otherwise it will be a list of the
+        form (file_offset, packer_name) specifying where
+        in the file the signature was found.
+        """
+
+        matches = self.__match(pe, ep_only, section_start_only)
+
+        # The last match (the most precise) from the
+        # list of matches (if any) is returned
+        #
+        if matches:
+            if ep_only == False:
+                # Get the most exact match for each list of matches
+                # at a given offset
+                #
+                return [(match[0], match[1][-1]) for match in matches]
+
+            return matches[1][-1]
+
+        return None
+
+    def match_all(self, pe, ep_only=True, section_start_only=False):
+        """Matches and returns all the likely matches."""
+
+        matches = self.__match(pe, ep_only, section_start_only)
+
+        if matches:
+            if ep_only == False:
+                # Get the most exact match for each list of matches
+                # at a given offset
+                #
+                return matches
+
+            return matches[1]
+
+        return None
+
+    def __match(self, pe, ep_only, section_start_only):
+
+        # Load the corresponding set of signatures
+        # Either the one for ep_only equal to True or
+        # to False
+        #
+        if section_start_only is True:
+
+            # Fetch the data of the executable as it'd
+            # look once loaded in memory
+            #
+            try:
+                data = pe.__data__
+            except Exception as excp:
+                raise
+
+            # Load the corresponding tree of signatures
+            #
+            signatures = self.signature_tree_section_start
+
+            # Set the starting address to start scanning from
+            #
+            scan_addresses = [section.PointerToRawData for section in pe.sections]
+
+        elif ep_only is True:
+
+            # Fetch the data of the executable as it'd
+            # look once loaded in memory
+            #
+            try:
+                data = pe.get_memory_mapped_image()
+            except Exception as excp:
+                raise
+
+            # Load the corresponding tree of signatures
+            #
+            signatures = self.signature_tree_eponly_true
+
+            # Fetch the entry point of the PE file and the data
+            # at the entry point
+            #
+            ep = pe.OPTIONAL_HEADER.AddressOfEntryPoint
+
+            # Set the starting address to start scanning from
+            #
+            scan_addresses = [ep]
+
+        else:
+
+            data = pe.__data__
+
+            signatures = self.signature_tree_eponly_false
+
+            scan_addresses = range(len(data))
+
+        # For each start address, check if any signature matches
+        #
+        matches = []
+        for idx in scan_addresses:
+            result = self.__match_signature_tree(
+                signatures, data[idx : idx + self.max_depth]
+            )
+            if result:
+                matches.append((idx, result))
+
+        # Return only the matched items found at the entry point if
+        # ep_only is True (matches will have only one element in that
+        # case)
+        #
+        if ep_only is True:
+            if matches:
+                return matches[0]
+
+        return matches
+
+    def match_data(self, code_data, ep_only=True, section_start_only=False):
+
+        data = code_data
+        scan_addresses = [0]
+
+        # Load the corresponding set of signatures
+        # Either the one for ep_only equal to True or
+        # to False
+        #
+        if section_start_only is True:
+
+            # Load the corresponding tree of signatures
+            #
+            signatures = self.signature_tree_section_start
+
+            # Set the starting address to start scanning from
+            #
+
+        elif ep_only is True:
+
+            # Load the corresponding tree of signatures
+            #
+            signatures = self.signature_tree_eponly_true
+
+        # For each start address, check if any signature matches
+        #
+        matches = []
+        for idx in scan_addresses:
+            result = self.__match_signature_tree(
+                signatures, data[idx : idx + self.max_depth]
+            )
+            if result:
+                matches.append((idx, result))
+
+        # Return only the matched items found at the entry point if
+        # ep_only is True (matches will have only one element in that
+        # case)
+        #
+        if ep_only is True:
+            if matches:
+                return matches[0]
+
+        return matches
+
+    def __match_signature_tree(self, signature_tree, data, depth=0):
+        """Recursive function to find matches along the signature tree.
+
+        signature_tree  is the part of the tree left to walk
+        data    is the data being checked against the signature tree
+        depth   keeps track of how far we have gone down the tree
+        """
+
+        matched_names = list()
+        match = signature_tree
+
+        # Walk the bytes in the data and match them
+        # against the signature
+        #
+        for idx, byte in enumerate([b if isinstance(b, int) else ord(b) for b in data]):
+
+            # If the tree is exhausted...
+            #
+            if match is None:
+                break
+
+            # Get the next byte in the tree
+            #
+            match_next = match.get(byte, None)
+
+            # If None is among the values for the key
+            # it means that a signature in the database
+            # ends here and that there's an exact match.
+            #
+            if None in list(match.values()):
+                # idx represent how deep we are in the tree
+                #
+                # names = [idx+depth]
+                names = list()
+
+                # For each of the item pairs we check
+                # if it has an element other than None,
+                # if not then we have an exact signature
+                #
+                for item in list(match.items()):
+                    if item[1] is None:
+                        names.append(item[0])
+                matched_names.append(names)
+
+            # If a wildcard is found keep scanning the signature
+            # ignoring the byte.
+            #
+            if "??" in match:
+                match_tree_alternate = match.get("??", None)
+                data_remaining = data[idx + 1 :]
+                if data_remaining:
+                    matched_names.extend(
+                        self.__match_signature_tree(
+                            match_tree_alternate, data_remaining, idx + depth + 1
+                        )
+                    )
+
+            match = match_next
+
+        # If we have any more packer name in the end of the signature tree
+        # add them to the matches
+        #
+        if match is not None and None in list(match.values()):
+            # names = [idx + depth + 1]
+            names = list()
+            for item in list(match.items()):
+                if item[1] is None:
+                    names.append(item[0])
+            matched_names.append(names)
+
+        return matched_names
+
+    def load(self, filename=None, data=None):
+        """Load a PEiD signature file.
+
+        Invoking this method on different files combines the signatures.
+        """
+
+        self.__load(filename=filename, data=data)
+
+    def __load(self, filename=None, data=None):
+
+        if filename is not None:
+            # If the path does not exist, attempt to open a URL
+            #
+            if not os.path.exists(filename):
+                try:
+                    sig_f = urllib.request.urlopen(filename)
+                    sig_data = sig_f.read()
+                    sig_f.close()
+                except IOError:
+                    # Let this be raised back to the user...
+                    raise
+            else:
+                # Get the data for a file
+                #
+                try:
+                    sig_f = open(filename, "rt")
+                    sig_data = sig_f.read()
+                    sig_f.close()
+                except IOError:
+                    # Let this be raised back to the user...
+                    raise
+        else:
+            sig_data = data
+
+        # If the file/URL could not be read or no "raw" data
+        # was provided there's nothing else to do
+        #
+        if not sig_data:
+            return
+
+        # Helper function to parse the signature bytes
+        #
+        def to_byte(value):
+            if "?" in value:
+                return value
+            return int(value, 16)
+
+        # Parse all the signatures in the file
+        #
+        matches = self.parse_sig.findall(sig_data)
+
+        # For each signature, get the details and load it into the
+        # signature tree
+        #
+        for (
+            packer_name,
+            signature,
+            superfluous_wildcards,
+            ep_only,
+            section_start_only,
+        ) in matches:
+
+            ep_only = ep_only.strip().lower()
+
+            signature = signature.replace("\\n", "").strip()
+
+            signature_bytes = [to_byte(b) for b in signature.split()]
+
+            if ep_only == "true":
+                ep_only = True
+            else:
+                ep_only = False
+
+            if section_start_only == "true":
+                section_start_only = True
+            else:
+                section_start_only = False
+
+            depth = 0
+
+            if section_start_only is True:
+
+                tree = self.signature_tree_section_start
+                self.signature_count_section_start += 1
+
+            else:
+                if ep_only is True:
+                    tree = self.signature_tree_eponly_true
+                    self.signature_count_eponly_true += 1
+                else:
+                    tree = self.signature_tree_eponly_false
+                    self.signature_count_eponly_false += 1
+
+            for idx, byte in enumerate(signature_bytes):
+
+                if idx + 1 == len(signature_bytes):
+
+                    tree[byte] = tree.get(byte, dict())
+                    tree[byte][packer_name] = None
+
+                else:
+
+                    tree[byte] = tree.get(byte, dict())
+
+                tree = tree[byte]
+                depth += 1
+
+            if depth > self.max_depth:
+                self.max_depth = depth
+
+
+def is_valid(pe):
+    """"""
+    pass
+
+
+def is_suspicious(pe):
+    """
+    unusual locations of import tables
+    non recognized section names
+    presence of long ASCII strings
+    """
+
+    relocations_overlap_entry_point = False
+    sequential_relocs = 0
+
+    # If relocation data is found and the entries go over the entry point, and also are very
+    # continuous or point outside section's boundaries => it might imply that an obfuscation
+    # trick is being used or the relocations are corrupt (maybe intentionally)
+    #
+    if hasattr(pe, "DIRECTORY_ENTRY_BASERELOC"):
+        for base_reloc in pe.DIRECTORY_ENTRY_BASERELOC:
+            last_reloc_rva = None
+            for reloc in base_reloc.entries:
+                if reloc.rva <= pe.OPTIONAL_HEADER.AddressOfEntryPoint <= reloc.rva + 4:
+                    relocations_overlap_entry_point = True
+
+                if (
+                    last_reloc_rva is not None
+                    and last_reloc_rva <= reloc.rva <= last_reloc_rva + 4
+                ):
+                    sequential_relocs += 1
+
+                last_reloc_rva = reloc.rva
+
+    # If import tables or strings exist (are pointed to) to within the header or in the area
+    # between the PE header and the first section that's suspicious
+    #
+    # IMPLEMENT
+
+    warnings_while_parsing = False
+    # If we have warnings, that's suspicious, some of those will be because of out-of-ordinary
+    # values are found in the PE header fields
+    # Things that are reported in warnings:
+    # (parsing problems, special section characteristics i.e. W & X, uncommon values of fields,
+    # unusual entrypoint, suspicious imports)
+    #
+    warnings = pe.get_warnings()
+    if warnings:
+        warnings_while_parsing
+
+    # If there are few or none (should come with a standard "density" of strings/kilobytes of data) longer (>8)
+    # ascii sequences that might indicate packed data, (this is similar to the entropy test in some ways but
+    # might help to discard cases of legitimate installer or compressed data)
+
+    # If compressed data (high entropy) and is_driver => uuuuhhh, nasty
+
+    pass
+
+
+def is_probably_packed(pe):
+    """Returns True is there is a high likelihood that a file is packed or contains compressed data.
+
+    The sections of the PE file will be analyzed, if enough sections
+    look like containing compressed data and the data makes
+    up for more than 20% of the total file size, the function will
+    return True.
+    """
+
+    # Calculate the length of the data up to the end of the last section in the
+    # file. Overlay data won't be taken into account
+    #
+    total_pe_data_length = len(pe.trim())
+    # Assume that the file is packed when no data is available
+    if not total_pe_data_length:
+        return True
+    has_significant_amount_of_compressed_data = False
+
+    # If some of the sections have high entropy and they make for more than 20% of the file's size
+    # it's assumed that it could be an installer or a packed file
+
+    total_compressed_data = 0
+    for section in pe.sections:
+        s_entropy = section.get_entropy()
+        s_length = len(section.get_data())
+        # The value of 7.4 is empirical, based on looking at a few files packed
+        # by different packers
+        if s_entropy > 7.4:
+            total_compressed_data += s_length
+
+    if (total_compressed_data / total_pe_data_length) > 0.2:
+        has_significant_amount_of_compressed_data = True
+
+    return has_significant_amount_of_compressed_data
diff --git a/venv/Lib/site-packages/pip-24.2.dist-info/AUTHORS.txt b/venv/Lib/site-packages/pip-24.3.1.dist-info/AUTHORS.txt
similarity index 99%
rename from venv/Lib/site-packages/pip-24.2.dist-info/AUTHORS.txt
rename to venv/Lib/site-packages/pip-24.3.1.dist-info/AUTHORS.txt
index dda2ac3..8ccefbc 100644
--- a/venv/Lib/site-packages/pip-24.2.dist-info/AUTHORS.txt
+++ b/venv/Lib/site-packages/pip-24.3.1.dist-info/AUTHORS.txt
@@ -57,6 +57,7 @@ Anthony Sottile
 Antoine Musso
 Anton Ovchinnikov
 Anton Patrushev
+Anton Zelenov
 Antonio Alvarado Hernandez
 Antony Lee
 Antti Kaihola
@@ -225,6 +226,7 @@ Diego Ramirez
 DiegoCaraballo
 Dimitri Merejkowsky
 Dimitri Papadopoulos
+Dimitri Papadopoulos Orfanos
 Dirk Stolle
 Dmitry Gladkov
 Dmitry Volodin
@@ -690,6 +692,7 @@ snook92
 socketubs
 Sorin Sbarnea
 Srinivas Nyayapati
+Srishti Hegde
 Stavros Korokithakis
 Stefan Scherfke
 Stefano Rivera
diff --git a/venv/Lib/site-packages/pip-24.3.1.dist-info/INSTALLER b/venv/Lib/site-packages/pip-24.3.1.dist-info/INSTALLER
new file mode 100644
index 0000000..a1b589e
--- /dev/null
+++ b/venv/Lib/site-packages/pip-24.3.1.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/venv/Lib/site-packages/pip-24.2.dist-info/LICENSE.txt b/venv/Lib/site-packages/pip-24.3.1.dist-info/LICENSE.txt
similarity index 100%
rename from venv/Lib/site-packages/pip-24.2.dist-info/LICENSE.txt
rename to venv/Lib/site-packages/pip-24.3.1.dist-info/LICENSE.txt
diff --git a/venv/Lib/site-packages/pip-24.2.dist-info/METADATA b/venv/Lib/site-packages/pip-24.3.1.dist-info/METADATA
similarity index 98%
rename from venv/Lib/site-packages/pip-24.2.dist-info/METADATA
rename to venv/Lib/site-packages/pip-24.3.1.dist-info/METADATA
index 6141107..9e5aa3a 100644
--- a/venv/Lib/site-packages/pip-24.2.dist-info/METADATA
+++ b/venv/Lib/site-packages/pip-24.3.1.dist-info/METADATA
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: pip
-Version: 24.2
+Version: 24.3.1
 Summary: The PyPA recommended tool for installing Python packages.
 Author-email: The pip developers 
 License: MIT
@@ -20,6 +20,7 @@ Classifier: Programming Language :: Python :: 3.9
 Classifier: Programming Language :: Python :: 3.10
 Classifier: Programming Language :: Python :: 3.11
 Classifier: Programming Language :: Python :: 3.12
+Classifier: Programming Language :: Python :: 3.13
 Classifier: Programming Language :: Python :: Implementation :: CPython
 Classifier: Programming Language :: Python :: Implementation :: PyPy
 Requires-Python: >=3.8
diff --git a/venv/Lib/site-packages/pip-24.2.dist-info/RECORD b/venv/Lib/site-packages/pip-24.3.1.dist-info/RECORD
similarity index 92%
rename from venv/Lib/site-packages/pip-24.2.dist-info/RECORD
rename to venv/Lib/site-packages/pip-24.3.1.dist-info/RECORD
index 54bc442..3a332cb 100644
--- a/venv/Lib/site-packages/pip-24.2.dist-info/RECORD
+++ b/venv/Lib/site-packages/pip-24.3.1.dist-info/RECORD
@@ -1,16 +1,16 @@
-../../Scripts/pip.exe,sha256=YQfW5tdtkSbt8ujVSiQQfVfbebzxnviBNRMfbIwFGyA,108409
-../../Scripts/pip3.11.exe,sha256=YQfW5tdtkSbt8ujVSiQQfVfbebzxnviBNRMfbIwFGyA,108409
-../../Scripts/pip3.exe,sha256=YQfW5tdtkSbt8ujVSiQQfVfbebzxnviBNRMfbIwFGyA,108409
-pip-24.2.dist-info/AUTHORS.txt,sha256=KDa8Pd3GDeKSogF6yFW0l9A9eMneLDOFrcIDqkL8G8s,10868
-pip-24.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
-pip-24.2.dist-info/LICENSE.txt,sha256=Y0MApmnUmurmWxLGxIySTFGkzfPR_whtw0VtyLyqIQQ,1093
-pip-24.2.dist-info/METADATA,sha256=PhzCxQxIhsnZ871cPUe3Hew9PhhpgflLbfqU3WizZqM,3624
-pip-24.2.dist-info/RECORD,,
-pip-24.2.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
-pip-24.2.dist-info/WHEEL,sha256=Wyh-_nZ0DJYolHNn1_hMa4lM7uDedD_RGVwbmTjyItk,91
-pip-24.2.dist-info/entry_points.txt,sha256=eeIjuzfnfR2PrhbjnbzFU6MnSS70kZLxwaHHq6M-bD0,87
-pip-24.2.dist-info/top_level.txt,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
-pip/__init__.py,sha256=EQxEGXUQIu-9fNJxVEK74ufx_fTk_HpYV9lAbw-WWbs,355
+../../Scripts/pip.exe,sha256=i27pIUFH6LIQbZG5ze0rXXFZhdkkuAHd9ahR2MT1KCQ,108409
+../../Scripts/pip3.11.exe,sha256=i27pIUFH6LIQbZG5ze0rXXFZhdkkuAHd9ahR2MT1KCQ,108409
+../../Scripts/pip3.exe,sha256=i27pIUFH6LIQbZG5ze0rXXFZhdkkuAHd9ahR2MT1KCQ,108409
+pip-24.3.1.dist-info/AUTHORS.txt,sha256=Cbb630k8EL9FkBzX9Vpi6hpYWrLSlh08eXodL5u0eLI,10925
+pip-24.3.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+pip-24.3.1.dist-info/LICENSE.txt,sha256=Y0MApmnUmurmWxLGxIySTFGkzfPR_whtw0VtyLyqIQQ,1093
+pip-24.3.1.dist-info/METADATA,sha256=V8iCNK1GYbC82PWsLMsASDh9AO4veocRlM4Pn9q2KFI,3677
+pip-24.3.1.dist-info/RECORD,,
+pip-24.3.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+pip-24.3.1.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
+pip-24.3.1.dist-info/entry_points.txt,sha256=eeIjuzfnfR2PrhbjnbzFU6MnSS70kZLxwaHHq6M-bD0,87
+pip-24.3.1.dist-info/top_level.txt,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+pip/__init__.py,sha256=faXY_neeYrA_88plEhkyhwAaYeds7wu5U1iGwP24J0s,357
 pip/__main__.py,sha256=WzbhHXTbSE6gBY19mNN9m4s5o_365LOvTYSgqgbdBhE,854
 pip/__pip-runner__.py,sha256=cPPWuJ6NK_k-GzfvlejLFgwzmYUROmpAR6QC3Q-vkXQ,1450
 pip/__pycache__/__init__.cpython-311.pyc,,
@@ -26,7 +26,7 @@ pip/_internal/__pycache__/main.cpython-311.pyc,,
 pip/_internal/__pycache__/pyproject.cpython-311.pyc,,
 pip/_internal/__pycache__/self_outdated_check.cpython-311.pyc,,
 pip/_internal/__pycache__/wheel_builder.cpython-311.pyc,,
-pip/_internal/build_env.py,sha256=QiusW8QEaj387y0hdRqVbuelHSHGYcT7WzVckbmMhR0,10420
+pip/_internal/build_env.py,sha256=wsTPOWyPTKvUREUcO585OU01kbQufpdigY8fVHv3WIw,10584
 pip/_internal/cache.py,sha256=Jb698p5PNigRtpW5o26wQNkkUv4MnQ94mc471wL63A0,10369
 pip/_internal/cli/__init__.py,sha256=FkHBgpxxb-_gd6r1FjnNhfMOzAUYyXoXKJ6abijfcFU,132
 pip/_internal/cli/__pycache__/__init__.cpython-311.pyc,,
@@ -46,11 +46,11 @@ pip/_internal/cli/autocompletion.py,sha256=Lli3Mr6aDNu7ZkJJFFvwD2-hFxNI6Avz8OwMy
 pip/_internal/cli/base_command.py,sha256=F8nUcSM-Y-MQljJUe724-yxmc5viFXHyM_zH70NmIh4,8289
 pip/_internal/cli/cmdoptions.py,sha256=mDqBr0d0hoztbRJs-PWtcKpqNAc7khU6ZpoesZKocT8,30110
 pip/_internal/cli/command_context.py,sha256=RHgIPwtObh5KhMrd3YZTkl8zbVG-6Okml7YbFX4Ehg0,774
-pip/_internal/cli/index_command.py,sha256=YIJ84cfYcbDBACnB8eoDgqjYJU6GpiWP2Rh7Ij-Xyak,5633
+pip/_internal/cli/index_command.py,sha256=-0oPTruZGkLSMrWDleZ6UtcKP3G-SImRRuhH0RfVE3o,5631
 pip/_internal/cli/main.py,sha256=BDZef-bWe9g9Jpr4OVs4dDf-845HJsKw835T7AqEnAc,2817
 pip/_internal/cli/main_parser.py,sha256=laDpsuBDl6kyfywp9eMMA9s84jfH2TJJn-vmL0GG90w,4338
-pip/_internal/cli/parser.py,sha256=QAkY6s8N-AD7w5D2PQm2Y8C2MIJSv7iuAeNjOMvDBUA,10811
-pip/_internal/cli/progress_bars.py,sha256=0FAf7eN67KnIv_gZQhTWSnKXXUzQko1ftGXEoLe5Yec,2713
+pip/_internal/cli/parser.py,sha256=VCMtduzECUV87KaHNu-xJ-wLNL82yT3x16V4XBxOAqI,10825
+pip/_internal/cli/progress_bars.py,sha256=VgydyqjZvfhqpuNcFDn00QNuA9GxRe9CKrRG8jhPuKU,2723
 pip/_internal/cli/req_command.py,sha256=DqeFhmUMs6o6Ev8qawAcOoYNdAZsfyKS0MZI5jsJYwQ,12250
 pip/_internal/cli/spinners.py,sha256=hIJ83GerdFgFCdobIA23Jggetegl_uC4Sp586nzFbPE,5118
 pip/_internal/cli/status_codes.py,sha256=sEFHUaUJbqv8iArL3HAtcztWZmGOFX01hTesSytDEh0,116
@@ -85,8 +85,8 @@ pip/_internal/commands/help.py,sha256=gcc6QDkcgHMOuAn5UxaZwAStsRBrnGSn_yxjS57JIo
 pip/_internal/commands/index.py,sha256=RAXxmJwFhVb5S1BYzb5ifX3sn9Na8v2CCVYwSMP8pao,4731
 pip/_internal/commands/inspect.py,sha256=PGrY9TRTRCM3y5Ml8Bdk8DEOXquWRfscr4DRo1LOTPc,3189
 pip/_internal/commands/install.py,sha256=iqesiLIZc6Op9uihMQFYRhAA2DQRZUxbM4z1BwXoFls,29428
-pip/_internal/commands/list.py,sha256=RgaIV4kN-eMSpgUAXc-6bjnURzl0v3cRE11xr54O9Cg,12771
-pip/_internal/commands/search.py,sha256=hSGtIHg26LRe468Ly7oZ6gfd9KbTxBRZAAtJc9Um6S4,5628
+pip/_internal/commands/list.py,sha256=oiIzSjLP6__d7dIS3q0Xb5ywsaOThBWRqMyjjKzkPdM,12769
+pip/_internal/commands/search.py,sha256=fWkUQVx_gm8ebbFAlCgqtxKXT9rNahpJ-BI__3HNZpg,5626
 pip/_internal/commands/show.py,sha256=IG9L5uo8w6UA4tI_IlmaxLCoNKPa5JNJCljj3NWs0OE,7507
 pip/_internal/commands/uninstall.py,sha256=7pOR7enK76gimyxQbzxcG1OsyLXL3DvX939xmM8Fvtg,3892
 pip/_internal/commands/wheel.py,sha256=eJRhr_qoNNxWAkkdJCNiQM7CXd4E1_YyQhsqJnBPGGg,6414
@@ -101,7 +101,7 @@ pip/_internal/distributions/base.py,sha256=QeB9qvKXDIjLdPBDE5fMgpfGqMMCr-govnuoQ
 pip/_internal/distributions/installed.py,sha256=QinHFbWAQ8oE0pbD8MFZWkwlnfU1QYTccA1vnhrlYOU,842
 pip/_internal/distributions/sdist.py,sha256=PlcP4a6-R6c98XnOM-b6Lkb3rsvh9iG4ok8shaanrzs,6751
 pip/_internal/distributions/wheel.py,sha256=THBYfnv7VVt8mYhMYUtH13S1E7FDwtDyDfmUcl8ai0E,1317
-pip/_internal/exceptions.py,sha256=6qcW3QgmFVlRxlZvDSLUhSzKJ7_Tedo-lyqWA6NfdAU,25371
+pip/_internal/exceptions.py,sha256=2_byISIv3kSnI_9T-Esfxrt0LnTRgcUHyxu0twsHjQY,26481
 pip/_internal/index/__init__.py,sha256=vpt-JeTZefh8a-FC22ZeBSXFVbuBcXSGiILhQZJaNpQ,30
 pip/_internal/index/__pycache__/__init__.cpython-311.pyc,,
 pip/_internal/index/__pycache__/collector.cpython-311.pyc,,
@@ -109,13 +109,13 @@ pip/_internal/index/__pycache__/package_finder.cpython-311.pyc,,
 pip/_internal/index/__pycache__/sources.cpython-311.pyc,,
 pip/_internal/index/collector.py,sha256=RdPO0JLAlmyBWPAWYHPyRoGjz3GNAeTngCNkbGey_mE,16265
 pip/_internal/index/package_finder.py,sha256=yRC4xsyudwKnNoU6IXvNoyqYo5ScT7lB6Wa-z2eh7cs,37666
-pip/_internal/index/sources.py,sha256=dJegiR9f86kslaAHcv9-R5L_XBf5Rzm_FkyPteDuPxI,8688
+pip/_internal/index/sources.py,sha256=lPBLK5Xiy8Q6IQMio26Wl7ocfZOKkgGklIBNyUJ23fI,8632
 pip/_internal/locations/__init__.py,sha256=UaAxeZ_f93FyouuFf4p7SXYF-4WstXuEvd3LbmPCAno,14925
 pip/_internal/locations/__pycache__/__init__.cpython-311.pyc,,
 pip/_internal/locations/__pycache__/_distutils.cpython-311.pyc,,
 pip/_internal/locations/__pycache__/_sysconfig.cpython-311.pyc,,
 pip/_internal/locations/__pycache__/base.cpython-311.pyc,,
-pip/_internal/locations/_distutils.py,sha256=H9ZHK_35rdDV1Qsmi4QeaBULjFT4Mbu6QuoVGkJ6QHI,6009
+pip/_internal/locations/_distutils.py,sha256=x6nyVLj7X11Y4khIdf-mFlxMl2FWadtVEgeb8upc_WI,6013
 pip/_internal/locations/_sysconfig.py,sha256=IGzds60qsFneRogC-oeBaY7bEh3lPt_v47kMJChQXsU,7724
 pip/_internal/locations/base.py,sha256=RQiPi1d4FVM2Bxk04dQhXZ2PqkeljEL2fZZ9SYqIQ78,2556
 pip/_internal/main.py,sha256=r-UnUe8HLo5XFJz8inTcOOTiu_sxNhgHb6VwlGUllOI,340
@@ -133,7 +133,7 @@ pip/_internal/metadata/importlib/__pycache__/_dists.cpython-311.pyc,,
 pip/_internal/metadata/importlib/__pycache__/_envs.cpython-311.pyc,,
 pip/_internal/metadata/importlib/_compat.py,sha256=c6av8sP8BBjAZuFSJow1iWfygUXNM3xRTCn5nqw6B9M,2796
 pip/_internal/metadata/importlib/_dists.py,sha256=anh0mLI-FYRPUhAdipd0Va3YJJc6HelCKQ0bFhY10a0,8017
-pip/_internal/metadata/importlib/_envs.py,sha256=JHjNfnk9RsjrcQw8dLBqdfBglOKSepEe9aq03B4nRpU,7431
+pip/_internal/metadata/importlib/_envs.py,sha256=UUB980XSrDWrMpQ1_G45i0r8Hqlg_tg3IPQ63mEqbNc,7431
 pip/_internal/metadata/pkg_resources.py,sha256=U07ETAINSGeSRBfWUG93E4tZZbaW_f7PGzEqZN0hulc,10542
 pip/_internal/models/__init__.py,sha256=3DHUd_qxpPozfzouoqa9g9ts1Czr5qaHfFxbnxriepM,63
 pip/_internal/models/__pycache__/__init__.cpython-311.pyc,,
@@ -158,7 +158,7 @@ pip/_internal/models/scheme.py,sha256=PakmHJM3e8OOWSZFtfz1Az7f1meONJnkGuQxFlt3wB
 pip/_internal/models/search_scope.py,sha256=67NEnsYY84784S-MM7ekQuo9KXLH-7MzFntXjapvAo0,4531
 pip/_internal/models/selection_prefs.py,sha256=qaFfDs3ciqoXPg6xx45N1jPLqccLJw4N0s4P0PyHTQ8,2015
 pip/_internal/models/target_python.py,sha256=2XaH2rZ5ZF-K5wcJbEMGEl7SqrTToDDNkrtQ2v_v_-Q,4271
-pip/_internal/models/wheel.py,sha256=Odc1NVWL5N-i6A3vFa50BfNvCRlGvGa4som60FQM198,3601
+pip/_internal/models/wheel.py,sha256=G7dND_s4ebPkEL7RJ1qCY0QhUUWIIK6AnjWgRATF5no,4539
 pip/_internal/network/__init__.py,sha256=jf6Tt5nV_7zkARBrKojIXItgejvoegVJVKUbhAa5Ioc,50
 pip/_internal/network/__pycache__/__init__.cpython-311.pyc,,
 pip/_internal/network/__pycache__/auth.cpython-311.pyc,,
@@ -171,7 +171,7 @@ pip/_internal/network/__pycache__/xmlrpc.cpython-311.pyc,,
 pip/_internal/network/auth.py,sha256=D4gASjUrqoDFlSt6gQ767KAAjv6PUyJU0puDlhXNVRE,20809
 pip/_internal/network/cache.py,sha256=48A971qCzKNFvkb57uGEk7-0xaqPS0HWj2711QNTxkU,3935
 pip/_internal/network/download.py,sha256=FLOP29dPYECBiAi7eEjvAbNkyzaKNqbyjOT2m8HPW8U,6048
-pip/_internal/network/lazy_wheel.py,sha256=2PXVduYZPCPZkkQFe1J1GbfHJWeCU--FXonGyIfw9eU,7638
+pip/_internal/network/lazy_wheel.py,sha256=PBdoMoNQQIA84Fhgne38jWF52W4x_KtsHjxgv4dkRKA,7622
 pip/_internal/network/session.py,sha256=XmanBKjVwPFmh1iJ58q6TDh9xabH37gREuQJ_feuZGA,18741
 pip/_internal/network/utils.py,sha256=Inaxel-NxBu4PQWkjyErdnfewsFCcgHph7dzR1-FboY,4088
 pip/_internal/network/xmlrpc.py,sha256=sAxzOacJ-N1NXGPvap9jC3zuYWSnnv3GXtgR2-E2APA,1838
@@ -213,8 +213,8 @@ pip/_internal/req/__pycache__/req_file.cpython-311.pyc,,
 pip/_internal/req/__pycache__/req_install.cpython-311.pyc,,
 pip/_internal/req/__pycache__/req_set.cpython-311.pyc,,
 pip/_internal/req/__pycache__/req_uninstall.cpython-311.pyc,,
-pip/_internal/req/constructors.py,sha256=qXNZtUqhsXpHxkRaIQhp20_Kz6I88MDKM8SQR9fckIc,18424
-pip/_internal/req/req_file.py,sha256=hnC9Oz-trqGQpuDnCVWqwpJkAvtbCsk7-5k0EWVQhlQ,17687
+pip/_internal/req/constructors.py,sha256=v1qzCN1mIldwx-nCrPc8JO4lxkm3Fv8M5RWvt8LISjc,18430
+pip/_internal/req/req_file.py,sha256=gOOJTzL-mDRPcQhjwqjDrjn4V-3rK9TnEFnU3v8RA4Q,18752
 pip/_internal/req/req_install.py,sha256=yhT98NGDoAEk03jznTJnYCznzhiMEEA2ocgsUG_dcNU,35788
 pip/_internal/req/req_set.py,sha256=j3esG0s6SzoVReX9rWn4rpYNtyET_fwxbwJPRimvRxo,2858
 pip/_internal/req/req_uninstall.py,sha256=qzDIxJo-OETWqGais7tSMCDcWbATYABT-Tid3ityF0s,23853
@@ -237,8 +237,8 @@ pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-311.pyc,,
 pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-311.pyc,,
 pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-311.pyc,,
 pip/_internal/resolution/resolvelib/base.py,sha256=DCf669FsqyQY5uqXeePDHQY1e4QO-pBzWH8O0s9-K94,5023
-pip/_internal/resolution/resolvelib/candidates.py,sha256=07CBc85ya3J19XqdvUsLQwtVIxiTYq9km9hbTRh0jb0,19823
-pip/_internal/resolution/resolvelib/factory.py,sha256=mTTq_nG1F9Eq3VnlYPH6Ap-mydcS-mxC5y5L-CLLp80,32459
+pip/_internal/resolution/resolvelib/candidates.py,sha256=5UZ1upNnmqsP-nmEZaDYxaBgCoejw_e2WVGmmAvBxXc,20001
+pip/_internal/resolution/resolvelib/factory.py,sha256=511CaUR41LqjALuFafLVfx15WRvMhxYTdjQCoSvp4gw,32661
 pip/_internal/resolution/resolvelib/found_candidates.py,sha256=9hrTyQqFvl9I7Tji79F1AxHv39Qh1rkJ_7deSHSMfQc,6383
 pip/_internal/resolution/resolvelib/provider.py,sha256=bcsFnYvlmtB80cwVdW1fIwgol8ZNr1f1VHyRTkz47SM,9935
 pip/_internal/resolution/resolvelib/reporter.py,sha256=00JtoXEkTlw0-rl_sl54d71avwOsJHt9GGHcrj5Sza0,3168
@@ -277,7 +277,7 @@ pip/_internal/utils/_jaraco_text.py,sha256=M15uUPIh5NpP1tdUGBxRau6q1ZAEtI8-XyLEE
 pip/_internal/utils/_log.py,sha256=-jHLOE_THaZz5BFcCnoSL9EYAtJ0nXem49s9of4jvKw,1015
 pip/_internal/utils/appdirs.py,sha256=swgcTKOm3daLeXTW6v5BUS2Ti2RvEnGRQYH_yDXklAo,1665
 pip/_internal/utils/compat.py,sha256=ckkFveBiYQjRWjkNsajt_oWPS57tJvE8XxoC4OIYgCY,2399
-pip/_internal/utils/compatibility_tags.py,sha256=ydin8QG8BHqYRsPY4OL6cmb44CbqXl1T0xxS97VhHkk,5377
+pip/_internal/utils/compatibility_tags.py,sha256=OWq5axHpW-MEEPztGdvgADrgJPAcV9a88Rxm4Z8VBs8,6272
 pip/_internal/utils/datetime.py,sha256=m21Y3wAtQc-ji6Veb6k_M5g6A0ZyFI4egchTdnwh-pQ,242
 pip/_internal/utils/deprecation.py,sha256=k7Qg_UBAaaTdyq82YVARA6D7RmcGTXGv7fnfcgigj4Q,3707
 pip/_internal/utils/direct_url_helpers.py,sha256=r2MRtkVDACv9AGqYODBUC9CjwgtsUU1s68hmgfCJMtA,3196
@@ -289,7 +289,7 @@ pip/_internal/utils/filetypes.py,sha256=i8XAQ0eFCog26Fw9yV0Yb1ygAqKYB1w9Cz9n0fj8
 pip/_internal/utils/glibc.py,sha256=vUkWq_1pJuzcYNcGKLlQmABoUiisK8noYY1yc8Wq4w4,3734
 pip/_internal/utils/hashes.py,sha256=XGGLL0AG8-RhWnyz87xF6MFZ--BKadHU35D47eApCKI,4972
 pip/_internal/utils/logging.py,sha256=7BFKB1uFjdxD5crM-GtwA5T2qjbQ2LPD-gJDuJeDNTg,11606
-pip/_internal/utils/misc.py,sha256=HR_V97vNTHNzwq01JrnTZtsLLkWAOJ9_EeYfHJZSgDY,23745
+pip/_internal/utils/misc.py,sha256=NRV0_2fFhzy1jhvInSBv4dqCmTwct8PV7Kp0m-BPRGM,23530
 pip/_internal/utils/packaging.py,sha256=iI3LH43lVNR4hWBOqF6lFsZq4aycb2j0UcHlmDmcqUg,2109
 pip/_internal/utils/retry.py,sha256=mhFbykXjhTnZfgzeuy-vl9c8nECnYn_CMtwNJX2tYzQ,1392
 pip/_internal/utils/setuptools_build.py,sha256=ouXpud-jeS8xPyTPsXJ-m34NPvK5os45otAzdSV_IJE,4435
@@ -340,15 +340,15 @@ pip/_vendor/cachecontrol/heuristics.py,sha256=IYe4QmHERWsMvtxNrp920WeaIsaTTyqLB1
 pip/_vendor/cachecontrol/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
 pip/_vendor/cachecontrol/serialize.py,sha256=HQd2IllQ05HzPkVLMXTF2uX5mjEQjDBkxCqUJUODpZk,5163
 pip/_vendor/cachecontrol/wrapper.py,sha256=hsGc7g8QGQTT-4f8tgz3AM5qwScg6FO0BSdLSRdEvpU,1417
-pip/_vendor/certifi/__init__.py,sha256=LHXz7E80YJYBzCBv6ZyidQ5-ciYSkSebpY2E5OM0l7o,94
+pip/_vendor/certifi/__init__.py,sha256=p_GYZrjUwPBUhpLlCZoGb0miKBKSqDAyZC5DvIuqbHQ,94
 pip/_vendor/certifi/__main__.py,sha256=1k3Cr95vCxxGRGDljrW3wMdpZdL3Nhf0u1n-k2qdsCY,255
 pip/_vendor/certifi/__pycache__/__init__.cpython-311.pyc,,
 pip/_vendor/certifi/__pycache__/__main__.cpython-311.pyc,,
 pip/_vendor/certifi/__pycache__/core.cpython-311.pyc,,
-pip/_vendor/certifi/cacert.pem,sha256=SIupYGAr8HzGP073rsEIaS_sQYIPwzKKjj894DgUmu4,291528
+pip/_vendor/certifi/cacert.pem,sha256=lO3rZukXdPyuk6BWUJFOKQliWaXH6HGh9l1GGrUgG0c,299427
 pip/_vendor/certifi/core.py,sha256=2SRT5rIcQChFDbe37BQa-kULxAgJ8qN6l1jfqTp4HIs,4486
 pip/_vendor/certifi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
-pip/_vendor/distlib/__init__.py,sha256=hJKF7FHoqbmGckncDuEINWo_OYkDNiHODtYXSMcvjcc,625
+pip/_vendor/distlib/__init__.py,sha256=dcwgYGYGQqAEawBXPDtIx80DO_3cOmFv8HTc8JMzknQ,625
 pip/_vendor/distlib/__pycache__/__init__.cpython-311.pyc,,
 pip/_vendor/distlib/__pycache__/compat.cpython-311.pyc,,
 pip/_vendor/distlib/__pycache__/database.cpython-311.pyc,,
@@ -362,24 +362,24 @@ pip/_vendor/distlib/__pycache__/scripts.cpython-311.pyc,,
 pip/_vendor/distlib/__pycache__/util.cpython-311.pyc,,
 pip/_vendor/distlib/__pycache__/version.cpython-311.pyc,,
 pip/_vendor/distlib/__pycache__/wheel.cpython-311.pyc,,
-pip/_vendor/distlib/compat.py,sha256=Un-uIBvy02w-D267OG4VEhuddqWgKj9nNkxVltAb75w,41487
-pip/_vendor/distlib/database.py,sha256=0V9Qvs0Vrxa2F_-hLWitIyVyRifJ0pCxyOI-kEOBwsA,51965
+pip/_vendor/distlib/compat.py,sha256=2jRSjRI4o-vlXeTK2BCGIUhkc6e9ZGhSsacRM5oseTw,41467
+pip/_vendor/distlib/database.py,sha256=mHy_LxiXIsIVRb-T0-idBrVLw3Ffij5teHCpbjmJ9YU,51160
 pip/_vendor/distlib/index.py,sha256=lTbw268rRhj8dw1sib3VZ_0EhSGgoJO3FKJzSFMOaeA,20797
-pip/_vendor/distlib/locators.py,sha256=o1r_M86_bRLafSpetmyfX8KRtFu-_Q58abvQrnOSnbA,51767
+pip/_vendor/distlib/locators.py,sha256=oBeAZpFuPQSY09MgNnLfQGGAXXvVO96BFpZyKMuK4tM,51026
 pip/_vendor/distlib/manifest.py,sha256=3qfmAmVwxRqU1o23AlfXrQGZzh6g_GGzTAP_Hb9C5zQ,14168
-pip/_vendor/distlib/markers.py,sha256=n3DfOh1yvZ_8EW7atMyoYeZFXjYla0Nz0itQlojCd0A,5268
-pip/_vendor/distlib/metadata.py,sha256=pB9WZ9mBfmQxc9OVIldLS5CjOoQRvKAvUwwQyKwKQtQ,39693
+pip/_vendor/distlib/markers.py,sha256=X6sDvkFGcYS8gUW8hfsWuKEKAqhQZAJ7iXOMLxRYjYk,5164
+pip/_vendor/distlib/metadata.py,sha256=zil3sg2EUfLXVigljY2d_03IJt-JSs7nX-73fECMX2s,38724
 pip/_vendor/distlib/resources.py,sha256=LwbPksc0A1JMbi6XnuPdMBUn83X7BPuFNWqPGEKI698,10820
-pip/_vendor/distlib/scripts.py,sha256=8_gP9J7_tlNRicnWmPX4ZiDlP5wTwJKDeeg-8_qXUZU,18780
+pip/_vendor/distlib/scripts.py,sha256=BJliaDAZaVB7WAkwokgC3HXwLD2iWiHaVI50H7C6eG8,18608
 pip/_vendor/distlib/t32.exe,sha256=a0GV5kCoWsMutvliiCKmIgV98eRZ33wXoS-XrqvJQVs,97792
 pip/_vendor/distlib/t64-arm.exe,sha256=68TAa32V504xVBnufojh0PcenpR3U4wAqTqf-MZqbPw,182784
 pip/_vendor/distlib/t64.exe,sha256=gaYY8hy4fbkHYTTnA4i26ct8IQZzkBG2pRdy0iyuBrc,108032
-pip/_vendor/distlib/util.py,sha256=XSznxEi_i3T20UJuaVc0qXHz5ksGUCW1khYlBprN_QE,67530
-pip/_vendor/distlib/version.py,sha256=9pXkduchve_aN7JG6iL9VTYV_kqNSGoc2Dwl8JuySnQ,23747
+pip/_vendor/distlib/util.py,sha256=vMPGvsS4j9hF6Y9k3Tyom1aaHLb0rFmZAEyzeAdel9w,66682
+pip/_vendor/distlib/version.py,sha256=s5VIs8wBn0fxzGxWM_aA2ZZyx525HcZbMvcTlTyZ3Rg,23727
 pip/_vendor/distlib/w32.exe,sha256=R4csx3-OGM9kL4aPIzQKRo5TfmRSHZo6QWyLhDhNBks,91648
 pip/_vendor/distlib/w64-arm.exe,sha256=xdyYhKj0WDcVUOCb05blQYvzdYIKMbmJn2SZvzkcey4,168448
 pip/_vendor/distlib/w64.exe,sha256=ejGf-rojoBfXseGLpya6bFTFPWRG21X5KvU8J5iU-K0,101888
-pip/_vendor/distlib/wheel.py,sha256=FVQCve8u-L0QYk5-YTZc7s4WmNQdvjRWTK08KXzZVX4,43958
+pip/_vendor/distlib/wheel.py,sha256=DFIVguEQHCdxnSdAO0dfFsgMcvVZitg7bCOuLwZ7A_s,43979
 pip/_vendor/distro/__init__.py,sha256=2fHjF-SfgPvjyNZ1iHh_wjqWdR_Yo5ODHwZC0jLBPhc,981
 pip/_vendor/distro/__main__.py,sha256=bu9d3TifoKciZFcqRBuygV3GSuThnVD_m2IK4cz96Vs,64
 pip/_vendor/distro/__pycache__/__init__.cpython-311.pyc,,
@@ -438,7 +438,7 @@ pip/_vendor/packaging/metadata.py,sha256=KINuSkJ12u-SyoKNTy_pHNGAfMUtxNvZ53qA1zA
 pip/_vendor/packaging/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
 pip/_vendor/packaging/requirements.py,sha256=gYyRSAdbrIyKDY66ugIDUQjRMvxkH2ALioTmX3tnL6o,2947
 pip/_vendor/packaging/specifiers.py,sha256=HfGgfNJRvrzC759gnnoojHyiWs_DYmcw5PEh5jHH-YE,39738
-pip/_vendor/packaging/tags.py,sha256=y8EbheOu9WS7s-MebaXMcHMF-jzsA_C1Lz5XRTiSy4w,18883
+pip/_vendor/packaging/tags.py,sha256=Fo6_cit95-7QfcMb16XtI7AUiSMgdwA_hCO_9lV2pz4,21388
 pip/_vendor/packaging/utils.py,sha256=NAdYUwnlAOpkat_RthavX8a07YuVxgGL_vwrx73GSDM,5287
 pip/_vendor/packaging/version.py,sha256=wE4sSVlF-d1H6HFC1vszEe35CwTig_fh4HHIFg95hFE,16210
 pip/_vendor/pkg_resources/__init__.py,sha256=jrhDRbOubP74QuPXxd7U7Po42PH2l-LZ2XfcO7llpZ4,124463
@@ -757,18 +757,18 @@ pip/_vendor/tomli/_parser.py,sha256=g9-ENaALS-B8dokYpCuzUFalWlog7T-SIYMjLZSWrtM,
 pip/_vendor/tomli/_re.py,sha256=dbjg5ChZT23Ka9z9DHOXfdtSpPwUfdgMXnj8NOoly-w,2943
 pip/_vendor/tomli/_types.py,sha256=-GTG2VUqkpxwMqzmVO4F7ybKddIbAnuAHXfmWQcTi3Q,254
 pip/_vendor/tomli/py.typed,sha256=8PjyZ1aVoQpRVvt71muvuq5qE-jTFZkK-GLHkhdebmc,26
-pip/_vendor/truststore/__init__.py,sha256=M-PhuLMIF7gxKXk7tpo2MD7dk6nqG1ae8GXWdNXbMdQ,403
+pip/_vendor/truststore/__init__.py,sha256=WIDeyzWm7EVX44g354M25vpRXbeY1lsPH6EmUJUcq4o,1264
 pip/_vendor/truststore/__pycache__/__init__.cpython-311.pyc,,
 pip/_vendor/truststore/__pycache__/_api.cpython-311.pyc,,
 pip/_vendor/truststore/__pycache__/_macos.cpython-311.pyc,,
 pip/_vendor/truststore/__pycache__/_openssl.cpython-311.pyc,,
 pip/_vendor/truststore/__pycache__/_ssl_constants.cpython-311.pyc,,
 pip/_vendor/truststore/__pycache__/_windows.cpython-311.pyc,,
-pip/_vendor/truststore/_api.py,sha256=B9JIHipzBIS8pMP_J50-o1DHVZsvKZQUXTB0HQQ_UPg,10461
-pip/_vendor/truststore/_macos.py,sha256=VJ24avz5aEGYAs_kWvnGjMJtuIP4xJcYa459UQOQC3M,17608
+pip/_vendor/truststore/_api.py,sha256=GeXRNTlxPZ3kif4kNoh6JY0oE4QRzTGcgXr6l_X_Gk0,10555
+pip/_vendor/truststore/_macos.py,sha256=nZlLkOmszUE0g6ryRwBVGY5COzPyudcsiJtDWarM5LQ,20503
 pip/_vendor/truststore/_openssl.py,sha256=LLUZ7ZGaio-i5dpKKjKCSeSufmn6T8pi9lDcFnvSyq0,2324
 pip/_vendor/truststore/_ssl_constants.py,sha256=NUD4fVKdSD02ri7-db0tnO0VqLP9aHuzmStcW7tAl08,1130
-pip/_vendor/truststore/_windows.py,sha256=eldNViHNHeY5r3fiBoz_JFGD37atXB9S5yaRoPKEGAA,17891
+pip/_vendor/truststore/_windows.py,sha256=rAHyKYD8M7t-bXfG8VgOVa3TpfhVhbt4rZQlO45YuP8,17993
 pip/_vendor/truststore/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
 pip/_vendor/typing_extensions.py,sha256=78hFl0HpDY-ylHUVCnWdU5nTHxUP2-S-3wEZk6CQmLk,134499
 pip/_vendor/urllib3/__init__.py,sha256=iXLcYiJySn0GNbWOOZDDApgBL1JgP44EZ8i1760S8Mc,3333
@@ -784,9 +784,9 @@ pip/_vendor/urllib3/__pycache__/poolmanager.cpython-311.pyc,,
 pip/_vendor/urllib3/__pycache__/request.cpython-311.pyc,,
 pip/_vendor/urllib3/__pycache__/response.cpython-311.pyc,,
 pip/_vendor/urllib3/_collections.py,sha256=pyASJJhW7wdOpqJj9QJA8FyGRfr8E8uUUhqUvhF0728,11372
-pip/_vendor/urllib3/_version.py,sha256=cuJvnSrWxXGYgQ3-ZRoPMw8-qaN5tpw71jnH1t16dLA,64
-pip/_vendor/urllib3/connection.py,sha256=92k9td_y4PEiTIjNufCUa1NzMB3J3w0LEdyokYgXnW8,20300
-pip/_vendor/urllib3/connectionpool.py,sha256=Be6q65SR9laoikg-h_jmc_p8OWtEmwgq_Om_Xtig-2M,40285
+pip/_vendor/urllib3/_version.py,sha256=t9wGB6ooOTXXgiY66K1m6BZS1CJyXHAU8EoWDTe6Shk,64
+pip/_vendor/urllib3/connection.py,sha256=ttIA909BrbTUzwkqEe_TzZVh4JOOj7g61Ysei2mrwGg,20314
+pip/_vendor/urllib3/connectionpool.py,sha256=e2eiAwNbFNCKxj4bwDKNK-w7HIdSz3OmMxU_TIt-evQ,40408
 pip/_vendor/urllib3/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
 pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-311.pyc,,
 pip/_vendor/urllib3/contrib/__pycache__/_appengine_environ.cpython-311.pyc,,
@@ -842,12 +842,12 @@ pip/_vendor/urllib3/util/proxy.py,sha256=zUvPPCJrp6dOF0N4GAVbOcl6o-4uXKSrGiTkkr5
 pip/_vendor/urllib3/util/queue.py,sha256=nRgX8_eX-_VkvxoX096QWoz8Ps0QHUAExILCY_7PncM,498
 pip/_vendor/urllib3/util/request.py,sha256=C0OUt2tcU6LRiQJ7YYNP9GvPrSvl7ziIBekQ-5nlBZk,3997
 pip/_vendor/urllib3/util/response.py,sha256=GJpg3Egi9qaJXRwBh5wv-MNuRWan5BIu40oReoxWP28,3510
-pip/_vendor/urllib3/util/retry.py,sha256=Z6WEf518eTOXP5jr5QSQ9gqJI0DVYt3Xs3EKnYaTmus,22013
-pip/_vendor/urllib3/util/ssl_.py,sha256=X4-AqW91aYPhPx6-xbf66yHFQKbqqfC_5Zt4WkLX1Hc,17177
+pip/_vendor/urllib3/util/retry.py,sha256=6ENvOZ8PBDzh8kgixpql9lIrb2dxH-k7ZmBanJF2Ng4,22050
+pip/_vendor/urllib3/util/ssl_.py,sha256=QDuuTxPSCj1rYtZ4xpD7Ux-r20TD50aHyqKyhQ7Bq4A,17460
 pip/_vendor/urllib3/util/ssl_match_hostname.py,sha256=Ir4cZVEjmAk8gUAIHWSi7wtOO83UCYABY2xFD1Ql_WA,5758
 pip/_vendor/urllib3/util/ssltransport.py,sha256=NA-u5rMTrDFDFC8QzRKUEKMG0561hOD4qBTr3Z4pv6E,6895
 pip/_vendor/urllib3/util/timeout.py,sha256=cwq4dMk87mJHSBktK1miYJ-85G-3T3RmT20v7SFCpno,10168
 pip/_vendor/urllib3/util/url.py,sha256=lCAE7M5myA8EDdW0sJuyyZhVB9K_j38ljWhHAnFaWoE,14296
 pip/_vendor/urllib3/util/wait.py,sha256=fOX0_faozG2P7iVojQoE1mbydweNyTcm-hXEfFrTtLI,5403
-pip/_vendor/vendor.txt,sha256=PxNaxxkkpBaw5zOTsDpHEY-zEaHjgkDgyrSxOuxg8nw,330
+pip/_vendor/vendor.txt,sha256=43152uDtpsunEE29vmLqqKZUosdrbvzIFkzscLB55Cg,332
 pip/py.typed,sha256=EBVvvPRTn_eIpz5e5QztSCdrMX7Qwd7VP93RSoIlZ2I,286
diff --git a/venv/Lib/site-packages/pip-24.3.1.dist-info/REQUESTED b/venv/Lib/site-packages/pip-24.3.1.dist-info/REQUESTED
new file mode 100644
index 0000000..e69de29
diff --git a/venv/Lib/site-packages/pip-24.2.dist-info/WHEEL b/venv/Lib/site-packages/pip-24.3.1.dist-info/WHEEL
similarity index 65%
rename from venv/Lib/site-packages/pip-24.2.dist-info/WHEEL
rename to venv/Lib/site-packages/pip-24.3.1.dist-info/WHEEL
index ecaf39f..da25d7b 100644
--- a/venv/Lib/site-packages/pip-24.2.dist-info/WHEEL
+++ b/venv/Lib/site-packages/pip-24.3.1.dist-info/WHEEL
@@ -1,5 +1,5 @@
 Wheel-Version: 1.0
-Generator: setuptools (71.1.0)
+Generator: setuptools (75.2.0)
 Root-Is-Purelib: true
 Tag: py3-none-any
 
diff --git a/venv/Lib/site-packages/pip-24.2.dist-info/entry_points.txt b/venv/Lib/site-packages/pip-24.3.1.dist-info/entry_points.txt
similarity index 100%
rename from venv/Lib/site-packages/pip-24.2.dist-info/entry_points.txt
rename to venv/Lib/site-packages/pip-24.3.1.dist-info/entry_points.txt
diff --git a/venv/Lib/site-packages/pip-24.3.1.dist-info/top_level.txt b/venv/Lib/site-packages/pip-24.3.1.dist-info/top_level.txt
new file mode 100644
index 0000000..a1b589e
--- /dev/null
+++ b/venv/Lib/site-packages/pip-24.3.1.dist-info/top_level.txt
@@ -0,0 +1 @@
+pip
diff --git a/venv/Lib/site-packages/pip/__init__.py b/venv/Lib/site-packages/pip/__init__.py
index 640e922..efefccf 100644
--- a/venv/Lib/site-packages/pip/__init__.py
+++ b/venv/Lib/site-packages/pip/__init__.py
@@ -1,6 +1,6 @@
 from typing import List, Optional
 
-__version__ = "24.2"
+__version__ = "24.3.1"
 
 
 def main(args: Optional[List[str]] = None) -> int:
diff --git a/venv/Lib/site-packages/pip/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/__pycache__/__init__.cpython-311.pyc
index 8b3d49a..e52ec65 100644
Binary files a/venv/Lib/site-packages/pip/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/__pycache__/__main__.cpython-311.pyc b/venv/Lib/site-packages/pip/__pycache__/__main__.cpython-311.pyc
index 081723e..5acbbea 100644
Binary files a/venv/Lib/site-packages/pip/__pycache__/__main__.cpython-311.pyc and b/venv/Lib/site-packages/pip/__pycache__/__main__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/__pycache__/__pip-runner__.cpython-311.pyc b/venv/Lib/site-packages/pip/__pycache__/__pip-runner__.cpython-311.pyc
index d3aaa60..e51a9b1 100644
Binary files a/venv/Lib/site-packages/pip/__pycache__/__pip-runner__.cpython-311.pyc and b/venv/Lib/site-packages/pip/__pycache__/__pip-runner__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/__pycache__/__init__.cpython-311.pyc
index f51ca28..54b2a16 100644
Binary files a/venv/Lib/site-packages/pip/_internal/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/__pycache__/build_env.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/__pycache__/build_env.cpython-311.pyc
index c00f4ef..5ba1087 100644
Binary files a/venv/Lib/site-packages/pip/_internal/__pycache__/build_env.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/__pycache__/build_env.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/__pycache__/cache.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/__pycache__/cache.cpython-311.pyc
index 9d5e6ef..1c637fa 100644
Binary files a/venv/Lib/site-packages/pip/_internal/__pycache__/cache.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/__pycache__/cache.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/__pycache__/configuration.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/__pycache__/configuration.cpython-311.pyc
index bc1cd47..2873755 100644
Binary files a/venv/Lib/site-packages/pip/_internal/__pycache__/configuration.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/__pycache__/configuration.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/__pycache__/exceptions.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/__pycache__/exceptions.cpython-311.pyc
index 9b217a8..9526602 100644
Binary files a/venv/Lib/site-packages/pip/_internal/__pycache__/exceptions.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/__pycache__/exceptions.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/__pycache__/main.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/__pycache__/main.cpython-311.pyc
index 6f5b805..da0685e 100644
Binary files a/venv/Lib/site-packages/pip/_internal/__pycache__/main.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/__pycache__/main.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/__pycache__/pyproject.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/__pycache__/pyproject.cpython-311.pyc
index ea0d4e1..ebcf014 100644
Binary files a/venv/Lib/site-packages/pip/_internal/__pycache__/pyproject.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/__pycache__/pyproject.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/__pycache__/self_outdated_check.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/__pycache__/self_outdated_check.cpython-311.pyc
index 9c6da83..8e69022 100644
Binary files a/venv/Lib/site-packages/pip/_internal/__pycache__/self_outdated_check.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/__pycache__/self_outdated_check.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/__pycache__/wheel_builder.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/__pycache__/wheel_builder.cpython-311.pyc
index a2d6cde..f95f85f 100644
Binary files a/venv/Lib/site-packages/pip/_internal/__pycache__/wheel_builder.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/__pycache__/wheel_builder.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/build_env.py b/venv/Lib/site-packages/pip/_internal/build_env.py
index be1e0ca..0f1e266 100644
--- a/venv/Lib/site-packages/pip/_internal/build_env.py
+++ b/venv/Lib/site-packages/pip/_internal/build_env.py
@@ -242,6 +242,10 @@ def _install_requirements(
             prefix.path,
             "--no-warn-script-location",
             "--disable-pip-version-check",
+            # The prefix specified two lines above, thus
+            # target from config file or env var should be ignored
+            "--target",
+            "",
         ]
         if logger.getEffectiveLevel() <= logging.DEBUG:
             args.append("-vv")
diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-311.pyc
index d2e8a9e..855868b 100644
Binary files a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/autocompletion.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/autocompletion.cpython-311.pyc
index a6dee60..f5c44f1 100644
Binary files a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/autocompletion.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/autocompletion.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/base_command.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/base_command.cpython-311.pyc
index 1964221..dc89c23 100644
Binary files a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/base_command.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/base_command.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/cmdoptions.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/cmdoptions.cpython-311.pyc
index 33de227..6cbf015 100644
Binary files a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/cmdoptions.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/cmdoptions.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/command_context.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/command_context.cpython-311.pyc
index 41e91a2..95c1c58 100644
Binary files a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/command_context.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/command_context.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/index_command.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/index_command.cpython-311.pyc
index e5fdaf0..22c90e6 100644
Binary files a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/index_command.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/index_command.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/main.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/main.cpython-311.pyc
index c198433..94a25f9 100644
Binary files a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/main.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/main.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/main_parser.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/main_parser.cpython-311.pyc
index 38e3a53..f6944ef 100644
Binary files a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/main_parser.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/main_parser.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/parser.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/parser.cpython-311.pyc
index 6a8097b..65d7499 100644
Binary files a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/parser.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/parser.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/progress_bars.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/progress_bars.cpython-311.pyc
index f2dc124..e1e70e9 100644
Binary files a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/progress_bars.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/progress_bars.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/req_command.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/req_command.cpython-311.pyc
index 5a8e65e..8c48d1c 100644
Binary files a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/req_command.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/req_command.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/spinners.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/spinners.cpython-311.pyc
index 0d35e0d..80340cc 100644
Binary files a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/spinners.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/spinners.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/status_codes.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/status_codes.cpython-311.pyc
index 113f661..546bcf7 100644
Binary files a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/status_codes.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/status_codes.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/cli/index_command.py b/venv/Lib/site-packages/pip/_internal/cli/index_command.py
index 226f8da..db105d0 100644
--- a/venv/Lib/site-packages/pip/_internal/cli/index_command.py
+++ b/venv/Lib/site-packages/pip/_internal/cli/index_command.py
@@ -54,7 +54,7 @@ class SessionCommandMixin(CommandContextMixIn):
 
     def __init__(self) -> None:
         super().__init__()
-        self._session: Optional["PipSession"] = None
+        self._session: Optional[PipSession] = None
 
     @classmethod
     def _get_index_urls(cls, options: Values) -> Optional[List[str]]:
diff --git a/venv/Lib/site-packages/pip/_internal/cli/parser.py b/venv/Lib/site-packages/pip/_internal/cli/parser.py
index b7d7c1f..bc4aca0 100644
--- a/venv/Lib/site-packages/pip/_internal/cli/parser.py
+++ b/venv/Lib/site-packages/pip/_internal/cli/parser.py
@@ -6,7 +6,7 @@
 import sys
 import textwrap
 from contextlib import suppress
-from typing import Any, Dict, Generator, List, Optional, Tuple
+from typing import Any, Dict, Generator, List, NoReturn, Optional, Tuple
 
 from pip._internal.cli.status_codes import UNKNOWN_ERROR
 from pip._internal.configuration import Configuration, ConfigurationError
@@ -289,6 +289,6 @@ def get_default_values(self) -> optparse.Values:
                 defaults[option.dest] = option.check_value(opt_str, default)
         return optparse.Values(defaults)
 
-    def error(self, msg: str) -> None:
+    def error(self, msg: str) -> NoReturn:
         self.print_usage(sys.stderr)
         self.exit(UNKNOWN_ERROR, f"{msg}\n")
diff --git a/venv/Lib/site-packages/pip/_internal/cli/progress_bars.py b/venv/Lib/site-packages/pip/_internal/cli/progress_bars.py
index 883359c..1236180 100644
--- a/venv/Lib/site-packages/pip/_internal/cli/progress_bars.py
+++ b/venv/Lib/site-packages/pip/_internal/cli/progress_bars.py
@@ -25,7 +25,7 @@ def _rich_progress_bar(
     iterable: Iterable[bytes],
     *,
     bar_type: str,
-    size: int,
+    size: Optional[int],
 ) -> Generator[bytes, None, None]:
     assert bar_type == "on", "This should only be used in the default mode."
 
diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-311.pyc
index 9bdd124..e75c5e2 100644
Binary files a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/cache.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/cache.cpython-311.pyc
index ca021dd..84eec37 100644
Binary files a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/cache.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/cache.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/check.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/check.cpython-311.pyc
index 1cffe9d..458d068 100644
Binary files a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/check.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/check.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/completion.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/completion.cpython-311.pyc
index 5f4b5b5..4356179 100644
Binary files a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/completion.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/completion.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-311.pyc
index f6ecff7..0fc3947 100644
Binary files a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/debug.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/debug.cpython-311.pyc
index 5ab5393..8954a16 100644
Binary files a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/debug.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/debug.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/download.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/download.cpython-311.pyc
index dfd3703..715a159 100644
Binary files a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/download.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/download.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-311.pyc
index f2f1b3c..ba16663 100644
Binary files a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/hash.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/hash.cpython-311.pyc
index e6c2c0b..5e81f48 100644
Binary files a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/hash.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/hash.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/help.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/help.cpython-311.pyc
index b91e4ab..ae3d1e9 100644
Binary files a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/help.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/help.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/index.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/index.cpython-311.pyc
index f4caeae..846c905 100644
Binary files a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/index.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/index.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/inspect.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/inspect.cpython-311.pyc
index 346a742..250d250 100644
Binary files a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/inspect.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/inspect.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/install.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/install.cpython-311.pyc
index 15ec359..31b5bcd 100644
Binary files a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/install.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/install.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/list.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/list.cpython-311.pyc
index 0ef7d2c..714ed6a 100644
Binary files a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/list.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/list.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/search.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/search.cpython-311.pyc
index 142980d..72e7f36 100644
Binary files a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/search.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/search.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/show.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/show.cpython-311.pyc
index 14c054a..d1a1595 100644
Binary files a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/show.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/show.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-311.pyc
index 27eefb3..e7c15cb 100644
Binary files a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-311.pyc
index 994d2eb..9846680 100644
Binary files a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/commands/list.py b/venv/Lib/site-packages/pip/_internal/commands/list.py
index 82fc46a..8494370 100644
--- a/venv/Lib/site-packages/pip/_internal/commands/list.py
+++ b/venv/Lib/site-packages/pip/_internal/commands/list.py
@@ -176,7 +176,7 @@ def run(self, options: Values, args: List[str]) -> int:
         if options.excludes:
             skip.update(canonicalize_name(n) for n in options.excludes)
 
-        packages: "_ProcessedDists" = [
+        packages: _ProcessedDists = [
             cast("_DistWithLatestInfo", d)
             for d in get_environment(options.path).iter_installed_distributions(
                 local_only=options.local,
diff --git a/venv/Lib/site-packages/pip/_internal/commands/search.py b/venv/Lib/site-packages/pip/_internal/commands/search.py
index e0d329d..74b8d65 100644
--- a/venv/Lib/site-packages/pip/_internal/commands/search.py
+++ b/venv/Lib/site-packages/pip/_internal/commands/search.py
@@ -89,7 +89,7 @@ def transform_hits(hits: List[Dict[str, str]]) -> List["TransformedHit"]:
     packages with the list of versions stored inline. This converts the
     list from pypi into one we can use.
     """
-    packages: Dict[str, "TransformedHit"] = OrderedDict()
+    packages: Dict[str, TransformedHit] = OrderedDict()
     for hit in hits:
         name = hit["name"]
         summary = hit["summary"]
diff --git a/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/__init__.cpython-311.pyc
index 2a6b51d..fccd553 100644
Binary files a/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/base.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/base.cpython-311.pyc
index 0a079d3..b61e8b2 100644
Binary files a/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/base.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/base.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/installed.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/installed.cpython-311.pyc
index edb4c87..90b6102 100644
Binary files a/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/installed.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/installed.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/sdist.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/sdist.cpython-311.pyc
index dfe4c2b..ab1cc28 100644
Binary files a/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/sdist.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/sdist.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/wheel.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/wheel.cpython-311.pyc
index b56d7ab..814ce66 100644
Binary files a/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/wheel.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/wheel.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/exceptions.py b/venv/Lib/site-packages/pip/_internal/exceptions.py
index 2587740..45a876a 100644
--- a/venv/Lib/site-packages/pip/_internal/exceptions.py
+++ b/venv/Lib/site-packages/pip/_internal/exceptions.py
@@ -15,6 +15,8 @@
 from itertools import chain, groupby, repeat
 from typing import TYPE_CHECKING, Dict, Iterator, List, Literal, Optional, Union
 
+from pip._vendor.packaging.requirements import InvalidRequirement
+from pip._vendor.packaging.version import InvalidVersion
 from pip._vendor.rich.console import Console, ConsoleOptions, RenderResult
 from pip._vendor.rich.markup import escape
 from pip._vendor.rich.text import Text
@@ -429,7 +431,7 @@ class HashErrors(InstallationError):
     """Multiple HashError instances rolled into one for reporting"""
 
     def __init__(self) -> None:
-        self.errors: List["HashError"] = []
+        self.errors: List[HashError] = []
 
     def append(self, error: "HashError") -> None:
         self.errors.append(error)
@@ -775,3 +777,33 @@ def __init__(self, *, distribution: "BaseDistribution") -> None:
             ),
             hint_stmt=None,
         )
+
+
+class InvalidInstalledPackage(DiagnosticPipError):
+    reference = "invalid-installed-package"
+
+    def __init__(
+        self,
+        *,
+        dist: "BaseDistribution",
+        invalid_exc: Union[InvalidRequirement, InvalidVersion],
+    ) -> None:
+        installed_location = dist.installed_location
+
+        if isinstance(invalid_exc, InvalidRequirement):
+            invalid_type = "requirement"
+        else:
+            invalid_type = "version"
+
+        super().__init__(
+            message=Text(
+                f"Cannot process installed package {dist} "
+                + (f"in {installed_location!r} " if installed_location else "")
+                + f"because it has an invalid {invalid_type}:\n{invalid_exc.args[0]}"
+            ),
+            context=(
+                "Starting with pip 24.1, packages with invalid "
+                f"{invalid_type}s can not be processed."
+            ),
+            hint_stmt="To proceed this package must be uninstalled.",
+        )
diff --git a/venv/Lib/site-packages/pip/_internal/index/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/index/__pycache__/__init__.cpython-311.pyc
index 8d07816..4623f11 100644
Binary files a/venv/Lib/site-packages/pip/_internal/index/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/index/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/index/__pycache__/collector.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/index/__pycache__/collector.cpython-311.pyc
index 009023c..7db9ccb 100644
Binary files a/venv/Lib/site-packages/pip/_internal/index/__pycache__/collector.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/index/__pycache__/collector.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/index/__pycache__/package_finder.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/index/__pycache__/package_finder.cpython-311.pyc
index 438bc3f..ce1fbc4 100644
Binary files a/venv/Lib/site-packages/pip/_internal/index/__pycache__/package_finder.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/index/__pycache__/package_finder.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/index/__pycache__/sources.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/index/__pycache__/sources.cpython-311.pyc
index 6e255c6..e0ee34d 100644
Binary files a/venv/Lib/site-packages/pip/_internal/index/__pycache__/sources.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/index/__pycache__/sources.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/index/sources.py b/venv/Lib/site-packages/pip/_internal/index/sources.py
index f4626d7..3dafb30 100644
--- a/venv/Lib/site-packages/pip/_internal/index/sources.py
+++ b/venv/Lib/site-packages/pip/_internal/index/sources.py
@@ -6,7 +6,6 @@
 
 from pip._vendor.packaging.utils import (
     InvalidSdistFilename,
-    InvalidVersion,
     InvalidWheelFilename,
     canonicalize_name,
     parse_sdist_filename,
@@ -68,10 +67,10 @@ def _scan_directory(self) -> None:
             # otherwise not worth considering as a package
             try:
                 project_filename = parse_wheel_filename(entry.name)[0]
-            except (InvalidWheelFilename, InvalidVersion):
+            except InvalidWheelFilename:
                 try:
                     project_filename = parse_sdist_filename(entry.name)[0]
-                except (InvalidSdistFilename, InvalidVersion):
+                except InvalidSdistFilename:
                     continue
 
             self._project_name_to_urls[project_filename].append(url)
diff --git a/venv/Lib/site-packages/pip/_internal/locations/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/locations/__pycache__/__init__.cpython-311.pyc
index 5f2f4e5..d41ec53 100644
Binary files a/venv/Lib/site-packages/pip/_internal/locations/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/locations/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/locations/__pycache__/_distutils.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/locations/__pycache__/_distutils.cpython-311.pyc
index bb76887..e82beca 100644
Binary files a/venv/Lib/site-packages/pip/_internal/locations/__pycache__/_distutils.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/locations/__pycache__/_distutils.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/locations/__pycache__/_sysconfig.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/locations/__pycache__/_sysconfig.cpython-311.pyc
index 9c092e6..9d6a788 100644
Binary files a/venv/Lib/site-packages/pip/_internal/locations/__pycache__/_sysconfig.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/locations/__pycache__/_sysconfig.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/locations/__pycache__/base.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/locations/__pycache__/base.cpython-311.pyc
index 3287d35..2e24493 100644
Binary files a/venv/Lib/site-packages/pip/_internal/locations/__pycache__/base.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/locations/__pycache__/base.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/locations/_distutils.py b/venv/Lib/site-packages/pip/_internal/locations/_distutils.py
index 0e18c6e..3d85625 100644
--- a/venv/Lib/site-packages/pip/_internal/locations/_distutils.py
+++ b/venv/Lib/site-packages/pip/_internal/locations/_distutils.py
@@ -21,7 +21,7 @@
 from distutils.command.install import SCHEME_KEYS
 from distutils.command.install import install as distutils_install_command
 from distutils.sysconfig import get_python_lib
-from typing import Dict, List, Optional, Union, cast
+from typing import Dict, List, Optional, Union
 
 from pip._internal.models.scheme import Scheme
 from pip._internal.utils.compat import WINDOWS
@@ -64,7 +64,7 @@ def distutils_scheme(
     obj: Optional[DistutilsCommand] = None
     obj = d.get_command_obj("install", create=True)
     assert obj is not None
-    i = cast(distutils_install_command, obj)
+    i: distutils_install_command = obj
     # NOTE: setting user or home has the side-effect of creating the home dir
     # or user base for installations during finalize_options()
     # ideally, we'd prefer a scheme class that has no side-effects.
@@ -78,7 +78,7 @@ def distutils_scheme(
     i.root = root or i.root
     i.finalize_options()
 
-    scheme = {}
+    scheme: Dict[str, str] = {}
     for key in SCHEME_KEYS:
         scheme[key] = getattr(i, "install_" + key)
 
diff --git a/venv/Lib/site-packages/pip/_internal/metadata/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/metadata/__pycache__/__init__.cpython-311.pyc
index 442994f..3b38480 100644
Binary files a/venv/Lib/site-packages/pip/_internal/metadata/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/metadata/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/metadata/__pycache__/_json.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/metadata/__pycache__/_json.cpython-311.pyc
index 838a9b4..d4e9e1d 100644
Binary files a/venv/Lib/site-packages/pip/_internal/metadata/__pycache__/_json.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/metadata/__pycache__/_json.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/metadata/__pycache__/base.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/metadata/__pycache__/base.cpython-311.pyc
index 7f57092..ef32fd1 100644
Binary files a/venv/Lib/site-packages/pip/_internal/metadata/__pycache__/base.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/metadata/__pycache__/base.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/metadata/__pycache__/pkg_resources.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/metadata/__pycache__/pkg_resources.cpython-311.pyc
index 65c9503..4cd6f85 100644
Binary files a/venv/Lib/site-packages/pip/_internal/metadata/__pycache__/pkg_resources.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/metadata/__pycache__/pkg_resources.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/__init__.cpython-311.pyc
index b02354f..83c7035 100644
Binary files a/venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/_compat.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/_compat.cpython-311.pyc
index 427164c..0afd13e 100644
Binary files a/venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/_compat.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/_compat.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/_dists.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/_dists.cpython-311.pyc
index 4110eda..90a6196 100644
Binary files a/venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/_dists.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/_dists.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/_envs.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/_envs.cpython-311.pyc
index ebd9a15..70bd075 100644
Binary files a/venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/_envs.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/_envs.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/metadata/importlib/_envs.py b/venv/Lib/site-packages/pip/_internal/metadata/importlib/_envs.py
index 70cb7a6..4d906fd 100644
--- a/venv/Lib/site-packages/pip/_internal/metadata/importlib/_envs.py
+++ b/venv/Lib/site-packages/pip/_internal/metadata/importlib/_envs.py
@@ -150,7 +150,7 @@ def _emit_egg_deprecation(location: Optional[str]) -> None:
     deprecated(
         reason=f"Loading egg at {location} is deprecated.",
         replacement="to use pip for package installation",
-        gone_in="24.3",
+        gone_in="25.1",
         issue=12330,
     )
 
diff --git a/venv/Lib/site-packages/pip/_internal/models/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/models/__pycache__/__init__.cpython-311.pyc
index 98158e9..f890a19 100644
Binary files a/venv/Lib/site-packages/pip/_internal/models/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/models/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/models/__pycache__/candidate.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/models/__pycache__/candidate.cpython-311.pyc
index 26a0c58..d872e32 100644
Binary files a/venv/Lib/site-packages/pip/_internal/models/__pycache__/candidate.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/models/__pycache__/candidate.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/models/__pycache__/direct_url.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/models/__pycache__/direct_url.cpython-311.pyc
index 8c5f826..9faa0e1 100644
Binary files a/venv/Lib/site-packages/pip/_internal/models/__pycache__/direct_url.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/models/__pycache__/direct_url.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/models/__pycache__/format_control.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/models/__pycache__/format_control.cpython-311.pyc
index e3d90de..8b4e50a 100644
Binary files a/venv/Lib/site-packages/pip/_internal/models/__pycache__/format_control.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/models/__pycache__/format_control.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/models/__pycache__/index.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/models/__pycache__/index.cpython-311.pyc
index 67ba715..d0769b9 100644
Binary files a/venv/Lib/site-packages/pip/_internal/models/__pycache__/index.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/models/__pycache__/index.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/models/__pycache__/installation_report.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/models/__pycache__/installation_report.cpython-311.pyc
index 6eadae3..0bbb4d5 100644
Binary files a/venv/Lib/site-packages/pip/_internal/models/__pycache__/installation_report.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/models/__pycache__/installation_report.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/models/__pycache__/link.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/models/__pycache__/link.cpython-311.pyc
index 851f30c..8d02d87 100644
Binary files a/venv/Lib/site-packages/pip/_internal/models/__pycache__/link.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/models/__pycache__/link.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/models/__pycache__/scheme.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/models/__pycache__/scheme.cpython-311.pyc
index 4a1bc59..395c650 100644
Binary files a/venv/Lib/site-packages/pip/_internal/models/__pycache__/scheme.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/models/__pycache__/scheme.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/models/__pycache__/search_scope.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/models/__pycache__/search_scope.cpython-311.pyc
index 8181c08..79b1693 100644
Binary files a/venv/Lib/site-packages/pip/_internal/models/__pycache__/search_scope.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/models/__pycache__/search_scope.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/models/__pycache__/selection_prefs.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/models/__pycache__/selection_prefs.cpython-311.pyc
index efcfc50..e915c46 100644
Binary files a/venv/Lib/site-packages/pip/_internal/models/__pycache__/selection_prefs.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/models/__pycache__/selection_prefs.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/models/__pycache__/target_python.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/models/__pycache__/target_python.cpython-311.pyc
index 247af66..964094c 100644
Binary files a/venv/Lib/site-packages/pip/_internal/models/__pycache__/target_python.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/models/__pycache__/target_python.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/models/__pycache__/wheel.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/models/__pycache__/wheel.cpython-311.pyc
index 2faa62e..983f8c3 100644
Binary files a/venv/Lib/site-packages/pip/_internal/models/__pycache__/wheel.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/models/__pycache__/wheel.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/models/wheel.py b/venv/Lib/site-packages/pip/_internal/models/wheel.py
index 36d4d2e..ea85600 100644
--- a/venv/Lib/site-packages/pip/_internal/models/wheel.py
+++ b/venv/Lib/site-packages/pip/_internal/models/wheel.py
@@ -6,8 +6,13 @@
 from typing import Dict, Iterable, List
 
 from pip._vendor.packaging.tags import Tag
+from pip._vendor.packaging.utils import (
+    InvalidWheelFilename as PackagingInvalidWheelName,
+)
+from pip._vendor.packaging.utils import parse_wheel_filename
 
 from pip._internal.exceptions import InvalidWheelFilename
+from pip._internal.utils.deprecation import deprecated
 
 
 class Wheel:
@@ -29,9 +34,29 @@ def __init__(self, filename: str) -> None:
             raise InvalidWheelFilename(f"{filename} is not a valid wheel filename.")
         self.filename = filename
         self.name = wheel_info.group("name").replace("_", "-")
-        # we'll assume "_" means "-" due to wheel naming scheme
-        # (https://github.com/pypa/pip/issues/1150)
-        self.version = wheel_info.group("ver").replace("_", "-")
+        _version = wheel_info.group("ver")
+        if "_" in _version:
+            try:
+                parse_wheel_filename(filename)
+            except PackagingInvalidWheelName as e:
+                deprecated(
+                    reason=(
+                        f"Wheel filename {filename!r} is not correctly normalised. "
+                        "Future versions of pip will raise the following error:\n"
+                        f"{e.args[0]}\n\n"
+                    ),
+                    replacement=(
+                        "to rename the wheel to use a correctly normalised "
+                        "name (this may require updating the version in "
+                        "the project metadata)"
+                    ),
+                    gone_in="25.1",
+                    issue=12938,
+                )
+
+            _version = _version.replace("_", "-")
+
+        self.version = _version
         self.build_tag = wheel_info.group("build")
         self.pyversions = wheel_info.group("pyver").split(".")
         self.abis = wheel_info.group("abi").split(".")
diff --git a/venv/Lib/site-packages/pip/_internal/network/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/network/__pycache__/__init__.cpython-311.pyc
index 7b8805b..143364b 100644
Binary files a/venv/Lib/site-packages/pip/_internal/network/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/network/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/network/__pycache__/auth.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/network/__pycache__/auth.cpython-311.pyc
index 5bcbc33..8baec14 100644
Binary files a/venv/Lib/site-packages/pip/_internal/network/__pycache__/auth.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/network/__pycache__/auth.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/network/__pycache__/cache.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/network/__pycache__/cache.cpython-311.pyc
index 22dc161..7bf7511 100644
Binary files a/venv/Lib/site-packages/pip/_internal/network/__pycache__/cache.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/network/__pycache__/cache.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/network/__pycache__/download.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/network/__pycache__/download.cpython-311.pyc
index ed4bbf3..72c455f 100644
Binary files a/venv/Lib/site-packages/pip/_internal/network/__pycache__/download.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/network/__pycache__/download.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/network/__pycache__/lazy_wheel.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/network/__pycache__/lazy_wheel.cpython-311.pyc
index 730e5eb..8404dcc 100644
Binary files a/venv/Lib/site-packages/pip/_internal/network/__pycache__/lazy_wheel.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/network/__pycache__/lazy_wheel.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/network/__pycache__/session.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/network/__pycache__/session.cpython-311.pyc
index c7a3555..7ca3210 100644
Binary files a/venv/Lib/site-packages/pip/_internal/network/__pycache__/session.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/network/__pycache__/session.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/network/__pycache__/utils.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/network/__pycache__/utils.cpython-311.pyc
index 6ccbfc0..686a8fc 100644
Binary files a/venv/Lib/site-packages/pip/_internal/network/__pycache__/utils.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/network/__pycache__/utils.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/network/__pycache__/xmlrpc.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/network/__pycache__/xmlrpc.cpython-311.pyc
index 070078d..d17c673 100644
Binary files a/venv/Lib/site-packages/pip/_internal/network/__pycache__/xmlrpc.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/network/__pycache__/xmlrpc.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/network/lazy_wheel.py b/venv/Lib/site-packages/pip/_internal/network/lazy_wheel.py
index 82ec50d..03f883c 100644
--- a/venv/Lib/site-packages/pip/_internal/network/lazy_wheel.py
+++ b/venv/Lib/site-packages/pip/_internal/network/lazy_wheel.py
@@ -159,7 +159,7 @@ def _check_zip(self) -> None:
                 try:
                     # For read-only ZIP files, ZipFile only needs
                     # methods read, seek, seekable and tell.
-                    ZipFile(self)  # type: ignore
+                    ZipFile(self)
                 except BadZipFile:
                     pass
                 else:
diff --git a/venv/Lib/site-packages/pip/_internal/operations/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/operations/__pycache__/__init__.cpython-311.pyc
index 3b03bb3..37224eb 100644
Binary files a/venv/Lib/site-packages/pip/_internal/operations/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/operations/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/operations/__pycache__/check.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/operations/__pycache__/check.cpython-311.pyc
index 0c76007..99a6b90 100644
Binary files a/venv/Lib/site-packages/pip/_internal/operations/__pycache__/check.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/operations/__pycache__/check.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/operations/__pycache__/freeze.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/operations/__pycache__/freeze.cpython-311.pyc
index bed6096..1cf85c6 100644
Binary files a/venv/Lib/site-packages/pip/_internal/operations/__pycache__/freeze.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/operations/__pycache__/freeze.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/operations/__pycache__/prepare.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/operations/__pycache__/prepare.cpython-311.pyc
index fba83f1..74525ec 100644
Binary files a/venv/Lib/site-packages/pip/_internal/operations/__pycache__/prepare.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/operations/__pycache__/prepare.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/__init__.cpython-311.pyc
index fcb117e..243eb5e 100644
Binary files a/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/build_tracker.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/build_tracker.cpython-311.pyc
index f1c5fd5..2088c86 100644
Binary files a/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/build_tracker.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/build_tracker.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata.cpython-311.pyc
index e4393b3..3d0aa3b 100644
Binary files a/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_editable.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_editable.cpython-311.pyc
index d4eeb5b..bd77cfa 100644
Binary files a/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_editable.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_editable.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-311.pyc
index 7024eba..85aa281 100644
Binary files a/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel.cpython-311.pyc
index 4da9deb..150f3d1 100644
Binary files a/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel_editable.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel_editable.cpython-311.pyc
index 1694e9c..ba47135 100644
Binary files a/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel_editable.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel_editable.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel_legacy.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel_legacy.cpython-311.pyc
index 7912cb9..77acc49 100644
Binary files a/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel_legacy.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel_legacy.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/__init__.cpython-311.pyc
index 1020bcd..802a4de 100644
Binary files a/venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/editable_legacy.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/editable_legacy.cpython-311.pyc
index 015e20d..9f36c47 100644
Binary files a/venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/editable_legacy.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/editable_legacy.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/wheel.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/wheel.cpython-311.pyc
index 99eb268..c175da5 100644
Binary files a/venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/wheel.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/wheel.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/req/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/req/__pycache__/__init__.cpython-311.pyc
index 1894e43..c063159 100644
Binary files a/venv/Lib/site-packages/pip/_internal/req/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/req/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/req/__pycache__/constructors.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/req/__pycache__/constructors.cpython-311.pyc
index b88d465..e37541e 100644
Binary files a/venv/Lib/site-packages/pip/_internal/req/__pycache__/constructors.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/req/__pycache__/constructors.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/req/__pycache__/req_file.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/req/__pycache__/req_file.cpython-311.pyc
index 9156500..e228481 100644
Binary files a/venv/Lib/site-packages/pip/_internal/req/__pycache__/req_file.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/req/__pycache__/req_file.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/req/__pycache__/req_install.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/req/__pycache__/req_install.cpython-311.pyc
index 41e800e..e1ec3d6 100644
Binary files a/venv/Lib/site-packages/pip/_internal/req/__pycache__/req_install.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/req/__pycache__/req_install.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/req/__pycache__/req_set.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/req/__pycache__/req_set.cpython-311.pyc
index e496840..5a93285 100644
Binary files a/venv/Lib/site-packages/pip/_internal/req/__pycache__/req_set.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/req/__pycache__/req_set.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/req/__pycache__/req_uninstall.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/req/__pycache__/req_uninstall.cpython-311.pyc
index 375263b..7525794 100644
Binary files a/venv/Lib/site-packages/pip/_internal/req/__pycache__/req_uninstall.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/req/__pycache__/req_uninstall.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/req/constructors.py b/venv/Lib/site-packages/pip/_internal/req/constructors.py
index d73236e..56a964f 100644
--- a/venv/Lib/site-packages/pip/_internal/req/constructors.py
+++ b/venv/Lib/site-packages/pip/_internal/req/constructors.py
@@ -80,7 +80,7 @@ def _set_requirement_extras(req: Requirement, new_extras: Set[str]) -> Requireme
     assert (
         pre is not None and post is not None
     ), f"regex group selection for requirement {req} failed, this should never happen"
-    extras: str = "[%s]" % ",".join(sorted(new_extras)) if new_extras else ""
+    extras: str = "[{}]".format(",".join(sorted(new_extras)) if new_extras else "")
     return get_requirement(f"{pre}{extras}{post}")
 
 
diff --git a/venv/Lib/site-packages/pip/_internal/req/req_file.py b/venv/Lib/site-packages/pip/_internal/req/req_file.py
index 53ad867..eb2a1f6 100644
--- a/venv/Lib/site-packages/pip/_internal/req/req_file.py
+++ b/venv/Lib/site-packages/pip/_internal/req/req_file.py
@@ -329,10 +329,15 @@ def parse(
         self, filename: str, constraint: bool
     ) -> Generator[ParsedLine, None, None]:
         """Parse a given file, yielding parsed lines."""
-        yield from self._parse_and_recurse(filename, constraint)
+        yield from self._parse_and_recurse(
+            filename, constraint, [{os.path.abspath(filename): None}]
+        )
 
     def _parse_and_recurse(
-        self, filename: str, constraint: bool
+        self,
+        filename: str,
+        constraint: bool,
+        parsed_files_stack: List[Dict[str, Optional[str]]],
     ) -> Generator[ParsedLine, None, None]:
         for line in self._parse_file(filename, constraint):
             if not line.is_requirement and (
@@ -353,12 +358,30 @@ def _parse_and_recurse(
                 # original file and nested file are paths
                 elif not SCHEME_RE.search(req_path):
                     # do a join so relative paths work
-                    req_path = os.path.join(
-                        os.path.dirname(filename),
-                        req_path,
+                    # and then abspath so that we can identify recursive references
+                    req_path = os.path.abspath(
+                        os.path.join(
+                            os.path.dirname(filename),
+                            req_path,
+                        )
                     )
-
-                yield from self._parse_and_recurse(req_path, nested_constraint)
+                parsed_files = parsed_files_stack[0]
+                if req_path in parsed_files:
+                    initial_file = parsed_files[req_path]
+                    tail = (
+                        f" and again in {initial_file}"
+                        if initial_file is not None
+                        else ""
+                    )
+                    raise RequirementsFileParseError(
+                        f"{req_path} recursively references itself in {filename}{tail}"
+                    )
+                # Keeping a track where was each file first included in
+                new_parsed_files = parsed_files.copy()
+                new_parsed_files[req_path] = filename
+                yield from self._parse_and_recurse(
+                    req_path, nested_constraint, [new_parsed_files, *parsed_files_stack]
+                )
             else:
                 yield line
 
diff --git a/venv/Lib/site-packages/pip/_internal/resolution/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/resolution/__pycache__/__init__.cpython-311.pyc
index 6c7e3ae..b9cd0ea 100644
Binary files a/venv/Lib/site-packages/pip/_internal/resolution/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/resolution/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/resolution/__pycache__/base.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/resolution/__pycache__/base.cpython-311.pyc
index e3ac238..e1e09cb 100644
Binary files a/venv/Lib/site-packages/pip/_internal/resolution/__pycache__/base.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/resolution/__pycache__/base.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/__init__.cpython-311.pyc
index 4cf5655..3eeaa84 100644
Binary files a/venv/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/resolver.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/resolver.cpython-311.pyc
index 61bcdce..e40f66b 100644
Binary files a/venv/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/resolver.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/resolver.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-311.pyc
index 26ba876..29bb9fe 100644
Binary files a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/base.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/base.cpython-311.pyc
index 5a49916..da7a9a3 100644
Binary files a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/base.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/base.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-311.pyc
index e3cbcc7..0549080 100644
Binary files a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-311.pyc
index 0b09cf7..914f996 100644
Binary files a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-311.pyc
index 4712a4f..3fcc025 100644
Binary files a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-311.pyc
index 17811d5..d5d7681 100644
Binary files a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-311.pyc
index 19d5546..a27e9b0 100644
Binary files a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-311.pyc
index 2de7c6f..969654f 100644
Binary files a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-311.pyc
index c2daf27..2c3394c 100644
Binary files a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py
index d30d477..6617644 100644
--- a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py
+++ b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py
@@ -9,6 +9,7 @@
 from pip._internal.exceptions import (
     HashError,
     InstallationSubprocessError,
+    InvalidInstalledPackage,
     MetadataInconsistent,
     MetadataInvalid,
 )
@@ -398,8 +399,12 @@ def format_for_error(self) -> str:
     def iter_dependencies(self, with_requires: bool) -> Iterable[Optional[Requirement]]:
         if not with_requires:
             return
-        for r in self.dist.iter_dependencies():
-            yield from self._factory.make_requirements_from_spec(str(r), self._ireq)
+
+        try:
+            for r in self.dist.iter_dependencies():
+                yield from self._factory.make_requirements_from_spec(str(r), self._ireq)
+        except InvalidRequirement as exc:
+            raise InvalidInstalledPackage(dist=self.dist, invalid_exc=exc) from None
 
     def get_install_requirement(self) -> Optional[InstallRequirement]:
         return None
diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py
index 145bdbf..dc6e2e1 100644
--- a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py
+++ b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py
@@ -23,13 +23,14 @@
 from pip._vendor.packaging.requirements import InvalidRequirement
 from pip._vendor.packaging.specifiers import SpecifierSet
 from pip._vendor.packaging.utils import NormalizedName, canonicalize_name
-from pip._vendor.packaging.version import Version
+from pip._vendor.packaging.version import InvalidVersion, Version
 from pip._vendor.resolvelib import ResolutionImpossible
 
 from pip._internal.cache import CacheEntry, WheelCache
 from pip._internal.exceptions import (
     DistributionNotFound,
     InstallationError,
+    InvalidInstalledPackage,
     MetadataInconsistent,
     MetadataInvalid,
     UnsupportedPythonVersion,
@@ -283,10 +284,15 @@ def _get_installed_candidate() -> Optional[Candidate]:
                 installed_dist = self._installed_dists[name]
             except KeyError:
                 return None
-            # Don't use the installed distribution if its version does not fit
-            # the current dependency graph.
-            if not specifier.contains(installed_dist.version, prereleases=True):
-                return None
+
+            try:
+                # Don't use the installed distribution if its version
+                # does not fit the current dependency graph.
+                if not specifier.contains(installed_dist.version, prereleases=True):
+                    return None
+            except InvalidVersion as e:
+                raise InvalidInstalledPackage(dist=installed_dist, invalid_exc=e)
+
             candidate = self._make_candidate_from_dist(
                 dist=installed_dist,
                 extras=extras,
diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/__init__.cpython-311.pyc
index 8f919f7..d7becac 100644
Binary files a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/_jaraco_text.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/_jaraco_text.cpython-311.pyc
index 4432f85..04eecc9 100644
Binary files a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/_jaraco_text.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/_jaraco_text.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/_log.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/_log.cpython-311.pyc
index fc84bbf..1a28c64 100644
Binary files a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/_log.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/_log.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/appdirs.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/appdirs.cpython-311.pyc
index 890a6d1..c4fae86 100644
Binary files a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/appdirs.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/appdirs.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/compat.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/compat.cpython-311.pyc
index 34d6236..2795e80 100644
Binary files a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/compat.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/compat.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/compatibility_tags.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/compatibility_tags.cpython-311.pyc
index b508e8b..4259570 100644
Binary files a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/compatibility_tags.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/compatibility_tags.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/datetime.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/datetime.cpython-311.pyc
index 9177681..4e0d25c 100644
Binary files a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/datetime.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/datetime.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/deprecation.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/deprecation.cpython-311.pyc
index 4a2ed18..0375e9a 100644
Binary files a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/deprecation.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/deprecation.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/direct_url_helpers.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/direct_url_helpers.cpython-311.pyc
index 42c9cf9..4542d43 100644
Binary files a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/direct_url_helpers.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/direct_url_helpers.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/egg_link.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/egg_link.cpython-311.pyc
index 70aad52..d3c5941 100644
Binary files a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/egg_link.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/egg_link.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/encoding.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/encoding.cpython-311.pyc
index 59acd4e..0c955f5 100644
Binary files a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/encoding.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/encoding.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/entrypoints.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/entrypoints.cpython-311.pyc
index 428bbf6..eb7fa1d 100644
Binary files a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/entrypoints.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/entrypoints.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-311.pyc
index 16d81d9..207920e 100644
Binary files a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/filetypes.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/filetypes.cpython-311.pyc
index 05e6736..e807ebd 100644
Binary files a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/filetypes.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/filetypes.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/glibc.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/glibc.cpython-311.pyc
index defeb78..081326f 100644
Binary files a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/glibc.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/glibc.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/hashes.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/hashes.cpython-311.pyc
index 3a78b57..5dfd2c9 100644
Binary files a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/hashes.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/hashes.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/logging.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/logging.cpython-311.pyc
index 58326ff..fc0a59d 100644
Binary files a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/logging.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/logging.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/misc.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/misc.cpython-311.pyc
index 51f17aa..875e1e9 100644
Binary files a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/misc.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/misc.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/packaging.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/packaging.cpython-311.pyc
index ed10167..6ff86fb 100644
Binary files a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/packaging.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/packaging.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/retry.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/retry.cpython-311.pyc
index c66a247..7b957bd 100644
Binary files a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/retry.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/retry.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/setuptools_build.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/setuptools_build.cpython-311.pyc
index ddcd0a0..3bf4f55 100644
Binary files a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/setuptools_build.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/setuptools_build.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/subprocess.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/subprocess.cpython-311.pyc
index c2b7969..3bae7b1 100644
Binary files a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/subprocess.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/subprocess.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/temp_dir.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/temp_dir.cpython-311.pyc
index 09739f4..c24f2ba 100644
Binary files a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/temp_dir.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/temp_dir.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/unpacking.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/unpacking.cpython-311.pyc
index dded8a4..9db6c94 100644
Binary files a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/unpacking.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/unpacking.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/urls.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/urls.cpython-311.pyc
index c415758..2d9c017 100644
Binary files a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/urls.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/urls.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/virtualenv.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/virtualenv.cpython-311.pyc
index 66181be..2a01c4e 100644
Binary files a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/virtualenv.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/virtualenv.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/wheel.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/wheel.cpython-311.pyc
index 5bfaa28..a357678 100644
Binary files a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/wheel.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/wheel.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/utils/compatibility_tags.py b/venv/Lib/site-packages/pip/_internal/utils/compatibility_tags.py
index b6ed9a7..2e7b745 100644
--- a/venv/Lib/site-packages/pip/_internal/utils/compatibility_tags.py
+++ b/venv/Lib/site-packages/pip/_internal/utils/compatibility_tags.py
@@ -12,10 +12,11 @@
     generic_tags,
     interpreter_name,
     interpreter_version,
+    ios_platforms,
     mac_platforms,
 )
 
-_osx_arch_pat = re.compile(r"(.+)_(\d+)_(\d+)_(.+)")
+_apple_arch_pat = re.compile(r"(.+)_(\d+)_(\d+)_(.+)")
 
 
 def version_info_to_nodot(version_info: Tuple[int, ...]) -> str:
@@ -24,7 +25,7 @@ def version_info_to_nodot(version_info: Tuple[int, ...]) -> str:
 
 
 def _mac_platforms(arch: str) -> List[str]:
-    match = _osx_arch_pat.match(arch)
+    match = _apple_arch_pat.match(arch)
     if match:
         name, major, minor, actual_arch = match.groups()
         mac_version = (int(major), int(minor))
@@ -43,6 +44,26 @@ def _mac_platforms(arch: str) -> List[str]:
     return arches
 
 
+def _ios_platforms(arch: str) -> List[str]:
+    match = _apple_arch_pat.match(arch)
+    if match:
+        name, major, minor, actual_multiarch = match.groups()
+        ios_version = (int(major), int(minor))
+        arches = [
+            # Since we have always only checked that the platform starts
+            # with "ios", for backwards-compatibility we extract the
+            # actual prefix provided by the user in case they provided
+            # something like "ioscustom_". It may be good to remove
+            # this as undocumented or deprecate it in the future.
+            "{}_{}".format(name, arch[len("ios_") :])
+            for arch in ios_platforms(ios_version, actual_multiarch)
+        ]
+    else:
+        # arch pattern didn't match (?!)
+        arches = [arch]
+    return arches
+
+
 def _custom_manylinux_platforms(arch: str) -> List[str]:
     arches = [arch]
     arch_prefix, arch_sep, arch_suffix = arch.partition("_")
@@ -68,6 +89,8 @@ def _get_custom_platforms(arch: str) -> List[str]:
     arch_prefix, arch_sep, arch_suffix = arch.partition("_")
     if arch.startswith("macosx"):
         arches = _mac_platforms(arch)
+    elif arch.startswith("ios"):
+        arches = _ios_platforms(arch)
     elif arch_prefix in ["manylinux2014", "manylinux2010"]:
         arches = _custom_manylinux_platforms(arch)
     else:
diff --git a/venv/Lib/site-packages/pip/_internal/utils/misc.py b/venv/Lib/site-packages/pip/_internal/utils/misc.py
index 3707e87..c0a3e4d 100644
--- a/venv/Lib/site-packages/pip/_internal/utils/misc.py
+++ b/venv/Lib/site-packages/pip/_internal/utils/misc.py
@@ -129,12 +129,7 @@ def rmtree(
         onexc = _onerror_ignore
     if onexc is None:
         onexc = _onerror_reraise
-    handler: OnErr = partial(
-        # `[func, path, Union[ExcInfo, BaseException]] -> Any` is equivalent to
-        # `Union[([func, path, ExcInfo] -> Any), ([func, path, BaseException] -> Any)]`.
-        cast(Union[OnExc, OnErr], rmtree_errorhandler),
-        onexc=onexc,
-    )
+    handler: OnErr = partial(rmtree_errorhandler, onexc=onexc)
     if sys.version_info >= (3, 12):
         # See https://docs.python.org/3.12/whatsnew/3.12.html#shutil.
         shutil.rmtree(dir, onexc=handler)  # type: ignore
@@ -555,7 +550,7 @@ def __str__(self) -> str:
 
     # This is useful for testing.
     def __eq__(self, other: Any) -> bool:
-        if type(self) != type(other):
+        if type(self) is not type(other):
             return False
 
         # The string being used for redaction doesn't also have to match,
diff --git a/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/__init__.cpython-311.pyc
index 288d708..6c3428d 100644
Binary files a/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/bazaar.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/bazaar.cpython-311.pyc
index 5dd13ab..98d5e70 100644
Binary files a/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/bazaar.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/bazaar.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/git.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/git.cpython-311.pyc
index 0a38a17..fa52826 100644
Binary files a/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/git.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/git.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/mercurial.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/mercurial.cpython-311.pyc
index 3957cb2..89c14fe 100644
Binary files a/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/mercurial.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/mercurial.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/subversion.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/subversion.cpython-311.pyc
index e28104b..5843d65 100644
Binary files a/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/subversion.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/subversion.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/versioncontrol.cpython-311.pyc b/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/versioncontrol.cpython-311.pyc
index e8066af..314f75f 100644
Binary files a/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/versioncontrol.cpython-311.pyc and b/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/versioncontrol.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/__pycache__/__init__.cpython-311.pyc
index f00620e..e10895f 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/__pycache__/typing_extensions.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/__pycache__/typing_extensions.cpython-311.pyc
index 8eda5a6..b3abb20 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/__pycache__/typing_extensions.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/__pycache__/typing_extensions.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/__init__.cpython-311.pyc
index 991e5bf..1067b52 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-311.pyc
index c20510c..77f3fcf 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/adapter.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/adapter.cpython-311.pyc
index b1f17ec..9f0ffda 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/adapter.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/adapter.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/cache.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/cache.cpython-311.pyc
index 64fbb92..b514b52 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/cache.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/cache.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/controller.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/controller.cpython-311.pyc
index da6787e..1de8038 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/controller.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/controller.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-311.pyc
index ecca770..14678a2 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-311.pyc
index 7587083..6cc0d59 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/serialize.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/serialize.cpython-311.pyc
index 4678493..fbbcf4c 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/serialize.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/serialize.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-311.pyc
index f7bea69..069a656 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-311.pyc
index 5234fdb..ebbb702 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-311.pyc
index 5177638..a935941 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-311.pyc
index 534a16b..ad0f331 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/certifi/__init__.py b/venv/Lib/site-packages/pip/_vendor/certifi/__init__.py
index d321f1b..f61d77f 100644
--- a/venv/Lib/site-packages/pip/_vendor/certifi/__init__.py
+++ b/venv/Lib/site-packages/pip/_vendor/certifi/__init__.py
@@ -1,4 +1,4 @@
 from .core import contents, where
 
 __all__ = ["contents", "where"]
-__version__ = "2024.07.04"
+__version__ = "2024.08.30"
diff --git a/venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/__init__.cpython-311.pyc
index 4b01d04..a8b01c5 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/__main__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/__main__.cpython-311.pyc
index 09cf1bd..d2b6cf8 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/__main__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/__main__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/core.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/core.cpython-311.pyc
index ee21999..405502f 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/core.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/core.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/certifi/cacert.pem b/venv/Lib/site-packages/pip/_vendor/certifi/cacert.pem
index a658158..3c165a1 100644
--- a/venv/Lib/site-packages/pip/_vendor/certifi/cacert.pem
+++ b/venv/Lib/site-packages/pip/_vendor/certifi/cacert.pem
@@ -4796,3 +4796,134 @@ PQQDAwNoADBlAjAdfKR7w4l1M+E7qUW/Runpod3JIha3RxEL2Jq68cgLcFBTApFw
 hVmpHqTm6iMxoAACMQD94vizrxa5HnPEluPBMBnYfubDl94cT7iJLzPrSA8Z94dG
 XSaQpYXFuXqUPoeovQA=
 -----END CERTIFICATE-----
+
+# Issuer: CN=TWCA CYBER Root CA O=TAIWAN-CA OU=Root CA
+# Subject: CN=TWCA CYBER Root CA O=TAIWAN-CA OU=Root CA
+# Label: "TWCA CYBER Root CA"
+# Serial: 85076849864375384482682434040119489222
+# MD5 Fingerprint: 0b:33:a0:97:52:95:d4:a9:fd:bb:db:6e:a3:55:5b:51
+# SHA1 Fingerprint: f6:b1:1c:1a:83:38:e9:7b:db:b3:a8:c8:33:24:e0:2d:9c:7f:26:66
+# SHA256 Fingerprint: 3f:63:bb:28:14:be:17:4e:c8:b6:43:9c:f0:8d:6d:56:f0:b7:c4:05:88:3a:56:48:a3:34:42:4d:6b:3e:c5:58
+-----BEGIN CERTIFICATE-----
+MIIFjTCCA3WgAwIBAgIQQAE0jMIAAAAAAAAAATzyxjANBgkqhkiG9w0BAQwFADBQ
+MQswCQYDVQQGEwJUVzESMBAGA1UEChMJVEFJV0FOLUNBMRAwDgYDVQQLEwdSb290
+IENBMRswGQYDVQQDExJUV0NBIENZQkVSIFJvb3QgQ0EwHhcNMjIxMTIyMDY1NDI5
+WhcNNDcxMTIyMTU1OTU5WjBQMQswCQYDVQQGEwJUVzESMBAGA1UEChMJVEFJV0FO
+LUNBMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJUV0NBIENZQkVSIFJvb3Qg
+Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDG+Moe2Qkgfh1sTs6P
+40czRJzHyWmqOlt47nDSkvgEs1JSHWdyKKHfi12VCv7qze33Kc7wb3+szT3vsxxF
+avcokPFhV8UMxKNQXd7UtcsZyoC5dc4pztKFIuwCY8xEMCDa6pFbVuYdHNWdZsc/
+34bKS1PE2Y2yHer43CdTo0fhYcx9tbD47nORxc5zb87uEB8aBs/pJ2DFTxnk684i
+JkXXYJndzk834H/nY62wuFm40AZoNWDTNq5xQwTxaWV4fPMf88oon1oglWa0zbfu
+j3ikRRjpJi+NmykosaS3Om251Bw4ckVYsV7r8Cibt4LK/c/WMw+f+5eesRycnupf
+Xtuq3VTpMCEobY5583WSjCb+3MX2w7DfRFlDo7YDKPYIMKoNM+HvnKkHIuNZW0CP
+2oi3aQiotyMuRAlZN1vH4xfyIutuOVLF3lSnmMlLIJXcRolftBL5hSmO68gnFSDA
+S9TMfAxsNAwmmyYxpjyn9tnQS6Jk/zuZQXLB4HCX8SS7K8R0IrGsayIyJNN4KsDA
+oS/xUgXJP+92ZuJF2A09rZXIx4kmyA+upwMu+8Ff+iDhcK2wZSA3M2Cw1a/XDBzC
+kHDXShi8fgGwsOsVHkQGzaRP6AzRwyAQ4VRlnrZR0Bp2a0JaWHY06rc3Ga4udfmW
+5cFZ95RXKSWNOkyrTZpB0F8mAwIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBSdhWEUfMFib5do5E83QOGt4A1WNzAd
+BgNVHQ4EFgQUnYVhFHzBYm+XaORPN0DhreANVjcwDQYJKoZIhvcNAQEMBQADggIB
+AGSPesRiDrWIzLjHhg6hShbNcAu3p4ULs3a2D6f/CIsLJc+o1IN1KriWiLb73y0t
+tGlTITVX1olNc79pj3CjYcya2x6a4CD4bLubIp1dhDGaLIrdaqHXKGnK/nZVekZn
+68xDiBaiA9a5F/gZbG0jAn/xX9AKKSM70aoK7akXJlQKTcKlTfjF/biBzysseKNn
+TKkHmvPfXvt89YnNdJdhEGoHK4Fa0o635yDRIG4kqIQnoVesqlVYL9zZyvpoBJ7t
+RCT5dEA7IzOrg1oYJkK2bVS1FmAwbLGg+LhBoF1JSdJlBTrq/p1hvIbZv97Tujqx
+f36SNI7JAG7cmL3c7IAFrQI932XtCwP39xaEBDG6k5TY8hL4iuO/Qq+n1M0RFxbI
+Qh0UqEL20kCGoE8jypZFVmAGzbdVAaYBlGX+bgUJurSkquLvWL69J1bY73NxW0Qz
+8ppy6rBePm6pUlvscG21h483XjyMnM7k8M4MZ0HMzvaAq07MTFb1wWFZk7Q+ptq4
+NxKfKjLji7gh7MMrZQzvIt6IKTtM1/r+t+FHvpw+PoP7UV31aPcuIYXcv/Fa4nzX
+xeSDwWrruoBa3lwtcHb4yOWHh8qgnaHlIhInD0Q9HWzq1MKLL295q39QpsQZp6F6
+t5b5wR9iWqJDB0BeJsas7a5wFsWqynKKTbDPAYsDP27X
+-----END CERTIFICATE-----
+
+# Issuer: CN=SecureSign Root CA12 O=Cybertrust Japan Co., Ltd.
+# Subject: CN=SecureSign Root CA12 O=Cybertrust Japan Co., Ltd.
+# Label: "SecureSign Root CA12"
+# Serial: 587887345431707215246142177076162061960426065942
+# MD5 Fingerprint: c6:89:ca:64:42:9b:62:08:49:0b:1e:7f:e9:07:3d:e8
+# SHA1 Fingerprint: 7a:22:1e:3d:de:1b:06:ac:9e:c8:47:70:16:8e:3c:e5:f7:6b:06:f4
+# SHA256 Fingerprint: 3f:03:4b:b5:70:4d:44:b2:d0:85:45:a0:20:57:de:93:eb:f3:90:5f:ce:72:1a:cb:c7:30:c0:6d:da:ee:90:4e
+-----BEGIN CERTIFICATE-----
+MIIDcjCCAlqgAwIBAgIUZvnHwa/swlG07VOX5uaCwysckBYwDQYJKoZIhvcNAQEL
+BQAwUTELMAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28u
+LCBMdGQuMR0wGwYDVQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExMjAeFw0yMDA0MDgw
+NTM2NDZaFw00MDA0MDgwNTM2NDZaMFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpD
+eWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2VjdXJlU2lnbiBS
+b290IENBMTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6OcE3emhF
+KxS06+QT61d1I02PJC0W6K6OyX2kVzsqdiUzg2zqMoqUm048luT9Ub+ZyZN+v/mt
+p7JIKwccJ/VMvHASd6SFVLX9kHrko+RRWAPNEHl57muTH2SOa2SroxPjcf59q5zd
+J1M3s6oYwlkm7Fsf0uZlfO+TvdhYXAvA42VvPMfKWeP+bl+sg779XSVOKik71gur
+FzJ4pOE+lEa+Ym6b3kaosRbnhW70CEBFEaCeVESE99g2zvVQR9wsMJvuwPWW0v4J
+hscGWa5Pro4RmHvzC1KqYiaqId+OJTN5lxZJjfU+1UefNzFJM3IFTQy2VYzxV4+K
+h9GtxRESOaCtAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD
+AgEGMB0GA1UdDgQWBBRXNPN0zwRL1SXm8UC2LEzZLemgrTANBgkqhkiG9w0BAQsF
+AAOCAQEAPrvbFxbS8hQBICw4g0utvsqFepq2m2um4fylOqyttCg6r9cBg0krY6Ld
+mmQOmFxv3Y67ilQiLUoT865AQ9tPkbeGGuwAtEGBpE/6aouIs3YIcipJQMPTw4WJ
+mBClnW8Zt7vPemVV2zfrPIpyMpcemik+rY3moxtt9XUa5rBouVui7mlHJzWhhpmA
+8zNL4WukJsPvdFlseqJkth5Ew1DgDzk9qTPxpfPSvWKErI4cqc1avTc7bgoitPQV
+55FYxTpE05Uo2cBl6XLK0A+9H7MV2anjpEcJnuDLN/v9vZfVvhgaaaI5gdka9at/
+yOPiZwud9AzqVN/Ssq+xIvEg37xEHA==
+-----END CERTIFICATE-----
+
+# Issuer: CN=SecureSign Root CA14 O=Cybertrust Japan Co., Ltd.
+# Subject: CN=SecureSign Root CA14 O=Cybertrust Japan Co., Ltd.
+# Label: "SecureSign Root CA14"
+# Serial: 575790784512929437950770173562378038616896959179
+# MD5 Fingerprint: 71:0d:72:fa:92:19:65:5e:89:04:ac:16:33:f0:bc:d5
+# SHA1 Fingerprint: dd:50:c0:f7:79:b3:64:2e:74:a2:b8:9d:9f:d3:40:dd:bb:f0:f2:4f
+# SHA256 Fingerprint: 4b:00:9c:10:34:49:4f:9a:b5:6b:ba:3b:a1:d6:27:31:fc:4d:20:d8:95:5a:dc:ec:10:a9:25:60:72:61:e3:38
+-----BEGIN CERTIFICATE-----
+MIIFcjCCA1qgAwIBAgIUZNtaDCBO6Ncpd8hQJ6JaJ90t8sswDQYJKoZIhvcNAQEM
+BQAwUTELMAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28u
+LCBMdGQuMR0wGwYDVQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExNDAeFw0yMDA0MDgw
+NzA2MTlaFw00NTA0MDgwNzA2MTlaMFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpD
+eWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2VjdXJlU2lnbiBS
+b290IENBMTQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDF0nqh1oq/
+FjHQmNE6lPxauG4iwWL3pwon71D2LrGeaBLwbCRjOfHw3xDG3rdSINVSW0KZnvOg
+vlIfX8xnbacuUKLBl422+JX1sLrcneC+y9/3OPJH9aaakpUqYllQC6KxNedlsmGy
+6pJxaeQp8E+BgQQ8sqVb1MWoWWd7VRxJq3qdwudzTe/NCcLEVxLbAQ4jeQkHO6Lo
+/IrPj8BGJJw4J+CDnRugv3gVEOuGTgpa/d/aLIJ+7sr2KeH6caH3iGicnPCNvg9J
+kdjqOvn90Ghx2+m1K06Ckm9mH+Dw3EzsytHqunQG+bOEkJTRX45zGRBdAuVwpcAQ
+0BB8b8VYSbSwbprafZX1zNoCr7gsfXmPvkPx+SgojQlD+Ajda8iLLCSxjVIHvXib
+y8posqTdDEx5YMaZ0ZPxMBoH064iwurO8YQJzOAUbn8/ftKChazcqRZOhaBgy/ac
+18izju3Gm5h1DVXoX+WViwKkrkMpKBGk5hIwAUt1ax5mnXkvpXYvHUC0bcl9eQjs
+0Wq2XSqypWa9a4X0dFbD9ed1Uigspf9mR6XU/v6eVL9lfgHWMI+lNpyiUBzuOIAB
+SMbHdPTGrMNASRZhdCyvjG817XsYAFs2PJxQDcqSMxDxJklt33UkN4Ii1+iW/RVL
+ApY+B3KVfqs9TC7XyvDf4Fg/LS8EmjijAQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
+AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUBpOjCl4oaTeqYR3r6/wtbyPk
+86AwDQYJKoZIhvcNAQEMBQADggIBAJaAcgkGfpzMkwQWu6A6jZJOtxEaCnFxEM0E
+rX+lRVAQZk5KQaID2RFPeje5S+LGjzJmdSX7684/AykmjbgWHfYfM25I5uj4V7Ib
+ed87hwriZLoAymzvftAj63iP/2SbNDefNWWipAA9EiOWWF3KY4fGoweITedpdopT
+zfFP7ELyk+OZpDc8h7hi2/DsHzc/N19DzFGdtfCXwreFamgLRB7lUe6TzktuhsHS
+DCRZNhqfLJGP4xjblJUK7ZGqDpncllPjYYPGFrojutzdfhrGe0K22VoF3Jpf1d+4
+2kd92jjbrDnVHmtsKheMYc2xbXIBw8MgAGJoFjHVdqqGuw6qnsb58Nn4DSEC5MUo
+FlkRudlpcyqSeLiSV5sI8jrlL5WwWLdrIBRtFO8KvH7YVdiI2i/6GaX7i+B/OfVy
+K4XELKzvGUWSTLNhB9xNH27SgRNcmvMSZ4PPmz+Ln52kuaiWA3rF7iDeM9ovnhp6
+dB7h7sxaOgTdsxoEqBRjrLdHEoOabPXm6RUVkRqEGQ6UROcSjiVbgGcZ3GOTEAtl
+Lor6CZpO2oYofaphNdgOpygau1LgePhsumywbrmHXumZNTfxPWQrqaA0k89jL9WB
+365jJ6UeTo3cKXhZ+PmhIIynJkBugnLNeLLIjzwec+fBH7/PzqUqm9tEZDKgu39c
+JRNItX+S
+-----END CERTIFICATE-----
+
+# Issuer: CN=SecureSign Root CA15 O=Cybertrust Japan Co., Ltd.
+# Subject: CN=SecureSign Root CA15 O=Cybertrust Japan Co., Ltd.
+# Label: "SecureSign Root CA15"
+# Serial: 126083514594751269499665114766174399806381178503
+# MD5 Fingerprint: 13:30:fc:c4:62:a6:a9:de:b5:c1:68:af:b5:d2:31:47
+# SHA1 Fingerprint: cb:ba:83:c8:c1:5a:5d:f1:f9:73:6f:ca:d7:ef:28:13:06:4a:07:7d
+# SHA256 Fingerprint: e7:78:f0:f0:95:fe:84:37:29:cd:1a:00:82:17:9e:53:14:a9:c2:91:44:28:05:e1:fb:1d:8f:b6:b8:88:6c:3a
+-----BEGIN CERTIFICATE-----
+MIICIzCCAamgAwIBAgIUFhXHw9hJp75pDIqI7fBw+d23PocwCgYIKoZIzj0EAwMw
+UTELMAkGA1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBM
+dGQuMR0wGwYDVQQDExRTZWN1cmVTaWduIFJvb3QgQ0ExNTAeFw0yMDA0MDgwODMy
+NTZaFw00NTA0MDgwODMyNTZaMFExCzAJBgNVBAYTAkpQMSMwIQYDVQQKExpDeWJl
+cnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2VjdXJlU2lnbiBSb290
+IENBMTUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQLUHSNZDKZmbPSYAi4Io5GdCx4
+wCtELW1fHcmuS1Iggz24FG1Th2CeX2yF2wYUleDHKP+dX+Sq8bOLbe1PL0vJSpSR
+ZHX+AezB2Ot6lHhWGENfa4HL9rzatAy2KZMIaY+jQjBAMA8GA1UdEwEB/wQFMAMB
+Af8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTrQciu/NWeUUj1vYv0hyCTQSvT
+9DAKBggqhkjOPQQDAwNoADBlAjEA2S6Jfl5OpBEHvVnCB96rMjhTKkZEBhd6zlHp
+4P9mLQlO4E/0BdGF9jVg3PVys0Z9AjBEmEYagoUeYWmJSwdLZrWeqrqgHkHZAXQ6
+bkU6iYAZezKYVWOr62Nuk22rGwlgMU4=
+-----END CERTIFICATE-----
diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/__init__.py b/venv/Lib/site-packages/pip/_vendor/distlib/__init__.py
index e999438..bf0d6c6 100644
--- a/venv/Lib/site-packages/pip/_vendor/distlib/__init__.py
+++ b/venv/Lib/site-packages/pip/_vendor/distlib/__init__.py
@@ -6,7 +6,7 @@
 #
 import logging
 
-__version__ = '0.3.8'
+__version__ = '0.3.9'
 
 
 class DistlibException(Exception):
diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/__init__.cpython-311.pyc
index c697416..969555c 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/compat.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/compat.cpython-311.pyc
index 60e3415..406c65f 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/compat.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/compat.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/database.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/database.cpython-311.pyc
index cbcfd9f..2eea6b5 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/database.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/database.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/index.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/index.cpython-311.pyc
index 0e03993..f70a82f 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/index.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/index.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/locators.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/locators.cpython-311.pyc
index f37d2ff..3899793 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/locators.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/locators.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/manifest.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/manifest.cpython-311.pyc
index a9dbff8..b08b439 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/manifest.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/manifest.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/markers.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/markers.cpython-311.pyc
index 1d7428d..2e17396 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/markers.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/markers.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/metadata.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/metadata.cpython-311.pyc
index 4553b53..c177c32 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/metadata.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/metadata.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/resources.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/resources.cpython-311.pyc
index 6fc927a..adf7991 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/resources.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/resources.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/scripts.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/scripts.cpython-311.pyc
index fa368f0..d2b1abb 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/scripts.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/scripts.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/util.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/util.cpython-311.pyc
index 4a293db..b7c2ada 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/util.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/util.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/version.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/version.cpython-311.pyc
index 550f80b..0e812d8 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/version.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/version.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/wheel.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/wheel.cpython-311.pyc
index 37d50bd..e246e6a 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/wheel.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/wheel.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/compat.py b/venv/Lib/site-packages/pip/_vendor/distlib/compat.py
index e93dc27..ca561dd 100644
--- a/venv/Lib/site-packages/pip/_vendor/distlib/compat.py
+++ b/venv/Lib/site-packages/pip/_vendor/distlib/compat.py
@@ -217,8 +217,7 @@ def which(cmd, mode=os.F_OK | os.X_OK, path=None):
         # Additionally check that `file` is not a directory, as on Windows
         # directories pass the os.access check.
         def _access_check(fn, mode):
-            return (os.path.exists(fn) and os.access(fn, mode)
-                    and not os.path.isdir(fn))
+            return (os.path.exists(fn) and os.access(fn, mode) and not os.path.isdir(fn))
 
         # If we're given a path with a directory part, look it up directly rather
         # than referring to PATH directories. This includes checking relative to the
diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/database.py b/venv/Lib/site-packages/pip/_vendor/distlib/database.py
index eb3765f..c0f896a 100644
--- a/venv/Lib/site-packages/pip/_vendor/distlib/database.py
+++ b/venv/Lib/site-packages/pip/_vendor/distlib/database.py
@@ -20,14 +20,12 @@
 from . import DistlibException, resources
 from .compat import StringIO
 from .version import get_scheme, UnsupportedVersionError
-from .metadata import (Metadata, METADATA_FILENAME, WHEEL_METADATA_FILENAME,
-                       LEGACY_METADATA_FILENAME)
-from .util import (parse_requirement, cached_property, parse_name_and_version,
-                   read_exports, write_exports, CSVReader, CSVWriter)
+from .metadata import (Metadata, METADATA_FILENAME, WHEEL_METADATA_FILENAME, LEGACY_METADATA_FILENAME)
+from .util import (parse_requirement, cached_property, parse_name_and_version, read_exports, write_exports, CSVReader,
+                   CSVWriter)
 
 __all__ = [
-    'Distribution', 'BaseInstalledDistribution', 'InstalledDistribution',
-    'EggInfoDistribution', 'DistributionPath'
+    'Distribution', 'BaseInstalledDistribution', 'InstalledDistribution', 'EggInfoDistribution', 'DistributionPath'
 ]
 
 logger = logging.getLogger(__name__)
@@ -35,8 +33,7 @@
 EXPORTS_FILENAME = 'pydist-exports.json'
 COMMANDS_FILENAME = 'pydist-commands.json'
 
-DIST_FILES = ('INSTALLER', METADATA_FILENAME, 'RECORD', 'REQUESTED',
-              'RESOURCES', EXPORTS_FILENAME, 'SHARED')
+DIST_FILES = ('INSTALLER', METADATA_FILENAME, 'RECORD', 'REQUESTED', 'RESOURCES', EXPORTS_FILENAME, 'SHARED')
 
 DISTINFO_EXT = '.dist-info'
 
@@ -134,13 +131,9 @@ def _yield_distributions(self):
                     continue
                 try:
                     if self._include_dist and entry.endswith(DISTINFO_EXT):
-                        possible_filenames = [
-                            METADATA_FILENAME, WHEEL_METADATA_FILENAME,
-                            LEGACY_METADATA_FILENAME
-                        ]
+                        possible_filenames = [METADATA_FILENAME, WHEEL_METADATA_FILENAME, LEGACY_METADATA_FILENAME]
                         for metadata_filename in possible_filenames:
-                            metadata_path = posixpath.join(
-                                entry, metadata_filename)
+                            metadata_path = posixpath.join(entry, metadata_filename)
                             pydist = finder.find(metadata_path)
                             if pydist:
                                 break
@@ -148,15 +141,11 @@ def _yield_distributions(self):
                             continue
 
                         with contextlib.closing(pydist.as_stream()) as stream:
-                            metadata = Metadata(fileobj=stream,
-                                                scheme='legacy')
+                            metadata = Metadata(fileobj=stream, scheme='legacy')
                         logger.debug('Found %s', r.path)
                         seen.add(r.path)
-                        yield new_dist_class(r.path,
-                                             metadata=metadata,
-                                             env=self)
-                    elif self._include_egg and entry.endswith(
-                            ('.egg-info', '.egg')):
+                        yield new_dist_class(r.path, metadata=metadata, env=self)
+                    elif self._include_egg and entry.endswith(('.egg-info', '.egg')):
                         logger.debug('Found %s', r.path)
                         seen.add(r.path)
                         yield old_dist_class(r.path, self)
@@ -274,8 +263,7 @@ def provides_distribution(self, name, version=None):
             try:
                 matcher = self._scheme.matcher('%s (%s)' % (name, version))
             except ValueError:
-                raise DistlibException('invalid name or version: %r, %r' %
-                                       (name, version))
+                raise DistlibException('invalid name or version: %r, %r' % (name, version))
 
         for dist in self.get_distributions():
             # We hit a problem on Travis where enum34 was installed and doesn't
@@ -390,10 +378,8 @@ def provides(self):
     def _get_requirements(self, req_attr):
         md = self.metadata
         reqts = getattr(md, req_attr)
-        logger.debug('%s: got requirements %r from metadata: %r', self.name,
-                     req_attr, reqts)
-        return set(
-            md.get_requirements(reqts, extras=self.extras, env=self.context))
+        logger.debug('%s: got requirements %r from metadata: %r', self.name, req_attr, reqts)
+        return set(md.get_requirements(reqts, extras=self.extras, env=self.context))
 
     @property
     def run_requires(self):
@@ -469,8 +455,7 @@ def __eq__(self, other):
         if type(other) is not type(self):
             result = False
         else:
-            result = (self.name == other.name and self.version == other.version
-                      and self.source_url == other.source_url)
+            result = (self.name == other.name and self.version == other.version and self.source_url == other.source_url)
         return result
 
     def __hash__(self):
@@ -561,8 +546,7 @@ def __init__(self, path, metadata=None, env=None):
             if r is None:
                 r = finder.find(LEGACY_METADATA_FILENAME)
             if r is None:
-                raise ValueError('no %s found in %s' %
-                                 (METADATA_FILENAME, path))
+                raise ValueError('no %s found in %s' % (METADATA_FILENAME, path))
             with contextlib.closing(r.as_stream()) as stream:
                 metadata = Metadata(fileobj=stream, scheme='legacy')
 
@@ -580,8 +564,7 @@ def __init__(self, path, metadata=None, env=None):
             self.modules = data.splitlines()
 
     def __repr__(self):
-        return '' % (
-            self.name, self.version, self.path)
+        return '' % (self.name, self.version, self.path)
 
     def __str__(self):
         return "%s %s" % (self.name, self.version)
@@ -703,8 +686,7 @@ def write_installed_files(self, paths, prefix, dry_run=False):
                     size = '%d' % os.path.getsize(path)
                     with open(path, 'rb') as fp:
                         hash_value = self.get_hash(fp.read())
-                if path.startswith(base) or (base_under_prefix
-                                             and path.startswith(prefix)):
+                if path.startswith(base) or (base_under_prefix and path.startswith(prefix)):
                     path = os.path.relpath(path, base)
                 writer.writerow((path, hash_value, size))
 
@@ -746,8 +728,7 @@ def check_installed_files(self):
                     with open(path, 'rb') as f:
                         actual_hash = self.get_hash(f.read(), hasher)
                         if actual_hash != hash_value:
-                            mismatches.append(
-                                (path, 'hash', hash_value, actual_hash))
+                            mismatches.append((path, 'hash', hash_value, actual_hash))
         return mismatches
 
     @cached_property
@@ -829,9 +810,8 @@ def get_distinfo_file(self, path):
             # it's an absolute path?
             distinfo_dirname, path = path.split(os.sep)[-2:]
             if distinfo_dirname != self.path.split(os.sep)[-1]:
-                raise DistlibException(
-                    'dist-info file %r does not belong to the %r %s '
-                    'distribution' % (path, self.name, self.version))
+                raise DistlibException('dist-info file %r does not belong to the %r %s '
+                                       'distribution' % (path, self.name, self.version))
 
         # The file must be relative
         if path not in DIST_FILES:
@@ -857,8 +837,7 @@ def list_distinfo_files(self):
                 yield path
 
     def __eq__(self, other):
-        return (isinstance(other, InstalledDistribution)
-                and self.path == other.path)
+        return (isinstance(other, InstalledDistribution) and self.path == other.path)
 
     # See http://docs.python.org/reference/datamodel#object.__hash__
     __hash__ = object.__hash__
@@ -911,8 +890,7 @@ def parse_requires_data(data):
                 if not line:  # pragma: no cover
                     continue
                 if line.startswith('['):  # pragma: no cover
-                    logger.warning(
-                        'Unexpected line: quitting requirement scan: %r', line)
+                    logger.warning('Unexpected line: quitting requirement scan: %r', line)
                     break
                 r = parse_requirement(line)
                 if not r:  # pragma: no cover
@@ -954,13 +932,11 @@ def parse_requires_path(req_path):
             else:
                 # FIXME handle the case where zipfile is not available
                 zipf = zipimport.zipimporter(path)
-                fileobj = StringIO(
-                    zipf.get_data('EGG-INFO/PKG-INFO').decode('utf8'))
+                fileobj = StringIO(zipf.get_data('EGG-INFO/PKG-INFO').decode('utf8'))
                 metadata = Metadata(fileobj=fileobj, scheme='legacy')
                 try:
                     data = zipf.get_data('EGG-INFO/requires.txt')
-                    tl_data = zipf.get_data('EGG-INFO/top_level.txt').decode(
-                        'utf-8')
+                    tl_data = zipf.get_data('EGG-INFO/top_level.txt').decode('utf-8')
                     requires = parse_requires_data(data.decode('utf-8'))
                 except IOError:
                     requires = None
@@ -990,8 +966,7 @@ def parse_requires_path(req_path):
         return metadata
 
     def __repr__(self):
-        return '' % (self.name, self.version,
-                                                      self.path)
+        return '' % (self.name, self.version, self.path)
 
     def __str__(self):
         return "%s %s" % (self.name, self.version)
@@ -1083,8 +1058,7 @@ def list_distinfo_files(self, absolute=False):
                                 yield line
 
     def __eq__(self, other):
-        return (isinstance(other, EggInfoDistribution)
-                and self.path == other.path)
+        return (isinstance(other, EggInfoDistribution) and self.path == other.path)
 
     # See http://docs.python.org/reference/datamodel#object.__hash__
     __hash__ = object.__hash__
@@ -1184,8 +1158,7 @@ def to_dot(self, f, skip_disconnected=True):
                 disconnected.append(dist)
             for other, label in adjs:
                 if label is not None:
-                    f.write('"%s" -> "%s" [label="%s"]\n' %
-                            (dist.name, other.name, label))
+                    f.write('"%s" -> "%s" [label="%s"]\n' % (dist.name, other.name, label))
                 else:
                     f.write('"%s" -> "%s"\n' % (dist.name, other.name))
         if not skip_disconnected and len(disconnected) > 0:
@@ -1225,8 +1198,7 @@ def topological_sort(self):
             # Remove from the adjacency list of others
             for k, v in alist.items():
                 alist[k] = [(d, r) for d, r in v if d not in to_remove]
-            logger.debug('Moving to result: %s',
-                         ['%s (%s)' % (d.name, d.version) for d in to_remove])
+            logger.debug('Moving to result: %s', ['%s (%s)' % (d.name, d.version) for d in to_remove])
             result.extend(to_remove)
         return result, list(alist.keys())
 
@@ -1261,15 +1233,13 @@ def make_graph(dists, scheme='default'):
 
     # now make the edges
     for dist in dists:
-        requires = (dist.run_requires | dist.meta_requires
-                    | dist.build_requires | dist.dev_requires)
+        requires = (dist.run_requires | dist.meta_requires | dist.build_requires | dist.dev_requires)
         for req in requires:
             try:
                 matcher = scheme.matcher(req)
             except UnsupportedVersionError:
                 # XXX compat-mode if cannot read the version
-                logger.warning('could not read version %r - using name only',
-                               req)
+                logger.warning('could not read version %r - using name only', req)
                 name = req.split()[0]
                 matcher = scheme.matcher(name)
 
diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/locators.py b/venv/Lib/site-packages/pip/_vendor/distlib/locators.py
index f9f0788..222c1bf 100644
--- a/venv/Lib/site-packages/pip/_vendor/distlib/locators.py
+++ b/venv/Lib/site-packages/pip/_vendor/distlib/locators.py
@@ -19,15 +19,12 @@
 import zlib
 
 from . import DistlibException
-from .compat import (urljoin, urlparse, urlunparse, url2pathname, pathname2url,
-                     queue, quote, unescape, build_opener,
-                     HTTPRedirectHandler as BaseRedirectHandler, text_type,
-                     Request, HTTPError, URLError)
+from .compat import (urljoin, urlparse, urlunparse, url2pathname, pathname2url, queue, quote, unescape, build_opener,
+                     HTTPRedirectHandler as BaseRedirectHandler, text_type, Request, HTTPError, URLError)
 from .database import Distribution, DistributionPath, make_dist
 from .metadata import Metadata, MetadataInvalidError
-from .util import (cached_property, ensure_slash, split_filename, get_project_data,
-                   parse_requirement, parse_name_and_version, ServerProxy,
-                   normalize_name)
+from .util import (cached_property, ensure_slash, split_filename, get_project_data, parse_requirement,
+                   parse_name_and_version, ServerProxy, normalize_name)
 from .version import get_scheme, UnsupportedVersionError
 from .wheel import Wheel, is_compatible
 
@@ -58,6 +55,7 @@ class RedirectHandler(BaseRedirectHandler):
     """
     A class to work around a bug in some Python 3.2.x releases.
     """
+
     # There's a bug in the base version for some 3.2.x
     # (e.g. 3.2.2 on Ubuntu Oneiric). If a Location header
     # returns e.g. /abc, it bails because it says the scheme ''
@@ -80,8 +78,7 @@ def http_error_302(self, req, fp, code, msg, headers):
                 headers.replace_header(key, newurl)
             else:
                 headers[key] = newurl
-        return BaseRedirectHandler.http_error_302(self, req, fp, code, msg,
-                                                  headers)
+        return BaseRedirectHandler.http_error_302(self, req, fp, code, msg, headers)
 
     http_error_301 = http_error_303 = http_error_307 = http_error_302
 
@@ -92,7 +89,7 @@ class Locator(object):
     """
     source_extensions = ('.tar.gz', '.tar.bz2', '.tar', '.zip', '.tgz', '.tbz')
     binary_extensions = ('.egg', '.exe', '.whl')
-    excluded_extensions = ('.pdf',)
+    excluded_extensions = ('.pdf', )
 
     # A list of tags indicating which wheels you want to match. The default
     # value of None matches against the tags compatible with the running
@@ -100,7 +97,7 @@ class Locator(object):
     # instance to a list of tuples (pyver, abi, arch) which you want to match.
     wheel_tags = None
 
-    downloadable_extensions = source_extensions + ('.whl',)
+    downloadable_extensions = source_extensions + ('.whl', )
 
     def __init__(self, scheme='default'):
         """
@@ -200,8 +197,7 @@ def score_url(self, url):
         is_downloadable = basename.endswith(self.downloadable_extensions)
         if is_wheel:
             compatible = is_compatible(Wheel(basename), self.wheel_tags)
-        return (t.scheme == 'https', 'pypi.org' in t.netloc,
-                is_downloadable, is_wheel, compatible, basename)
+        return (t.scheme == 'https', 'pypi.org' in t.netloc, is_downloadable, is_wheel, compatible, basename)
 
     def prefer_url(self, url1, url2):
         """
@@ -239,14 +235,14 @@ def convert_url_to_download_info(self, url, project_name):
         If it is, a dictionary is returned with keys "name", "version",
         "filename" and "url"; otherwise, None is returned.
         """
+
         def same_project(name1, name2):
             return normalize_name(name1) == normalize_name(name2)
 
         result = None
         scheme, netloc, path, params, query, frag = urlparse(url)
         if frag.lower().startswith('egg='):  # pragma: no cover
-            logger.debug('%s: version hint in fragment: %r',
-                         project_name, frag)
+            logger.debug('%s: version hint in fragment: %r', project_name, frag)
         m = HASHER_HASH.match(frag)
         if m:
             algo, digest = m.groups()
@@ -270,10 +266,8 @@ def same_project(name1, name2):
                             'name': wheel.name,
                             'version': wheel.version,
                             'filename': wheel.filename,
-                            'url': urlunparse((scheme, netloc, origpath,
-                                               params, query, '')),
-                            'python-version': ', '.join(
-                                ['.'.join(list(v[2:])) for v in wheel.pyver]),
+                            'url': urlunparse((scheme, netloc, origpath, params, query, '')),
+                            'python-version': ', '.join(['.'.join(list(v[2:])) for v in wheel.pyver]),
                         }
             except Exception:  # pragma: no cover
                 logger.warning('invalid path for wheel: %s', path)
@@ -294,8 +288,7 @@ def same_project(name1, name2):
                                 'name': name,
                                 'version': version,
                                 'filename': filename,
-                                'url': urlunparse((scheme, netloc, origpath,
-                                                   params, query, '')),
+                                'url': urlunparse((scheme, netloc, origpath, params, query, '')),
                             }
                             if pyver:  # pragma: no cover
                                 result['python-version'] = pyver
@@ -371,7 +364,7 @@ def locate(self, requirement, prereleases=False):
         self.matcher = matcher = scheme.matcher(r.requirement)
         logger.debug('matcher: %s (%s)', matcher, type(matcher).__name__)
         versions = self.get_project(r.name)
-        if len(versions) > 2:   # urls and digests keys are present
+        if len(versions) > 2:  # urls and digests keys are present
             # sometimes, versions are invalid
             slist = []
             vcls = matcher.version_class
@@ -412,6 +405,7 @@ class PyPIRPCLocator(Locator):
     This locator uses XML-RPC to locate distributions. It therefore
     cannot be used with simple mirrors (that only mirror file content).
     """
+
     def __init__(self, url, **kwargs):
         """
         Initialise an instance.
@@ -461,6 +455,7 @@ class PyPIJSONLocator(Locator):
     This locator uses PyPI's JSON interface. It's very limited in functionality
     and probably not worth using.
     """
+
     def __init__(self, url, **kwargs):
         super(PyPIJSONLocator, self).__init__(**kwargs)
         self.base_url = ensure_slash(url)
@@ -498,7 +493,7 @@ def _get_project(self, name):
             # Now get other releases
             for version, infos in d['releases'].items():
                 if version == md.version:
-                    continue    # already done
+                    continue  # already done
                 omd = Metadata(scheme=self.scheme)
                 omd.name = md.name
                 omd.version = version
@@ -511,6 +506,8 @@ def _get_project(self, name):
                     odist.digests[url] = self._get_digest(info)
                     result['urls'].setdefault(version, set()).add(url)
                     result['digests'][url] = self._get_digest(info)
+
+
 #            for info in urls:
 #                md.source_url = info['url']
 #                dist.digest = self._get_digest(info)
@@ -534,7 +531,8 @@ class Page(object):
     # or immediately followed by a "rel" attribute. The attribute values can be
     # declared with double quotes, single quotes or no quotes - which leads to
     # the length of the expression.
-    _href = re.compile("""
+    _href = re.compile(
+        """
 (rel\\s*=\\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\\s\n]*))\\s+)?
 href\\s*=\\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\\s\n]*))
 (\\s+rel\\s*=\\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\\s\n]*)))?
@@ -561,17 +559,16 @@ def links(self):
         about their "rel" attribute, for determining which ones to treat as
         downloads and which ones to queue for further scraping.
         """
+
         def clean(url):
             "Tidy up an URL."
             scheme, netloc, path, params, query, frag = urlparse(url)
-            return urlunparse((scheme, netloc, quote(path),
-                               params, query, frag))
+            return urlunparse((scheme, netloc, quote(path), params, query, frag))
 
         result = set()
         for match in self._href.finditer(self.data):
             d = match.groupdict('')
-            rel = (d['rel1'] or d['rel2'] or d['rel3'] or
-                   d['rel4'] or d['rel5'] or d['rel6'])
+            rel = (d['rel1'] or d['rel2'] or d['rel3'] or d['rel4'] or d['rel5'] or d['rel6'])
             url = d['url1'] or d['url2'] or d['url3']
             url = urljoin(self.base_url, url)
             url = unescape(url)
@@ -645,7 +642,7 @@ def _wait_threads(self):
         # Note that you need two loops, since you can't say which
         # thread will get each sentinel
         for t in self._threads:
-            self._to_fetch.put(None)    # sentinel
+            self._to_fetch.put(None)  # sentinel
         for t in self._threads:
             t.join()
         self._threads = []
@@ -693,7 +690,7 @@ def _process_download(self, url):
             info = self.convert_url_to_download_info(url, self.project_name)
         logger.debug('process_download: %s -> %s', url, info)
         if info:
-            with self._lock:    # needed because self.result is shared
+            with self._lock:  # needed because self.result is shared
                 self._update_version_data(self.result, info)
         return info
 
@@ -703,8 +700,7 @@ def _should_queue(self, link, referrer, rel):
         particular "rel" attribute should be queued for scraping.
         """
         scheme, netloc, path, _, _, _ = urlparse(link)
-        if path.endswith(self.source_extensions + self.binary_extensions +
-                         self.excluded_extensions):
+        if path.endswith(self.source_extensions + self.binary_extensions + self.excluded_extensions):
             result = False
         elif self.skip_externals and not link.startswith(self.base_url):
             result = False
@@ -722,8 +718,7 @@ def _should_queue(self, link, referrer, rel):
                 result = False
             else:
                 result = True
-        logger.debug('should_queue: %s (%s) from %s -> %s', link, rel,
-                     referrer, result)
+        logger.debug('should_queue: %s (%s) from %s -> %s', link, rel, referrer, result)
         return result
 
     def _fetch(self):
@@ -738,14 +733,13 @@ def _fetch(self):
             try:
                 if url:
                     page = self.get_page(url)
-                    if page is None:    # e.g. after an error
+                    if page is None:  # e.g. after an error
                         continue
                     for link, rel in page.links:
                         if link not in self._seen:
                             try:
                                 self._seen.add(link)
-                                if (not self._process_download(link) and
-                                        self._should_queue(link, url, rel)):
+                                if (not self._process_download(link) and self._should_queue(link, url, rel)):
                                     logger.debug('Queueing %s from %s', link, url)
                                     self._to_fetch.put(link)
                             except MetadataInvalidError:  # e.g. invalid versions
@@ -793,7 +787,7 @@ def get_page(self, url):
                         data = resp.read()
                         encoding = headers.get('Content-Encoding')
                         if encoding:
-                            decoder = self.decoders[encoding]   # fail if not found
+                            decoder = self.decoders[encoding]  # fail if not found
                             data = decoder(data)
                         encoding = 'utf-8'
                         m = CHARSET.search(content_type)
@@ -802,7 +796,7 @@ def get_page(self, url):
                         try:
                             data = data.decode(encoding)
                         except UnicodeError:  # pragma: no cover
-                            data = data.decode('latin-1')    # fallback
+                            data = data.decode('latin-1')  # fallback
                         result = Page(data, final_url)
                         self._page_cache[final_url] = result
                 except HTTPError as e:
@@ -815,7 +809,7 @@ def get_page(self, url):
                 except Exception as e:  # pragma: no cover
                     logger.exception('Fetch failed: %s: %s', url, e)
                 finally:
-                    self._page_cache[url] = result   # even if None (failure)
+                    self._page_cache[url] = result  # even if None (failure)
         return result
 
     _distname_re = re.compile(']*>([^<]+)<')
@@ -869,9 +863,7 @@ def _get_project(self, name):
             for fn in files:
                 if self.should_include(fn, root):
                     fn = os.path.join(root, fn)
-                    url = urlunparse(('file', '',
-                                      pathname2url(os.path.abspath(fn)),
-                                      '', '', ''))
+                    url = urlunparse(('file', '', pathname2url(os.path.abspath(fn)), '', '', ''))
                     info = self.convert_url_to_download_info(url, name)
                     if info:
                         self._update_version_data(result, info)
@@ -888,9 +880,7 @@ def get_distribution_names(self):
             for fn in files:
                 if self.should_include(fn, root):
                     fn = os.path.join(root, fn)
-                    url = urlunparse(('file', '',
-                                      pathname2url(os.path.abspath(fn)),
-                                      '', '', ''))
+                    url = urlunparse(('file', '', pathname2url(os.path.abspath(fn)), '', '', ''))
                     info = self.convert_url_to_download_info(url, None)
                     if info:
                         result.add(info['name'])
@@ -906,6 +896,7 @@ class JSONLocator(Locator):
     require archive downloads before dependencies can be determined! As you
     might imagine, that can be slow.
     """
+
     def get_distribution_names(self):
         """
         Return all the distribution names known to this locator.
@@ -922,9 +913,9 @@ def _get_project(self, name):
                 # We don't store summary in project metadata as it makes
                 # the data bigger for no benefit during dependency
                 # resolution
-                dist = make_dist(data['name'], info['version'],
-                                 summary=data.get('summary',
-                                                  'Placeholder for summary'),
+                dist = make_dist(data['name'],
+                                 info['version'],
+                                 summary=data.get('summary', 'Placeholder for summary'),
                                  scheme=self.scheme)
                 md = dist.metadata
                 md.source_url = info['url']
@@ -943,6 +934,7 @@ class DistPathLocator(Locator):
     This locator finds installed distributions in a path. It can be useful for
     adding to an :class:`AggregatingLocator`.
     """
+
     def __init__(self, distpath, **kwargs):
         """
         Initialise an instance.
@@ -960,8 +952,12 @@ def _get_project(self, name):
         else:
             result = {
                 dist.version: dist,
-                'urls': {dist.version: set([dist.source_url])},
-                'digests': {dist.version: set([None])}
+                'urls': {
+                    dist.version: set([dist.source_url])
+                },
+                'digests': {
+                    dist.version: set([None])
+                }
             }
         return result
 
@@ -970,6 +966,7 @@ class AggregatingLocator(Locator):
     """
     This class allows you to chain and/or merge a list of locators.
     """
+
     def __init__(self, *locators, **kwargs):
         """
         Initialise an instance.
@@ -1058,10 +1055,9 @@ def get_distribution_names(self):
 # We use a legacy scheme simply because most of the dists on PyPI use legacy
 # versions which don't conform to PEP 440.
 default_locator = AggregatingLocator(
-                    # JSONLocator(), # don't use as PEP 426 is withdrawn
-                    SimpleScrapingLocator('https://pypi.org/simple/',
-                                          timeout=3.0),
-                    scheme='legacy')
+    # JSONLocator(), # don't use as PEP 426 is withdrawn
+    SimpleScrapingLocator('https://pypi.org/simple/', timeout=3.0),
+    scheme='legacy')
 
 locate = default_locator.locate
 
@@ -1137,7 +1133,7 @@ def find_providers(self, reqt):
         :return: A set of distribution which can fulfill the requirement.
         """
         matcher = self.get_matcher(reqt)
-        name = matcher.key   # case-insensitive
+        name = matcher.key  # case-insensitive
         result = set()
         provided = self.provided
         if name in provided:
@@ -1179,8 +1175,7 @@ def try_to_replace(self, provider, other, problems):
                 unmatched.add(s)
         if unmatched:
             # can't replace other with provider
-            problems.add(('cantreplace', provider, other,
-                          frozenset(unmatched)))
+            problems.add(('cantreplace', provider, other, frozenset(unmatched)))
             result = False
         else:
             # can replace other with provider
@@ -1233,8 +1228,7 @@ def find(self, requirement, meta_extras=None, prereleases=False):
             dist = odist = requirement
             logger.debug('passed %s as requirement', odist)
         else:
-            dist = odist = self.locator.locate(requirement,
-                                               prereleases=prereleases)
+            dist = odist = self.locator.locate(requirement, prereleases=prereleases)
             if dist is None:
                 raise DistlibException('Unable to locate %r' % requirement)
             logger.debug('located %s', odist)
@@ -1244,7 +1238,7 @@ def find(self, requirement, meta_extras=None, prereleases=False):
         install_dists = set([odist])
         while todo:
             dist = todo.pop()
-            name = dist.key     # case-insensitive
+            name = dist.key  # case-insensitive
             if name not in self.dists_by_name:
                 self.add_distribution(dist)
             else:
@@ -1281,8 +1275,7 @@ def find(self, requirement, meta_extras=None, prereleases=False):
                         providers.add(provider)
                         if r in ireqts and dist in install_dists:
                             install_dists.add(provider)
-                            logger.debug('Adding %s to install_dists',
-                                         provider.name_and_version)
+                            logger.debug('Adding %s to install_dists', provider.name_and_version)
                 for p in providers:
                     name = p.key
                     if name not in self.dists_by_name:
@@ -1297,7 +1290,6 @@ def find(self, requirement, meta_extras=None, prereleases=False):
         for dist in dists:
             dist.build_time_dependency = dist not in install_dists
             if dist.build_time_dependency:
-                logger.debug('%s is a build-time dependency only.',
-                             dist.name_and_version)
+                logger.debug('%s is a build-time dependency only.', dist.name_and_version)
         logger.debug('find done for %s', odist)
         return dists, problems
diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/markers.py b/venv/Lib/site-packages/pip/_vendor/distlib/markers.py
index 1514d46..3f5632b 100644
--- a/venv/Lib/site-packages/pip/_vendor/distlib/markers.py
+++ b/venv/Lib/site-packages/pip/_vendor/distlib/markers.py
@@ -23,8 +23,7 @@
 
 __all__ = ['interpret']
 
-_VERSION_PATTERN = re.compile(
-    r'((\d+(\.\d+)*\w*)|\'(\d+(\.\d+)*\w*)\'|\"(\d+(\.\d+)*\w*)\")')
+_VERSION_PATTERN = re.compile(r'((\d+(\.\d+)*\w*)|\'(\d+(\.\d+)*\w*)\'|\"(\d+(\.\d+)*\w*)\")')
 _VERSION_MARKERS = {'python_version', 'python_full_version'}
 
 
@@ -82,13 +81,12 @@ def evaluate(self, expr, context):
             elhs = expr['lhs']
             erhs = expr['rhs']
             if _is_literal(expr['lhs']) and _is_literal(expr['rhs']):
-                raise SyntaxError('invalid comparison: %s %s %s' %
-                                  (elhs, op, erhs))
+                raise SyntaxError('invalid comparison: %s %s %s' % (elhs, op, erhs))
 
             lhs = self.evaluate(elhs, context)
             rhs = self.evaluate(erhs, context)
-            if ((_is_version_marker(elhs) or _is_version_marker(erhs))
-                    and op in ('<', '<=', '>', '>=', '===', '==', '!=', '~=')):
+            if ((_is_version_marker(elhs) or _is_version_marker(erhs)) and
+                    op in ('<', '<=', '>', '>=', '===', '==', '!=', '~=')):
                 lhs = LV(lhs)
                 rhs = LV(rhs)
             elif _is_version_marker(elhs) and op in ('in', 'not in'):
@@ -111,8 +109,7 @@ def format_full_version(info):
         return version
 
     if hasattr(sys, 'implementation'):
-        implementation_version = format_full_version(
-            sys.implementation.version)
+        implementation_version = format_full_version(sys.implementation.version)
         implementation_name = sys.implementation.name
     else:
         implementation_version = '0'
@@ -156,11 +153,9 @@ def interpret(marker, execution_context=None):
     try:
         expr, rest = parse_marker(marker)
     except Exception as e:
-        raise SyntaxError('Unable to interpret marker syntax: %s: %s' %
-                          (marker, e))
+        raise SyntaxError('Unable to interpret marker syntax: %s: %s' % (marker, e))
     if rest and rest[0] != '#':
-        raise SyntaxError('unexpected trailing data in marker: %s: %s' %
-                          (marker, rest))
+        raise SyntaxError('unexpected trailing data in marker: %s: %s' % (marker, rest))
     context = dict(DEFAULT_CONTEXT)
     if execution_context:
         context.update(execution_context)
diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/metadata.py b/venv/Lib/site-packages/pip/_vendor/distlib/metadata.py
index 7189aee..ce9a34b 100644
--- a/venv/Lib/site-packages/pip/_vendor/distlib/metadata.py
+++ b/venv/Lib/site-packages/pip/_vendor/distlib/metadata.py
@@ -15,7 +15,6 @@
 import logging
 import re
 
-
 from . import DistlibException, __version__
 from .compat import StringIO, string_types, text_type
 from .markers import interpret
@@ -40,6 +39,7 @@ class MetadataUnrecognizedVersionError(DistlibException):
 class MetadataInvalidError(DistlibException):
     """A metadata value is invalid"""
 
+
 # public API of this module
 __all__ = ['Metadata', 'PKG_INFO_ENCODING', 'PKG_INFO_PREFERRED_VERSION']
 
@@ -52,53 +52,38 @@ class MetadataInvalidError(DistlibException):
 
 _LINE_PREFIX_1_2 = re.compile('\n       \\|')
 _LINE_PREFIX_PRE_1_2 = re.compile('\n        ')
-_241_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform',
-               'Summary', 'Description',
-               'Keywords', 'Home-page', 'Author', 'Author-email',
-               'License')
-
-_314_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform',
-               'Supported-Platform', 'Summary', 'Description',
-               'Keywords', 'Home-page', 'Author', 'Author-email',
-               'License', 'Classifier', 'Download-URL', 'Obsoletes',
+_241_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', 'Summary', 'Description', 'Keywords', 'Home-page',
+               'Author', 'Author-email', 'License')
+
+_314_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', 'Supported-Platform', 'Summary', 'Description',
+               'Keywords', 'Home-page', 'Author', 'Author-email', 'License', 'Classifier', 'Download-URL', 'Obsoletes',
                'Provides', 'Requires')
 
-_314_MARKERS = ('Obsoletes', 'Provides', 'Requires', 'Classifier',
-                'Download-URL')
+_314_MARKERS = ('Obsoletes', 'Provides', 'Requires', 'Classifier', 'Download-URL')
 
-_345_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform',
-               'Supported-Platform', 'Summary', 'Description',
-               'Keywords', 'Home-page', 'Author', 'Author-email',
-               'Maintainer', 'Maintainer-email', 'License',
-               'Classifier', 'Download-URL', 'Obsoletes-Dist',
-               'Project-URL', 'Provides-Dist', 'Requires-Dist',
+_345_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', 'Supported-Platform', 'Summary', 'Description',
+               'Keywords', 'Home-page', 'Author', 'Author-email', 'Maintainer', 'Maintainer-email', 'License',
+               'Classifier', 'Download-URL', 'Obsoletes-Dist', 'Project-URL', 'Provides-Dist', 'Requires-Dist',
                'Requires-Python', 'Requires-External')
 
-_345_MARKERS = ('Provides-Dist', 'Requires-Dist', 'Requires-Python',
-                'Obsoletes-Dist', 'Requires-External', 'Maintainer',
-                'Maintainer-email', 'Project-URL')
+_345_MARKERS = ('Provides-Dist', 'Requires-Dist', 'Requires-Python', 'Obsoletes-Dist', 'Requires-External',
+                'Maintainer', 'Maintainer-email', 'Project-URL')
 
-_426_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform',
-               'Supported-Platform', 'Summary', 'Description',
-               'Keywords', 'Home-page', 'Author', 'Author-email',
-               'Maintainer', 'Maintainer-email', 'License',
-               'Classifier', 'Download-URL', 'Obsoletes-Dist',
-               'Project-URL', 'Provides-Dist', 'Requires-Dist',
-               'Requires-Python', 'Requires-External', 'Private-Version',
-               'Obsoleted-By', 'Setup-Requires-Dist', 'Extension',
-               'Provides-Extra')
+_426_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', 'Supported-Platform', 'Summary', 'Description',
+               'Keywords', 'Home-page', 'Author', 'Author-email', 'Maintainer', 'Maintainer-email', 'License',
+               'Classifier', 'Download-URL', 'Obsoletes-Dist', 'Project-URL', 'Provides-Dist', 'Requires-Dist',
+               'Requires-Python', 'Requires-External', 'Private-Version', 'Obsoleted-By', 'Setup-Requires-Dist',
+               'Extension', 'Provides-Extra')
 
-_426_MARKERS = ('Private-Version', 'Provides-Extra', 'Obsoleted-By',
-                'Setup-Requires-Dist', 'Extension')
+_426_MARKERS = ('Private-Version', 'Provides-Extra', 'Obsoleted-By', 'Setup-Requires-Dist', 'Extension')
 
 # See issue #106: Sometimes 'Requires' and 'Provides' occur wrongly in
 # the metadata. Include them in the tuple literal below to allow them
 # (for now).
 # Ditto for Obsoletes - see issue #140.
-_566_FIELDS = _426_FIELDS + ('Description-Content-Type',
-                             'Requires', 'Provides', 'Obsoletes')
+_566_FIELDS = _426_FIELDS + ('Description-Content-Type', 'Requires', 'Provides', 'Obsoletes')
 
-_566_MARKERS = ('Description-Content-Type',)
+_566_MARKERS = ('Description-Content-Type', )
 
 _643_MARKERS = ('Dynamic', 'License-File')
 
@@ -135,6 +120,7 @@ def _version2fieldlist(version):
 
 def _best_version(fields):
     """Detect the best version depending on the fields used."""
+
     def _has_marker(keys, markers):
         return any(marker in keys for marker in markers)
 
@@ -163,12 +149,12 @@ def _has_marker(keys, markers):
             possible_versions.remove('2.2')
             logger.debug('Removed 2.2 due to %s', key)
         # if key not in _426_FIELDS and '2.0' in possible_versions:
-            # possible_versions.remove('2.0')
-            # logger.debug('Removed 2.0 due to %s', key)
+        # possible_versions.remove('2.0')
+        # logger.debug('Removed 2.0 due to %s', key)
 
     # possible_version contains qualified versions
     if len(possible_versions) == 1:
-        return possible_versions[0]   # found !
+        return possible_versions[0]  # found !
     elif len(possible_versions) == 0:
         logger.debug('Out of options - unknown metadata set: %s', fields)
         raise MetadataConflictError('Unknown metadata set')
@@ -199,28 +185,25 @@ def _has_marker(keys, markers):
     if is_2_1:
         return '2.1'
     # if is_2_2:
-        # return '2.2'
+    # return '2.2'
 
     return '2.2'
 
+
 # This follows the rules about transforming keys as described in
 # https://www.python.org/dev/peps/pep-0566/#id17
-_ATTR2FIELD = {
-    name.lower().replace("-", "_"): name for name in _ALL_FIELDS
-}
+_ATTR2FIELD = {name.lower().replace("-", "_"): name for name in _ALL_FIELDS}
 _FIELD2ATTR = {field: attr for attr, field in _ATTR2FIELD.items()}
 
 _PREDICATE_FIELDS = ('Requires-Dist', 'Obsoletes-Dist', 'Provides-Dist')
-_VERSIONS_FIELDS = ('Requires-Python',)
-_VERSION_FIELDS = ('Version',)
-_LISTFIELDS = ('Platform', 'Classifier', 'Obsoletes',
-               'Requires', 'Provides', 'Obsoletes-Dist',
-               'Provides-Dist', 'Requires-Dist', 'Requires-External',
-               'Project-URL', 'Supported-Platform', 'Setup-Requires-Dist',
+_VERSIONS_FIELDS = ('Requires-Python', )
+_VERSION_FIELDS = ('Version', )
+_LISTFIELDS = ('Platform', 'Classifier', 'Obsoletes', 'Requires', 'Provides', 'Obsoletes-Dist', 'Provides-Dist',
+               'Requires-Dist', 'Requires-External', 'Project-URL', 'Supported-Platform', 'Setup-Requires-Dist',
                'Provides-Extra', 'Extension', 'License-File')
-_LISTTUPLEFIELDS = ('Project-URL',)
+_LISTTUPLEFIELDS = ('Project-URL', )
 
-_ELEMENTSFIELD = ('Keywords',)
+_ELEMENTSFIELD = ('Keywords', )
 
 _UNICODEFIELDS = ('Author', 'Maintainer', 'Summary', 'Description')
 
@@ -252,10 +235,10 @@ class LegacyMetadata(object):
     - *mapping* is a dict-like object
     - *scheme* is a version scheme name
     """
+
     # TODO document the mapping API and UNKNOWN default key
 
-    def __init__(self, path=None, fileobj=None, mapping=None,
-                 scheme='default'):
+    def __init__(self, path=None, fileobj=None, mapping=None, scheme='default'):
         if [path, fileobj, mapping].count(None) < 2:
             raise TypeError('path, fileobj and mapping are exclusive')
         self._fields = {}
@@ -290,8 +273,7 @@ def __delitem__(self, name):
             raise KeyError(name)
 
     def __contains__(self, name):
-        return (name in self._fields or
-                self._convert_name(name) in self._fields)
+        return (name in self._fields or self._convert_name(name) in self._fields)
 
     def _convert_name(self, name):
         if name in _ALL_FIELDS:
@@ -319,12 +301,12 @@ def __getattr__(self, name):
     # Public API
     #
 
-#    dependencies = property(_get_dependencies, _set_dependencies)
-
     def get_fullname(self, filesafe=False):
-        """Return the distribution name with version.
+        """
+        Return the distribution name with version.
 
-        If filesafe is true, return a filename-escaped form."""
+        If filesafe is true, return a filename-escaped form.
+        """
         return _get_name_and_version(self['Name'], self['Version'], filesafe)
 
     def is_field(self, name):
@@ -415,6 +397,7 @@ def update(self, other=None, **kwargs):
         Keys that don't match a metadata field or that have an empty value are
         dropped.
         """
+
         def _set(key, value):
             if key in _ATTR2FIELD and value:
                 self.set(self._convert_name(key), value)
@@ -437,14 +420,12 @@ def set(self, name, value):
         """Control then set a metadata field."""
         name = self._convert_name(name)
 
-        if ((name in _ELEMENTSFIELD or name == 'Platform') and
-            not isinstance(value, (list, tuple))):
+        if ((name in _ELEMENTSFIELD or name == 'Platform') and not isinstance(value, (list, tuple))):
             if isinstance(value, string_types):
                 value = [v.strip() for v in value.split(',')]
             else:
                 value = []
-        elif (name in _LISTFIELDS and
-              not isinstance(value, (list, tuple))):
+        elif (name in _LISTFIELDS and not isinstance(value, (list, tuple))):
             if isinstance(value, string_types):
                 value = [value]
             else:
@@ -458,18 +439,14 @@ def set(self, name, value):
                 for v in value:
                     # check that the values are valid
                     if not scheme.is_valid_matcher(v.split(';')[0]):
-                        logger.warning(
-                            "'%s': '%s' is not valid (field '%s')",
-                            project_name, v, name)
+                        logger.warning("'%s': '%s' is not valid (field '%s')", project_name, v, name)
             # FIXME this rejects UNKNOWN, is that right?
             elif name in _VERSIONS_FIELDS and value is not None:
                 if not scheme.is_valid_constraint_list(value):
-                    logger.warning("'%s': '%s' is not a valid version (field '%s')",
-                                   project_name, value, name)
+                    logger.warning("'%s': '%s' is not a valid version (field '%s')", project_name, value, name)
             elif name in _VERSION_FIELDS and value is not None:
                 if not scheme.is_valid_version(value):
-                    logger.warning("'%s': '%s' is not a valid version (field '%s')",
-                                   project_name, value, name)
+                    logger.warning("'%s': '%s' is not a valid version (field '%s')", project_name, value, name)
 
         if name in _UNICODEFIELDS:
             if name == 'Description':
@@ -539,10 +516,8 @@ def are_valid_constraints(value):
             return True
 
         for fields, controller in ((_PREDICATE_FIELDS, are_valid_constraints),
-                                   (_VERSIONS_FIELDS,
-                                    scheme.is_valid_constraint_list),
-                                   (_VERSION_FIELDS,
-                                    scheme.is_valid_version)):
+                                   (_VERSIONS_FIELDS, scheme.is_valid_constraint_list), (_VERSION_FIELDS,
+                                                                                         scheme.is_valid_version)):
             for field in fields:
                 value = self.get(field, None)
                 if value is not None and not controller(value):
@@ -598,8 +573,7 @@ def items(self):
         return [(key, self[key]) for key in self.keys()]
 
     def __repr__(self):
-        return '<%s %s %s>' % (self.__class__.__name__, self.name,
-                               self.version)
+        return '<%s %s %s>' % (self.__class__.__name__, self.name, self.version)
 
 
 METADATA_FILENAME = 'pydist.json'
@@ -631,7 +605,7 @@ class Metadata(object):
     MANDATORY_KEYS = {
         'name': (),
         'version': (),
-        'summary': ('legacy',),
+        'summary': ('legacy', ),
     }
 
     INDEX_KEYS = ('name version license summary description author '
@@ -644,22 +618,21 @@ class Metadata(object):
 
     SYNTAX_VALIDATORS = {
         'metadata_version': (METADATA_VERSION_MATCHER, ()),
-        'name': (NAME_MATCHER, ('legacy',)),
-        'version': (VERSION_MATCHER, ('legacy',)),
-        'summary': (SUMMARY_MATCHER, ('legacy',)),
-        'dynamic': (FIELDNAME_MATCHER, ('legacy',)),
+        'name': (NAME_MATCHER, ('legacy', )),
+        'version': (VERSION_MATCHER, ('legacy', )),
+        'summary': (SUMMARY_MATCHER, ('legacy', )),
+        'dynamic': (FIELDNAME_MATCHER, ('legacy', )),
     }
 
     __slots__ = ('_legacy', '_data', 'scheme')
 
-    def __init__(self, path=None, fileobj=None, mapping=None,
-                 scheme='default'):
+    def __init__(self, path=None, fileobj=None, mapping=None, scheme='default'):
         if [path, fileobj, mapping].count(None) < 2:
             raise TypeError('path, fileobj and mapping are exclusive')
         self._legacy = None
         self._data = None
         self.scheme = scheme
-        #import pdb; pdb.set_trace()
+        # import pdb; pdb.set_trace()
         if mapping is not None:
             try:
                 self._validate_mapping(mapping, scheme)
@@ -693,8 +666,7 @@ def __init__(self, path=None, fileobj=None, mapping=None,
                     # The ValueError comes from the json.load - if that
                     # succeeds and we get a validation error, we want
                     # that to propagate
-                    self._legacy = LegacyMetadata(fileobj=StringIO(data),
-                                                  scheme=scheme)
+                    self._legacy = LegacyMetadata(fileobj=StringIO(data), scheme=scheme)
                     self.validate()
 
     common_keys = set(('name', 'version', 'license', 'keywords', 'summary'))
@@ -732,8 +704,7 @@ def __getattribute__(self, key):
                     result = self._legacy.get(lk)
             else:
                 value = None if maker is None else maker()
-                if key not in ('commands', 'exports', 'modules', 'namespaces',
-                               'classifiers'):
+                if key not in ('commands', 'exports', 'modules', 'namespaces', 'classifiers'):
                     result = self._data.get(key, value)
                 else:
                     # special cases for PEP 459
@@ -770,8 +741,7 @@ def _validate_value(self, key, value, scheme=None):
                 m = pattern.match(value)
                 if not m:
                     raise MetadataInvalidError("'%s' is an invalid value for "
-                                               "the '%s' property" % (value,
-                                                                    key))
+                                               "the '%s' property" % (value, key))
 
     def __setattr__(self, key, value):
         self._validate_value(key, value)
@@ -783,8 +753,7 @@ def __setattr__(self, key, value):
                 if lk is None:
                     raise NotImplementedError
                 self._legacy[lk] = value
-            elif key not in ('commands', 'exports', 'modules', 'namespaces',
-                             'classifiers'):
+            elif key not in ('commands', 'exports', 'modules', 'namespaces', 'classifiers'):
                 self._data[key] = value
             else:
                 # special cases for PEP 459
@@ -872,8 +841,7 @@ def get_requirements(self, reqts, extras=None, env=None):
                     # A recursive call, but it should terminate since 'test'
                     # has been removed from the extras
                     reqts = self._data.get('%s_requires' % key, [])
-                    result.extend(self.get_requirements(reqts, extras=extras,
-                                                        env=env))
+                    result.extend(self.get_requirements(reqts, extras=extras, env=env))
         return result
 
     @property
@@ -914,8 +882,7 @@ def validate(self):
         if self._legacy:
             missing, warnings = self._legacy.check(True)
             if missing or warnings:
-                logger.warning('Metadata: missing: %s, warnings: %s',
-                               missing, warnings)
+                logger.warning('Metadata: missing: %s, warnings: %s', missing, warnings)
         else:
             self._validate_mapping(self._data, self.scheme)
 
@@ -932,9 +899,8 @@ def _from_legacy(self):
             'metadata_version': self.METADATA_VERSION,
             'generator': self.GENERATOR,
         }
-        lmd = self._legacy.todict(True)     # skip missing ones
-        for k in ('name', 'version', 'license', 'summary', 'description',
-                  'classifier'):
+        lmd = self._legacy.todict(True)  # skip missing ones
+        for k in ('name', 'version', 'license', 'summary', 'description', 'classifier'):
             if k in lmd:
                 if k == 'classifier':
                     nk = 'classifiers'
@@ -945,14 +911,13 @@ def _from_legacy(self):
         if kw == ['']:
             kw = []
         result['keywords'] = kw
-        keys = (('requires_dist', 'run_requires'),
-                ('setup_requires_dist', 'build_requires'))
+        keys = (('requires_dist', 'run_requires'), ('setup_requires_dist', 'build_requires'))
         for ok, nk in keys:
             if ok in lmd and lmd[ok]:
                 result[nk] = [{'requires': lmd[ok]}]
         result['provides'] = self.provides
-        author = {}
-        maintainer = {}
+        # author = {}
+        # maintainer = {}
         return result
 
     LEGACY_MAPPING = {
@@ -969,6 +934,7 @@ def _from_legacy(self):
     }
 
     def _to_legacy(self):
+
         def process_entries(entries):
             reqts = set()
             for e in entries:
@@ -1037,12 +1003,10 @@ def write(self, path=None, fileobj=None, legacy=False, skip_unknown=True):
             else:
                 d = self._data
             if fileobj:
-                json.dump(d, fileobj, ensure_ascii=True, indent=2,
-                          sort_keys=True)
+                json.dump(d, fileobj, ensure_ascii=True, indent=2, sort_keys=True)
             else:
                 with codecs.open(path, 'w', 'utf-8') as f:
-                    json.dump(d, f, ensure_ascii=True, indent=2,
-                              sort_keys=True)
+                    json.dump(d, f, ensure_ascii=True, indent=2, sort_keys=True)
 
     def add_requirements(self, requirements):
         if self._legacy:
@@ -1055,7 +1019,7 @@ def add_requirements(self, requirements):
                     always = entry
                     break
             if always is None:
-                always = { 'requires': requirements }
+                always = {'requires': requirements}
                 run_requires.insert(0, always)
             else:
                 rset = set(always['requires']) | set(requirements)
@@ -1064,5 +1028,4 @@ def add_requirements(self, requirements):
     def __repr__(self):
         name = self.name or '(no name)'
         version = self.version or 'no version'
-        return '<%s %s %s (%s)>' % (self.__class__.__name__,
-                                    self.metadata_version, name, version)
+        return '<%s %s %s (%s)>' % (self.__class__.__name__, self.metadata_version, name, version)
diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/scripts.py b/venv/Lib/site-packages/pip/_vendor/distlib/scripts.py
index e16292b..b1fc705 100644
--- a/venv/Lib/site-packages/pip/_vendor/distlib/scripts.py
+++ b/venv/Lib/site-packages/pip/_vendor/distlib/scripts.py
@@ -15,8 +15,7 @@
 
 from .compat import sysconfig, detect_encoding, ZipFile
 from .resources import finder
-from .util import (FileOperator, get_export_entry, convert_path,
-                   get_executable, get_platform, in_venv)
+from .util import (FileOperator, get_export_entry, convert_path, get_executable, get_platform, in_venv)
 
 logger = logging.getLogger(__name__)
 
@@ -57,15 +56,16 @@
 # location where it was imported from. So we load everything into memory in
 # advance.
 
-# Issue 31: don't hardcode an absolute package name, but
-# determine it relative to the current package
-distlib_package = __name__.rsplit('.', 1)[0]
+if os.name == 'nt' or (os.name == 'java' and os._name == 'nt'):
+    # Issue 31: don't hardcode an absolute package name, but
+    # determine it relative to the current package
+    DISTLIB_PACKAGE = __name__.rsplit('.', 1)[0]
 
-WRAPPERS = {
-    r.name: r.bytes
-    for r in finder(distlib_package).iterator("")
-    if r.name.endswith(".exe")
-}
+    WRAPPERS = {
+        r.name: r.bytes
+        for r in finder(DISTLIB_PACKAGE).iterator("")
+        if r.name.endswith(".exe")
+    }
 
 
 def enquote_executable(executable):
@@ -97,25 +97,18 @@ class ScriptMaker(object):
 
     executable = None  # for shebangs
 
-    def __init__(self,
-                 source_dir,
-                 target_dir,
-                 add_launchers=True,
-                 dry_run=False,
-                 fileop=None):
+    def __init__(self, source_dir, target_dir, add_launchers=True, dry_run=False, fileop=None):
         self.source_dir = source_dir
         self.target_dir = target_dir
         self.add_launchers = add_launchers
         self.force = False
         self.clobber = False
         # It only makes sense to set mode bits on POSIX.
-        self.set_mode = (os.name == 'posix') or (os.name == 'java'
-                                                 and os._name == 'posix')
+        self.set_mode = (os.name == 'posix') or (os.name == 'java' and os._name == 'posix')
         self.variants = set(('', 'X.Y'))
         self._fileop = fileop or FileOperator(dry_run)
 
-        self._is_nt = os.name == 'nt' or (os.name == 'java'
-                                          and os._name == 'nt')
+        self._is_nt = os.name == 'nt' or (os.name == 'java' and os._name == 'nt')
         self.version_info = sys.version_info
 
     def _get_alternate_executable(self, executable, options):
@@ -164,6 +157,12 @@ def _build_shebang(self, executable, post_interp):
         """
         if os.name != 'posix':
             simple_shebang = True
+        elif getattr(sys, "cross_compiling", False):
+            # In a cross-compiling environment, the shebang will likely be a
+            # script; this *must* be invoked with the "safe" version of the
+            # shebang, or else using os.exec() to run the entry script will
+            # fail, raising "OSError 8 [Errno 8] Exec format error".
+            simple_shebang = False
         else:
             # Add 3 for '#!' prefix and newline suffix.
             shebang_length = len(executable) + len(post_interp) + 3
@@ -171,15 +170,14 @@ def _build_shebang(self, executable, post_interp):
                 max_shebang_length = 512
             else:
                 max_shebang_length = 127
-            simple_shebang = ((b' ' not in executable)
-                              and (shebang_length <= max_shebang_length))
+            simple_shebang = ((b' ' not in executable) and (shebang_length <= max_shebang_length))
 
         if simple_shebang:
             result = b'#!' + executable + post_interp + b'\n'
         else:
             result = b'#!/bin/sh\n'
             result += b"'''exec' " + executable + post_interp + b' "$0" "$@"\n'
-            result += b"' '''"
+            result += b"' '''\n"
         return result
 
     def _get_shebang(self, encoding, post_interp=b'', options=None):
@@ -190,21 +188,17 @@ def _get_shebang(self, encoding, post_interp=b'', options=None):
         elif not sysconfig.is_python_build():
             executable = get_executable()
         elif in_venv():  # pragma: no cover
-            executable = os.path.join(
-                sysconfig.get_path('scripts'),
-                'python%s' % sysconfig.get_config_var('EXE'))
+            executable = os.path.join(sysconfig.get_path('scripts'), 'python%s' % sysconfig.get_config_var('EXE'))
         else:  # pragma: no cover
             if os.name == 'nt':
                 # for Python builds from source on Windows, no Python executables with
                 # a version suffix are created, so we use python.exe
-                executable = os.path.join(
-                    sysconfig.get_config_var('BINDIR'),
-                    'python%s' % (sysconfig.get_config_var('EXE')))
+                executable = os.path.join(sysconfig.get_config_var('BINDIR'),
+                                          'python%s' % (sysconfig.get_config_var('EXE')))
             else:
                 executable = os.path.join(
                     sysconfig.get_config_var('BINDIR'),
-                    'python%s%s' % (sysconfig.get_config_var('VERSION'),
-                                    sysconfig.get_config_var('EXE')))
+                    'python%s%s' % (sysconfig.get_config_var('VERSION'), sysconfig.get_config_var('EXE')))
         if options:
             executable = self._get_alternate_executable(executable, options)
 
@@ -228,8 +222,8 @@ def _get_shebang(self, encoding, post_interp=b'', options=None):
         # check that the shebang is decodable using utf-8.
         executable = executable.encode('utf-8')
         # in case of IronPython, play safe and enable frames support
-        if (sys.platform == 'cli' and '-X:Frames' not in post_interp
-                and '-X:FullFrames' not in post_interp):  # pragma: no cover
+        if (sys.platform == 'cli' and '-X:Frames' not in post_interp and
+                '-X:FullFrames' not in post_interp):  # pragma: no cover
             post_interp += b' -X:Frames'
         shebang = self._build_shebang(executable, post_interp)
         # Python parser starts to read a script using UTF-8 until
@@ -240,8 +234,7 @@ def _get_shebang(self, encoding, post_interp=b'', options=None):
         try:
             shebang.decode('utf-8')
         except UnicodeDecodeError:  # pragma: no cover
-            raise ValueError('The shebang (%r) is not decodable from utf-8' %
-                             shebang)
+            raise ValueError('The shebang (%r) is not decodable from utf-8' % shebang)
         # If the script is encoded to a custom encoding (use a
         # #coding:xxx cookie), the shebang has to be decodable from
         # the script encoding too.
@@ -250,15 +243,12 @@ def _get_shebang(self, encoding, post_interp=b'', options=None):
                 shebang.decode(encoding)
             except UnicodeDecodeError:  # pragma: no cover
                 raise ValueError('The shebang (%r) is not decodable '
-                                 'from the script encoding (%r)' %
-                                 (shebang, encoding))
+                                 'from the script encoding (%r)' % (shebang, encoding))
         return shebang
 
     def _get_script_text(self, entry):
         return self.script_template % dict(
-            module=entry.prefix,
-            import_name=entry.suffix.split('.')[0],
-            func=entry.suffix)
+            module=entry.prefix, import_name=entry.suffix.split('.')[0], func=entry.suffix)
 
     manifest = _DEFAULT_MANIFEST
 
@@ -268,9 +258,6 @@ def get_manifest(self, exename):
 
     def _write_script(self, names, shebang, script_bytes, filenames, ext):
         use_launcher = self.add_launchers and self._is_nt
-        linesep = os.linesep.encode('utf-8')
-        if not shebang.endswith(linesep):
-            shebang += linesep
         if not use_launcher:
             script_bytes = shebang + script_bytes
         else:  # pragma: no cover
@@ -283,8 +270,7 @@ def _write_script(self, names, shebang, script_bytes, filenames, ext):
                 source_date_epoch = os.environ.get('SOURCE_DATE_EPOCH')
                 if source_date_epoch:
                     date_time = time.gmtime(int(source_date_epoch))[:6]
-                    zinfo = ZipInfo(filename='__main__.py',
-                                    date_time=date_time)
+                    zinfo = ZipInfo(filename='__main__.py', date_time=date_time)
                     zf.writestr(zinfo, script_bytes)
                 else:
                     zf.writestr('__main__.py', script_bytes)
@@ -315,8 +301,7 @@ def _write_script(self, names, shebang, script_bytes, filenames, ext):
                     except Exception:
                         pass  # still in use - ignore error
             else:
-                if self._is_nt and not outname.endswith(
-                        '.' + ext):  # pragma: no cover
+                if self._is_nt and not outname.endswith('.' + ext):  # pragma: no cover
                     outname = '%s.%s' % (outname, ext)
                 if os.path.exists(outname) and not self.clobber:
                     logger.warning('Skipping existing file %s', outname)
@@ -335,9 +320,7 @@ def get_script_filenames(self, name):
         if 'X' in self.variants:
             result.add('%s%s' % (name, self.version_info[0]))
         if 'X.Y' in self.variants:
-            result.add('%s%s%s.%s' %
-                       (name, self.variant_separator, self.version_info[0],
-                        self.version_info[1]))
+            result.add('%s%s%s.%s' % (name, self.variant_separator, self.version_info[0], self.version_info[1]))
         return result
 
     def _make_script(self, entry, filenames, options=None):
@@ -392,8 +375,7 @@ def _copy_script(self, script, filenames):
                 self._fileop.set_executable_mode([outname])
             filenames.append(outname)
         else:
-            logger.info('copying and adjusting %s -> %s', script,
-                        self.target_dir)
+            logger.info('copying and adjusting %s -> %s', script, self.target_dir)
             if not self._fileop.dry_run:
                 encoding, lines = detect_encoding(f.readline)
                 f.seek(0)
@@ -415,8 +397,7 @@ def dry_run(self):
     def dry_run(self, value):
         self._fileop.dry_run = value
 
-    if os.name == 'nt' or (os.name == 'java'
-                           and os._name == 'nt'):  # pragma: no cover
+    if os.name == 'nt' or (os.name == 'java' and os._name == 'nt'):  # pragma: no cover
         # Executable launcher support.
         # Launchers are from https://bitbucket.org/vinay.sajip/simple_launcher/
 
@@ -429,7 +410,7 @@ def _get_launcher(self, kind):
             name = '%s%s%s.exe' % (kind, bits, platform_suffix)
             if name not in WRAPPERS:
                 msg = ('Unable to find resource %s in package %s' %
-                       (name, distlib_package))
+                       (name, DISTLIB_PACKAGE))
                 raise ValueError(msg)
             return WRAPPERS[name]
 
diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/util.py b/venv/Lib/site-packages/pip/_vendor/distlib/util.py
index ba58858..0d5bd7a 100644
--- a/venv/Lib/site-packages/pip/_vendor/distlib/util.py
+++ b/venv/Lib/site-packages/pip/_vendor/distlib/util.py
@@ -31,11 +31,9 @@
 import time
 
 from . import DistlibException
-from .compat import (string_types, text_type, shutil, raw_input, StringIO,
-                     cache_from_source, urlopen, urljoin, httplib, xmlrpclib,
-                     HTTPHandler, BaseConfigurator, valid_ident,
-                     Container, configparser, URLError, ZipFile, fsdecode,
-                     unquote, urlparse)
+from .compat import (string_types, text_type, shutil, raw_input, StringIO, cache_from_source, urlopen, urljoin, httplib,
+                     xmlrpclib, HTTPHandler, BaseConfigurator, valid_ident, Container, configparser, URLError, ZipFile,
+                     fsdecode, unquote, urlparse)
 
 logger = logging.getLogger(__name__)
 
@@ -88,8 +86,7 @@ def marker_var(remaining):
                 else:
                     m = STRING_CHUNK.match(remaining)
                     if not m:
-                        raise SyntaxError('error in string literal: %s' %
-                                          remaining)
+                        raise SyntaxError('error in string literal: %s' % remaining)
                     parts.append(m.groups()[0])
                     remaining = remaining[m.end():]
             else:
@@ -210,8 +207,7 @@ def get_versions(ver_remaining):
                         ver_remaining = ver_remaining[m.end():]
                         m = VERSION_IDENTIFIER.match(ver_remaining)
                         if not m:
-                            raise SyntaxError('invalid version: %s' %
-                                              ver_remaining)
+                            raise SyntaxError('invalid version: %s' % ver_remaining)
                         v = m.groups()[0]
                         versions.append((op, v))
                         ver_remaining = ver_remaining[m.end():]
@@ -224,8 +220,7 @@ def get_versions(ver_remaining):
                             break
                         m = COMPARE_OP.match(ver_remaining)
                         if not m:
-                            raise SyntaxError('invalid constraint: %s' %
-                                              ver_remaining)
+                            raise SyntaxError('invalid constraint: %s' % ver_remaining)
                     if not versions:
                         versions = None
                 return versions, ver_remaining
@@ -235,8 +230,7 @@ def get_versions(ver_remaining):
             else:
                 i = remaining.find(')', 1)
                 if i < 0:
-                    raise SyntaxError('unterminated parenthesis: %s' %
-                                      remaining)
+                    raise SyntaxError('unterminated parenthesis: %s' % remaining)
                 s = remaining[1:i]
                 remaining = remaining[i + 1:].lstrip()
                 # As a special diversion from PEP 508, allow a version number
@@ -267,14 +261,8 @@ def get_versions(ver_remaining):
     if not versions:
         rs = distname
     else:
-        rs = '%s %s' % (distname, ', '.join(
-            ['%s %s' % con for con in versions]))
-    return Container(name=distname,
-                     extras=extras,
-                     constraints=versions,
-                     marker=mark_expr,
-                     url=uri,
-                     requirement=rs)
+        rs = '%s %s' % (distname, ', '.join(['%s %s' % con for con in versions]))
+    return Container(name=distname, extras=extras, constraints=versions, marker=mark_expr, url=uri, requirement=rs)
 
 
 def get_resources_dests(resources_root, rules):
@@ -524,8 +512,7 @@ def newer(self, source, target):
         second will have the same "age".
         """
         if not os.path.exists(source):
-            raise DistlibException("file '%r' does not exist" %
-                                   os.path.abspath(source))
+            raise DistlibException("file '%r' does not exist" % os.path.abspath(source))
         if not os.path.exists(target):
             return True
 
@@ -601,12 +588,7 @@ def ensure_dir(self, path):
             if self.record:
                 self.dirs_created.add(path)
 
-    def byte_compile(self,
-                     path,
-                     optimize=False,
-                     force=False,
-                     prefix=None,
-                     hashed_invalidation=False):
+    def byte_compile(self, path, optimize=False, force=False, prefix=None, hashed_invalidation=False):
         dpath = cache_from_source(path, not optimize)
         logger.info('Byte-compiling %s to %s', path, dpath)
         if not self.dry_run:
@@ -617,12 +599,11 @@ def byte_compile(self,
                     assert path.startswith(prefix)
                     diagpath = path[len(prefix):]
             compile_kwargs = {}
-            if hashed_invalidation and hasattr(py_compile,
-                                               'PycInvalidationMode'):
-                compile_kwargs[
-                    'invalidation_mode'] = py_compile.PycInvalidationMode.CHECKED_HASH
-            py_compile.compile(path, dpath, diagpath, True,
-                               **compile_kwargs)  # raise error
+            if hashed_invalidation and hasattr(py_compile, 'PycInvalidationMode'):
+                if not isinstance(hashed_invalidation, py_compile.PycInvalidationMode):
+                    hashed_invalidation = py_compile.PycInvalidationMode.CHECKED_HASH
+                compile_kwargs['invalidation_mode'] = hashed_invalidation
+            py_compile.compile(path, dpath, diagpath, True, **compile_kwargs)  # raise error
         self.record_as_written(dpath)
         return dpath
 
@@ -716,16 +697,14 @@ def value(self):
         return resolve(self.prefix, self.suffix)
 
     def __repr__(self):  # pragma: no cover
-        return '' % (self.name, self.prefix,
-                                                self.suffix, self.flags)
+        return '' % (self.name, self.prefix, self.suffix, self.flags)
 
     def __eq__(self, other):
         if not isinstance(other, ExportEntry):
             result = False
         else:
-            result = (self.name == other.name and self.prefix == other.prefix
-                      and self.suffix == other.suffix
-                      and self.flags == other.flags)
+            result = (self.name == other.name and self.prefix == other.prefix and self.suffix == other.suffix and
+                      self.flags == other.flags)
         return result
 
     __hash__ = object.__hash__
@@ -810,7 +789,7 @@ def get_cache_base(suffix=None):
     return os.path.join(result, suffix)
 
 
-def path_to_cache_dir(path):
+def path_to_cache_dir(path, use_abspath=True):
     """
     Convert an absolute path to a directory name for use in a cache.
 
@@ -820,7 +799,7 @@ def path_to_cache_dir(path):
     #. Any occurrence of ``os.sep`` is replaced with ``'--'``.
     #. ``'.cache'`` is appended.
     """
-    d, p = os.path.splitdrive(os.path.abspath(path))
+    d, p = os.path.splitdrive(os.path.abspath(path) if use_abspath else path)
     if d:
         d = d.replace(':', '---')
     p = p.replace(os.sep, '--')
@@ -865,9 +844,8 @@ def is_string_sequence(seq):
     return result
 
 
-PROJECT_NAME_AND_VERSION = re.compile(
-    '([a-z0-9_]+([.-][a-z_][a-z0-9_]*)*)-'
-    '([a-z0-9_.+-]+)', re.I)
+PROJECT_NAME_AND_VERSION = re.compile('([a-z0-9_]+([.-][a-z_][a-z0-9_]*)*)-'
+                                      '([a-z0-9_.+-]+)', re.I)
 PYTHON_VERSION = re.compile(r'-py(\d\.?\d?)')
 
 
@@ -1003,11 +981,11 @@ def __init__(self, base):
             logger.warning('Directory \'%s\' is not private', base)
         self.base = os.path.abspath(os.path.normpath(base))
 
-    def prefix_to_dir(self, prefix):
+    def prefix_to_dir(self, prefix, use_abspath=True):
         """
         Converts a resource prefix to a directory name in the cache.
         """
-        return path_to_cache_dir(prefix)
+        return path_to_cache_dir(prefix, use_abspath=use_abspath)
 
     def clear(self):
         """
@@ -1092,8 +1070,7 @@ def publish(self, event, *args, **kwargs):
                 logger.exception('Exception during event publication')
                 value = None
             result.append(value)
-        logger.debug('publish %s: args = %s, kwargs = %s, result = %s', event,
-                     args, kwargs, result)
+        logger.debug('publish %s: args = %s, kwargs = %s, result = %s', event, args, kwargs, result)
         return result
 
 
@@ -1145,8 +1122,7 @@ def remove(self, pred, succ):
             raise ValueError('%r not a successor of %r' % (succ, pred))
 
     def is_step(self, step):
-        return (step in self._preds or step in self._succs
-                or step in self._nodes)
+        return (step in self._preds or step in self._succs or step in self._nodes)
 
     def get_steps(self, final):
         if not self.is_step(final):
@@ -1242,8 +1218,7 @@ def dot(self):
 # Unarchiving functionality for zip, tar, tgz, tbz, whl
 #
 
-ARCHIVE_EXTENSIONS = ('.tar.gz', '.tar.bz2', '.tar', '.zip', '.tgz', '.tbz',
-                      '.whl')
+ARCHIVE_EXTENSIONS = ('.tar.gz', '.tar.bz2', '.tar', '.zip', '.tgz', '.tbz', '.whl')
 
 
 def unarchive(archive_filename, dest_dir, format=None, check=True):
@@ -1474,8 +1449,7 @@ def _iglob(path_glob):
 
 
 if ssl:
-    from .compat import (HTTPSHandler as BaseHTTPSHandler, match_hostname,
-                         CertificateError)
+    from .compat import (HTTPSHandler as BaseHTTPSHandler, match_hostname, CertificateError)
 
     #
     # HTTPSConnection which verifies certificates/matches domains
@@ -1487,8 +1461,7 @@ class HTTPSConnection(httplib.HTTPSConnection):
 
         # noinspection PyPropertyAccess
         def connect(self):
-            sock = socket.create_connection((self.host, self.port),
-                                            self.timeout)
+            sock = socket.create_connection((self.host, self.port), self.timeout)
             if getattr(self, '_tunnel_host', False):
                 self.sock = sock
                 self._tunnel()
@@ -1543,9 +1516,8 @@ def https_open(self, req):
                 return self.do_open(self._conn_maker, req)
             except URLError as e:
                 if 'certificate verify failed' in str(e.reason):
-                    raise CertificateError(
-                        'Unable to verify server certificate '
-                        'for %s' % req.host)
+                    raise CertificateError('Unable to verify server certificate '
+                                           'for %s' % req.host)
                 else:
                     raise
 
@@ -1561,9 +1533,8 @@ def https_open(self, req):
     class HTTPSOnlyHandler(HTTPSHandler, HTTPHandler):
 
         def http_open(self, req):
-            raise URLError(
-                'Unexpected HTTP request on what should be a secure '
-                'connection: %s' % req)
+            raise URLError('Unexpected HTTP request on what should be a secure '
+                           'connection: %s' % req)
 
 
 #
@@ -1598,8 +1569,7 @@ def make_connection(self, host):
             kwargs['timeout'] = self.timeout
             if not self._connection or host != self._connection[0]:
                 self._extra_headers = eh
-                self._connection = host, httplib.HTTPSConnection(
-                    h, None, **kwargs)
+                self._connection = host, httplib.HTTPSConnection(h, None, **kwargs)
             return self._connection[1]
 
 
@@ -1789,10 +1759,7 @@ def reader(self, stream, context):
         stream.close()
 
     def run_command(self, cmd, **kwargs):
-        p = subprocess.Popen(cmd,
-                             stdout=subprocess.PIPE,
-                             stderr=subprocess.PIPE,
-                             **kwargs)
+        p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)
         t1 = threading.Thread(target=self.reader, args=(p.stdout, 'stdout'))
         t1.start()
         t2 = threading.Thread(target=self.reader, args=(p.stderr, 'stderr'))
@@ -1847,10 +1814,7 @@ def read(self):
             if 'distutils' in sections:
                 # let's get the list of servers
                 index_servers = config.get('distutils', 'index-servers')
-                _servers = [
-                    server.strip() for server in index_servers.split('\n')
-                    if server.strip() != ''
-                ]
+                _servers = [server.strip() for server in index_servers.split('\n') if server.strip() != '']
                 if _servers == []:
                     # nothing set, let's try to get the default pypi
                     if 'pypi' in sections:
@@ -1861,9 +1825,7 @@ def read(self):
                         result['username'] = config.get(server, 'username')
 
                         # optional params
-                        for key, default in (('repository',
-                                              self.DEFAULT_REPOSITORY),
-                                             ('realm', self.DEFAULT_REALM),
+                        for key, default in (('repository', self.DEFAULT_REPOSITORY), ('realm', self.DEFAULT_REALM),
                                              ('password', None)):
                             if config.has_option(server, key):
                                 result[key] = config.get(server, key)
@@ -1873,11 +1835,9 @@ def read(self):
                         # work around people having "repository" for the "pypi"
                         # section of their config set to the HTTP (rather than
                         # HTTPS) URL
-                        if (server == 'pypi' and repository
-                                in (self.DEFAULT_REPOSITORY, 'pypi')):
+                        if (server == 'pypi' and repository in (self.DEFAULT_REPOSITORY, 'pypi')):
                             result['repository'] = self.DEFAULT_REPOSITORY
-                        elif (result['server'] != repository
-                              and result['repository'] != repository):
+                        elif (result['server'] != repository and result['repository'] != repository):
                             result = {}
             elif 'server-login' in sections:
                 # old format
@@ -2003,8 +1963,7 @@ def get_host_platform():
             from distutils import sysconfig
         except ImportError:
             import sysconfig
-        osname, release, machine = _osx_support.get_platform_osx(
-            sysconfig.get_config_vars(), osname, release, machine)
+        osname, release, machine = _osx_support.get_platform_osx(sysconfig.get_config_vars(), osname, release, machine)
 
     return '%s-%s-%s' % (osname, release, machine)
 
diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/version.py b/venv/Lib/site-packages/pip/_vendor/distlib/version.py
index 14171ac..d70a96e 100644
--- a/venv/Lib/site-packages/pip/_vendor/distlib/version.py
+++ b/venv/Lib/site-packages/pip/_vendor/distlib/version.py
@@ -619,8 +619,7 @@ def parse(self, s):
     def is_prerelease(self):
         result = False
         for x in self._parts:
-            if (isinstance(x, string_types) and x.startswith('*') and
-                    x < '*final'):
+            if (isinstance(x, string_types) and x.startswith('*') and x < '*final'):
                 result = True
                 break
         return result
diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/wheel.py b/venv/Lib/site-packages/pip/_vendor/distlib/wheel.py
index 4a5a30e..62ab10f 100644
--- a/venv/Lib/site-packages/pip/_vendor/distlib/wheel.py
+++ b/venv/Lib/site-packages/pip/_vendor/distlib/wheel.py
@@ -25,9 +25,8 @@
 from .compat import sysconfig, ZipFile, fsdecode, text_type, filter
 from .database import InstalledDistribution
 from .metadata import Metadata, WHEEL_METADATA_FILENAME, LEGACY_METADATA_FILENAME
-from .util import (FileOperator, convert_path, CSVReader, CSVWriter, Cache,
-                   cached_property, get_cache_base, read_exports, tempdir,
-                   get_platform)
+from .util import (FileOperator, convert_path, CSVReader, CSVWriter, Cache, cached_property, get_cache_base,
+                   read_exports, tempdir, get_platform)
 from .version import NormalizedVersion, UnsupportedVersionError
 
 logger = logging.getLogger(__name__)
@@ -88,8 +87,7 @@ def _derive_abi():
 \.whl$
 ''', re.IGNORECASE | re.VERBOSE)
 
-NAME_VERSION_RE = re.compile(
-    r'''
+NAME_VERSION_RE = re.compile(r'''
 (?P[^-]+)
 -(?P\d+[^-]*)
 (-(?P\d+[^-]*))?$
@@ -235,8 +233,7 @@ def filename(self):
         arch = '.'.join(self.arch)
         # replace - with _ as a local version separator
         version = self.version.replace('-', '_')
-        return '%s-%s%s-%s-%s-%s.whl' % (self.name, version, buildver, pyver,
-                                         abi, arch)
+        return '%s-%s%s-%s-%s-%s.whl' % (self.name, version, buildver, pyver, abi, arch)
 
     @property
     def exists(self):
@@ -334,8 +331,7 @@ def get_hash(self, data, hash_kind=None):
         try:
             hasher = getattr(hashlib, hash_kind)
         except AttributeError:
-            raise DistlibException('Unsupported hash algorithm: %r' %
-                                   hash_kind)
+            raise DistlibException('Unsupported hash algorithm: %r' % hash_kind)
         result = hasher(data).digest()
         result = base64.urlsafe_b64encode(result).rstrip(b'=').decode('ascii')
         return hash_kind, result
@@ -513,7 +509,7 @@ def install(self, paths, maker, **kwargs):
         installed, and the headers, scripts, data and dist-info metadata are
         not written. If kwarg ``bytecode_hashed_invalidation`` is True, written
         bytecode will try to use file-hash based invalidation (PEP-552) on
-        supported interpreter versions (CPython 2.7+).
+        supported interpreter versions (CPython 3.7+).
 
         The return value is a :class:`InstalledDistribution` instance unless
         ``options.lib_only`` is True, in which case the return value is ``None``.
@@ -522,8 +518,7 @@ def install(self, paths, maker, **kwargs):
         dry_run = maker.dry_run
         warner = kwargs.get('warner')
         lib_only = kwargs.get('lib_only', False)
-        bc_hashed_invalidation = kwargs.get('bytecode_hashed_invalidation',
-                                            False)
+        bc_hashed_invalidation = kwargs.get('bytecode_hashed_invalidation', False)
 
         pathname = os.path.join(self.dirname, self.filename)
         name_ver = '%s-%s' % (self.name, self.version)
@@ -602,8 +597,7 @@ def install(self, paths, maker, **kwargs):
                     if lib_only and u_arcname.startswith((info_pfx, data_pfx)):
                         logger.debug('lib_only: skipping %s', u_arcname)
                         continue
-                    is_script = (u_arcname.startswith(script_pfx)
-                                 and not u_arcname.endswith('.exe'))
+                    is_script = (u_arcname.startswith(script_pfx) and not u_arcname.endswith('.exe'))
 
                     if u_arcname.startswith(data_pfx):
                         _, where, rp = u_arcname.split('/', 2)
@@ -622,8 +616,7 @@ def install(self, paths, maker, **kwargs):
                         # So ... manually preserve permission bits as given in zinfo
                         if os.name == 'posix':
                             # just set the normal permission bits
-                            os.chmod(outfile,
-                                     (zinfo.external_attr >> 16) & 0x1FF)
+                            os.chmod(outfile, (zinfo.external_attr >> 16) & 0x1FF)
                         outfiles.append(outfile)
                         # Double check the digest of the written file
                         if not dry_run and row[1]:
@@ -636,15 +629,12 @@ def install(self, paths, maker, **kwargs):
                                                            '%s' % outfile)
                         if bc and outfile.endswith('.py'):
                             try:
-                                pyc = fileop.byte_compile(
-                                    outfile,
-                                    hashed_invalidation=bc_hashed_invalidation)
+                                pyc = fileop.byte_compile(outfile, hashed_invalidation=bc_hashed_invalidation)
                                 outfiles.append(pyc)
                             except Exception:
                                 # Don't give up if byte-compilation fails,
                                 # but log it and perhaps warn the user
-                                logger.warning('Byte-compilation failed',
-                                               exc_info=True)
+                                logger.warning('Byte-compilation failed', exc_info=True)
                     else:
                         fn = os.path.basename(convert_path(arcname))
                         workname = os.path.join(workdir, fn)
@@ -732,8 +722,7 @@ def install(self, paths, maker, **kwargs):
                         outfiles.append(p)
 
                     # Write RECORD
-                    dist.write_installed_files(outfiles, paths['prefix'],
-                                               dry_run)
+                    dist.write_installed_files(outfiles, paths['prefix'], dry_run)
                 return dist
             except Exception:  # pragma: no cover
                 logger.exception('installation failed.')
@@ -746,8 +735,7 @@ def _get_dylib_cache(self):
         global cache
         if cache is None:
             # Use native string to avoid issues on 2.x: see Python #20140.
-            base = os.path.join(get_cache_base(), str('dylib-cache'),
-                                '%s.%s' % sys.version_info[:2])
+            base = os.path.join(get_cache_base(), str('dylib-cache'), '%s.%s' % sys.version_info[:2])
             cache = Cache(base)
         return cache
 
@@ -764,7 +752,7 @@ def _get_extensions(self):
                     wf = wrapper(bf)
                     extensions = json.load(wf)
                     cache = self._get_dylib_cache()
-                    prefix = cache.prefix_to_dir(pathname)
+                    prefix = cache.prefix_to_dir(self.filename, use_abspath=False)
                     cache_base = os.path.join(cache.base, prefix)
                     if not os.path.isdir(cache_base):
                         os.makedirs(cache_base)
@@ -774,8 +762,7 @@ def _get_extensions(self):
                             extract = True
                         else:
                             file_time = os.stat(dest).st_mtime
-                            file_time = datetime.datetime.fromtimestamp(
-                                file_time)
+                            file_time = datetime.datetime.fromtimestamp(file_time)
                             info = zf.getinfo(relpath)
                             wheel_time = datetime.datetime(*info.date_time)
                             extract = wheel_time > file_time
@@ -924,12 +911,10 @@ def update_version(version, path):
                 else:
                     parts = [int(s) for s in version[i + 1:].split('.')]
                     parts[-1] += 1
-                    updated = '%s+%s' % (version[:i], '.'.join(
-                        str(i) for i in parts))
+                    updated = '%s+%s' % (version[:i], '.'.join(str(i) for i in parts))
             except UnsupportedVersionError:
-                logger.debug(
-                    'Cannot update non-compliant (PEP-440) '
-                    'version %r', version)
+                logger.debug('Cannot update non-compliant (PEP-440) '
+                             'version %r', version)
             if updated:
                 md = Metadata(path=path)
                 md.version = updated
@@ -971,14 +956,11 @@ def update_version(version, path):
                     update_version(current_version, path)
                 # Decide where the new wheel goes.
                 if dest_dir is None:
-                    fd, newpath = tempfile.mkstemp(suffix='.whl',
-                                                   prefix='wheel-update-',
-                                                   dir=workdir)
+                    fd, newpath = tempfile.mkstemp(suffix='.whl', prefix='wheel-update-', dir=workdir)
                     os.close(fd)
                 else:
                     if not os.path.isdir(dest_dir):
-                        raise DistlibException('Not a directory: %r' %
-                                               dest_dir)
+                        raise DistlibException('Not a directory: %r' % dest_dir)
                     newpath = os.path.join(dest_dir, self.filename)
                 archive_paths = list(path_map.items())
                 distinfo = os.path.join(workdir, info_dir)
@@ -1005,11 +987,20 @@ def compatible_tags():
     """
     Return (pyver, abi, arch) tuples compatible with this Python.
     """
-    versions = [VER_SUFFIX]
-    major = VER_SUFFIX[0]
-    for minor in range(sys.version_info[1] - 1, -1, -1):
-        versions.append(''.join([major, str(minor)]))
+    class _Version:
+        def __init__(self, major, minor):
+            self.major = major
+            self.major_minor = (major, minor)
+            self.string = ''.join((str(major), str(minor)))
+
+        def __str__(self):
+            return self.string
+
 
+    versions = [
+        _Version(sys.version_info.major, minor_version)
+        for minor_version in range(sys.version_info.minor, -1, -1)
+    ]
     abis = []
     for suffix in _get_suffixes():
         if suffix.startswith('.abi'):
@@ -1045,35 +1036,45 @@ def compatible_tags():
                 minor -= 1
 
     # Most specific - our Python version, ABI and arch
-    for abi in abis:
-        for arch in arches:
-            result.append((''.join((IMP_PREFIX, versions[0])), abi, arch))
-            # manylinux
-            if abi != 'none' and sys.platform.startswith('linux'):
-                arch = arch.replace('linux_', '')
-                parts = _get_glibc_version()
-                if len(parts) == 2:
-                    if parts >= (2, 5):
-                        result.append((''.join((IMP_PREFIX, versions[0])), abi,
-                                       'manylinux1_%s' % arch))
-                    if parts >= (2, 12):
-                        result.append((''.join((IMP_PREFIX, versions[0])), abi,
-                                       'manylinux2010_%s' % arch))
-                    if parts >= (2, 17):
-                        result.append((''.join((IMP_PREFIX, versions[0])), abi,
-                                       'manylinux2014_%s' % arch))
-                    result.append(
-                        (''.join((IMP_PREFIX, versions[0])), abi,
-                         'manylinux_%s_%s_%s' % (parts[0], parts[1], arch)))
+    for i, version_object in enumerate(versions):
+        version = str(version_object)
+        add_abis = []
+
+        if i == 0:
+            add_abis = abis
+
+        if IMP_PREFIX == 'cp' and version_object.major_minor >= (3, 2):
+            limited_api_abi = 'abi' + str(version_object.major)
+            if limited_api_abi not in add_abis:
+                add_abis.append(limited_api_abi)
+
+        for abi in add_abis:
+            for arch in arches:
+                result.append((''.join((IMP_PREFIX, version)), abi, arch))
+                # manylinux
+                if abi != 'none' and sys.platform.startswith('linux'):
+                    arch = arch.replace('linux_', '')
+                    parts = _get_glibc_version()
+                    if len(parts) == 2:
+                        if parts >= (2, 5):
+                            result.append((''.join((IMP_PREFIX, version)), abi, 'manylinux1_%s' % arch))
+                        if parts >= (2, 12):
+                            result.append((''.join((IMP_PREFIX, version)), abi, 'manylinux2010_%s' % arch))
+                        if parts >= (2, 17):
+                            result.append((''.join((IMP_PREFIX, version)), abi, 'manylinux2014_%s' % arch))
+                        result.append((''.join(
+                            (IMP_PREFIX, version)), abi, 'manylinux_%s_%s_%s' % (parts[0], parts[1], arch)))
 
     # where no ABI / arch dependency, but IMP_PREFIX dependency
-    for i, version in enumerate(versions):
+    for i, version_object in enumerate(versions):
+        version = str(version_object)
         result.append((''.join((IMP_PREFIX, version)), 'none', 'any'))
         if i == 0:
             result.append((''.join((IMP_PREFIX, version[0])), 'none', 'any'))
 
     # no IMP_PREFIX, ABI or arch dependency
-    for i, version in enumerate(versions):
+    for i, version_object in enumerate(versions):
+        version = str(version_object)
         result.append((''.join(('py', version)), 'none', 'any'))
         if i == 0:
             result.append((''.join(('py', version[0])), 'none', 'any'))
diff --git a/venv/Lib/site-packages/pip/_vendor/distro/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/distro/__pycache__/__init__.cpython-311.pyc
index a4beb2c..c6b75fa 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/distro/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/distro/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/distro/__pycache__/__main__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/distro/__pycache__/__main__.cpython-311.pyc
index 9bf0968..1514ce9 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/distro/__pycache__/__main__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/distro/__pycache__/__main__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/distro/__pycache__/distro.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/distro/__pycache__/distro.cpython-311.pyc
index 46d020a..61abe7c 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/distro/__pycache__/distro.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/distro/__pycache__/distro.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/__init__.cpython-311.pyc
index 4b7a9fb..d604c47 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/codec.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/codec.cpython-311.pyc
index 133ca74..75a917d 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/codec.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/codec.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/compat.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/compat.cpython-311.pyc
index 967f063..85d09e3 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/compat.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/compat.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/core.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/core.cpython-311.pyc
index f263df3..0f4f709 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/core.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/core.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/idnadata.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/idnadata.cpython-311.pyc
index f348255..8027c4e 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/idnadata.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/idnadata.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/intranges.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/intranges.cpython-311.pyc
index 11814e2..6875d65 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/intranges.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/intranges.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/package_data.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/package_data.cpython-311.pyc
index 1a3b5bb..d7491bb 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/package_data.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/package_data.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/uts46data.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/uts46data.cpython-311.pyc
index 4ee0b18..5b7960c 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/uts46data.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/idna/__pycache__/uts46data.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-311.pyc
index f32f5c1..5ddcff5 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/exceptions.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/exceptions.cpython-311.pyc
index 2af2a33..b6fe540 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/exceptions.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/exceptions.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/ext.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/ext.cpython-311.pyc
index 5bb4604..b53e1bc 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/ext.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/ext.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/fallback.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/fallback.cpython-311.pyc
index 7d150e4..bde38f3 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/fallback.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/fallback.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/__init__.cpython-311.pyc
index bfb0206..b613bda 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_elffile.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_elffile.cpython-311.pyc
index dbc0a8d..20ff24e 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_elffile.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_elffile.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_manylinux.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_manylinux.cpython-311.pyc
index 2f4d108..f7f0a35 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_manylinux.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_manylinux.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_musllinux.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_musllinux.cpython-311.pyc
index 0a5f504..25df22d 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_musllinux.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_musllinux.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_parser.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_parser.cpython-311.pyc
index f36652b..449686f 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_parser.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_parser.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_structures.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_structures.cpython-311.pyc
index d4ec2eb..be5b883 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_structures.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_structures.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_tokenizer.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_tokenizer.cpython-311.pyc
index adefa59..8d203fc 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_tokenizer.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_tokenizer.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/markers.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/markers.cpython-311.pyc
index d1fbede..81101e8 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/markers.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/markers.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/metadata.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/metadata.cpython-311.pyc
index 9e8933b..8acbf05 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/metadata.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/metadata.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/requirements.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/requirements.cpython-311.pyc
index 5aeb712..d9dd27c 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/requirements.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/requirements.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/specifiers.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/specifiers.cpython-311.pyc
index 76b521a..4228950 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/specifiers.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/specifiers.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/tags.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/tags.cpython-311.pyc
index 8d00d84..89aa834 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/tags.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/tags.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/utils.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/utils.cpython-311.pyc
index 74efc88..779fdf7 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/utils.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/utils.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/version.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/version.cpython-311.pyc
index 005f8d4..bc7800e 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/version.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/version.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/packaging/tags.py b/venv/Lib/site-packages/pip/_vendor/packaging/tags.py
index 6667d29..703f0ed 100644
--- a/venv/Lib/site-packages/pip/_vendor/packaging/tags.py
+++ b/venv/Lib/site-packages/pip/_vendor/packaging/tags.py
@@ -25,7 +25,7 @@
 logger = logging.getLogger(__name__)
 
 PythonVersion = Sequence[int]
-MacVersion = Tuple[int, int]
+AppleVersion = Tuple[int, int]
 
 INTERPRETER_SHORT_NAMES: dict[str, str] = {
     "python": "py",  # Generic.
@@ -363,7 +363,7 @@ def _mac_arch(arch: str, is_32bit: bool = _32_BIT_INTERPRETER) -> str:
     return "i386"
 
 
-def _mac_binary_formats(version: MacVersion, cpu_arch: str) -> list[str]:
+def _mac_binary_formats(version: AppleVersion, cpu_arch: str) -> list[str]:
     formats = [cpu_arch]
     if cpu_arch == "x86_64":
         if version < (10, 4):
@@ -396,7 +396,7 @@ def _mac_binary_formats(version: MacVersion, cpu_arch: str) -> list[str]:
 
 
 def mac_platforms(
-    version: MacVersion | None = None, arch: str | None = None
+    version: AppleVersion | None = None, arch: str | None = None
 ) -> Iterator[str]:
     """
     Yields the platform tags for a macOS system.
@@ -408,7 +408,7 @@ def mac_platforms(
     """
     version_str, _, cpu_arch = platform.mac_ver()
     if version is None:
-        version = cast("MacVersion", tuple(map(int, version_str.split(".")[:2])))
+        version = cast("AppleVersion", tuple(map(int, version_str.split(".")[:2])))
         if version == (10, 16):
             # When built against an older macOS SDK, Python will report macOS 10.16
             # instead of the real version.
@@ -424,7 +424,7 @@ def mac_platforms(
                 stdout=subprocess.PIPE,
                 text=True,
             ).stdout
-            version = cast("MacVersion", tuple(map(int, version_str.split(".")[:2])))
+            version = cast("AppleVersion", tuple(map(int, version_str.split(".")[:2])))
     else:
         version = version
     if arch is None:
@@ -483,6 +483,63 @@ def mac_platforms(
                 )
 
 
+def ios_platforms(
+    version: AppleVersion | None = None, multiarch: str | None = None
+) -> Iterator[str]:
+    """
+    Yields the platform tags for an iOS system.
+
+    :param version: A two-item tuple specifying the iOS version to generate
+        platform tags for. Defaults to the current iOS version.
+    :param multiarch: The CPU architecture+ABI to generate platform tags for -
+        (the value used by `sys.implementation._multiarch` e.g.,
+        `arm64_iphoneos` or `x84_64_iphonesimulator`). Defaults to the current
+        multiarch value.
+    """
+    if version is None:
+        # if iOS is the current platform, ios_ver *must* be defined. However,
+        # it won't exist for CPython versions before 3.13, which causes a mypy
+        # error.
+        _, release, _, _ = platform.ios_ver()  # type: ignore[attr-defined]
+        version = cast("AppleVersion", tuple(map(int, release.split(".")[:2])))
+
+    if multiarch is None:
+        multiarch = sys.implementation._multiarch
+    multiarch = multiarch.replace("-", "_")
+
+    ios_platform_template = "ios_{major}_{minor}_{multiarch}"
+
+    # Consider any iOS major.minor version from the version requested, down to
+    # 12.0. 12.0 is the first iOS version that is known to have enough features
+    # to support CPython. Consider every possible minor release up to X.9. There
+    # highest the minor has ever gone is 8 (14.8 and 15.8) but having some extra
+    # candidates that won't ever match doesn't really hurt, and it saves us from
+    # having to keep an explicit list of known iOS versions in the code. Return
+    # the results descending order of version number.
+
+    # If the requested major version is less than 12, there won't be any matches.
+    if version[0] < 12:
+        return
+
+    # Consider the actual X.Y version that was requested.
+    yield ios_platform_template.format(
+        major=version[0], minor=version[1], multiarch=multiarch
+    )
+
+    # Consider every minor version from X.0 to the minor version prior to the
+    # version requested by the platform.
+    for minor in range(version[1] - 1, -1, -1):
+        yield ios_platform_template.format(
+            major=version[0], minor=minor, multiarch=multiarch
+        )
+
+    for major in range(version[0] - 1, 11, -1):
+        for minor in range(9, -1, -1):
+            yield ios_platform_template.format(
+                major=major, minor=minor, multiarch=multiarch
+            )
+
+
 def _linux_platforms(is_32bit: bool = _32_BIT_INTERPRETER) -> Iterator[str]:
     linux = _normalize_string(sysconfig.get_platform())
     if not linux.startswith("linux_"):
@@ -512,6 +569,8 @@ def platform_tags() -> Iterator[str]:
     """
     if platform.system() == "Darwin":
         return mac_platforms()
+    elif platform.system() == "iOS":
+        return ios_platforms()
     elif platform.system() == "Linux":
         return _linux_platforms()
     else:
diff --git a/venv/Lib/site-packages/pip/_vendor/pkg_resources/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pkg_resources/__pycache__/__init__.cpython-311.pyc
index fa54a19..85bdf4c 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pkg_resources/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pkg_resources/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/__init__.cpython-311.pyc
index f7b2693..1f5ebc2 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/__main__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/__main__.cpython-311.pyc
index 8cceb45..3216fcf 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/__main__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/__main__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/android.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/android.cpython-311.pyc
index a036b8b..d2708e9 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/android.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/android.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/api.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/api.cpython-311.pyc
index 1babe85..fdf90a2 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/api.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/api.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/macos.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/macos.cpython-311.pyc
index 7b5a5d8..9cf2788 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/macos.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/macos.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/unix.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/unix.cpython-311.pyc
index 541af91..6e218c6 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/unix.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/unix.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/version.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/version.cpython-311.pyc
index 928b29f..1744e04 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/version.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/version.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/windows.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/windows.cpython-311.pyc
index 08de345..e5b2bbf 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/windows.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/windows.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/__init__.cpython-311.pyc
index ed758d5..0b2df56 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/__main__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/__main__.cpython-311.pyc
index 1e07818..a7d053f 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/__main__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/__main__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/cmdline.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/cmdline.cpython-311.pyc
index c0b0091..fb5b492 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/cmdline.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/cmdline.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/console.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/console.cpython-311.pyc
index a63942f..ea5009d 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/console.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/console.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/filter.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/filter.cpython-311.pyc
index d7d8e72..199de20 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/filter.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/filter.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/formatter.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/formatter.cpython-311.pyc
index d0165e6..d530ae7 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/formatter.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/formatter.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/lexer.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/lexer.cpython-311.pyc
index 2f1a7b8..18d433f 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/lexer.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/lexer.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/modeline.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/modeline.cpython-311.pyc
index 346785c..43db32e 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/modeline.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/modeline.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/plugin.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/plugin.cpython-311.pyc
index 8402c13..c5fa23a 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/plugin.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/plugin.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/regexopt.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/regexopt.cpython-311.pyc
index 4e3331d..00c06ad 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/regexopt.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/regexopt.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/scanner.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/scanner.cpython-311.pyc
index f721ad9..3f9cb70 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/scanner.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/scanner.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/sphinxext.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/sphinxext.cpython-311.pyc
index a1bd09a..6ebfe13 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/sphinxext.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/sphinxext.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/style.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/style.cpython-311.pyc
index 1a34731..e5ba499 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/style.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/style.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/token.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/token.cpython-311.pyc
index 977a1b0..9d95fbc 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/token.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/token.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/unistring.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/unistring.cpython-311.pyc
index 3d80975..0354f7a 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/unistring.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/unistring.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/util.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/util.cpython-311.pyc
index 502d402..6fa69e3 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/util.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/util.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/filters/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/filters/__pycache__/__init__.cpython-311.pyc
index dd73683..4cbaee6 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/filters/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/filters/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/__init__.cpython-311.pyc
index 14c1d4c..d3302b0 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/_mapping.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/_mapping.cpython-311.pyc
index ca82e34..eabe46d 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/_mapping.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/_mapping.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/bbcode.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/bbcode.cpython-311.pyc
index 82a38ff..4efd9b1 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/bbcode.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/bbcode.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/groff.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/groff.cpython-311.pyc
index 2fb482b..761bc82 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/groff.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/groff.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/html.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/html.cpython-311.pyc
index 9e9da73..cf0211b 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/html.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/html.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/img.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/img.cpython-311.pyc
index 30ccd79..ec9d840 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/img.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/img.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/irc.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/irc.cpython-311.pyc
index 7617d9b..47170f7 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/irc.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/irc.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/latex.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/latex.cpython-311.pyc
index 7f974e8..930ed39 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/latex.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/latex.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/other.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/other.cpython-311.pyc
index 5a4c14e..99d2ae2 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/other.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/other.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/pangomarkup.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/pangomarkup.cpython-311.pyc
index 851c388..24261c2 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/pangomarkup.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/pangomarkup.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/rtf.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/rtf.cpython-311.pyc
index c0aabb0..ec19d5a 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/rtf.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/rtf.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/svg.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/svg.cpython-311.pyc
index c1388fe..313d688 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/svg.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/svg.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal.cpython-311.pyc
index fd5231d..e4e0e63 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal256.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal256.cpython-311.pyc
index 436b061..cf8f743 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal256.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal256.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/__init__.cpython-311.pyc
index 97f4ca9..07b0194 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/_mapping.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/_mapping.cpython-311.pyc
index 3a9574d..fdf6761 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/_mapping.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/_mapping.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/python.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/python.cpython-311.pyc
index 31573dc..21beb5f 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/python.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/python.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/styles/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/styles/__pycache__/__init__.cpython-311.pyc
index 746c47c..d07b653 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/styles/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/styles/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pygments/styles/__pycache__/_mapping.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pygments/styles/__pycache__/_mapping.cpython-311.pyc
index f8b4b31..0a3c83e 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pygments/styles/__pycache__/_mapping.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pygments/styles/__pycache__/_mapping.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__pycache__/__init__.cpython-311.pyc
index e2d31b2..4549872 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_compat.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_compat.cpython-311.pyc
index ffb6322..1955bd0 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_compat.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_compat.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_impl.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_impl.cpython-311.pyc
index ea4167f..415ebff 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_impl.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_impl.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/__init__.cpython-311.pyc
index 8712da9..a3e49a2 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/_in_process.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/_in_process.cpython-311.pyc
index ffb1f23..f0a82c6 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/_in_process.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/_in_process.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/__init__.cpython-311.pyc
index 25be7c7..9fc97c0 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/__version__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/__version__.cpython-311.pyc
index 8f3dd2f..2995a4b 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/__version__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/__version__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/_internal_utils.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/_internal_utils.cpython-311.pyc
index 77081e5..636a78a 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/_internal_utils.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/_internal_utils.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/adapters.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/adapters.cpython-311.pyc
index cfd3553..65a2164 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/adapters.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/adapters.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/api.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/api.cpython-311.pyc
index 88a69ae..549a8f2 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/api.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/api.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/auth.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/auth.cpython-311.pyc
index fd1111f..8155d2a 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/auth.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/auth.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/certs.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/certs.cpython-311.pyc
index 9a7c2d0..af858da 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/certs.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/certs.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/compat.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/compat.cpython-311.pyc
index 3956b2c..898ecc3 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/compat.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/compat.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/cookies.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/cookies.cpython-311.pyc
index b16037e..5265d06 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/cookies.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/cookies.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/exceptions.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/exceptions.cpython-311.pyc
index 4e6d401..cacc17f 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/exceptions.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/exceptions.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/help.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/help.cpython-311.pyc
index 1f6a32d..ec03bf2 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/help.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/help.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/hooks.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/hooks.cpython-311.pyc
index 1ff48a5..9d411c1 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/hooks.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/hooks.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/models.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/models.cpython-311.pyc
index f35e9a0..bbba645 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/models.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/models.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/packages.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/packages.cpython-311.pyc
index 241bed6..1820859 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/packages.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/packages.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/sessions.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/sessions.cpython-311.pyc
index d527d97..4d9b7da 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/sessions.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/sessions.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/status_codes.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/status_codes.cpython-311.pyc
index 6df33ba..1ecf68c 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/status_codes.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/status_codes.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/structures.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/structures.cpython-311.pyc
index 80135f1..4e373ba 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/structures.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/structures.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/utils.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/utils.cpython-311.pyc
index f0f1dd0..faf938a 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/utils.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/requests/__pycache__/utils.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/__init__.cpython-311.pyc
index 53367cc..50015a0 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/providers.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/providers.cpython-311.pyc
index 953b0c3..a866eac 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/providers.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/providers.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/reporters.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/reporters.cpython-311.pyc
index 2739b64..41fc82d 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/reporters.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/reporters.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/resolvers.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/resolvers.cpython-311.pyc
index 95243e0..65d4c59 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/resolvers.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/resolvers.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/structs.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/structs.cpython-311.pyc
index 76696a6..ef1fd50 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/structs.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/structs.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/resolvelib/compat/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/resolvelib/compat/__pycache__/__init__.cpython-311.pyc
index 58d05f3..4c5e866 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/resolvelib/compat/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/resolvelib/compat/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/resolvelib/compat/__pycache__/collections_abc.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/resolvelib/compat/__pycache__/collections_abc.cpython-311.pyc
index e780f35..ea149df 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/resolvelib/compat/__pycache__/collections_abc.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/resolvelib/compat/__pycache__/collections_abc.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/__init__.cpython-311.pyc
index 132636e..d786aa9 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/__main__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/__main__.cpython-311.pyc
index 8e55ada..d811b35 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/__main__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/__main__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_cell_widths.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_cell_widths.cpython-311.pyc
index d70d659..c672172 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_cell_widths.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_cell_widths.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_emoji_codes.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_emoji_codes.cpython-311.pyc
index 2cc2864..8fc0bc4 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_emoji_codes.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_emoji_codes.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_emoji_replace.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_emoji_replace.cpython-311.pyc
index a8275ef..45023e8 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_emoji_replace.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_emoji_replace.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_export_format.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_export_format.cpython-311.pyc
index a54788b..fb86ce8 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_export_format.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_export_format.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_extension.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_extension.cpython-311.pyc
index 7bd064d..5b84263 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_extension.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_extension.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_fileno.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_fileno.cpython-311.pyc
index 70e99a8..2cede05 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_fileno.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_fileno.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_inspect.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_inspect.cpython-311.pyc
index dc17f96..0b13124 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_inspect.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_inspect.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_log_render.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_log_render.cpython-311.pyc
index c65f40a..1c2d818 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_log_render.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_log_render.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_loop.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_loop.cpython-311.pyc
index be83a4e..cbb1ddf 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_loop.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_loop.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_null_file.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_null_file.cpython-311.pyc
index e7d6ee3..2af51f5 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_null_file.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_null_file.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_palettes.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_palettes.cpython-311.pyc
index 2357176..d0d41ff 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_palettes.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_palettes.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_pick.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_pick.cpython-311.pyc
index 3752dde..378e5fc 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_pick.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_pick.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_ratio.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_ratio.cpython-311.pyc
index 5140262..527e592 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_ratio.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_ratio.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_spinners.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_spinners.cpython-311.pyc
index 381d83d..bf9e268 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_spinners.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_spinners.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_stack.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_stack.cpython-311.pyc
index 576ceba..bb1c74c 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_stack.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_stack.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_timer.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_timer.cpython-311.pyc
index a7fc5e6..b4b8c4f 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_timer.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_timer.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_win32_console.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_win32_console.cpython-311.pyc
index 09018da..1cae5e7 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_win32_console.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_win32_console.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_windows.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_windows.cpython-311.pyc
index 4fd6b63..4719788 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_windows.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_windows.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_windows_renderer.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_windows_renderer.cpython-311.pyc
index b91b776..f5554d8 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_windows_renderer.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_windows_renderer.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_wrap.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_wrap.cpython-311.pyc
index 16b4d43..8dc0df5 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_wrap.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_wrap.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/abc.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/abc.cpython-311.pyc
index e6322a1..37c6992 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/abc.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/abc.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/align.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/align.cpython-311.pyc
index 6a97d15..ef00b2d 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/align.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/align.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/ansi.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/ansi.cpython-311.pyc
index e332027..0fb37f1 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/ansi.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/ansi.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/bar.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/bar.cpython-311.pyc
index 0f50a93..9beb289 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/bar.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/bar.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/box.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/box.cpython-311.pyc
index 5821b45..2b7ab28 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/box.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/box.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/cells.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/cells.cpython-311.pyc
index bee69ab..4104921 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/cells.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/cells.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/color.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/color.cpython-311.pyc
index cf08268..beb7757 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/color.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/color.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/color_triplet.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/color_triplet.cpython-311.pyc
index b26c2dc..f4c5a30 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/color_triplet.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/color_triplet.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/columns.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/columns.cpython-311.pyc
index e902908..4fe5a6d 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/columns.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/columns.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/console.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/console.cpython-311.pyc
index 91d7696..f8b3333 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/console.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/console.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/constrain.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/constrain.cpython-311.pyc
index 82e45a7..5933726 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/constrain.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/constrain.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/containers.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/containers.cpython-311.pyc
index 5a805fa..3da6f70 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/containers.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/containers.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/control.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/control.cpython-311.pyc
index 1d06349..1714356 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/control.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/control.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/default_styles.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/default_styles.cpython-311.pyc
index 8bff2b5..7d5b9f6 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/default_styles.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/default_styles.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/diagnose.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/diagnose.cpython-311.pyc
index dc8cde5..ea1ba6f 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/diagnose.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/diagnose.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/emoji.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/emoji.cpython-311.pyc
index 1e36981..525d204 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/emoji.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/emoji.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/errors.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/errors.cpython-311.pyc
index 474524e..add9329 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/errors.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/errors.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/file_proxy.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/file_proxy.cpython-311.pyc
index 418fd27..559ec2a 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/file_proxy.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/file_proxy.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/filesize.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/filesize.cpython-311.pyc
index 93b2379..db1e0e7 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/filesize.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/filesize.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/highlighter.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/highlighter.cpython-311.pyc
index e7772c3..d770770 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/highlighter.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/highlighter.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/json.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/json.cpython-311.pyc
index 2691004..4577449 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/json.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/json.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/jupyter.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/jupyter.cpython-311.pyc
index ac6d898..ea4fb8a 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/jupyter.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/jupyter.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/layout.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/layout.cpython-311.pyc
index 86533d1..405804d 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/layout.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/layout.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/live.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/live.cpython-311.pyc
index 8869fca..cc17627 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/live.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/live.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/live_render.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/live_render.cpython-311.pyc
index 48411a3..531f73f 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/live_render.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/live_render.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/logging.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/logging.cpython-311.pyc
index a24f922..a382c0b 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/logging.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/logging.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/markup.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/markup.cpython-311.pyc
index c6851fc..eed1def 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/markup.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/markup.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/measure.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/measure.cpython-311.pyc
index 7060f93..ac3afaa 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/measure.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/measure.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/padding.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/padding.cpython-311.pyc
index de4f8b4..f07abeb 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/padding.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/padding.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/pager.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/pager.cpython-311.pyc
index 55f4531..b0d47aa 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/pager.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/pager.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/palette.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/palette.cpython-311.pyc
index 89b4008..7e1e439 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/palette.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/palette.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/panel.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/panel.cpython-311.pyc
index ad8d664..e5de5e0 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/panel.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/panel.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/pretty.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/pretty.cpython-311.pyc
index b8a5c35..119d9cc 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/pretty.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/pretty.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/progress.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/progress.cpython-311.pyc
index eb20ad4..01554eb 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/progress.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/progress.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/progress_bar.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/progress_bar.cpython-311.pyc
index d3d1d8f..53c0e5c 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/progress_bar.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/progress_bar.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/prompt.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/prompt.cpython-311.pyc
index a3d84ed..9b2a037 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/prompt.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/prompt.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/protocol.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/protocol.cpython-311.pyc
index a470c03..99fdaa9 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/protocol.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/protocol.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/region.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/region.cpython-311.pyc
index 8c24ccf..74f91f6 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/region.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/region.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/repr.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/repr.cpython-311.pyc
index 9490ded..72be722 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/repr.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/repr.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/rule.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/rule.cpython-311.pyc
index 99ba4c5..19b6157 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/rule.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/rule.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/scope.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/scope.cpython-311.pyc
index 6c96e2d..ad87bc0 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/scope.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/scope.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/screen.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/screen.cpython-311.pyc
index 0dad27a..c559d03 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/screen.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/screen.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/segment.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/segment.cpython-311.pyc
index c3aa07a..432f745 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/segment.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/segment.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/spinner.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/spinner.cpython-311.pyc
index b53efc6..9475ae0 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/spinner.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/spinner.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/status.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/status.cpython-311.pyc
index aab2fcd..0ed90cb 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/status.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/status.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/style.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/style.cpython-311.pyc
index 0335bc3..b91248d 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/style.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/style.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/styled.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/styled.cpython-311.pyc
index 2208351..c995299 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/styled.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/styled.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/syntax.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/syntax.cpython-311.pyc
index 556a638..d987c24 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/syntax.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/syntax.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/table.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/table.cpython-311.pyc
index ebacf1d..ef669ca 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/table.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/table.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/terminal_theme.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/terminal_theme.cpython-311.pyc
index 267b8fd..a4ebbcb 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/terminal_theme.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/terminal_theme.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/text.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/text.cpython-311.pyc
index f0ecf57..d835de3 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/text.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/text.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/theme.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/theme.cpython-311.pyc
index 5155567..46020de 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/theme.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/theme.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/themes.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/themes.cpython-311.pyc
index 127fd80..10c4e8d 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/themes.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/themes.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/traceback.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/traceback.cpython-311.pyc
index 99cebbd..c94649e 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/traceback.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/traceback.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/tree.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/tree.cpython-311.pyc
index 303062f..962b43d 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/tree.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/rich/__pycache__/tree.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/__init__.cpython-311.pyc
index 999527b..ac3878e 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_parser.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_parser.cpython-311.pyc
index 8f5470c..0809f80 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_parser.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_parser.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_re.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_re.cpython-311.pyc
index 3a1a8c4..7638f7a 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_re.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_re.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_types.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_types.cpython-311.pyc
index 5c2909d..8f14faf 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_types.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_types.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/truststore/__init__.py b/venv/Lib/site-packages/pip/_vendor/truststore/__init__.py
index 8636814..e468bf8 100644
--- a/venv/Lib/site-packages/pip/_vendor/truststore/__init__.py
+++ b/venv/Lib/site-packages/pip/_vendor/truststore/__init__.py
@@ -5,9 +5,32 @@
 if _sys.version_info < (3, 10):
     raise ImportError("truststore requires Python 3.10 or later")
 
+# Detect Python runtimes which don't implement SSLObject.get_unverified_chain() API
+# This API only became public in Python 3.13 but was available in CPython and PyPy since 3.10.
+if _sys.version_info < (3, 13):
+    try:
+        import ssl as _ssl
+    except ImportError:
+        raise ImportError("truststore requires the 'ssl' module")
+    else:
+        _sslmem = _ssl.MemoryBIO()
+        _sslobj = _ssl.create_default_context().wrap_bio(
+            _sslmem,
+            _sslmem,
+        )
+        try:
+            while not hasattr(_sslobj, "get_unverified_chain"):
+                _sslobj = _sslobj._sslobj  # type: ignore[attr-defined]
+        except AttributeError:
+            raise ImportError(
+                "truststore requires peer certificate chain APIs to be available"
+            ) from None
+
+        del _ssl, _sslobj, _sslmem  # noqa: F821
+
 from ._api import SSLContext, extract_from_ssl, inject_into_ssl  # noqa: E402
 
 del _api, _sys  # type: ignore[name-defined] # noqa: F821
 
 __all__ = ["SSLContext", "inject_into_ssl", "extract_from_ssl"]
-__version__ = "0.9.1"
+__version__ = "0.10.0"
diff --git a/venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/__init__.cpython-311.pyc
index 1958dc0..a1c652f 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_api.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_api.cpython-311.pyc
index 7c37c63..48b3afd 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_api.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_api.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_macos.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_macos.cpython-311.pyc
index 0e76739..17922df 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_macos.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_macos.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_openssl.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_openssl.cpython-311.pyc
index 68ac824..ff0fe64 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_openssl.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_openssl.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_ssl_constants.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_ssl_constants.cpython-311.pyc
index 1f6bd53..11c7c0e 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_ssl_constants.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_ssl_constants.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_windows.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_windows.cpython-311.pyc
index 71c46ac..9d3ba20 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_windows.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/truststore/__pycache__/_windows.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/truststore/_api.py b/venv/Lib/site-packages/pip/_vendor/truststore/_api.py
index b1ea3b0..aeb023a 100644
--- a/venv/Lib/site-packages/pip/_vendor/truststore/_api.py
+++ b/venv/Lib/site-packages/pip/_vendor/truststore/_api.py
@@ -169,6 +169,9 @@ def session_stats(self) -> dict[str, int]:
     def cert_store_stats(self) -> dict[str, int]:
         raise NotImplementedError()
 
+    def set_default_verify_paths(self) -> None:
+        self._ctx.set_default_verify_paths()
+
     @typing.overload
     def get_ca_certs(
         self, binary_form: typing.Literal[False] = ...
diff --git a/venv/Lib/site-packages/pip/_vendor/truststore/_macos.py b/venv/Lib/site-packages/pip/_vendor/truststore/_macos.py
index b234ffe..3450307 100644
--- a/venv/Lib/site-packages/pip/_vendor/truststore/_macos.py
+++ b/venv/Lib/site-packages/pip/_vendor/truststore/_macos.py
@@ -25,6 +25,8 @@
         f"Only OS X 10.8 and newer are supported, not {_mac_version_info[0]}.{_mac_version_info[1]}"
     )
 
+_is_macos_version_10_14_or_later = _mac_version_info >= (10, 14)
+
 
 def _load_cdll(name: str, macos10_16_path: str) -> CDLL:
     """Loads a CDLL by name, falling back to known path on 10.16+"""
@@ -115,6 +117,12 @@ def _load_cdll(name: str, macos10_16_path: str) -> CDLL:
     ]
     Security.SecTrustGetTrustResult.restype = OSStatus
 
+    Security.SecTrustEvaluate.argtypes = [
+        SecTrustRef,
+        POINTER(SecTrustResultType),
+    ]
+    Security.SecTrustEvaluate.restype = OSStatus
+
     Security.SecTrustRef = SecTrustRef  # type: ignore[attr-defined]
     Security.SecTrustResultType = SecTrustResultType  # type: ignore[attr-defined]
     Security.OSStatus = OSStatus  # type: ignore[attr-defined]
@@ -197,8 +205,19 @@ def _load_cdll(name: str, macos10_16_path: str) -> CDLL:
     CoreFoundation.CFStringRef = CFStringRef  # type: ignore[attr-defined]
     CoreFoundation.CFErrorRef = CFErrorRef  # type: ignore[attr-defined]
 
-except AttributeError:
-    raise ImportError("Error initializing ctypes") from None
+except AttributeError as e:
+    raise ImportError(f"Error initializing ctypes: {e}") from None
+
+# SecTrustEvaluateWithError is macOS 10.14+
+if _is_macos_version_10_14_or_later:
+    try:
+        Security.SecTrustEvaluateWithError.argtypes = [
+            SecTrustRef,
+            POINTER(CFErrorRef),
+        ]
+        Security.SecTrustEvaluateWithError.restype = c_bool
+    except AttributeError as e:
+        raise ImportError(f"Error initializing ctypes: {e}") from None
 
 
 def _handle_osstatus(result: OSStatus, _: typing.Any, args: typing.Any) -> typing.Any:
@@ -258,6 +277,7 @@ def _handle_osstatus(result: OSStatus, _: typing.Any, args: typing.Any) -> typin
 Security.SecTrustSetAnchorCertificates.errcheck = _handle_osstatus  # type: ignore[assignment]
 Security.SecTrustSetAnchorCertificatesOnly.errcheck = _handle_osstatus  # type: ignore[assignment]
 Security.SecTrustGetTrustResult.errcheck = _handle_osstatus  # type: ignore[assignment]
+Security.SecTrustEvaluate.errcheck = _handle_osstatus  # type: ignore[assignment]
 
 
 class CFConst:
@@ -365,9 +385,10 @@ def _verify_peercerts_impl(
     certs = None
     policies = None
     trust = None
-    cf_error = None
     try:
-        if server_hostname is not None:
+        # Only set a hostname on the policy if we're verifying the hostname
+        # on the leaf certificate.
+        if server_hostname is not None and ssl_context.check_hostname:
             cf_str_hostname = None
             try:
                 cf_str_hostname = _bytes_to_cf_string(server_hostname.encode("ascii"))
@@ -431,69 +452,120 @@ def _verify_peercerts_impl(
         # We always want system certificates.
         Security.SecTrustSetAnchorCertificatesOnly(trust, False)
 
-        cf_error = CoreFoundation.CFErrorRef()
-        sec_trust_eval_result = Security.SecTrustEvaluateWithError(
-            trust, ctypes.byref(cf_error)
-        )
-        # sec_trust_eval_result is a bool (0 or 1)
-        # where 1 means that the certs are trusted.
-        if sec_trust_eval_result == 1:
-            is_trusted = True
-        elif sec_trust_eval_result == 0:
-            is_trusted = False
+        # macOS 10.13 and earlier don't support SecTrustEvaluateWithError()
+        # so we use SecTrustEvaluate() which means we need to construct error
+        # messages ourselves.
+        if _is_macos_version_10_14_or_later:
+            _verify_peercerts_impl_macos_10_14(ssl_context, trust)
         else:
-            raise ssl.SSLError(
-                f"Unknown result from Security.SecTrustEvaluateWithError: {sec_trust_eval_result!r}"
-            )
-
-        cf_error_code = 0
-        if not is_trusted:
-            cf_error_code = CoreFoundation.CFErrorGetCode(cf_error)
-
-            # If the error is a known failure that we're
-            # explicitly okay with from SSLContext configuration
-            # we can set is_trusted accordingly.
-            if ssl_context.verify_mode != ssl.CERT_REQUIRED and (
-                cf_error_code == CFConst.errSecNotTrusted
-                or cf_error_code == CFConst.errSecCertificateExpired
-            ):
-                is_trusted = True
-            elif (
-                not ssl_context.check_hostname
-                and cf_error_code == CFConst.errSecHostNameMismatch
-            ):
-                is_trusted = True
-
-        # If we're still not trusted then we start to
-        # construct and raise the SSLCertVerificationError.
-        if not is_trusted:
-            cf_error_string_ref = None
-            try:
-                cf_error_string_ref = CoreFoundation.CFErrorCopyDescription(cf_error)
-
-                # Can this ever return 'None' if there's a CFError?
-                cf_error_message = (
-                    _cf_string_ref_to_str(cf_error_string_ref)
-                    or "Certificate verification failed"
-                )
-
-                # TODO: Not sure if we need the SecTrustResultType for anything?
-                # We only care whether or not it's a success or failure for now.
-                sec_trust_result_type = Security.SecTrustResultType()
-                Security.SecTrustGetTrustResult(
-                    trust, ctypes.byref(sec_trust_result_type)
-                )
-
-                err = ssl.SSLCertVerificationError(cf_error_message)
-                err.verify_message = cf_error_message
-                err.verify_code = cf_error_code
-                raise err
-            finally:
-                if cf_error_string_ref:
-                    CoreFoundation.CFRelease(cf_error_string_ref)
-
+            _verify_peercerts_impl_macos_10_13(ssl_context, trust)
     finally:
         if policies:
             CoreFoundation.CFRelease(policies)
         if trust:
             CoreFoundation.CFRelease(trust)
+
+
+def _verify_peercerts_impl_macos_10_13(
+    ssl_context: ssl.SSLContext, sec_trust_ref: typing.Any
+) -> None:
+    """Verify using 'SecTrustEvaluate' API for macOS 10.13 and earlier.
+    macOS 10.14 added the 'SecTrustEvaluateWithError' API.
+    """
+    sec_trust_result_type = Security.SecTrustResultType()
+    Security.SecTrustEvaluate(sec_trust_ref, ctypes.byref(sec_trust_result_type))
+
+    try:
+        sec_trust_result_type_as_int = int(sec_trust_result_type.value)
+    except (ValueError, TypeError):
+        sec_trust_result_type_as_int = -1
+
+    # Apple doesn't document these values in their own API docs.
+    # See: https://github.com/xybp888/iOS-SDKs/blob/master/iPhoneOS13.0.sdk/System/Library/Frameworks/Security.framework/Headers/SecTrust.h#L84
+    if (
+        ssl_context.verify_mode == ssl.CERT_REQUIRED
+        and sec_trust_result_type_as_int not in (1, 4)
+    ):
+        # Note that we're not able to ignore only hostname errors
+        # for macOS 10.13 and earlier, so check_hostname=False will
+        # still return an error.
+        sec_trust_result_type_to_message = {
+            0: "Invalid trust result type",
+            # 1: "Trust evaluation succeeded",
+            2: "User confirmation required",
+            3: "User specified that certificate is not trusted",
+            # 4: "Trust result is unspecified",
+            5: "Recoverable trust failure occurred",
+            6: "Fatal trust failure occurred",
+            7: "Other error occurred, certificate may be revoked",
+        }
+        error_message = sec_trust_result_type_to_message.get(
+            sec_trust_result_type_as_int,
+            f"Unknown trust result: {sec_trust_result_type_as_int}",
+        )
+
+        err = ssl.SSLCertVerificationError(error_message)
+        err.verify_message = error_message
+        err.verify_code = sec_trust_result_type_as_int
+        raise err
+
+
+def _verify_peercerts_impl_macos_10_14(
+    ssl_context: ssl.SSLContext, sec_trust_ref: typing.Any
+) -> None:
+    """Verify using 'SecTrustEvaluateWithError' API for macOS 10.14+."""
+    cf_error = CoreFoundation.CFErrorRef()
+    sec_trust_eval_result = Security.SecTrustEvaluateWithError(
+        sec_trust_ref, ctypes.byref(cf_error)
+    )
+    # sec_trust_eval_result is a bool (0 or 1)
+    # where 1 means that the certs are trusted.
+    if sec_trust_eval_result == 1:
+        is_trusted = True
+    elif sec_trust_eval_result == 0:
+        is_trusted = False
+    else:
+        raise ssl.SSLError(
+            f"Unknown result from Security.SecTrustEvaluateWithError: {sec_trust_eval_result!r}"
+        )
+
+    cf_error_code = 0
+    if not is_trusted:
+        cf_error_code = CoreFoundation.CFErrorGetCode(cf_error)
+
+        # If the error is a known failure that we're
+        # explicitly okay with from SSLContext configuration
+        # we can set is_trusted accordingly.
+        if ssl_context.verify_mode != ssl.CERT_REQUIRED and (
+            cf_error_code == CFConst.errSecNotTrusted
+            or cf_error_code == CFConst.errSecCertificateExpired
+        ):
+            is_trusted = True
+
+    # If we're still not trusted then we start to
+    # construct and raise the SSLCertVerificationError.
+    if not is_trusted:
+        cf_error_string_ref = None
+        try:
+            cf_error_string_ref = CoreFoundation.CFErrorCopyDescription(cf_error)
+
+            # Can this ever return 'None' if there's a CFError?
+            cf_error_message = (
+                _cf_string_ref_to_str(cf_error_string_ref)
+                or "Certificate verification failed"
+            )
+
+            # TODO: Not sure if we need the SecTrustResultType for anything?
+            # We only care whether or not it's a success or failure for now.
+            sec_trust_result_type = Security.SecTrustResultType()
+            Security.SecTrustGetTrustResult(
+                sec_trust_ref, ctypes.byref(sec_trust_result_type)
+            )
+
+            err = ssl.SSLCertVerificationError(cf_error_message)
+            err.verify_message = cf_error_message
+            err.verify_code = cf_error_code
+            raise err
+        finally:
+            if cf_error_string_ref:
+                CoreFoundation.CFRelease(cf_error_string_ref)
diff --git a/venv/Lib/site-packages/pip/_vendor/truststore/_windows.py b/venv/Lib/site-packages/pip/_vendor/truststore/_windows.py
index 3d00d46..a9bf9ab 100644
--- a/venv/Lib/site-packages/pip/_vendor/truststore/_windows.py
+++ b/venv/Lib/site-packages/pip/_vendor/truststore/_windows.py
@@ -212,6 +212,7 @@ class CERT_CHAIN_ENGINE_CONFIG(Structure):
 CERT_CHAIN_POLICY_IGNORE_ALL_REV_UNKNOWN_FLAGS = 0x00000F00
 CERT_CHAIN_POLICY_ALLOW_TESTROOT_FLAG = 0x00008000
 CERT_CHAIN_POLICY_TRUST_TESTROOT_FLAG = 0x00004000
+SECURITY_FLAG_IGNORE_CERT_CN_INVALID = 0x00001000
 AUTHTYPE_SERVER = 2
 CERT_CHAIN_POLICY_SSL = 4
 FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000
@@ -443,6 +444,10 @@ def _get_and_verify_cert_chain(
         )
         ssl_extra_cert_chain_policy_para.dwAuthType = AUTHTYPE_SERVER
         ssl_extra_cert_chain_policy_para.fdwChecks = 0
+        if ssl_context.check_hostname is False:
+            ssl_extra_cert_chain_policy_para.fdwChecks = (
+                SECURITY_FLAG_IGNORE_CERT_CN_INVALID
+            )
         if server_hostname:
             ssl_extra_cert_chain_policy_para.pwszServerName = c_wchar_p(server_hostname)
 
@@ -452,8 +457,6 @@ def _get_and_verify_cert_chain(
         )
         if ssl_context.verify_mode == ssl.CERT_NONE:
             chain_policy.dwFlags |= CERT_CHAIN_POLICY_VERIFY_MODE_NONE_FLAGS
-        if not ssl_context.check_hostname:
-            chain_policy.dwFlags |= CERT_CHAIN_POLICY_IGNORE_INVALID_NAME_FLAG
         chain_policy.cbSize = sizeof(chain_policy)
 
         pPolicyPara = pointer(chain_policy)
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/__init__.cpython-311.pyc
index 704d98f..5cdb1d0 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/_collections.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/_collections.cpython-311.pyc
index e157b66..9084dc9 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/_collections.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/_collections.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/_version.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/_version.cpython-311.pyc
index 324e047..0378272 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/_version.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/_version.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/connection.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/connection.cpython-311.pyc
index 35a2d04..76b1789 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/connection.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/connection.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/connectionpool.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/connectionpool.cpython-311.pyc
index 0df26da..11c3cc9 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/connectionpool.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/connectionpool.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/exceptions.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/exceptions.cpython-311.pyc
index 4cf3767..8729024 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/exceptions.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/exceptions.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/fields.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/fields.cpython-311.pyc
index 600cc5e..1ed96c8 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/fields.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/fields.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/filepost.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/filepost.cpython-311.pyc
index 9eca180..80629e6 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/filepost.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/filepost.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/poolmanager.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/poolmanager.cpython-311.pyc
index 15e8e0a..8194a26 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/poolmanager.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/poolmanager.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/request.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/request.cpython-311.pyc
index 59d32b1..d6b86a6 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/request.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/request.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/response.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/response.cpython-311.pyc
index 8de903b..3eb03ec 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/response.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/response.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/_version.py b/venv/Lib/site-packages/pip/_vendor/urllib3/_version.py
index 85e725e..d49df2a 100644
--- a/venv/Lib/site-packages/pip/_vendor/urllib3/_version.py
+++ b/venv/Lib/site-packages/pip/_vendor/urllib3/_version.py
@@ -1,2 +1,2 @@
 # This file is protected via CODEOWNERS
-__version__ = "1.26.18"
+__version__ = "1.26.20"
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/connection.py b/venv/Lib/site-packages/pip/_vendor/urllib3/connection.py
index 54b96b1..de35b63 100644
--- a/venv/Lib/site-packages/pip/_vendor/urllib3/connection.py
+++ b/venv/Lib/site-packages/pip/_vendor/urllib3/connection.py
@@ -68,7 +68,7 @@ class BrokenPipeError(Exception):
 
 # When it comes time to update this value as a part of regular maintenance
 # (ie test_recent_date is failing) update it to ~6 months before the current date.
-RECENT_DATE = datetime.date(2022, 1, 1)
+RECENT_DATE = datetime.date(2024, 1, 1)
 
 _CONTAINS_CONTROL_CHAR_RE = re.compile(r"[^-!#$%&'*+.^_`|~0-9a-zA-Z]")
 
@@ -437,7 +437,7 @@ def connect(self):
             and self.ssl_version is None
             and hasattr(self.sock, "version")
             and self.sock.version() in {"TLSv1", "TLSv1.1"}
-        ):
+        ):  # Defensive:
             warnings.warn(
                 "Negotiating TLSv1/TLSv1.1 by default is deprecated "
                 "and will be disabled in urllib3 v2.0.0. Connecting to "
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/connectionpool.py b/venv/Lib/site-packages/pip/_vendor/urllib3/connectionpool.py
index 5a6adcb..0872ed7 100644
--- a/venv/Lib/site-packages/pip/_vendor/urllib3/connectionpool.py
+++ b/venv/Lib/site-packages/pip/_vendor/urllib3/connectionpool.py
@@ -423,12 +423,13 @@ def _make_request(
             pass
         except IOError as e:
             # Python 2 and macOS/Linux
-            # EPIPE and ESHUTDOWN are BrokenPipeError on Python 2, and EPROTOTYPE is needed on macOS
+            # EPIPE and ESHUTDOWN are BrokenPipeError on Python 2, and EPROTOTYPE/ECONNRESET are needed on macOS
             # https://erickt.github.io/blog/2014/11/19/adventures-in-debugging-a-potential-osx-kernel-bug/
             if e.errno not in {
                 errno.EPIPE,
                 errno.ESHUTDOWN,
                 errno.EPROTOTYPE,
+                errno.ECONNRESET,
             }:
                 raise
 
@@ -768,7 +769,9 @@ def _is_ssl_error_message_from_http_proxy(ssl_error):
                 # so we try to cover our bases here!
                 message = " ".join(re.split("[^a-z]", str(ssl_error).lower()))
                 return (
-                    "wrong version number" in message or "unknown protocol" in message
+                    "wrong version number" in message
+                    or "unknown protocol" in message
+                    or "record layer failure" in message
                 )
 
             # Try to detect a common user error with proxies which is to
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-311.pyc
index 4cac816..45104c2 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/_appengine_environ.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/_appengine_environ.cpython-311.pyc
index 4c689d1..b868b3a 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/_appengine_environ.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/_appengine_environ.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-311.pyc
index f7cbf93..87fcbd6 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/ntlmpool.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/ntlmpool.cpython-311.pyc
index 1257d11..e95bf31 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/ntlmpool.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/ntlmpool.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/pyopenssl.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/pyopenssl.cpython-311.pyc
index ea04ade..dfa0d99 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/pyopenssl.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/pyopenssl.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/securetransport.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/securetransport.cpython-311.pyc
index c94f562..28e72fe 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/securetransport.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/securetransport.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/socks.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/socks.cpython-311.pyc
index cbf52e5..06943e6 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/socks.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/socks.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/__init__.cpython-311.pyc
index 0dee7ff..d6fdfa6 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-311.pyc
index 1b59091..34a832f 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/low_level.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/low_level.cpython-311.pyc
index d38e59b..dd25e2e 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/low_level.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/low_level.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-311.pyc
index 7334167..7569cca 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/packages/__pycache__/six.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/packages/__pycache__/six.cpython-311.pyc
index 2772986..f4a0aee 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/packages/__pycache__/six.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/packages/__pycache__/six.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/__init__.cpython-311.pyc
index b2d5a21..1df12a5 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/makefile.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/makefile.cpython-311.pyc
index 1e19900..688fbbe 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/makefile.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/makefile.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/weakref_finalize.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/weakref_finalize.cpython-311.pyc
index f08aae1..33f92ab 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/weakref_finalize.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/weakref_finalize.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/__init__.cpython-311.pyc
index 60312ff..d40e901 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/__init__.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/__init__.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/connection.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/connection.cpython-311.pyc
index cf26969..6068c07 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/connection.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/connection.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/proxy.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/proxy.cpython-311.pyc
index b64e4cc..5ab1ec7 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/proxy.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/proxy.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/queue.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/queue.cpython-311.pyc
index 6ac222d..6e31001 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/queue.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/queue.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/request.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/request.cpython-311.pyc
index c9708a6..ea19b1e 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/request.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/request.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/response.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/response.cpython-311.pyc
index 2ad9212..df6a3b4 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/response.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/response.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/retry.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/retry.cpython-311.pyc
index f333792..4e02e6b 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/retry.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/retry.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-311.pyc
index 60f121a..3936e20 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_match_hostname.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_match_hostname.cpython-311.pyc
index 6856a9f..e755f8d 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_match_hostname.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_match_hostname.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssltransport.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssltransport.cpython-311.pyc
index 0a335b5..48dca78 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssltransport.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssltransport.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/timeout.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/timeout.cpython-311.pyc
index 1db7f20..cb92a85 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/timeout.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/timeout.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/url.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/url.cpython-311.pyc
index 8b02ced..42b5197 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/url.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/url.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/wait.cpython-311.pyc b/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/wait.cpython-311.pyc
index e0c7745..5deb41b 100644
Binary files a/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/wait.cpython-311.pyc and b/venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/wait.cpython-311.pyc differ
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/util/retry.py b/venv/Lib/site-packages/pip/_vendor/urllib3/util/retry.py
index 60ef6c4..9a1e90d 100644
--- a/venv/Lib/site-packages/pip/_vendor/urllib3/util/retry.py
+++ b/venv/Lib/site-packages/pip/_vendor/urllib3/util/retry.py
@@ -235,7 +235,9 @@ class Retry(object):
     RETRY_AFTER_STATUS_CODES = frozenset([413, 429, 503])
 
     #: Default headers to be used for ``remove_headers_on_redirect``
-    DEFAULT_REMOVE_HEADERS_ON_REDIRECT = frozenset(["Cookie", "Authorization"])
+    DEFAULT_REMOVE_HEADERS_ON_REDIRECT = frozenset(
+        ["Cookie", "Authorization", "Proxy-Authorization"]
+    )
 
     #: Maximum backoff time.
     DEFAULT_BACKOFF_MAX = 120
diff --git a/venv/Lib/site-packages/pip/_vendor/urllib3/util/ssl_.py b/venv/Lib/site-packages/pip/_vendor/urllib3/util/ssl_.py
index 2b45d39..0a6a0e0 100644
--- a/venv/Lib/site-packages/pip/_vendor/urllib3/util/ssl_.py
+++ b/venv/Lib/site-packages/pip/_vendor/urllib3/util/ssl_.py
@@ -1,11 +1,11 @@
 from __future__ import absolute_import
 
+import hashlib
 import hmac
 import os
 import sys
 import warnings
 from binascii import hexlify, unhexlify
-from hashlib import md5, sha1, sha256
 
 from ..exceptions import (
     InsecurePlatformWarning,
@@ -24,7 +24,10 @@
 ALPN_PROTOCOLS = ["http/1.1"]
 
 # Maps the length of a digest to a possible hash function producing this digest
-HASHFUNC_MAP = {32: md5, 40: sha1, 64: sha256}
+HASHFUNC_MAP = {
+    length: getattr(hashlib, algorithm, None)
+    for length, algorithm in ((32, "md5"), (40, "sha1"), (64, "sha256"))
+}
 
 
 def _const_compare_digest_backport(a, b):
@@ -191,9 +194,15 @@ def assert_fingerprint(cert, fingerprint):
 
     fingerprint = fingerprint.replace(":", "").lower()
     digest_length = len(fingerprint)
-    hashfunc = HASHFUNC_MAP.get(digest_length)
-    if not hashfunc:
+    if digest_length not in HASHFUNC_MAP:
         raise SSLError("Fingerprint of invalid length: {0}".format(fingerprint))
+    hashfunc = HASHFUNC_MAP.get(digest_length)
+    if hashfunc is None:
+        raise SSLError(
+            "Hash function implementation unavailable for fingerprint length: {0}".format(
+                digest_length
+            )
+        )
 
     # We need encode() here for py32; works on py2 and p33.
     fingerprint_bytes = unhexlify(fingerprint.encode())
diff --git a/venv/Lib/site-packages/pip/_vendor/vendor.txt b/venv/Lib/site-packages/pip/_vendor/vendor.txt
index fd92690..2ba053a 100644
--- a/venv/Lib/site-packages/pip/_vendor/vendor.txt
+++ b/venv/Lib/site-packages/pip/_vendor/vendor.txt
@@ -1,18 +1,18 @@
 CacheControl==0.14.0
-distlib==0.3.8
+distlib==0.3.9
 distro==1.9.0
 msgpack==1.0.8
 packaging==24.1
 platformdirs==4.2.2
 pyproject-hooks==1.0.0
 requests==2.32.3
-    certifi==2024.7.4
+    certifi==2024.8.30
     idna==3.7
-    urllib3==1.26.18
+    urllib3==1.26.20
 rich==13.7.1
     pygments==2.18.0
     typing_extensions==4.12.2
 resolvelib==1.0.1
 setuptools==70.3.0
 tomli==2.0.1
-truststore==0.9.1
+truststore==0.10.0
diff --git a/venv/Lib/site-packages/pyinstaller-6.11.1.dist-info/COPYING.txt b/venv/Lib/site-packages/pyinstaller-6.11.1.dist-info/COPYING.txt
new file mode 100644
index 0000000..51bf4bd
--- /dev/null
+++ b/venv/Lib/site-packages/pyinstaller-6.11.1.dist-info/COPYING.txt
@@ -0,0 +1,636 @@
+================================
+ The PyInstaller licensing terms
+================================
+ 
+
+Copyright (c) 2010-2023, PyInstaller Development Team
+Copyright (c) 2005-2009, Giovanni Bajo
+Based on previous work under copyright (c) 2002 McMillan Enterprises, Inc.
+
+
+PyInstaller is licensed under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+
+Bootloader Exception
+--------------------
+
+In addition to the permissions in the GNU General Public License, the
+authors give you unlimited permission to link or embed compiled bootloader
+and related files into combinations with other programs, and to distribute
+those combinations without any restriction coming from the use of those
+files. (The General Public License restrictions do apply in other respects;
+for example, they cover modification of the files, and distribution when
+not linked into a combined executable.)
+ 
+ 
+Bootloader and Related Files
+----------------------------
+
+Bootloader and related files are files which are embedded within the
+final executable. This includes files in directories:
+
+./bootloader/
+./PyInstaller/loader
+
+
+Run-time Hooks
+----------------------------
+
+Run-time Hooks are a different kind of files embedded within the final
+executable. To ease moving them into a separate repository, or into the
+respective project, these files are now licensed under the Apache License,
+Version 2.0.
+
+Run-time Hooks are in the directory
+./PyInstaller/hooks/rthooks
+
+
+The PyInstaller.isolated submodule
+----------------------------------
+
+By request, the PyInstaller.isolated submodule and its corresponding tests are
+additionally licensed with the MIT license so that it may be reused outside of
+PyInstaller under GPL 2.0 or MIT terms and conditions -- whichever is the most
+suitable to the recipient downstream project. Affected files/directories are:
+
+./PyInstaller/isolated/
+./tests/unit/test_isolation.py
+
+
+About the PyInstaller Development Team
+--------------------------------------
+
+The PyInstaller Development Team is the set of contributors
+to the PyInstaller project. A full list with details is kept
+in the documentation directory, in the file
+``doc/CREDITS.rst``.
+
+The core team that coordinates development on GitHub can be found here:
+https://github.com/pyinstaller/pyinstaller.  As of 2021, it consists of:
+
+* Hartmut Goebel
+* Jasper Harrison
+* Bryan Jones
+* Brenainn Woodsend
+* Rok Mandeljc
+
+Our Copyright Policy
+--------------------
+
+PyInstaller uses a shared copyright model. Each contributor maintains copyright
+over their contributions to PyInstaller. But, it is important to note that these
+contributions are typically only changes to the repositories. Thus,
+the PyInstaller source code, in its entirety is not the copyright of any single
+person or institution.  Instead, it is the collective copyright of the entire
+PyInstaller Development Team.  If individual contributors want to maintain
+a record of what changes/contributions they have specific copyright on, they
+should indicate their copyright in the commit message of the change, when they
+commit the change to the PyInstaller repository.
+
+With this in mind, the following banner should be used in any source code file
+to indicate the copyright and license terms:
+
+
+#-----------------------------------------------------------------------------
+# 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)
+#-----------------------------------------------------------------------------
+
+
+For run-time hooks, the following banner should be used:
+
+#-----------------------------------------------------------------------------
+# 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
+#-----------------------------------------------------------------------------
+
+
+================================
+GNU General Public License
+================================
+
+https://gnu.org/licenses/gpl-2.0.html
+
+
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+================================
+Apache License 2.0
+================================
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+===========
+MIT License
+===========
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/venv/Lib/site-packages/pyinstaller-6.11.1.dist-info/INSTALLER b/venv/Lib/site-packages/pyinstaller-6.11.1.dist-info/INSTALLER
new file mode 100644
index 0000000..a1b589e
--- /dev/null
+++ b/venv/Lib/site-packages/pyinstaller-6.11.1.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/venv/Lib/site-packages/pyinstaller-6.11.1.dist-info/METADATA b/venv/Lib/site-packages/pyinstaller-6.11.1.dist-info/METADATA
new file mode 100644
index 0000000..cb80d87
--- /dev/null
+++ b/venv/Lib/site-packages/pyinstaller-6.11.1.dist-info/METADATA
@@ -0,0 +1,209 @@
+Metadata-Version: 2.1
+Name: pyinstaller
+Version: 6.11.1
+Summary: PyInstaller bundles a Python application and all its dependencies into a single package.
+Home-page: https://www.pyinstaller.org/
+Author: Hartmut Goebel, Giovanni Bajo, David Vierra, David Cortesi, Martin Zibricky
+License: GPLv2-or-later with a special exception which allows to use PyInstaller to build and distribute non-free programs (including commercial ones)
+Project-URL: Source, https://github.com/pyinstaller/pyinstaller
+Keywords: packaging, app, apps, bundle, convert, standalone, executable,pyinstaller, cxfreeze, freeze, py2exe, py2app, bbfreeze
+Classifier: Development Status :: 6 - Mature
+Classifier: Environment :: Console
+Classifier: Intended Audience :: Developers
+Classifier: Intended Audience :: Other Audience
+Classifier: Intended Audience :: System Administrators
+Classifier: License :: OSI Approved :: GNU General Public License v2 (GPLv2)
+Classifier: Natural Language :: English
+Classifier: Operating System :: MacOS :: MacOS X
+Classifier: Operating System :: Microsoft :: Windows
+Classifier: Operating System :: POSIX
+Classifier: Operating System :: POSIX :: AIX
+Classifier: Operating System :: POSIX :: BSD
+Classifier: Operating System :: POSIX :: Linux
+Classifier: Operating System :: POSIX :: SunOS/Solaris
+Classifier: Programming Language :: C
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3 :: Only
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
+Classifier: Programming Language :: Python :: 3.10
+Classifier: Programming Language :: Python :: 3.11
+Classifier: Programming Language :: Python :: 3.12
+Classifier: Programming Language :: Python :: 3.13
+Classifier: Programming Language :: Python :: Implementation :: CPython
+Classifier: Topic :: Software Development
+Classifier: Topic :: Software Development :: Build Tools
+Classifier: Topic :: Software Development :: Interpreters
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Classifier: Topic :: System :: Installation/Setup
+Classifier: Topic :: System :: Software Distribution
+Classifier: Topic :: Utilities
+Requires-Python: <3.14,>=3.8
+Description-Content-Type: text/x-rst
+License-File: COPYING.txt
+Requires-Dist: setuptools>=42.0.0
+Requires-Dist: altgraph
+Requires-Dist: pyinstaller-hooks-contrib>=2024.9
+Requires-Dist: packaging>=22.0
+Requires-Dist: importlib-metadata>=4.6; python_version < "3.10"
+Requires-Dist: macholib>=1.8; sys_platform == "darwin"
+Requires-Dist: pefile!=2024.8.26,>=2022.5.30; sys_platform == "win32"
+Requires-Dist: pywin32-ctypes>=0.2.1; sys_platform == "win32"
+Provides-Extra: completion
+Requires-Dist: argcomplete; extra == "completion"
+Provides-Extra: hook_testing
+Requires-Dist: pytest>=2.7.3; extra == "hook-testing"
+Requires-Dist: execnet>=1.5.0; extra == "hook-testing"
+Requires-Dist: psutil; extra == "hook-testing"
+
+PyInstaller Overview
+====================
+
+.. image:: https://img.shields.io/pypi/v/pyinstaller
+   :alt: PyPI
+   :target: https://pypi.org/project/pyinstaller
+.. image:: https://img.shields.io/pypi/pyversions/pyinstaller
+   :alt: PyPI - Python Version
+   :target: https://pypi.org/project/pyinstaller
+.. image:: https://img.shields.io/readthedocs/pyinstaller/stable
+   :alt: Read the Docs (version)
+   :target: https://pyinstaller.org
+.. image:: https://img.shields.io/pypi/dm/pyinstaller
+   :alt: PyPI - Downloads
+   :target: https://pypistats.org/packages/pyinstaller
+
+
+PyInstaller bundles a Python application and all its dependencies into a single
+package. The user can run the packaged app without installing a Python
+interpreter or any modules.
+
+:Documentation: https://pyinstaller.org/
+:Code:          https://github.com/pyinstaller/pyinstaller
+
+PyInstaller reads a Python script written by you. It analyzes your code
+to discover every other module and library your script needs in order to
+execute. Then it collects copies of all those files -- including the active
+Python interpreter! -- and puts them with your script in a single folder, or
+optionally in a single executable file.
+
+
+PyInstaller is tested against Windows, macOS, and GNU/Linux.
+However, it is not a cross-compiler:
+to make a Windows app you run PyInstaller in Windows; to make
+a GNU/Linux app you run it in GNU/Linux, etc.
+PyInstaller has been used successfully
+with AIX, Solaris, FreeBSD and OpenBSD,
+but is not tested against them as part of the continuous integration tests.
+
+
+Main Advantages
+---------------
+
+- Works out-of-the-box with any Python version 3.8-3.13.
+- Fully multi-platform, and uses the OS support to load the dynamic libraries,
+  thus ensuring full compatibility.
+- Correctly bundles the major Python packages such as numpy, PyQt5,
+  PySide2, PyQt6, PySide6, wxPython, matplotlib and others out-of-the-box.
+- Compatible with many 3rd-party packages out-of-the-box. (All the required
+  tricks to make external packages work are already integrated.)
+- Works with code signing on macOS.
+- Bundles MS Visual C++ DLLs on Windows.
+
+
+Installation
+------------
+
+PyInstaller is available on PyPI. You can install it through `pip`:
+
+.. code:: bash
+
+      pip install pyinstaller
+
+
+Requirements and Tested Platforms
+---------------------------------
+
+- Python:
+    - 3.8-3.13. Note that Python 3.10.0 contains a bug making it unsupportable by
+      PyInstaller. PyInstaller will also not work with beta releases of Python
+      3.14.
+- Windows (32bit/64bit/ARM64):
+    - PyInstaller should work on Windows 7 or newer, but we only officially support Windows 8+.
+    - Support for Python installed from the Windows store without using virtual
+      environments requires PyInstaller 4.4 or later.
+- Linux:
+    - GNU libc based distributions on architectures ``x86_64``, ``aarch64``,
+      ``i686``, ``ppc64le``, ``s390x``.
+    - musl libc based distributions on architectures ``x86_64``, ``aarch64``.
+    - ldd: Console application to print the shared libraries required
+      by each program or shared library. This typically can be found in
+      the distribution-package `glibc` or `libc-bin`.
+    - objdump: Console application to display information from
+      object files. This typically can be found in the
+      distribution-package `binutils`.
+    - objcopy: Console application to copy and translate object files.
+      This typically can be found in the distribution-package `binutils`,
+      too.
+    - Raspberry Pi users on ``armv5``-``armv7`` should `add piwheels as an extra
+      index url `_ then ``pip install pyinstaller``
+      as usual.
+- macOS (``x86_64`` or ``arm64``):
+    - macOS 10.15 (Catalina) or newer.
+    - Supports building ``universal2`` applications provided that your installation
+      of Python and all your dependencies are also compiled ``universal2``.
+
+
+Usage
+-----
+
+Basic usage is very simple, just run it against your main script:
+
+.. code:: bash
+
+      pyinstaller /path/to/yourscript.py
+
+For more details, see the `manual`_.
+
+
+Untested Platforms
+------------------
+
+The following platforms have been contributed and any feedback or
+enhancements on these are welcome.
+
+- FreeBSD
+    - ldd
+- Solaris
+    - ldd
+    - objdump
+- AIX
+    - AIX 6.1 or newer. PyInstaller will not work with statically
+      linked Python libraries.
+    - ldd
+- Linux on any other libc implementation/architecture combination not listed
+  above.
+
+Before using any contributed platform, you need to build the PyInstaller
+bootloader. This will happen automatically when you ``pip install
+pyinstaller`` provided that you have an appropriate C compiler (typically
+either ``gcc`` or ``clang``) and zlib's development headers already installed.
+
+
+Support
+-------
+
+- Official debugging guide: https://pyinstaller.org/en/v6.11.1/when-things-go-wrong.html
+- Assorted user contributed help topics: https://github.com/pyinstaller/pyinstaller/wiki
+- Web based Q&A forums: https://github.com/pyinstaller/pyinstaller/discussions
+- Email based Q&A forums: https://groups.google.com/g/pyinstaller
+
+
+Changes in this Release
+-----------------------
+
+You can find a detailed list of changes in this release
+in the `Changelog`_ section of the manual.
+
+.. _`manual`: https://pyinstaller.org/en/v6.11.1/
+.. _`Changelog`: https://pyinstaller.org/en/v6.11.1/CHANGES.html
diff --git a/venv/Lib/site-packages/pyinstaller-6.11.1.dist-info/RECORD b/venv/Lib/site-packages/pyinstaller-6.11.1.dist-info/RECORD
new file mode 100644
index 0000000..1663fc3
--- /dev/null
+++ b/venv/Lib/site-packages/pyinstaller-6.11.1.dist-info/RECORD
@@ -0,0 +1,1084 @@
+../../Scripts/pyi-archive_viewer.exe,sha256=oDvoAOwCUJeOxypF8gkX8z5lomiRuEw-sFI_UlRzXL8,108426
+../../Scripts/pyi-bindepend.exe,sha256=cKIGsPJBWGdL8w-Ie3pRHyoAVWvz6GnOPEuVwJ20Cvc,108421
+../../Scripts/pyi-grab_version.exe,sha256=q8kSUnOqJm_JG8aHDPVDjTw2lx2mXKsr9YTYTOTUuP8,108424
+../../Scripts/pyi-makespec.exe,sha256=3Tf0HI2_hQmu_GeicesQrbYGxzstyXoYTWGEwF-UiuM,108420
+../../Scripts/pyi-set_version.exe,sha256=HDgBqqYF1vmzkNLg24Hc76wAUXIWrESPN0lO8ndxee0,108423
+../../Scripts/pyinstaller.exe,sha256=BJKWWZXt2PtqA_Xzo1fYQasd8YDEXA3R6CZGvi9xQ_w,108437
+PyInstaller/__init__.py,sha256=_UJQvP5QN8xLoghFxceNLTkSuqDcP8mGWJmGXb7IJIU,2012
+PyInstaller/__main__.py,sha256=R-Cs40eMwBX7HNmcON77T1D-_GDRbUE9KJSdINxDUVk,12622
+PyInstaller/__pycache__/__init__.cpython-311.pyc,,
+PyInstaller/__pycache__/__main__.cpython-311.pyc,,
+PyInstaller/__pycache__/_recursion_too_deep_message.cpython-311.pyc,,
+PyInstaller/__pycache__/_shared_with_waf.cpython-311.pyc,,
+PyInstaller/__pycache__/compat.cpython-311.pyc,,
+PyInstaller/__pycache__/config.cpython-311.pyc,,
+PyInstaller/__pycache__/configure.cpython-311.pyc,,
+PyInstaller/__pycache__/exceptions.cpython-311.pyc,,
+PyInstaller/__pycache__/log.cpython-311.pyc,,
+PyInstaller/_recursion_too_deep_message.py,sha256=Nq51eGfSfiU_CKYk7nAvz591LHiLsmY4KVEK5Lr-HUQ,1820
+PyInstaller/_shared_with_waf.py,sha256=5geAGNdLJU4sGTdqXXoPmOudxqE1H0qz5xiXLT4RqiY,3911
+PyInstaller/archive/__init__.py,sha256=fNGhsx0m5s9iq4yMvH6J1tI0vzUKWd62lIQNSnKTGCE,22
+PyInstaller/archive/__pycache__/__init__.cpython-311.pyc,,
+PyInstaller/archive/__pycache__/pyz_crypto.cpython-311.pyc,,
+PyInstaller/archive/__pycache__/readers.cpython-311.pyc,,
+PyInstaller/archive/__pycache__/writers.cpython-311.pyc,,
+PyInstaller/archive/pyz_crypto.py,sha256=9SsKY26cVDwVxlwD-6LSC0Pw3rsIoOhV-A6Y6s9IPBI,747
+PyInstaller/archive/readers.py,sha256=cc8-Av88NhfgZjkgv5JM3DFNyTpNjQT0G7oqKS2Z7d0,7981
+PyInstaller/archive/writers.py,sha256=70Irw1wlqFptNhYVpjSI-NiF3sHxHp8D-P3HY5PrivQ,18482
+PyInstaller/bootloader/Windows-64bit-intel/run.exe,sha256=KERtUJun0U-c9roJINp92B-bBu4JGid-TpntzHLXf00,268800
+PyInstaller/bootloader/Windows-64bit-intel/run_d.exe,sha256=WF9J8rE5qXtH11uGzR5QCK4VEy3mHKqET7aUCYfLlhI,285184
+PyInstaller/bootloader/Windows-64bit-intel/runw.exe,sha256=YcXE4_oQt55hfNdHf2OEIKbHhW-ecTYUrCS-F7KlO_E,264704
+PyInstaller/bootloader/Windows-64bit-intel/runw_d.exe,sha256=9qdxjRbi2QxJi5XqhudMsG2zg-qU8iWsO0ESgf84gVY,280576
+PyInstaller/bootloader/images/icon-console.ico,sha256=aALW1IOexhlTRN7sYcLc9gIWH52Xsk9ic3kEaehHets,59521
+PyInstaller/bootloader/images/icon-windowed.ico,sha256=Fo2xuKfGL6KrksEhAYXRRZI_McG-I_3tQtlCD0i5g5I,60690
+PyInstaller/building/__init__.py,sha256=MsSFjiLMLJZ7QhUPpVBWKiyDnCzryquRyr329NoCACI,2
+PyInstaller/building/__pycache__/__init__.cpython-311.pyc,,
+PyInstaller/building/__pycache__/api.cpython-311.pyc,,
+PyInstaller/building/__pycache__/build_main.cpython-311.pyc,,
+PyInstaller/building/__pycache__/datastruct.cpython-311.pyc,,
+PyInstaller/building/__pycache__/icon.cpython-311.pyc,,
+PyInstaller/building/__pycache__/makespec.cpython-311.pyc,,
+PyInstaller/building/__pycache__/osx.cpython-311.pyc,,
+PyInstaller/building/__pycache__/splash.cpython-311.pyc,,
+PyInstaller/building/__pycache__/splash_templates.cpython-311.pyc,,
+PyInstaller/building/__pycache__/templates.cpython-311.pyc,,
+PyInstaller/building/__pycache__/utils.cpython-311.pyc,,
+PyInstaller/building/api.py,sha256=H0Ra3qiJz34Ut2VBdUZXBejklzpqRinFU0Tu2syAuVA,66821
+PyInstaller/building/build_main.py,sha256=E3cWXqzx5O2QxiFh_v7bL_g-ePfZ9inaSyQYhupbhGE,60347
+PyInstaller/building/datastruct.py,sha256=AGQQTL4cfQIApxl_vD5LRpl5nHpEcCN5El3u89jkRmU,17435
+PyInstaller/building/icon.py,sha256=BMyohNvNi-Zp1hbC0i9wExyxoa9QMP_7wfQqBOnauYg,4015
+PyInstaller/building/makespec.py,sha256=ebBQVs5aeNTbVbqGkCpdf4T3z1GfMMSyFfzGszODji8,35831
+PyInstaller/building/osx.py,sha256=16Ns1uwNfMAxMYpM_T_41X4lJzV_b1aryj68lwgAepg,41582
+PyInstaller/building/splash.py,sha256=O0IB8L1TBV2qYV6PVwwLWxm5zjCNzmz4Q07ciUnsj10,21256
+PyInstaller/building/splash_templates.py,sha256=VmtOwhx6B37ufbvbTC74uADLpWEFpev-qjnFNJlpdIE,7453
+PyInstaller/building/templates.py,sha256=T64VeVrybxnFVL-m4OmoVgmbmGsgBmz-GltBSLu-YWg,3146
+PyInstaller/building/utils.py,sha256=bkR08pYHLjH9XHVQHMpwDJ4b_mnyhqhkuk_alqHOkDI,36047
+PyInstaller/compat.py,sha256=nAohhzm_0gYmkzd7VgeJ4K49z-HBwRPZuZj4MDooDsw,31996
+PyInstaller/config.py,sha256=7GMtLgwDTZwcG2pwY6jUEtCQbLA7K_5hauTvbGdQ5Eo,1852
+PyInstaller/configure.py,sha256=cy15xry6JclyWqGfhTPtsCgJXfRA8Qp7CMGTgHZYeFA,4160
+PyInstaller/depend/__init__.py,sha256=MsSFjiLMLJZ7QhUPpVBWKiyDnCzryquRyr329NoCACI,2
+PyInstaller/depend/__pycache__/__init__.cpython-311.pyc,,
+PyInstaller/depend/__pycache__/analysis.cpython-311.pyc,,
+PyInstaller/depend/__pycache__/bindepend.cpython-311.pyc,,
+PyInstaller/depend/__pycache__/bytecode.cpython-311.pyc,,
+PyInstaller/depend/__pycache__/dylib.cpython-311.pyc,,
+PyInstaller/depend/__pycache__/imphook.cpython-311.pyc,,
+PyInstaller/depend/__pycache__/imphookapi.cpython-311.pyc,,
+PyInstaller/depend/__pycache__/utils.cpython-311.pyc,,
+PyInstaller/depend/analysis.py,sha256=H7Yq-GO1_SB5GsfB_b1s8jcCX3aPKYfWcdSk4nd929g,50232
+PyInstaller/depend/bindepend.py,sha256=RNBSqVDnstKrSuVwKqYyBKvO_qPbBJzYE0E6UXpw0Z4,42827
+PyInstaller/depend/bytecode.py,sha256=PDKfJwaP6wQ0Ol6ERfGUOls2SeUFWpP46UlIsl19EyE,13702
+PyInstaller/depend/dylib.py,sha256=voLoU6LMK3WhsjaY7xMyEAqKaAdw8uY4kEnn9FPZTJA,12716
+PyInstaller/depend/imphook.py,sha256=LRcdRjQmQcTjBcq_zsuhg4T506f_j5jHawRMrIIEsdo,27568
+PyInstaller/depend/imphookapi.py,sha256=gDEoXiyUuo6AkDq8USwwwurY8fHNQhVcO0QQiiz6J9I,21234
+PyInstaller/depend/utils.py,sha256=qeHsmfLdlRQmKOpM3hchlezeYChHa2iq4CEdmplQD7A,16939
+PyInstaller/exceptions.py,sha256=8GDeuIYYbmZdaxDE356uG6v5EEnxyA7Fihuja_7t4g4,3001
+PyInstaller/fake-modules/__pycache__/pyi_splash.cpython-311.pyc,,
+PyInstaller/fake-modules/_pyi_rth_utils/__init__.py,sha256=eB5Dwu9lqSMqbLtIXpkYUaU7dEiymGkij-MOIDO9ZdI,1710
+PyInstaller/fake-modules/_pyi_rth_utils/__pycache__/__init__.cpython-311.pyc,,
+PyInstaller/fake-modules/_pyi_rth_utils/__pycache__/_win32.cpython-311.pyc,,
+PyInstaller/fake-modules/_pyi_rth_utils/__pycache__/qt.cpython-311.pyc,,
+PyInstaller/fake-modules/_pyi_rth_utils/__pycache__/tempfile.cpython-311.pyc,,
+PyInstaller/fake-modules/_pyi_rth_utils/_win32.py,sha256=8DO_CZTynydjJJmIHCgvvjBpjc46MN5bg0dOkQsIX1M,11564
+PyInstaller/fake-modules/_pyi_rth_utils/qt.py,sha256=24b7dxj7GQQiXeFuYm74TQBDUCGnEdREuQhyvEKAepM,4204
+PyInstaller/fake-modules/_pyi_rth_utils/tempfile.py,sha256=xU--svg9lzC2Aj6dTrQMCh2Zek4-eN1sLrRjKpoEct0,2262
+PyInstaller/fake-modules/pyi_splash.py,sha256=uHOBvS9elRsxhCypWsG_KxB0NmQu6U1gxMLNMa-4_A8,7703
+PyInstaller/hooks/__init__.py,sha256=MsSFjiLMLJZ7QhUPpVBWKiyDnCzryquRyr329NoCACI,2
+PyInstaller/hooks/__pycache__/__init__.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PIL.Image.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PIL.ImageFilter.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PIL.SpiderImagePlugin.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PIL.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QAxContainer.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.Qsci.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.Qt.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.Qt3DAnimation.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.Qt3DCore.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.Qt3DExtras.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.Qt3DInput.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.Qt3DLogic.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.Qt3DRender.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtBluetooth.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtChart.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtCore.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtDBus.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtDataVisualization.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtDesigner.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtGui.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtHelp.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtLocation.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtMacExtras.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtMultimedia.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtMultimediaWidgets.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtNetwork.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtNetworkAuth.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtNfc.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtOpenGL.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtPositioning.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtPrintSupport.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtPurchasing.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtQml.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtQuick.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtQuick3D.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtQuickWidgets.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtRemoteObjects.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtScript.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtSensors.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtSerialPort.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtSql.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtSvg.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtTest.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtTextToSpeech.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtWebChannel.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtWebEngine.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtWebEngineCore.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtWebEngineWidgets.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtWebKit.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtWebKitWidgets.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtWebSockets.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtWidgets.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtWinExtras.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtX11Extras.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtXml.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.QtXmlPatterns.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt5.uic.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QAxContainer.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.Qsci.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.Qt3DAnimation.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.Qt3DCore.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.Qt3DExtras.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.Qt3DInput.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.Qt3DLogic.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.Qt3DRender.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtBluetooth.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtCharts.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtCore.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtDBus.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtDataVisualization.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtDesigner.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtGui.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtHelp.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtMultimedia.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtMultimediaWidgets.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtNetwork.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtNetworkAuth.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtNfc.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtOpenGL.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtOpenGLWidgets.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtPdf.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtPdfWidgets.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtPositioning.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtPrintSupport.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtQml.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtQuick.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtQuick3D.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtQuickWidgets.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtRemoteObjects.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtSensors.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtSerialPort.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtSpatialAudio.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtSql.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtSvg.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtSvgWidgets.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtTest.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtTextToSpeech.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtWebChannel.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtWebEngineCore.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtWebEngineQuick.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtWebEngineWidgets.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtWebSockets.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtWidgets.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.QtXml.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PyQt6.uic.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.Qt3DAnimation.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.Qt3DCore.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.Qt3DExtras.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.Qt3DInput.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.Qt3DLogic.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.Qt3DRender.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtAxContainer.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtCharts.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtConcurrent.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtCore.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtDataVisualization.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtGui.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtHelp.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtLocation.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtMacExtras.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtMultimedia.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtMultimediaWidgets.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtNetwork.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtOpenGL.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtOpenGLFunctions.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtPositioning.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtPrintSupport.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtQml.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtQuick.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtQuickControls2.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtQuickWidgets.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtRemoteObjects.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtScript.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtScriptTools.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtScxml.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtSensors.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtSerialPort.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtSql.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtSvg.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtTest.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtTextToSpeech.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtUiTools.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtWebChannel.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtWebEngine.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtWebEngineCore.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtWebEngineWidgets.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtWebKit.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtWebKitWidgets.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtWebSockets.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtWidgets.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtWinExtras.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtX11Extras.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtXml.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.QtXmlPatterns.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.Qwt5.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide2.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.Qt3DAnimation.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.Qt3DCore.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.Qt3DExtras.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.Qt3DInput.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.Qt3DLogic.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.Qt3DRender.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtAxContainer.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtBluetooth.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtCharts.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtConcurrent.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtCore.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtDBus.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtDataVisualization.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtDesigner.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtGraphs.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtGraphsWidgets.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtGui.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtHelp.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtHttpServer.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtLocation.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtMultimedia.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtMultimediaWidgets.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtNetwork.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtNetworkAuth.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtNfc.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtOpenGL.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtOpenGLWidgets.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtPdf.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtPdfWidgets.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtPositioning.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtPrintSupport.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtQml.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtQuick.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtQuick3D.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtQuickControls2.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtQuickWidgets.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtRemoteObjects.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtScxml.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtSensors.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtSerialBus.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtSerialPort.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtSpatialAudio.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtSql.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtStateMachine.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtSvg.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtSvgWidgets.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtTest.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtTextToSpeech.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtUiTools.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtWebChannel.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtWebEngineCore.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtWebEngineQuick.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtWebEngineWidgets.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtWebSockets.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtWidgets.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.QtXml.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-PySide6.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-_pyi_rth_utils.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-_tkinter.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-babel.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-difflib.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-distutils.command.check.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-distutils.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-distutils.util.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-django.contrib.sessions.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-django.core.cache.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-django.core.mail.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-django.core.management.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-django.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-django.db.backends.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-django.db.backends.mysql.base.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-django.db.backends.oracle.base.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-django.template.loaders.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-encodings.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gevent.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.Adw.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.AppIndicator3.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.Atk.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.AyatanaAppIndicator3.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.Champlain.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.Clutter.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.DBus.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GIRepository.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GLib.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GModule.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GObject.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.Gdk.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GdkPixbuf.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.Gio.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.Graphene.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.Gsk.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.Gst.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GstAllocators.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GstApp.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GstAudio.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GstBadAudio.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GstBase.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GstCheck.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GstCodecs.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GstController.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GstGL.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GstGLEGL.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GstGLWayland.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GstGLX11.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GstInsertBin.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GstMpegts.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GstNet.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GstPbutils.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GstPlay.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GstPlayer.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GstRtp.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GstRtsp.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GstRtspServer.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GstSdp.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GstTag.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GstTranscoder.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GstVideo.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GstVulkan.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GstVulkanWayland.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GstVulkanXCB.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GstWebRTC.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.Gtk.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GtkChamplain.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GtkClutter.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GtkSource.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.GtkosxApplication.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.HarfBuzz.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.Pango.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.PangoCairo.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.cairo.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.freetype2.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-gi.repository.xlib.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-heapq.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-idlelib.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-importlib_metadata.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-importlib_resources.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-keyring.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-kivy.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-lib2to3.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-matplotlib.backend_bases.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-matplotlib.backends.backend_qtagg.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-matplotlib.backends.backend_qtcairo.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-matplotlib.backends.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-matplotlib.backends.qt_compat.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-matplotlib.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-matplotlib.numerix.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-matplotlib.pyplot.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-multiprocessing.util.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-numpy.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-packaging.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-pandas.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-pandas.io.clipboard.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-pandas.io.formats.style.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-pandas.plotting.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-pickle.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-pkg_resources.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-platform.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-pygments.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-pytz.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-pytzdata.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-qtawesome.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-qtpy.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-scapy.layers.all.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-scipy.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-scipy.io.matlab.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-scipy.linalg.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-scipy.sparse.csgraph.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-scipy.spatial.transform.rotation.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-scipy.special._ellip_harm_2.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-scipy.special._ufuncs.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-scipy.stats._stats.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-scrapy.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-setuptools._vendor.importlib_metadata.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-setuptools._vendor.jaraco.text.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-setuptools.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-shelve.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-shiboken6.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-sphinx.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-sqlalchemy.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-sqlite3.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-sysconfig.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-wcwidth.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-win32ctypes.core.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-xml.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-xml.dom.domreg.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-xml.etree.cElementTree.cpython-311.pyc,,
+PyInstaller/hooks/__pycache__/hook-zope.interface.cpython-311.pyc,,
+PyInstaller/hooks/hook-PIL.Image.py,sha256=xVqeatL2Pyud1OfdEd_NsBYoWKgJxYndA5zAJUq65Qs,845
+PyInstaller/hooks/hook-PIL.ImageFilter.py,sha256=SzNTo7kh7tRKKovVkCTWvGg6MHzGBTacbqPI-e55gkk,589
+PyInstaller/hooks/hook-PIL.SpiderImagePlugin.py,sha256=RfNA7s9x1Ti__UNR1aFGJbIAilfhyX99q1hDJ7eWwng,773
+PyInstaller/hooks/hook-PIL.py,sha256=iDHOmiCbD_JVYkhIfyILP8RqfhH16iRONpADqoa-q44,1100
+PyInstaller/hooks/hook-PyQt5.QAxContainer.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.Qsci.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.Qt.py,sha256=j0So5QvbWd1q2UpwmxWQSGco770fUEOSnu0kyKAVTvA,1274
+PyInstaller/hooks/hook-PyQt5.Qt3DAnimation.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.Qt3DCore.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.Qt3DExtras.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.Qt3DInput.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.Qt3DLogic.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.Qt3DRender.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtBluetooth.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtChart.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtCore.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtDBus.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtDataVisualization.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtDesigner.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtGui.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtHelp.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtLocation.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtMacExtras.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtMultimedia.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtMultimediaWidgets.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtNetwork.py,sha256=ulfru1n_aKP8t70lPw9mmA1JOUCUVKRuE2udksUzQHQ,710
+PyInstaller/hooks/hook-PyQt5.QtNetworkAuth.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtNfc.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtOpenGL.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtPositioning.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtPrintSupport.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtPurchasing.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtQml.py,sha256=9iBtfG0pUGnSHFAyzJdUaOX6tftELh1iEYE-BF1f3U8,764
+PyInstaller/hooks/hook-PyQt5.QtQuick.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtQuick3D.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtQuickWidgets.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtRemoteObjects.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtScript.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtSensors.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtSerialPort.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtSql.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtSvg.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtTest.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtTextToSpeech.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtWebChannel.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtWebEngine.py,sha256=8v1T1hQOX9jSD3y6rEiwdEOytqqNB7FxGejXbVkDlMU,633
+PyInstaller/hooks/hook-PyQt5.QtWebEngineCore.py,sha256=aZzbd6E_89Ype_7HqLt987AKQsZ81NWsZJhHz9sxBqA,995
+PyInstaller/hooks/hook-PyQt5.QtWebEngineWidgets.py,sha256=8v1T1hQOX9jSD3y6rEiwdEOytqqNB7FxGejXbVkDlMU,633
+PyInstaller/hooks/hook-PyQt5.QtWebKit.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtWebKitWidgets.py,sha256=8v1T1hQOX9jSD3y6rEiwdEOytqqNB7FxGejXbVkDlMU,633
+PyInstaller/hooks/hook-PyQt5.QtWebSockets.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtWidgets.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtWinExtras.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtX11Extras.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtXml.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.QtXmlPatterns.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PyQt5.py,sha256=EJVCGUfy59jwZgAPgRCfKDMU8xA2nTw-jV_881EoTrU,1182
+PyInstaller/hooks/hook-PyQt5.uic.py,sha256=84RPP_83POC6omCwnWObq5ll63SxVoSvwfhX3j_exD4,979
+PyInstaller/hooks/hook-PyQt6.QAxContainer.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PyQt6.Qsci.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PyQt6.Qt3DAnimation.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PyQt6.Qt3DCore.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PyQt6.Qt3DExtras.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PyQt6.Qt3DInput.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PyQt6.Qt3DLogic.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PyQt6.Qt3DRender.py,sha256=oVmMojFOwYquJN_iyTDESJ0nhs4ehshmtt46ud2cu0k,670
+PyInstaller/hooks/hook-PyQt6.QtBluetooth.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PyQt6.QtCharts.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PyQt6.QtCore.py,sha256=2F9qD4YqIZq6DMKRegn7DHvS6Eq3IWkBa5SRie11N-o,633
+PyInstaller/hooks/hook-PyQt6.QtDBus.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PyQt6.QtDataVisualization.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PyQt6.QtDesigner.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PyQt6.QtGui.py,sha256=2F9qD4YqIZq6DMKRegn7DHvS6Eq3IWkBa5SRie11N-o,633
+PyInstaller/hooks/hook-PyQt6.QtHelp.py,sha256=2F9qD4YqIZq6DMKRegn7DHvS6Eq3IWkBa5SRie11N-o,633
+PyInstaller/hooks/hook-PyQt6.QtMultimedia.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PyQt6.QtMultimediaWidgets.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PyQt6.QtNetwork.py,sha256=dgck_Mmop4kEanguw_yXaedNRxzOOuu7bEtZyVYYh-U,710
+PyInstaller/hooks/hook-PyQt6.QtNetworkAuth.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PyQt6.QtNfc.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PyQt6.QtOpenGL.py,sha256=2F9qD4YqIZq6DMKRegn7DHvS6Eq3IWkBa5SRie11N-o,633
+PyInstaller/hooks/hook-PyQt6.QtOpenGLWidgets.py,sha256=2F9qD4YqIZq6DMKRegn7DHvS6Eq3IWkBa5SRie11N-o,633
+PyInstaller/hooks/hook-PyQt6.QtPdf.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PyQt6.QtPdfWidgets.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PyQt6.QtPositioning.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PyQt6.QtPrintSupport.py,sha256=2F9qD4YqIZq6DMKRegn7DHvS6Eq3IWkBa5SRie11N-o,633
+PyInstaller/hooks/hook-PyQt6.QtQml.py,sha256=PLw5WhHb8V0WXXFY69RZLMWIZXwB_lr3mut0AyWmCIw,764
+PyInstaller/hooks/hook-PyQt6.QtQuick.py,sha256=2F9qD4YqIZq6DMKRegn7DHvS6Eq3IWkBa5SRie11N-o,633
+PyInstaller/hooks/hook-PyQt6.QtQuick3D.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PyQt6.QtQuickWidgets.py,sha256=2F9qD4YqIZq6DMKRegn7DHvS6Eq3IWkBa5SRie11N-o,633
+PyInstaller/hooks/hook-PyQt6.QtRemoteObjects.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PyQt6.QtSensors.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PyQt6.QtSerialPort.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PyQt6.QtSpatialAudio.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PyQt6.QtSql.py,sha256=2F9qD4YqIZq6DMKRegn7DHvS6Eq3IWkBa5SRie11N-o,633
+PyInstaller/hooks/hook-PyQt6.QtSvg.py,sha256=2F9qD4YqIZq6DMKRegn7DHvS6Eq3IWkBa5SRie11N-o,633
+PyInstaller/hooks/hook-PyQt6.QtSvgWidgets.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PyQt6.QtTest.py,sha256=2F9qD4YqIZq6DMKRegn7DHvS6Eq3IWkBa5SRie11N-o,633
+PyInstaller/hooks/hook-PyQt6.QtTextToSpeech.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PyQt6.QtWebChannel.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PyQt6.QtWebEngineCore.py,sha256=X9bCUdal9-_Ymhj-Ue3TgWFMyzs2Q4Rdu7D9qqLsipQ,1351
+PyInstaller/hooks/hook-PyQt6.QtWebEngineQuick.py,sha256=cq1LjMw4S_JrC47Ihz1kh7td06JQ1FO_a94J0dJFG94,633
+PyInstaller/hooks/hook-PyQt6.QtWebEngineWidgets.py,sha256=cq1LjMw4S_JrC47Ihz1kh7td06JQ1FO_a94J0dJFG94,633
+PyInstaller/hooks/hook-PyQt6.QtWebSockets.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PyQt6.QtWidgets.py,sha256=2F9qD4YqIZq6DMKRegn7DHvS6Eq3IWkBa5SRie11N-o,633
+PyInstaller/hooks/hook-PyQt6.QtXml.py,sha256=2F9qD4YqIZq6DMKRegn7DHvS6Eq3IWkBa5SRie11N-o,633
+PyInstaller/hooks/hook-PyQt6.py,sha256=9M5liqiED7hrlqRFSJzWn2fgiUjS0-ljCri_lr9PyG0,1025
+PyInstaller/hooks/hook-PyQt6.uic.py,sha256=aqbbDAUty1kOTEHQDKak-N1Yk78pQIXt1LtgLiOw3Sg,979
+PyInstaller/hooks/hook-PySide2.Qt3DAnimation.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.Qt3DCore.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.Qt3DExtras.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.Qt3DInput.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.Qt3DLogic.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.Qt3DRender.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtAxContainer.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtCharts.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtConcurrent.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtCore.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtDataVisualization.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtGui.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtHelp.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtLocation.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtMacExtras.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtMultimedia.py,sha256=DyIsljc-dNhSMZsjyFtouaLp8ZLdhUWQaMeaQQ8cQjY,979
+PyInstaller/hooks/hook-PySide2.QtMultimediaWidgets.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtNetwork.py,sha256=52vtimdyB73bgVxazsQ-VfNnEAj_VDjl9eX0Uk6OVxs,714
+PyInstaller/hooks/hook-PySide2.QtOpenGL.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtOpenGLFunctions.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtPositioning.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtPrintSupport.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtQml.py,sha256=5W2Zr3rpyso-91Hjc28tfRkEYOdulhdwQnOX3uMBBzQ,804
+PyInstaller/hooks/hook-PySide2.QtQuick.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtQuickControls2.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtQuickWidgets.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtRemoteObjects.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtScript.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtScriptTools.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtScxml.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtSensors.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtSerialPort.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtSql.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtSvg.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtTest.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtTextToSpeech.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtUiTools.py,sha256=vK9DFnB41R-Falc9v-vpXr_MvCo719gJfAaYGn_pbAo,710
+PyInstaller/hooks/hook-PySide2.QtWebChannel.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtWebEngine.py,sha256=8v1T1hQOX9jSD3y6rEiwdEOytqqNB7FxGejXbVkDlMU,633
+PyInstaller/hooks/hook-PySide2.QtWebEngineCore.py,sha256=95kMNBhui4wfAOqu0R5P0atuk28qNx76CiglODAnJwQ,1003
+PyInstaller/hooks/hook-PySide2.QtWebEngineWidgets.py,sha256=8v1T1hQOX9jSD3y6rEiwdEOytqqNB7FxGejXbVkDlMU,633
+PyInstaller/hooks/hook-PySide2.QtWebKit.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtWebKitWidgets.py,sha256=8v1T1hQOX9jSD3y6rEiwdEOytqqNB7FxGejXbVkDlMU,633
+PyInstaller/hooks/hook-PySide2.QtWebSockets.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtWidgets.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtWinExtras.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtX11Extras.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtXml.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.QtXmlPatterns.py,sha256=UochHJ51ckZ_syXJyeLM264STUXRCB_RUsv3oCd6g98,633
+PyInstaller/hooks/hook-PySide2.Qwt5.py,sha256=iPZ4IL_gOs0h5pYTjvYHnJCdVCB-sDvpHFpoX-VOh_k,972
+PyInstaller/hooks/hook-PySide2.py,sha256=6vzXvVtUQYJiifknYcvJJdV1ojWoAQJxonYBddpPoiQ,1141
+PyInstaller/hooks/hook-PySide6.Qt3DAnimation.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.Qt3DCore.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.Qt3DExtras.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.Qt3DInput.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.Qt3DLogic.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.Qt3DRender.py,sha256=45jlg3Va-bAusaRaZA3JWfJGg4XgfS_exNnbvCVBPw0,1122
+PyInstaller/hooks/hook-PySide6.QtAxContainer.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.QtBluetooth.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.QtCharts.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.QtConcurrent.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.QtCore.py,sha256=2F9qD4YqIZq6DMKRegn7DHvS6Eq3IWkBa5SRie11N-o,633
+PyInstaller/hooks/hook-PySide6.QtDBus.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.QtDataVisualization.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.QtDesigner.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.QtGraphs.py,sha256=rgWc6i9j5HrbRyVDZjptPrNu24NT-Uc0_bJAj8Z8v9o,628
+PyInstaller/hooks/hook-PySide6.QtGraphsWidgets.py,sha256=w9ICAH2zNa2KniPB7NunLK3MpI1ECJmzkpEaOq2j64Q,764
+PyInstaller/hooks/hook-PySide6.QtGui.py,sha256=2F9qD4YqIZq6DMKRegn7DHvS6Eq3IWkBa5SRie11N-o,633
+PyInstaller/hooks/hook-PySide6.QtHelp.py,sha256=2F9qD4YqIZq6DMKRegn7DHvS6Eq3IWkBa5SRie11N-o,633
+PyInstaller/hooks/hook-PySide6.QtHttpServer.py,sha256=pnm0JlKbPaJvU4C2CBTZf5YOFdLv0JzstefyQTmc3M8,837
+PyInstaller/hooks/hook-PySide6.QtLocation.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.QtMultimedia.py,sha256=apdddXdKLkbCSREJo8W9zHP_iZh-wiFGZeezSMYKw2c,981
+PyInstaller/hooks/hook-PySide6.QtMultimediaWidgets.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.QtNetwork.py,sha256=o1tB7jEyZGCUQzEv-uypg8ghl3iMaEUJR9uppFjlSAk,714
+PyInstaller/hooks/hook-PySide6.QtNetworkAuth.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.QtNfc.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.QtOpenGL.py,sha256=2F9qD4YqIZq6DMKRegn7DHvS6Eq3IWkBa5SRie11N-o,633
+PyInstaller/hooks/hook-PySide6.QtOpenGLWidgets.py,sha256=2F9qD4YqIZq6DMKRegn7DHvS6Eq3IWkBa5SRie11N-o,633
+PyInstaller/hooks/hook-PySide6.QtPdf.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.QtPdfWidgets.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.QtPositioning.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.QtPrintSupport.py,sha256=2F9qD4YqIZq6DMKRegn7DHvS6Eq3IWkBa5SRie11N-o,633
+PyInstaller/hooks/hook-PySide6.QtQml.py,sha256=kPZge8513WUfKoV4yr49zND7K-m5oug7gHAZVJt3sDc,768
+PyInstaller/hooks/hook-PySide6.QtQuick.py,sha256=2F9qD4YqIZq6DMKRegn7DHvS6Eq3IWkBa5SRie11N-o,633
+PyInstaller/hooks/hook-PySide6.QtQuick3D.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.QtQuickControls2.py,sha256=rlKwMNNYovkBDloHUZjpQFS6bungJ8ZRjiHaHpPeWhs,671
+PyInstaller/hooks/hook-PySide6.QtQuickWidgets.py,sha256=2F9qD4YqIZq6DMKRegn7DHvS6Eq3IWkBa5SRie11N-o,633
+PyInstaller/hooks/hook-PySide6.QtRemoteObjects.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.QtScxml.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.QtSensors.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.QtSerialBus.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.QtSerialPort.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.QtSpatialAudio.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.QtSql.py,sha256=2F9qD4YqIZq6DMKRegn7DHvS6Eq3IWkBa5SRie11N-o,633
+PyInstaller/hooks/hook-PySide6.QtStateMachine.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.QtSvg.py,sha256=2F9qD4YqIZq6DMKRegn7DHvS6Eq3IWkBa5SRie11N-o,633
+PyInstaller/hooks/hook-PySide6.QtSvgWidgets.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.QtTest.py,sha256=2F9qD4YqIZq6DMKRegn7DHvS6Eq3IWkBa5SRie11N-o,633
+PyInstaller/hooks/hook-PySide6.QtTextToSpeech.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.QtUiTools.py,sha256=2F9qD4YqIZq6DMKRegn7DHvS6Eq3IWkBa5SRie11N-o,633
+PyInstaller/hooks/hook-PySide6.QtWebChannel.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.QtWebEngineCore.py,sha256=gVHkCC20EZTbqlSl2AM76jpz7xBcKY0VYDbobWjD5V0,1410
+PyInstaller/hooks/hook-PySide6.QtWebEngineQuick.py,sha256=cq1LjMw4S_JrC47Ihz1kh7td06JQ1FO_a94J0dJFG94,633
+PyInstaller/hooks/hook-PySide6.QtWebEngineWidgets.py,sha256=cq1LjMw4S_JrC47Ihz1kh7td06JQ1FO_a94J0dJFG94,633
+PyInstaller/hooks/hook-PySide6.QtWebSockets.py,sha256=xyYQlN8teZE9iQ9eCbUVKEKG7Q7fKhShb4skrs0llHY,633
+PyInstaller/hooks/hook-PySide6.QtWidgets.py,sha256=2F9qD4YqIZq6DMKRegn7DHvS6Eq3IWkBa5SRie11N-o,633
+PyInstaller/hooks/hook-PySide6.QtXml.py,sha256=2F9qD4YqIZq6DMKRegn7DHvS6Eq3IWkBa5SRie11N-o,633
+PyInstaller/hooks/hook-PySide6.py,sha256=_vu5Cx2tP-xeizvYi7oZS2g62KmK8tCfAyvs1Ga7dQY,1279
+PyInstaller/hooks/hook-_pyi_rth_utils.py,sha256=HvliUIYSZQFmhLz9ABAzwK-iNurl6oY_eM9mgJRIcHQ,680
+PyInstaller/hooks/hook-_tkinter.py,sha256=2Sz18FAMHPdfdG1cLIyXTqyoXf5y7UcNDA8CIZLApdU,1191
+PyInstaller/hooks/hook-babel.py,sha256=2W8yoXGOs2c7gmoI71VzKsiVwIrNfOywB3NPK46wweI,924
+PyInstaller/hooks/hook-difflib.py,sha256=whXBs38P70PWAv5IW-L6B3phR_D3gkzzT6jap7PqBCE,577
+PyInstaller/hooks/hook-distutils.command.check.py,sha256=so8h5fLMRsiJrEVWNaAPAekziYQY744kpA2J8BFDioQ,606
+PyInstaller/hooks/hook-distutils.py,sha256=JHrLMrbVMTCwqV83Z84eOaXNYruODZrz-aan1x-2R4c,1893
+PyInstaller/hooks/hook-distutils.util.py,sha256=ogjFFsduAfi4QXp2K-qMovorSZM0Wk-ON9lsIKpn1d0,661
+PyInstaller/hooks/hook-django.contrib.sessions.py,sha256=1bXvBmfdjldiywMQPSkl5e94NShMoUmtTLoW5yN4k3M,635
+PyInstaller/hooks/hook-django.core.cache.py,sha256=yiRj8bhzRhB4rkQWiFe4RAtSuJsRakzfMNg8mtknjzo,629
+PyInstaller/hooks/hook-django.core.mail.py,sha256=Fhwo_CjxNQ8jh9_cu0Z5d0QlX5-8LRO4LusKc3sskwc,1069
+PyInstaller/hooks/hook-django.core.management.py,sha256=g8NXb7a-cgfo0IRIZuravW1YcSxDvLASr1p3trefhQM,942
+PyInstaller/hooks/hook-django.db.backends.mysql.base.py,sha256=XDf5vHB7eUZnQzP_xc68F1w2avWO1vKzAxykpSACHss,611
+PyInstaller/hooks/hook-django.db.backends.oracle.base.py,sha256=NtUXz6s4xJyxJgVXsatrMO3X42RxnVq5-v1JAMVU29k,563
+PyInstaller/hooks/hook-django.db.backends.py,sha256=NTWkllG7dc-TR-6rCkcNvlEfwlmGi8vhVbXxQuOKa8o,983
+PyInstaller/hooks/hook-django.py,sha256=5chCU9FUO1Th8-GcVhQgO4VpovCg9ysU3LWSf3yXWAE,3922
+PyInstaller/hooks/hook-django.template.loaders.py,sha256=rcU0WR52DFFxt91MWHscKaDxhvja94d7Ggejtw_5aH0,626
+PyInstaller/hooks/hook-encodings.py,sha256=zTyqMMiW7ghKxyygcOl6MJfmQwt5EdyD1JJnzB7Ol34,612
+PyInstaller/hooks/hook-gevent.py,sha256=_EFWvRtFto7AN-mx-cBcn6L9u-rtZtLeLbwx7Lv6meM,1011
+PyInstaller/hooks/hook-gi.py,sha256=xvJ12MAltpj-r9GzPKLsN4zIQ7Ax9g1cc3Ss7b3UWGA,552
+PyInstaller/hooks/hook-gi.repository.Adw.py,sha256=NwRYqmZESkyKkpCOJbNq8BVu_h5Y7Qw7_bBSsAWe6As,698
+PyInstaller/hooks/hook-gi.repository.AppIndicator3.py,sha256=Bwid2vErvCkB1kkjYc6QJnnv3_Jqf3VvC1fn2vkz6AY,710
+PyInstaller/hooks/hook-gi.repository.Atk.py,sha256=di-iBdmgg6BNhdXgUi0NSTIilzAF7dAx213vlZXzaIo,1084
+PyInstaller/hooks/hook-gi.repository.AyatanaAppIndicator3.py,sha256=9BTVgthn0s8CLk52V-bB4GRmfxlR7N45CGvAbcG4WNM,717
+PyInstaller/hooks/hook-gi.repository.Champlain.py,sha256=b-WMOJ5wo9IJxTA8VEtRA0DkoLGIKGpZRROt97K6sdA,707
+PyInstaller/hooks/hook-gi.repository.Clutter.py,sha256=VR3XwfcdcerLYuG6C_8jH9DbX9Ka2reBBZ_aFkC8__o,704
+PyInstaller/hooks/hook-gi.repository.DBus.py,sha256=pv9g8ObQCghzaLzGYrf5oYoA0fAhVMGktw1v2d4Okkw,701
+PyInstaller/hooks/hook-gi.repository.GIRepository.py,sha256=pADSM-De6Pa6jl45ZBKeP9ObE2At2vWpKUe-8Q3PUbs,709
+PyInstaller/hooks/hook-gi.repository.GLib.py,sha256=6Lhx56wjr3wl5oeSx134eVVWK2WudF13kPOqzKyfvm4,1490
+PyInstaller/hooks/hook-gi.repository.GModule.py,sha256=fpyExmwwNceUthEUZpS9EuaanoKqc8NAsGFuZgov_mM,704
+PyInstaller/hooks/hook-gi.repository.GObject.py,sha256=KkT6C-YbGIoPMkPfCLXprAWdSB2_Cn6f52-pdQ9c_9s,905
+PyInstaller/hooks/hook-gi.repository.Gdk.py,sha256=gGUVXbJ9sKf8WPjrxjPTlW0QEriKy6gvKre3GTP4NbA,1393
+PyInstaller/hooks/hook-gi.repository.GdkPixbuf.py,sha256=N6cB1VyD6EKmYo4xjqcuveugFwTxiq-bp2OXwwGRtdw,6318
+PyInstaller/hooks/hook-gi.repository.Gio.py,sha256=9vMXEAMaiZG0CoHXZXtMHAiXJjVAp1u_b6CPcVWKlew,2605
+PyInstaller/hooks/hook-gi.repository.Graphene.py,sha256=kPN5lzSJZ1yH-wQ0s00vL_zHMckNH7SS1w7dz4-5Dhc,705
+PyInstaller/hooks/hook-gi.repository.Gsk.py,sha256=UK0rvXX0CsHNyJ3SLs29aOnN92KFoSKtSXU08exYzjM,700
+PyInstaller/hooks/hook-gi.repository.Gst.py,sha256=1yevQzFiRUAjzTkwiZOgsQiu6rrUYB_Hg3KpviSfT7c,3461
+PyInstaller/hooks/hook-gi.repository.GstAllocators.py,sha256=ryA-HqngziZjrL3OBCF6zOvqT4INKhejrRi8JNNIB3s,710
+PyInstaller/hooks/hook-gi.repository.GstApp.py,sha256=eyqjhws-xrCrfFFDhqHjp8RV-GLiI5Qop3FSx84aoJA,703
+PyInstaller/hooks/hook-gi.repository.GstAudio.py,sha256=kJnvOIlWDflbCMFNatGsN7Ql1Xvo9ffmdRlzHFnKKT8,705
+PyInstaller/hooks/hook-gi.repository.GstBadAudio.py,sha256=tCt0HhYm9M98SiBREXCrKh__d5KuT0FZFr1QlZhq7BM,708
+PyInstaller/hooks/hook-gi.repository.GstBase.py,sha256=JaETtokmwH78qQfpjesqKTfBEk-1g1ktvMaIpXzFTEU,704
+PyInstaller/hooks/hook-gi.repository.GstCheck.py,sha256=2vgJstFwiiKyARmpag0wfBcU3pevgm8Zo4dySyEzRyg,705
+PyInstaller/hooks/hook-gi.repository.GstCodecs.py,sha256=_IktlFHwuRd7dWNTY7I-WkddtSPTnarXFTOlQXiVt18,706
+PyInstaller/hooks/hook-gi.repository.GstController.py,sha256=IOq8HWRh_VPdY7NT4OV0-pmFAAYYcKBwZ0QA0WIBanY,710
+PyInstaller/hooks/hook-gi.repository.GstGL.py,sha256=L6bSj5NSIu6XMPpC7tjGukuKJtbXVkQsf8zRM_g5EZY,702
+PyInstaller/hooks/hook-gi.repository.GstGLEGL.py,sha256=FrSoWPNESToC36pZGVpVIiiJ3ox798AqZRGUwMiAzSM,705
+PyInstaller/hooks/hook-gi.repository.GstGLWayland.py,sha256=LTQqLLY99wUKQqlbG3eQ_5SRo4g_enehVKUshE3wB8o,709
+PyInstaller/hooks/hook-gi.repository.GstGLX11.py,sha256=CW8_aDTy1eg5-h0scvoDrwf1_WmfSyubG4-LOS-yhlE,705
+PyInstaller/hooks/hook-gi.repository.GstInsertBin.py,sha256=9YyLJmMHQl7i-q1oTZckGC23_YTDbVpTI58fhw9C6A0,709
+PyInstaller/hooks/hook-gi.repository.GstMpegts.py,sha256=1H4EnbwZW70trU8ivRv2EowUZvebs1B5sO27bKX7Lvo,706
+PyInstaller/hooks/hook-gi.repository.GstNet.py,sha256=anwfzAqBlaGh_Kmy25z2-YynVJo4cgKKgsLzvqUtrvU,703
+PyInstaller/hooks/hook-gi.repository.GstPbutils.py,sha256=eIaEhzlsyawjzjiiqNGFwIiflfDWZ1GO1GnY72gIolk,707
+PyInstaller/hooks/hook-gi.repository.GstPlay.py,sha256=kih5CSzeBI2Zgg7DIz-9ZQbs0MKjqbjBKtLE0bE8vzY,704
+PyInstaller/hooks/hook-gi.repository.GstPlayer.py,sha256=4-8kI3EHUf610zfcA6ovaU_1YiMybz8m1jX-N_9dbRM,706
+PyInstaller/hooks/hook-gi.repository.GstRtp.py,sha256=MT5yvnKq1FBaEFIWy0yGZAQKC8Z20tuQUSB_koDwPIw,703
+PyInstaller/hooks/hook-gi.repository.GstRtsp.py,sha256=h7pOjxw1sFEpe33M3r_-24YczqfI1sQg0Y2ZBQ6nlFE,704
+PyInstaller/hooks/hook-gi.repository.GstRtspServer.py,sha256=lAIHSUOIrC7XQ4ZG5AbR2J-OiukSFK2TiBWBLaq7gZo,710
+PyInstaller/hooks/hook-gi.repository.GstSdp.py,sha256=ywxH8YxjksNuhpdeWrGIkSuMBF8xBau-YkYXqFIl9DM,703
+PyInstaller/hooks/hook-gi.repository.GstTag.py,sha256=bu9I6OoSUEVNbkrUOUFHKe0e057INqeMCeyB5AHH0dM,703
+PyInstaller/hooks/hook-gi.repository.GstTranscoder.py,sha256=m6YtxnRBG1wWalzZgtTKOIv8fKvzwiHjepbckfli7vc,710
+PyInstaller/hooks/hook-gi.repository.GstVideo.py,sha256=6wDSl-9fg_C3qorsgiCnHrqR46Y0tA4NnWEQnAX0tug,705
+PyInstaller/hooks/hook-gi.repository.GstVulkan.py,sha256=wQXXd9_Wp03xsu_Y8ml3bGBDj1JjB1NxqYSqZ6XJFUk,706
+PyInstaller/hooks/hook-gi.repository.GstVulkanWayland.py,sha256=0t7TQcr5pJ058whWXN-pVJhYvbmA0bPMkjshDyRWY7Y,713
+PyInstaller/hooks/hook-gi.repository.GstVulkanXCB.py,sha256=CVKjOp2xJ6Iq3MxbtV9nQJTV0TQXvsumojRzI5NkkFM,709
+PyInstaller/hooks/hook-gi.repository.GstWebRTC.py,sha256=9W6manw1GmQKnWA-Cq6rbykbAAoEQB359XBMwRmQWv8,706
+PyInstaller/hooks/hook-gi.repository.Gtk.py,sha256=8kAtofOZcoiBjTgf0S2mBxv5thpFU3JFEeQ5YG8TiTo,2150
+PyInstaller/hooks/hook-gi.repository.GtkChamplain.py,sha256=mk1keoUxkuD8FHfIFW8i9IpSpN2qiUvVRWVNnOco8nI,710
+PyInstaller/hooks/hook-gi.repository.GtkClutter.py,sha256=Yu6TRHQVi42DsZsoKWwE2G-GDGNzMUrxTR5BBQRkyOc,707
+PyInstaller/hooks/hook-gi.repository.GtkSource.py,sha256=MERiaYTs-_swaRUFS1BqJQ5T5FpfrgPSvH9I4pjzKo4,1297
+PyInstaller/hooks/hook-gi.repository.GtkosxApplication.py,sha256=E-nWcs8eef4Gu1N5miKUMaXPMI0xu3O6PRzX1ZkP9Zw,781
+PyInstaller/hooks/hook-gi.repository.HarfBuzz.py,sha256=vUu5j4FBHqQPLGbjhkWJx1tWi86-HxiBmkgRjrXEpko,705
+PyInstaller/hooks/hook-gi.repository.Pango.py,sha256=yB2ZbRI2vG1OuigPDCIGRKqIxPPAE2SGQ5dh5UoL9uU,702
+PyInstaller/hooks/hook-gi.repository.PangoCairo.py,sha256=0z-JkDB74mtvK-qBbIpqB9UmChAPfcY4Z0cdXa7156U,707
+PyInstaller/hooks/hook-gi.repository.cairo.py,sha256=8E7NMq7RGLg5S506KrHp02qPi8Xq70cTQLz8-2L1Yko,702
+PyInstaller/hooks/hook-gi.repository.freetype2.py,sha256=X6cMHL6XRVrw92SFGRAmwCrWm_k8fHJdk8bVsBxUAnY,706
+PyInstaller/hooks/hook-gi.repository.xlib.py,sha256=MvSXmdVHKrEPpbCRVikFfpK_tCPifwGSyTjkxZ70WMA,701
+PyInstaller/hooks/hook-heapq.py,sha256=gjF79X1Jt5zDPGD9Q_VdmBfn8_NZCn622l7YArn2u38,578
+PyInstaller/hooks/hook-idlelib.py,sha256=96jkUh7GNAPaBdV2ebvtuW7QhnmVMp8F_uvRl7IEyug,602
+PyInstaller/hooks/hook-importlib_metadata.py,sha256=lWesTFNaBn9FjUekBi82wqRwZTU35JqeXRRdBn8hvUA,1350
+PyInstaller/hooks/hook-importlib_resources.py,sha256=qnYt9Bu6zOErsKmDsk6dX7ImRVwCV_cDNSZJRFK7Hxo,1015
+PyInstaller/hooks/hook-keyring.py,sha256=bYnya8YRlh8Cn1DLoDNINWMp_YTKgnSZafhHIecGS1Y,888
+PyInstaller/hooks/hook-kivy.py,sha256=QlC2_9p6MqyKuIVePUGVHzxl_y4j7EC3k_Wlr5UKdXc,1126
+PyInstaller/hooks/hook-lib2to3.py,sha256=uU3mDEtYPN-Z_GxO-zt6orNo7qK8Q_30bSugb02RyPo,653
+PyInstaller/hooks/hook-matplotlib.backend_bases.py,sha256=7iniaWkwXT6sohBNGxq9mA1EpQdZe8i6G4-FdW25Eos,533
+PyInstaller/hooks/hook-matplotlib.backends.backend_qtagg.py,sha256=P1oAFSt-848iD4kuhE4AthDGWXmsV1tgI9gPTCMOLWM,894
+PyInstaller/hooks/hook-matplotlib.backends.backend_qtcairo.py,sha256=tBYzMUrY7pKSuBklcAJvVrKZ8mddX1O-nxy_YgkIrq8,896
+PyInstaller/hooks/hook-matplotlib.backends.py,sha256=SWWxGBJfrZ7NbZqZtIkMeD0I-nysDo2Ek58m9Wesk3E,9657
+PyInstaller/hooks/hook-matplotlib.backends.qt_compat.py,sha256=YmmBT0MiyEDmVXrNMpgj0G9EEjUma2a5xGsCUSpvWoM,1284
+PyInstaller/hooks/hook-matplotlib.numerix.py,sha256=IeAi4MV6B5QJ1xhrrknpna6W7GOoU-hHZDqGRi0jJbw,683
+PyInstaller/hooks/hook-matplotlib.py,sha256=oScRuUc0Y3jXjp_Yy1vkyETtkrOZzwRr-eWmWKOeDhY,1568
+PyInstaller/hooks/hook-matplotlib.pyplot.py,sha256=Z_bOet2njmp6DZt4nc6afxLyGBCbgSsj9TEc3rerX0o,560
+PyInstaller/hooks/hook-multiprocessing.util.py,sha256=d9rgj6yOLda8nXxCQofqgcQABGhl4snJu-oIA4tk8zw,791
+PyInstaller/hooks/hook-numpy.py,sha256=_TXRgxZu3Buoi4vcfxuAEMocVatOrYTfvskWYclPAL0,6051
+PyInstaller/hooks/hook-packaging.py,sha256=-xKZIGp9It9_aWoZYQZLdFMNhsxJjwwv5tYSem8t-2I,577
+PyInstaller/hooks/hook-pandas.io.clipboard.py,sha256=syzylK5jU3Lm8IFomqrdtKx_-rZzdEGUnG5X6vaquC4,1156
+PyInstaller/hooks/hook-pandas.io.formats.style.py,sha256=zxvJxol9G5FwRjU90EpmzgMBlzx03lrLkAorhDAXxa4,751
+PyInstaller/hooks/hook-pandas.plotting.py,sha256=XGZMzp_CUX8VTzLG-4Stbb8AAM_ICnW758-eQGrBDwc,938
+PyInstaller/hooks/hook-pandas.py,sha256=x7kjmXFdtYYWYlBMgNq4wjO0vMalSrf_XgJiB-vxq2o,955
+PyInstaller/hooks/hook-pickle.py,sha256=UodGjHVD_QtTR8VW2mQ8XL4toCpHYfU3QIVwPd1DOu4,589
+PyInstaller/hooks/hook-pkg_resources.py,sha256=CoQupujLoZgi79d_flMEhFPpOUJxDJGXgqBXCww3cLI,3563
+PyInstaller/hooks/hook-platform.py,sha256=PXPyeR-xcVpVagddP0opUdW6QNi5F_gOTkl7f4b77S8,713
+PyInstaller/hooks/hook-pygments.py,sha256=bFqk7NfL9GXrMTDCWUv1oOK9pQbx1354THBLlgsqOFE,1184
+PyInstaller/hooks/hook-pytz.py,sha256=ZCJFYXAljJSbyqiu262tZL_qpnZsajehWzRDKvoI7dc,734
+PyInstaller/hooks/hook-pytzdata.py,sha256=h6qOdqNVmFnWE0b1DeE-gpVqeL-MVs25VbC-s8dsvNY,603
+PyInstaller/hooks/hook-qtawesome.py,sha256=UDQFON0R3GbQoPxJ2nBYmr11FOVbc2mZn0jWg0i8q28,792
+PyInstaller/hooks/hook-qtpy.py,sha256=Imf8Sma0zykdKY_ltMlKtccb0CWPsL0DY0UWjU2ckYE,1179
+PyInstaller/hooks/hook-scapy.layers.all.py,sha256=71caVRTCmcClHNBwlmRKKBHZfWEYE9qubn_DNxN8Xbo,930
+PyInstaller/hooks/hook-scipy.io.matlab.py,sha256=_W8WtCFFsLIoxUX5DRDj2YULfi4bo13OkK6MoNKj25g,655
+PyInstaller/hooks/hook-scipy.linalg.py,sha256=iXsaTpTOgNalynuMqMdI0JRenRsZ1G5kx_D8EKJWaRU,633
+PyInstaller/hooks/hook-scipy.py,sha256=HSc1rIEz-XGrBqS9NQMD7skf-AAJ2PeQPnTt48_Ia60,2467
+PyInstaller/hooks/hook-scipy.sparse.csgraph.py,sha256=pCQv4w_ReJsQCl0udEomCM9WcrsYVJ1QGxxW5IikLLY,611
+PyInstaller/hooks/hook-scipy.spatial.transform.rotation.py,sha256=YJ44N1xt8P1SB3PKSfuPiB1E2iV1MSLWLMKS_hSmlL0,793
+PyInstaller/hooks/hook-scipy.special._ellip_harm_2.py,sha256=UlLNQkgYOCFCmMItBKvvVRwSUZpAWJRst0IpdJqX8M4,1317
+PyInstaller/hooks/hook-scipy.special._ufuncs.py,sha256=v1GYZ6g5NA9g0GfZV7ymBz-xIGD_3oWv9MoaPGxSElA,1258
+PyInstaller/hooks/hook-scipy.stats._stats.py,sha256=9HkYRAJhusS5gyXIvhBjtkc2z0EjvtMY_0zTBxq70sY,656
+PyInstaller/hooks/hook-scrapy.py,sha256=360AxhD-RoAKPY9gNo-DW4Yx9YCc1WTTJ_VKRu6Amp0,819
+PyInstaller/hooks/hook-setuptools._vendor.importlib_metadata.py,sha256=olw_k1O_UERG8lXz7aqi3iOg7svYNEAZX6t3dDXRxg0,1127
+PyInstaller/hooks/hook-setuptools._vendor.jaraco.text.py,sha256=4mzkjFNSvo27UGVm6dteGPB8ilUgb1LEbnmnSiMeW6o,927
+PyInstaller/hooks/hook-setuptools.py,sha256=iyfdli1uj8DMObrg9mDuCK55KhlezS2cdJWHQt9PeUw,4466
+PyInstaller/hooks/hook-shelve.py,sha256=ToCfEfqwboTS42HS9Ugv1h0xAo2M_CmBb8_gP2cldqE,603
+PyInstaller/hooks/hook-shiboken6.py,sha256=1krp8Ui-4Kl5IoPzX3HECUmD5BG2M0J3LNHLvaVnpw0,766
+PyInstaller/hooks/hook-sphinx.py,sha256=fc8mbEuArO9mEelgapVJjI3Lcln1u4d_XkW4nMudpYE,1998
+PyInstaller/hooks/hook-sqlalchemy.py,sha256=14Ccv93R6oHjyYlXTQ-l0F3x1xcf_4xkI_O0Hk4jOmc,3496
+PyInstaller/hooks/hook-sqlite3.py,sha256=oZ2oAKTuORGunOzbvMDyRKV9lLpDbMede9ozuyLDeqM,813
+PyInstaller/hooks/hook-sysconfig.py,sha256=5IcB6ZlhVkP6kf8csyo8Xrz7WleJTbWEhMZKoswAUu0,1558
+PyInstaller/hooks/hook-wcwidth.py,sha256=zWcpM-dXNP7vuhDyjEMhlsjWQQ9WPtTtxn1S9xG5jc8,602
+PyInstaller/hooks/hook-win32ctypes.core.py,sha256=_IqEnHRy2Jhq-57MKZGFZGS5Bvg53vMp9eQqzeaJY0E,1204
+PyInstaller/hooks/hook-xml.dom.domreg.py,sha256=dCHWL_UpnTqCnrv7DL3-IWULcqthaJVtm2WX4FTmPHo,569
+PyInstaller/hooks/hook-xml.etree.cElementTree.py,sha256=Duh1C8zTwmt_lg_Ek9rLgxxww88fgpiuGyI8OynK-q8,615
+PyInstaller/hooks/hook-xml.py,sha256=oxHKZoo7YNgI_8qG9q3wgYukjIDr27PL8Wv051SrzyA,569
+PyInstaller/hooks/hook-zope.interface.py,sha256=1Xrezxtifo9OUMPDTDGGaEoOn04xIU33OsO_lvX2gWM,539
+PyInstaller/hooks/pre_find_module_path/__init__.py,sha256=MsSFjiLMLJZ7QhUPpVBWKiyDnCzryquRyr329NoCACI,2
+PyInstaller/hooks/pre_find_module_path/__pycache__/__init__.cpython-311.pyc,,
+PyInstaller/hooks/pre_find_module_path/__pycache__/hook-PyQt5.uic.port_v2.cpython-311.pyc,,
+PyInstaller/hooks/pre_find_module_path/__pycache__/hook-_pyi_rth_utils.cpython-311.pyc,,
+PyInstaller/hooks/pre_find_module_path/__pycache__/hook-distutils.cpython-311.pyc,,
+PyInstaller/hooks/pre_find_module_path/__pycache__/hook-pyi_splash.cpython-311.pyc,,
+PyInstaller/hooks/pre_find_module_path/__pycache__/hook-tkinter.cpython-311.pyc,,
+PyInstaller/hooks/pre_find_module_path/hook-PyQt5.uic.port_v2.py,sha256=lMGJ1xNvaAxuHkGivHHno1q7QZ_F0WsTKstlmc4NcHc,696
+PyInstaller/hooks/pre_find_module_path/hook-_pyi_rth_utils.py,sha256=cPgCZrMJdWTO43CEN4J3mvtlzF9yWlEBsEmzi5u8fyo,905
+PyInstaller/hooks/pre_find_module_path/hook-distutils.py,sha256=yLU8K5hn85G2y5Hs_XF0hgMP9hQg3qIqOJKEv2q39jo,2347
+PyInstaller/hooks/pre_find_module_path/hook-pyi_splash.py,sha256=edbvRQ2Thc2qHA36uUCLHPC-HIembOEkr5bA8orH9pU,1412
+PyInstaller/hooks/pre_find_module_path/hook-tkinter.py,sha256=lbu1k3kYhULblbqn90-g5GN2qir7Rz7ShbTfYEyGAiw,834
+PyInstaller/hooks/pre_safe_import_module/__init__.py,sha256=MsSFjiLMLJZ7QhUPpVBWKiyDnCzryquRyr329NoCACI,2
+PyInstaller/hooks/pre_safe_import_module/__pycache__/__init__.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-autocommand.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-backports.tarfile.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-distutils.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Adw.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.AppIndicator3.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Atk.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.AyatanaAppIndicator3.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Champlain.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Clutter.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.DBus.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GIRepository.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GLib.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GModule.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GObject.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Gdk.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GdkPixbuf.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Gio.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Graphene.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Gsk.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Gst.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstAllocators.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstApp.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstAudio.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstBadAudio.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstBase.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstCheck.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstCodecs.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstController.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstGL.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstGLEGL.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstGLWayland.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstGLX11.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstInsertBin.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstMpegts.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstNet.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstPbutils.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstPlay.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstPlayer.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstRtp.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstRtsp.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstRtspServer.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstSdp.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstTag.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstTranscoder.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstVideo.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstVulkan.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstVulkanWayland.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstVulkanXCB.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GstWebRTC.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Gtk.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GtkChamplain.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GtkClutter.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GtkSource.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.GtkosxApplication.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.HarfBuzz.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.Pango.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.PangoCairo.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.cairo.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.freetype2.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-gi.repository.xlib.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-importlib_metadata.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-importlib_resources.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-inflect.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-jaraco.context.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-jaraco.functools.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-jaraco.text.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-more_itertools.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-ordered_set.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-packaging.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-platformdirs.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-setuptools.extern.six.moves.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-six.moves.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-tomli.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-typeguard.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-typing_extensions.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-urllib3.packages.six.moves.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-wheel.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/__pycache__/hook-zipp.cpython-311.pyc,,
+PyInstaller/hooks/pre_safe_import_module/hook-autocommand.py,sha256=O56uUBdY_je3jGpxwWo_qyKHCUPZX805adawrj8kBBE,924
+PyInstaller/hooks/pre_safe_import_module/hook-backports.tarfile.py,sha256=O56uUBdY_je3jGpxwWo_qyKHCUPZX805adawrj8kBBE,924
+PyInstaller/hooks/pre_safe_import_module/hook-distutils.py,sha256=LDvJiYH0gr2-e5UC0wD5U2MU2jB2KHvGIlDqmMT4Ubw,1235
+PyInstaller/hooks/pre_safe_import_module/hook-gi.py,sha256=UU9LBJIf3EIFC1pKwi1hqxV-iGvI4VtJBVa6KPOXXKU,1955
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Adw.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.AppIndicator3.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Atk.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.AyatanaAppIndicator3.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Champlain.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Clutter.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.DBus.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GIRepository.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GLib.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GModule.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GObject.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Gdk.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GdkPixbuf.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Gio.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Graphene.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Gsk.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Gst.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstAllocators.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstApp.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstAudio.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstBadAudio.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstBase.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstCheck.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstCodecs.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstController.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstGL.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstGLEGL.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstGLWayland.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstGLX11.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstInsertBin.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstMpegts.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstNet.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstPbutils.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstPlay.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstPlayer.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstRtp.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstRtsp.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstRtspServer.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstSdp.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstTag.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstTranscoder.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstVideo.py,sha256=wwWsrx5A4AsvLZimx7h9M9T0gBFBqPXb5z2MIgX3EEs,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstVulkan.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstVulkanWayland.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstVulkanXCB.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GstWebRTC.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Gtk.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GtkChamplain.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GtkClutter.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GtkSource.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.GtkosxApplication.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.HarfBuzz.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.Pango.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.PangoCairo.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.cairo.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.freetype2.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-gi.repository.xlib.py,sha256=c5f74KePUHt-7fH_tJQfuqB44ysYTLbCm76u2QVB07U,783
+PyInstaller/hooks/pre_safe_import_module/hook-importlib_metadata.py,sha256=O56uUBdY_je3jGpxwWo_qyKHCUPZX805adawrj8kBBE,924
+PyInstaller/hooks/pre_safe_import_module/hook-importlib_resources.py,sha256=O56uUBdY_je3jGpxwWo_qyKHCUPZX805adawrj8kBBE,924
+PyInstaller/hooks/pre_safe_import_module/hook-inflect.py,sha256=O56uUBdY_je3jGpxwWo_qyKHCUPZX805adawrj8kBBE,924
+PyInstaller/hooks/pre_safe_import_module/hook-jaraco.context.py,sha256=O56uUBdY_je3jGpxwWo_qyKHCUPZX805adawrj8kBBE,924
+PyInstaller/hooks/pre_safe_import_module/hook-jaraco.functools.py,sha256=O56uUBdY_je3jGpxwWo_qyKHCUPZX805adawrj8kBBE,924
+PyInstaller/hooks/pre_safe_import_module/hook-jaraco.text.py,sha256=O56uUBdY_je3jGpxwWo_qyKHCUPZX805adawrj8kBBE,924
+PyInstaller/hooks/pre_safe_import_module/hook-more_itertools.py,sha256=O56uUBdY_je3jGpxwWo_qyKHCUPZX805adawrj8kBBE,924
+PyInstaller/hooks/pre_safe_import_module/hook-ordered_set.py,sha256=O56uUBdY_je3jGpxwWo_qyKHCUPZX805adawrj8kBBE,924
+PyInstaller/hooks/pre_safe_import_module/hook-packaging.py,sha256=O56uUBdY_je3jGpxwWo_qyKHCUPZX805adawrj8kBBE,924
+PyInstaller/hooks/pre_safe_import_module/hook-platformdirs.py,sha256=O56uUBdY_je3jGpxwWo_qyKHCUPZX805adawrj8kBBE,924
+PyInstaller/hooks/pre_safe_import_module/hook-setuptools.extern.six.moves.py,sha256=A-aFL3cZ_AgA2Ia5UPEnFijM5vCP-S-U24kiOMrgdpY,1629
+PyInstaller/hooks/pre_safe_import_module/hook-six.moves.py,sha256=drAs8emHi0X9vxDtKo-n3XBTanM6RuJPJATfVoVFOXE,3744
+PyInstaller/hooks/pre_safe_import_module/hook-tomli.py,sha256=O56uUBdY_je3jGpxwWo_qyKHCUPZX805adawrj8kBBE,924
+PyInstaller/hooks/pre_safe_import_module/hook-typeguard.py,sha256=O56uUBdY_je3jGpxwWo_qyKHCUPZX805adawrj8kBBE,924
+PyInstaller/hooks/pre_safe_import_module/hook-typing_extensions.py,sha256=O56uUBdY_je3jGpxwWo_qyKHCUPZX805adawrj8kBBE,924
+PyInstaller/hooks/pre_safe_import_module/hook-urllib3.packages.six.moves.py,sha256=vLiXNHM4LwX4sWP6j_pQnBpLpwFXz0TCxHnQpqUdjf8,1380
+PyInstaller/hooks/pre_safe_import_module/hook-wheel.py,sha256=O56uUBdY_je3jGpxwWo_qyKHCUPZX805adawrj8kBBE,924
+PyInstaller/hooks/pre_safe_import_module/hook-zipp.py,sha256=O56uUBdY_je3jGpxwWo_qyKHCUPZX805adawrj8kBBE,924
+PyInstaller/hooks/rthooks.dat,sha256=bdXIqqe9MG02b81XxSNDeewioDtjKLydPCyiPZsX9g8,956
+PyInstaller/hooks/rthooks/__init__.py,sha256=MsSFjiLMLJZ7QhUPpVBWKiyDnCzryquRyr329NoCACI,2
+PyInstaller/hooks/rthooks/__pycache__/__init__.cpython-311.pyc,,
+PyInstaller/hooks/rthooks/__pycache__/pyi_rth__tkinter.cpython-311.pyc,,
+PyInstaller/hooks/rthooks/__pycache__/pyi_rth_django.cpython-311.pyc,,
+PyInstaller/hooks/rthooks/__pycache__/pyi_rth_gdkpixbuf.cpython-311.pyc,,
+PyInstaller/hooks/rthooks/__pycache__/pyi_rth_gi.cpython-311.pyc,,
+PyInstaller/hooks/rthooks/__pycache__/pyi_rth_gio.cpython-311.pyc,,
+PyInstaller/hooks/rthooks/__pycache__/pyi_rth_glib.cpython-311.pyc,,
+PyInstaller/hooks/rthooks/__pycache__/pyi_rth_gstreamer.cpython-311.pyc,,
+PyInstaller/hooks/rthooks/__pycache__/pyi_rth_gtk.cpython-311.pyc,,
+PyInstaller/hooks/rthooks/__pycache__/pyi_rth_inspect.cpython-311.pyc,,
+PyInstaller/hooks/rthooks/__pycache__/pyi_rth_kivy.cpython-311.pyc,,
+PyInstaller/hooks/rthooks/__pycache__/pyi_rth_mplconfig.cpython-311.pyc,,
+PyInstaller/hooks/rthooks/__pycache__/pyi_rth_multiprocessing.cpython-311.pyc,,
+PyInstaller/hooks/rthooks/__pycache__/pyi_rth_pkgres.cpython-311.pyc,,
+PyInstaller/hooks/rthooks/__pycache__/pyi_rth_pkgutil.cpython-311.pyc,,
+PyInstaller/hooks/rthooks/__pycache__/pyi_rth_pyqt5.cpython-311.pyc,,
+PyInstaller/hooks/rthooks/__pycache__/pyi_rth_pyqt6.cpython-311.pyc,,
+PyInstaller/hooks/rthooks/__pycache__/pyi_rth_pyside2.cpython-311.pyc,,
+PyInstaller/hooks/rthooks/__pycache__/pyi_rth_pyside6.cpython-311.pyc,,
+PyInstaller/hooks/rthooks/__pycache__/pyi_rth_setuptools.cpython-311.pyc,,
+PyInstaller/hooks/rthooks/pyi_rth__tkinter.py,sha256=iF0MUBG5v18Mygb1sgqkvSgFPGmgF-z0DmtlOK2n9DE,1381
+PyInstaller/hooks/rthooks/pyi_rth_django.py,sha256=9FeO_ektm32U-b-dZvvNdjrT0S6-H3I5rFCHSvBmG0A,1111
+PyInstaller/hooks/rthooks/pyi_rth_gdkpixbuf.py,sha256=IOq2fxAQZ4OIMam-sLr0NI93dfMC8KgsrmXdjzE7M3g,1437
+PyInstaller/hooks/rthooks/pyi_rth_gi.py,sha256=H5wdL7AjlrfPib7En_YYLebfltmm5V4AUZ_PacAEFlQ,632
+PyInstaller/hooks/rthooks/pyi_rth_gio.py,sha256=6T0LIFqi8l5HzCWE-0mYIQ6DaxNGn0533Xn7V0uhLZo,631
+PyInstaller/hooks/rthooks/pyi_rth_glib.py,sha256=s7VmqbBTJBAU--RrroztL5u7CY3seSbFM6xR6BpCa1U,1444
+PyInstaller/hooks/rthooks/pyi_rth_gstreamer.py,sha256=r2MTC-bYPN1Kdfvw_Am2KiVnvA6WqikLGpaqVLeDIZM,1175
+PyInstaller/hooks/rthooks/pyi_rth_gtk.py,sha256=yR1NT5tRR-g9y-bG7Tk7ZosPTNHMnV7KFme7dlz6NFA,886
+PyInstaller/hooks/rthooks/pyi_rth_inspect.py,sha256=plSsK6xps0rNPr2UY7e_vljFKH4InjddNU66VyRCk2A,2429
+PyInstaller/hooks/rthooks/pyi_rth_kivy.py,sha256=jIBZeNe2Kmbxi00XJ96l5KvNWD9KCvzFQp-Ug93-FpU,737
+PyInstaller/hooks/rthooks/pyi_rth_mplconfig.py,sha256=XuCFEHpud0vYuwQX56LcuGoZgkjB_pHPyseJcs5UwSY,1808
+PyInstaller/hooks/rthooks/pyi_rth_multiprocessing.py,sha256=6a2ZoTIVNGKHdB-aAAfG7dVN56R9soM5AJV0-D9T-Yg,2219
+PyInstaller/hooks/rthooks/pyi_rth_pkgres.py,sha256=pK7zQnH9D7yYuqQOhDCYlvphC6ckQRyKFGSAP9RCNpI,8660
+PyInstaller/hooks/rthooks/pyi_rth_pkgutil.py,sha256=052KyovwgWko4GUDJyl5wWtu1hY2hAWxAb0aSsjFVN4,3084
+PyInstaller/hooks/rthooks/pyi_rth_pyqt5.py,sha256=og6YoJVF0NfPDvZUCydq5Hc1mOylHfoPlZr5U9FDQ4c,3542
+PyInstaller/hooks/rthooks/pyi_rth_pyqt6.py,sha256=La9r6nfWJzXPGi9llkcEq5PvLaZLnkqdhCMhySS6oQY,3803
+PyInstaller/hooks/rthooks/pyi_rth_pyside2.py,sha256=UNxayNyGCcbxheNwM0zz9shmGuOcy4ubIr0OQ0qHJms,3235
+PyInstaller/hooks/rthooks/pyi_rth_pyside6.py,sha256=0SAB-MUdyPdxFNnUgHixB-HXwNvYnQOPTucn08GlN6s,3730
+PyInstaller/hooks/rthooks/pyi_rth_setuptools.py,sha256=rrDcdbUGSuUnUeXDRR_HalxM1-ghtJiWFIgOvOIIMPo,1430
+PyInstaller/isolated/__init__.py,sha256=eY1YBvBNir3Mwn2-lSXEBmiY-i_jz1ZZ_uQVRq_qZms,1526
+PyInstaller/isolated/__pycache__/__init__.cpython-311.pyc,,
+PyInstaller/isolated/__pycache__/_child.cpython-311.pyc,,
+PyInstaller/isolated/__pycache__/_parent.cpython-311.pyc,,
+PyInstaller/isolated/_child.py,sha256=sQERIgcb0bB38MAZP2s6UM29yEKkVeB_jV0lEHXckzQ,3980
+PyInstaller/isolated/_parent.py,sha256=w1AGtK8vWlazpJUaAjlBV10MSs1JEtfVnxq_T40pY2Q,18005
+PyInstaller/lib/README.rst,sha256=VdkvnJUKg6D2bv3nfb-bJoWQ00jTf-pLbvv7KbsSaTA,1333
+PyInstaller/lib/__init__.py,sha256=MsSFjiLMLJZ7QhUPpVBWKiyDnCzryquRyr329NoCACI,2
+PyInstaller/lib/__pycache__/__init__.cpython-311.pyc,,
+PyInstaller/lib/modulegraph/__init__.py,sha256=q1XQN2YGfSINUSLuBsTs7uhMArf62AFQxdSrq3fS4-o,21
+PyInstaller/lib/modulegraph/__main__.py,sha256=hiwjxxmiY3QfLQ7f0Pd_eSDQYL8MXQyQtkRoJSHe3hU,2653
+PyInstaller/lib/modulegraph/__pycache__/__init__.cpython-311.pyc,,
+PyInstaller/lib/modulegraph/__pycache__/__main__.cpython-311.pyc,,
+PyInstaller/lib/modulegraph/__pycache__/find_modules.cpython-311.pyc,,
+PyInstaller/lib/modulegraph/__pycache__/modulegraph.cpython-311.pyc,,
+PyInstaller/lib/modulegraph/__pycache__/util.cpython-311.pyc,,
+PyInstaller/lib/modulegraph/find_modules.py,sha256=D3B5WujxMc6syDuReriZfwxoFw7mBbkLj3-MADyVLD8,1754
+PyInstaller/lib/modulegraph/modulegraph.py,sha256=UUpwYXUZLb0dKX4AwbZWdPKITpjO-Y3YkZDDyBw9gZ8,130955
+PyInstaller/lib/modulegraph/util.py,sha256=S-0SI65fylZqvy0bN-xMB1xRYp5o0qo7UJnX5IwCzcg,849
+PyInstaller/loader/__init__.py,sha256=MsSFjiLMLJZ7QhUPpVBWKiyDnCzryquRyr329NoCACI,2
+PyInstaller/loader/__pycache__/__init__.cpython-311.pyc,,
+PyInstaller/loader/__pycache__/pyiboot01_bootstrap.cpython-311.pyc,,
+PyInstaller/loader/__pycache__/pyimod01_archive.cpython-311.pyc,,
+PyInstaller/loader/__pycache__/pyimod02_importers.cpython-311.pyc,,
+PyInstaller/loader/__pycache__/pyimod03_ctypes.cpython-311.pyc,,
+PyInstaller/loader/__pycache__/pyimod04_pywin32.cpython-311.pyc,,
+PyInstaller/loader/pyiboot01_bootstrap.py,sha256=L-dAFf4veUwC6xF9qXPvCxuimCDVYyf_f8QU5cJ803A,3712
+PyInstaller/loader/pyimod01_archive.py,sha256=cw3eZLwFidkSLzCrbaGjFuevlxjxSAi02Eg_S2eubWw,5346
+PyInstaller/loader/pyimod02_importers.py,sha256=NArs-KoR2vn4mqq2kLqSxU5YdVPt_GMJ4exdxq_j394,32643
+PyInstaller/loader/pyimod03_ctypes.py,sha256=ZdLzbVIP1uf5RB5mLs2JTJJjdfu5pswa_5S6vEBTMSc,4915
+PyInstaller/loader/pyimod04_pywin32.py,sha256=vFVETWdFpZIroatj0TGpDE2fAMgAVTs80IQjrNGYKuw,2936
+PyInstaller/log.py,sha256=1Pqaq6YwtV-zg4UMA826AJey6zWZwajFwwKsXNBmIu8,2058
+PyInstaller/utils/__init__.py,sha256=MsSFjiLMLJZ7QhUPpVBWKiyDnCzryquRyr329NoCACI,2
+PyInstaller/utils/__pycache__/__init__.cpython-311.pyc,,
+PyInstaller/utils/__pycache__/conftest.cpython-311.pyc,,
+PyInstaller/utils/__pycache__/misc.cpython-311.pyc,,
+PyInstaller/utils/__pycache__/osx.cpython-311.pyc,,
+PyInstaller/utils/__pycache__/run_tests.cpython-311.pyc,,
+PyInstaller/utils/__pycache__/tests.cpython-311.pyc,,
+PyInstaller/utils/cliutils/__init__.py,sha256=MsSFjiLMLJZ7QhUPpVBWKiyDnCzryquRyr329NoCACI,2
+PyInstaller/utils/cliutils/__pycache__/__init__.cpython-311.pyc,,
+PyInstaller/utils/cliutils/__pycache__/archive_viewer.cpython-311.pyc,,
+PyInstaller/utils/cliutils/__pycache__/bindepend.cpython-311.pyc,,
+PyInstaller/utils/cliutils/__pycache__/grab_version.cpython-311.pyc,,
+PyInstaller/utils/cliutils/__pycache__/makespec.cpython-311.pyc,,
+PyInstaller/utils/cliutils/__pycache__/set_version.cpython-311.pyc,,
+PyInstaller/utils/cliutils/archive_viewer.py,sha256=TApsAzyxsO0TL02Dyu0G_u-ckOmZnuy-UoVQ2bNfjwQ,9253
+PyInstaller/utils/cliutils/bindepend.py,sha256=3ds2RnLHUtRYZricqMPRjMcVccKsn9zcwauPCFIRHLA,1844
+PyInstaller/utils/cliutils/grab_version.py,sha256=i2j8WItcJp5tgUUCVFqO2tRN-DtBe-yO3lKqbBP0Zjo,1857
+PyInstaller/utils/cliutils/makespec.py,sha256=dO9-KTe_lsUFlurY2gF6bOnd7OAn2hvGcmgg2n-GBSs,1640
+PyInstaller/utils/cliutils/set_version.py,sha256=FbC-FfXZs3W0XAvpgsy16T8HPJgZbFlHd2xB9EBwIMc,1503
+PyInstaller/utils/conftest.py,sha256=BVJnY2YVtu28VePDDVYlBzB-1t-0Wdd-K9IOxsiNn7M,24294
+PyInstaller/utils/hooks/__init__.py,sha256=xWb-ye-BfKMYWYQoAuO0lJUL5LaTLK5YDScQdB9v7HY,54416
+PyInstaller/utils/hooks/__pycache__/__init__.cpython-311.pyc,,
+PyInstaller/utils/hooks/__pycache__/conda.cpython-311.pyc,,
+PyInstaller/utils/hooks/__pycache__/django.cpython-311.pyc,,
+PyInstaller/utils/hooks/__pycache__/gi.cpython-311.pyc,,
+PyInstaller/utils/hooks/__pycache__/setuptools.cpython-311.pyc,,
+PyInstaller/utils/hooks/__pycache__/tcl_tk.cpython-311.pyc,,
+PyInstaller/utils/hooks/conda.py,sha256=HKIaa1UoqOTBaUfk7_Nm5eRGv3sCZLy7fZBwvoFIafE,14694
+PyInstaller/utils/hooks/django.py,sha256=veWnLehyo9xC94_D0TchQuCL4M2-T6EVjNrsoUEoiO0,6135
+PyInstaller/utils/hooks/gi.py,sha256=e_L3yot9Np4ajl57c3hbn5abFOmFOoBGTN2J1lKqezY,17414
+PyInstaller/utils/hooks/qt/__init__.py,sha256=3eboHkSBiH33ikHtq-ior55HEFHWsP2nYmY_Abt-a8I,75389
+PyInstaller/utils/hooks/qt/__pycache__/__init__.cpython-311.pyc,,
+PyInstaller/utils/hooks/qt/__pycache__/_modules_info.cpython-311.pyc,,
+PyInstaller/utils/hooks/qt/_modules_info.py,sha256=OWfRSZa-zMmOtvdSurQhaf2VTbQYhIKU8FtlAEFnqqg,25226
+PyInstaller/utils/hooks/setuptools.py,sha256=iwNd50MM-jaL3sgaUOPt_iw6O_bFPXAopQv-WPBbg4Q,10735
+PyInstaller/utils/hooks/tcl_tk.py,sha256=7kNT1WTUZQyjJsK7i_iPAKlWGfLfQFc_5DbeXXGsYr0,14931
+PyInstaller/utils/misc.py,sha256=5NmfvxjaomhoPEg7yRv1-evvTWTD2HQysd3lhOfgRNg,7030
+PyInstaller/utils/osx.py,sha256=RBb79kbLTzTLLfMROBxkYUptXq0TJjaEAruNNiLdIQE,29624
+PyInstaller/utils/run_tests.py,sha256=OCnUmL3dBAN5D-wKM1Dg3sSvsMy925LicSEktIyYodE,2875
+PyInstaller/utils/tests.py,sha256=v0TZbQH9A7sijrfko7aEOKBVodh2qk10E48n_sfSdpI,5813
+PyInstaller/utils/win32/__init__.py,sha256=fNGhsx0m5s9iq4yMvH6J1tI0vzUKWd62lIQNSnKTGCE,22
+PyInstaller/utils/win32/__pycache__/__init__.cpython-311.pyc,,
+PyInstaller/utils/win32/__pycache__/icon.cpython-311.pyc,,
+PyInstaller/utils/win32/__pycache__/versioninfo.cpython-311.pyc,,
+PyInstaller/utils/win32/__pycache__/winmanifest.cpython-311.pyc,,
+PyInstaller/utils/win32/__pycache__/winresource.cpython-311.pyc,,
+PyInstaller/utils/win32/__pycache__/winutils.cpython-311.pyc,,
+PyInstaller/utils/win32/icon.py,sha256=vgM-RKozX_VoXBpV5eXwWjyeryJJFkCXe_7RsDrUMDc,9327
+PyInstaller/utils/win32/versioninfo.py,sha256=ykWWzXVSnouldIfVapxysCEtWIR0oigX_rLL4zggO2k,20594
+PyInstaller/utils/win32/winmanifest.py,sha256=zO7kzIDp7MD_9GeF_RfsTrxaTOu_UnICMQUJFGoO54M,10644
+PyInstaller/utils/win32/winresource.py,sha256=DcA0UehlxjoU4s-mRPc51kHrQcHY0GEmAddGnYTekyk,7625
+PyInstaller/utils/win32/winutils.py,sha256=SSU_rotjJ0Eomy1Nn1oPRxF7qtAe_7UMWyAQsr_BZQc,9175
+pyinstaller-6.11.1.dist-info/COPYING.txt,sha256=3Pdf25WdseO0HA-FBQadLs54G17Gs9Ck0wl1z8ZYAkU,32138
+pyinstaller-6.11.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+pyinstaller-6.11.1.dist-info/METADATA,sha256=VdS2TKaQdrzntHPB8zO_gTIa2-uOq-p5VBQkoXq8vis,8344
+pyinstaller-6.11.1.dist-info/RECORD,,
+pyinstaller-6.11.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+pyinstaller-6.11.1.dist-info/WHEEL,sha256=MKsKTYcJ8UB7nlhmb6_u5qoYj_ULa0PDSKtamp2tTfc,98
+pyinstaller-6.11.1.dist-info/entry_points.txt,sha256=laaKjYFiMC3YuqudHNNx42-TdVB-y4YDLNDOrRFgk4I,376
+pyinstaller-6.11.1.dist-info/top_level.txt,sha256=GuRmvWXGTRJNYmK5iWGOglNv4L3by7YKaEiKycNZ4XQ,12
diff --git a/venv/Lib/site-packages/pyinstaller-6.11.1.dist-info/REQUESTED b/venv/Lib/site-packages/pyinstaller-6.11.1.dist-info/REQUESTED
new file mode 100644
index 0000000..e69de29
diff --git a/venv/Lib/site-packages/pyinstaller-6.11.1.dist-info/WHEEL b/venv/Lib/site-packages/pyinstaller-6.11.1.dist-info/WHEEL
new file mode 100644
index 0000000..e4fec26
--- /dev/null
+++ b/venv/Lib/site-packages/pyinstaller-6.11.1.dist-info/WHEEL
@@ -0,0 +1,5 @@
+Wheel-Version: 1.0
+Generator: bdist_wheel (0.44.0)
+Root-Is-Purelib: true
+Tag: py3-none-win_amd64
+
diff --git a/venv/Lib/site-packages/pyinstaller-6.11.1.dist-info/entry_points.txt b/venv/Lib/site-packages/pyinstaller-6.11.1.dist-info/entry_points.txt
new file mode 100644
index 0000000..22c2452
--- /dev/null
+++ b/venv/Lib/site-packages/pyinstaller-6.11.1.dist-info/entry_points.txt
@@ -0,0 +1,7 @@
+[console_scripts]
+pyi-archive_viewer = PyInstaller.utils.cliutils.archive_viewer:run
+pyi-bindepend = PyInstaller.utils.cliutils.bindepend:run
+pyi-grab_version = PyInstaller.utils.cliutils.grab_version:run
+pyi-makespec = PyInstaller.utils.cliutils.makespec:run
+pyi-set_version = PyInstaller.utils.cliutils.set_version:run
+pyinstaller = PyInstaller.__main__:_console_script_run
diff --git a/venv/Lib/site-packages/pyinstaller-6.11.1.dist-info/top_level.txt b/venv/Lib/site-packages/pyinstaller-6.11.1.dist-info/top_level.txt
new file mode 100644
index 0000000..c313980
--- /dev/null
+++ b/venv/Lib/site-packages/pyinstaller-6.11.1.dist-info/top_level.txt
@@ -0,0 +1 @@
+PyInstaller
diff --git a/venv/Lib/site-packages/pyinstaller_hooks_contrib-2024.10.dist-info/INSTALLER b/venv/Lib/site-packages/pyinstaller_hooks_contrib-2024.10.dist-info/INSTALLER
new file mode 100644
index 0000000..a1b589e
--- /dev/null
+++ b/venv/Lib/site-packages/pyinstaller_hooks_contrib-2024.10.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/venv/Lib/site-packages/pyinstaller_hooks_contrib-2024.10.dist-info/LICENSE b/venv/Lib/site-packages/pyinstaller_hooks_contrib-2024.10.dist-info/LICENSE
new file mode 100644
index 0000000..99bef9e
--- /dev/null
+++ b/venv/Lib/site-packages/pyinstaller_hooks_contrib-2024.10.dist-info/LICENSE
@@ -0,0 +1,521 @@
+============================================
+PyInstaller Community Hooks: License details
+============================================
+
+This software is made available under the terms of the licenses found below.
+Contributions to the Community Hooks are made under the terms of the license
+that covers that type of hook/file. (See below)
+
+
+Standard hooks and files
+------------------------
+
+The PyInstaller Community Hooks are licensed under the terms of the GNU General
+Public License as published by the Free Software Foundation; either version 2 of
+the License, or (at your option) any later version (SPDX GPL-2.0-or-later).
+These are all hooks/files except runtime hooks (see below). The terms of GPL 2.0
+are found in the section titled *GNU General Public License* below.
+
+
+Runtime hooks
+-------------
+
+These are runtime hooks, bundled with complete pyinstaller executables. These
+files are licensed under the Apache-2.0 whose terms are found in the section
+titled *Apache License 2.0*.
+
+These reside in "_pyinstaller_hooks_contrib/rthooks".
+
+
+GNU General Public License
+--------------------------
+
+https://gnu.org/licenses/gpl-2.0.html
+
+
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+
+Apache License 2.0
+++++++++++++++++++
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/venv/Lib/site-packages/pyinstaller_hooks_contrib-2024.10.dist-info/METADATA b/venv/Lib/site-packages/pyinstaller_hooks_contrib-2024.10.dist-info/METADATA
new file mode 100644
index 0000000..7d1d760
--- /dev/null
+++ b/venv/Lib/site-packages/pyinstaller_hooks_contrib-2024.10.dist-info/METADATA
@@ -0,0 +1,371 @@
+Metadata-Version: 2.1
+Name: pyinstaller-hooks-contrib
+Version: 2024.10
+Summary: Community maintained hooks for PyInstaller
+Home-page: https://github.com/pyinstaller/pyinstaller-hooks-contrib
+Download-URL: https://pypi.org/project/pyinstaller-hooks-contrib
+Maintainer: Legorooj
+Maintainer-email: legorooj@protonmail.com
+Keywords: pyinstaller development hooks
+Classifier: Intended Audience :: Developers
+Classifier: Topic :: Software Development :: Build Tools
+Classifier: License :: OSI Approved :: Apache Software License
+Classifier: License :: OSI Approved :: GNU General Public License v2 (GPLv2)
+Classifier: Natural Language :: English
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 3
+Requires-Python: >=3.8
+Description-Content-Type: text/markdown
+License-File: LICENSE
+Requires-Dist: setuptools>=42.0.0
+Requires-Dist: packaging>=22.0
+Requires-Dist: importlib-metadata>=4.6; python_version < "3.10"
+
+# `pyinstaller-hooks-contrib`: The PyInstaller community hooks repository
+
+What happens when (your?) package doesn't work with PyInstaller? Say you have data files that you need at runtime?
+PyInstaller doesn't bundle those. Your package requires others which PyInstaller can't see? How do you fix that?
+
+In summary, a "hook" file extends PyInstaller to adapt it to the special needs and methods used by a Python package.
+The word "hook" is used for two kinds of files. A runtime hook helps the bootloader to launch an app, setting up the
+environment. A package hook (there are several types of those) tells PyInstaller what to include in the final app -
+such as the data files and (hidden) imports mentioned above.
+
+This repository is a collection of hooks for many packages, and allows PyInstaller to work with these packages
+seamlessly.
+
+
+## Installation
+
+`pyinstaller-hooks-contrib` is automatically installed when you install PyInstaller, or can be installed with pip:
+
+```commandline
+pip install -U pyinstaller-hooks-contrib
+```
+
+
+## I can't see a hook for `a-package`
+
+Either `a-package` works fine without a hook, or no-one has contributed hooks.
+If you'd like to add a hook, or view information about hooks,
+please see below.
+
+
+## Hook configuration (options)
+
+Hooks that support configuration (options) and their options are documented in
+[Supported hooks and options](hooks-config.rst).
+
+
+## I want to help!
+
+If you've got a hook you want to share then great!
+The rest of this page will walk you through the process of contributing a hook.
+If you've been here before then you may want to skip to the [summary checklist](#summary)
+
+**Unless you are very comfortable with `git rebase -i`, please provide one hook per pull request!**
+**If you have more than one then submit them in separate pull requests.**
+
+
+### Setup
+
+[Fork this repo](https://github.com/pyinstaller/pyinstaller-hooks-contrib/fork) if you haven't already done so.
+(If you have a fork already but its old, click the **Fetch upstream** button on your fork's homepage.)
+Clone and `cd` inside your fork by running the following (replacing `bob-the-barnacle` with your github username):
+
+```
+git clone https://github.com/bob-the-barnacle/pyinstaller-hoooks-contrib.git
+cd pyinstaller-hooks-contrib
+```
+
+Create a new branch for you changes (replacing `foo` with the name of the package):
+You can name this branch whatever you like.
+
+```
+git checkout -b hook-for-foo
+```
+
+If you wish to create a virtual environment then do it now before proceeding to the next step.
+
+Install this repo in editable mode.
+This will overwrite your current installation.
+(Note that you can reverse this with `pip install --force-reinstall pyinstaller-hooks-contrib`).
+
+```
+pip install -e .
+pip install -r requirements-test.txt
+pip install flake8 pyinstaller
+```
+
+Note that on macOS and Linux, `pip` may by called `pip3`.
+If you normally use `pip3` and `python3` then use `pip3` here too.
+You may skip the 2nd line if you have no intention of providing tests (but please do provide tests!).
+
+
+### Add the hook
+
+Standard hooks live in the [_pyinstaller_hooks_contrib/stdhooks/](../master/_pyinstaller_hooks_contrib/stdhooks/) directory.
+Runtime hooks live in the [_pyinstaller_hooks_contrib/rthooks/](../master/_pyinstaller_hooks_contrib/rthooks/) directory.
+Simply copy your hook into there.
+If you're unsure if your hook is a runtime hook then it almost certainly is a standard hook.
+
+Please annotate (with comments) anything unusual in the hook.
+*Unusual* here is defined as any of the following:
+
+*   Long lists of `hiddenimport` submodules.
+    If you need lots of hidden imports then use [`collect_submodules('foo')`](https://pyinstaller.readthedocs.io/en/latest/hooks.html#PyInstaller.utils.hooks.collect_submodules).
+    For bonus points, track down why so many submodules are hidden. Typical causes are:
+    *   Lazily loaded submodules (`importlib.importmodule()` inside a module `__getattr__()`).
+    *   Dynamically loaded *backends*.
+    *   Usage of `Cython` or Python extension modules containing `import` statements.
+*   Use of [`collect_all()`](https://pyinstaller.readthedocs.io/en/latest/hooks.html#PyInstaller.utils.hooks.collect_all).
+    This function's performance is abismal and [it is broken by
+    design](https://github.com/pyinstaller/pyinstaller/issues/6458#issuecomment-1000481631) because it confuses
+    packages with distributions.
+    Check that you really do need to collect all of submodules, data files, binaries, metadata and dependencies.
+    If you do then add a comment to say so (and if you know it - why).
+    Do not simply use `collect_all()` just to *future proof* the hook.
+*   Any complicated `os.path` arithmetic (by which I simply mean overly complex filename manipulations).
+
+
+#### Add the copyright header
+
+All source files must contain the copyright header to be covered by our terms and conditions.
+
+If you are **adding** a new hook (or any new python file), copy/paste the appropriate copyright header (below) at the top
+replacing 2021 with the current year.
+
+
GPL 2 header for standard hooks or other Python files. + +```python +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the GNU General Public +# License (version 2.0 or later). +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# ------------------------------------------------------------------ +``` + +
+ +
Apache header for runtime hooks only. +Again, if you're unsure if your hook is a runtime hook then it'll be a standard hook. + +```python +# ------------------------------------------------------------------ +# Copyright (c) 2024 PyInstaller Development Team. +# +# This file is distributed under the terms of the Apache License 2.0 +# +# The full license is available in LICENSE, distributed with +# this software. +# +# SPDX-License-Identifier: Apache-2.0 +# ------------------------------------------------------------------ +``` + +
+ + +If you are **updating** a hook, skip this step. +Do not update the year of the copyright header - even if it's out of date. + + +### Test + +Having tests is key to our continuous integration. +With them we can automatically verify that your hook works on all platforms, all Python versions and new versions of +libraries as and when they are released. +Without them, we have no idea if the hook is broken until someone finds out the hard way. +Please write tests!!! + +Some user interface libraries may be impossible to test without user interaction +or a wrapper library for some web API may require credentials (and possibly a paid subscription) to test. +In such cases, don't provide a test. +Instead explain either in the commit message or when you open your pull request why an automatic test is impractical +then skip on to [the next step](#run-linter). + + +#### Write tests(s) + +A test should be the least amount of code required to cause a breakage +if you do not have the hook which you are contributing. +For example if you are writing a hook for a library called `foo` +which crashes immediately under PyInstaller on `import foo` then `import foo` is your test. +If `import foo` works even without the hook then you will have to get a bit more creative. +Good sources of such minimal tests are introductory examples +from the documentation of whichever library you're writing a hook for. +Package's internal data files and hidden dependencies are prone to moving around so +tests should not explicitly check for presence of data files or hidden modules directly - +rather they should use parts of the library which are expected to use said data files or hidden modules. + +Tests generally live in [tests/test_libraries.py](../master/tests/test_libraries.py). +Navigate there and add something like the following, replacing all occurrences of `foo` with the real name of the library. +(Note where you put it in that file doesn't matter.) + +```python +@importorskip('foo') +def test_foo(pyi_builder): + pyi_builder.test_source(""" + + # Your test here! + import foo + + foo.something_fooey() + + """) +``` + +If the library has changed significantly over past versions then you may need to add version constraints to the test. +To do that, replace the `@importorskip("foo")` with a call to `PyInstaller.utils.tests.requires()` (e.g. +`@requires("foo >= 1.4")`) to only run the test if the given version constraint is satisfied. +Note that `@importorskip` uses module names (something you'd `import`) whereas `@requires` uses distribution names +(something you'd `pip install`) so you'd use `@importorskip("PIL")` but `@requires("pillow")`. +For most packages, the distribution and packages names are the same. + + +#### Run the test locally + +Running our full test suite is not recommended as it will spend a very long time testing code which you have not touched. +Instead, run tests individually using either the `-k` option to search for test names: + +``` +pytest -k test_foo +``` + +Or using full paths: +``` +pytest tests/test_libraries.py::test_foo +``` + + +#### Pin the test requirement + +Get the version of the package you are working with (`pip show foo`) +and add it to the [requirements-test-libraries.txt](../master/requirements-test-libraries.txt) file. +The requirements already in there should guide you on the syntax. + + +#### Run the test on CI/CD + +
CI/CD now triggers itself when you open a pull request. +These instructions for triggering jobs manually are obsolete except in rare cases. + +To test hooks on all platforms we use Github's continuous integration (CI/CD). +Our CI/CD is a bit unusual in that it's triggered manually and takes arguments +which limit which tests are run. +This is for the same reason we filter tests when running locally - +the full test suite takes ages. + +First push the changes you've made so far. + +```commandline +git push --set-upstream origin hook-for-foo +``` + +Replace *billy-the-buffalo* with your Github username in the following url then open it. +It should take you to the `oneshot-test` actions workflow on your fork. +You may be asked if you want to enable actions on your fork - say yes. +``` +https://github.com/billy-the-buffalo/pyinstaller-hooks-contrib/actions/workflows/oneshot-test.yml +``` + +Find the **Run workflow** button and click on it. +If you can't see the button, +select the **Oneshot test** tab from the list of workflows on the left of the page +and it should appear. +A dialog should appear containing one drop-down menu and 5 line-edit fields. +This dialog is where you specify what to test and which platforms and Python versions to test on. +Its fields are as follows: + +1. A branch to run from. Set this to the branch which you are using (e.g. ``hook-for-foo``), +2. Which package(s) to install and their version(s). + Which packages to test are inferred from which packages are installed. + You can generally just copy your own changes to the `requirements-test-libraries.txt` file into this box. + * Set to `foo` to test the latest version of `foo`, + * Set to `foo==1.2, foo==2.3` (note the comma) to test two different versions of `foo` in separate jobs, + * Set to `foo bar` (note the lack of a comma) to test `foo` and `bar` in the same job, +3. Which OS or OSs to run on + * Set to `ubuntu` to test only `ubuntu`, + * Set to `ubuntu, macos, windows` (order is unimportant) to test all three OSs. +4. Which Python version(s) to run on + * Set to `3.9` to test only Python 3.9, + * Set to `3.8, 3.9, 3.10, 3.11` to test all currently supported version of Python. +5. The final two options can generally be left alone. + +Hit the green **Run workflow** button at the bottom of the dialog, wait a few seconds then refresh the page. +Your workflow run should appear. + +We'll eventually want to see a build (or collection of builds) which pass on +all OSs and all Python versions. +Once you have one, hang onto its URL - you'll need it when you submit the pull request. +If you can't get it to work - that's fine. +Open a pull request as a draft, show us what you've got and we'll try and help. + + +#### Triggering CI/CD from a terminal + +If you find repeatedly entering the configuration into Github's **Run workflow** dialog arduous +then we also have a CLI script to launch it. +Run ``python scripts/cloud-test.py --help`` which should walk you through it. +You will have to enter all the details again but, thanks to the wonders of terminal history, +rerunning a configuration is just a case of pressing up then enter. + +
+ + +### Run Linter + +We use `flake8` to enforce code-style. +`pip install flake8` if you haven't already then run it with the following. + +``` +flake8 +``` + +No news is good news. +If it complains about your changes then do what it asks then run it again. +If you don't understand the errors it come up with them lookup the error code +in each line (a capital letter followed by a number e.g. `W391`). + +**Please do not fix flake8 issues found in parts of the repository other than the bit that you are working on.** Not only is it very boring for you, but it is harder for maintainers to +review your changes because so many of them are irrelevant to the hook you are adding or changing. + + +### Add a news entry + +Please read [news/README.txt](https://github.com/pyinstaller/pyinstaller-hooks-contrib/blob/master/news/README.txt) before submitting you pull request. +This will require you to know the pull request number before you make the pull request. +You can usually guess it by adding 1 to the number of [the latest issue or pull request](https://github.com/pyinstaller/pyinstaller-hooks-contrib/issues?q=sort%3Acreated-desc). +Alternatively, [submit the pull request](#submit-the-pull-request) as a draft, +then add, commit and push the news item after you know your pull request number. + + +### Summary + +A brief checklist for before submitting your pull request: + +* [ ] All new Python files have [the appropriate copyright header](#add-the-copyright-header). +* [ ] You have written a [news entry](#add-a-news-entry). +* [ ] Your changes [satisfy the linter](#run-linter) (run `flake8`). +* [ ] You have written tests (if possible) and [pinned the test requirement](#pin-the-test-requirement). + + +### Submit the pull request + +Once you've done all the above, run `git push --set-upstream origin hook-for-foo` then go ahead and create a pull request. +If you're stuck doing any of the above steps, create a draft pull request and explain what's wrong - we'll sort you out... +Feel free to copy/paste commit messages into the Github pull request title and description. +If you've never done a pull request before, note that you can edit it simply by running `git push` again. +No need to close the old one and start a new one. + +--- + +If you plan to contribute frequently or are interested in becoming a developer, +send an email to `legorooj@protonmail.com` to let us know. diff --git a/venv/Lib/site-packages/pyinstaller_hooks_contrib-2024.10.dist-info/RECORD b/venv/Lib/site-packages/pyinstaller_hooks_contrib-2024.10.dist-info/RECORD new file mode 100644 index 0000000..282ef60 --- /dev/null +++ b/venv/Lib/site-packages/pyinstaller_hooks_contrib-2024.10.dist-info/RECORD @@ -0,0 +1,1015 @@ +_pyinstaller_hooks_contrib/__init__.py,sha256=FekX0pQUgYHbYEgBJre2WK1fmFZvD8bsAQ_wszOOfII,855 +_pyinstaller_hooks_contrib/__pycache__/__init__.cpython-311.pyc,, +_pyinstaller_hooks_contrib/__pycache__/__init__.cpython-39.pyc,sha256=RTaaARFMZmwZ35exzJuBrG_TRsecIUXkooswyXatHY0,548 +_pyinstaller_hooks_contrib/__pycache__/compat.cpython-311.pyc,, +_pyinstaller_hooks_contrib/compat.py,sha256=0j90ldRf8YpffLKamgybdqt4OepoPO1gFHI7HKE08b8,1535 +_pyinstaller_hooks_contrib/pre_find_module_path/__init__.py,sha256=XqTB__uJKeDTb84jwHlEmqemORWifP5u1Qi4lRzoTqo,420 +_pyinstaller_hooks_contrib/pre_find_module_path/__pycache__/__init__.cpython-311.pyc,, +_pyinstaller_hooks_contrib/pre_safe_import_module/__init__.py,sha256=XqTB__uJKeDTb84jwHlEmqemORWifP5u1Qi4lRzoTqo,420 +_pyinstaller_hooks_contrib/pre_safe_import_module/__pycache__/__init__.cpython-311.pyc,, +_pyinstaller_hooks_contrib/pre_safe_import_module/__pycache__/hook-tensorflow.cpython-311.pyc,, +_pyinstaller_hooks_contrib/pre_safe_import_module/__pycache__/hook-win32com.cpython-311.pyc,, +_pyinstaller_hooks_contrib/pre_safe_import_module/hook-tensorflow.py,sha256=2g3DIc1sCJGnaWQtAHNtU4P0GxBwO2qb07leNCLQVqw,1415 +_pyinstaller_hooks_contrib/pre_safe_import_module/hook-win32com.py,sha256=0MWymjscSjZYmAZ5y8EnHQaWiWxNKP9gvxYjKJWlbpc,1591 +_pyinstaller_hooks_contrib/rthooks.dat,sha256=3njJi-VRQez966tAcQge2yu82SxpbIEVevqNj7MVinI,599 +_pyinstaller_hooks_contrib/rthooks/__init__.py,sha256=QCvGkX3OU8wyd01O8N1mu-joIPa0-FEZ7eUxvpLXCMY,380 +_pyinstaller_hooks_contrib/rthooks/__pycache__/__init__.cpython-311.pyc,, +_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_cryptography_openssl.cpython-311.pyc,, +_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_enchant.cpython-311.pyc,, +_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_ffpyplayer.cpython-311.pyc,, +_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_findlibs.cpython-311.pyc,, +_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_nltk.cpython-311.pyc,, +_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_osgeo.cpython-311.pyc,, +_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_pygraphviz.cpython-311.pyc,, +_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_pyproj.cpython-311.pyc,, +_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_pyqtgraph_multiprocess.cpython-311.pyc,, +_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_pythoncom.cpython-311.pyc,, +_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_pywintypes.cpython-311.pyc,, +_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_tensorflow.cpython-311.pyc,, +_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_traitlets.cpython-311.pyc,, +_pyinstaller_hooks_contrib/rthooks/__pycache__/pyi_rth_usb.cpython-311.pyc,, +_pyinstaller_hooks_contrib/rthooks/pyi_rth_cryptography_openssl.py,sha256=jnzEkk1MZzFk9Mf3fGKvargi127JTaE2QdSrECbiDx4,755 +_pyinstaller_hooks_contrib/rthooks/pyi_rth_enchant.py,sha256=PrKqo5wO5SRSiGnZUXxVUFs-HWXLUHp5ky9HBO-Xtto,903 +_pyinstaller_hooks_contrib/rthooks/pyi_rth_ffpyplayer.py,sha256=qKPwYCFQmmBKitKrbQ0BFTra3bbVmGXB8QwcxXkng6Y,879 +_pyinstaller_hooks_contrib/rthooks/pyi_rth_findlibs.py,sha256=vMqQP1qXnAp-VzDOoLjD2Y-DRPm-cT3wMUZjp-a0Hlw,2046 +_pyinstaller_hooks_contrib/rthooks/pyi_rth_nltk.py,sha256=J50SKKti3MvZIWBRnIBBaqtq91dQ1ogRCVrDvn6Ea54,534 +_pyinstaller_hooks_contrib/rthooks/pyi_rth_osgeo.py,sha256=3REIgW6smeuQhOkiO2OkQ0K6YSqppDHFOmgnJ6AlTZk,1090 +_pyinstaller_hooks_contrib/rthooks/pyi_rth_pygraphviz.py,sha256=G5baiXo35aEQuqdzrRqmPd9BVhdsv5xO9O-5WJvdSpk,1076 +_pyinstaller_hooks_contrib/rthooks/pyi_rth_pyproj.py,sha256=GBehG9sdgrdac6t47V-6azNz5CCjbVegCeezuajdC9k,754 +_pyinstaller_hooks_contrib/rthooks/pyi_rth_pyqtgraph_multiprocess.py,sha256=1ZmW_cic9OaOrojd1RknjTgvn7N6_C53Ej0imuuwEzE,2375 +_pyinstaller_hooks_contrib/rthooks/pyi_rth_pythoncom.py,sha256=HYSYLvFIWF2p_-VBreDLFLLkux2WzUFvxJX3dmuDyu8,1259 +_pyinstaller_hooks_contrib/rthooks/pyi_rth_pywintypes.py,sha256=HYSYLvFIWF2p_-VBreDLFLLkux2WzUFvxJX3dmuDyu8,1259 +_pyinstaller_hooks_contrib/rthooks/pyi_rth_tensorflow.py,sha256=5iE26zQTgDcjxvnSKy_CCXpJOLVN9-6cQEeFpb_8h34,2665 +_pyinstaller_hooks_contrib/rthooks/pyi_rth_traitlets.py,sha256=6zxDqoyDuCwvg7u-Xu13zsW1hN58Ns8TGqEA06mytow,806 +_pyinstaller_hooks_contrib/rthooks/pyi_rth_usb.py,sha256=_FTLys4_Nj-9oYM0n8N-_d9P5TQ5Z7D3Z_-FRcXheMg,2799 +_pyinstaller_hooks_contrib/stdhooks/__init__.py,sha256=XqTB__uJKeDTb84jwHlEmqemORWifP5u1Qi4lRzoTqo,420 +_pyinstaller_hooks_contrib/stdhooks/__pycache__/__init__.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-BTrees.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-CTkMessagebox.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-Crypto.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-Cryptodome.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-HtmlTestRunner.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-IPython.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-OpenGL.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-OpenGL_accelerate.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-PyTaskbar.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-Xlib.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-_mssql.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-_mysql.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-accessible_output2.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-adbutils.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-adios.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-afmformats.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-aliyunsdkcore.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-altair.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-amazonproduct.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-anyio.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-appdirs.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-appy.pod.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-apscheduler.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-argon2.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-astor.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-astroid.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-astropy.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-astropy_iers_data.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-av.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-avro.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-azurerm.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-backports.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-backports.zoneinfo.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-bacon.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-bcrypt.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-bitsandbytes.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-bleak.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-blspy.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-bokeh.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-boto.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-boto3.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-botocore.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-branca.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cairocffi.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cairosvg.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-capstone.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cassandra.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-celpy.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-certifi.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cf_units.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cftime.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-charset_normalizer.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cloudpickle.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cloudscraper.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-clr.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-clr_loader.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cmocean.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-compliance_checker.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-comtypes.client.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-countrycode.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-countryinfo.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cryptography.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-customtkinter.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cv2.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cx_Oracle.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-cytoolz.itertoolz.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dash.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dash_bootstrap_components.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dash_core_components.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dash_html_components.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dash_renderer.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dash_table.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dash_uploader.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dask.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-datasets.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dateparser.utils.strptime.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dbus_fast.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dclab.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-detectron2.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-discid.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-distorm3.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dns.rdata.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-docutils.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-docx.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-docx2pdf.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-dynaconf.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-easyocr.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eel.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-enchant.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eng_to_ipa.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ens.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-enzyme.parsers.ebml.core.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_abi.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_account.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_hash.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_keyfile.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_keys.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_rlp.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_typing.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_utils.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-eth_utils.network.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-exchangelib.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-fabric.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-fairscale.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-faker.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-falcon.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-fastai.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-fastparquet.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ffpyplayer.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-fiona.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-flask_compress.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-flask_restx.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-flex.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-flirpy.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-fmpy.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-folium.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-freetype.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-fvcore.nn.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gadfly.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gbulb.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gcloud.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-geopandas.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gitlab.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gmplot.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gmsh.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gooey.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.api_core.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.cloud.bigquery.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.cloud.core.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.cloud.kms_v1.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.cloud.pubsub_v1.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.cloud.speech.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.cloud.storage.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-google.cloud.translate.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-googleapiclient.model.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-grapheme.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-graphql_query.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-great_expectations.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gribapi.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-grpc.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gst._gst.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-gtk.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-h3.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-h5py.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-hdf5plugin.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-hexbytes.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-httplib2.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-humanize.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-hydra.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ijson.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-imageio.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-imageio_ffmpeg.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-iminuit.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-iso639.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-itk.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jaraco.text.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jedi.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jieba.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jinja2.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jinxed.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jira.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jsonpath_rw_ext.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jsonrpcserver.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jsonschema.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jsonschema_specifications.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-jupyterlab.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-kaleido.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-khmernltk.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-kinterbasdb.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-langchain.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-langcodes.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-langdetect.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-laonlp.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lark.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ldfparser.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lensfunpy.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-libaudioverse.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-librosa.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lightgbm.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lightning.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-limits.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-linear_operator.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lingua.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-litestar.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-llvmlite.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-logilab.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lxml.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lxml.etree.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lxml.isoschematron.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lxml.objectify.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-lz4.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-magic.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-mako.codegen.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-mariadb.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-markdown.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-mecab.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-metpy.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-migrate.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-mimesis.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-minecraft_launcher_lib.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-mistune.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-mnemonic.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-monai.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-moviepy.audio.fx.all.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-moviepy.video.fx.all.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-mpl_toolkits.basemap.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-msoffcrypto.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nacl.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-names.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nanite.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nbconvert.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nbdime.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nbformat.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nbt.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ncclient.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-netCDF4.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nltk.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nnpy.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-notebook.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-numba.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-numbers_parser.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-numcodecs.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cublas.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cuda_cupti.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cuda_nvcc.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cuda_nvrtc.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cuda_runtime.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cudnn.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cufft.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.curand.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cusolver.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.cusparse.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.nccl.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.nvjitlink.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-nvidia.nvtx.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-office365.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-onnxruntime.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-opencc.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-openpyxl.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-opentelemetry.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-orjson.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-osgeo.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pandas_flavor.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-panel.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-parsedatetime.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-parso.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-passlib.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-paste.exceptions.reporter.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-patoolib.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-patsy.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pdfminer.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pendulum.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-phonenumbers.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pingouin.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pint.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pinyin.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-platformdirs.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-plotly.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pptx.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-prettytable.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-psutil.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-psychopy.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-psycopg2.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-publicsuffix2.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pubsub.core.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-puremagic.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-py.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyarrow.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pycountry.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pycparser.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pycrfsuite.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pydantic.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pydicom.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pydivert.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel-io.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel-ods.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel-ods3.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel-odsr.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel-xls.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel-xlsx.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel-xlsxw.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel_io.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel_ods.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel_ods3.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel_odsr.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel_xls.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel_xlsx.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcel_xlsxw.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyexcelerate.Writer.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pygraphviz.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pygwalker.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pylibmagic.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pylint.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pylsl.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pymediainfo.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pymorphy3.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pymssql.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pynput.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyodbc.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyopencl.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pypemicro.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyphen.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyppeteer.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyproj.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pypsexec.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pypylon.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyqtgraph.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyshark.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pysnmp.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pystray.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pytest.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pythainlp.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pythoncom.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyttsx.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyttsx3.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyviz_comms.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pyvjoy.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pywintypes.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-pywt.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-qtmodern.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-radicale.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-raven.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-rawpy.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-rdflib.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-redmine.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-regex.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-reportlab.lib.utils.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-reportlab.pdfbase._fontdata.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-resampy.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-rlp.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-rpy2.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-rtree.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-rubicon.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sacremoses.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-saml2.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-schwifty.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-seedir.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-selenium.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sentry_sdk.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-setuptools_scm.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-shapely.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-shotgun_api3.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-simplemma.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.color.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.data.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.draw.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.exposure.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.feature.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.filters.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.future.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.graph.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.io.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.measure.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.metrics.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.morphology.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.registration.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.restoration.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skimage.transform.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.cluster.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.linear_model.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.metrics.cluster.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.metrics.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.metrics.pairwise.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.neighbors.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.tree.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sklearn.utils.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-skyfield.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-slixmpp.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sound_lib.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sounddevice.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-soundfile.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-spacy.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-speech_recognition.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-spiceypy.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-spnego.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-srsly.msgpack._packer.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sspilib.raw.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-statsmodels.tsa.statespace.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-stdnum.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-storm.database.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sudachipy.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sunpy.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sv_ttk.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-swagger_spec_validator.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-sympy.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-tableauhyperapi.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-tables.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-tcod.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-tensorflow.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-text_unidecode.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-textdistance.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-thinc.backends.numpy_ops.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-thinc.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-timezonefinder.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-timm.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-tinycss2.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-toga.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-toga_cocoa.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-toga_gtk.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-toga_winforms.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-torch.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-torchaudio.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-torchtext.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-torchvision.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-torchvision.io.image.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_client.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_code.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_components.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_datagrid.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_deckgl.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_formkit.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_grid.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_iframe.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_keycloak.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_leaflet.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_markdown.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_matplotlib.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_mesh_streamer.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_plotly.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_pvui.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_quasar.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_rca.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_router.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_simput.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_tauri.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_tweakpane.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_vega.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_vtk.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_vtk3d.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_vtklocal.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_vuetify.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trame_xterm.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-transformers.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-travertino.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-trimesh.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-triton.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ttkthemes.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ttkwidgets.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-tzdata.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-tzwhere.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-u1db.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-ultralytics.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-umap.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-unidecode.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-uniseg.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-usb.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-uvicorn.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-uvloop.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-vaderSentiment.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-vtkpython.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-wavefile.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-weasyprint.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-web3.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-webassets.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-webrtcvad.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-websockets.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-webview.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-win32com.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-wordcloud.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-workflow.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-wx.lib.activex.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-wx.lib.pubsub.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-wx.xrc.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-xarray.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-xml.dom.html.HTMLDocument.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-xml.sax.saxexts.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-xmldiff.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-xmlschema.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-xsge_gui.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-xyzservices.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-yapf_third_party.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-z3c.rml.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-zeep.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-zmq.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/__pycache__/hook-zoneinfo.cpython-311.pyc,, +_pyinstaller_hooks_contrib/stdhooks/hook-BTrees.py,sha256=7H9uPnxAIrlAlMRCpdB5R3EbW-A5LIwzQAGRqvYG3-s,581 +_pyinstaller_hooks_contrib/stdhooks/hook-CTkMessagebox.py,sha256=02LmjIn8U1VELdrxTS0a35PutAP4nKF8ZR99WfIwxvE,663 +_pyinstaller_hooks_contrib/stdhooks/hook-Crypto.py,sha256=ImifI41XPN7GRu8DXatzHp4gC0mcFeIYIjnsgNRABq4,2320 +_pyinstaller_hooks_contrib/stdhooks/hook-Cryptodome.py,sha256=a_fbq7kjC1Zz7qjX5UDYFww7jXZ_Np0PVRE9wY1rCHI,1441 +_pyinstaller_hooks_contrib/stdhooks/hook-HtmlTestRunner.py,sha256=thy5tcQy3lL8tYq_PVJKeqXH1XkOQwlz2xMYvNPDVHc,598 +_pyinstaller_hooks_contrib/stdhooks/hook-IPython.py,sha256=kKCfeaEb5xK2cfzsL0APdYiWOM-j3X2oPLtpOS1XaFY,1358 +_pyinstaller_hooks_contrib/stdhooks/hook-OpenGL.py,sha256=W-blhzRK3eicSxqRQ4tviS9svMs1nIX2DcML0fxeEgU,2153 +_pyinstaller_hooks_contrib/stdhooks/hook-OpenGL_accelerate.py,sha256=5yYETP_dLQwMiTaJMdPxTZPl7gqnVL11gyFcQkoTIf4,761 +_pyinstaller_hooks_contrib/stdhooks/hook-PyTaskbar.py,sha256=hu3r-jyXMpgGe5d6oT4WTKHsadgxvdkCMPRJt3r-JBw,516 +_pyinstaller_hooks_contrib/stdhooks/hook-Xlib.py,sha256=5xU-W0ViBe9fJzkCn9N0hwXQcotayyIJeJEhiDLFNGU,520 +_pyinstaller_hooks_contrib/stdhooks/hook-_mssql.py,sha256=V_j3fb9LsniyK2lWFHnpYLU_s2B2hIk0wEcFQbmye44,446 +_pyinstaller_hooks_contrib/stdhooks/hook-_mysql.py,sha256=7xdzIT7I98Sskkr4khJDGFqdl9wzr7BykdwZWDwGWgE,544 +_pyinstaller_hooks_contrib/stdhooks/hook-accessible_output2.py,sha256=Ua9KkGnbwt-vZqVBIDTQyI-CWRnonhz1RrxTUMrV8HQ,606 +_pyinstaller_hooks_contrib/stdhooks/hook-adbutils.py,sha256=QF2KWHkLivI_UaZLavIRYXdG_x4QnFmX5Wg10vF86Pw,1068 +_pyinstaller_hooks_contrib/stdhooks/hook-adios.py,sha256=3QjwQJxqlXbxDFZLE5V6KxlB5wKe7EWnQ4CPdeGiork,514 +_pyinstaller_hooks_contrib/stdhooks/hook-afmformats.py,sha256=GigubbKoElF8fyK11_ZjoWl_qATq29-o27GczSDAxNg,582 +_pyinstaller_hooks_contrib/stdhooks/hook-aliyunsdkcore.py,sha256=69Q48xGmEUNWohujaq8wgrzl5u-9Jf_EAWF0QblmYeU,520 +_pyinstaller_hooks_contrib/stdhooks/hook-altair.py,sha256=bt3IHynMXZPiD_Lgo_o4WkJ7YcaVfJx6fqGte1nSsOw,514 +_pyinstaller_hooks_contrib/stdhooks/hook-amazonproduct.py,sha256=l0CZhE6sGsuQNSW5B4pXkS0ggLPhf3HbpqSAqAsDL2o,1063 +_pyinstaller_hooks_contrib/stdhooks/hook-anyio.py,sha256=_JkaNd7mliBObKBivEGOJr7PME8fj0x-k7v4v-vfyps,652 +_pyinstaller_hooks_contrib/stdhooks/hook-appdirs.py,sha256=zyPFyUQeR2msS9V_jCqkHlbxKEI4F7fwcenRR_-_VPo,736 +_pyinstaller_hooks_contrib/stdhooks/hook-appy.pod.py,sha256=zXYSVcOaM1Rd5-7XHbdhXcPkXdp2F_Q-2haf-ePtTPM,584 +_pyinstaller_hooks_contrib/stdhooks/hook-apscheduler.py,sha256=JYZ3WCI-UvxHxlkub7BPtcgAC7rIvnmZu_lv8ug4SfE,958 +_pyinstaller_hooks_contrib/stdhooks/hook-argon2.py,sha256=uL9MNx-TVv7xkU6Yna7ZAut_lpmhfU3JtlxqXZPeCz8,455 +_pyinstaller_hooks_contrib/stdhooks/hook-astor.py,sha256=39fA7fjiii_16lKjKfIloHL_XBLZmiLY51EiVLDsdUc,513 +_pyinstaller_hooks_contrib/stdhooks/hook-astroid.py,sha256=c3vLz5R9gpXH1LMgGmgK2M4AyO6GNbjh5F2l9W4wM64,2096 +_pyinstaller_hooks_contrib/stdhooks/hook-astropy.py,sha256=VHGCBTgpzR91qWHyY6RJYvRhpc7dgAGjHLu6WiaHVUM,1744 +_pyinstaller_hooks_contrib/stdhooks/hook-astropy_iers_data.py,sha256=V_rB5H1YPNN8lDpMgItXXPjc5XGLdhm76U0L7I52mZw,581 +_pyinstaller_hooks_contrib/stdhooks/hook-av.py,sha256=j-tpSaAvpyiixxF98-WM-hdVm2kH1dFFDbJwv_4tvtY,2082 +_pyinstaller_hooks_contrib/stdhooks/hook-avro.py,sha256=RRQmqN-5RXPobRHPHO5vNnv-ZPzeQ-0lRoWknxWEkK4,981 +_pyinstaller_hooks_contrib/stdhooks/hook-azurerm.py,sha256=r9O9s3r438qfrR_gFEipp4DzoiVzdxVclosv53Vum0Y,838 +_pyinstaller_hooks_contrib/stdhooks/hook-backports.py,sha256=r0UIln-d8ep_5CTIr1dfV3mHd8SnbJfKgoBVhUbcSp8,905 +_pyinstaller_hooks_contrib/stdhooks/hook-backports.zoneinfo.py,sha256=99A9LN6khAbUAQfey6FaTHtdGZEaaOjavxwawAzbTdo,595 +_pyinstaller_hooks_contrib/stdhooks/hook-bacon.py,sha256=lqd0CnY45BUEVurtqc1VV92ltGnOjjTKfErgLeeBW-w,1675 +_pyinstaller_hooks_contrib/stdhooks/hook-bcrypt.py,sha256=hhNZqKFF5qODocZJ5lBRFdDtJdRBYoiryhtOoSn0jbc,505 +_pyinstaller_hooks_contrib/stdhooks/hook-bitsandbytes.py,sha256=qRx2M9xhKA4qVKLTWYDIee4SlkN4T6z1b5exIssYC3w,1117 +_pyinstaller_hooks_contrib/stdhooks/hook-bleak.py,sha256=Zm9WX0NmPZPbdTh-6pXhO0GFqvKFzXoGBarYngpXk0M,702 +_pyinstaller_hooks_contrib/stdhooks/hook-blspy.py,sha256=KCo9qWmcFhveIvngEgyNALozIAVKp-9DyaE7hs6F9rw,1407 +_pyinstaller_hooks_contrib/stdhooks/hook-bokeh.py,sha256=-8OUbeppabAY3qVGLWtJC0tqMbgq0W1yvBnKCU4pD4w,922 +_pyinstaller_hooks_contrib/stdhooks/hook-boto.py,sha256=JUGaLqkuSl8u7bO5UlEBoC0T3semsBxQlpr_yDxokUM,786 +_pyinstaller_hooks_contrib/stdhooks/hook-boto3.py,sha256=pI5miSDkHOUA9qHlh4-0lD8odMRD09NS-rLCXU0r-xQ,999 +_pyinstaller_hooks_contrib/stdhooks/hook-botocore.py,sha256=N3hZC_AoVGhB03Pk-nVmM5ezpXtrfaVaEPYwPLZ6sJ8,1067 +_pyinstaller_hooks_contrib/stdhooks/hook-branca.py,sha256=fYU2gaKNBRbG399Vif6CR61fPnDXkr1mzyihcG6cSqM,514 +_pyinstaller_hooks_contrib/stdhooks/hook-cairocffi.py,sha256=xFSRmFXxpK5g4cSfEyUHNMZiJZ-YQ1gzujICk056ch8,1596 +_pyinstaller_hooks_contrib/stdhooks/hook-cairosvg.py,sha256=LtlVNSqrF7mVxHZSYPY1n_8zZUqNhRYG-FuvRgAxkgQ,1303 +_pyinstaller_hooks_contrib/stdhooks/hook-capstone.py,sha256=aaFGgiFLPyUBTtsUQdU6bfzWNTDt6OfzhcaEJloxxrE,562 +_pyinstaller_hooks_contrib/stdhooks/hook-cassandra.py,sha256=-VhGeIvcKJJi8Okp3_cGGKBjStNr8iAB7H-8i1lqr8Q,832 +_pyinstaller_hooks_contrib/stdhooks/hook-celpy.py,sha256=k7jxOzOFwfwXI7cHslOivG6MSuQOWAqv5cwk7bejuts,979 +_pyinstaller_hooks_contrib/stdhooks/hook-certifi.py,sha256=kCFePXDxRwHIQdgFe4DeV-RhS-n33EGeApVuetO9omA,735 +_pyinstaller_hooks_contrib/stdhooks/hook-cf_units.py,sha256=13FWN2RadSk-yJuUkyjGUwqu9yP1xuJzWff5jKWmUS0,591 +_pyinstaller_hooks_contrib/stdhooks/hook-cftime.py,sha256=3rVzaTYOkzhwKOYGO5hpzKJt2dM45hPIUlJTMz01DA4,605 +_pyinstaller_hooks_contrib/stdhooks/hook-charset_normalizer.py,sha256=B9lqK-U2QxEjzf1zUUdZmiXRi9satc2xBGtvp5vIb-0,586 +_pyinstaller_hooks_contrib/stdhooks/hook-cloudpickle.py,sha256=HIrogozsv_bflq62cOENJ80BwrRzgZ2TH2r4zx5oPbA,776 +_pyinstaller_hooks_contrib/stdhooks/hook-cloudscraper.py,sha256=DUQsQhydlJBLnrJ5lLTvxA3CHKXZr4jfPkw1EhRlN04,520 +_pyinstaller_hooks_contrib/stdhooks/hook-clr.py,sha256=HkUhiIpLUJ1sZPpsrIvZtKLnJDRGvkVsKPgt8ERGfaI,2600 +_pyinstaller_hooks_contrib/stdhooks/hook-clr_loader.py,sha256=r6shf_xCOoGitgm3mje_tmpvOyCuPzZHmRpG9QPAMRs,954 +_pyinstaller_hooks_contrib/stdhooks/hook-cmocean.py,sha256=vwCbQwhokfcEO9Mt1jVSY952Nnxlv-QNort_Hj5v0AA,529 +_pyinstaller_hooks_contrib/stdhooks/hook-compliance_checker.py,sha256=wM6-xACzS3QuiXcXbNNvCqN_yx66bQu5hAWLirMYk-U,988 +_pyinstaller_hooks_contrib/stdhooks/hook-comtypes.client.py,sha256=iN0OgoMpMvIk1b3_ax9IdFyjKD3DSVDC4n3f3Dm7iwk,683 +_pyinstaller_hooks_contrib/stdhooks/hook-countrycode.py,sha256=1hqqPNPpQxOw78iFqOjkPv0JhpOD9_eiGZQRmuoNF5Y,519 +_pyinstaller_hooks_contrib/stdhooks/hook-countryinfo.py,sha256=z_QVmMe89k1f5n4R23mUQi2wUxiCdKvpU9LlKEGmQ_0,565 +_pyinstaller_hooks_contrib/stdhooks/hook-cryptography.py,sha256=oPbDqHZW9TSd2BYX6oxP3YSSPFv2S2WhY9mnpKkoVhs,5815 +_pyinstaller_hooks_contrib/stdhooks/hook-customtkinter.py,sha256=po89SWrZ1MnlliL1rpaiOdrdR7SZ3sYgeNA-IKdOCpE,520 +_pyinstaller_hooks_contrib/stdhooks/hook-cv2.py,sha256=2D7U2s8858uZk64zKFEIVLAylkjcSKj0no6T362aBMU,8117 +_pyinstaller_hooks_contrib/stdhooks/hook-cx_Oracle.py,sha256=_UwEKqFgJmFfipDEBw9_L6ZFTTkHvaPBfzNhLAREhEo,449 +_pyinstaller_hooks_contrib/stdhooks/hook-cytoolz.itertoolz.py,sha256=Sd_M-AavngziR768WUNTDA0MqQJR2-_u-6ZXbrgWy8s,614 +_pyinstaller_hooks_contrib/stdhooks/hook-dash.py,sha256=JrWymJXOyzHaHHkVoezeLA-pSqKshptuwtJE_eG0AhE,512 +_pyinstaller_hooks_contrib/stdhooks/hook-dash_bootstrap_components.py,sha256=6D7QdcZoxz-g_8Tkunk8TI5i37TY2sDTkDgdAQp4jI0,533 +_pyinstaller_hooks_contrib/stdhooks/hook-dash_core_components.py,sha256=wc5HQi5SGVkduizRW334gtF_oK3G6rBRRC-lnz4gGw4,528 +_pyinstaller_hooks_contrib/stdhooks/hook-dash_html_components.py,sha256=7GCOEhBFjj-T8qLzN6h5KkkrkSXC-t9K1ih303pkQ-0,528 +_pyinstaller_hooks_contrib/stdhooks/hook-dash_renderer.py,sha256=wSmHKr_Kxi8V072QfEYaau1AhnfaXJfdrNsyprRVZLY,521 +_pyinstaller_hooks_contrib/stdhooks/hook-dash_table.py,sha256=GEeJRc0W2nl0YYmCmqMQIuRgexUErPSNqnfLoMmUg1o,518 +_pyinstaller_hooks_contrib/stdhooks/hook-dash_uploader.py,sha256=TqkZRZUpSBqwoYQn4zutn2sg6relzM5-TZFwXATTT9s,521 +_pyinstaller_hooks_contrib/stdhooks/hook-dask.py,sha256=RyVKpErefI3rx7k5aWdXXalIS3_sObOhS8ki3I8P4X0,636 +_pyinstaller_hooks_contrib/stdhooks/hook-datasets.py,sha256=L508elVV7ax33mODkIR3zrkCnahihoH7UIjheGAzCkM,557 +_pyinstaller_hooks_contrib/stdhooks/hook-dateparser.utils.strptime.py,sha256=wp34VFRBNFRL5WE99cFNe7IH56n11ydsToVj4JLh6gE,608 +_pyinstaller_hooks_contrib/stdhooks/hook-dbus_fast.py,sha256=fWCWWH1HVQcSttJs75snPaUJQGDJ3S01oMnr-hJjnJk,601 +_pyinstaller_hooks_contrib/stdhooks/hook-dclab.py,sha256=CfGdIi5A3LiYpmq36m3cSwk2by3PeZJO-jvZRgM7XhU,567 +_pyinstaller_hooks_contrib/stdhooks/hook-detectron2.py,sha256=L508elVV7ax33mODkIR3zrkCnahihoH7UIjheGAzCkM,557 +_pyinstaller_hooks_contrib/stdhooks/hook-discid.py,sha256=qh4NpkcK8iGOaZTlDaFzSZs1_vn77ZxJAr_cEVleoRg,1424 +_pyinstaller_hooks_contrib/stdhooks/hook-distorm3.py,sha256=2_5Bog4d91cSmurO9g3LOgHkeYr293elZ4-EJjKjGu8,736 +_pyinstaller_hooks_contrib/stdhooks/hook-dns.rdata.py,sha256=4qJuSXX7pXMEfAKtLA4nfzOY_wglG_AHV3JIKUEZQK4,577 +_pyinstaller_hooks_contrib/stdhooks/hook-docutils.py,sha256=92774IR5j_D9YEL2lFNB31k01Y5jCZg2iqsazEoAxps,798 +_pyinstaller_hooks_contrib/stdhooks/hook-docx.py,sha256=KMXfmjt7AnJoeTS6hfhNBJUggZMti1liAl4kD5hpQxk,512 +_pyinstaller_hooks_contrib/stdhooks/hook-docx2pdf.py,sha256=FKJp5FKPzgSsZFu8YxdNrKwMSbk-6vZvT2hma02vaS0,624 +_pyinstaller_hooks_contrib/stdhooks/hook-dynaconf.py,sha256=Ss3Gq19q0S9mbBRWVNH6k0_JgFMz-ZXUA68QNYmOUbw,569 +_pyinstaller_hooks_contrib/stdhooks/hook-easyocr.py,sha256=Y_Q-FawbXomqbqHzMxPF8yqo-8c-6dyCx4_rGrUXyjw,793 +_pyinstaller_hooks_contrib/stdhooks/hook-eel.py,sha256=AacHCZd4184RbnUFOLTYbkmKkJEQkGr3LdMqn1UXiBc,548 +_pyinstaller_hooks_contrib/stdhooks/hook-enchant.py,sha256=6mswnI2jCHY18DS5J4wnmHvrDAGKr8yBhBHzCe4j1uY,2851 +_pyinstaller_hooks_contrib/stdhooks/hook-eng_to_ipa.py,sha256=YDRMsxwI9VzlZn69TwuYiMC4jv-7elcnO3IEYFnRw2E,518 +_pyinstaller_hooks_contrib/stdhooks/hook-ens.py,sha256=3vC3d_ENo5JdDSq2ajWKfnR5WKC2OJQOdPJqjtn7sLA,511 +_pyinstaller_hooks_contrib/stdhooks/hook-enzyme.parsers.ebml.core.py,sha256=yS_g1AxOW2-R-1xKtBK0Q9EC_D9ylhVBrirH9tJ0-zY,722 +_pyinstaller_hooks_contrib/stdhooks/hook-eth_abi.py,sha256=NHm7ncjWCD_l2XdP6vBaxz5y516U_IL1P4YevtTtuRM,505 +_pyinstaller_hooks_contrib/stdhooks/hook-eth_account.py,sha256=wjvWKcrTK2fWp6S4pEm-o8NYc3g9mCbHVZuU035zFrc,509 +_pyinstaller_hooks_contrib/stdhooks/hook-eth_hash.py,sha256=lzNsLR5kuz2sXXxkym0HTko_393jucPnFCQDQd_g7zg,814 +_pyinstaller_hooks_contrib/stdhooks/hook-eth_keyfile.py,sha256=CYTnYWvRKUwVEjUTF1-O8gA3_uqKOHZpZJryaFVSFPc,509 +_pyinstaller_hooks_contrib/stdhooks/hook-eth_keys.py,sha256=4r5kmLTtARNZza-JoJP1rLL2RExMrwbxrTtxBsLIIQg,667 +_pyinstaller_hooks_contrib/stdhooks/hook-eth_rlp.py,sha256=kQWMVCiyc4htFsk1JySBkj74Q0QqrSjcD-C-C_xn5yI,643 +_pyinstaller_hooks_contrib/stdhooks/hook-eth_typing.py,sha256=c6ywwe1EhToKTbCbGmUGK6RUTD8oVwP5DGM6rl5JKPI,586 +_pyinstaller_hooks_contrib/stdhooks/hook-eth_utils.network.py,sha256=1dmUGrCLFa_xkiF5fNDYUom4SjnnI2t9yd5XSXl32Lw,517 +_pyinstaller_hooks_contrib/stdhooks/hook-eth_utils.py,sha256=ORE3BzSrHBDzqMjFR88iTm5VOvL7EPOjgLgP3caXoPU,507 +_pyinstaller_hooks_contrib/stdhooks/hook-exchangelib.py,sha256=PjUxCRbRboGbLZzFeehWOhPzr0jO11AYstKtsFQvRkw,447 +_pyinstaller_hooks_contrib/stdhooks/hook-fabric.py,sha256=H87in7hd-RG6PfQTmEulm_mG0sbs5rG3-H8gWfct96A,733 +_pyinstaller_hooks_contrib/stdhooks/hook-fairscale.py,sha256=c_35rJ4w0apax7S0Pnkz7gN0oM3fmbGYhhp1eo9rfHk,557 +_pyinstaller_hooks_contrib/stdhooks/hook-faker.py,sha256=6MMBGNG0oZC4wiq4FnFxqRimXOoNUHDeO8QCxNqdbfg,685 +_pyinstaller_hooks_contrib/stdhooks/hook-falcon.py,sha256=qOelGQSufRVtgZNH0DFMQtPFAl-9UbYXkgWIEIB74qg,1194 +_pyinstaller_hooks_contrib/stdhooks/hook-fastai.py,sha256=L508elVV7ax33mODkIR3zrkCnahihoH7UIjheGAzCkM,557 +_pyinstaller_hooks_contrib/stdhooks/hook-fastparquet.py,sha256=y3QWOzrz-Ra8H18SWDujD9dozbkzXR8BPesRWReYN-U,1469 +_pyinstaller_hooks_contrib/stdhooks/hook-ffpyplayer.py,sha256=WD4t4z-SQHZAe-bqIKVEwrWbIUhxQNn6io5PnPWL6UY,741 +_pyinstaller_hooks_contrib/stdhooks/hook-fiona.py,sha256=IjYbiaUeeKB_gq4lPM6OJDLAnXjLyiIyW5jp3cNZ_JA,860 +_pyinstaller_hooks_contrib/stdhooks/hook-flask_compress.py,sha256=UMHjLHHYDtnW50Y_MtQUZqJX0-cimZJsJsA3El6ZUJc,512 +_pyinstaller_hooks_contrib/stdhooks/hook-flask_restx.py,sha256=KnTudaPgYyQXgmDtjYQUJ_lVkUc9hvZOLNNO_Fa_LHo,546 +_pyinstaller_hooks_contrib/stdhooks/hook-flex.py,sha256=q7mHzzXLkNUYRZNJRz-60lvuPtHYoPYd3MUxue5Lh5E,551 +_pyinstaller_hooks_contrib/stdhooks/hook-flirpy.py,sha256=xmI3ET8t0j3rVUbN_4foknfB1W9QGFRZq0l6pa3u4h8,650 +_pyinstaller_hooks_contrib/stdhooks/hook-fmpy.py,sha256=ZLsw9nwYplOC9AZpYRS08WYech5yNW3LdYmbL1-oTqE,799 +_pyinstaller_hooks_contrib/stdhooks/hook-folium.py,sha256=J81aLD-9FBtrnO1XhRpZUQ6qNoRpvBkByYa45Xs_FbI,547 +_pyinstaller_hooks_contrib/stdhooks/hook-freetype.py,sha256=t1qrKUdxYInJIt0pplH-vsvLyt-YUJsbLobgPN0dGq4,584 +_pyinstaller_hooks_contrib/stdhooks/hook-fvcore.nn.py,sha256=L508elVV7ax33mODkIR3zrkCnahihoH7UIjheGAzCkM,557 +_pyinstaller_hooks_contrib/stdhooks/hook-gadfly.py,sha256=9mUNliNadIqvXXvQth9EPB6LdBfPWSbMYwumdy9m8NA,449 +_pyinstaller_hooks_contrib/stdhooks/hook-gbulb.py,sha256=QMzeWRQmulGUFSBGcyfjxTP3iDz_sf5ItOVyiENGCN4,574 +_pyinstaller_hooks_contrib/stdhooks/hook-gcloud.py,sha256=2g2hKGl7Zrvrqf3LoStiJlKyt-8HQsghwOCyxtyx2R4,793 +_pyinstaller_hooks_contrib/stdhooks/hook-geopandas.py,sha256=f48s1JU_xMkNmMqP_SC1mFsEP_wDmh6T3N0jWd6vGBE,536 +_pyinstaller_hooks_contrib/stdhooks/hook-gitlab.py,sha256=aG2RH2UnKEwxnWNRbC5qpiOF7_K0CC56TOS-lDaXtl0,735 +_pyinstaller_hooks_contrib/stdhooks/hook-gmplot.py,sha256=3ushmjY5pSdT1NogR2UQ7Gx6ICcBNCyvuoKb3-vSXsQ,519 +_pyinstaller_hooks_contrib/stdhooks/hook-gmsh.py,sha256=LDtlKdCjMuk5pCq-BC962k9LFvfDMpUy5y8GSNj0t98,999 +_pyinstaller_hooks_contrib/stdhooks/hook-gooey.py,sha256=bqarqbH4UYL6HayuYlxlwpdbupmsX6bh6wiaH_Bf0YQ,589 +_pyinstaller_hooks_contrib/stdhooks/hook-google.api_core.py,sha256=2bn_nmbQSXYrIryWoWSiQKZc_n366zmRGaygkb5CLF8,513 +_pyinstaller_hooks_contrib/stdhooks/hook-google.cloud.bigquery.py,sha256=HC9mpFSO_64lDE0NPt1x6jJ-8jDjQSJD5R8sclQ0bB8,616 +_pyinstaller_hooks_contrib/stdhooks/hook-google.cloud.core.py,sha256=KS3LQpaY_QdbB7dukd9-A4_XwlfNpZAAu7eFnABVHe8,515 +_pyinstaller_hooks_contrib/stdhooks/hook-google.cloud.kms_v1.py,sha256=63WBtHUc0Cmd5jaGGuDXpC7nfvMjy6B8GGs4Kr4hfHQ,709 +_pyinstaller_hooks_contrib/stdhooks/hook-google.cloud.pubsub_v1.py,sha256=NBN0AvXonoi8gVC7mbO9GcEkpgqvTJusw77cf8x9d58,517 +_pyinstaller_hooks_contrib/stdhooks/hook-google.cloud.speech.py,sha256=IDmBkM2IXW9stcNaPEZmdpo8zCyNJN_lARhDx3USKYE,517 +_pyinstaller_hooks_contrib/stdhooks/hook-google.cloud.storage.py,sha256=IPIqFK6fbDn1pfBoZz9Qblh3fd9yzFvv7tmEgcB52AM,518 +_pyinstaller_hooks_contrib/stdhooks/hook-google.cloud.translate.py,sha256=qEs34x4eIHlMbgXEYlF_lWsoS7WueJT4MuaVRrU3P3A,520 +_pyinstaller_hooks_contrib/stdhooks/hook-googleapiclient.model.py,sha256=E-iDIuZc6ZVAdREtV3N3HLpytuL6I8ZQEtiUanbYlCo,852 +_pyinstaller_hooks_contrib/stdhooks/hook-grapheme.py,sha256=qZDgWdsOXerr29TAVkT6Kf74WnAWL_4Sln-09f-t_tA,516 +_pyinstaller_hooks_contrib/stdhooks/hook-graphql_query.py,sha256=KJUnT5Mw7j2bRecW2sRQ6qCRtUUuzF9r6wJ5lqWb-Ow,623 +_pyinstaller_hooks_contrib/stdhooks/hook-great_expectations.py,sha256=lGEsG7c8SCYYqTTkIq5-lFH5y8HXumf0XiE6wnj7J1k,526 +_pyinstaller_hooks_contrib/stdhooks/hook-gribapi.py,sha256=3MYOhV30T2NYugbHORnjj4B8DcoUFdNnjlMscYAdMKs,3607 +_pyinstaller_hooks_contrib/stdhooks/hook-grpc.py,sha256=LOSNA9INFfZNN3ExRQgVuof--iX63covoc_Qak_Vf8M,512 +_pyinstaller_hooks_contrib/stdhooks/hook-gst._gst.py,sha256=pUwgQGZvZcqc0B17mKrQkjO9HK6LJVvT2bOESNH0CaU,1324 +_pyinstaller_hooks_contrib/stdhooks/hook-gtk.py,sha256=fsCK_gJ-Gr3wQwp6KKA3Schnp5M7fCaHVKW_17aSEXU,667 +_pyinstaller_hooks_contrib/stdhooks/hook-h3.py,sha256=l02ffSxT6gn8TGL-Gy6Ckp7S3wwHTZNWggBm8NALNWw,633 +_pyinstaller_hooks_contrib/stdhooks/hook-h5py.py,sha256=gBakBqcfHnzCv2_OmERWW2Ec74l_W4i_jKRGlSK5dl4,544 +_pyinstaller_hooks_contrib/stdhooks/hook-hdf5plugin.py,sha256=VXWPfqygkI3MEqgtYwMId1y9stV1hw2cgxzKdClYIPI,583 +_pyinstaller_hooks_contrib/stdhooks/hook-hexbytes.py,sha256=xNwjMe8uKcWA38uvakQD2Ai82Fpnlq2U00vFSEqXRUE,646 +_pyinstaller_hooks_contrib/stdhooks/hook-httplib2.py,sha256=jfXcSWs7-Y6rZnTzMdn8EeWZ2gIrQ853PjJS0Q5EUkU,588 +_pyinstaller_hooks_contrib/stdhooks/hook-humanize.py,sha256=jrrLXtdJHGahTfb9PJ87bYvF_NWeQIeNCdv03Tsq_rs,785 +_pyinstaller_hooks_contrib/stdhooks/hook-hydra.py,sha256=OS29zE6K1PfxfIjqhjrVB0gEBMIGuBItM1PfIrJpfiA,1627 +_pyinstaller_hooks_contrib/stdhooks/hook-ijson.py,sha256=3aBT5U_9srfc87VKclEFjnhfspLFqARnBtVS4eQ4GiE,530 +_pyinstaller_hooks_contrib/stdhooks/hook-imageio.py,sha256=vJhTwA3FFwJtM2PpBYs8KbE61ZMZ2EmAY_5aVoybPvo,793 +_pyinstaller_hooks_contrib/stdhooks/hook-imageio_ffmpeg.py,sha256=2-sPmk5OXOCJM2n4_OFPLLTsjwVdLc5Gm9TPfG-Oyno,905 +_pyinstaller_hooks_contrib/stdhooks/hook-iminuit.py,sha256=N5CFLEfIobQAEBX8QDaC5dXmmRiKeW6hoQiZw1H8oN4,843 +_pyinstaller_hooks_contrib/stdhooks/hook-iso639.py,sha256=1EpKUHp9Is6cXqKg_xZGt2WXD6YzXDvkhvwp1UIEWzQ,546 +_pyinstaller_hooks_contrib/stdhooks/hook-itk.py,sha256=zKRK27k3FbTapA4qND2cRBTpuZLomDytNapCoprjQzA,784 +_pyinstaller_hooks_contrib/stdhooks/hook-jaraco.text.py,sha256=fyTyuTGQtSohmuztyrpqnhNMypIpuDqydCfDgjxgNYw,586 +_pyinstaller_hooks_contrib/stdhooks/hook-jedi.py,sha256=UV5c9XwxrJbidPDmA6XsOxTvz80t2ApH7gwfpB7rw-c,584 +_pyinstaller_hooks_contrib/stdhooks/hook-jieba.py,sha256=0jVycYYGjL1l5VhuzqOuNbrqtH4r8NCsUM2NEazptZ4,513 +_pyinstaller_hooks_contrib/stdhooks/hook-jinja2.py,sha256=FFEjO4CoqIlIFVGrdE1dczGexwhjtpUM3rfI3iMj9rE,452 +_pyinstaller_hooks_contrib/stdhooks/hook-jinxed.py,sha256=4Gb2axZd_-IZOsehrDA77EU3UiJgSinNt3AZ8TqHyZg,498 +_pyinstaller_hooks_contrib/stdhooks/hook-jira.py,sha256=MmTbxQc6MyvmGkkVeCHW2I3LrTu5A9LqYiErBBQnnIc,617 +_pyinstaller_hooks_contrib/stdhooks/hook-jsonpath_rw_ext.py,sha256=g9VVlyJm5vG6WfOFL39F4cAOpzoFQRbeQbLgw9l6Zvg,513 +_pyinstaller_hooks_contrib/stdhooks/hook-jsonrpcserver.py,sha256=uWOOdTGQqG3DvJNXrH5RieeiXp-EiCIyEmj6c4TMSTU,608 +_pyinstaller_hooks_contrib/stdhooks/hook-jsonschema.py,sha256=qmhcVRvyD_Zp18NsI53HIDfG25LdT7Aumw7W4n37Uqs,828 +_pyinstaller_hooks_contrib/stdhooks/hook-jsonschema_specifications.py,sha256=kDKzf09IHlbHzq2Ks4Tl40iN6WrxQfWPjpn3DYnWseI,532 +_pyinstaller_hooks_contrib/stdhooks/hook-jupyterlab.py,sha256=TU3o0IgEU9y9fyv5PsHzsKiadmXvvTxHyLYcLYzUQhk,518 +_pyinstaller_hooks_contrib/stdhooks/hook-kaleido.py,sha256=VQMvkWK3B1bSOmaKUZuSx_BHyAhMW2goRmZzEqGHYas,515 +_pyinstaller_hooks_contrib/stdhooks/hook-khmernltk.py,sha256=9RQud3NQliAQCtgo8hwQaS1Z5TKAc1he4zQ6bfeYMk8,554 +_pyinstaller_hooks_contrib/stdhooks/hook-kinterbasdb.py,sha256=cztOr2aUEqQ8d5qpQpuEAridpYruESuhfxBWSlJ6QoE,843 +_pyinstaller_hooks_contrib/stdhooks/hook-langchain.py,sha256=Ot2OiUOmUdzd_eK3Lmsp-p9N9BjwZvTEYjukprNaxxQ,517 +_pyinstaller_hooks_contrib/stdhooks/hook-langcodes.py,sha256=7hkFTGFSzn0DxY4NV1UEKodps6H6r4bYXUTojIFfhX4,517 +_pyinstaller_hooks_contrib/stdhooks/hook-langdetect.py,sha256=Qz0siDS9evVsqD3_OP2AgNpCz80qZ-hbfWUXs1ELtI4,518 +_pyinstaller_hooks_contrib/stdhooks/hook-laonlp.py,sha256=ZdENgKj_FFxnJfMoylOOouTn9UO2ifsamzT_PaWm-C0,514 +_pyinstaller_hooks_contrib/stdhooks/hook-lark.py,sha256=zQzLT5Uu5jzKTDvGu377iTWbzW77LhJV_W-vDcnmHI0,512 +_pyinstaller_hooks_contrib/stdhooks/hook-ldfparser.py,sha256=EIwxRlqMm2cOBgY6l1kgiJu_mTCX5lAryYty-I4FkZ0,527 +_pyinstaller_hooks_contrib/stdhooks/hook-lensfunpy.py,sha256=mPlp2664ax5tALxpyFiMsl_IQMBb746yMUD4bi8cS1I,665 +_pyinstaller_hooks_contrib/stdhooks/hook-libaudioverse.py,sha256=Y0tna0zcvXUUd5GFAhPWtPYv7wdrrcFt84HPecw-Sm8,598 +_pyinstaller_hooks_contrib/stdhooks/hook-librosa.py,sha256=rGNfBzWJENA4pBcL2r7-mtkQo9itqSu3JMyBfPpP5Yg,1178 +_pyinstaller_hooks_contrib/stdhooks/hook-lightgbm.py,sha256=70sAQmPVTOmG4N2tlwoCx8IAJi4u9L7ETQtFJzST2gI,937 +_pyinstaller_hooks_contrib/stdhooks/hook-lightning.py,sha256=7t0rY7UaocV5G_o09y1tNygCuilGCVX7XMG0sUfqEWw,834 +_pyinstaller_hooks_contrib/stdhooks/hook-limits.py,sha256=KvoW_h8Y_wcVkE_vlFIasuZ4S94kSKYdSlm1Ixg3_KI,514 +_pyinstaller_hooks_contrib/stdhooks/hook-linear_operator.py,sha256=amNNgp4raSBDaxNePyQVBov8_HzAhRflS66FWxljFQ0,542 +_pyinstaller_hooks_contrib/stdhooks/hook-lingua.py,sha256=gesRIVvBsRj3D4FWRY0jyMsQXR9uWs-mxWD3lruevdc,514 +_pyinstaller_hooks_contrib/stdhooks/hook-litestar.py,sha256=xJ3Y0Fj2sbkjFUhXiZIpUUsP9X81Z0bw7iGQ03Xif6o,531 +_pyinstaller_hooks_contrib/stdhooks/hook-llvmlite.py,sha256=B3-ddCSih9fqn8mbdY23YoENrC8s7rNw8WrMiSWgYmA,705 +_pyinstaller_hooks_contrib/stdhooks/hook-logilab.py,sha256=yb-uN2Rg-1ihtwse8jrTjHIMjNU6nmj1bEA4wIrPFNg,939 +_pyinstaller_hooks_contrib/stdhooks/hook-lxml.etree.py,sha256=XF1VE0AnAth1M-K6uYgtMCeFxfamSy7SLC4dH5-iee8,481 +_pyinstaller_hooks_contrib/stdhooks/hook-lxml.isoschematron.py,sha256=sKerEc6cSSX7CkkMWKfLRYHd-mu_iH0iQUrsp_MZXpM,608 +_pyinstaller_hooks_contrib/stdhooks/hook-lxml.objectify.py,sha256=MZX0zqo3_F6E4k0MS2A0iNF6QMGVD9fHhd2Ma0cXv9g,452 +_pyinstaller_hooks_contrib/stdhooks/hook-lxml.py,sha256=luxF2PUPGJFBDZY6Y486XEfhPowPSgzB_AKE-H7Xgig,673 +_pyinstaller_hooks_contrib/stdhooks/hook-lz4.py,sha256=FtaB7EdUUQc85tIhSDLhdTqauinP4RoyaqtQDbacmyk,553 +_pyinstaller_hooks_contrib/stdhooks/hook-magic.py,sha256=tBNg4y0dohfsfx2au3pHY8Sa56zkwRiqd2QdNY2P8o8,630 +_pyinstaller_hooks_contrib/stdhooks/hook-mako.codegen.py,sha256=jxcMKzHiK-n92wy4pA1WNbvZi-j6Icsu6RRU_wI1_z4,608 +_pyinstaller_hooks_contrib/stdhooks/hook-mariadb.py,sha256=8VjEMveHwCNh0SmJhs3IF5BpdrC-vq-oCsf59E4Hilk,1102 +_pyinstaller_hooks_contrib/stdhooks/hook-markdown.py,sha256=GuzXwF811hd-X4plC2JpxsnPZ8_iiXhDp0UcODyDaDg,957 +_pyinstaller_hooks_contrib/stdhooks/hook-mecab.py,sha256=TmOaHmDsVqUhHWqIJs9dKGL-T3AECAVLkGx8KjLj0y0,557 +_pyinstaller_hooks_contrib/stdhooks/hook-metpy.py,sha256=C-jKRq46CqsM8RDxDWvqgJzzjutzdVmbG1QyZZtzsWE,763 +_pyinstaller_hooks_contrib/stdhooks/hook-migrate.py,sha256=wzhAF5oPLYG2SBnK4h_4Rvd-x3hxJvCXYgdZlTutYTE,743 +_pyinstaller_hooks_contrib/stdhooks/hook-mimesis.py,sha256=njbgWuTJAA7W-l-EtiUU6G7xaRO3yP6ifjLJ1n1aScc,616 +_pyinstaller_hooks_contrib/stdhooks/hook-minecraft_launcher_lib.py,sha256=N6mf05sx3DX6pD1brbLuH6ftqMvA4fd_vi97FzBX3ec,529 +_pyinstaller_hooks_contrib/stdhooks/hook-mistune.py,sha256=9_blbpnB___kQ7gGpnJevHCjuGOVG3COt2-r-lgEpds,766 +_pyinstaller_hooks_contrib/stdhooks/hook-mnemonic.py,sha256=7XNJhrD_xeQb-2GX0kc_SeWMpMqIDHs8QV6u6NDGXD8,516 +_pyinstaller_hooks_contrib/stdhooks/hook-monai.py,sha256=P6KfEOWbPSQAjG9v81gKtZN4uz_PAGBMoOIB9eGEEfE,557 +_pyinstaller_hooks_contrib/stdhooks/hook-moviepy.audio.fx.all.py,sha256=JV9JNs53PuDR0Cxs0f2HjdJeqpHPEscnVfAXjJyks3w,682 +_pyinstaller_hooks_contrib/stdhooks/hook-moviepy.video.fx.all.py,sha256=cV4zBHk-_Lv5KX6unZirO_6JaqOSZpCciO0WTAEM19M,682 +_pyinstaller_hooks_contrib/stdhooks/hook-mpl_toolkits.basemap.py,sha256=ON-rPY8kO_IASnjpEeDaHrQXkUmXpzIP03GX-xOyzY8,1283 +_pyinstaller_hooks_contrib/stdhooks/hook-msoffcrypto.py,sha256=6PhHu099kv6aw1SizJFkUvQjyd8uOwHXdrx4jOmFQV4,573 +_pyinstaller_hooks_contrib/stdhooks/hook-nacl.py,sha256=Yl9cJzIOFKxTpmPJQhZZC_0dU3N-wpcumgXftncw_x4,1029 +_pyinstaller_hooks_contrib/stdhooks/hook-names.py,sha256=xT5qJlRMFOoftJfxVTlzamWQDBBp4iS0o8MxVLXPH6Y,610 +_pyinstaller_hooks_contrib/stdhooks/hook-nanite.py,sha256=1WAm5zr93zGp-9tCkSAjAHrn_Ip20EGOWvkCE9KhODc,570 +_pyinstaller_hooks_contrib/stdhooks/hook-nbconvert.py,sha256=hjVfkj9XSy6Cb0oqjXPUMDsOPXFFw0J-WbWVVe5Sf48,663 +_pyinstaller_hooks_contrib/stdhooks/hook-nbdime.py,sha256=KRxL0qDNvWCeYVcaBJZkNiQlxiY8uhbitRVs0-b3PNo,514 +_pyinstaller_hooks_contrib/stdhooks/hook-nbformat.py,sha256=pODKrbD5E56BvJ1igFFFI0zGhNX94ariUckS-FzTyJg,516 +_pyinstaller_hooks_contrib/stdhooks/hook-nbt.py,sha256=uVSdxM8DzSAXrm-Vj4ZUbjbSA1DxAC-O17wx33sXVIM,488 +_pyinstaller_hooks_contrib/stdhooks/hook-ncclient.py,sha256=272a8onLx4TVwQOLgkACgxdB3IFqWSO3gMeTtY75Hy8,862 +_pyinstaller_hooks_contrib/stdhooks/hook-netCDF4.py,sha256=eIijhYxEiYtuOJ7k7kdlfNDb5Jm49UWx7f-Y39m4M-8,1658 +_pyinstaller_hooks_contrib/stdhooks/hook-nltk.py,sha256=muSBoO_ynOKyiAgrrxFG8TEbw8c7PwIz2rRzHYMPg14,808 +_pyinstaller_hooks_contrib/stdhooks/hook-nnpy.py,sha256=ZKFpMzgVuMehm_cGLWb8ABTE0ZEJEmNuCTjEhnn87Zo,503 +_pyinstaller_hooks_contrib/stdhooks/hook-notebook.py,sha256=1wUrdtvTqXi6Q7kBNOnavWY4LIGVbRMPDVjZ3KlQu24,1046 +_pyinstaller_hooks_contrib/stdhooks/hook-numba.py,sha256=G7sHUxTodrq3vBXPw19DwAyG2_lhZVzqzLWnfJ1jxPQ,1029 +_pyinstaller_hooks_contrib/stdhooks/hook-numbers_parser.py,sha256=TkQrE6nvV-DR2pDjUWPqlBRJ2w-e2oGP6CFqrmyGMkk,586 +_pyinstaller_hooks_contrib/stdhooks/hook-numcodecs.py,sha256=gsc_2nebGq6C2ugbvzWOeowavn4Nw-wgyBamPjN7jCM,524 +_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cublas.py,sha256=rvXPfMIVmWjQZMd-d-fXV-m2XnIG4ACHlYPwBk18CfM,686 +_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cuda_cupti.py,sha256=rvXPfMIVmWjQZMd-d-fXV-m2XnIG4ACHlYPwBk18CfM,686 +_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cuda_nvcc.py,sha256=hWVCA2qKLcvnp84nUA7SmbrAwL4Iu-coalThGBKhaRU,1287 +_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cuda_nvrtc.py,sha256=rvXPfMIVmWjQZMd-d-fXV-m2XnIG4ACHlYPwBk18CfM,686 +_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cuda_runtime.py,sha256=rvXPfMIVmWjQZMd-d-fXV-m2XnIG4ACHlYPwBk18CfM,686 +_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cudnn.py,sha256=rvXPfMIVmWjQZMd-d-fXV-m2XnIG4ACHlYPwBk18CfM,686 +_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cufft.py,sha256=rvXPfMIVmWjQZMd-d-fXV-m2XnIG4ACHlYPwBk18CfM,686 +_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.curand.py,sha256=rvXPfMIVmWjQZMd-d-fXV-m2XnIG4ACHlYPwBk18CfM,686 +_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cusolver.py,sha256=rvXPfMIVmWjQZMd-d-fXV-m2XnIG4ACHlYPwBk18CfM,686 +_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.cusparse.py,sha256=rvXPfMIVmWjQZMd-d-fXV-m2XnIG4ACHlYPwBk18CfM,686 +_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.nccl.py,sha256=rvXPfMIVmWjQZMd-d-fXV-m2XnIG4ACHlYPwBk18CfM,686 +_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.nvjitlink.py,sha256=rvXPfMIVmWjQZMd-d-fXV-m2XnIG4ACHlYPwBk18CfM,686 +_pyinstaller_hooks_contrib/stdhooks/hook-nvidia.nvtx.py,sha256=rvXPfMIVmWjQZMd-d-fXV-m2XnIG4ACHlYPwBk18CfM,686 +_pyinstaller_hooks_contrib/stdhooks/hook-office365.py,sha256=eOajWAQm3b8-4Du-ow8MGOVhUfTZYzGBdwEX7GIXu60,679 +_pyinstaller_hooks_contrib/stdhooks/hook-onnxruntime.py,sha256=98X6Ba4datHVWvkqHP-9facA_acVjYqCjW2560W8eQ8,576 +_pyinstaller_hooks_contrib/stdhooks/hook-opencc.py,sha256=P9mLJiUtD-dnFuBX3KzoDyRIXdN-XqduXGiGGCJkLOo,514 +_pyinstaller_hooks_contrib/stdhooks/hook-openpyxl.py,sha256=m6WoCKU1nco__-gW-a03SOSXYM12bcTTf-Pz8gCWMk8,637 +_pyinstaller_hooks_contrib/stdhooks/hook-opentelemetry.py,sha256=Qkoy-y7-PzJgEKCEIwr1W60AjEmjxbGAKFeKUdKTsPk,1290 +_pyinstaller_hooks_contrib/stdhooks/hook-orjson.py,sha256=bqnlukfGNV4oD4XL5VoW6l8F4LXic9e5lh22Ji1dLsE,621 +_pyinstaller_hooks_contrib/stdhooks/hook-osgeo.py,sha256=Y9uwC6ERLExngFNyXW0uX6NrKzGBukgsy2bqeh4eF_s,2910 +_pyinstaller_hooks_contrib/stdhooks/hook-pandas_flavor.py,sha256=SebmIynW0u0ScnL49GF_7MlT9hrN74UKCcEH9DchpXM,648 +_pyinstaller_hooks_contrib/stdhooks/hook-panel.py,sha256=tYSkJ7c75X9hRmlBOwnDvxjlrQiyxqHpTsDZGucy-SI,654 +_pyinstaller_hooks_contrib/stdhooks/hook-parsedatetime.py,sha256=9Q3zkAIr6WKW_ORQ8eiM37v00-9PP1qbEf_HI8r1y_4,844 +_pyinstaller_hooks_contrib/stdhooks/hook-parso.py,sha256=wytvf2FAJOYVr41XBBoBhSdHwBqmVRcW6NX48YLSPDY,635 +_pyinstaller_hooks_contrib/stdhooks/hook-passlib.py,sha256=4-RQEZow_YmJAMN_fMe_fTzE1d7cIDnX5OAHLxF02vo,744 +_pyinstaller_hooks_contrib/stdhooks/hook-paste.exceptions.reporter.py,sha256=Kqn35mVCmW_jp942jhkjQ-OYdkz5QkT3RJV6I9eF7YM,594 +_pyinstaller_hooks_contrib/stdhooks/hook-patoolib.py,sha256=ZcP0tnJlIh_PFJlXWc0oNfXAn_npLl5dD0YqkSOOrKo,665 +_pyinstaller_hooks_contrib/stdhooks/hook-patsy.py,sha256=vWNbnyzAJzVMrZSsHTNBr7XZCOLGVFapdM4im0v73P8,456 +_pyinstaller_hooks_contrib/stdhooks/hook-pdfminer.py,sha256=bI8JBQn7-RAcINnPIZWULYjWs-SQhoIWbAV0et_SQN8,516 +_pyinstaller_hooks_contrib/stdhooks/hook-pendulum.py,sha256=jboGCmxlO7DfRGK9JJ19KUH4nMjGTU5uz5Gc-c5xRls,795 +_pyinstaller_hooks_contrib/stdhooks/hook-phonenumbers.py,sha256=zjjxVuQCGUftbsnXuuA1UaihlDt1_4sHVEsAu-GnElU,682 +_pyinstaller_hooks_contrib/stdhooks/hook-pingouin.py,sha256=8DnNfY_Hfpv-pwXzQqyk5bJuLJcYHPE6kph_G7eSuDc,516 +_pyinstaller_hooks_contrib/stdhooks/hook-pint.py,sha256=kZVeEtqKYXlqGtt_sfT7NFeg7jsCnilyujbfV6U-vhY,558 +_pyinstaller_hooks_contrib/stdhooks/hook-pinyin.py,sha256=g0iSA9JlUm0TPCC4CxaTOJpiNW0gl6Izc2xKZqcgh4g,738 +_pyinstaller_hooks_contrib/stdhooks/hook-platformdirs.py,sha256=NCEoeP_XKX5yxCjDwT0cPohcZ3-xPMZnLCQRFsuTJRI,839 +_pyinstaller_hooks_contrib/stdhooks/hook-plotly.py,sha256=Yp4RK1TyjmL8bAPFpNsfZiz5UhWxH48t8eKKOmMCZOo,681 +_pyinstaller_hooks_contrib/stdhooks/hook-pptx.py,sha256=Z2S-ITYXrEEQgfhj1anvOnAaQrrKtMhz4nB1jJaO9gw,522 +_pyinstaller_hooks_contrib/stdhooks/hook-prettytable.py,sha256=LR7k0VtxljNCpkfypkAClotbRTvIId2HIElIx0UHor4,508 +_pyinstaller_hooks_contrib/stdhooks/hook-psutil.py,sha256=q3PHBjQWaW_9uvMbKNBTdXRAENKM5HX0m0xE_WtHOy8,1662 +_pyinstaller_hooks_contrib/stdhooks/hook-psychopy.py,sha256=TjcAifKGMUmn7Up5o251n0-7F4igd34jO_tI7D1QjMc,584 +_pyinstaller_hooks_contrib/stdhooks/hook-psycopg2.py,sha256=AYhLOAtcetLs0m_cjJQjnOmhUCTM3GeNL0R14rXTxC0,453 +_pyinstaller_hooks_contrib/stdhooks/hook-publicsuffix2.py,sha256=1JAim_QMHt74gn2JCxPjXz7qjEiXR9y9vsowb0vuSFE,521 +_pyinstaller_hooks_contrib/stdhooks/hook-pubsub.core.py,sha256=6HrYFNpinML13-6r8Qha6CuCKXpXu7rgIJxQ_gND4Xo,580 +_pyinstaller_hooks_contrib/stdhooks/hook-puremagic.py,sha256=0Xvb0WRlPB4nOCV7LffKg6S6NSOsGKuOKpGSkva-HpM,517 +_pyinstaller_hooks_contrib/stdhooks/hook-py.py,sha256=U7XDI-qn1L8VoSivgpyuNbHwyw2nijYIknmWEqGpm68,524 +_pyinstaller_hooks_contrib/stdhooks/hook-pyarrow.py,sha256=kYm4XaJ8GQFn4lsxzO1tqeDtPb8JgYvDDe8EW5wDiTg,727 +_pyinstaller_hooks_contrib/stdhooks/hook-pycountry.py,sha256=CfZlViBOJLtbWhY4s-_8P3qRA_M1dOtiwh4ECDNS_c8,691 +_pyinstaller_hooks_contrib/stdhooks/hook-pycparser.py,sha256=P43K-yDI8XmmxcchKI8KLTyr44hI4tK21FzQzL9qf1A,875 +_pyinstaller_hooks_contrib/stdhooks/hook-pycrfsuite.py,sha256=RWHkauAGHZ7-Xed0GNGnI8VXBnruXi1zrAHvfUKkD00,501 +_pyinstaller_hooks_contrib/stdhooks/hook-pydantic.py,sha256=y6yrY-KKB_zxwgaOGHm72sZkR9o6qJDTryq6osq1UHU,1944 +_pyinstaller_hooks_contrib/stdhooks/hook-pydicom.py,sha256=8OdvGBM_OgIG7LmOt-ghu4yRMxITkuTJoldEH0rEzI0,3170 +_pyinstaller_hooks_contrib/stdhooks/hook-pydivert.py,sha256=fTOz2ZV8ds9hMxjxpkRWnO3Hu1Rp-TklQn_i5l3BQ6w,530 +_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel-io.py,sha256=FZcuwojyp_ohP2hlcfOPaKMnIn6z1sdYpUdG2Ttuus4,540 +_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel-ods.py,sha256=wm2aZ2uH2cyFeQkmOuxmAm-Rb38buqrybqSJJ1Wu_yY,542 +_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel-ods3.py,sha256=ElPK-BsVkzZyYovwRr6STzP9zwPv8vNQtKdcgII7y2w,545 +_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel-odsr.py,sha256=H8f3KuemVMIhd4jiDnF7Yqm8tV_rMX_-Rji1d2soHGU,541 +_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel-xls.py,sha256=4R0j_zrp_f3Fsso9a4VEnCDUV4yj5Jn-bbVEYdJps8s,542 +_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel-xlsx.py,sha256=8Ciw7Xgcn9jrXjFge_c2miroB9-Tbl4uKm8TFpzB_t0,545 +_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel-xlsxw.py,sha256=fdUqkVzW8lVNPZl-hZLWB-V0W84IsFilxDWxJuG0KDY,548 +_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel.py,sha256=O4AxWgjHAqEY0qwDEHI7oRyadmkCJvvlcr51W0FH1Uo,1270 +_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel_io.py,sha256=dvm5ED0pqFM8Nm_qXTiOiazK1Yy4lKLFpApozAchnf4,1026 +_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel_ods.py,sha256=Iz0fWJ_yu-bUcOReVdlIONX10AK2tS9eulAFMXRdwqY,604 +_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel_ods3.py,sha256=Jq2vUOuWLH6eGgSsaQ2FUGe2SBnhpRU2Mw4n1zoezO8,587 +_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel_odsr.py,sha256=nrT8jVqP6XMJsvkjsz9CvR29mGfBHE57iCfCZk7u0k8,562 +_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel_xls.py,sha256=oKb4_uAhN4lD2HIkCZ6Y7nZTq6Vrm0ASNguxzvqrQZ4,582 +_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel_xlsx.py,sha256=4f6MoRb5lv6q2v1Ep6aZH_fzbHhqOKYV88-63Kc-1Og,589 +_pyinstaller_hooks_contrib/stdhooks/hook-pyexcel_xlsxw.py,sha256=Q6nFCXD_8M4n6eP6c6bDKZ9FMgHdmlcwUWseprA1RWw,571 +_pyinstaller_hooks_contrib/stdhooks/hook-pyexcelerate.Writer.py,sha256=L_KxyR2a27d0hjtK_L5Xt6Bh8CSXwsrDCJmwN5SRrxc,520 +_pyinstaller_hooks_contrib/stdhooks/hook-pygraphviz.py,sha256=Mt__nm7XELuC_MDM4cGBzJfvZ9woBq2dtPuDdiE3IVc,2090 +_pyinstaller_hooks_contrib/stdhooks/hook-pygwalker.py,sha256=riOBNf_TUoNdah7wNAPg0YOZ9ruzexvYN5_DhTW_uuQ,517 +_pyinstaller_hooks_contrib/stdhooks/hook-pylibmagic.py,sha256=HCi2VRbUeBRFHbu3aZaQVpdH4CLjt6Mg55MT5r29AtU,638 +_pyinstaller_hooks_contrib/stdhooks/hook-pylint.py,sha256=7CGgOElk4-j1dUFSYvdgkDhnaWA64NyPklA59tJYCxE,2797 +_pyinstaller_hooks_contrib/stdhooks/hook-pylsl.py,sha256=3alIt8qCeJwrbIWx2DZB0gUl3pP_OyPC5Gl6E_kq9js,1380 +_pyinstaller_hooks_contrib/stdhooks/hook-pymediainfo.py,sha256=SZHmXlXI3hg6WQI1DB0SQ2CgMdvC4R_lKXITC28JdSc,1720 +_pyinstaller_hooks_contrib/stdhooks/hook-pymorphy3.py,sha256=WiiMapatPQ-tMqu9uJMqb-YrZgz4-z9UzCuGIH-hFuk,882 +_pyinstaller_hooks_contrib/stdhooks/hook-pymssql.py,sha256=lvxXSQPWOjXk01HpxQD4vuz_NWRLu7dHVzdBBFObd4Q,702 +_pyinstaller_hooks_contrib/stdhooks/hook-pynput.py,sha256=Bst5K7rJ2x6zu7RH9Rw2o3bt9OH6zKcdCSvkjLxiVVs,522 +_pyinstaller_hooks_contrib/stdhooks/hook-pyodbc.py,sha256=O4xxP-3UYj1U-F5brNgHUJqrLZ1xEhi8dmyewtdjAQg,800 +_pyinstaller_hooks_contrib/stdhooks/hook-pyopencl.py,sha256=BYmdmFmWfLvTCwYfoU5R6te6ZLiOIOowt3lCFf90vSI,636 +_pyinstaller_hooks_contrib/stdhooks/hook-pypemicro.py,sha256=AAcRqmDT99-Hf6qOx-oYpVz5ikMSSrdmTHNIPlw0fRE,1537 +_pyinstaller_hooks_contrib/stdhooks/hook-pyphen.py,sha256=TOIIizX9zsR8Yxne30gn3kVD3-_SR3yLbIdDeRrRNm0,514 +_pyinstaller_hooks_contrib/stdhooks/hook-pyppeteer.py,sha256=tQBftDHjR6UE8hLS9TOhdfZ2CtYj3pQA7RPQICnEq2Y,569 +_pyinstaller_hooks_contrib/stdhooks/hook-pyproj.py,sha256=AutxkRkRAaaHv6pepOHlntsGew20Aw0BHfp27XIpoDY,2874 +_pyinstaller_hooks_contrib/stdhooks/hook-pypsexec.py,sha256=1dsJpXxQSf_ax1ZG404Gt_lugYsZnp4sccNDC9ARs2k,663 +_pyinstaller_hooks_contrib/stdhooks/hook-pypylon.py,sha256=0lVseKKn8a_oAJSD2gKmk1BB8c2JV0JzPLpV29-lQr4,2502 +_pyinstaller_hooks_contrib/stdhooks/hook-pyqtgraph.py,sha256=TV_83_49-Ct7JMDLTWZ40lhUkBu2JgrVeh9ViyDKvVY,2724 +_pyinstaller_hooks_contrib/stdhooks/hook-pyshark.py,sha256=QiK5ngnGJgd-4Ej9bSCfLm6C0T59nR2Wcmv9W4T3OGk,894 +_pyinstaller_hooks_contrib/stdhooks/hook-pysnmp.py,sha256=VTFu70OKNnuxQf5BgFoQfRNKhHIYpsYBBq3Um61cBpk,620 +_pyinstaller_hooks_contrib/stdhooks/hook-pystray.py,sha256=zwrmSkRqcqCTB0LorfBeohRhK6z83Gn6mtHkn8stjHk,645 +_pyinstaller_hooks_contrib/stdhooks/hook-pytest.py,sha256=KswRiZA4mc6ntcoRZP1uuWCvWjeOMH3EyXlUR1HIk6U,530 +_pyinstaller_hooks_contrib/stdhooks/hook-pythainlp.py,sha256=LjYyaZ6bippZB_FaEhfO98ZoMuMq2ts4tJNM-oFOX0M,517 +_pyinstaller_hooks_contrib/stdhooks/hook-pythoncom.py,sha256=8BNoI-XzdFcMMYZGhtgJlKQafkLCPNEcNkYvklCl-oA,1310 +_pyinstaller_hooks_contrib/stdhooks/hook-pyttsx.py,sha256=Dc_k1cOMrTiyUD2ykczvMjFnKsxqnsRyoubp6AZuK0U,680 +_pyinstaller_hooks_contrib/stdhooks/hook-pyttsx3.py,sha256=tSKAGe5li3ZNgXmD8uBAOklK2gXZsb8N_g0DmDwXz3Q,953 +_pyinstaller_hooks_contrib/stdhooks/hook-pyviz_comms.py,sha256=tIouDRIPXMthfkbl92nPp_WoiV95hgkvX2fJmNt6Q_M,519 +_pyinstaller_hooks_contrib/stdhooks/hook-pyvjoy.py,sha256=z_5pzdhljTAIqXr6ZUAU90yetm9XsismXM8fJACXJOE,520 +_pyinstaller_hooks_contrib/stdhooks/hook-pywintypes.py,sha256=P1c320OpZ0aYBcuvJYuyn6GXs9rR9SXYlifElNhGg3A,1312 +_pyinstaller_hooks_contrib/stdhooks/hook-pywt.py,sha256=h66LHiEystMScItTwayt9BVAbxTKtRaHh9eAJn3yVbU,875 +_pyinstaller_hooks_contrib/stdhooks/hook-qtmodern.py,sha256=YsxMuexOuumpdDaxGJHm72B3Ir1g4QYFhQaaGcMPiTc,539 +_pyinstaller_hooks_contrib/stdhooks/hook-radicale.py,sha256=fiBeBFdZEF4SOsmex1KuBzxk8wuIPbXvSAYtw9Z333k,566 +_pyinstaller_hooks_contrib/stdhooks/hook-raven.py,sha256=ZMjvs_bMMzL6ivmkMYd4JaH1GQjySXFvMWY2FKo_QMQ,474 +_pyinstaller_hooks_contrib/stdhooks/hook-rawpy.py,sha256=Unn3Dmi-1DO6PEsP1V1fc4msZKjlfdRfRJ1lHuhW430,549 +_pyinstaller_hooks_contrib/stdhooks/hook-rdflib.py,sha256=rZILYAIHxVLRb8Yoo-OrCwOxgpnXa0mIUtAt7NQdn1w,530 +_pyinstaller_hooks_contrib/stdhooks/hook-redmine.py,sha256=WB6xvPntTEPCgr0OObGvIrA2-tJf_Pj6VPOg-haG_Lw,459 +_pyinstaller_hooks_contrib/stdhooks/hook-regex.py,sha256=NbwTOxbeaB2odUSDRMfG_A3MlsE4gBK5-87xXDDVoLE,450 +_pyinstaller_hooks_contrib/stdhooks/hook-reportlab.lib.utils.py,sha256=pZqRNQOrita5omAC5_nSskyAAu3p4JpsgQ1aqPYyKlE,495 +_pyinstaller_hooks_contrib/stdhooks/hook-reportlab.pdfbase._fontdata.py,sha256=tEXZopdzGoV68mBgXZiDFEj2X2BoIBc6q7QcGI-4glY,754 +_pyinstaller_hooks_contrib/stdhooks/hook-resampy.py,sha256=vAXcFQNF7T3C_Noq2d7BhhWh4M2rUMR-w7m0WsA631w,596 +_pyinstaller_hooks_contrib/stdhooks/hook-rlp.py,sha256=MZaRLPT-yxpVpYHmPSn6QKZDesyZrgWvjOQSiF-s0qs,631 +_pyinstaller_hooks_contrib/stdhooks/hook-rpy2.py,sha256=jw3x7MFzZ1W4JmLG3ee-mJAfeHONVj0OfD6P0XMD9sQ,526 +_pyinstaller_hooks_contrib/stdhooks/hook-rtree.py,sha256=qWGm91ktqZNaRgxcC2sTjz2d3ii1f3J-lQvQticA6Io,1735 +_pyinstaller_hooks_contrib/stdhooks/hook-rubicon.py,sha256=QMzeWRQmulGUFSBGcyfjxTP3iDz_sf5ItOVyiENGCN4,574 +_pyinstaller_hooks_contrib/stdhooks/hook-sacremoses.py,sha256=lm66cE71dKrvqLJJA-yJ3vtuxH7kcb8ptroAEfdQRJ8,518 +_pyinstaller_hooks_contrib/stdhooks/hook-saml2.py,sha256=S1UqQSq4qsJqr731S_pQ3n78vZ0sD5HLl8j6WyjqfQk,1138 +_pyinstaller_hooks_contrib/stdhooks/hook-schwifty.py,sha256=KR8NXP6rWyt7QlUpDSwT1YFM9SbTpzZAsv8FCqXdNQ8,566 +_pyinstaller_hooks_contrib/stdhooks/hook-seedir.py,sha256=IHIIi5YRBlRmixBGQkKG20hTbxCFFSAmTn5PKoSDyxI,514 +_pyinstaller_hooks_contrib/stdhooks/hook-selenium.py,sha256=evaqzJ9MoXzbS0RaUGyta7C75YOLm0pL2FbqrOL0sV8,516 +_pyinstaller_hooks_contrib/stdhooks/hook-sentry_sdk.py,sha256=RRHQjGatbPphkfgBXH6ZRC663uVEDtVUR4YQqnf0ivo,1555 +_pyinstaller_hooks_contrib/stdhooks/hook-setuptools_scm.py,sha256=AKzhxS_poloeTW3P1AqpfEhv1Pj22ObVPlcmMKVxTcE,638 +_pyinstaller_hooks_contrib/stdhooks/hook-shapely.py,sha256=xyvXIL2GvUJrT47IrWc_8sJ5oRttUGzB_2HSCu54ek0,4786 +_pyinstaller_hooks_contrib/stdhooks/hook-shotgun_api3.py,sha256=PWWJA_bTQulDDZ_SlJknhwMmBJMlA0syMN7ty4CqKfA,837 +_pyinstaller_hooks_contrib/stdhooks/hook-simplemma.py,sha256=1bBXLPhsKhWION7Yao22LQTMQJ4Yo0LWKX0cFjBSONg,517 +_pyinstaller_hooks_contrib/stdhooks/hook-skimage.color.py,sha256=f3Gggsi95Q8Mzr4dV_WECbSmvWMeQ4YZptkzNf-5wlE,885 +_pyinstaller_hooks_contrib/stdhooks/hook-skimage.data.py,sha256=wDeAlllX4ohrXZQMMPFDhXqwSQKaJszi_X0fLhh4FOw,882 +_pyinstaller_hooks_contrib/stdhooks/hook-skimage.draw.py,sha256=BdsCh5CYIlUmB9TU0q6LRo0vNfkiP9Ikl1CGOrrf02g,882 +_pyinstaller_hooks_contrib/stdhooks/hook-skimage.exposure.py,sha256=RvZnk0miH3VeMCjXcPk7PMjgyaD2-Ts5WomfA6l2DkQ,894 +_pyinstaller_hooks_contrib/stdhooks/hook-skimage.feature.py,sha256=hGjCqKixqNQWSNeh3YbWL9Pgeu-Oj_jo66r6OfSz6vA,1348 +_pyinstaller_hooks_contrib/stdhooks/hook-skimage.filters.py,sha256=Wf1FoAwOOSEJN338XePFGQQQEY2mDsnLn1djfXmyJa8,1224 +_pyinstaller_hooks_contrib/stdhooks/hook-skimage.future.py,sha256=A1Ozf_BsbVh9FeNY7M7RPYlPmQqq5XqaG1nnDscjmEE,888 +_pyinstaller_hooks_contrib/stdhooks/hook-skimage.graph.py,sha256=W6E_UbfmgCvsf7xFVLnjNWRbEnWQCXFIKrylJ19af0M,1012 +_pyinstaller_hooks_contrib/stdhooks/hook-skimage.io.py,sha256=gvA5t2GkyzSTDe475c7TWJMxH0ZwcIVZtBFypufVTHU,692 +_pyinstaller_hooks_contrib/stdhooks/hook-skimage.measure.py,sha256=kBIwSn8bHZkyBx4e_kmbIfEhBDpM56-TUMds2NrIotM,891 +_pyinstaller_hooks_contrib/stdhooks/hook-skimage.metrics.py,sha256=UXc7fYHmZtjSjigpNpRWNXd8n5PlrttGpNf-6FJhCd8,891 +_pyinstaller_hooks_contrib/stdhooks/hook-skimage.morphology.py,sha256=rNY8kBmId9ZjqErQCtjcaVM5z7NAV7GX5-6zDe-ejPk,708 +_pyinstaller_hooks_contrib/stdhooks/hook-skimage.py,sha256=X1D4G1ifc2NJYgEP8BJv7_HbibSIh_zU_mi02Tz2Ro8,699 +_pyinstaller_hooks_contrib/stdhooks/hook-skimage.registration.py,sha256=fPIIIOtwjCrTjtrFx-Gm43gQRQ3hIt07j5B0ukkPnZ8,906 +_pyinstaller_hooks_contrib/stdhooks/hook-skimage.restoration.py,sha256=L8Sl7-uEt0w0fkMFuj_F9Br5t3rPmeTC9Gl5tOTB1kE,903 +_pyinstaller_hooks_contrib/stdhooks/hook-skimage.transform.py,sha256=JzT1ZOZSYF9AIE0GqofIDqeJAzeZqR8ueOtWH4USQ2A,1160 +_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.cluster.py,sha256=oP45i7CNTVbV24F7lcW1SENbY3FkL-r_g-ZfsRhPo3g,646 +_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.linear_model.py,sha256=CwIAWIFg3WAB9h77Cy606FOWJ8M1PwM84APlOi6wP7o,681 +_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.metrics.cluster.py,sha256=q77JZ2N5g2JAdJ9KZc1M6VmghFFJEZix9QCIppRyvpo,1059 +_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.metrics.pairwise.py,sha256=Y-mMC21KcFLZl8tBlFZk0Rhxh3RAF7uBZa9_XC3yBT4,695 +_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.metrics.py,sha256=jMbCX7-k2My3roYB8InOM8MW80_7TYJtaOsR5CVW41I,836 +_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.neighbors.py,sha256=QqEsYvxvqhtkraAZCGeJyqV9vmv6N6Gzf4PVJLQiXxY,1256 +_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.py,sha256=IBTUfO-Z5Sa2mw2iCEMKGd_0-kDpDXSTlXo-BqiuS4Q,563 +_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.tree.py,sha256=BNYMndC-EY8vAnVArPYjjpJ895PxllGlsc1suGUh1A0,463 +_pyinstaller_hooks_contrib/stdhooks/hook-sklearn.utils.py,sha256=N768grgs_ku04fPBmluXTO7Xbh5Yzfl5lwABwghG1z4,470 +_pyinstaller_hooks_contrib/stdhooks/hook-skyfield.py,sha256=6oKXVPWHwEbqV_RrMOxL1t7PGZ7hiBhH4ChjG3CdXfY,515 +_pyinstaller_hooks_contrib/stdhooks/hook-slixmpp.py,sha256=oQkL_3sMJ5PVQJbYP4xCnybIW50WvDCnGXefOVot4ug,532 +_pyinstaller_hooks_contrib/stdhooks/hook-sound_lib.py,sha256=Kq3QihOuvNPWwy_6A9aWUAaL7WNzpNuilXKztVEFKLk,579 +_pyinstaller_hooks_contrib/stdhooks/hook-sounddevice.py,sha256=FGwJDIZkgFIbMiS0PvT6nu3aXDX08tzTqLgx3tGbP-A,2274 +_pyinstaller_hooks_contrib/stdhooks/hook-soundfile.py,sha256=0LjHvLYMaqRFdwj-ejmNPKe00TfXa2n4JzSf9WtMdz4,2205 +_pyinstaller_hooks_contrib/stdhooks/hook-spacy.py,sha256=0mBcrUsC6yf2Ojn6U8H6qxv91pQu6pMthpYt0KHa8Jk,660 +_pyinstaller_hooks_contrib/stdhooks/hook-speech_recognition.py,sha256=piGWZuxa_PXxTEyPOFb7iyFzJxiG6n3Tt_-zPm1kaug,661 +_pyinstaller_hooks_contrib/stdhooks/hook-spiceypy.py,sha256=Ed6LYIhF6poAcCSPyb5rvhVjUFkdl9qw0qxyn73JJDU,625 +_pyinstaller_hooks_contrib/stdhooks/hook-spnego.py,sha256=ehk5wUbK8Xj-Oh75VyPssmzZSeK7QcFo2wNFZ8RaJW8,522 +_pyinstaller_hooks_contrib/stdhooks/hook-srsly.msgpack._packer.py,sha256=WXdQwncBqLpuxfcR_i-OySkzAtlkbAepvX82vMnfQ7M,596 +_pyinstaller_hooks_contrib/stdhooks/hook-sspilib.raw.py,sha256=d4vicope-Y7s4BjCk9I6lrsYm9MUc5_NDa3tiyATOlg,861 +_pyinstaller_hooks_contrib/stdhooks/hook-statsmodels.tsa.statespace.py,sha256=z1YSRSV5BtzND932WFgwB70XFU2yz0-lK5vxIJpCKLQ,619 +_pyinstaller_hooks_contrib/stdhooks/hook-stdnum.py,sha256=KOp6fIP-1UYDUQvQTtjsfDf85sTfouUh9XDP28TTGdg,589 +_pyinstaller_hooks_contrib/stdhooks/hook-storm.database.py,sha256=Enp0r3QnP011rR4Lo6Jmh_7tuKeX-FO9wF-b2rF_Gfo,559 +_pyinstaller_hooks_contrib/stdhooks/hook-sudachipy.py,sha256=mznzdDeOa49mGSqNMjmIlWHgTI0tabQ1Xy-8IbS6ks8,1088 +_pyinstaller_hooks_contrib/stdhooks/hook-sunpy.py,sha256=WdRTp2-VH2zgM8lhXbeL4H08MWVyfHh8lVee5RPSZiA,810 +_pyinstaller_hooks_contrib/stdhooks/hook-sv_ttk.py,sha256=gkQBskWzIY9vj5JaCgIZbFGsiBPWtd2KRXiUzWOLY5g,564 +_pyinstaller_hooks_contrib/stdhooks/hook-swagger_spec_validator.py,sha256=CZxq9j5qkkuVAjSQWQwRRaIJT9GGa978Q9F57erq4HY,530 +_pyinstaller_hooks_contrib/stdhooks/hook-sympy.py,sha256=pQtYWj2ASprai-lEud0Jq-Ld-JT0yT2Vk7E5udcbCrI,874 +_pyinstaller_hooks_contrib/stdhooks/hook-tableauhyperapi.py,sha256=AumaK0lkQrfiCsG9p6t5L7RGWme6OJ5b579vugQVF4k,530 +_pyinstaller_hooks_contrib/stdhooks/hook-tables.py,sha256=IOnpCJdV4hWIz1is97IDMSC1prG4c2wkIsyB1WikmxI,1471 +_pyinstaller_hooks_contrib/stdhooks/hook-tcod.py,sha256=d30d6w3skLxkY1O-4qgWOcITPbiXKN-Af3tp9gqAYpk,675 +_pyinstaller_hooks_contrib/stdhooks/hook-tensorflow.py,sha256=X98jHWPPNuqgpQq_Pm08gOsUFFMYjiegB4ue916uVlU,8521 +_pyinstaller_hooks_contrib/stdhooks/hook-text_unidecode.py,sha256=aiKF9Adg3AERYMKQfnGu4NIjXvkd9cabMbn7EWbnZaU,823 +_pyinstaller_hooks_contrib/stdhooks/hook-textdistance.py,sha256=VMB0NOWxX-wm0iaN7LZu7DDNl-oZeYPOLkq99bQynyY,602 +_pyinstaller_hooks_contrib/stdhooks/hook-thinc.backends.numpy_ops.py,sha256=fQe7iRyYKHzh2O51Rhqla_wQTDD0qPh4MwS70SuBGwA,620 +_pyinstaller_hooks_contrib/stdhooks/hook-thinc.py,sha256=kv4x4ewqLapioW9Iyt4pgZAklPqYH2buCl0bU6l4q94,682 +_pyinstaller_hooks_contrib/stdhooks/hook-timezonefinder.py,sha256=gFfA4F9ImepBorXt9onYcWoaNCv-PSrjUrkS8H-Vt8w,522 +_pyinstaller_hooks_contrib/stdhooks/hook-timm.py,sha256=L508elVV7ax33mODkIR3zrkCnahihoH7UIjheGAzCkM,557 +_pyinstaller_hooks_contrib/stdhooks/hook-tinycss2.py,sha256=ke7JomKRtbpoKSoOAbqBsVs7KBbMyqNc9LdKPsy8940,718 +_pyinstaller_hooks_contrib/stdhooks/hook-toga.py,sha256=AlnWcLqUrzOnB4tYPHoarDZBmrJNQugfw9WeA5rrync,1068 +_pyinstaller_hooks_contrib/stdhooks/hook-toga_cocoa.py,sha256=lRTBxt7K5mDBr0Vg9_cKtlWjYwo3aYkuxYZYUGQBFgI,695 +_pyinstaller_hooks_contrib/stdhooks/hook-toga_gtk.py,sha256=BLhknKuw1taIhpChywxds5YAaErt3p1QEbMaD_LW5N0,698 +_pyinstaller_hooks_contrib/stdhooks/hook-toga_winforms.py,sha256=ZdedhJzay8JBOpHFkh886uhqkbVceUtZCQ42a0PcIIQ,1676 +_pyinstaller_hooks_contrib/stdhooks/hook-torch.py,sha256=Bycjt0ibDsfalzHOo9dsXqJRauC_imRQULUR2BA1LyM,6353 +_pyinstaller_hooks_contrib/stdhooks/hook-torchaudio.py,sha256=uiHAOGQ-3-ObT97AVxv0z0QlpbjFJbNE2Q0gYNADXGM,867 +_pyinstaller_hooks_contrib/stdhooks/hook-torchtext.py,sha256=CzTfNYupWeGaRRfSIL2eJY0aDBhQv1QXtJbWA-NEDN0,864 +_pyinstaller_hooks_contrib/stdhooks/hook-torchvision.io.image.py,sha256=gY1Lyzi4FXkXgunJsO1tu0L1mF57K7UYEJRbUv5ty8A,544 +_pyinstaller_hooks_contrib/stdhooks/hook-torchvision.py,sha256=4b1nEXZqf2wF3NQmnxHSAzjKdVg5_v7vdXqQZBnDqcY,750 +_pyinstaller_hooks_contrib/stdhooks/hook-trame.py,sha256=wfWJdueXwSbtg5ltTooMVKIScckp4MJfAMjQUSrggZI,449 +_pyinstaller_hooks_contrib/stdhooks/hook-trame_client.py,sha256=VzWxVdG9C6_5R0VSNK13fbi6UEpiqrho26uU8y4jgFc,537 +_pyinstaller_hooks_contrib/stdhooks/hook-trame_code.py,sha256=lBe5ZK_X8AjASCPIV9APv5YGX2ISWvBnbIkjg_FfNw0,538 +_pyinstaller_hooks_contrib/stdhooks/hook-trame_components.py,sha256=54f4hYedYKygfRWKPdagVKWHUW_Rln9hYUsz1bIV-lc,541 +_pyinstaller_hooks_contrib/stdhooks/hook-trame_datagrid.py,sha256=_YgeTfiZm-HByd8G1_DIb70yXdgKiDXyROaDXBiXHs8,539 +_pyinstaller_hooks_contrib/stdhooks/hook-trame_deckgl.py,sha256=Jv0w7wuGjC3AuQ4sgLGtA3Eiijda2D_i8eFFkgyRuB8,537 +_pyinstaller_hooks_contrib/stdhooks/hook-trame_formkit.py,sha256=ryM4qXa18QDuBdWffklfR-B3-FUs5N_x1l1LVJxcIus,541 +_pyinstaller_hooks_contrib/stdhooks/hook-trame_grid.py,sha256=za_pkjIroAH_VjdYywXdSsA4uP8yAHIMT84UYkmUlm8,538 +_pyinstaller_hooks_contrib/stdhooks/hook-trame_iframe.py,sha256=EIAhF1ARh2m19WvQIIkzkKbmAWrVzqLcxp97qd5fZ-8,537 +_pyinstaller_hooks_contrib/stdhooks/hook-trame_keycloak.py,sha256=BrfdnSqBj2xwebMRwxiFtnBK6bpl99ytdZWv_mS5YLo,539 +_pyinstaller_hooks_contrib/stdhooks/hook-trame_leaflet.py,sha256=A5HftRWLEo-4JxANDRf1qyYdzQ9UMjkT9ZQAITqhK4k,541 +_pyinstaller_hooks_contrib/stdhooks/hook-trame_markdown.py,sha256=F6U1hYfdc76jU4Mw64o8DNSsbDzputARvHW3_NpMRwQ,542 +_pyinstaller_hooks_contrib/stdhooks/hook-trame_matplotlib.py,sha256=y2zdoreEfcZ12d7K8tZdtMrnkT8m5-JS5pi5_4JVHI0,544 +_pyinstaller_hooks_contrib/stdhooks/hook-trame_mesh_streamer.py,sha256=MM0sW1v0nCpXywQ4j6ioy9RK6cxS5Yg-0eY7zZxua0c,568 +_pyinstaller_hooks_contrib/stdhooks/hook-trame_plotly.py,sha256=Jus__aRsqdUEyLe96VsAKggn3eNEqL2SvDV8R6kB7ao,537 +_pyinstaller_hooks_contrib/stdhooks/hook-trame_pvui.py,sha256=t-k_oh-jEQ7WZYxWp5mrF_zdbjlDb5K-f9b26p6OTFU,535 +_pyinstaller_hooks_contrib/stdhooks/hook-trame_quasar.py,sha256=yGPS7wYndn26rud-Qry0HxMvB3N7mYgoBv5CbQe7JBI,540 +_pyinstaller_hooks_contrib/stdhooks/hook-trame_rca.py,sha256=Vz-h_WumdIelMNLG31vWUO7fSjEM2O2zG2Je7Mg5Jkk,534 +_pyinstaller_hooks_contrib/stdhooks/hook-trame_router.py,sha256=u1wTcmw6sfgWMyEX3pkj7_4PVkuL9VQsFE98IkB1X0I,537 +_pyinstaller_hooks_contrib/stdhooks/hook-trame_simput.py,sha256=e7XVwnoMR-grO51ir3iX0ToTOB7M31oqp7EAv5TNb5M,537 +_pyinstaller_hooks_contrib/stdhooks/hook-trame_tauri.py,sha256=c-qQLEenEVzwFl9CJvGioTnf-9OHQhL-4SUD_iAlgf8,536 +_pyinstaller_hooks_contrib/stdhooks/hook-trame_tweakpane.py,sha256=1yTKF43c-bwM5GNUiP5pg-7dZoLi2MicTGiIy6djgAo,543 +_pyinstaller_hooks_contrib/stdhooks/hook-trame_vega.py,sha256=8m8NgpnnfQDKB96FSLkVdVFBXrut8EVFN6p_d74KK0s,535 +_pyinstaller_hooks_contrib/stdhooks/hook-trame_vtk.py,sha256=rQzWSHqHjITxVctPZCcvupmNUrP6qWO5KvfapQ59Jug,599 +_pyinstaller_hooks_contrib/stdhooks/hook-trame_vtk3d.py,sha256=C50pnto4_ZHuYoNnwUbQwxKPnVbLUgAbGVEzdm3QCYY,536 +_pyinstaller_hooks_contrib/stdhooks/hook-trame_vtklocal.py,sha256=MJ4b692GnZ8xeLf7U3MfA_8UhnPH6m8WU3vv1V0C1WI,563 +_pyinstaller_hooks_contrib/stdhooks/hook-trame_vuetify.py,sha256=uzrIK50-q9-ElD4iGi7r9hCUshtntdpdJgSWCFMTORo,538 +_pyinstaller_hooks_contrib/stdhooks/hook-trame_xterm.py,sha256=bv8OYRBotPrbovDdbRAIm__Byask8Gl-WNn3S6nqFT8,536 +_pyinstaller_hooks_contrib/stdhooks/hook-transformers.py,sha256=oUp7eMv1GZVkRwu8uoUPPoMnbUN7T-9QHhE5LeeovTg,1441 +_pyinstaller_hooks_contrib/stdhooks/hook-travertino.py,sha256=QMzeWRQmulGUFSBGcyfjxTP3iDz_sf5ItOVyiENGCN4,574 +_pyinstaller_hooks_contrib/stdhooks/hook-trimesh.py,sha256=8rZOJcrZzvQP1dcNFbFiIGNciMNcN8nfQ5l8A962ct0,630 +_pyinstaller_hooks_contrib/stdhooks/hook-triton.py,sha256=tPWQDjLZ5K9F9uU6XKomodKxwBq0uBGKi17GMn47nE8,1429 +_pyinstaller_hooks_contrib/stdhooks/hook-ttkthemes.py,sha256=r3b6GzZQ5Kr9JLCK8NOmodZkBl_lbYA8yuiPohVEzDA,1822 +_pyinstaller_hooks_contrib/stdhooks/hook-ttkwidgets.py,sha256=vS1Xdgi8Q-m9qhK97u1T111pBEPm2HVgmbWi7byqTr0,1288 +_pyinstaller_hooks_contrib/stdhooks/hook-tzdata.py,sha256=OsSahzrcY_SuaoZB6gXT7HtkWSJGb_c_h76du4talxk,826 +_pyinstaller_hooks_contrib/stdhooks/hook-tzwhere.py,sha256=qNPXs2MAeH5Y0FWDCOXoplHp5FI-GIRkI62yFvUzN5A,515 +_pyinstaller_hooks_contrib/stdhooks/hook-u1db.py,sha256=ftGC2v2SEPsypYXY934pYN8H_dvOoEbafKaeiNP06n4,876 +_pyinstaller_hooks_contrib/stdhooks/hook-ultralytics.py,sha256=LoDbFbjOrzRzEpViEzZ1ZPb4DVk_h3QNjsPSex_hgys,717 +_pyinstaller_hooks_contrib/stdhooks/hook-umap.py,sha256=Df75m78IePhWxlordune2qRC_UmgTLDvrlQyePr5HMI,508 +_pyinstaller_hooks_contrib/stdhooks/hook-unidecode.py,sha256=t86yg_WZ0An4pjHIVQ_Mnnvn8u74LKZmNEsnPd2CiAo,812 +_pyinstaller_hooks_contrib/stdhooks/hook-uniseg.py,sha256=vBDFt52WHwaVWhSJGmBxlPR8Iuvjo9iVvw8l5xSrv_I,581 +_pyinstaller_hooks_contrib/stdhooks/hook-usb.py,sha256=es_6ZM9HBo-fIhyRACCiCINf_0rGHSlJuUBCQcNetag,3211 +_pyinstaller_hooks_contrib/stdhooks/hook-uvicorn.py,sha256=rPwThXcBdALtt0PQ2_kCG77QhiFTsLPVVvRHnO-zPdE,523 +_pyinstaller_hooks_contrib/stdhooks/hook-uvloop.py,sha256=klDycjXcNetKquOPOWYx2VedfVovgHE4sT0d24EsG6Q,663 +_pyinstaller_hooks_contrib/stdhooks/hook-vaderSentiment.py,sha256=oLtl1Fxlp5BBvcPvnY350FlkKJ_xe6TNDt6e20-CwQk,522 +_pyinstaller_hooks_contrib/stdhooks/hook-vtkpython.py,sha256=XY14rmVQKna1LvNhqszoImb0sW0UKuVZzYm_kOocjbs,949 +_pyinstaller_hooks_contrib/stdhooks/hook-wavefile.py,sha256=F-rA6wwxPPP-Ri15hEjDUVZ5uZ57uNt9rkNawmNaEuw,591 +_pyinstaller_hooks_contrib/stdhooks/hook-weasyprint.py,sha256=YQOd1AX1lmOr8rHwKcuuhzClJ4DlEFf8MZcsG5bAwI8,3915 +_pyinstaller_hooks_contrib/stdhooks/hook-web3.py,sha256=0XtNeiUKBz-SpHYaij3g_1KatWh3fIxJWyQrbK1Dg68,502 +_pyinstaller_hooks_contrib/stdhooks/hook-webassets.py,sha256=-9vQAQ_Dd_-zwabZSkNxn-vcCBbIDNp6mHKXT2jRhKk,539 +_pyinstaller_hooks_contrib/stdhooks/hook-webrtcvad.py,sha256=-Hhm45kE1oYpZ9c00GJfMdd46Isxh7IqXh58oircRcA,507 +_pyinstaller_hooks_contrib/stdhooks/hook-websockets.py,sha256=PklUXHU4iZxvFsnOgGdRyDFRxc15MCUSYIukc5L6vrA,568 +_pyinstaller_hooks_contrib/stdhooks/hook-webview.py,sha256=gcMHLFaKnsJuT08WGHbNeUOG0CabbQkggLursppRF40,698 +_pyinstaller_hooks_contrib/stdhooks/hook-win32com.py,sha256=0qR38kqHPFVAVKNhoCf7J-Oiui5gMM4myOTnZ5iEARI,644 +_pyinstaller_hooks_contrib/stdhooks/hook-wordcloud.py,sha256=nxDRIYdgKiB4QAoHBWRH5NFIqIaGVn560YWDI3Wnj1Y,517 +_pyinstaller_hooks_contrib/stdhooks/hook-workflow.py,sha256=l-HbGtVerjzReiLC0yrcyU0jsif_-NS7X2_f4_oxxII,506 +_pyinstaller_hooks_contrib/stdhooks/hook-wx.lib.activex.py,sha256=2ulQkghVbnvMxfynUZqGnRvpmplAYbOW08g578JY9Ik,581 +_pyinstaller_hooks_contrib/stdhooks/hook-wx.lib.pubsub.py,sha256=DIywUIZkoSM9VOqolMahmlcy8S3wdo4EOA6SxAawetE,582 +_pyinstaller_hooks_contrib/stdhooks/hook-wx.xrc.py,sha256=G1iIeRh7Kfa1W6dkewEK28s1zAgLWP8RN9nYnNVbPbU,455 +_pyinstaller_hooks_contrib/stdhooks/hook-xarray.py,sha256=LMjkQzvZN96S9PQOUKYguyWOyAFqFOakIWYONg9sW_g,1137 +_pyinstaller_hooks_contrib/stdhooks/hook-xml.dom.html.HTMLDocument.py,sha256=ABU_wswgSp07v_Bi_5mba8z1m3UpQHFl-xL7ihogAvs,3146 +_pyinstaller_hooks_contrib/stdhooks/hook-xml.sax.saxexts.py,sha256=406w-Anp5EylNFApwQ0bnbuIyMpiU1jU4BfdSGuPl-4,990 +_pyinstaller_hooks_contrib/stdhooks/hook-xmldiff.py,sha256=4Ko0wHSSSsmBPntpyr22NzY1ZAbB546go6Vxmjwst68,550 +_pyinstaller_hooks_contrib/stdhooks/hook-xmlschema.py,sha256=l59u4QIkdzmcIMj27GLW1puTVMNIdr8e96ur3viCYmk,644 +_pyinstaller_hooks_contrib/stdhooks/hook-xsge_gui.py,sha256=NJ70wLfuoi-jyCD-mDR1NAP01mhSr0AT3qwuvkZT8dU,587 +_pyinstaller_hooks_contrib/stdhooks/hook-xyzservices.py,sha256=6cgNAv3RLgNsQYF91Y61ai3EfJCaz2f6Htcn-Dsm9Wo,519 +_pyinstaller_hooks_contrib/stdhooks/hook-yapf_third_party.py,sha256=JwB1RswTKDKzdIVFe3qmt30Y6DHsMu2N7vzd6U8GY-g,524 +_pyinstaller_hooks_contrib/stdhooks/hook-z3c.rml.py,sha256=phkXTZu8hR1Y7GfFnbGw6Zcj2yVwRvbqvpx1fNR6KAQ,959 +_pyinstaller_hooks_contrib/stdhooks/hook-zeep.py,sha256=Ds1kPuoCIJmioNWV91MI76TUO5al5QBlfHW_4Hu2ubI,612 +_pyinstaller_hooks_contrib/stdhooks/hook-zmq.py,sha256=B_VFStoRQzFF5tej6d6keZ1TGNCsEedH56FmdKkRqVk,2725 +_pyinstaller_hooks_contrib/stdhooks/hook-zoneinfo.py,sha256=99A9LN6khAbUAQfey6FaTHtdGZEaaOjavxwawAzbTdo,595 +_pyinstaller_hooks_contrib/utils/__init__.py,sha256=MsSFjiLMLJZ7QhUPpVBWKiyDnCzryquRyr329NoCACI,2 +_pyinstaller_hooks_contrib/utils/__pycache__/__init__.cpython-311.pyc,, +_pyinstaller_hooks_contrib/utils/__pycache__/nvidia_cuda.cpython-311.pyc,, +_pyinstaller_hooks_contrib/utils/nvidia_cuda.py,sha256=gJO659n9CBpaGi6zYgFl1cdHHPvN125IaWWBC3yR9Qc,3009 +pyinstaller_hooks_contrib-2024.10.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +pyinstaller_hooks_contrib-2024.10.dist-info/LICENSE,sha256=kdC6r_AHcwOOcsCh_J1dLThwa3ornATzQpZgj5MbnNA,27666 +pyinstaller_hooks_contrib-2024.10.dist-info/METADATA,sha256=rwdCwvShyp0HojumqxC8yukk4_Hawzro87xZXHjgg_0,16000 +pyinstaller_hooks_contrib-2024.10.dist-info/RECORD,, +pyinstaller_hooks_contrib-2024.10.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91 +pyinstaller_hooks_contrib-2024.10.dist-info/entry_points.txt,sha256=FsM9QtmkHCPo9b23sWrxVW7Fv4awouh1WnBDFJpxJPs,69 +pyinstaller_hooks_contrib-2024.10.dist-info/top_level.txt,sha256=iLfKgsga5bLZMSkoWpHxWt6tDjcPVCvGsJgvwfMYcnA,27 diff --git a/venv/Lib/site-packages/pyinstaller_hooks_contrib-2024.10.dist-info/WHEEL b/venv/Lib/site-packages/pyinstaller_hooks_contrib-2024.10.dist-info/WHEEL new file mode 100644 index 0000000..9b78c44 --- /dev/null +++ b/venv/Lib/site-packages/pyinstaller_hooks_contrib-2024.10.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: setuptools (75.3.0) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/venv/Lib/site-packages/pyinstaller_hooks_contrib-2024.10.dist-info/entry_points.txt b/venv/Lib/site-packages/pyinstaller_hooks_contrib-2024.10.dist-info/entry_points.txt new file mode 100644 index 0000000..a8c18cf --- /dev/null +++ b/venv/Lib/site-packages/pyinstaller_hooks_contrib-2024.10.dist-info/entry_points.txt @@ -0,0 +1,2 @@ +[pyinstaller40] +hook-dirs = _pyinstaller_hooks_contrib:get_hook_dirs diff --git a/venv/Lib/site-packages/pyinstaller_hooks_contrib-2024.10.dist-info/top_level.txt b/venv/Lib/site-packages/pyinstaller_hooks_contrib-2024.10.dist-info/top_level.txt new file mode 100644 index 0000000..3d4a9b3 --- /dev/null +++ b/venv/Lib/site-packages/pyinstaller_hooks_contrib-2024.10.dist-info/top_level.txt @@ -0,0 +1 @@ +_pyinstaller_hooks_contrib diff --git a/venv/Lib/site-packages/pywin32_ctypes-0.2.3.dist-info/INSTALLER b/venv/Lib/site-packages/pywin32_ctypes-0.2.3.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/Lib/site-packages/pywin32_ctypes-0.2.3.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/venv/Lib/site-packages/pywin32_ctypes-0.2.3.dist-info/LICENSE.txt b/venv/Lib/site-packages/pywin32_ctypes-0.2.3.dist-info/LICENSE.txt new file mode 100644 index 0000000..d0ce125 --- /dev/null +++ b/venv/Lib/site-packages/pywin32_ctypes-0.2.3.dist-info/LICENSE.txt @@ -0,0 +1,28 @@ +This software is OSI Certified Open Source Software. +OSI Certified is a certification mark of the Open Source Initiative. + +Copyright (c) 2014, Enthought, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of Enthought, Inc. nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/venv/Lib/site-packages/pywin32_ctypes-0.2.3.dist-info/METADATA b/venv/Lib/site-packages/pywin32_ctypes-0.2.3.dist-info/METADATA new file mode 100644 index 0000000..1d67907 --- /dev/null +++ b/venv/Lib/site-packages/pywin32_ctypes-0.2.3.dist-info/METADATA @@ -0,0 +1,134 @@ +Metadata-Version: 2.1 +Name: pywin32-ctypes +Version: 0.2.3 +Summary: A (partial) reimplementation of pywin32 using ctypes/cffi +Home-page: https://github.com/enthought/pywin32-ctypes +Author: Enthought Inc. +Author-email: info@enthough.com +License: BSD-3-Clause +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Requires-Python: >=3.6 + + +.. image:: https://readthedocs.org/projects/pywin32-ctypes/badge/?version=master + :target: http://pywin32-ctypes.readthedocs.org/en/latest/?badge=master + :alt: Documentation Status + +A reimplementation of pywin32 that is pure python. The default +behaviour will try to use cffi (>= 1.3.0), if available, and fall back +to using ctypes. Please note that there is no need to have a compiler +available on installation or at runtime. + +Usage +===== + +Example:: + + # Equivalent to 'import win32api' from pywin32. + from win32ctypes.pywin32 import win32api + + win32api.LoadLibraryEx(sys.executable, 0, win32api.LOAD_LIBRARY_AS_DATAFILE) + +.. note:: + + Currently pywin32ctypes implements only a very small subset + of pywin32, for internal needs at Enthought. We do welcome + additional features and PRs, though. + +Development setup +================= + +The following should be good enough:: + + pip install -r test_requirements.txt + python install -e . + +.. note:: + + - While pywin32-ctypes should regularly be tested on windows, you can also + develop/test on unix by using wine + +Change Log +========== + +Version 0.2.3 +------------- + +- Do not use loal_module in backend selection code (#131, #132) +- Add pywin32.pywintypes.Time (#122) + +Version 0.2.2 +------------- + +- Use ctypes.set_last_error to avoid race conditions (#122) + +Version 0.2.1 +------------- + +- Use faulthandler when testing and fix discovered errors (#115, #117). +- Fix support for None username in credentials to be consistent in all backends (#99). +- Test also on cp38, cp39, cp310, cp311 and use cp38 for linking (#114, #107, #100). +- Add support for CredEnumerate extending code from @markb-EE (#110, #109, #111) +- Remove support for older python versions < cp36 (#104, #120). + +Version 0.2.0 +------------- + +- Fix syntax error when installing in python 3.7 (#81). +- Support testing on python 3.7 (#82). +- Support testing on python 3.3 and python 3.4 (#77). +- Do not use 2to3 (#75). +- Support lazy wrapping of win32 functions (#67). +- Add CRED_PERSIST constants (#79 contributed by @tivnet). + +Version 0.1.2 +------------- + +(bugfix release) + +- Fix implementation for the deprecated api (#64). + +Version 0.1.1 +------------- + +(bugfix release) + +- Update Manifest.in entries (#63) +- fix VERSION path in Manifest.in (#62 contributed by @MinchinWeb) + + +Version 0.1.0 +------------- + +- Update tests and provide better compatibility with pywin32 for + Resource functions +- Fix: Python 3.5 and 3.6 support (#52). +- API additions to allow pywin32-ctypes to work with pyinstaller (#46 + and #57 contributed by @virtuald). +- Fix: do not update the global copy of the windows dlls (#42) +- Add documentation and setup automatic builds in ReadTheDocs (#3, #36). +- Add cffi backend to be used when available (#31). +- Fix: EnumResourceTypes and EnumResourceNames would only return ints + (#21, #30). +- Restructure package layout to split core wrapping modules from + pywin32 emulation (#15, #17). + +Version 0.0.1 +------------- + +7/04/2014 + +- Python 2.6 support (#13) +- Python 3 support (#12) +- Basic maintenance work (#11, #7) +- Fix error raising to be pywin32 compatible (#8) +- Package rename mini_pywin32 -> pywin32-ctypes +- Add travis-ci integration using wine! (#2) +- Support basic library and resource loading (#1) +- mini_pywin32 is born diff --git a/venv/Lib/site-packages/pywin32_ctypes-0.2.3.dist-info/RECORD b/venv/Lib/site-packages/pywin32_ctypes-0.2.3.dist-info/RECORD new file mode 100644 index 0000000..282adb3 --- /dev/null +++ b/venv/Lib/site-packages/pywin32_ctypes-0.2.3.dist-info/RECORD @@ -0,0 +1,74 @@ +pywin32_ctypes-0.2.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +pywin32_ctypes-0.2.3.dist-info/LICENSE.txt,sha256=36g7PicJrfzbg42a1VgjymdKu3gOYFY9ndlUTMv3hek,1644 +pywin32_ctypes-0.2.3.dist-info/METADATA,sha256=Hjdn0_r_TVucNHFgiDgxCY0fJaz0MGsCyazcxr-1iDs,3909 +pywin32_ctypes-0.2.3.dist-info/RECORD,, +pywin32_ctypes-0.2.3.dist-info/WHEEL,sha256=OqRkF0eY5GHssMorFjlbTIq072vpHpF60fIQA6lS9xA,92 +pywin32_ctypes-0.2.3.dist-info/top_level.txt,sha256=Q67ar0C8ghsHWr96rJ8iA0mLCxbYQLxeS5fHmMODw0k,12 +win32ctypes/__init__.py,sha256=EmS7iTWm0dQUortMjTA5JEWYIH25AUBUaDPhppFfTHo,214 +win32ctypes/__pycache__/__init__.cpython-311.pyc,, +win32ctypes/__pycache__/pywintypes.cpython-311.pyc,, +win32ctypes/__pycache__/version.cpython-311.pyc,, +win32ctypes/__pycache__/win32api.cpython-311.pyc,, +win32ctypes/__pycache__/win32cred.cpython-311.pyc,, +win32ctypes/core/__init__.py,sha256=qbdg3TvIwp_CZd4nHUhGiXEw1bTKXxJHqQt-4647c1Q,1647 +win32ctypes/core/__pycache__/__init__.cpython-311.pyc,, +win32ctypes/core/__pycache__/_winerrors.cpython-311.pyc,, +win32ctypes/core/__pycache__/compat.cpython-311.pyc,, +win32ctypes/core/_winerrors.py,sha256=p52rv5vvDGMNiRvvT_npIXWEsXPoVDMtom-gmto5k0M,199 +win32ctypes/core/cffi/__init__.py,sha256=M68T4frchcWxHFZZhDm7F9Os4YbPX4RUtKBboPTsu70,270 +win32ctypes/core/cffi/__pycache__/__init__.cpython-311.pyc,, +win32ctypes/core/cffi/__pycache__/_authentication.cpython-311.pyc,, +win32ctypes/core/cffi/__pycache__/_common.cpython-311.pyc,, +win32ctypes/core/cffi/__pycache__/_dll.cpython-311.pyc,, +win32ctypes/core/cffi/__pycache__/_nl_support.cpython-311.pyc,, +win32ctypes/core/cffi/__pycache__/_resource.cpython-311.pyc,, +win32ctypes/core/cffi/__pycache__/_system_information.cpython-311.pyc,, +win32ctypes/core/cffi/__pycache__/_time.cpython-311.pyc,, +win32ctypes/core/cffi/__pycache__/_util.cpython-311.pyc,, +win32ctypes/core/cffi/_authentication.py,sha256=oRxgigZ3mB_JTXFHIlJZxWY2b35PnQaDvEbzqJNxpzs,5333 +win32ctypes/core/cffi/_common.py,sha256=tKvSSDBiYlL1gqvg1FX_RHLTYaoNWO7LJ61d78CVyf4,576 +win32ctypes/core/cffi/_dll.py,sha256=GIGxlq_6hY-OiCc0pAmPcGNav-q68jdtMdoTSCgUt64,771 +win32ctypes/core/cffi/_nl_support.py,sha256=FFxF4XcAF2W_fPvpwrrTpA61lYMRh03qwF3kF9dvFkw,313 +win32ctypes/core/cffi/_resource.py,sha256=GABPpUTN16QiXlXqYSjkw7kpJUY-DZExfMVWc8cBRlo,4555 +win32ctypes/core/cffi/_system_information.py,sha256=a_WRyYi-F9Bf299lvNMb_ZEc4zxIoL02VMj-5j_dkM8,872 +win32ctypes/core/cffi/_time.py,sha256=yEUTm7TIx_d2Me1vOFVsubOR_8Xmsob6e80n6dj9wYI,332 +win32ctypes/core/cffi/_util.py,sha256=qwc1wkFdryhvOPZf1W7nWZMkuS2o8GuPpQM2-sQCDUY,2662 +win32ctypes/core/compat.py,sha256=XPSOaAxQA4dLn0knXO9wferQb6IpVVA56AKa95W5MkU,158 +win32ctypes/core/ctypes/__init__.py,sha256=HeNUjdP0Bj5SHeb_cVMqCZa00BUTHD8E1DqFq0wpaFk,272 +win32ctypes/core/ctypes/__pycache__/__init__.cpython-311.pyc,, +win32ctypes/core/ctypes/__pycache__/_authentication.cpython-311.pyc,, +win32ctypes/core/ctypes/__pycache__/_common.cpython-311.pyc,, +win32ctypes/core/ctypes/__pycache__/_dll.cpython-311.pyc,, +win32ctypes/core/ctypes/__pycache__/_nl_support.cpython-311.pyc,, +win32ctypes/core/ctypes/__pycache__/_resource.cpython-311.pyc,, +win32ctypes/core/ctypes/__pycache__/_system_information.cpython-311.pyc,, +win32ctypes/core/ctypes/__pycache__/_time.cpython-311.pyc,, +win32ctypes/core/ctypes/__pycache__/_util.cpython-311.pyc,, +win32ctypes/core/ctypes/_authentication.py,sha256=vcNber8K_MUWDgzieTiV4wVEWl1wwTBevnMKpf6SDTM,3822 +win32ctypes/core/ctypes/_common.py,sha256=xPyUGrNusRGHPJcstR4vxPJiXD75COovAWo0EsCX7ro,1223 +win32ctypes/core/ctypes/_dll.py,sha256=mfEhaV7Nbp8pok0xg0O6GhasE6oSOOxb4cgKPe38FTg,552 +win32ctypes/core/ctypes/_nl_support.py,sha256=ST6YPzpCVq1JqiXVxEoULUTRFl_rBjMF_1qPNmsLqlU,315 +win32ctypes/core/ctypes/_resource.py,sha256=YzmBvf04Gd0pWLt0i2cIQYmaBcBW4X2Qu--sbk4331A,4264 +win32ctypes/core/ctypes/_system_information.py,sha256=TDrldTP4LTrOOGe6UVLKdFkrRwE428BWVTE2GPNHVMo,941 +win32ctypes/core/ctypes/_time.py,sha256=0XYWMiahecwh2VgCLdfoHxFqw-bufX4_RCA2sr4CSxI,342 +win32ctypes/core/ctypes/_util.py,sha256=Yb5hKGpbfnHfZX6x4oYzco5iLg6AhMTa6OCeLHf8-go,2030 +win32ctypes/pywin32/__init__.py,sha256=Wx5mqYeeweqoUDcHEBzrgDNLRPye2SoWk1MwUsDDkSU,354 +win32ctypes/pywin32/__pycache__/__init__.cpython-311.pyc,, +win32ctypes/pywin32/__pycache__/pywintypes.cpython-311.pyc,, +win32ctypes/pywin32/__pycache__/win32api.cpython-311.pyc,, +win32ctypes/pywin32/__pycache__/win32cred.cpython-311.pyc,, +win32ctypes/pywin32/pywintypes.py,sha256=kpOmM9lJ8w3BIP0T7j7efzxhroD7Yyp7Em80O8q1BrQ,1867 +win32ctypes/pywin32/win32api.py,sha256=NZ3dUJ9bdMPBhH89EDb3s_ijljFRWvy2vFwrO6bJuA8,7724 +win32ctypes/pywin32/win32cred.py,sha256=ZgSLu7NU5kAQP8a6SlHXtfTSLufAd24uO8govj1i2kA,4801 +win32ctypes/pywintypes.py,sha256=wVw61R5MJfof6hExSaI4RR3cnxEZjoJarCH80NtPnr8,350 +win32ctypes/tests/__init__.py,sha256=sr6UZPhlGoCY5Hm7pEt8NKzXKP9YIuiIObi-HO2BLiI,693 +win32ctypes/tests/__pycache__/__init__.cpython-311.pyc,, +win32ctypes/tests/__pycache__/test_backends.cpython-311.pyc,, +win32ctypes/tests/__pycache__/test_win32api.cpython-311.pyc,, +win32ctypes/tests/__pycache__/test_win32cred.cpython-311.pyc,, +win32ctypes/tests/test_backends.py,sha256=Qjlo6GC2HHkcS31wnmvLjna2UtCym2qwR1jWWcqo_EY,1245 +win32ctypes/tests/test_win32api.py,sha256=8b-ZvjAjHhUO5aCqKM2rYR_4UprSfv8AFNKSo2b5grA,11687 +win32ctypes/tests/test_win32cred.py,sha256=SM__Oj6LNPzmZIOWZwBK3nHvSRNW6Nk6AO8kk9iR9bE,7948 +win32ctypes/version.py,sha256=o4ScPsx3ebE9pX-fF55Y4NZwE-gZl1putS6aE2pTVtI,23 +win32ctypes/win32api.py,sha256=iEIHL_pJIHauSkKXKAz0CpQ-tg9lR9YJzrV68jAVjq0,346 +win32ctypes/win32cred.py,sha256=NNXVc3-4Cot0xxwJmTFzY9B6H6YEX6egQW-kbmWFkf8,348 diff --git a/venv/Lib/site-packages/pywin32_ctypes-0.2.3.dist-info/WHEEL b/venv/Lib/site-packages/pywin32_ctypes-0.2.3.dist-info/WHEEL new file mode 100644 index 0000000..385faab --- /dev/null +++ b/venv/Lib/site-packages/pywin32_ctypes-0.2.3.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.36.2) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/venv/Lib/site-packages/pywin32_ctypes-0.2.3.dist-info/top_level.txt b/venv/Lib/site-packages/pywin32_ctypes-0.2.3.dist-info/top_level.txt new file mode 100644 index 0000000..b10cf3c --- /dev/null +++ b/venv/Lib/site-packages/pywin32_ctypes-0.2.3.dist-info/top_level.txt @@ -0,0 +1 @@ +win32ctypes diff --git a/venv/Lib/site-packages/win32ctypes/__init__.py b/venv/Lib/site-packages/win32ctypes/__init__.py new file mode 100644 index 0000000..d769d60 --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/__init__.py @@ -0,0 +1,8 @@ +# +# (C) Copyright 2014 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +from .version import __version__ # noqa diff --git a/venv/Lib/site-packages/win32ctypes/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..b6fe815 Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/__pycache__/pywintypes.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/__pycache__/pywintypes.cpython-311.pyc new file mode 100644 index 0000000..d7735de Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/__pycache__/pywintypes.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/__pycache__/version.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/__pycache__/version.cpython-311.pyc new file mode 100644 index 0000000..d3d211a Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/__pycache__/version.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/__pycache__/win32api.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/__pycache__/win32api.cpython-311.pyc new file mode 100644 index 0000000..4874d00 Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/__pycache__/win32api.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/__pycache__/win32cred.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/__pycache__/win32cred.cpython-311.pyc new file mode 100644 index 0000000..f262112 Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/__pycache__/win32cred.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/core/__init__.py b/venv/Lib/site-packages/win32ctypes/core/__init__.py new file mode 100644 index 0000000..887bb03 --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/core/__init__.py @@ -0,0 +1,60 @@ +# +# (C) Copyright 2014-2024 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +import sys +import importlib +from importlib.abc import MetaPathFinder, Loader + +from . import _winerrors # noqa + +# Setup module redirection based on the backend +try: + import cffi +except ImportError: + _backend = 'ctypes' +else: + del cffi + _backend = 'cffi' + + +class BackendLoader(Loader): + + def __init__(self, redirect_module): + self.redirect_module = redirect_module + + def create_module(self, spec): + return importlib.import_module(self.redirect_module) + + def exec_module(self, module): + pass + + +class BackendFinder(MetaPathFinder): + + def __init__(self, modules): + self.redirected_modules = { + 'win32ctypes.core.{}'.format(module) + for module in modules} + + def find_spec(self, fullname, path, target=None): + if fullname in self.redirected_modules: + module_name = fullname.split('.')[-1] + if _backend == 'ctypes': + redirected = f'win32ctypes.core.ctypes.{module_name}' + else: + redirected = f'win32ctypes.core.cffi.{module_name}' + loader = BackendLoader(redirected) + return importlib.machinery.ModuleSpec( + f'win32ctypes.core.{module_name}', loader) + else: + return None + + +sys.meta_path.append(BackendFinder([ + '_dll', '_authentication', '_time', + '_common', '_resource', '_nl_support', + '_system_information'])) diff --git a/venv/Lib/site-packages/win32ctypes/core/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/core/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..aa03e89 Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/core/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/core/__pycache__/_winerrors.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/core/__pycache__/_winerrors.cpython-311.pyc new file mode 100644 index 0000000..26ac308 Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/core/__pycache__/_winerrors.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/core/__pycache__/compat.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/core/__pycache__/compat.cpython-311.pyc new file mode 100644 index 0000000..bbf2196 Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/core/__pycache__/compat.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/core/_winerrors.py b/venv/Lib/site-packages/win32ctypes/core/_winerrors.py new file mode 100644 index 0000000..bb760d5 --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/core/_winerrors.py @@ -0,0 +1,9 @@ +# +# (C) Copyright 2014 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# + +ERROR_NOT_FOUND = 0x490 diff --git a/venv/Lib/site-packages/win32ctypes/core/cffi/__init__.py b/venv/Lib/site-packages/win32ctypes/core/cffi/__init__.py new file mode 100644 index 0000000..6fac1f4 --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/core/cffi/__init__.py @@ -0,0 +1,11 @@ +# +# (C) Copyright 2014-2023 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +import logging + +logger = logging.getLogger(__name__) +logger.debug('Loaded cffi backend') diff --git a/venv/Lib/site-packages/win32ctypes/core/cffi/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/core/cffi/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..03ca094 Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/core/cffi/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/core/cffi/__pycache__/_authentication.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/core/cffi/__pycache__/_authentication.cpython-311.pyc new file mode 100644 index 0000000..36fcc27 Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/core/cffi/__pycache__/_authentication.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/core/cffi/__pycache__/_common.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/core/cffi/__pycache__/_common.cpython-311.pyc new file mode 100644 index 0000000..942d853 Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/core/cffi/__pycache__/_common.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/core/cffi/__pycache__/_dll.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/core/cffi/__pycache__/_dll.cpython-311.pyc new file mode 100644 index 0000000..77f76eb Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/core/cffi/__pycache__/_dll.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/core/cffi/__pycache__/_nl_support.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/core/cffi/__pycache__/_nl_support.cpython-311.pyc new file mode 100644 index 0000000..17cfbe3 Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/core/cffi/__pycache__/_nl_support.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/core/cffi/__pycache__/_resource.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/core/cffi/__pycache__/_resource.cpython-311.pyc new file mode 100644 index 0000000..2568197 Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/core/cffi/__pycache__/_resource.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/core/cffi/__pycache__/_system_information.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/core/cffi/__pycache__/_system_information.cpython-311.pyc new file mode 100644 index 0000000..15a4e6e Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/core/cffi/__pycache__/_system_information.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/core/cffi/__pycache__/_time.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/core/cffi/__pycache__/_time.cpython-311.pyc new file mode 100644 index 0000000..d1bf545 Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/core/cffi/__pycache__/_time.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/core/cffi/__pycache__/_util.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/core/cffi/__pycache__/_util.cpython-311.pyc new file mode 100644 index 0000000..dbef7b7 Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/core/cffi/__pycache__/_util.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/core/cffi/_authentication.py b/venv/Lib/site-packages/win32ctypes/core/cffi/_authentication.py new file mode 100644 index 0000000..a74b8fb --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/core/cffi/_authentication.py @@ -0,0 +1,172 @@ +# +# (C) Copyright 2015 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +from weakref import WeakKeyDictionary + +from win32ctypes.core.compat import is_text +from ._util import ffi, check_false, dlls +from ._nl_support import _GetACP +from ._common import _PyBytes_FromStringAndSize + + +ffi.cdef(""" + +typedef struct _FILETIME { + DWORD dwLowDateTime; + DWORD dwHighDateTime; +} FILETIME, *PFILETIME; + +typedef struct _CREDENTIAL_ATTRIBUTE { + LPWSTR Keyword; + DWORD Flags; + DWORD ValueSize; + LPBYTE Value; +} CREDENTIAL_ATTRIBUTE, *PCREDENTIAL_ATTRIBUTE; + +typedef struct _CREDENTIAL { + DWORD Flags; + DWORD Type; + LPWSTR TargetName; + LPWSTR Comment; + FILETIME LastWritten; + DWORD CredentialBlobSize; + LPBYTE CredentialBlob; + DWORD Persist; + DWORD AttributeCount; + PCREDENTIAL_ATTRIBUTE Attributes; + LPWSTR TargetAlias; + LPWSTR UserName; +} CREDENTIAL, *PCREDENTIAL; + + +BOOL WINAPI CredReadW( + LPCWSTR TargetName, DWORD Type, DWORD Flags, PCREDENTIAL *Credential); +BOOL WINAPI CredWriteW(PCREDENTIAL Credential, DWORD); +VOID WINAPI CredFree(PVOID Buffer); +BOOL WINAPI CredDeleteW(LPCWSTR TargetName, DWORD Type, DWORD Flags); +BOOL WINAPI CredEnumerateW( + LPCWSTR Filter, DWORD Flags, DWORD *Count, PCREDENTIAL **Credential); +""") + +_keep_alive = WeakKeyDictionary() + + +SUPPORTED_CREDKEYS = set(( + u'Type', u'TargetName', u'Persist', + u'UserName', u'Comment', u'CredentialBlob')) + + +def make_unicode(password): + """ Convert the input string to unicode. + + """ + if is_text(password): + return password + else: + code_page = _GetACP() + return password.decode(encoding=str(code_page), errors='strict') + + +class _CREDENTIAL(object): + + def __call__(self): + return ffi.new("PCREDENTIAL")[0] + + @classmethod + def fromdict(cls, credential, flag=0): + unsupported = set(credential.keys()) - SUPPORTED_CREDKEYS + if len(unsupported): + raise ValueError("Unsupported keys: {0}".format(unsupported)) + if flag != 0: + raise ValueError("flag != 0 not yet supported") + + factory = cls() + c_creds = factory() + # values to ref and make sure that they will not go away + values = [] + for key, value in credential.items(): + if key == u'CredentialBlob': + blob = make_unicode(value) + blob_data = ffi.new('wchar_t[]', blob) + # new adds a NULL at the end that we do not want. + c_creds.CredentialBlobSize = \ + ffi.sizeof(blob_data) - ffi.sizeof('wchar_t') + c_creds.CredentialBlob = ffi.cast('LPBYTE', blob_data) + values.append(blob_data) + elif key in (u'Type', u'Persist'): + setattr(c_creds, key, value) + elif value is None: + setattr(c_creds, key, ffi.NULL) + else: + blob = make_unicode(value) + pblob = ffi.new('wchar_t[]', blob) + values.append(pblob) + setattr(c_creds, key, ffi.cast('LPTSTR', pblob)) + # keep values alive until c_creds goes away. + _keep_alive[c_creds] = tuple(values) + return c_creds + + +CREDENTIAL = _CREDENTIAL() + + +def PCREDENTIAL(value=None): + return ffi.new("PCREDENTIAL", ffi.NULL if value is None else value) + + +def PPCREDENTIAL(value=None): + return ffi.new("PCREDENTIAL*", ffi.NULL if value is None else value) + + +def PPPCREDENTIAL(value=None): + return ffi.new("PCREDENTIAL**", ffi.NULL if value is None else value) + + +def credential2dict(pc_creds): + credentials = {} + for key in SUPPORTED_CREDKEYS: + if key == u'CredentialBlob': + data = _PyBytes_FromStringAndSize( + pc_creds.CredentialBlob, pc_creds.CredentialBlobSize) + elif key in (u'Type', u'Persist'): + data = int(getattr(pc_creds, key)) + else: + string_pointer = getattr(pc_creds, key) + if string_pointer == ffi.NULL: + data = None + else: + data = ffi.string(string_pointer) + credentials[key] = data + return credentials + + +def _CredRead(TargetName, Type, Flags, ppCredential): + target = make_unicode(TargetName) + return check_false( + dlls.advapi32.CredReadW(target, Type, Flags, ppCredential), + u'CredRead') + + +def _CredWrite(Credential, Flags): + return check_false( + dlls.advapi32.CredWriteW(Credential, Flags), u'CredWrite') + + +def _CredDelete(TargetName, Type, Flags): + return check_false( + dlls.advapi32.CredDeleteW( + make_unicode(TargetName), Type, Flags), u'CredDelete') + + +def _CredEnumerate(Filter, Flags, Count, pppCredential): + filter = make_unicode(Filter) if Filter is not None else ffi.NULL + return check_false( + dlls.advapi32.CredEnumerateW(filter, Flags, Count, pppCredential), + u'CredEnumerate') + + +_CredFree = dlls.advapi32.CredFree diff --git a/venv/Lib/site-packages/win32ctypes/core/cffi/_common.py b/venv/Lib/site-packages/win32ctypes/core/cffi/_common.py new file mode 100644 index 0000000..df7e0ec --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/core/cffi/_common.py @@ -0,0 +1,29 @@ +# +# (C) Copyright 2015 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +from weakref import WeakKeyDictionary + +from ._util import ffi + +_keep_alive = WeakKeyDictionary() + + +def _PyBytes_FromStringAndSize(pointer, size): + buffer = ffi.buffer(pointer, size) + return buffer[:] + + +def byreference(x): + return ffi.new(ffi.getctype(ffi.typeof(x), '*'), x) + + +def dereference(x): + return x[0] + + +def PDWORD(value=0): + return ffi.new("DWORD *", value) diff --git a/venv/Lib/site-packages/win32ctypes/core/cffi/_dll.py b/venv/Lib/site-packages/win32ctypes/core/cffi/_dll.py new file mode 100644 index 0000000..038e761 --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/core/cffi/_dll.py @@ -0,0 +1,30 @@ +# +# (C) Copyright 2018 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +from ._util import ffi, check_null, check_false, dlls, HMODULE, PVOID + + +ffi.cdef(""" + +HMODULE WINAPI LoadLibraryExW(LPCTSTR lpFileName, HANDLE hFile, DWORD dwFlags); +BOOL WINAPI FreeLibrary(HMODULE hModule); + +""") + + +def _LoadLibraryEx(lpFilename, hFile, dwFlags): + result = check_null( + dlls.kernel32.LoadLibraryExW( + str(lpFilename), ffi.NULL, dwFlags), + function_name='LoadLibraryEx') + return HMODULE(result) + + +def _FreeLibrary(hModule): + check_false( + dlls.kernel32.FreeLibrary(PVOID(hModule)), + function_name='FreeLibrary') diff --git a/venv/Lib/site-packages/win32ctypes/core/cffi/_nl_support.py b/venv/Lib/site-packages/win32ctypes/core/cffi/_nl_support.py new file mode 100644 index 0000000..51f7194 --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/core/cffi/_nl_support.py @@ -0,0 +1,18 @@ +# +# (C) Copyright 2015-18 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +from ._util import ffi, dlls + +ffi.cdef(""" + +UINT WINAPI GetACP(void); + +""") + + +def _GetACP(): + return dlls.kernel32.GetACP() diff --git a/venv/Lib/site-packages/win32ctypes/core/cffi/_resource.py b/venv/Lib/site-packages/win32ctypes/core/cffi/_resource.py new file mode 100644 index 0000000..42bcbde --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/core/cffi/_resource.py @@ -0,0 +1,132 @@ +# +# (C) Copyright 2015 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +from ._util import ( + ffi, check_null, check_zero, check_false, HMODULE, + PVOID, RESOURCE, resource, dlls) + + +ffi.cdef(""" + +typedef int WINBOOL; +typedef WINBOOL (__stdcall *ENUMRESTYPEPROC) (HANDLE, LPTSTR, LONG_PTR); +typedef WINBOOL (__stdcall *ENUMRESNAMEPROC) (HANDLE, LPCTSTR, LPTSTR, LONG_PTR); +typedef WINBOOL (__stdcall *ENUMRESLANGPROC) (HANDLE, LPCTSTR, LPCTSTR, WORD, LONG_PTR); + +BOOL WINAPI EnumResourceTypesW( + HMODULE hModule, ENUMRESTYPEPROC lpEnumFunc, LONG_PTR lParam); +BOOL WINAPI EnumResourceNamesW( + HMODULE hModule, LPCTSTR lpszType, + ENUMRESNAMEPROC lpEnumFunc, LONG_PTR lParam); +BOOL WINAPI EnumResourceLanguagesW( + HMODULE hModule, LPCTSTR lpType, + LPCTSTR lpName, ENUMRESLANGPROC lpEnumFunc, LONG_PTR lParam); +HRSRC WINAPI FindResourceExW( + HMODULE hModule, LPCTSTR lpType, LPCTSTR lpName, WORD wLanguage); +DWORD WINAPI SizeofResource(HMODULE hModule, HRSRC hResInfo); +HGLOBAL WINAPI LoadResource(HMODULE hModule, HRSRC hResInfo); +LPVOID WINAPI LockResource(HGLOBAL hResData); + +HANDLE WINAPI BeginUpdateResourceW(LPCTSTR pFileName, BOOL bDeleteExistingResources); +BOOL WINAPI EndUpdateResourceW(HANDLE hUpdate, BOOL fDiscard); +BOOL WINAPI UpdateResourceW(HANDLE hUpdate, LPCTSTR lpType, LPCTSTR lpName, WORD wLanguage, LPVOID lpData, DWORD cbData); + +""") # noqa + + +def ENUMRESTYPEPROC(callback): + def wrapped(hModule, lpszType, lParam): + return callback(hModule, resource(lpszType), lParam) + return wrapped + + +def ENUMRESNAMEPROC(callback): + def wrapped(hModule, lpszType, lpszName, lParam): + if lpszName == ffi.NULL: + return False + return callback( + hModule, resource(lpszType), resource(lpszName), lParam) + return wrapped + + +def ENUMRESLANGPROC(callback): + def wrapped(hModule, lpszType, lpszName, wIDLanguage, lParam): + return callback( + hModule, resource(lpszType), resource(lpszName), + wIDLanguage, lParam) + return wrapped + + +def _EnumResourceTypes(hModule, lpEnumFunc, lParam): + callback = ffi.callback('ENUMRESTYPEPROC', lpEnumFunc) + check_false( + dlls.kernel32.EnumResourceTypesW(PVOID(hModule), callback, lParam), + function_name='EnumResourceTypes') + + +def _EnumResourceNames(hModule, lpszType, lpEnumFunc, lParam): + callback = ffi.callback('ENUMRESNAMEPROC', lpEnumFunc) + check_false( + dlls.kernel32.EnumResourceNamesW( + PVOID(hModule), RESOURCE(lpszType), callback, lParam), + function_name='EnumResourceNames') + + +def _EnumResourceLanguages(hModule, lpType, lpName, lpEnumFunc, lParam): + callback = ffi.callback('ENUMRESLANGPROC', lpEnumFunc) + check_false( + dlls.kernel32.EnumResourceLanguagesW( + PVOID(hModule), RESOURCE(lpType), + RESOURCE(lpName), callback, lParam), + function_name='EnumResourceLanguages') + + +def _FindResourceEx(hModule, lpType, lpName, wLanguage): + return check_null( + dlls.kernel32.FindResourceExW( + PVOID(hModule), RESOURCE(lpType), RESOURCE(lpName), wLanguage), + function_name='FindResourceEx') + + +def _SizeofResource(hModule, hResInfo): + return check_zero( + dlls.kernel32.SizeofResource(PVOID(hModule), hResInfo), + function_name='SizeofResource') + + +def _LoadResource(hModule, hResInfo): + return check_null( + dlls.kernel32.LoadResource(PVOID(hModule), hResInfo), + function_name='LoadResource') + + +def _LockResource(hResData): + return check_null( + dlls.kernel32.LockResource(hResData), + function_name='LockResource') + + +def _BeginUpdateResource(pFileName, bDeleteExistingResources): + result = check_null( + dlls.kernel32.BeginUpdateResourceW( + str(pFileName), bDeleteExistingResources)) + return HMODULE(result) + + +def _EndUpdateResource(hUpdate, fDiscard): + check_false( + dlls.kernel32.EndUpdateResourceW(PVOID(hUpdate), fDiscard), + function_name='EndUpdateResource') + + +def _UpdateResource(hUpdate, lpType, lpName, wLanguage, cData, cbData): + lpData = ffi.from_buffer(cData) + check_false( + dlls.kernel32.UpdateResourceW( + PVOID(hUpdate), RESOURCE(lpType), RESOURCE(lpName), + wLanguage, PVOID(lpData), cbData), + function_name='UpdateResource') diff --git a/venv/Lib/site-packages/win32ctypes/core/cffi/_system_information.py b/venv/Lib/site-packages/win32ctypes/core/cffi/_system_information.py new file mode 100644 index 0000000..f642da8 --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/core/cffi/_system_information.py @@ -0,0 +1,32 @@ +# +# (C) Copyright 2018 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +from ._util import ffi, dlls + +# TODO: retrieve this value using ffi +MAX_PATH = 260 +MAX_PATH_BUF = u'wchar_t[{0}]'.format(MAX_PATH) + +ffi.cdef(""" + +BOOL WINAPI Beep(DWORD dwFreq, DWORD dwDuration); +UINT WINAPI GetWindowsDirectoryW(LPTSTR lpBuffer, UINT uSize); +UINT WINAPI GetSystemDirectoryW(LPTSTR lpBuffer, UINT uSize); + +""") + + +def _GetWindowsDirectory(): + buffer = ffi.new(MAX_PATH_BUF) + directory = dlls.kernel32.GetWindowsDirectoryW(buffer, MAX_PATH) + return ffi.unpack(buffer, directory) + + +def _GetSystemDirectory(): + buffer = ffi.new(MAX_PATH_BUF) + directory = dlls.kernel32.GetSystemDirectoryW(buffer, MAX_PATH) + return ffi.unpack(buffer, directory) diff --git a/venv/Lib/site-packages/win32ctypes/core/cffi/_time.py b/venv/Lib/site-packages/win32ctypes/core/cffi/_time.py new file mode 100644 index 0000000..ad33846 --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/core/cffi/_time.py @@ -0,0 +1,18 @@ +# +# (C) Copyright 2015-18 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +from ._util import ffi, dlls + +ffi.cdef(""" + +DWORD WINAPI GetTickCount(void); + +""") + + +def _GetTickCount(): + return dlls.kernel32.GetTickCount() diff --git a/venv/Lib/site-packages/win32ctypes/core/cffi/_util.py b/venv/Lib/site-packages/win32ctypes/core/cffi/_util.py new file mode 100644 index 0000000..b4ce1ff --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/core/cffi/_util.py @@ -0,0 +1,105 @@ +# +# (C) Copyright 2015 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +""" Utility functions to help with cffi wrapping. +""" +from win32ctypes.core.compat import is_bytes, is_integer +from cffi import FFI + +ffi = FFI() +ffi.set_unicode(True) + + +def HMODULE(cdata): + return int(ffi.cast("intptr_t", cdata)) + + +def PVOID(x): + return ffi.cast("void *", x) + + +def IS_INTRESOURCE(x): + """ Check if x is an index into the id list. + + """ + return int(ffi.cast("uintptr_t", x)) >> 16 == 0 + + +def RESOURCE(resource): + """ Convert a resource into a compatible input for cffi. + + """ + if is_integer(resource): + resource = ffi.cast('wchar_t *', resource) + elif is_bytes(resource): + resource = str(resource) + return resource + + +def resource(lpRESOURCEID): + """ Convert the windows RESOURCE into a python friendly object. + """ + if IS_INTRESOURCE(lpRESOURCEID): + resource = int(ffi.cast("uintptr_t", lpRESOURCEID)) + else: + resource = ffi.string(lpRESOURCEID) + return resource + + +class ErrorWhen(object): + """ Callable factory for raising errors when calling cffi functions. + + """ + + def __init__(self, check, raise_on_zero=True): + """ Constructor + + Parameters + ---------- + check : + The return value that designates that an error has taken place. + + raise_on_zero : bool + When set any error will be raised. When false the winerror + is checked and only non-zero win errors are raised. Currently + this parameters is used to workaround issues with the win32 + implementation in ``wine``. + + """ + self._check = check + self._raise_on_zero = raise_on_zero + + def __call__(self, value, function_name=''): + if value == self._check: + self._raise_error(function_name) + else: + return value + + def _raise_error(self, function_name=''): + code, message = ffi.getwinerror() + exception = WindowsError() + exception.errno = ffi.errno + exception.winerror = code + exception.strerror = message + exception.function = function_name + raise exception + + +check_null = ErrorWhen(ffi.NULL) +check_zero = ErrorWhen(0) +check_false = ErrorWhen(False) + + +class Libraries(object): + + def __getattr__(self, name): + library = ffi.dlopen('{}.dll'.format(name)) + self.__dict__[name] = library + return library + + +dlls = Libraries() diff --git a/venv/Lib/site-packages/win32ctypes/core/compat.py b/venv/Lib/site-packages/win32ctypes/core/compat.py new file mode 100644 index 0000000..2de6bf2 --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/core/compat.py @@ -0,0 +1,10 @@ +def is_bytes(b): + return isinstance(b, bytes) + + +def is_text(s): + return isinstance(s, str) + + +def is_integer(i): + return isinstance(i, int) diff --git a/venv/Lib/site-packages/win32ctypes/core/ctypes/__init__.py b/venv/Lib/site-packages/win32ctypes/core/ctypes/__init__.py new file mode 100644 index 0000000..628b1eb --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/core/ctypes/__init__.py @@ -0,0 +1,11 @@ +# +# (C) Copyright 2014-2023 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +import logging + +logger = logging.getLogger(__name__) +logger.debug('Loaded ctypes backend') diff --git a/venv/Lib/site-packages/win32ctypes/core/ctypes/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/core/ctypes/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..5c02d8b Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/core/ctypes/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/core/ctypes/__pycache__/_authentication.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/core/ctypes/__pycache__/_authentication.cpython-311.pyc new file mode 100644 index 0000000..30e1f57 Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/core/ctypes/__pycache__/_authentication.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/core/ctypes/__pycache__/_common.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/core/ctypes/__pycache__/_common.cpython-311.pyc new file mode 100644 index 0000000..639de13 Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/core/ctypes/__pycache__/_common.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/core/ctypes/__pycache__/_dll.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/core/ctypes/__pycache__/_dll.cpython-311.pyc new file mode 100644 index 0000000..c8eb068 Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/core/ctypes/__pycache__/_dll.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/core/ctypes/__pycache__/_nl_support.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/core/ctypes/__pycache__/_nl_support.cpython-311.pyc new file mode 100644 index 0000000..2b89183 Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/core/ctypes/__pycache__/_nl_support.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/core/ctypes/__pycache__/_resource.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/core/ctypes/__pycache__/_resource.cpython-311.pyc new file mode 100644 index 0000000..e3f7df7 Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/core/ctypes/__pycache__/_resource.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/core/ctypes/__pycache__/_system_information.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/core/ctypes/__pycache__/_system_information.cpython-311.pyc new file mode 100644 index 0000000..248899a Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/core/ctypes/__pycache__/_system_information.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/core/ctypes/__pycache__/_time.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/core/ctypes/__pycache__/_time.cpython-311.pyc new file mode 100644 index 0000000..805e4bb Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/core/ctypes/__pycache__/_time.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/core/ctypes/__pycache__/_util.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/core/ctypes/__pycache__/_util.cpython-311.pyc new file mode 100644 index 0000000..c972f00 Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/core/ctypes/__pycache__/_util.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/core/ctypes/_authentication.py b/venv/Lib/site-packages/win32ctypes/core/ctypes/_authentication.py new file mode 100644 index 0000000..508f4b1 --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/core/ctypes/_authentication.py @@ -0,0 +1,122 @@ +# +# (C) Copyright 2014-18 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +import ctypes +from ctypes import POINTER, Structure, c_void_p, c_wchar_p, c_char_p, cast +from ctypes.wintypes import ( + BOOL, DWORD, FILETIME, LPCWSTR) + +from win32ctypes.core.compat import is_text +from ._common import LPBYTE, _PyBytes_FromStringAndSize +from ._util import function_factory, check_false_factory, dlls +from ._nl_support import _GetACP + + +SUPPORTED_CREDKEYS = set(( + u'Type', u'TargetName', u'Persist', + u'UserName', u'Comment', u'CredentialBlob')) + + +class CREDENTIAL(Structure): + _fields_ = [ + ("Flags", DWORD), + ("Type", DWORD), + ("TargetName", c_wchar_p), + ("Comment", c_wchar_p), + ("LastWritten", FILETIME), + ("CredentialBlobSize", DWORD), + ("CredentialBlob", LPBYTE), + ("Persist", DWORD), + ("_DO_NOT_USE_AttributeCount", DWORD), + ("__DO_NOT_USE_Attribute", c_void_p), + ("TargetAlias", c_wchar_p), + ("UserName", c_wchar_p)] + + @classmethod + def fromdict(cls, credential, flags=0): + unsupported = set(credential.keys()) - SUPPORTED_CREDKEYS + if len(unsupported): + raise ValueError("Unsupported keys: {0}".format(unsupported)) + if flags != 0: + raise ValueError("flag != 0 not yet supported") + + c_creds = cls() + c_pcreds = PCREDENTIAL(c_creds) + + # zero-out memory + ctypes.memset(c_pcreds, 0, ctypes.sizeof(c_creds)) + + for key in SUPPORTED_CREDKEYS: + if key in credential: + if key != 'CredentialBlob': + setattr(c_creds, key, credential[key]) + else: + blob = make_unicode(credential['CredentialBlob']) + blob_data = ctypes.create_unicode_buffer(blob) + # Create_unicode_buffer adds a NULL at the end of the + # string we do not want that. + c_creds.CredentialBlobSize = \ + ctypes.sizeof(blob_data) - \ + ctypes.sizeof(ctypes.c_wchar) + c_creds.CredentialBlob = ctypes.cast(blob_data, LPBYTE) + return c_creds + + +PCREDENTIAL = POINTER(CREDENTIAL) +PPCREDENTIAL = POINTER(PCREDENTIAL) +PPPCREDENTIAL = POINTER(PPCREDENTIAL) + + +def make_unicode(text): + """ Convert the input string to unicode. + + """ + if is_text(text): + return text + else: + code_page = _GetACP() + return text.decode(encoding=str(code_page), errors='strict') + + +def credential2dict(creds): + credential = {} + for key in SUPPORTED_CREDKEYS: + if key != u'CredentialBlob': + credential[key] = getattr(creds, key) + else: + blob = _PyBytes_FromStringAndSize( + cast(creds.CredentialBlob, c_char_p), + creds.CredentialBlobSize) + credential[u'CredentialBlob'] = blob + return credential + + +_CredWrite = function_factory( + dlls.advapi32.CredWriteW, + [PCREDENTIAL, DWORD], + BOOL, + check_false_factory("CredWrite")) + +_CredRead = function_factory( + dlls.advapi32.CredReadW, + [LPCWSTR, DWORD, DWORD, PPCREDENTIAL], + BOOL, + check_false_factory("CredRead")) + +_CredDelete = function_factory( + dlls.advapi32.CredDeleteW, + [LPCWSTR, DWORD, DWORD], + BOOL, + check_false_factory("CredDelete")) + +_CredEnumerate = function_factory( + dlls.advapi32.CredEnumerateW, + [LPCWSTR, DWORD, POINTER(DWORD), PPPCREDENTIAL], + BOOL, + check_false_factory("CredEnumerate")) + +_CredFree = function_factory(dlls.advapi32.CredFree, [PCREDENTIAL]) diff --git a/venv/Lib/site-packages/win32ctypes/core/ctypes/_common.py b/venv/Lib/site-packages/win32ctypes/core/ctypes/_common.py new file mode 100644 index 0000000..2067bb7 --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/core/ctypes/_common.py @@ -0,0 +1,53 @@ +# +# (C) Copyright 2014 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +import ctypes +import sys +from ctypes import ( + pythonapi, POINTER, c_void_p, py_object, c_char_p, c_int, c_long, c_int64, + c_longlong) +from ctypes import cast # noqa imported here for convenience +from ctypes.wintypes import BYTE + +from ._util import function_factory + +PPy_UNICODE = c_void_p +LPBYTE = POINTER(BYTE) +is_64bits = sys.maxsize > 2**32 +Py_ssize_t = c_int64 if is_64bits else c_int + +if ctypes.sizeof(c_long) == ctypes.sizeof(c_void_p): + LONG_PTR = c_long +elif ctypes.sizeof(c_longlong) == ctypes.sizeof(c_void_p): + LONG_PTR = c_longlong + +_PyBytes_FromStringAndSize = function_factory( + pythonapi.PyBytes_FromStringAndSize, + [c_char_p, Py_ssize_t], + return_type=py_object) + + +def IS_INTRESOURCE(x): + return x >> 16 == 0 + + +byreference = ctypes.byref + + +def dereference(x): + return x.contents + + +class Libraries(object): + + def __getattr__(self, name): + library = ctypes.WinDLL(name) + self.__dict__[name] = library + return library + + +dlls = Libraries() diff --git a/venv/Lib/site-packages/win32ctypes/core/ctypes/_dll.py b/venv/Lib/site-packages/win32ctypes/core/ctypes/_dll.py new file mode 100644 index 0000000..e44c663 --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/core/ctypes/_dll.py @@ -0,0 +1,21 @@ +# +# (C) Copyright 2018 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +from ctypes.wintypes import BOOL, DWORD, HANDLE, HMODULE, LPCWSTR + +from ._util import check_null, check_false, function_factory, dlls + +_LoadLibraryEx = function_factory( + dlls.kernel32.LoadLibraryExW, + [LPCWSTR, HANDLE, DWORD], + HMODULE, check_null) + +_FreeLibrary = function_factory( + dlls.kernel32.FreeLibrary, + [HMODULE], + BOOL, + check_false) diff --git a/venv/Lib/site-packages/win32ctypes/core/ctypes/_nl_support.py b/venv/Lib/site-packages/win32ctypes/core/ctypes/_nl_support.py new file mode 100644 index 0000000..9a3a07d --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/core/ctypes/_nl_support.py @@ -0,0 +1,12 @@ +# +# (C) Copyright 2018 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +from ctypes.wintypes import UINT + +from ._util import function_factory, dlls + +_GetACP = function_factory(dlls.kernel32.GetACP, None, UINT) diff --git a/venv/Lib/site-packages/win32ctypes/core/ctypes/_resource.py b/venv/Lib/site-packages/win32ctypes/core/ctypes/_resource.py new file mode 100644 index 0000000..23adb1f --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/core/ctypes/_resource.py @@ -0,0 +1,148 @@ +# +# (C) Copyright 2018 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +import ctypes +from ctypes.wintypes import ( + BOOL, DWORD, HANDLE, HMODULE, LPCWSTR, WORD, HRSRC, + HGLOBAL, LPVOID) + +from ._common import LONG_PTR, IS_INTRESOURCE +from ._util import check_null, check_zero, check_false, function_factory, dlls + +_ENUMRESTYPEPROC = ctypes.WINFUNCTYPE(BOOL, HMODULE, LPVOID, LONG_PTR) +_ENUMRESNAMEPROC = ctypes.WINFUNCTYPE(BOOL, HMODULE, LPVOID, LPVOID, LONG_PTR) +_ENUMRESLANGPROC = ctypes.WINFUNCTYPE( + BOOL, HMODULE, LPVOID, LPVOID, WORD, LONG_PTR) + + +def ENUMRESTYPEPROC(callback): + def wrapped(handle, type_, param): + if IS_INTRESOURCE(type_): + type_ = int(type_) + else: + type_ = ctypes.cast(type_, LPCWSTR).value + return callback(handle, type_, param) + + return _ENUMRESTYPEPROC(wrapped) + + +def ENUMRESNAMEPROC(callback): + def wrapped(handle, type_, name, param): + if IS_INTRESOURCE(type_): + type_ = int(type_) + else: + type_ = ctypes.cast(type_, LPCWSTR).value + if name is None: + return False + elif IS_INTRESOURCE(name): + name = int(name) + else: + name = ctypes.cast(name, LPCWSTR).value + return callback(handle, type_, name, param) + + return _ENUMRESNAMEPROC(wrapped) + + +def ENUMRESLANGPROC(callback): + def wrapped(handle, type_, name, language, param): + if IS_INTRESOURCE(type_): + type_ = int(type_) + else: + type_ = ctypes.cast(type_, LPCWSTR).value + if IS_INTRESOURCE(name): + name = int(name) + else: + name = ctypes.cast(name, LPCWSTR).value + return callback(handle, type_, name, language, param) + + return _ENUMRESLANGPROC(wrapped) + + +def _UpdateResource(hUpdate, lpType, lpName, wLanguage, lpData, cbData): + lp_type = LPCWSTR(lpType) + lp_name = LPCWSTR(lpName) + _BaseUpdateResource(hUpdate, lp_type, lp_name, wLanguage, lpData, cbData) + + +def _EnumResourceNames(hModule, lpszType, lpEnumFunc, lParam): + resource_type = LPCWSTR(lpszType) + _BaseEnumResourceNames(hModule, resource_type, lpEnumFunc, lParam) + + +def _EnumResourceLanguages(hModule, lpType, lpName, lpEnumFunc, lParam): + resource_type = LPCWSTR(lpType) + resource_name = LPCWSTR(lpName) + _BaseEnumResourceLanguages( + hModule, resource_type, resource_name, lpEnumFunc, lParam) + + +def _FindResourceEx(hModule, lpType, lpName, wLanguage): + resource_type = LPCWSTR(lpType) + resource_name = LPCWSTR(lpName) + return _BaseFindResourceEx( + hModule, resource_type, resource_name, wLanguage) + + +_EnumResourceTypes = function_factory( + dlls.kernel32.EnumResourceTypesW, + [HMODULE, _ENUMRESTYPEPROC, LONG_PTR], + BOOL, + check_false) + +_LoadResource = function_factory( + dlls.kernel32.LoadResource, + [HMODULE, HRSRC], + HGLOBAL, + check_null) + +_LockResource = function_factory( + dlls.kernel32.LockResource, + [HGLOBAL], + LPVOID, + check_null) + +_SizeofResource = function_factory( + dlls.kernel32.SizeofResource, + [HMODULE, HRSRC], + DWORD, + check_zero) + +_BeginUpdateResource = function_factory( + dlls.kernel32.BeginUpdateResourceW, + [LPCWSTR, BOOL], + HANDLE, + check_null) + +_EndUpdateResource = function_factory( + dlls.kernel32.EndUpdateResourceW, + [HANDLE, BOOL], + BOOL, + check_false) + +_BaseEnumResourceNames = function_factory( + dlls.kernel32.EnumResourceNamesW, + [HMODULE, LPCWSTR, _ENUMRESNAMEPROC, LONG_PTR], + BOOL, + check_false) + +_BaseEnumResourceLanguages = function_factory( + dlls.kernel32.EnumResourceLanguagesW, + [HMODULE, LPCWSTR, LPCWSTR, _ENUMRESLANGPROC, LONG_PTR], + BOOL, + check_false) + +_BaseFindResourceEx = function_factory( + dlls.kernel32.FindResourceExW, + [HMODULE, LPCWSTR, LPCWSTR, WORD], + HRSRC, + check_null) + +_BaseUpdateResource = function_factory( + dlls.kernel32.UpdateResourceW, + [HANDLE, LPCWSTR, LPCWSTR, WORD, LPVOID, DWORD], + BOOL, + check_false) diff --git a/venv/Lib/site-packages/win32ctypes/core/ctypes/_system_information.py b/venv/Lib/site-packages/win32ctypes/core/ctypes/_system_information.py new file mode 100644 index 0000000..1a38757 --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/core/ctypes/_system_information.py @@ -0,0 +1,36 @@ +# +# (C) Copyright 2018 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +import ctypes +from ctypes.wintypes import LPCWSTR, UINT, LPWSTR, MAX_PATH + +from ._util import check_zero, function_factory, dlls + + +def _GetWindowsDirectory(): + buffer = ctypes.create_unicode_buffer(MAX_PATH) + _BaseGetWindowsDirectory(buffer, MAX_PATH) + return ctypes.cast(buffer, LPCWSTR).value + + +def _GetSystemDirectory(): + buffer = ctypes.create_unicode_buffer(MAX_PATH) + _BaseGetSystemDirectory(buffer, MAX_PATH) + return ctypes.cast(buffer, LPCWSTR).value + + +_BaseGetWindowsDirectory = function_factory( + dlls.kernel32.GetWindowsDirectoryW, + [LPWSTR, UINT], + UINT, + check_zero) + +_BaseGetSystemDirectory = function_factory( + dlls.kernel32.GetSystemDirectoryW, + [LPWSTR, UINT], + UINT, + check_zero) diff --git a/venv/Lib/site-packages/win32ctypes/core/ctypes/_time.py b/venv/Lib/site-packages/win32ctypes/core/ctypes/_time.py new file mode 100644 index 0000000..da8a936 --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/core/ctypes/_time.py @@ -0,0 +1,15 @@ +# +# (C) Copyright 2018 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +from ctypes.wintypes import DWORD + +from ._util import function_factory, dlls + + +_GetTickCount = function_factory( + dlls.kernel32.GetTickCount, + None, DWORD) diff --git a/venv/Lib/site-packages/win32ctypes/core/ctypes/_util.py b/venv/Lib/site-packages/win32ctypes/core/ctypes/_util.py new file mode 100644 index 0000000..27b5fc4 --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/core/ctypes/_util.py @@ -0,0 +1,78 @@ +# +# (C) Copyright 2014 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +""" Utility functions to help with ctypes wrapping. +""" +from ctypes import get_last_error, FormatError, WinDLL + + +def function_factory( + function, argument_types=None, + return_type=None, error_checking=None): + if argument_types is not None: + function.argtypes = argument_types + function.restype = return_type + if error_checking is not None: + function.errcheck = error_checking + return function + + +def make_error(function, function_name=None): + code = get_last_error() + description = FormatError(code).strip() + if function_name is None: + function_name = function.__name__ + exception = WindowsError() + exception.winerror = code + exception.function = function_name + exception.strerror = description + return exception + + +def check_null_factory(function_name=None): + def check_null(result, function, arguments, *args): + if result is None: + raise make_error(function, function_name) + return result + return check_null + + +check_null = check_null_factory() + + +def check_zero_factory(function_name=None): + def check_zero(result, function, arguments, *args): + if result == 0: + raise make_error(function, function_name) + return result + return check_zero + + +check_zero = check_zero_factory() + + +def check_false_factory(function_name=None): + def check_false(result, function, arguments, *args): + if not bool(result): + raise make_error(function, function_name) + else: + return True + return check_false + + +check_false = check_false_factory() + + +class Libraries(object): + + def __getattr__(self, name): + library = WinDLL(name, use_last_error=True) + self.__dict__[name] = library + return library + + +dlls = Libraries() diff --git a/venv/Lib/site-packages/win32ctypes/pywin32/__init__.py b/venv/Lib/site-packages/win32ctypes/pywin32/__init__.py new file mode 100644 index 0000000..3fc135b --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/pywin32/__init__.py @@ -0,0 +1,12 @@ +# +# (C) Copyright 2014 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +from win32ctypes.pywin32 import pywintypes +from win32ctypes.pywin32 import win32api +from win32ctypes.pywin32 import win32cred + +__all__ = ['win32api', 'win32cred', 'pywintypes'] diff --git a/venv/Lib/site-packages/win32ctypes/pywin32/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/pywin32/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..1784240 Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/pywin32/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/pywin32/__pycache__/pywintypes.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/pywin32/__pycache__/pywintypes.cpython-311.pyc new file mode 100644 index 0000000..08c7bf3 Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/pywin32/__pycache__/pywintypes.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/pywin32/__pycache__/win32api.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/pywin32/__pycache__/win32api.cpython-311.pyc new file mode 100644 index 0000000..732daae Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/pywin32/__pycache__/win32api.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/pywin32/__pycache__/win32cred.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/pywin32/__pycache__/win32cred.cpython-311.pyc new file mode 100644 index 0000000..3b88a93 Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/pywin32/__pycache__/win32cred.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/pywin32/pywintypes.py b/venv/Lib/site-packages/win32ctypes/pywin32/pywintypes.py new file mode 100644 index 0000000..80d071c --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/pywin32/pywintypes.py @@ -0,0 +1,67 @@ +# +# (C) Copyright 2014 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +""" A module which supports common Windows types. """ +import contextlib +import collections +import time +from datetime import datetime as _datetime + + +class error(Exception): + def __init__(self, *args, **kw): + nargs = len(args) + if nargs > 0: + self.winerror = args[0] + else: + self.winerror = None + if nargs > 1: + self.funcname = args[1] + else: + self.funcname = None + if nargs > 2: + self.strerror = args[2] + else: + self.strerror = None + Exception.__init__(self, *args, **kw) + + +@contextlib.contextmanager +def pywin32error(): + try: + yield + except WindowsError as exception: + if not hasattr(exception, 'function'): + exception.function = 'unknown' + raise error(exception.winerror, exception.function, exception.strerror) + + +class datetime(_datetime): + + def Format(self, fmt='%c'): + return self.strftime(fmt) + + +def Time(value): + if isinstance(value, datetime): + return value + elif hasattr(value, 'timetuple'): + timetuple = value.timetuple() + return datetime.fromtimestamp(time.mktime(timetuple)) + elif isinstance(value, collections.abc.Sequence): + time_value = time.mktime(value[:9]) + if len(value) == 10: + time_value += value[9] / 1000.0 + return datetime.fromtimestamp(time_value) + else: + try: + return datetime.fromtimestamp(value) + except OSError as error: + if error.errno == 22: + raise ValueError(error.strerror) + else: + raise diff --git a/venv/Lib/site-packages/win32ctypes/pywin32/win32api.py b/venv/Lib/site-packages/win32ctypes/pywin32/win32api.py new file mode 100644 index 0000000..18e1934 --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/pywin32/win32api.py @@ -0,0 +1,294 @@ +# +# (C) Copyright 2014 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +""" A module, encapsulating the Windows Win32 API. """ +from win32ctypes.core import ( + _common, _dll, _resource, _system_information, _backend, _time) +from win32ctypes.pywin32.pywintypes import pywin32error as _pywin32error + +LOAD_LIBRARY_AS_DATAFILE = 0x2 +LANG_NEUTRAL = 0x00 + + +def LoadLibraryEx(fileName, handle, flags): + """ Loads the specified DLL, and returns the handle. + + Parameters + ---------- + fileName : unicode + The filename of the module to load. + + handle : int + Reserved, always zero. + + flags : int + The action to be taken when loading the module. + + Returns + ------- + handle : hModule + The handle of the loaded module + + """ + if not handle == 0: + raise ValueError("handle != 0 not supported") + with _pywin32error(): + return _dll._LoadLibraryEx(fileName, 0, flags) + + +def EnumResourceTypes(hModule): + """ Enumerates resource types within a module. + + Parameters + ---------- + hModule : handle + The handle to the module. + + Returns + ------- + resource_types : list + The list of resource types in the module. + + """ + resource_types = [] + + def callback(hModule, type_, param): + resource_types.append(type_) + return True + + with _pywin32error(): + _resource._EnumResourceTypes( + hModule, _resource.ENUMRESTYPEPROC(callback), 0) + return resource_types + + +def EnumResourceNames(hModule, resType): + """ Enumerates all the resources of the specified type within a module. + + Parameters + ---------- + hModule : handle + The handle to the module. + resType : str : int + The type or id of resource to enumerate. + + Returns + ------- + resource_names : list + The list of resource names (unicode strings) of the specific + resource type in the module. + + """ + resource_names = [] + + def callback(hModule, type_, type_name, param): + resource_names.append(type_name) + return True + + with _pywin32error(): + _resource._EnumResourceNames( + hModule, resType, _resource.ENUMRESNAMEPROC(callback), 0) + return resource_names + + +def EnumResourceLanguages(hModule, lpType, lpName): + """ List languages of a resource module. + + Parameters + ---------- + hModule : handle + Handle to the resource module. + + lpType : str : int + The type or id of resource to enumerate. + + lpName : str : int + The type or id of resource to enumerate. + + Returns + ------- + resource_languages : list + List of the resource language ids. + + """ + resource_languages = [] + + def callback(hModule, type_name, res_name, language_id, param): + resource_languages.append(language_id) + return True + + with _pywin32error(): + _resource._EnumResourceLanguages( + hModule, lpType, lpName, _resource.ENUMRESLANGPROC(callback), 0) + return resource_languages + + +def LoadResource(hModule, type, name, language=LANG_NEUTRAL): + """ Find and Load a resource component. + + Parameters + ---------- + handle : hModule + The handle of the module containing the resource. + Use None for current process executable. + + type : str : int + The type of resource to load. + + name : str : int + The name or Id of the resource to load. + + language : int + Language to use, default is LANG_NEUTRAL. + + Returns + ------- + resource : bytes + The byte string blob of the resource + + """ + with _pywin32error(): + hrsrc = _resource._FindResourceEx(hModule, type, name, language) + size = _resource._SizeofResource(hModule, hrsrc) + hglob = _resource._LoadResource(hModule, hrsrc) + if _backend == 'ctypes': + pointer = _common.cast( + _resource._LockResource(hglob), _common.c_char_p) + else: + pointer = _resource._LockResource(hglob) + return _common._PyBytes_FromStringAndSize(pointer, size) + + +def FreeLibrary(hModule): + """ Free the loaded dynamic-link library (DLL) module. + + If necessary, decrements its reference count. + + Parameters + ---------- + handle : hModule + The handle to the library as returned by the LoadLibrary function. + + """ + with _pywin32error(): + return _dll._FreeLibrary(hModule) + + +def GetTickCount(): + """ The number of milliseconds that have elapsed since startup + + Returns + ------- + counts : int + The millisecond counts since system startup. + """ + return _time._GetTickCount() + + +def BeginUpdateResource(filename, delete): + """ Get a handle that can be used by the :func:`UpdateResource`. + + Parameters + ---------- + fileName : unicode + The filename of the module to load. + delete : bool + When true all existing resources are deleted + + Returns + ------- + result : hModule + Handle of the resource. + + """ + with _pywin32error(): + return _resource._BeginUpdateResource(filename, delete) + + +def EndUpdateResource(handle, discard): + """ End the update resource of the handle. + + Parameters + ---------- + handle : hModule + The handle of the resource as it is returned + by :func:`BeginUpdateResource` + + discard : bool + When True all writes are discarded. + + """ + with _pywin32error(): + _resource._EndUpdateResource(handle, discard) + + +def UpdateResource(handle, type, name, data, language=LANG_NEUTRAL): + """ Update a resource. + + Parameters + ---------- + handle : hModule + The handle of the resource file as returned by + :func:`BeginUpdateResource`. + + type : str : int + The type of resource to update. + + name : str : int + The name or Id of the resource to update. + + data : bytes + A bytes like object is expected. + + .. note:: + PyWin32 version 219, on Python 2.7, can handle unicode inputs. + However, the data are stored as bytes and it is not really + possible to convert the information back into the original + unicode string. To be consistent with the Python 3 behaviour + of PyWin32, we raise an error if the input cannot be + converted to `bytes`. + + language : int + Language to use, default is LANG_NEUTRAL. + + """ + with _pywin32error(): + try: + lp_data = bytes(data) + except UnicodeEncodeError: + raise TypeError( + "a bytes-like object is required, not a 'unicode'") + _resource._UpdateResource( + handle, type, name, language, lp_data, len(lp_data)) + + +def GetWindowsDirectory(): + """ Get the ``Windows`` directory. + + Returns + ------- + result : str + The path to the ``Windows`` directory. + + """ + with _pywin32error(): + # Note: pywin32 returns str on py27, unicode (which is str) on py3 + return str(_system_information._GetWindowsDirectory()) + + +def GetSystemDirectory(): + """ Get the ``System`` directory. + + Returns + ------- + result : str + The path to the ``System`` directory. + + """ + with _pywin32error(): + # Note: pywin32 returns str on py27, unicode (which is str) on py3 + return str(_system_information._GetSystemDirectory()) diff --git a/venv/Lib/site-packages/win32ctypes/pywin32/win32cred.py b/venv/Lib/site-packages/win32ctypes/pywin32/win32cred.py new file mode 100644 index 0000000..0f37f1d --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/pywin32/win32cred.py @@ -0,0 +1,145 @@ +# +# (C) Copyright 2014 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +""" Interface to credentials management functions. """ +from win32ctypes.core import _authentication, _common, _backend +from win32ctypes.pywin32.pywintypes import pywin32error as _pywin32error + +CRED_TYPE_GENERIC = 0x1 +CRED_PERSIST_SESSION = 0x1 +CRED_PERSIST_LOCAL_MACHINE = 0x2 +CRED_PERSIST_ENTERPRISE = 0x3 +CRED_PRESERVE_CREDENTIAL_BLOB = 0 +CRED_ENUMERATE_ALL_CREDENTIALS = 0x1 + + +def CredWrite(Credential, Flags=CRED_PRESERVE_CREDENTIAL_BLOB): + """ Creates or updates a stored credential. + + Parameters + ---------- + Credential : dict + A dictionary corresponding to the PyWin32 ``PyCREDENTIAL`` + structure. + Flags : int + Always pass ``CRED_PRESERVE_CREDENTIAL_BLOB`` (i.e. 0). + + """ + c_creds = _authentication.CREDENTIAL.fromdict(Credential, Flags) + c_pcreds = _authentication.PCREDENTIAL(c_creds) + with _pywin32error(): + _authentication._CredWrite(c_pcreds, 0) + + +def CredRead(TargetName, Type, Flags=0): + """ Retrieves a stored credential. + + Parameters + ---------- + TargetName : unicode + The target name to fetch from the keyring. + Type : int + One of the CRED_TYPE_* constants. + Flags : int + Reserved, always use 0. + + Returns + ------- + credentials : dict + ``None`` if the target name was not found or A dictionary + corresponding to the PyWin32 ``PyCREDENTIAL`` structure. + + """ + if Type != CRED_TYPE_GENERIC: + raise ValueError("Type != CRED_TYPE_GENERIC not yet supported") + + flag = 0 + with _pywin32error(): + if _backend == 'cffi': + ppcreds = _authentication.PPCREDENTIAL() + _authentication._CredRead(TargetName, Type, flag, ppcreds) + pcreds = _common.dereference(ppcreds) + else: + pcreds = _authentication.PCREDENTIAL() + _authentication._CredRead( + TargetName, Type, flag, _common.byreference(pcreds)) + try: + return _authentication.credential2dict(_common.dereference(pcreds)) + finally: + _authentication._CredFree(pcreds) + + +def CredDelete(TargetName, Type, Flags=0): + """ Remove the given target name from the stored credentials. + + Parameters + ---------- + TargetName : unicode + The target name to fetch from the keyring. + Type : int + One of the CRED_TYPE_* constants. + Flags : int + Reserved, always use 0. + + """ + if not Type == CRED_TYPE_GENERIC: + raise ValueError("Type != CRED_TYPE_GENERIC not yet supported.") + with _pywin32error(): + _authentication._CredDelete(TargetName, Type, 0) + + +def CredEnumerate(Filter=None, Flags=0): + """ Remove the given target name from the stored credentials. + + Parameters + ---------- + Filter : unicode + Matches credentials' target names by prefix, can be None. + Flags : int + When set to CRED_ENUMERATE_ALL_CREDENTIALS enumerates all of + the credentials in the user's credential set but in that + case the Filter parameter should be NULL, an error is + raised otherwise + + Returns + ------- + credentials : list + Returns a sequence of CREDENTIAL dictionaries. + + """ + with _pywin32error(): + if _backend == 'cffi': + pcount = _common.PDWORD() + pppcredential = _authentication.PPPCREDENTIAL() + _authentication._CredEnumerate( + Filter, Flags, pcount, pppcredential) + count = pcount[0] + data = _common.dereference( + _common.ffi.cast(f"PCREDENTIAL*[{count}]", pppcredential)) + memory = _common.dereference(pppcredential) + else: + import ctypes + count = _authentication.DWORD() + pcredential = _authentication.PCREDENTIAL() + ppcredential = ctypes.pointer(pcredential) + pppcredential = ctypes.pointer(ppcredential) + _authentication._CredEnumerate( + Filter, Flags, _common.byreference(count), pppcredential) + count = count.value + data = _common.dereference( + _common.cast( + ppcredential, + _common.POINTER(_authentication.PCREDENTIAL*count))) + memory = pcredential + try: + result = [] + for i in range(count): + credential = _common.dereference(data[i]) + result.append(_authentication.credential2dict(credential)) + return result + finally: + _authentication._CredFree(memory) diff --git a/venv/Lib/site-packages/win32ctypes/pywintypes.py b/venv/Lib/site-packages/win32ctypes/pywintypes.py new file mode 100644 index 0000000..6209e1f --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/pywintypes.py @@ -0,0 +1,13 @@ +# +# (C) Copyright 2017 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +import warnings +from win32ctypes.pywin32.pywintypes import * # noqa + +warnings.warn( + "Please use 'from win32ctypes.pywin32 import pywintypes'", + DeprecationWarning) diff --git a/venv/Lib/site-packages/win32ctypes/tests/__init__.py b/venv/Lib/site-packages/win32ctypes/tests/__init__.py new file mode 100644 index 0000000..44e7289 --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/tests/__init__.py @@ -0,0 +1,21 @@ +# +# (C) Copyright 2014 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +import os + +if 'SHOW_TEST_ENV' in os.environ: + import sys + from win32ctypes.core import _backend + is_64bits = sys.maxsize > 2**32 + print('=' * 30, file=sys.stderr) + print( + 'Running on python: {} {}'.format( + sys.version, '64bit' if is_64bits else '32bit'), + file=sys.stderr) + print('The executable is: {}'.format(sys.executable), file=sys.stderr) + print('Using the {} backend'.format(_backend), file=sys.stderr) + print('=' * 30, file=sys.stderr, flush=True) diff --git a/venv/Lib/site-packages/win32ctypes/tests/__pycache__/__init__.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/tests/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..1f65c4c Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/tests/__pycache__/__init__.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/tests/__pycache__/test_backends.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/tests/__pycache__/test_backends.cpython-311.pyc new file mode 100644 index 0000000..d009133 Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/tests/__pycache__/test_backends.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/tests/__pycache__/test_win32api.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/tests/__pycache__/test_win32api.cpython-311.pyc new file mode 100644 index 0000000..24d0f3e Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/tests/__pycache__/test_win32api.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/tests/__pycache__/test_win32cred.cpython-311.pyc b/venv/Lib/site-packages/win32ctypes/tests/__pycache__/test_win32cred.cpython-311.pyc new file mode 100644 index 0000000..6e3fc6a Binary files /dev/null and b/venv/Lib/site-packages/win32ctypes/tests/__pycache__/test_win32cred.cpython-311.pyc differ diff --git a/venv/Lib/site-packages/win32ctypes/tests/test_backends.py b/venv/Lib/site-packages/win32ctypes/tests/test_backends.py new file mode 100644 index 0000000..97a7de8 --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/tests/test_backends.py @@ -0,0 +1,36 @@ +# +# (C) Copyright 2023 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +import importlib +import unittest + +from win32ctypes.core import _backend + +_modules = [ + '_dll', '_authentication', '_time', '_common', + '_resource', '_nl_support', '_system_information'] + + +class TestBackends(unittest.TestCase): + + @unittest.skipIf(_backend != 'cffi', 'cffi backend not enabled') + def test_backend_cffi_load(self): + # when/then + for name in _modules: + module = importlib.import_module(f'win32ctypes.core.{name}') + self.assertEqual( + module.__spec__.name, f'win32ctypes.core.{name}') + self.assertTrue(module.__file__.endswith(f'cffi\\{name}.py')) + + @unittest.skipIf(_backend != 'ctypes', 'ctypes backend not enabled') + def test_backend_ctypes_load(self): + # when/then + for name in _modules: + module = importlib.import_module(f'win32ctypes.core.{name}') + self.assertEqual( + module.__spec__.name, f'win32ctypes.core.{name}') + self.assertTrue(module.__file__.endswith(f'ctypes\\{name}.py')) diff --git a/venv/Lib/site-packages/win32ctypes/tests/test_win32api.py b/venv/Lib/site-packages/win32ctypes/tests/test_win32api.py new file mode 100644 index 0000000..e84dff9 --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/tests/test_win32api.py @@ -0,0 +1,304 @@ +# +# (C) Copyright 2014 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +import os +import sys +import unittest +import contextlib +import tempfile +import shutil +import faulthandler + +import win32api + + +from win32ctypes import pywin32 +from win32ctypes.pywin32.pywintypes import error + + +skip_on_wine = 'SKIP_WINE_KNOWN_FAILURES' in os.environ + + +class TestWin32API(unittest.TestCase): + + # the pywin32ctypes implementation + module = pywin32.win32api + + def setUp(self): + self.tempdir = tempfile.mkdtemp() + shutil.copy(sys.executable, self.tempdir) + + def tearDown(self): + shutil.rmtree(self.tempdir) + + @contextlib.contextmanager + def load_library(self, module, library=sys.executable, flags=0x2): + handle = module.LoadLibraryEx(library, 0, flags) + try: + yield handle + finally: + module.FreeLibrary(handle) + + @contextlib.contextmanager + def resource_update(self, module, library=sys.executable): + handle = module.BeginUpdateResource(library, False) + try: + yield handle + finally: + module.EndUpdateResource(handle, False) + + @contextlib.contextmanager + def nofaulthandler(self): + """ Disable the faulthander + + Use this function to avoid poluting the output with errors + When it is known that an access violation is expected. + + """ + enabled = faulthandler.is_enabled() + faulthandler.disable() + try: + yield + finally: + if enabled: + faulthandler.enable() + + def test_load_library_ex(self): + with self.load_library(win32api) as expected: + with self.load_library(self.module) as handle: + self.assertEqual(handle, expected) + + with self.assertRaises(error): + self.module.LoadLibraryEx(u'ttt.dll', 0, 0x2) + + def test_free_library(self): + with self.load_library(win32api) as handle: + self.assertTrue(win32api.FreeLibrary(handle) is None) + self.assertNotEqual(self.module.FreeLibrary(handle), 0) + + with self.assertRaises(error): + with self.nofaulthandler(): + self.module.FreeLibrary(-3) + + def test_enum_resource_types(self): + with self.load_library(win32api, u'shell32.dll') as handle: + expected = win32api.EnumResourceTypes(handle) + + with self.load_library(pywin32.win32api, u'shell32.dll') as handle: + resource_types = self.module.EnumResourceTypes(handle) + + self.assertEqual(resource_types, expected) + + with self.assertRaises(error): + with self.nofaulthandler(): + self.module.EnumResourceTypes(-3) + + def test_enum_resource_names(self): + with self.load_library(win32api, u'shell32.dll') as handle: + resource_types = win32api.EnumResourceTypes(handle) + for resource_type in resource_types: + expected = win32api.EnumResourceNames(handle, resource_type) + resource_names = self.module.EnumResourceNames( + handle, resource_type) + self.assertEqual(resource_names, expected) + # check that the # format works + resource_names = self.module.EnumResourceNames( + handle, self._id2str(resource_type)) + self.assertEqual(resource_names, expected) + + with self.assertRaises(error): + self.module.EnumResourceNames(2, 3) + + def test_enum_resource_languages(self): + with self.load_library(win32api, u'shell32.dll') as handle: + resource_types = win32api.EnumResourceTypes(handle) + for resource_type in resource_types: + resource_names = win32api.EnumResourceNames( + handle, resource_type) + for resource_name in resource_names: + expected = win32api.EnumResourceLanguages( + handle, resource_type, resource_name) + resource_languages = self.module.EnumResourceLanguages( + handle, resource_type, resource_name) + self.assertEqual(resource_languages, expected) + # check that the # format works + resource_languages = self.module.EnumResourceLanguages( + handle, self._id2str(resource_type), + self._id2str(resource_name)) + self.assertEqual(resource_languages, expected) + + with self.assertRaises(error): + self.module.EnumResourceLanguages(handle, resource_type, 2235) + + def test_load_resource(self): + with self.load_library(win32api, u'explorer.exe') as handle: + resource_types = win32api.EnumResourceTypes(handle) + for resource_type in resource_types: + resource_names = win32api.EnumResourceNames( + handle, resource_type) + for resource_name in resource_names: + resource_languages = win32api.EnumResourceLanguages( + handle, resource_type, resource_name) + for resource_language in resource_languages: + expected = win32api.LoadResource( + handle, resource_type, resource_name, + resource_language) + resource = self.module.LoadResource( + handle, resource_type, resource_name, + resource_language) + # check that the # format works + resource = self.module.LoadResource( + handle, self._id2str(resource_type), + self._id2str(resource_name), + resource_language) + self.assertEqual(resource, expected) + + with self.assertRaises(error): + with self.nofaulthandler(): + self.module.LoadResource( + handle, resource_type, resource_name, 12435) + + def test_get_tick_count(self): + self.assertGreater(self.module.GetTickCount(), 0.0) + + def test_begin_and_end_update_resource(self): + # given + module = self.module + filename = os.path.join(self.tempdir, 'python.exe') + with self.load_library(module, filename) as handle: + count = len(module.EnumResourceTypes(handle)) + + # when + handle = module.BeginUpdateResource(filename, False) + module.EndUpdateResource(handle, False) + + # then + with self.load_library(module, filename) as handle: + self.assertEqual(len(module.EnumResourceTypes(handle)), count) + + # when + handle = module.BeginUpdateResource(filename, True) + module.EndUpdateResource(handle, True) + + # then + with self.load_library(module, filename) as handle: + self.assertEqual(len(module.EnumResourceTypes(handle)), count) + + def test_begin_removing_all_resources(self): + if skip_on_wine: + self.skipTest('EnumResourceTypes known failure on wine, see #59') + + # given + module = self.module + filename = os.path.join(self.tempdir, 'python.exe') + + # when + handle = module.BeginUpdateResource(filename, True) + module.EndUpdateResource(handle, False) + + # then + with self.load_library(module, filename) as handle: + self.assertEqual(len(module.EnumResourceTypes(handle)), 0) + + def test_begin_update_resource_with_invalid(self): + if skip_on_wine: + self.skipTest('BeginUpdateResource known failure on wine, see #59') + + # when/then + with self.assertRaises(error) as context: + self.module.BeginUpdateResource('invalid', False) + # the errno cannot be 0 (i.e. success) + self.assertNotEqual(context.exception.winerror, 0) + + def test_end_update_resource_with_invalid(self): + if skip_on_wine: + self.skipTest('EndUpdateResource known failure on wine, see #59') + + # when/then + with self.assertRaises(error) as context: + self.module.EndUpdateResource(-3, False) + # the errno cannot be 0 (i.e. success) + self.assertNotEqual(context.exception.winerror, 0) + + def test_update_resource(self): + # given + module = self.module + filename = os.path.join(self.tempdir, 'python.exe') + with self.load_library(self.module, filename) as handle: + resource_type = module.EnumResourceTypes(handle)[-1] + resource_name = module.EnumResourceNames(handle, resource_type)[-1] + resource_language = module.EnumResourceLanguages( + handle, resource_type, resource_name)[-1] + resource = module.LoadResource( + handle, resource_type, resource_name, resource_language) + + # when + with self.resource_update(self.module, filename) as handle: + module.UpdateResource( + handle, resource_type, resource_name, resource[:-2], + resource_language) + + # then + with self.load_library(self.module, filename) as handle: + updated = module.LoadResource( + handle, resource_type, resource_name, resource_language) + self.assertEqual(len(updated), len(resource) - 2) + self.assertEqual(updated, resource[:-2]) + + def test_update_resource_with_unicode(self): + # given + module = self.module + filename = os.path.join(self.tempdir, 'python.exe') + with self.load_library(module, filename) as handle: + resource_type = module.EnumResourceTypes(handle)[-1] + resource_name = module.EnumResourceNames(handle, resource_type)[-1] + resource_language = module.EnumResourceLanguages( + handle, resource_type, resource_name)[-1] + resource = u"\N{GREEK CAPITAL LETTER DELTA}" + + # when + with self.resource_update(module, filename) as handle: + with self.assertRaises(TypeError): + module.UpdateResource( + handle, resource_type, resource_name, resource, + resource_language) + + def test_get_windows_directory(self): + # given + expected = win32api.GetWindowsDirectory() + + # when + result = self.module.GetWindowsDirectory() + + # then + # note: pywin32 returns str on py27, unicode (which is str) on py3 + self.assertIsInstance(result, str) + self.assertEqual(result.lower(), r"c:\windows") + self.assertEqual(result, expected) + + def test_get_system_directory(self): + # given + expected = win32api.GetSystemDirectory() + + # when + result = self.module.GetSystemDirectory() + + # then + # note: pywin32 returns str on py27, unicode (which is str) on py3 + self.assertIsInstance(result, str) + self.assertEqual(result.lower(), r"c:\windows\system32") + self.assertEqual(result, expected) + + def _id2str(self, type_id): + if hasattr(type_id, 'index'): + return type_id + else: + return u'#{0}'.format(type_id) + + +if __name__ == '__main__': + unittest.main() diff --git a/venv/Lib/site-packages/win32ctypes/tests/test_win32cred.py b/venv/Lib/site-packages/win32ctypes/tests/test_win32cred.py new file mode 100644 index 0000000..b34506a --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/tests/test_win32cred.py @@ -0,0 +1,230 @@ +# +# (C) Copyright 2014 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +import os +import sys +import unittest + +import win32cred + +from win32ctypes.core._winerrors import ERROR_NOT_FOUND +from win32ctypes.pywin32.pywintypes import error +from win32ctypes.pywin32.win32cred import ( + CredDelete, CredRead, CredWrite, CredEnumerate, + CRED_PERSIST_ENTERPRISE, CRED_TYPE_GENERIC, + CRED_ENUMERATE_ALL_CREDENTIALS) + +# find the pywin32 version +version_file = os.path.join( + os.path.dirname( + os.path.dirname(win32cred.__file__)), 'pywin32.version.txt') +if os.path.exists(version_file): + with open(version_file) as handle: + pywin32_build = handle.read().strip() +else: + pywin32_build = None + + +class TestCred(unittest.TestCase): + + def setUp(self): + from pywintypes import error + try: + win32cred.CredDelete(u'jone@doe', CRED_TYPE_GENERIC) + except error: + pass + + def _demo_credentials(self, UserName=u'jone'): + return { + "Type": CRED_TYPE_GENERIC, + "TargetName": u'jone@doe', + "UserName": UserName, + "CredentialBlob": u"doefsajfsakfj", + "Comment": u"Created by MiniPyWin32Cred test suite", + "Persist": CRED_PERSIST_ENTERPRISE} + + @unittest.skipIf( + pywin32_build == "223" and sys.version_info[:2] == (3, 7), + "pywin32 version 223 bug with CredRead (mhammond/pywin32#1232)") + def test_write_to_pywin32(self): + # given + target = u'jone@doe' + r_credentials = self._demo_credentials() + CredWrite(r_credentials) + + # when + credentials = win32cred.CredRead( + TargetName=target, Type=CRED_TYPE_GENERIC) + + # then + self.assertEqual(credentials["Type"], CRED_TYPE_GENERIC) + self.assertEqual(credentials["UserName"], u"jone") + self.assertEqual(credentials["TargetName"], u'jone@doe') + self.assertEqual( + credentials["Comment"], u"Created by MiniPyWin32Cred test suite") + # XXX: the fact that we have to decode the password when reading, but + # not encode when writing is a bit strange, but that's what pywin32 + # seems to do and we try to be backward compatible here. + self.assertEqual( + credentials["CredentialBlob"].decode('utf-16'), u"doefsajfsakfj") + + def test_read_from_pywin32(self): + # given + target = u'jone@doe' + r_credentials = self._demo_credentials() + win32cred.CredWrite(r_credentials) + + # when + credentials = CredRead(target, CRED_TYPE_GENERIC) + + # then + self.assertEqual(credentials["UserName"], u"jone") + self.assertEqual(credentials["TargetName"], u'jone@doe') + self.assertEqual( + credentials["Comment"], u"Created by MiniPyWin32Cred test suite") + self.assertEqual( + credentials["CredentialBlob"].decode('utf-16'), u"doefsajfsakfj") + + def test_read_from_pywin32_with_none_usename(self): + # given + target = u'jone@doe' + r_credentials = self._demo_credentials(None) + win32cred.CredWrite(r_credentials) + + # when + credentials = CredRead(target, CRED_TYPE_GENERIC) + + self.assertEqual(credentials["UserName"], None) + self.assertEqual(credentials["TargetName"], u'jone@doe') + self.assertEqual( + credentials["Comment"], u"Created by MiniPyWin32Cred test suite") + self.assertEqual( + credentials["CredentialBlob"].decode('utf-16'), u"doefsajfsakfj") + + def test_write_to_pywin32_with_none_usename(self): + # given + target = u'jone@doe' + r_credentials = self._demo_credentials(None) + CredWrite(r_credentials) + + # when + credentials = win32cred.CredRead(target, CRED_TYPE_GENERIC) + + self.assertEqual(credentials["UserName"], None) + self.assertEqual(credentials["TargetName"], u'jone@doe') + self.assertEqual( + credentials["Comment"], u"Created by MiniPyWin32Cred test suite") + self.assertEqual( + credentials["CredentialBlob"].decode('utf-16'), u"doefsajfsakfj") + + def test_read_write(self): + # given + target = u'jone@doe' + r_credentials = self._demo_credentials() + + # when + CredWrite(r_credentials) + credentials = CredRead(target, CRED_TYPE_GENERIC) + + self.assertEqual(credentials["UserName"], u"jone") + self.assertEqual(credentials["TargetName"], u'jone@doe') + self.assertEqual( + credentials["Comment"], u"Created by MiniPyWin32Cred test suite") + self.assertEqual( + credentials["CredentialBlob"].decode('utf-16'), u"doefsajfsakfj") + + def test_read_write_with_none_username(self): + # given + target = u'jone@doe' + r_credentials = self._demo_credentials(None) + + # when + CredWrite(r_credentials) + credentials = CredRead(target, CRED_TYPE_GENERIC) + + # then + self.assertEqual(credentials["UserName"], None) + self.assertEqual(credentials["TargetName"], u'jone@doe') + self.assertEqual( + credentials["Comment"], u"Created by MiniPyWin32Cred test suite") + self.assertEqual( + credentials["CredentialBlob"].decode('utf-16'), u"doefsajfsakfj") + + def test_enumerate_filter(self): + # given + r_credentials = self._demo_credentials() + CredWrite(r_credentials) + + # when + credentials = CredEnumerate('jone*')[0] + + # then + self.assertEqual(credentials["UserName"], u"jone") + self.assertEqual(credentials["TargetName"], u'jone@doe') + self.assertEqual( + credentials["Comment"], u"Created by MiniPyWin32Cred test suite") + self.assertEqual( + credentials["CredentialBlob"].decode('utf-16'), u"doefsajfsakfj") + + def test_enumerate_no_filter(self): + # given + r_credentials = self._demo_credentials() + CredWrite(r_credentials) + + # when + pywin32_result = win32cred.CredEnumerate() + credentials = CredEnumerate() + + # then + self.assertEqual(len(credentials), len(pywin32_result)) + + def test_enumerate_all(self): + # when + credentials = CredEnumerate(Flags=CRED_ENUMERATE_ALL_CREDENTIALS) + + # then + self.assertGreater(len(credentials), 1) + + def test_read_doesnt_exists(self): + # given + target = "Floupi_dont_exists@MiniPyWin" + + # when/then + with self.assertRaises(error) as ctx: + CredRead(target, CRED_TYPE_GENERIC) + self.assertTrue(ctx.exception.winerror, ERROR_NOT_FOUND) + + def test_delete_simple(self): + # given + target = u'jone@doe' + r_credentials = self._demo_credentials() + CredWrite(r_credentials, 0) + credentials = CredRead(target, CRED_TYPE_GENERIC) + self.assertTrue(credentials is not None) + + # when + CredDelete(target, CRED_TYPE_GENERIC) + + # then + with self.assertRaises(error) as ctx: + CredRead(target, CRED_TYPE_GENERIC) + self.assertEqual(ctx.exception.winerror, ERROR_NOT_FOUND) + self.assertEqual(ctx.exception.funcname, "CredRead") + + def test_delete_doesnt_exists(self): + # given + target = u"Floupi_doesnt_exists@MiniPyWin32" + + # when/then + with self.assertRaises(error) as ctx: + CredDelete(target, CRED_TYPE_GENERIC) + self.assertEqual(ctx.exception.winerror, ERROR_NOT_FOUND) + self.assertEqual(ctx.exception.funcname, "CredDelete") + + +if __name__ == '__main__': + unittest.main() diff --git a/venv/Lib/site-packages/win32ctypes/version.py b/venv/Lib/site-packages/win32ctypes/version.py new file mode 100644 index 0000000..d31c31e --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/version.py @@ -0,0 +1 @@ +__version__ = "0.2.3" diff --git a/venv/Lib/site-packages/win32ctypes/win32api.py b/venv/Lib/site-packages/win32ctypes/win32api.py new file mode 100644 index 0000000..493974b --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/win32api.py @@ -0,0 +1,13 @@ +# +# (C) Copyright 2014 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +import warnings +from win32ctypes.pywin32.win32api import * # noqa + +warnings.warn( + "Please use 'from win32ctypes.pywin32 import win32api'", + DeprecationWarning) diff --git a/venv/Lib/site-packages/win32ctypes/win32cred.py b/venv/Lib/site-packages/win32ctypes/win32cred.py new file mode 100644 index 0000000..de4cd66 --- /dev/null +++ b/venv/Lib/site-packages/win32ctypes/win32cred.py @@ -0,0 +1,13 @@ +# +# (C) Copyright 2014 Enthought, Inc., Austin, TX +# All right reserved. +# +# This file is open source software distributed according to the terms in +# LICENSE.txt +# +import warnings +from win32ctypes.pywin32.win32cred import * # noqa + +warnings.warn( + "Please use 'from win32ctypes.pywin32 import win32cred'", + DeprecationWarning) diff --git a/venv/Scripts/pip.exe b/venv/Scripts/pip.exe index 2f931cf..d42331a 100644 Binary files a/venv/Scripts/pip.exe and b/venv/Scripts/pip.exe differ diff --git a/venv/Scripts/pip3.11.exe b/venv/Scripts/pip3.11.exe index 2f931cf..d42331a 100644 Binary files a/venv/Scripts/pip3.11.exe and b/venv/Scripts/pip3.11.exe differ diff --git a/venv/Scripts/pip3.exe b/venv/Scripts/pip3.exe index 2f931cf..d42331a 100644 Binary files a/venv/Scripts/pip3.exe and b/venv/Scripts/pip3.exe differ diff --git a/venv/Scripts/pyi-archive_viewer.exe b/venv/Scripts/pyi-archive_viewer.exe new file mode 100644 index 0000000..03c1329 Binary files /dev/null and b/venv/Scripts/pyi-archive_viewer.exe differ diff --git a/venv/Scripts/pyi-bindepend.exe b/venv/Scripts/pyi-bindepend.exe new file mode 100644 index 0000000..709e939 Binary files /dev/null and b/venv/Scripts/pyi-bindepend.exe differ diff --git a/venv/Scripts/pyi-grab_version.exe b/venv/Scripts/pyi-grab_version.exe new file mode 100644 index 0000000..fbee720 Binary files /dev/null and b/venv/Scripts/pyi-grab_version.exe differ diff --git a/venv/Scripts/pyi-makespec.exe b/venv/Scripts/pyi-makespec.exe new file mode 100644 index 0000000..7e4b271 Binary files /dev/null and b/venv/Scripts/pyi-makespec.exe differ diff --git a/venv/Scripts/pyi-set_version.exe b/venv/Scripts/pyi-set_version.exe new file mode 100644 index 0000000..9938808 Binary files /dev/null and b/venv/Scripts/pyi-set_version.exe differ diff --git a/venv/Scripts/pyinstaller.exe b/venv/Scripts/pyinstaller.exe new file mode 100644 index 0000000..b0707f2 Binary files /dev/null and b/venv/Scripts/pyinstaller.exe differ diff --git a/windows_module_compile.bat b/windows_module_compile.bat new file mode 100644 index 0000000..f2ebbdd --- /dev/null +++ b/windows_module_compile.bat @@ -0,0 +1 @@ +pyinstaller --onefile run.py \ No newline at end of file