Final exam version

This commit is contained in:
2026-06-26 10:40:09 +03:00
commit 3e593aea3e
5224 changed files with 535773 additions and 0 deletions

View File

@@ -0,0 +1,47 @@
# ------------------------------------------------------------------
# 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
__version__ = '2026.6'
__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,
]
# Several packages for which provide hooks are involved in deep dependency chains when various optional dependencies are
# installed in the environment, and their analysis typically requires recursion limit that exceeds the default 1000.
# Therefore, automatically raise the recursion limit to at least 5000. This alleviates the need to do so on per-hook
# basis.
if (sys.platform.startswith('win') or sys.platform == 'cygwin') and sys.version_info < (3, 11):
# The recursion limit test in PyInstaller main repository seems to push the recursion level to the limit; and if the
# limit is set to 5000, this crashes python 3.8 - 3.10 on Windows and 3.9 that is (at the time of writing) available
# under Cygwin. Further investigation revealed that Windows builds of python 3.8 and 3.10 handle recursion up to
# level ~2075, while the practical limit for 3.9 is between 1950 and 1975. Therefore, for affected combinations of
# platforms and python versions, use a conservative limit of 1900 - if only to avoid issues with the recursion limit
# test in the main PyInstaller repository...
new_recursion_limit = 1900
else:
new_recursion_limit = 5000
if sys.getrecursionlimit() < new_recursion_limit:
sys.setrecursionlimit(new_recursion_limit)

View File

@@ -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()

View File

@@ -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
# ------------------------------------------------------------------

View File

@@ -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
# ------------------------------------------------------------------

View File

@@ -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')

View File

@@ -0,0 +1,50 @@
#-----------------------------------------------------------------------------
# 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 its __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 import compat
from PyInstaller import isolated
from PyInstaller.utils.hooks import logger
@isolated.decorate
def _get_win32com_file():
try:
import win32com
return win32com.__file__
except Exception:
return None
def pre_safe_import_module(api):
if not compat.is_win or compat.is_cygwin:
return
win32com_file = _get_win32com_file()
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)

View File

@@ -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'],
}

View File

@@ -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
# ------------------------------------------------------------------

View File

@@ -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

View File

@@ -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')

View File

@@ -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 = ''

View File

@@ -0,0 +1,57 @@
#-----------------------------------------------------------------------------
# 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 with custom implementation that checks whether the original implementation
# resolves the copy of a library that is bundled with the frozen application. If the original implementation fails to
# resolve the shared library or resolves a system copy, explicitly check if a copy exists in the top-level application
# directory and if it does, return it instead. This aims to mitigate issues with older versions of `findlibs` (< 0.1.0)
# that failed to pick up bundled copy from top-level application directory due to hard-coded search paths.
def _pyi_rthook():
import sys
import os
import pathlib
# findlibs v0.1.0 broke compatibility with python < 3.10; due to incompatible typing annotation, attempting to
# import the package raises `TypeError: unsupported operand type(s) for |: 'type' and 'NoneType'`. Gracefully
# handle this situation by making this run-time hook no-op, in order to avoid crashing the frozen program even
# if it would never end up importing/using `findlibs`.
try:
import findlibs
except TypeError:
return
_orig_find = getattr(findlibs, 'find', None)
if _orig_find is None:
return
def _pyi_find(lib_name, *args, **kwargs):
# Try resolving with the original implementation. If resolved, check that a bundled copy was resolved.
orig_lib = _orig_find(lib_name, *args, **kwargs)
if orig_lib is not None:
application_dir = pathlib.Path(sys._MEIPASS).resolve()
lib_path = pathlib.Path(orig_lib).resolve()
if application_dir in lib_path.parents:
return orig_lib
# Look for a copy in top-level application directory.
extension = findlibs.EXTENSIONS.get(sys.platform, ".so")
fullname = os.path.join(sys._MEIPASS, f"lib{lib_name}{extension}")
if os.path.isfile(fullname):
return fullname
# As a last resort, return the result of original resolution attempt.
return orig_lib
findlibs.find = _pyi_find
_pyi_rthook()
del _pyi_rthook

View File

@@ -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"))

View File

@@ -0,0 +1,38 @@
#-----------------------------------------------------------------------------
# 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')
if not os.path.exists(gdal_data):
# last attempt, check if one of the required files is in the
# generic folder Library/data.
generic_folder = os.path.join(sys._MEIPASS, 'Library', 'data')
# 'gcs.csv' is included by gdal <= 2.4.4
# 'gdalicon.png' is included by gdal >= 2.4.4 (and presumeably earlier)
if os.path.exists(os.path.join(generic_folder, 'gcs.csv')) or \
os.path.exists(os.path.join(generic_folder, 'gdalicon.png')):
gdal_data = generic_folder
else:
gdal_data = os.path.join(sys._MEIPASS, 'share', 'gdal')
if os.path.exists(gdal_data):
os.environ['GDAL_DATA'] = gdal_data

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,52 @@
#-----------------------------------------------------------------------------
# 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:
import importlib.util
spec = importlib.util.find_spec("pyqtgraph.multiprocess.bootstrap")
bootstrap_co = spec.loader.get_code("pyqtgraph.multiprocess.bootstrap")
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
# This is obsolete for PyInstaller >= v6.10.0
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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,85 @@
#-----------------------------------------------------------------------------
# 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:
# Find a list of library files that match 'candidate'.
if find_library:
# Caller provides a function that lookup lib path by candidate name.
lib_path = find_library(candidate)
libs = [lib_path] if lib_path else []
else:
# No find_library callback function, we look at the default location.
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))
# Do linker's path lookup work to force load bundled copy.
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', ))

View File

@@ -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
# ------------------------------------------------------------------

Some files were not shown because too many files have changed in this diff Show More