From 903454b20300449473a94afc61a6043288bdcd29 Mon Sep 17 00:00:00 2001 From: Avasam Date: Tue, 6 Sep 2022 14:20:54 -0400 Subject: [PATCH] No type variable or generic argument --- PyInstaller/__init__.py | 7 ++- PyInstaller/__main__.py | 6 +-- PyInstaller/compat.py | 43 +++++------------ PyInstaller/utils/hooks/__init__.py | 71 ++++++++++++----------------- PyInstaller/utils/hooks/conda.py | 44 ++++++------------ pyi_splash-stubs/__init__.pyi | 11 +---- 6 files changed, 62 insertions(+), 120 deletions(-) diff --git a/PyInstaller/__init__.py b/PyInstaller/__init__.py index 02cbf7800f..a488473afd 100644 --- a/PyInstaller/__init__.py +++ b/PyInstaller/__init__.py @@ -55,12 +55,11 @@ # Where to put all the temporary files; .log, .pyz, etc. DEFAULT_WORKPATH = os.path.join(os.getcwd(), 'build') -_PLATFORM = compat.system + '-' + compat.architecture -PLATFORM = _PLATFORM +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 = _PLATFORM + '-' + compat.machine + PLATFORM += '-' + compat.machine # Similarly, disambiguate musl Linux from glibc Linux. if compat.is_musl: - PLATFORM = _PLATFORM + '-musl' + PLATFORM += '-musl' diff --git a/PyInstaller/__main__.py b/PyInstaller/__main__.py index 879a082699..94a906ce22 100644 --- a/PyInstaller/__main__.py +++ b/PyInstaller/__main__.py @@ -17,16 +17,12 @@ import os import platform from collections import defaultdict -from typing import Dict, Iterable, List, Tuple, Union 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 -_PyIConfig = Union[Dict[str, Union[bool, str, List[str], None]], Iterable[Tuple[str, Union[bool, str, List[str], - None]]]] - logger = logging.getLogger(__name__) # Taken from https://stackoverflow.com/a/22157136 to format args more flexibly: any help text which beings with ``R|`` @@ -151,7 +147,7 @@ def generate_parser() -> _PyiArgumentParser: return parser -def run(pyi_args: Iterable[str] | None = None, pyi_config: _PyIConfig | None = None): +def run(pyi_args: list | None = None, pyi_config: dict | list | None = None): """ pyi_args allows running PyInstaller programmatically without a subprocess pyi_config allows checking configuration once when running multiple tests diff --git a/PyInstaller/compat.py b/PyInstaller/compat.py index f1dd8fab0b..3d4096cb3f 100644 --- a/PyInstaller/compat.py +++ b/PyInstaller/compat.py @@ -23,27 +23,10 @@ import subprocess import sys import shutil -from typing import Iterable, List, Tuple, Union from PyInstaller._shared_with_waf import _pyi_machine from PyInstaller.exceptions import ExecCommandFailed -if sys.version_info >= (3, 9): - _StrOrBytesPath = Union[str, bytes, os.PathLike[str], os.PathLike[bytes]] -else: - _StrOrBytesPath = Union[str, bytes, os.PathLike] -_OpenFile = Union[_StrOrBytesPath, int] - -if sys.version_info >= (3, 8): - from typing import Literal - _Architecture = Literal['64bit', 'n32bit', '32bit'] - _System = Literal['Cygwin', 'Linux', 'Darwin', 'Java', 'Windows'] - _Machine = Literal['sw_64', 'loongarch64', 'arm', 'intel', 'ppc', 'mips', 'riscv', 's390x', 'unknown'] -else: - _Architecture = str - _System = str - _Machine = str - # Copied from https://docs.python.org/3/library/platform.html#cross-platform. is_64bits: bool = sys.maxsize > 2**32 @@ -220,20 +203,20 @@ # 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: _Architecture = '64bit' if sys.maxsize > 2**32 else '32bit' + architecture = '64bit' if sys.maxsize > 2**32 else '32bit' else: - architecture: _Architecture = platform.architecture()[0] + 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: _System = 'Cygwin' if is_cygwin else platform.system() +system = 'Cygwin' if is_cygwin else platform.system() # Machine suffix for bootloader. -machine: _Machine | None = _pyi_machine(platform.machine(), platform.system()) +machine = _pyi_machine(platform.machine(), platform.system()) # Wine detection and support -def is_wine_dll(filename: _OpenFile): +def is_wine_dll(filename: str | bytes | os.PathLike | int): """ Check if the given PE file is a Wine DLL (PE-converted built-in, or fake/placeholder one). @@ -303,7 +286,7 @@ def exec_command( *cmdargs: str, encoding: str | None = None, raise_enoent: bool | None = None, - **kwargs: int | bool | Iterable[int] | None + **kwargs: int | bool | Iterable | None ): """ Run the command specified by the passed positional arguments, optionally configured by the passed keyword arguments. @@ -383,7 +366,7 @@ def exec_command( return out -def exec_command_rc(*cmdargs: str, **kwargs: float | bool | Iterable[int] | None): +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. @@ -412,7 +395,7 @@ def exec_command_rc(*cmdargs: str, **kwargs: float | bool | Iterable[int] | None def exec_command_stdout( - *command_args: str, encoding: str | None = None, **kwargs: float | str | bytes | bool | Iterable[int] | None + *command_args: str, encoding: str | None = None, **kwargs: float | str | bytes | bool | list | None ): """ Capture and return the standard output of the command specified by the passed positional arguments, optionally @@ -459,9 +442,7 @@ def exec_command_stdout( return stdout if encoding is None else stdout.decode(encoding) -def exec_command_all(*cmdargs: str, - encoding: str | None = None, - **kwargs: int | bool | Iterable[int] | None) -> Tuple[int, str, str]: +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. @@ -583,7 +564,7 @@ def exec_python_rc(*args: str, **kwargs: str | None): # Path handling. -def expand_path(path: _StrOrBytesPath): +def expand_path(path: str | bytes | os.PathLike): """ Replace initial tilde '~' in path with user's home directory, and also expand environment variables (i.e., ${VARNAME} on Unix, %VARNAME% on Windows). @@ -592,7 +573,7 @@ def expand_path(path: _StrOrBytesPath): # Site-packages functions - use native function if available. -def getsitepackages(prefixes: Iterable[str] | None = None): +def getsitepackages(prefixes: list | None = None): """ Returns a list containing all global site-packages directories. @@ -600,7 +581,7 @@ def getsitepackages(prefixes: Iterable[str] | None = None): 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: List[str] = [] + sitepackages = [] seen = set() if prefixes is None: diff --git a/PyInstaller/utils/hooks/__init__.py b/PyInstaller/utils/hooks/__init__.py index 681f2bb621..556df17fff 100644 --- a/PyInstaller/utils/hooks/__init__.py +++ b/PyInstaller/utils/hooks/__init__.py @@ -18,7 +18,7 @@ import fnmatch from pathlib import Path from collections import deque -from typing import Callable, Dict, Iterable, List, Tuple, Union +from typing import Callable import pkg_resources @@ -30,19 +30,6 @@ get_pywin32_module_file_attribute # noqa: F401 from PyInstaller import isolated -if sys.version_info >= (3, 9): - _StrOrBytesPath = Union[str, bytes, os.PathLike[str], os.PathLike[bytes]] -else: - _StrOrBytesPath = Union[str, bytes, os.PathLike] - -if sys.version_info >= (3, 8): - from typing import Literal - _OnError = Literal["ignore", "warn once", "warn", "raise"] -else: - _OnError = str - -_Environ = Union[Dict[str, str], Iterable[Tuple[str, str]]] - logger = logging.getLogger(__name__) # These extensions represent Python executables and should therefore be ignored when collecting data files. @@ -55,7 +42,7 @@ # # For example the 'wx' module needs variable 'wxpubsub'. This tells PyInstaller which protocol of the wx module # should be bundled. -hook_variables: Dict[str, str] = {} +hook_variables = {} def __exec_python_cmd(cmd, env=None, capture_stdout=True): @@ -140,7 +127,7 @@ def __exec_script(script_filename, *args, env=None, capture_stdout=True): return __exec_python_cmd(cmd, env=env, capture_stdout=capture_stdout) -def exec_script(script_filename: _StrOrBytesPath, *args: str, env: _Environ | None = None): +def exec_script(script_filename: str | bytes | os.PathLike, *args: str, env: dict | list | None = None): """ Executes a Python script in an externally spawned interpreter, and returns anything that was emitted to the standard output as a single string. @@ -151,7 +138,7 @@ def exec_script(script_filename: _StrOrBytesPath, *args: str, env: _Environ | No return __exec_script(script_filename, *args, env=env, capture_stdout=True) -def exec_script_rc(script_filename: _StrOrBytesPath, *args: str, env: _Environ | None = None): +def exec_script_rc(script_filename: str | bytes | os.PathLike, *args: str, env: dict | list | None = None): """ Executes a Python script in an externally spawned interpreter, and returns the exit code. @@ -186,7 +173,7 @@ def eval_statement(statement: str): return eval(txt) -def eval_script(script_filename: _StrOrBytesPath, *args: str, env: _Environ | None = None): +def eval_script(script_filename: str | bytes | os.PathLike, *args: str, env: dict | list | None = None): txt = exec_script(script_filename, *args, env=env).strip() if not txt: # Return an empty string, which is "not true" but is iterable. @@ -412,7 +399,7 @@ def _get_module_file_attribute(package): def is_module_satisfies( - requirements: Iterable[str] | pkg_resources.Requirement, + requirements: list | pkg_resources.Requirement, version: str | pkg_resources.Distribution | None = None, version_attr: str = "__version__", ): @@ -617,7 +604,7 @@ def get_package_paths(package: str): def collect_submodules( package: str, filter: Callable[[str], bool] = lambda name: True, - on_error: _OnError = "warn once", + on_error: str = "warn once", ): """ List all submodules of a given package. @@ -672,7 +659,7 @@ def collect_submodules( return [] # Determine the filesystem path(s) to the specified package. - package_submodules: List[str] = [] + package_submodules = [] todo = deque() todo.append(package) @@ -699,8 +686,8 @@ def collect_submodules( # This function is called in an isolated sub-process via `isolated.Python.call`. def _collect_submodules(name, on_error): - import pkgutil import sys + import pkgutil from traceback import format_exception_only from PyInstaller.utils.hooks import logger @@ -791,7 +778,7 @@ def collect_dynamic_libs(package: str, destdir: object | None = None): return [] pkg_dirs = get_all_package_paths(package) - dylibs: List[Tuple[str, str]] = [] + 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 @@ -814,9 +801,9 @@ def collect_dynamic_libs(package: str, destdir: object | None = None): def collect_data_files( package: str, include_py_files: bool = False, - subdir: _StrOrBytesPath | None = None, - excludes: Iterable[str] | None = None, - includes: Iterable[str] | None = None, + subdir: str | bytes | os.PathLike | None = None, + excludes: list | None = None, + includes: list | None = None, ): r""" This function produces a list of ``(source, dest)`` non-Python (i.e., data) files that reside in ``package``. @@ -899,7 +886,7 @@ def clude_walker( sources.add(g) if is_include else sources.discard(g) # Obtain all paths for the specified package, and process each path independently. - datas: List[Tuple[str, str]] = [] + datas = [] pkg_dirs = get_all_package_paths(package) for pkg_dir in pkg_dirs: @@ -920,7 +907,9 @@ def clude_walker( return datas -def collect_system_data_files(path: str, destdir: _StrOrBytesPath | None = None, include_py_files: bool = False): +def collect_system_data_files( + path: str, destdir: str | bytes | 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. @@ -932,7 +921,7 @@ def collect_system_data_files(path: str, destdir: _StrOrBytesPath | None = None, raise TypeError('path must be a str') # Walk through all file in the given package, looking for data files. - datas: List[Tuple[str, str]] = [] + datas = [] for dirpath, dirnames, files in os.walk(path): for f in files: extension = os.path.splitext(f)[1] @@ -994,7 +983,7 @@ def copy_metadata(package_name: str, recursive: bool = False): todo = deque([package_name]) done = set() - out: List[Tuple[str, str]] = [] + out = [] while todo: package_name = todo.pop() @@ -1177,7 +1166,7 @@ def helper(): @_memoize def _map_distribution_to_packages(): logger.info('Determining a mapping of distributions to packages...') - dist_to_packages: Dict[str, List[str]] = {} + dist_to_packages = {} for p in sys.path: # The path entry ``''`` refers to the current directory. if not p: @@ -1203,7 +1192,7 @@ def _map_distribution_to_packages(): # Given a ``package_name`` as a string, this function returns a list of packages needed to satisfy the requirements. # This output can be assigned directly to ``hiddenimports``. def requirements_for_package(package_name: str): - hiddenimports: List[str] = [] + hiddenimports = [] dist_to_packages = _map_distribution_to_packages() for requirement in pkg_resources.get_distribution(package_name).requires(): @@ -1222,10 +1211,10 @@ def requirements_for_package(package_name: str): def collect_all( package_name: str, include_py_files: bool = True, - filter_submodules: Callable[[str], bool] | None = None, - exclude_datas: Iterable[str] | None = None, - include_datas: Iterable[str] | None = None, - on_error: _OnError = "warn once", + filter_submodules: Callable | None = None, + exclude_datas: list | None = None, + include_datas: list | None = None, + on_error: str = "warn once", ): """ Collect everything for a given package name. @@ -1255,7 +1244,7 @@ def collect_all( datas, binaries, hiddenimports = collect_all('my_module_name') """ - datas: List[Tuple[str, str]] = [] + datas = [] try: datas += copy_metadata(package_name) except Exception as e: @@ -1299,8 +1288,8 @@ def collect_entry_point(name: str): .. versionadded:: 4.3 """ import pkg_resources - datas: List[Tuple[str, str]] = [] - imports: List[str] = [] + datas = [] + imports = [] for dist in pkg_resources.iter_entry_points(name): project_name = '' if dist.dist is None else dist.dist.project_name datas += copy_metadata(project_name) @@ -1345,8 +1334,8 @@ def get_hook_config(hook_api: PostGraphAPI, module_name: str, key: str): def include_or_exclude_file( filename: str, - include_list: Iterable[str] | None = None, - exclude_list: Iterable[str] | None = None, + 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. diff --git a/PyInstaller/utils/hooks/conda.py b/PyInstaller/utils/hooks/conda.py index a4d6fe191f..db44bdd3c5 100644 --- a/PyInstaller/utils/hooks/conda.py +++ b/PyInstaller/utils/hooks/conda.py @@ -38,30 +38,16 @@ import fnmatch import json import sys -from pathlib import Path, PurePath -from typing import Dict, Iterable, List, Tuple, Union -from os import PathLike +from pathlib import Path +from typing import Iterable, List from PyInstaller import compat from PyInstaller.log import logger -if sys.version_info >= (3, 9): - _StrOrBytesPath = Union[str, bytes, PathLike[str], PathLike[bytes]] -else: - _StrOrBytesPath = Union[str, bytes, PathLike] - -if sys.version_info >= (3, 8): +if compat.is_py38: from importlib.metadata import PackagePath as _PackagePath - from typing import TypedDict - - class _RawDict(TypedDict): - name: str - version: str - files: List[Union[_StrOrBytesPath, PurePath]] - depends: List[str] else: from importlib_metadata import PackagePath as _PackagePath - _RawDict = Dict[str, Union[str, List[str], List[Union[_StrOrBytesPath, PurePath]]]] # 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. @@ -69,7 +55,7 @@ class _RawDict(TypedDict): CONDA_META_DIR = CONDA_ROOT / "conda-meta" # Find all paths in `sys.path` that are inside Conda root. -PYTHONPATH_PREFIXES: List[Path] = [] +PYTHONPATH_PREFIXES = [] for _path in sys.path: _path = Path(_path) try: @@ -107,11 +93,11 @@ def __init__(self, json_path: str): ) # Everything we need (including this distribution's name) is kept in the metadata json. - self.raw: _RawDict = json.loads(self._json_path.read_text()) + self.raw: dict = json.loads(self._json_path.read_text()) # Unpack the more useful contents of the json. - self.name = self.raw["name"] - self.version = self.raw["version"] + 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() @@ -128,7 +114,7 @@ def _init_dependencies(self): The names in ``self.raw["depends"]`` come with extra version constraint information which must be stripped. """ - dependencies: List[str] = [] + dependencies = [] # For each dependency: for dependency in self.raw["depends"]: # ``dependency`` is a string of the form: "[name] [version constraints]" @@ -145,7 +131,7 @@ def _init_package_names(self): These are names you would ``import`` rather than names you would install. """ - packages: List[str] = [] + packages = [] for file in self.files: package = _get_package_name(file) if package is not None: @@ -220,7 +206,7 @@ def walk_dependency_tree(initial: str, excludes: Iterable[str] | None = None): # Rather than use true recursion, mimic it with a to-do queue. from collections import deque - done: Dict[str, Distribution] = {} + done = {} names_to_do = deque([initial]) while names_to_do: @@ -259,7 +245,7 @@ def _iter_distributions(name, dependencies, excludes): return [Distribution.from_name(name)] -def requires(name: str, strip_versions: bool = False): +def requires(name: str, strip_versions: bool = False) -> List[str]: """ List requirements of a distribution. @@ -276,7 +262,7 @@ def requires(name: str, strip_versions: bool = False): return distribution(name).raw["depends"] -def files(name: str, dependencies: bool = False, excludes: Iterable[str] | None = None): +def files(name: str, dependencies: bool = False, excludes: list | None = None) -> List[PackagePath]: """ List all files belonging to a distribution. @@ -322,7 +308,7 @@ def collect_dynamic_libs(name: str, dest: str = ".", dependencies: bool = True, 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`. """ - _files: List[Tuple[str, str]] = [] + _files = [] for file in files(name, dependencies, excludes): # A file is classified as a DLL if it lives inside the dedicated ``lib_dir`` DLL folder. if file.parent == lib_dir: @@ -382,7 +368,7 @@ def _get_package_name(file: PackagePath): def _init_distributions(): - distributions: Dict[str, Distribution] = {} + distributions = {} for path in CONDA_META_DIR.glob("*.json"): dist = Distribution(path) distributions[dist.name] = dist @@ -393,7 +379,7 @@ def _init_distributions(): def _init_packages(): - distributions_by_package: Dict[str, Distribution] = {} + distributions_by_package = {} for distribution in distributions.values(): for package in distribution.packages: distributions_by_package[package] = distribution diff --git a/pyi_splash-stubs/__init__.pyi b/pyi_splash-stubs/__init__.pyi index 35440475a9..daa2ca5090 100644 --- a/pyi_splash-stubs/__init__.pyi +++ b/pyi_splash-stubs/__init__.pyi @@ -11,12 +11,7 @@ # https://pyinstaller.org/en/stable/advanced-topics.html#module-pyi_splash # https://github.com/pyinstaller/pyinstaller/blob/develop/PyInstaller/fake-modules/pyi_splash.py -try: - from typing_extensions import Literal -except ImportError: - from typing import Literal - -__all__ = ["CLOSE_CONNECTION", "FLUSH_CHARACTER", "is_alive", "close", "update_text"] +__all__ = ["is_alive", "close", "update_text"] def is_alive() -> bool: @@ -29,7 +24,3 @@ def update_text(msg: str) -> None: def close() -> None: ... - - -CLOSE_CONNECTION: Literal[b"\u0004"] -FLUSH_CHARACTER: Literal[b"\r"]