diff --git a/app.py b/app.py index 42f6b803..4af83b32 100644 --- a/app.py +++ b/app.py @@ -1606,8 +1606,6 @@ def export_achievement(achievement_id): return redirect(url_for("student-achievements")) -if __name__ == "__main__": - init_db() - add_profile_picture_column() - app.run(debug=True) +if __name__ == '__main__': + app.run(debug=True, host='127.0.0.1', port=5001) diff --git a/templates/student.html b/templates/student.html index 4fe876b2..6635f92c 100644 --- a/templates/student.html +++ b/templates/student.html @@ -5,7 +5,7 @@ Student Login - Achievement Management System - + @@ -529,26 +537,15 @@
- - - - - Achievement Management System
diff --git a/venv1/Lib/site-packages/pip/__init__.py b/venv1/Lib/site-packages/pip/__init__.py index d0e2bf37..4ad3b2ac 100644 --- a/venv1/Lib/site-packages/pip/__init__.py +++ b/venv1/Lib/site-packages/pip/__init__.py @@ -1,9 +1,9 @@ -from __future__ import annotations +from typing import List, Optional -__version__ = "25.3" +__version__ = "23.1.2" -def main(args: list[str] | None = None) -> int: +def main(args: Optional[List[str]] = None) -> int: """This is an internal API only meant for use by pip's own console scripts. For additional details, see https://github.com/pypa/pip/issues/7498. diff --git a/venv1/Lib/site-packages/pip/__main__.py b/venv1/Lib/site-packages/pip/__main__.py index 59913261..fe34a7b7 100644 --- a/venv1/Lib/site-packages/pip/__main__.py +++ b/venv1/Lib/site-packages/pip/__main__.py @@ -1,5 +1,6 @@ import os import sys +import warnings # Remove '' and current working directory from the first entry # of sys.path, if present to avoid using current directory @@ -19,6 +20,12 @@ sys.path.insert(0, path) if __name__ == "__main__": + # Work around the error reported in #9540, pending a proper fix. + # Note: It is essential the warning filter is set *before* importing + # pip, as the deprecation happens at import time, not runtime. + warnings.filterwarnings( + "ignore", category=DeprecationWarning, module=".*packaging\\.version" + ) from pip._internal.cli.main import main as _main sys.exit(_main()) diff --git a/venv1/Lib/site-packages/pip/__pip-runner__.py b/venv1/Lib/site-packages/pip/__pip-runner__.py index d6be1578..49a148a0 100644 --- a/venv1/Lib/site-packages/pip/__pip-runner__.py +++ b/venv1/Lib/site-packages/pip/__pip-runner__.py @@ -8,8 +8,8 @@ import sys -# Copied from pyproject.toml -PYTHON_REQUIRES = (3, 9) +# Copied from setup.py +PYTHON_REQUIRES = (3, 7) def version_str(version): # type: ignore diff --git a/venv1/Lib/site-packages/pip/_internal/__init__.py b/venv1/Lib/site-packages/pip/_internal/__init__.py index 24d0baf0..6afb5c62 100644 --- a/venv1/Lib/site-packages/pip/_internal/__init__.py +++ b/venv1/Lib/site-packages/pip/_internal/__init__.py @@ -1,5 +1,6 @@ -from __future__ import annotations +from typing import List, Optional +import pip._internal.utils.inject_securetransport # noqa from pip._internal.utils import _log # init_logging() must be called before any call to logging.getLogger() @@ -7,7 +8,7 @@ _log.init_logging() -def main(args: list[str] | None = None) -> int: +def main(args: (Optional[List[str]]) = None) -> int: """This is preserved for old console scripts that may still be referencing it. diff --git a/venv1/Lib/site-packages/pip/_internal/build_env.py b/venv1/Lib/site-packages/pip/_internal/build_env.py index f28d862f..4f704a35 100644 --- a/venv1/Lib/site-packages/pip/_internal/build_env.py +++ b/venv1/Lib/site-packages/pip/_internal/build_env.py @@ -1,6 +1,5 @@ -"""Build Environment used for isolation during sdist building""" - -from __future__ import annotations +"""Build Environment used for isolation during sdist building +""" import logging import os @@ -9,34 +8,27 @@ import sys import textwrap from collections import OrderedDict -from collections.abc import Iterable from types import TracebackType -from typing import TYPE_CHECKING, Protocol, TypedDict +from typing import TYPE_CHECKING, Iterable, List, Optional, Set, Tuple, Type, Union +from pip._vendor.certifi import where +from pip._vendor.packaging.requirements import Requirement from pip._vendor.packaging.version import Version from pip import __file__ as pip_location from pip._internal.cli.spinners import open_spinner from pip._internal.locations import get_platlib, get_purelib, get_scheme from pip._internal.metadata import get_default_environment, get_environment -from pip._internal.utils.deprecation import deprecated -from pip._internal.utils.logging import VERBOSE -from pip._internal.utils.packaging import get_requirement from pip._internal.utils.subprocess import call_subprocess from pip._internal.utils.temp_dir import TempDirectory, tempdir_kinds if TYPE_CHECKING: from pip._internal.index.package_finder import PackageFinder - from pip._internal.req.req_install import InstallRequirement - - class ExtraEnviron(TypedDict, total=False): - extra_environ: dict[str, str] - logger = logging.getLogger(__name__) -def _dedup(a: str, b: str) -> tuple[str] | tuple[str, str]: +def _dedup(a: str, b: str) -> Union[Tuple[str], Tuple[str, str]]: return (a, b) if a != b else (a,) @@ -65,7 +57,7 @@ def get_runnable_pip() -> str: return os.fsdecode(source / "__pip-runner__.py") -def _get_system_sitepackages() -> set[str]: +def _get_system_sitepackages() -> Set[str]: """Get system site packages Usually from site.getsitepackages, @@ -85,171 +77,10 @@ def _get_system_sitepackages() -> set[str]: return {os.path.normcase(path) for path in system_sites} -class BuildEnvironmentInstaller(Protocol): - """ - Interface for installing build dependencies into an isolated build - environment. - """ - - def install( - self, - requirements: Iterable[str], - prefix: _Prefix, - *, - kind: str, - for_req: InstallRequirement | None, - ) -> None: ... - - -class SubprocessBuildEnvironmentInstaller: - """ - Install build dependencies by calling pip in a subprocess. - """ - - def __init__( - self, - finder: PackageFinder, - build_constraints: list[str] | None = None, - build_constraint_feature_enabled: bool = False, - ) -> None: - self.finder = finder - self._build_constraints = build_constraints or [] - self._build_constraint_feature_enabled = build_constraint_feature_enabled - - def _deprecation_constraint_check(self) -> None: - """ - Check for deprecation warning: PIP_CONSTRAINT affecting build environments. - - This warns when build-constraint feature is NOT enabled and PIP_CONSTRAINT - is not empty. - """ - if self._build_constraint_feature_enabled or self._build_constraints: - return - - pip_constraint = os.environ.get("PIP_CONSTRAINT") - if not pip_constraint or not pip_constraint.strip(): - return - - deprecated( - reason=( - "Setting PIP_CONSTRAINT will not affect " - "build constraints in the future," - ), - replacement=( - "to specify build constraints using --build-constraint or " - "PIP_BUILD_CONSTRAINT. To disable this warning without " - "any build constraints set --use-feature=build-constraint or " - 'PIP_USE_FEATURE="build-constraint"' - ), - gone_in="26.2", - issue=None, - ) - - def install( - self, - requirements: Iterable[str], - prefix: _Prefix, - *, - kind: str, - for_req: InstallRequirement | None, - ) -> None: - self._deprecation_constraint_check() - - finder = self.finder - args: list[str] = [ - sys.executable, - get_runnable_pip(), - "install", - "--ignore-installed", - "--no-user", - "--prefix", - prefix.path, - "--no-warn-script-location", - "--disable-pip-version-check", - # As the build environment is ephemeral, it's wasteful to - # pre-compile everything, especially as not every Python - # module will be used/compiled in most cases. - "--no-compile", - # 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") - elif logger.getEffectiveLevel() <= VERBOSE: - args.append("-v") - for format_control in ("no_binary", "only_binary"): - formats = getattr(finder.format_control, format_control) - args.extend( - ( - "--" + format_control.replace("_", "-"), - ",".join(sorted(formats or {":none:"})), - ) - ) - - index_urls = finder.index_urls - if index_urls: - args.extend(["-i", index_urls[0]]) - for extra_index in index_urls[1:]: - args.extend(["--extra-index-url", extra_index]) - else: - args.append("--no-index") - for link in finder.find_links: - args.extend(["--find-links", link]) - - if finder.proxy: - args.extend(["--proxy", finder.proxy]) - for host in finder.trusted_hosts: - args.extend(["--trusted-host", host]) - if finder.custom_cert: - args.extend(["--cert", finder.custom_cert]) - if finder.client_cert: - args.extend(["--client-cert", finder.client_cert]) - if finder.allow_all_prereleases: - args.append("--pre") - if finder.prefer_binary: - args.append("--prefer-binary") - - # Handle build constraints - if self._build_constraint_feature_enabled: - args.extend(["--use-feature", "build-constraint"]) - - if self._build_constraints: - # Build constraints must be passed as both constraints - # and build constraints, so that nested builds receive - # build constraints - for constraint_file in self._build_constraints: - args.extend(["--constraint", constraint_file]) - args.extend(["--build-constraint", constraint_file]) - - extra_environ: ExtraEnviron = {} - if self._build_constraint_feature_enabled and not self._build_constraints: - # If there are no build constraints but the build constraints - # feature is enabled then we must ignore regular constraints - # in the isolated build environment - extra_environ = {"extra_environ": {"_PIP_IN_BUILD_IGNORE_CONSTRAINTS": "1"}} - - args.append("--") - args.extend(requirements) - - identify_requirement = ( - f" for {for_req.name}" if for_req and for_req.name else "" - ) - with open_spinner(f"Installing {kind}") as spinner: - call_subprocess( - args, - command_desc=f"installing {kind}{identify_requirement}", - spinner=spinner, - **extra_environ, - ) - - class BuildEnvironment: """Creates and manages an isolated environment to install build deps""" - def __init__(self, installer: BuildEnvironmentInstaller) -> None: - self.installer = installer + def __init__(self) -> None: temp_dir = TempDirectory(kind=tempdir_kinds.BUILD_ENV, globally_managed=True) self._prefixes = OrderedDict( @@ -257,8 +88,8 @@ def __init__(self, installer: BuildEnvironmentInstaller) -> None: for name in ("normal", "overlay") ) - self._bin_dirs: list[str] = [] - self._lib_dirs: list[str] = [] + self._bin_dirs: List[str] = [] + self._lib_dirs: List[str] = [] for prefix in reversed(list(self._prefixes.values())): self._bin_dirs.append(prefix.bin_dir) self._lib_dirs.extend(prefix.lib_dirs) @@ -326,9 +157,9 @@ def __enter__(self) -> None: def __exit__( self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], ) -> None: for varname, old_value in self._save_env.items(): if old_value is None: @@ -338,7 +169,7 @@ def __exit__( def check_requirements( self, reqs: Iterable[str] - ) -> tuple[set[tuple[str, str]], set[str]]: + ) -> Tuple[Set[Tuple[str, str]], Set[str]]: """Return 2 sets: - conflicting requirements: set of (installed, wanted) reqs tuples - missing requirements: set of reqs @@ -352,7 +183,7 @@ def check_requirements( else get_default_environment() ) for req_str in reqs: - req = get_requirement(req_str) + req = Requirement(req_str) # We're explicitly evaluating with an empty extra value, since build # environments are not provided any mechanism to select specific extras. if req.marker is not None and not req.marker.evaluate({"extra": ""}): @@ -372,18 +203,81 @@ def check_requirements( def install_requirements( self, + finder: "PackageFinder", requirements: Iterable[str], prefix_as_string: str, *, kind: str, - for_req: InstallRequirement | None = None, ) -> None: prefix = self._prefixes[prefix_as_string] assert not prefix.setup prefix.setup = True if not requirements: return - self.installer.install(requirements, prefix, kind=kind, for_req=for_req) + self._install_requirements( + get_runnable_pip(), + finder, + requirements, + prefix, + kind=kind, + ) + + @staticmethod + def _install_requirements( + pip_runnable: str, + finder: "PackageFinder", + requirements: Iterable[str], + prefix: _Prefix, + *, + kind: str, + ) -> None: + args: List[str] = [ + sys.executable, + pip_runnable, + "install", + "--ignore-installed", + "--no-user", + "--prefix", + prefix.path, + "--no-warn-script-location", + ] + if logger.getEffectiveLevel() <= logging.DEBUG: + args.append("-v") + for format_control in ("no_binary", "only_binary"): + formats = getattr(finder.format_control, format_control) + args.extend( + ( + "--" + format_control.replace("_", "-"), + ",".join(sorted(formats or {":none:"})), + ) + ) + + index_urls = finder.index_urls + if index_urls: + args.extend(["-i", index_urls[0]]) + for extra_index in index_urls[1:]: + args.extend(["--extra-index-url", extra_index]) + else: + args.append("--no-index") + for link in finder.find_links: + args.extend(["--find-links", link]) + + for host in finder.trusted_hosts: + args.extend(["--trusted-host", host]) + if finder.allow_all_prereleases: + args.append("--pre") + if finder.prefer_binary: + args.append("--prefer-binary") + args.append("--") + args.extend(requirements) + extra_environ = {"_PIP_STANDALONE_CERT": where()} + with open_spinner(f"Installing {kind}") as spinner: + call_subprocess( + args, + command_desc=f"pip subprocess to install {kind}", + spinner=spinner, + extra_environ=extra_environ, + ) class NoOpBuildEnvironment(BuildEnvironment): @@ -397,9 +291,9 @@ def __enter__(self) -> None: def __exit__( self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], ) -> None: pass @@ -408,10 +302,10 @@ def cleanup(self) -> None: def install_requirements( self, + finder: "PackageFinder", requirements: Iterable[str], prefix_as_string: str, *, kind: str, - for_req: InstallRequirement | None = None, ) -> None: raise NotImplementedError() diff --git a/venv1/Lib/site-packages/pip/_internal/cache.py b/venv1/Lib/site-packages/pip/_internal/cache.py index 0bcb6975..05f0a9ac 100644 --- a/venv1/Lib/site-packages/pip/_internal/cache.py +++ b/venv1/Lib/site-packages/pip/_internal/cache.py @@ -1,13 +1,12 @@ -"""Cache Management""" - -from __future__ import annotations +"""Cache Management +""" import hashlib import json import logging import os from pathlib import Path -from typing import Any +from typing import Any, Dict, List, Optional from pip._vendor.packaging.tags import Tag, interpreter_name, interpreter_version from pip._vendor.packaging.utils import canonicalize_name @@ -24,7 +23,7 @@ ORIGIN_JSON_NAME = "origin.json" -def _hash_dict(d: dict[str, str]) -> str: +def _hash_dict(d: Dict[str, str]) -> str: """Return a stable sha224 of a dictionary.""" s = json.dumps(d, sort_keys=True, separators=(",", ":"), ensure_ascii=True) return hashlib.sha224(s.encode("ascii")).hexdigest() @@ -41,11 +40,11 @@ def __init__(self, cache_dir: str) -> None: assert not cache_dir or os.path.isabs(cache_dir) self.cache_dir = cache_dir or None - def _get_cache_path_parts(self, link: Link) -> list[str]: + def _get_cache_path_parts(self, link: Link) -> List[str]: """Get parts of part that must be os.path.joined with cache_dir""" # We want to generate an url to use as our cache key, we don't want to - # just reuse the URL because it might have other items in the fragment + # just re-use the URL because it might have other items in the fragment # and we don't care about those. key_parts = {"url": link.url_without_fragment} if link.hash_name is not None and link.hash is not None: @@ -74,15 +73,17 @@ def _get_cache_path_parts(self, link: Link) -> list[str]: return parts - def _get_candidates(self, link: Link, canonical_package_name: str) -> list[Any]: + def _get_candidates(self, link: Link, canonical_package_name: str) -> List[Any]: can_not_cache = not self.cache_dir or not canonical_package_name or not link if can_not_cache: return [] + candidates = [] path = self.get_path_for_link(link) if os.path.isdir(path): - return [(candidate, path) for candidate in os.listdir(path)] - return [] + for candidate in os.listdir(path): + candidates.append((candidate, path)) + return candidates def get_path_for_link(self, link: Link) -> str: """Return a directory to store cached items in for link.""" @@ -91,8 +92,8 @@ def get_path_for_link(self, link: Link) -> str: def get( self, link: Link, - package_name: str | None, - supported_tags: list[Tag], + package_name: Optional[str], + supported_tags: List[Tag], ) -> Link: """Returns a link to a cached item if it exists, otherwise returns the passed link. @@ -129,8 +130,8 @@ def get_path_for_link(self, link: Link) -> str: def get( self, link: Link, - package_name: str | None, - supported_tags: list[Tag], + package_name: Optional[str], + supported_tags: List[Tag], ) -> Link: candidates = [] @@ -143,7 +144,7 @@ def get( wheel = Wheel(wheel_name) except InvalidWheelFilename: continue - if wheel.name != canonical_package_name: + if canonicalize_name(wheel.name) != canonical_package_name: logger.debug( "Ignoring cached wheel %s for %s as it " "does not match the expected distribution name %s.", @@ -190,20 +191,10 @@ def __init__( ): self.link = link self.persistent = persistent - self.origin: DirectUrl | None = None + self.origin: Optional[DirectUrl] = None origin_direct_url_path = Path(self.link.file_path).parent / ORIGIN_JSON_NAME if origin_direct_url_path.exists(): - try: - self.origin = DirectUrl.from_json( - origin_direct_url_path.read_text(encoding="utf-8") - ) - except Exception as e: - logger.warning( - "Ignoring invalid cache entry origin file %s for %s (%s)", - origin_direct_url_path, - link.filename, - e, - ) + self.origin = DirectUrl.from_json(origin_direct_url_path.read_text()) class WheelCache(Cache): @@ -227,8 +218,8 @@ def get_ephem_path_for_link(self, link: Link) -> str: def get( self, link: Link, - package_name: str | None, - supported_tags: list[Tag], + package_name: Optional[str], + supported_tags: List[Tag], ) -> Link: cache_entry = self.get_cache_entry(link, package_name, supported_tags) if cache_entry is None: @@ -238,9 +229,9 @@ def get( def get_cache_entry( self, link: Link, - package_name: str | None, - supported_tags: list[Tag], - ) -> CacheEntry | None: + package_name: Optional[str], + supported_tags: List[Tag], + ) -> Optional[CacheEntry]: """Returns a CacheEntry with a link to a cached item if it exists or None. The cache entry indicates if the item was found in the persistent or ephemeral cache. @@ -266,26 +257,16 @@ def get_cache_entry( @staticmethod def record_download_origin(cache_dir: str, download_info: DirectUrl) -> None: origin_path = Path(cache_dir) / ORIGIN_JSON_NAME - if origin_path.exists(): - try: - origin = DirectUrl.from_json(origin_path.read_text(encoding="utf-8")) - except Exception as e: + if origin_path.is_file(): + origin = DirectUrl.from_json(origin_path.read_text()) + # TODO: use DirectUrl.equivalent when https://github.com/pypa/pip/pull/10564 + # is merged. + if origin.url != download_info.url: logger.warning( - "Could not read origin file %s in cache entry (%s). " - "Will attempt to overwrite it.", - origin_path, - e, + "Origin URL %s in cache entry %s does not match download URL %s. " + "This is likely a pip bug or a cache corruption issue.", + origin.url, + cache_dir, + download_info.url, ) - else: - # TODO: use DirectUrl.equivalent when - # https://github.com/pypa/pip/pull/10564 is merged. - if origin.url != download_info.url: - logger.warning( - "Origin URL %s in cache entry %s does not match download URL " - "%s. This is likely a pip bug or a cache corruption issue. " - "Will overwrite it with the new value.", - origin.url, - cache_dir, - download_info.url, - ) origin_path.write_text(download_info.to_json(), encoding="utf-8") diff --git a/venv1/Lib/site-packages/pip/_internal/cli/__init__.py b/venv1/Lib/site-packages/pip/_internal/cli/__init__.py index 5fcddf5d..e589bb91 100644 --- a/venv1/Lib/site-packages/pip/_internal/cli/__init__.py +++ b/venv1/Lib/site-packages/pip/_internal/cli/__init__.py @@ -1,3 +1,4 @@ -"""Subpackage containing all of pip's command line interface related code""" +"""Subpackage containing all of pip's command line interface related code +""" # This file intentionally does not import submodules diff --git a/venv1/Lib/site-packages/pip/_internal/cli/autocompletion.py b/venv1/Lib/site-packages/pip/_internal/cli/autocompletion.py index f22cd115..226fe84d 100644 --- a/venv1/Lib/site-packages/pip/_internal/cli/autocompletion.py +++ b/venv1/Lib/site-packages/pip/_internal/cli/autocompletion.py @@ -1,13 +1,11 @@ -"""Logic that powers autocompletion installed by ``pip completion``.""" - -from __future__ import annotations +"""Logic that powers autocompletion installed by ``pip completion``. +""" import optparse import os import sys -from collections.abc import Iterable from itertools import chain -from typing import Any +from typing import Any, Iterable, List, Optional from pip._internal.cli.main_parser import create_main_parser from pip._internal.commands import commands_dict, create_command @@ -19,10 +17,6 @@ def autocomplete() -> None: # Don't complete if user hasn't sourced bash_completion file. if "PIP_AUTO_COMPLETE" not in os.environ: return - # Don't complete if autocompletion environment variables - # are not present - if not os.environ.get("COMP_WORDS") or not os.environ.get("COMP_CWORD"): - return cwords = os.environ["COMP_WORDS"].split()[1:] cword = int(os.environ["COMP_CWORD"]) try: @@ -35,7 +29,7 @@ def autocomplete() -> None: options = [] # subcommand - subcommand_name: str | None = None + subcommand_name: Optional[str] = None for word in cwords: if word in subcommands: subcommand_name = word @@ -77,9 +71,8 @@ def autocomplete() -> None: for opt in subcommand.parser.option_list_all: if opt.help != optparse.SUPPRESS_HELP: - options += [ - (opt_str, opt.nargs) for opt_str in opt._long_opts + opt._short_opts - ] + for opt_str in opt._long_opts + opt._short_opts: + options.append((opt_str, opt.nargs)) # filter out previously specified options from available options prev_opts = [x.split("=")[0] for x in cwords[1 : cword - 1]] @@ -103,12 +96,6 @@ def autocomplete() -> None: if option[1] and option[0][:2] == "--": opt_label += "=" print(opt_label) - - # Complete sub-commands (unless one is already given). - if not any(name in cwords for name in subcommand.handler_map()): - for handler_name in subcommand.handler_map(): - if handler_name.startswith(current): - print(handler_name) else: # show main parser options only when necessary @@ -130,8 +117,8 @@ def autocomplete() -> None: def get_path_completion_type( - cwords: list[str], cword: int, opts: Iterable[Any] -) -> str | None: + cwords: List[str], cword: int, opts: Iterable[Any] +) -> Optional[str]: """Get the type of path completion (``file``, ``dir``, ``path`` or None) :param cwords: same as the environmental variable ``COMP_WORDS`` diff --git a/venv1/Lib/site-packages/pip/_internal/cli/base_command.py b/venv1/Lib/site-packages/pip/_internal/cli/base_command.py index 7acc29cb..637fba18 100644 --- a/venv1/Lib/site-packages/pip/_internal/cli/base_command.py +++ b/venv1/Lib/site-packages/pip/_internal/cli/base_command.py @@ -1,7 +1,6 @@ """Base Command class, and related routines""" -from __future__ import annotations - +import functools import logging import logging.config import optparse @@ -9,9 +8,8 @@ import sys import traceback from optparse import Values -from typing import Callable +from typing import Any, Callable, List, Optional, Tuple -from pip._vendor.rich import reconfigure from pip._vendor.rich import traceback as rich_traceback from pip._internal.cli import cmdoptions @@ -30,6 +28,7 @@ InstallationError, NetworkConnectionError, PreviousBuildDirError, + UninstallationError, ) from pip._internal.utils.filesystem import check_path_owner from pip._internal.utils.logging import BrokenStdoutLoggingError, setup_logging @@ -62,7 +61,7 @@ def __init__(self, name: str, summary: str, isolated: bool = False) -> None: isolated=isolated, ) - self.tempdir_registry: TempDirRegistry | None = None + self.tempdir_registry: Optional[TempDirRegistry] = None # Commands should add options to this option group optgroup_name = f"{self.name.capitalize()} Options" @@ -89,78 +88,21 @@ def handle_pip_version_check(self, options: Values) -> None: # are present. assert not hasattr(options, "no_index") - def run(self, options: Values, args: list[str]) -> int: + def run(self, options: Values, args: List[str]) -> int: raise NotImplementedError - def _run_wrapper(self, level_number: int, options: Values, args: list[str]) -> int: - def _inner_run() -> int: - try: - return self.run(options, args) - finally: - self.handle_pip_version_check(options) - - if options.debug_mode: - rich_traceback.install(show_locals=True) - return _inner_run() - - try: - status = _inner_run() - assert isinstance(status, int) - return status - except DiagnosticPipError as exc: - logger.error("%s", exc, extra={"rich": True}) - logger.debug("Exception information:", exc_info=True) - - return ERROR - except PreviousBuildDirError as exc: - logger.critical(str(exc)) - logger.debug("Exception information:", exc_info=True) - - return PREVIOUS_BUILD_DIR_ERROR - except ( - InstallationError, - BadCommand, - NetworkConnectionError, - ) as exc: - logger.critical(str(exc)) - logger.debug("Exception information:", exc_info=True) - - return ERROR - except CommandError as exc: - logger.critical("%s", exc) - logger.debug("Exception information:", exc_info=True) - - return ERROR - except BrokenStdoutLoggingError: - # Bypass our logger and write any remaining messages to - # stderr because stdout no longer works. - print("ERROR: Pipe to stdout was broken", file=sys.stderr) - if level_number <= logging.DEBUG: - traceback.print_exc(file=sys.stderr) - - return ERROR - except KeyboardInterrupt: - logger.critical("Operation cancelled by user") - logger.debug("Exception information:", exc_info=True) - - return ERROR - except BaseException: - logger.critical("Exception:", exc_info=True) - - return UNKNOWN_ERROR - - def parse_args(self, args: list[str]) -> tuple[Values, list[str]]: + def parse_args(self, args: List[str]) -> Tuple[Values, List[str]]: # factored out for testability return self.parser.parse_args(args) - def main(self, args: list[str]) -> int: + def main(self, args: List[str]) -> int: try: with self.main_context(): return self._main(args) finally: logging.shutdown() - def _main(self, args: list[str]) -> int: + def _main(self, args: List[str]) -> int: # We must initialize this before the tempdir manager, otherwise the # configuration would not be accessible by the time we clean up the # tempdir manager. @@ -173,13 +115,7 @@ def _main(self, args: list[str]) -> int: # Set verbosity so that it can be used elsewhere. self.verbosity = options.verbose - options.quiet - if options.debug_mode: - self.verbosity = 2 - - if hasattr(options, "progress_bar") and options.progress_bar == "auto": - options.progress_bar = "on" if self.verbosity >= 0 else "off" - reconfigure(no_color=options.no_color) level_number = setup_logging( verbosity=self.verbosity, no_color=options.no_color, @@ -195,17 +131,6 @@ def _main(self, args: list[str]) -> int: ", ".join(sorted(always_enabled_features)), ) - # Make sure that the --python argument isn't specified after the - # subcommand. We can tell, because if --python was specified, - # we should only reach this point if we're running in the created - # subprocess, which has the _PIP_RUNNING_IN_SUBPROCESS environment - # variable set. - if options.python and "_PIP_RUNNING_IN_SUBPROCESS" not in os.environ: - logger.critical( - "The --python option must be placed before the pip subcommand name" - ) - sys.exit(ERROR) - # TODO: Try to get these passing down from the command? # without resorting to os.environ to hold these. # This also affects isolated builds and it should. @@ -235,10 +160,66 @@ def _main(self, args: list[str]) -> int: ) options.cache_dir = None - return self._run_wrapper(level_number, options, args) + def intercepts_unhandled_exc( + run_func: Callable[..., int] + ) -> Callable[..., int]: + @functools.wraps(run_func) + def exc_logging_wrapper(*args: Any) -> int: + try: + status = run_func(*args) + assert isinstance(status, int) + return status + except DiagnosticPipError as exc: + logger.error("[present-rich] %s", exc) + logger.debug("Exception information:", exc_info=True) + + return ERROR + except PreviousBuildDirError as exc: + logger.critical(str(exc)) + logger.debug("Exception information:", exc_info=True) + + return PREVIOUS_BUILD_DIR_ERROR + except ( + InstallationError, + UninstallationError, + BadCommand, + NetworkConnectionError, + ) as exc: + logger.critical(str(exc)) + logger.debug("Exception information:", exc_info=True) + + return ERROR + except CommandError as exc: + logger.critical("%s", exc) + logger.debug("Exception information:", exc_info=True) + + return ERROR + except BrokenStdoutLoggingError: + # Bypass our logger and write any remaining messages to + # stderr because stdout no longer works. + print("ERROR: Pipe to stdout was broken", file=sys.stderr) + if level_number <= logging.DEBUG: + traceback.print_exc(file=sys.stderr) + + return ERROR + except KeyboardInterrupt: + logger.critical("Operation cancelled by user") + logger.debug("Exception information:", exc_info=True) + + return ERROR + except BaseException: + logger.critical("Exception:", exc_info=True) + + return UNKNOWN_ERROR + + return exc_logging_wrapper - def handler_map(self) -> dict[str, Callable[[Values, list[str]], None]]: - """ - map of names to handler actions for commands with sub-actions - """ - return {} + try: + if not options.debug_mode: + run = intercepts_unhandled_exc(self.run) + else: + run = self.run + rich_traceback.install(show_locals=True) + return run(options, args) + finally: + self.handle_pip_version_check(options) diff --git a/venv1/Lib/site-packages/pip/_internal/cli/cmdoptions.py b/venv1/Lib/site-packages/pip/_internal/cli/cmdoptions.py index a4737757..02ba6082 100644 --- a/venv1/Lib/site-packages/pip/_internal/cli/cmdoptions.py +++ b/venv1/Lib/site-packages/pip/_internal/cli/cmdoptions.py @@ -9,16 +9,15 @@ # The following comment should be removed at some point in the future. # mypy: strict-optional=False -from __future__ import annotations +import importlib.util import logging import os -import pathlib import textwrap from functools import partial from optparse import SUPPRESS_HELP, Option, OptionGroup, OptionParser, Values from textwrap import dedent -from typing import Any, Callable +from typing import Any, Callable, Dict, Optional, Tuple from pip._vendor.packaging.utils import canonicalize_name @@ -48,7 +47,7 @@ def raise_option_error(parser: OptionParser, option: Option, msg: str) -> None: parser.error(msg) -def make_option_group(group: dict[str, Any], parser: ConfigOptionParser) -> OptionGroup: +def make_option_group(group: Dict[str, Any], parser: ConfigOptionParser) -> OptionGroup: """ Return an OptionGroup object group -- assumed to be dict with 'name' and 'options' keys @@ -93,36 +92,13 @@ def check_dist_restriction(options: Values, check_target: bool = False) -> None: ) if check_target: - if not options.dry_run and dist_restriction_set and not options.target_dir: + if dist_restriction_set and not options.target_dir: raise CommandError( "Can not use any platform or abi specific options unless " - "installing via '--target' or using '--dry-run'" + "installing via '--target'" ) -def check_build_constraints(options: Values) -> None: - """Function for validating build constraints options. - - :param options: The OptionParser options. - """ - if hasattr(options, "build_constraints") and options.build_constraints: - if not options.build_isolation: - raise CommandError( - "--build-constraint cannot be used with --no-build-isolation." - ) - - # Import here to avoid circular imports - from pip._internal.network.session import PipSession - from pip._internal.req.req_file import get_file_content - - # Eagerly check build constraints file contents - # is valid so that we don't fail in when trying - # to check constraints in isolated build process - with PipSession() as session: - for constraint_file in options.build_constraints: - get_file_content(constraint_file, session) - - def _path_option_check(option: Option, opt: str, value: str) -> str: return os.path.expanduser(value) @@ -183,7 +159,8 @@ class PipOption(Option): action="store_true", default=False, help=( - "Allow pip to only run in a virtual environment; exit with an error otherwise." + "Allow pip to only run in a virtual environment; " + "exit with an error otherwise." ), ) @@ -249,13 +226,9 @@ class PipOption(Option): "--progress-bar", dest="progress_bar", type="choice", - choices=["auto", "on", "off", "raw"], - default="auto", - help=( - "Specify whether the progress bar should be used. In 'auto'" - " mode, --quiet will suppress all progress bars." - " [auto, on, off, raw] (default: auto)" - ), + choices=["on", "off"], + default="on", + help="Specify whether the progress bar should be used [on, off] (default: on)", ) log: Callable[..., Option] = partial( @@ -287,8 +260,8 @@ class PipOption(Option): default="auto", help=( "Enable the credential lookup via the keyring library if user input is allowed." - " Specify which mechanism to use [auto, disabled, import, subprocess]." - " (default: %default)" + " Specify which mechanism to use [disabled, import, subprocess]." + " (default: disabled)" ), ) @@ -307,17 +280,8 @@ class PipOption(Option): dest="retries", type="int", default=5, - help="Maximum attempts to establish a new HTTP connection. (default: %default)", -) - -resume_retries: Callable[..., Option] = partial( - Option, - "--resume-retries", - dest="resume_retries", - type="int", - default=5, - help="Maximum attempts to resume or restart an incomplete download. " - "(default: %default)", + help="Maximum number of retries each connection should attempt " + "(default %default times).", ) timeout: Callable[..., Option] = partial( @@ -451,21 +415,6 @@ def constraints() -> Option: ) -def build_constraints() -> Option: - return Option( - "--build-constraint", - dest="build_constraints", - action="append", - type="str", - default=[], - metavar="file", - help=( - "Constrain build dependencies using the given constraints file. " - "This option can be used multiple times." - ), - ) - - def requirements() -> Option: return Option( "-r", @@ -596,7 +545,7 @@ def only_binary() -> Option: # This was made a separate function for unit-testing purposes. -def _convert_python_version(value: str) -> tuple[tuple[int, ...], str | None]: +def _convert_python_version(value: str) -> Tuple[Tuple[int, ...], Optional[str]]: """ Convert a version string like "3", "37", or "3.7.3" into a tuple of ints. @@ -633,7 +582,10 @@ def _handle_python_version( """ version_info, error_msg = _convert_python_version(value) if error_msg is not None: - msg = f"invalid --python-version value: {value!r}: {error_msg}" + msg = "invalid --python-version value: {!r}: {}".format( + value, + error_msg, + ) raise_option_error(parser, option=option, msg=msg) parser.values.python_version = version_info @@ -718,10 +670,7 @@ def prefer_binary() -> Option: dest="prefer_binary", action="store_true", default=False, - help=( - "Prefer binary packages over source packages, even if the " - "source packages are newer." - ), + help="Prefer older binary packages over newer source packages.", ) @@ -784,46 +733,6 @@ def _handle_no_cache_dir( help="Don't install package dependencies.", ) - -def _handle_dependency_group( - option: Option, opt: str, value: str, parser: OptionParser -) -> None: - """ - Process a value provided for the --group option. - - Splits on the rightmost ":", and validates that the path (if present) ends - in `pyproject.toml`. Defaults the path to `pyproject.toml` when one is not given. - - `:` cannot appear in dependency group names, so this is a safe and simple parse. - - This is an optparse.Option callback for the dependency_groups option. - """ - path, sep, groupname = value.rpartition(":") - if not sep: - path = "pyproject.toml" - else: - # check for 'pyproject.toml' filenames using pathlib - if pathlib.PurePath(path).name != "pyproject.toml": - msg = "group paths use 'pyproject.toml' filenames" - raise_option_error(parser, option=option, msg=msg) - - parser.values.dependency_groups.append((path, groupname)) - - -dependency_groups: Callable[..., Option] = partial( - Option, - "--group", - dest="dependency_groups", - default=[], - type=str, - action="callback", - callback=_handle_dependency_group, - metavar="[path:]group", - help='Install a named dependency-group from a "pyproject.toml" file. ' - 'If a path is given, the name of the file must be "pyproject.toml". ' - 'Defaults to using "pyproject.toml" in the current directory.', -) - ignore_requires_python: Callable[..., Option] = partial( Option, "--ignore-requires-python", @@ -849,16 +758,62 @@ def _handle_dependency_group( dest="check_build_deps", action="store_true", default=False, - help="Check the build dependencies.", + help="Check the build dependencies when PEP517 is used.", ) +def _handle_no_use_pep517( + option: Option, opt: str, value: str, parser: OptionParser +) -> None: + """ + Process a value provided for the --no-use-pep517 option. + + This is an optparse.Option callback for the no_use_pep517 option. + """ + # Since --no-use-pep517 doesn't accept arguments, the value argument + # will be None if --no-use-pep517 is passed via the command-line. + # However, the value can be non-None if the option is triggered e.g. + # by an environment variable, for example "PIP_NO_USE_PEP517=true". + if value is not None: + msg = """A value was passed for --no-use-pep517, + probably using either the PIP_NO_USE_PEP517 environment variable + or the "no-use-pep517" config file option. Use an appropriate value + of the PIP_USE_PEP517 environment variable or the "use-pep517" + config file option instead. + """ + raise_option_error(parser, option=option, msg=msg) + + # If user doesn't wish to use pep517, we check if setuptools and wheel are installed + # and raise error if it is not. + packages = ("setuptools", "wheel") + if not all(importlib.util.find_spec(package) for package in packages): + msg = ( + f"It is not possible to use --no-use-pep517 " + f"without {' and '.join(packages)} installed." + ) + raise_option_error(parser, option=option, msg=msg) + + # Otherwise, --no-use-pep517 was passed via the command-line. + parser.values.use_pep517 = False + + use_pep517: Any = partial( Option, "--use-pep517", dest="use_pep517", action="store_true", - default=True, + default=None, + help="Use PEP 517 for building source distributions " + "(use --no-use-pep517 to force legacy behaviour).", +) + +no_use_pep517: Any = partial( + Option, + "--no-use-pep517", + dest="use_pep517", + action="callback", + callback=_handle_no_use_pep517, + default=None, help=SUPPRESS_HELP, ) @@ -868,7 +823,7 @@ def _handle_config_settings( ) -> None: key, sep, val = value.partition("=") if sep != "=": - parser.error(f"Arguments to {opt_str} must be of the form KEY=VAL") + parser.error(f"Arguments to {opt_str} must be of the form KEY=VAL") # noqa dest = getattr(parser.values, option.dest) if dest is None: dest = {} @@ -891,11 +846,30 @@ def _handle_config_settings( action="callback", callback=_handle_config_settings, metavar="settings", - help="Configuration settings to be passed to the build backend. " + help="Configuration settings to be passed to the PEP 517 build backend. " "Settings take the form KEY=VALUE. Use multiple --config-settings options " "to pass multiple keys to the backend.", ) +build_options: Callable[..., Option] = partial( + Option, + "--build-option", + dest="build_options", + metavar="options", + action="append", + help="Extra arguments to be supplied to 'setup.py bdist_wheel'.", +) + +global_options: Callable[..., Option] = partial( + Option, + "--global-option", + dest="global_options", + action="append", + metavar="options", + help="Extra global options to be supplied to the setup.py " + "call before the install or bdist_wheel command.", +) + no_clean: Callable[..., Option] = partial( Option, "--no-clean", @@ -913,14 +887,6 @@ def _handle_config_settings( "pip only finds stable versions.", ) -json: Callable[..., Option] = partial( - Option, - "--json", - action="store_true", - default=False, - help="Output data in a machine-readable JSON format.", -) - disable_pip_version_check: Callable[..., Option] = partial( Option, "--disable-pip-version-check", @@ -937,7 +903,7 @@ def _handle_config_settings( dest="root_user_action", default="warn", choices=["warn", "ignore"], - help="Action if pip is run as a root user [warn, ignore] (default: warn)", + help="Action if pip is run as a root user. By default, a warning message is shown.", ) @@ -952,13 +918,13 @@ def _handle_merge_hash( algo, digest = value.split(":", 1) except ValueError: parser.error( - f"Arguments to {opt_str} must be a hash name " + "Arguments to {} must be a hash name " # noqa "followed by a value, like --hash=sha256:" - "abcde..." + "abcde...".format(opt_str) ) if algo not in STRONG_HASHES: parser.error( - "Allowed hash algorithms for {} are {}.".format( + "Allowed hash algorithms for {} are {}.".format( # noqa opt_str, ", ".join(STRONG_HASHES) ) ) @@ -1024,13 +990,12 @@ def check_list_path_option(options: Values) -> None: dest="no_python_version_warning", action="store_true", default=False, - help=SUPPRESS_HELP, # No-op, a hold-over from the Python 2->3 transition. + help="Silence deprecation warnings for upcoming unsupported Pythons.", ) # Features that are now always on. A warning is printed if they are used. ALWAYS_ENABLED_FEATURES = [ - "truststore", # always on since 24.2 "no-binary-enable-wheel-cache", # always on since 23.1 ] @@ -1043,7 +1008,7 @@ def check_list_path_option(options: Values) -> None: default=[], choices=[ "fast-deps", - "build-constraint", + "truststore", ] + ALWAYS_ENABLED_FEATURES, help="Enable new functionality, that may be backward incompatible.", @@ -1058,16 +1023,16 @@ def check_list_path_option(options: Values) -> None: default=[], choices=[ "legacy-resolver", - "legacy-certs", ], help=("Enable deprecated functionality, that will be removed in the future."), ) + ########## # groups # ########## -general_group: dict[str, Any] = { +general_group: Dict[str, Any] = { "name": "General Options", "options": [ help_, @@ -1095,11 +1060,10 @@ def check_list_path_option(options: Values) -> None: no_python_version_warning, use_new_feature, use_deprecated_feature, - resume_retries, ], } -index_group: dict[str, Any] = { +index_group: Dict[str, Any] = { "name": "Package Index Options", "options": [ index_url, diff --git a/venv1/Lib/site-packages/pip/_internal/cli/command_context.py b/venv1/Lib/site-packages/pip/_internal/cli/command_context.py index 9c167bdc..139995ac 100644 --- a/venv1/Lib/site-packages/pip/_internal/cli/command_context.py +++ b/venv1/Lib/site-packages/pip/_internal/cli/command_context.py @@ -1,6 +1,5 @@ -from collections.abc import Generator -from contextlib import AbstractContextManager, ExitStack, contextmanager -from typing import TypeVar +from contextlib import ExitStack, contextmanager +from typing import ContextManager, Generator, TypeVar _T = TypeVar("_T", covariant=True) @@ -22,7 +21,7 @@ def main_context(self) -> Generator[None, None, None]: finally: self._in_main_context = False - def enter_context(self, context_provider: AbstractContextManager[_T]) -> _T: + def enter_context(self, context_provider: ContextManager[_T]) -> _T: assert self._in_main_context return self._main_context.enter_context(context_provider) diff --git a/venv1/Lib/site-packages/pip/_internal/cli/index_command.py b/venv1/Lib/site-packages/pip/_internal/cli/index_command.py deleted file mode 100644 index f6a82c8a..00000000 --- a/venv1/Lib/site-packages/pip/_internal/cli/index_command.py +++ /dev/null @@ -1,175 +0,0 @@ -""" -Contains command classes which may interact with an index / the network. - -Unlike its sister module, req_command, this module still uses lazy imports -so commands which don't always hit the network (e.g. list w/o --outdated or ---uptodate) don't need waste time importing PipSession and friends. -""" - -from __future__ import annotations - -import logging -import os -import sys -from functools import lru_cache -from optparse import Values -from typing import TYPE_CHECKING - -from pip._vendor import certifi - -from pip._internal.cli.base_command import Command -from pip._internal.cli.command_context import CommandContextMixIn - -if TYPE_CHECKING: - from ssl import SSLContext - - from pip._internal.network.session import PipSession - -logger = logging.getLogger(__name__) - - -@lru_cache -def _create_truststore_ssl_context() -> SSLContext | None: - if sys.version_info < (3, 10): - logger.debug("Disabling truststore because Python version isn't 3.10+") - return None - - try: - import ssl - except ImportError: - logger.warning("Disabling truststore since ssl support is missing") - return None - - try: - from pip._vendor import truststore - except ImportError: - logger.warning("Disabling truststore because platform isn't supported") - return None - - ctx = truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT) - ctx.load_verify_locations(certifi.where()) - return ctx - - -class SessionCommandMixin(CommandContextMixIn): - """ - A class mixin for command classes needing _build_session(). - """ - - def __init__(self) -> None: - super().__init__() - self._session: PipSession | None = None - - @classmethod - def _get_index_urls(cls, options: Values) -> list[str] | None: - """Return a list of index urls from user-provided options.""" - index_urls = [] - if not getattr(options, "no_index", False): - url = getattr(options, "index_url", None) - if url: - index_urls.append(url) - urls = getattr(options, "extra_index_urls", None) - if urls: - index_urls.extend(urls) - # Return None rather than an empty list - return index_urls or None - - def get_default_session(self, options: Values) -> PipSession: - """Get a default-managed session.""" - if self._session is None: - self._session = self.enter_context(self._build_session(options)) - # there's no type annotation on requests.Session, so it's - # automatically ContextManager[Any] and self._session becomes Any, - # then https://github.com/python/mypy/issues/7696 kicks in - assert self._session is not None - return self._session - - def _build_session( - self, - options: Values, - retries: int | None = None, - timeout: int | None = None, - ) -> PipSession: - from pip._internal.network.session import PipSession - - cache_dir = options.cache_dir - assert not cache_dir or os.path.isabs(cache_dir) - - if "legacy-certs" not in options.deprecated_features_enabled: - ssl_context = _create_truststore_ssl_context() - else: - ssl_context = None - - session = PipSession( - cache=os.path.join(cache_dir, "http-v2") if cache_dir else None, - retries=retries if retries is not None else options.retries, - trusted_hosts=options.trusted_hosts, - index_urls=self._get_index_urls(options), - ssl_context=ssl_context, - ) - - # Handle custom ca-bundles from the user - if options.cert: - session.verify = options.cert - - # Handle SSL client certificate - if options.client_cert: - session.cert = options.client_cert - - # Handle timeouts - if options.timeout or timeout: - session.timeout = timeout if timeout is not None else options.timeout - - # Handle configured proxies - if options.proxy: - session.proxies = { - "http": options.proxy, - "https": options.proxy, - } - session.trust_env = False - session.pip_proxy = options.proxy - - # Determine if we can prompt the user for authentication or not - session.auth.prompting = not options.no_input - session.auth.keyring_provider = options.keyring_provider - - return session - - -def _pip_self_version_check(session: PipSession, options: Values) -> None: - from pip._internal.self_outdated_check import pip_self_version_check as check - - check(session, options) - - -class IndexGroupCommand(Command, SessionCommandMixin): - """ - Abstract base class for commands with the index_group options. - - This also corresponds to the commands that permit the pip version check. - """ - - def handle_pip_version_check(self, options: Values) -> None: - """ - Do the pip version check if not disabled. - - This overrides the default behavior of not doing the check. - """ - # Make sure the index_group options are present. - assert hasattr(options, "no_index") - - if options.disable_pip_version_check or options.no_index: - return - - try: - # Otherwise, check if we're using the latest version of pip available. - session = self._build_session( - options, - retries=0, - timeout=min(5, options.timeout), - ) - with session: - _pip_self_version_check(session, options) - except Exception: - logger.warning("There was an error checking the latest version of pip.") - logger.debug("See below for error", exc_info=True) diff --git a/venv1/Lib/site-packages/pip/_internal/cli/main.py b/venv1/Lib/site-packages/pip/_internal/cli/main.py index 9a161fd1..7e061f5b 100644 --- a/venv1/Lib/site-packages/pip/_internal/cli/main.py +++ b/venv1/Lib/site-packages/pip/_internal/cli/main.py @@ -1,12 +1,11 @@ -"""Primary application entrypoint.""" - -from __future__ import annotations - +"""Primary application entrypoint. +""" import locale import logging import os import sys import warnings +from typing import List, Optional from pip._internal.cli.autocompletion import autocomplete from pip._internal.cli.main_parser import parse_command @@ -44,7 +43,7 @@ # main, this should not be an issue in practice. -def main(args: list[str] | None = None) -> int: +def main(args: Optional[List[str]] = None) -> int: if args is None: args = sys.argv[1:] diff --git a/venv1/Lib/site-packages/pip/_internal/cli/main_parser.py b/venv1/Lib/site-packages/pip/_internal/cli/main_parser.py index 5ce9f5a0..5ade356b 100644 --- a/venv1/Lib/site-packages/pip/_internal/cli/main_parser.py +++ b/venv1/Lib/site-packages/pip/_internal/cli/main_parser.py @@ -1,10 +1,10 @@ -"""A single place for constructing and exposing the main parser""" - -from __future__ import annotations +"""A single place for constructing and exposing the main parser +""" import os import subprocess import sys +from typing import List, Optional, Tuple from pip._internal.build_env import get_runnable_pip from pip._internal.cli import cmdoptions @@ -47,7 +47,7 @@ def create_main_parser() -> ConfigOptionParser: return parser -def identify_python_interpreter(python: str) -> str | None: +def identify_python_interpreter(python: str) -> Optional[str]: # If the named file exists, use it. # If it's a directory, assume it's a virtual environment and # look for the environment's Python executable. @@ -66,7 +66,7 @@ def identify_python_interpreter(python: str) -> str | None: return None -def parse_command(args: list[str]) -> tuple[str, list[str]]: +def parse_command(args: List[str]) -> Tuple[str, List[str]]: parser = create_main_parser() # Note: parser calls disable_interspersed_args(), so the result of this diff --git a/venv1/Lib/site-packages/pip/_internal/cli/parser.py b/venv1/Lib/site-packages/pip/_internal/cli/parser.py index 3905a91f..c762cf27 100644 --- a/venv1/Lib/site-packages/pip/_internal/cli/parser.py +++ b/venv1/Lib/site-packages/pip/_internal/cli/parser.py @@ -1,15 +1,12 @@ """Base option parser setup""" -from __future__ import annotations - import logging import optparse import shutil import sys import textwrap -from collections.abc import Generator from contextlib import suppress -from typing import Any, NoReturn +from typing import Any, Dict, Generator, List, Tuple from pip._internal.cli.status_codes import UNKNOWN_ERROR from pip._internal.configuration import Configuration, ConfigurationError @@ -70,7 +67,7 @@ def format_usage(self, usage: str) -> str: msg = "\nUsage: {}\n".format(self.indent_lines(textwrap.dedent(usage), " ")) return msg - def format_description(self, description: str | None) -> str: + def format_description(self, description: str) -> str: # leave full control over description to us if description: if hasattr(self.parser, "main"): @@ -88,7 +85,7 @@ def format_description(self, description: str | None) -> str: else: return "" - def format_epilog(self, epilog: str | None) -> str: + def format_epilog(self, epilog: str) -> str: # leave full control over epilog to us if epilog: return epilog @@ -145,7 +142,7 @@ def insert_option_group( return group @property - def option_list_all(self) -> list[optparse.Option]: + def option_list_all(self) -> List[optparse.Option]: """Get a list of all options, including those in option groups.""" res = self.option_list[:] for i in self.option_groups: @@ -180,34 +177,33 @@ def check_default(self, option: optparse.Option, key: str, val: Any) -> Any: def _get_ordered_configuration_items( self, - ) -> Generator[tuple[str, Any], None, None]: + ) -> Generator[Tuple[str, Any], None, None]: # Configuration gives keys in an unordered manner. Order them. override_order = ["global", self.name, ":env:"] # Pool the options into different groups - section_items: dict[str, list[tuple[str, Any]]] = { + section_items: Dict[str, List[Tuple[str, Any]]] = { name: [] for name in override_order } + for section_key, val in self.config.items(): + # ignore empty values + if not val: + logger.debug( + "Ignoring configuration key '%s' as it's value is empty.", + section_key, + ) + continue - for _, value in self.config.items(): # noqa: PERF102 - for section_key, val in value.items(): - # ignore empty values - if not val: - logger.debug( - "Ignoring configuration key '%s' as its value is empty.", - section_key, - ) - continue - - section, key = section_key.split(".", 1) - if section in override_order: - section_items[section].append((key, val)) + section, key = section_key.split(".", 1) + if section in override_order: + section_items[section].append((key, val)) # Yield each group in their override order for section in override_order: - yield from section_items[section] + for key, val in section_items[section]: + yield key, val - def _update_defaults(self, defaults: dict[str, Any]) -> dict[str, Any]: + def _update_defaults(self, defaults: Dict[str, Any]) -> Dict[str, Any]: """Updates the given defaults with values from the config files and the environ. Does a little special handling for certain types of options (lists).""" @@ -233,9 +229,9 @@ def _update_defaults(self, defaults: dict[str, Any]) -> dict[str, Any]: val = strtobool(val) except ValueError: self.error( - f"{val} is not a valid value for {key} option, " + "{} is not a valid value for {} option, " # noqa "please specify a boolean value like yes/no, " - "true/false or 1/0 instead." + "true/false or 1/0 instead.".format(val, key) ) elif option.action == "count": with suppress(ValueError): @@ -244,10 +240,10 @@ def _update_defaults(self, defaults: dict[str, Any]) -> dict[str, Any]: val = int(val) if not isinstance(val, int) or val < 0: self.error( - f"{val} is not a valid value for {key} option, " + "{} is not a valid value for {} option, " # noqa "please instead specify either a non-negative integer " "or a boolean value like yes/no or false/true " - "which is equivalent to 1/0." + "which is equivalent to 1/0.".format(val, key) ) elif option.action == "append": val = val.split() @@ -293,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) -> NoReturn: + def error(self, msg: str) -> None: self.print_usage(sys.stderr) self.exit(UNKNOWN_ERROR, f"{msg}\n") diff --git a/venv1/Lib/site-packages/pip/_internal/cli/progress_bars.py b/venv1/Lib/site-packages/pip/_internal/cli/progress_bars.py index af1bb6a5..0ad14031 100644 --- a/venv1/Lib/site-packages/pip/_internal/cli/progress_bars.py +++ b/venv1/Lib/site-packages/pip/_internal/cli/progress_bars.py @@ -1,15 +1,10 @@ -from __future__ import annotations - import functools -import sys -from collections.abc import Generator, Iterable, Iterator -from typing import Callable, Literal, TypeVar +from typing import Callable, Generator, Iterable, Iterator, Optional, Tuple from pip._vendor.rich.progress import ( BarColumn, DownloadColumn, FileSizeColumn, - MofNCompleteColumn, Progress, ProgressColumn, SpinnerColumn, @@ -19,27 +14,22 @@ TransferSpeedColumn, ) -from pip._internal.cli.spinners import RateLimiter -from pip._internal.req.req_install import InstallRequirement -from pip._internal.utils.logging import get_console, get_indentation +from pip._internal.utils.logging import get_indentation -T = TypeVar("T") -ProgressRenderer = Callable[[Iterable[T]], Iterator[T]] -BarType = Literal["on", "off", "raw"] +DownloadProgressRenderer = Callable[[Iterable[bytes]], Iterator[bytes]] -def _rich_download_progress_bar( +def _rich_progress_bar( iterable: Iterable[bytes], *, - bar_type: BarType, - size: int | None, - initial_progress: int | None = None, + bar_type: str, + size: int, ) -> Generator[bytes, None, None]: assert bar_type == "on", "This should only be used in the default mode." if not size: total = float("inf") - columns: tuple[ProgressColumn, ...] = ( + columns: Tuple[ProgressColumn, ...] = ( TextColumn("[progress.description]{task.description}"), SpinnerColumn("line", speed=1.5), FileSizeColumn(), @@ -53,99 +43,26 @@ def _rich_download_progress_bar( BarColumn(), DownloadColumn(), TransferSpeedColumn(), - TextColumn("{task.fields[time_description]}"), - TimeRemainingColumn(elapsed_when_finished=True), + TextColumn("eta"), + TimeRemainingColumn(), ) - progress = Progress(*columns, refresh_per_second=5) - task_id = progress.add_task( - " " * (get_indentation() + 2), total=total, time_description="eta" - ) - if initial_progress is not None: - progress.update(task_id, advance=initial_progress) + progress = Progress(*columns, refresh_per_second=30) + task_id = progress.add_task(" " * (get_indentation() + 2), total=total) with progress: for chunk in iterable: yield chunk progress.update(task_id, advance=len(chunk)) - progress.update(task_id, time_description="") - - -def _rich_install_progress_bar( - iterable: Iterable[InstallRequirement], *, total: int -) -> Iterator[InstallRequirement]: - columns = ( - TextColumn("{task.fields[indent]}"), - BarColumn(), - MofNCompleteColumn(), - TextColumn("{task.description}"), - ) - console = get_console() - - bar = Progress(*columns, refresh_per_second=6, console=console, transient=True) - # Hiding the progress bar at initialization forces a refresh cycle to occur - # until the bar appears, avoiding very short flashes. - task = bar.add_task("", total=total, indent=" " * get_indentation(), visible=False) - with bar: - for req in iterable: - bar.update(task, description=rf"\[{req.name}]", visible=True) - yield req - bar.advance(task) - - -def _raw_progress_bar( - iterable: Iterable[bytes], - *, - size: int | None, - initial_progress: int | None = None, -) -> Generator[bytes, None, None]: - def write_progress(current: int, total: int) -> None: - sys.stdout.write(f"Progress {current} of {total}\n") - sys.stdout.flush() - - current = initial_progress or 0 - total = size or 0 - rate_limiter = RateLimiter(0.25) - - write_progress(current, total) - for chunk in iterable: - current += len(chunk) - if rate_limiter.ready() or current == total: - write_progress(current, total) - rate_limiter.reset() - yield chunk def get_download_progress_renderer( - *, bar_type: BarType, size: int | None = None, initial_progress: int | None = None -) -> ProgressRenderer[bytes]: + *, bar_type: str, size: Optional[int] = None +) -> DownloadProgressRenderer: """Get an object that can be used to render the download progress. Returns a callable, that takes an iterable to "wrap". """ if bar_type == "on": - return functools.partial( - _rich_download_progress_bar, - bar_type=bar_type, - size=size, - initial_progress=initial_progress, - ) - elif bar_type == "raw": - return functools.partial( - _raw_progress_bar, - size=size, - initial_progress=initial_progress, - ) + return functools.partial(_rich_progress_bar, bar_type=bar_type, size=size) else: return iter # no-op, when passed an iterator - - -def get_install_progress_renderer( - *, bar_type: BarType, total: int -) -> ProgressRenderer[InstallRequirement]: - """Get an object that can be used to render the install progress. - Returns a callable, that takes an iterable to "wrap". - """ - if bar_type == "on": - return functools.partial(_rich_install_progress_bar, total=total) - else: - return iter diff --git a/venv1/Lib/site-packages/pip/_internal/cli/req_command.py b/venv1/Lib/site-packages/pip/_internal/cli/req_command.py index f6d7f81e..c2f4e38b 100644 --- a/venv1/Lib/site-packages/pip/_internal/cli/req_command.py +++ b/venv1/Lib/site-packages/pip/_internal/cli/req_command.py @@ -1,23 +1,21 @@ -"""Contains the RequirementCommand base class. +"""Contains the Command base classes that depend on PipSession. -This class is in a separate module so the commands that do not always -need PackageFinder capability don't unnecessarily import the +The classes in this module are in a separate module so the commands not +needing download / PackageFinder capability don't unnecessarily import the PackageFinder machinery and all its vendored dependencies, etc. """ -from __future__ import annotations - import logging import os +import sys from functools import partial from optparse import Values -from typing import Any, Callable, TypeVar +from typing import TYPE_CHECKING, Any, List, Optional, Tuple -from pip._internal.build_env import SubprocessBuildEnvironmentInstaller from pip._internal.cache import WheelCache from pip._internal.cli import cmdoptions -from pip._internal.cli.index_command import IndexGroupCommand -from pip._internal.cli.index_command import SessionCommandMixin as SessionCommandMixin +from pip._internal.cli.base_command import Command +from pip._internal.cli.command_context import CommandContextMixIn from pip._internal.exceptions import CommandError, PreviousBuildDirError from pip._internal.index.collector import LinkCollector from pip._internal.index.package_finder import PackageFinder @@ -32,27 +30,165 @@ install_req_from_parsed_requirement, install_req_from_req_string, ) -from pip._internal.req.req_dependency_group import parse_dependency_groups from pip._internal.req.req_file import parse_requirements from pip._internal.req.req_install import InstallRequirement from pip._internal.resolution.base import BaseResolver +from pip._internal.self_outdated_check import pip_self_version_check from pip._internal.utils.temp_dir import ( TempDirectory, TempDirectoryTypeRegistry, tempdir_kinds, ) +from pip._internal.utils.virtualenv import running_under_virtualenv + +if TYPE_CHECKING: + from ssl import SSLContext logger = logging.getLogger(__name__) -def should_ignore_regular_constraints(options: Values) -> bool: +def _create_truststore_ssl_context() -> Optional["SSLContext"]: + if sys.version_info < (3, 10): + raise CommandError("The truststore feature is only available for Python 3.10+") + + try: + import ssl + except ImportError: + logger.warning("Disabling truststore since ssl support is missing") + return None + + try: + import truststore + except ImportError: + raise CommandError( + "To use the truststore feature, 'truststore' must be installed into " + "pip's current environment." + ) + + return truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + + +class SessionCommandMixin(CommandContextMixIn): + + """ + A class mixin for command classes needing _build_session(). + """ + + def __init__(self) -> None: + super().__init__() + self._session: Optional[PipSession] = None + + @classmethod + def _get_index_urls(cls, options: Values) -> Optional[List[str]]: + """Return a list of index urls from user-provided options.""" + index_urls = [] + if not getattr(options, "no_index", False): + url = getattr(options, "index_url", None) + if url: + index_urls.append(url) + urls = getattr(options, "extra_index_urls", None) + if urls: + index_urls.extend(urls) + # Return None rather than an empty list + return index_urls or None + + def get_default_session(self, options: Values) -> PipSession: + """Get a default-managed session.""" + if self._session is None: + self._session = self.enter_context(self._build_session(options)) + # there's no type annotation on requests.Session, so it's + # automatically ContextManager[Any] and self._session becomes Any, + # then https://github.com/python/mypy/issues/7696 kicks in + assert self._session is not None + return self._session + + def _build_session( + self, + options: Values, + retries: Optional[int] = None, + timeout: Optional[int] = None, + fallback_to_certifi: bool = False, + ) -> PipSession: + cache_dir = options.cache_dir + assert not cache_dir or os.path.isabs(cache_dir) + + if "truststore" in options.features_enabled: + try: + ssl_context = _create_truststore_ssl_context() + except Exception: + if not fallback_to_certifi: + raise + ssl_context = None + else: + ssl_context = None + + session = PipSession( + cache=os.path.join(cache_dir, "http") if cache_dir else None, + retries=retries if retries is not None else options.retries, + trusted_hosts=options.trusted_hosts, + index_urls=self._get_index_urls(options), + ssl_context=ssl_context, + ) + + # Handle custom ca-bundles from the user + if options.cert: + session.verify = options.cert + + # Handle SSL client certificate + if options.client_cert: + session.cert = options.client_cert + + # Handle timeouts + if options.timeout or timeout: + session.timeout = timeout if timeout is not None else options.timeout + + # Handle configured proxies + if options.proxy: + session.proxies = { + "http": options.proxy, + "https": options.proxy, + } + + # Determine if we can prompt the user for authentication or not + session.auth.prompting = not options.no_input + session.auth.keyring_provider = options.keyring_provider + + return session + + +class IndexGroupCommand(Command, SessionCommandMixin): + """ - Check if regular constraints should be ignored because - we are in a isolated build process and build constraints - feature is enabled but no build constraints were passed. + Abstract base class for commands with the index_group options. + + This also corresponds to the commands that permit the pip version check. """ - return os.environ.get("_PIP_IN_BUILD_IGNORE_CONSTRAINTS") == "1" + def handle_pip_version_check(self, options: Values) -> None: + """ + Do the pip version check if not disabled. + + This overrides the default behavior of not doing the check. + """ + # Make sure the index_group options are present. + assert hasattr(options, "no_index") + + if options.disable_pip_version_check or options.no_index: + return + + # Otherwise, check if we're using the latest version of pip available. + session = self._build_session( + options, + retries=0, + timeout=min(5, options.timeout), + # This is set to ensure the function does not fail when truststore is + # specified in use-feature but cannot be loaded. This usually raises a + # CommandError and shows a nice user-facing error, but this function is not + # called in that try-except block. + fallback_to_certifi=True, + ) + with session: + pip_self_version_check(session, options) KEEPABLE_TEMPDIR_TYPES = [ @@ -62,12 +198,37 @@ def should_ignore_regular_constraints(options: Values) -> bool: ] -_CommandT = TypeVar("_CommandT", bound="RequirementCommand") +def warn_if_run_as_root() -> None: + """Output a warning for sudo users on Unix. - -def with_cleanup( - func: Callable[[_CommandT, Values, list[str]], int], -) -> Callable[[_CommandT, Values, list[str]], int]: + In a virtual environment, sudo pip still writes to virtualenv. + On Windows, users may run pip as Administrator without issues. + This warning only applies to Unix root users outside of virtualenv. + """ + if running_under_virtualenv(): + return + if not hasattr(os, "getuid"): + return + # On Windows, there are no "system managed" Python packages. Installing as + # Administrator via pip is the correct way of updating system environments. + # + # We choose sys.platform over utils.compat.WINDOWS here to enable Mypy platform + # checks: https://mypy.readthedocs.io/en/stable/common_issues.html + if sys.platform == "win32" or sys.platform == "cygwin": + return + + if os.getuid() != 0: + return + + logger.warning( + "Running pip as the 'root' user can result in broken permissions and " + "conflicting behaviour with the system package manager. " + "It is recommended to use a virtual environment instead: " + "https://pip.pypa.io/warnings/venv" + ) + + +def with_cleanup(func: Any) -> Any: """Decorator for common logic related to managing temporary directories. """ @@ -76,7 +237,9 @@ def configure_tempdir_registry(registry: TempDirectoryTypeRegistry) -> None: for t in KEEPABLE_TEMPDIR_TYPES: registry.set_delete(t, False) - def wrapper(self: _CommandT, options: Values, args: list[str]) -> int: + def wrapper( + self: RequirementCommand, options: Values, args: List[Any] + ) -> Optional[int]: assert self.tempdir_registry is not None if options.no_clean: configure_tempdir_registry(self.tempdir_registry) @@ -97,7 +260,6 @@ class RequirementCommand(IndexGroupCommand): def __init__(self, *args: Any, **kw: Any) -> None: super().__init__(*args, **kw) - self.cmd_opts.add_option(cmdoptions.dependency_groups()) self.cmd_opts.add_option(cmdoptions.no_clean()) @staticmethod @@ -106,7 +268,7 @@ def determine_resolver_variant(options: Values) -> str: if "legacy-resolver" in options.deprecated_features_enabled: return "legacy" - return "resolvelib" + return "2020-resolver" @classmethod def make_requirement_preparer( @@ -117,7 +279,7 @@ def make_requirement_preparer( session: PipSession, finder: PackageFinder, use_user_site: bool, - download_dir: str | None = None, + download_dir: Optional[str] = None, verbosity: int = 0, ) -> RequirementPreparer: """ @@ -125,10 +287,9 @@ def make_requirement_preparer( """ temp_build_dir_path = temp_build_dir.path assert temp_build_dir_path is not None - legacy_resolver = False resolver_variant = cls.determine_resolver_variant(options) - if resolver_variant == "resolvelib": + if resolver_variant == "2020-resolver": lazy_wheel = "fast-deps" in options.features_enabled if lazy_wheel: logger.warning( @@ -139,29 +300,17 @@ def make_requirement_preparer( "production." ) else: - legacy_resolver = True lazy_wheel = False if "fast-deps" in options.features_enabled: logger.warning( "fast-deps has no effect when used with the legacy resolver." ) - # Handle build constraints - build_constraints = getattr(options, "build_constraints", []) - build_constraint_feature_enabled = ( - "build-constraint" in options.features_enabled - ) - return RequirementPreparer( build_dir=temp_build_dir_path, src_dir=options.src_dir, download_dir=download_dir, build_isolation=options.build_isolation, - build_isolation_installer=SubprocessBuildEnvironmentInstaller( - finder, - build_constraints=build_constraints, - build_constraint_feature_enabled=build_constraint_feature_enabled, - ), check_build_deps=options.check_build_deps, build_tracker=build_tracker, session=session, @@ -171,8 +320,6 @@ def make_requirement_preparer( use_user_site=use_user_site, lazy_wheel=lazy_wheel, verbosity=verbosity, - legacy_resolver=legacy_resolver, - resume_retries=options.resume_retries, ) @classmethod @@ -181,13 +328,14 @@ def make_resolver( preparer: RequirementPreparer, finder: PackageFinder, options: Values, - wheel_cache: WheelCache | None = None, + wheel_cache: Optional[WheelCache] = None, use_user_site: bool = False, ignore_installed: bool = True, ignore_requires_python: bool = False, force_reinstall: bool = False, upgrade_strategy: str = "to-satisfy-only", - py_version_info: tuple[int, ...] | None = None, + use_pep517: Optional[bool] = None, + py_version_info: Optional[Tuple[int, ...]] = None, ) -> BaseResolver: """ Create a Resolver instance for the given parameters. @@ -195,12 +343,13 @@ def make_resolver( make_install_req = partial( install_req_from_req_string, isolated=options.isolated_mode, + use_pep517=use_pep517, ) resolver_variant = cls.determine_resolver_variant(options) # The long import name and duplicated invocation is needed to convince # Mypy into correctly typechecking. Otherwise it would complain the # "Resolver" class being redefined. - if resolver_variant == "resolvelib": + if resolver_variant == "2020-resolver": import pip._internal.resolution.resolvelib.resolver return pip._internal.resolution.resolvelib.resolver.Resolver( @@ -234,56 +383,47 @@ def make_resolver( def get_requirements( self, - args: list[str], + args: List[str], options: Values, finder: PackageFinder, session: PipSession, - ) -> list[InstallRequirement]: + ) -> List[InstallRequirement]: """ Parse command-line arguments into the corresponding requirements. """ - requirements: list[InstallRequirement] = [] - - if not should_ignore_regular_constraints(options): - for filename in options.constraints: - for parsed_req in parse_requirements( - filename, - constraint=True, - finder=finder, - options=options, - session=session, - ): - req_to_add = install_req_from_parsed_requirement( - parsed_req, - isolated=options.isolated_mode, - user_supplied=False, - ) - requirements.append(req_to_add) + requirements: List[InstallRequirement] = [] + for filename in options.constraints: + for parsed_req in parse_requirements( + filename, + constraint=True, + finder=finder, + options=options, + session=session, + ): + req_to_add = install_req_from_parsed_requirement( + parsed_req, + isolated=options.isolated_mode, + user_supplied=False, + ) + requirements.append(req_to_add) for req in args: req_to_add = install_req_from_line( req, comes_from=None, isolated=options.isolated_mode, + use_pep517=options.use_pep517, user_supplied=True, config_settings=getattr(options, "config_settings", None), ) requirements.append(req_to_add) - if options.dependency_groups: - for req in parse_dependency_groups(options.dependency_groups): - req_to_add = install_req_from_req_string( - req, - isolated=options.isolated_mode, - user_supplied=True, - ) - requirements.append(req_to_add) - for req in options.editables: req_to_add = install_req_from_editable( req, user_supplied=True, isolated=options.isolated_mode, + use_pep517=options.use_pep517, config_settings=getattr(options, "config_settings", None), ) requirements.append(req_to_add) @@ -296,12 +436,11 @@ def get_requirements( req_to_add = install_req_from_parsed_requirement( parsed_req, isolated=options.isolated_mode, + use_pep517=options.use_pep517, user_supplied=True, - config_settings=( - parsed_req.options.get("config_settings") - if parsed_req.options - else None - ), + config_settings=parsed_req.options.get("config_settings") + if parsed_req.options + else None, ) requirements.append(req_to_add) @@ -309,12 +448,7 @@ def get_requirements( if any(req.has_hash_options for req in requirements): options.require_hashes = True - if not ( - args - or options.editables - or options.requirements - or options.dependency_groups - ): + if not (args or options.editables or options.requirements): opts = {"name": self.name} if options.find_links: raise CommandError( @@ -346,8 +480,8 @@ def _build_package_finder( self, options: Values, session: PipSession, - target_python: TargetPython | None = None, - ignore_requires_python: bool | None = None, + target_python: Optional[TargetPython] = None, + ignore_requires_python: Optional[bool] = None, ) -> PackageFinder: """ Create a package finder appropriate to this requirement command. diff --git a/venv1/Lib/site-packages/pip/_internal/cli/spinners.py b/venv1/Lib/site-packages/pip/_internal/cli/spinners.py index 58aad285..cf2b976f 100644 --- a/venv1/Lib/site-packages/pip/_internal/cli/spinners.py +++ b/venv1/Lib/site-packages/pip/_internal/cli/spinners.py @@ -1,31 +1,15 @@ -from __future__ import annotations - import contextlib import itertools import logging import sys import time -from collections.abc import Generator -from typing import IO, Final - -from pip._vendor.rich.console import ( - Console, - ConsoleOptions, - RenderableType, - RenderResult, -) -from pip._vendor.rich.live import Live -from pip._vendor.rich.measure import Measurement -from pip._vendor.rich.text import Text +from typing import IO, Generator, Optional from pip._internal.utils.compat import WINDOWS -from pip._internal.utils.logging import get_console, get_indentation +from pip._internal.utils.logging import get_indentation logger = logging.getLogger(__name__) -SPINNER_CHARS: Final = r"-\|/" -SPINS_PER_SECOND: Final = 8 - class SpinnerInterface: def spin(self) -> None: @@ -39,10 +23,10 @@ class InteractiveSpinner(SpinnerInterface): def __init__( self, message: str, - file: IO[str] | None = None, - spin_chars: str = SPINNER_CHARS, + file: Optional[IO[str]] = None, + spin_chars: str = "-\\|/", # Empirically, 8 updates/second looks nice - min_update_interval_seconds: float = 1 / SPINS_PER_SECOND, + min_update_interval_seconds: float = 0.125, ): self._message = message if file is None: @@ -152,66 +136,6 @@ def open_spinner(message: str) -> Generator[SpinnerInterface, None, None]: spinner.finish("done") -class _PipRichSpinner: - """ - Custom rich spinner that matches the style of the legacy spinners. - - (*) Updates will be handled in a background thread by a rich live panel - which will call render() automatically at the appropriate time. - """ - - def __init__(self, label: str) -> None: - self.label = label - self._spin_cycle = itertools.cycle(SPINNER_CHARS) - self._spinner_text = "" - self._finished = False - self._indent = get_indentation() * " " - - def __rich_console__( - self, console: Console, options: ConsoleOptions - ) -> RenderResult: - yield self.render() - - def __rich_measure__( - self, console: Console, options: ConsoleOptions - ) -> Measurement: - text = self.render() - return Measurement.get(console, options, text) - - def render(self) -> RenderableType: - if not self._finished: - self._spinner_text = next(self._spin_cycle) - - return Text.assemble(self._indent, self.label, " ... ", self._spinner_text) - - def finish(self, status: str) -> None: - """Stop spinning and set a final status message.""" - self._spinner_text = status - self._finished = True - - -@contextlib.contextmanager -def open_rich_spinner(label: str, console: Console | None = None) -> Generator[None]: - if not logger.isEnabledFor(logging.INFO): - # Don't show spinner if --quiet is given. - yield - return - - console = console or get_console() - spinner = _PipRichSpinner(label) - with Live(spinner, refresh_per_second=SPINS_PER_SECOND, console=console): - try: - yield - except KeyboardInterrupt: - spinner.finish("canceled") - raise - except Exception: - spinner.finish("error") - raise - else: - spinner.finish("done") - - HIDE_CURSOR = "\x1b[?25l" SHOW_CURSOR = "\x1b[?25h" diff --git a/venv1/Lib/site-packages/pip/_internal/commands/__init__.py b/venv1/Lib/site-packages/pip/_internal/commands/__init__.py index bedeca9e..858a4101 100644 --- a/venv1/Lib/site-packages/pip/_internal/commands/__init__.py +++ b/venv1/Lib/site-packages/pip/_internal/commands/__init__.py @@ -2,11 +2,9 @@ Package containing all pip commands """ -from __future__ import annotations - import importlib from collections import namedtuple -from typing import Any +from typing import Any, Dict, Optional from pip._internal.cli.base_command import Command @@ -19,17 +17,12 @@ # Even though the module path starts with the same "pip._internal.commands" # prefix, the full path makes testing easier (specifically when modifying # `commands_dict` in test setup / teardown). -commands_dict: dict[str, CommandInfo] = { +commands_dict: Dict[str, CommandInfo] = { "install": CommandInfo( "pip._internal.commands.install", "InstallCommand", "Install packages.", ), - "lock": CommandInfo( - "pip._internal.commands.lock", - "LockCommand", - "Generate a lock file.", - ), "download": CommandInfo( "pip._internal.commands.download", "DownloadCommand", @@ -125,7 +118,7 @@ def create_command(name: str, **kwargs: Any) -> Command: return command -def get_similar_commands(name: str) -> str | None: +def get_similar_commands(name: str) -> Optional[str]: """Command name auto-correct.""" from difflib import get_close_matches diff --git a/venv1/Lib/site-packages/pip/_internal/commands/cache.py b/venv1/Lib/site-packages/pip/_internal/commands/cache.py index c8e7aede..e96d2b49 100644 --- a/venv1/Lib/site-packages/pip/_internal/commands/cache.py +++ b/venv1/Lib/site-packages/pip/_internal/commands/cache.py @@ -1,14 +1,13 @@ import os import textwrap from optparse import Values -from typing import Callable +from typing import Any, List +import pip._internal.utils.filesystem as filesystem from pip._internal.cli.base_command import Command from pip._internal.cli.status_codes import ERROR, SUCCESS from pip._internal.exceptions import CommandError, PipError -from pip._internal.utils import filesystem from pip._internal.utils.logging import getLogger -from pip._internal.utils.misc import format_size logger = getLogger(__name__) @@ -49,8 +48,8 @@ def add_options(self) -> None: self.parser.insert_option_group(0, self.cmd_opts) - def handler_map(self) -> dict[str, Callable[[Values, list[str]], None]]: - return { + def run(self, options: Values, args: List[str]) -> int: + handlers = { "dir": self.get_cache_dir, "info": self.get_cache_info, "list": self.list_cache_items, @@ -58,18 +57,15 @@ def handler_map(self) -> dict[str, Callable[[Values, list[str]], None]]: "purge": self.purge_cache, } - def run(self, options: Values, args: list[str]) -> int: - handler_map = self.handler_map() - if not options.cache_dir: logger.error("pip cache commands can not function since cache is disabled.") return ERROR # Determine action - if not args or args[0] not in handler_map: + if not args or args[0] not in handlers: logger.error( "Need an action (%s) to perform.", - ", ".join(sorted(handler_map)), + ", ".join(sorted(handlers)), ) return ERROR @@ -77,50 +73,44 @@ def run(self, options: Values, args: list[str]) -> int: # Error handling happens here, not in the action-handlers. try: - handler_map[action](options, args[1:]) + handlers[action](options, args[1:]) except PipError as e: logger.error(e.args[0]) return ERROR return SUCCESS - def get_cache_dir(self, options: Values, args: list[str]) -> None: + def get_cache_dir(self, options: Values, args: List[Any]) -> None: if args: raise CommandError("Too many arguments") logger.info(options.cache_dir) - def get_cache_info(self, options: Values, args: list[str]) -> None: + def get_cache_info(self, options: Values, args: List[Any]) -> None: if args: raise CommandError("Too many arguments") num_http_files = len(self._find_http_files(options)) num_packages = len(self._find_wheels(options, "*")) - http_cache_location = self._cache_dir(options, "http-v2") - old_http_cache_location = self._cache_dir(options, "http") + http_cache_location = self._cache_dir(options, "http") wheels_cache_location = self._cache_dir(options, "wheels") - http_cache_size = filesystem.format_size( - filesystem.directory_size(http_cache_location) - + filesystem.directory_size(old_http_cache_location) - ) + http_cache_size = filesystem.format_directory_size(http_cache_location) wheels_cache_size = filesystem.format_directory_size(wheels_cache_location) message = ( textwrap.dedent( """ - Package index page cache location (pip v23.3+): {http_cache_location} - Package index page cache location (older pips): {old_http_cache_location} + Package index page cache location: {http_cache_location} Package index page cache size: {http_cache_size} Number of HTTP files: {num_http_files} Locally built wheels location: {wheels_cache_location} Locally built wheels size: {wheels_cache_size} Number of locally built wheels: {package_count} - """ # noqa: E501 + """ ) .format( http_cache_location=http_cache_location, - old_http_cache_location=old_http_cache_location, http_cache_size=http_cache_size, num_http_files=num_http_files, wheels_cache_location=wheels_cache_location, @@ -132,7 +122,7 @@ def get_cache_info(self, options: Values, args: list[str]) -> None: logger.info(message) - def list_cache_items(self, options: Values, args: list[str]) -> None: + def list_cache_items(self, options: Values, args: List[Any]) -> None: if len(args) > 1: raise CommandError("Too many arguments") @@ -147,7 +137,7 @@ def list_cache_items(self, options: Values, args: list[str]) -> None: else: self.format_for_abspath(files) - def format_for_human(self, files: list[str]) -> None: + def format_for_human(self, files: List[str]) -> None: if not files: logger.info("No locally built wheels cached.") return @@ -160,11 +150,17 @@ def format_for_human(self, files: list[str]) -> None: logger.info("Cache contents:\n") logger.info("\n".join(sorted(results))) - def format_for_abspath(self, files: list[str]) -> None: - if files: - logger.info("\n".join(sorted(files))) + def format_for_abspath(self, files: List[str]) -> None: + if not files: + return - def remove_cache_items(self, options: Values, args: list[str]) -> None: + results = [] + for filename in files: + results.append(filename) + + logger.info("\n".join(sorted(results))) + + def remove_cache_items(self, options: Values, args: List[Any]) -> None: if len(args) > 1: raise CommandError("Too many arguments") @@ -179,19 +175,17 @@ def remove_cache_items(self, options: Values, args: list[str]) -> None: files += self._find_http_files(options) else: # Add the pattern to the log message - no_matching_msg += f' for pattern "{args[0]}"' + no_matching_msg += ' for pattern "{}"'.format(args[0]) if not files: logger.warning(no_matching_msg) - bytes_removed = 0 for filename in files: - bytes_removed += os.stat(filename).st_size os.unlink(filename) logger.verbose("Removed %s", filename) - logger.info("Files removed: %s (%s)", len(files), format_size(bytes_removed)) + logger.info("Files removed: %s", len(files)) - def purge_cache(self, options: Values, args: list[str]) -> None: + def purge_cache(self, options: Values, args: List[Any]) -> None: if args: raise CommandError("Too many arguments") @@ -200,14 +194,11 @@ def purge_cache(self, options: Values, args: list[str]) -> None: def _cache_dir(self, options: Values, subdir: str) -> str: return os.path.join(options.cache_dir, subdir) - def _find_http_files(self, options: Values) -> list[str]: - old_http_dir = self._cache_dir(options, "http") - new_http_dir = self._cache_dir(options, "http-v2") - return filesystem.find_files(old_http_dir, "*") + filesystem.find_files( - new_http_dir, "*" - ) + def _find_http_files(self, options: Values) -> List[str]: + http_dir = self._cache_dir(options, "http") + return filesystem.find_files(http_dir, "*") - def _find_wheels(self, options: Values, pattern: str) -> list[str]: + def _find_wheels(self, options: Values, pattern: str) -> List[str]: wheel_dir = self._cache_dir(options, "wheels") # The wheel filename format, as specified in PEP 427, is: diff --git a/venv1/Lib/site-packages/pip/_internal/commands/check.py b/venv1/Lib/site-packages/pip/_internal/commands/check.py index 516757ee..584df9f5 100644 --- a/venv1/Lib/site-packages/pip/_internal/commands/check.py +++ b/venv1/Lib/site-packages/pip/_internal/commands/check.py @@ -1,15 +1,13 @@ import logging from optparse import Values +from typing import List from pip._internal.cli.base_command import Command from pip._internal.cli.status_codes import ERROR, SUCCESS -from pip._internal.metadata import get_default_environment from pip._internal.operations.check import ( check_package_set, - check_unsupported, create_package_set_from_installed, ) -from pip._internal.utils.compatibility_tags import get_supported from pip._internal.utils.misc import write_output logger = logging.getLogger(__name__) @@ -18,19 +16,12 @@ class CheckCommand(Command): """Verify installed packages have compatible dependencies.""" - ignore_require_venv = True usage = """ %prog [options]""" - def run(self, options: Values, args: list[str]) -> int: + def run(self, options: Values, args: List[str]) -> int: package_set, parsing_probs = create_package_set_from_installed() missing, conflicting = check_package_set(package_set) - unsupported = list( - check_unsupported( - get_default_environment().iter_installed_distributions(), - get_supported(), - ) - ) for project_name in missing: version = package_set[project_name].version @@ -53,13 +44,8 @@ def run(self, options: Values, args: list[str]) -> int: dep_name, dep_version, ) - for package in unsupported: - write_output( - "%s %s is not supported on this platform", - package.raw_name, - package.version, - ) - if missing or conflicting or parsing_probs or unsupported: + + if missing or conflicting or parsing_probs: return ERROR else: write_output("No broken requirements found.") diff --git a/venv1/Lib/site-packages/pip/_internal/commands/completion.py b/venv1/Lib/site-packages/pip/_internal/commands/completion.py index 6d9597bd..deaa3089 100644 --- a/venv1/Lib/site-packages/pip/_internal/commands/completion.py +++ b/venv1/Lib/site-packages/pip/_internal/commands/completion.py @@ -1,6 +1,7 @@ import sys import textwrap from optparse import Values +from typing import List from pip._internal.cli.base_command import Command from pip._internal.cli.status_codes import SUCCESS @@ -21,34 +22,24 @@ complete -o default -F _pip_completion {prog} """, "zsh": """ - #compdef -P pip[0-9.]# - __pip() {{ - compadd $( COMP_WORDS="$words[*]" \\ - COMP_CWORD=$((CURRENT-1)) \\ - PIP_AUTO_COMPLETE=1 $words[1] 2>/dev/null ) + function _pip_completion {{ + local words cword + read -Ac words + read -cn cword + reply=( $( COMP_WORDS="$words[*]" \\ + COMP_CWORD=$(( cword-1 )) \\ + PIP_AUTO_COMPLETE=1 $words[1] 2>/dev/null )) }} - if [[ $zsh_eval_context[-1] == loadautofunc ]]; then - # autoload from fpath, call function directly - __pip "$@" - else - # eval/source/. command, register function for later - compdef __pip -P 'pip[0-9.]#' - fi + compctl -K _pip_completion {prog} """, "fish": """ function __fish_complete_pip - set -lx COMP_WORDS \\ - (commandline --current-process --tokenize --cut-at-cursor) \\ - (commandline --current-token --cut-at-cursor) - set -lx COMP_CWORD (math (count $COMP_WORDS) - 1) + set -lx COMP_WORDS (commandline -o) "" + set -lx COMP_CWORD ( \\ + math (contains -i -- (commandline -t) $COMP_WORDS)-1 \\ + ) set -lx PIP_AUTO_COMPLETE 1 - set -l completions - if string match -q '2.*' $version - set completions (eval $COMP_WORDS[1]) - else - set completions ($COMP_WORDS[1]) - end - string split \\ -- $completions + string split \\ -- (eval $COMP_WORDS[1]) end complete -fa "(__fish_complete_pip)" -c {prog} """, @@ -118,7 +109,7 @@ def add_options(self) -> None: self.parser.insert_option_group(0, self.cmd_opts) - def run(self, options: Values, args: list[str]) -> int: + def run(self, options: Values, args: List[str]) -> int: """Prints the completion code of the given shell""" shells = COMPLETION_SCRIPTS.keys() shell_options = ["--" + shell for shell in sorted(shells)] diff --git a/venv1/Lib/site-packages/pip/_internal/commands/configuration.py b/venv1/Lib/site-packages/pip/_internal/commands/configuration.py index 7bcea043..84b134e4 100644 --- a/venv1/Lib/site-packages/pip/_internal/commands/configuration.py +++ b/venv1/Lib/site-packages/pip/_internal/commands/configuration.py @@ -1,10 +1,8 @@ -from __future__ import annotations - import logging import os import subprocess from optparse import Values -from typing import Any, Callable +from typing import Any, List, Optional from pip._internal.cli.base_command import Command from pip._internal.cli.status_codes import ERROR, SUCCESS @@ -95,8 +93,8 @@ def add_options(self) -> None: self.parser.insert_option_group(0, self.cmd_opts) - def handler_map(self) -> dict[str, Callable[[Values, list[str]], None]]: - return { + def run(self, options: Values, args: List[str]) -> int: + handlers = { "list": self.list_values, "edit": self.open_in_editor, "get": self.get_name, @@ -105,14 +103,11 @@ def handler_map(self) -> dict[str, Callable[[Values, list[str]], None]]: "debug": self.list_config_values, } - def run(self, options: Values, args: list[str]) -> int: - handler_map = self.handler_map() - # Determine action - if not args or args[0] not in handler_map: + if not args or args[0] not in handlers: logger.error( "Need an action (%s) to perform.", - ", ".join(sorted(handler_map)), + ", ".join(sorted(handlers)), ) return ERROR @@ -136,14 +131,14 @@ def run(self, options: Values, args: list[str]) -> int: # Error handling happens here, not in the action-handlers. try: - handler_map[action](options, args[1:]) + handlers[action](options, args[1:]) except PipError as e: logger.error(e.args[0]) return ERROR return SUCCESS - def _determine_file(self, options: Values, need_value: bool) -> Kind | None: + def _determine_file(self, options: Values, need_value: bool) -> Optional[Kind]: file_options = [ key for key, value in ( @@ -173,32 +168,31 @@ def _determine_file(self, options: Values, need_value: bool) -> Kind | None: "(--user, --site, --global) to perform." ) - def list_values(self, options: Values, args: list[str]) -> None: + def list_values(self, options: Values, args: List[str]) -> None: self._get_n_args(args, "list", n=0) for key, value in sorted(self.configuration.items()): - for key, value in sorted(value.items()): - write_output("%s=%r", key, value) + write_output("%s=%r", key, value) - def get_name(self, options: Values, args: list[str]) -> None: + def get_name(self, options: Values, args: List[str]) -> None: key = self._get_n_args(args, "get [name]", n=1) value = self.configuration.get_value(key) write_output("%s", value) - def set_name_value(self, options: Values, args: list[str]) -> None: + def set_name_value(self, options: Values, args: List[str]) -> None: key, value = self._get_n_args(args, "set [name] [value]", n=2) self.configuration.set_value(key, value) self._save_configuration() - def unset_name(self, options: Values, args: list[str]) -> None: + def unset_name(self, options: Values, args: List[str]) -> None: key = self._get_n_args(args, "unset [name]", n=1) self.configuration.unset_value(key) self._save_configuration() - def list_config_values(self, options: Values, args: list[str]) -> None: + def list_config_values(self, options: Values, args: List[str]) -> None: """List config key-value pairs across different config files""" self._get_n_args(args, "debug", n=0) @@ -212,15 +206,13 @@ def list_config_values(self, options: Values, args: list[str]) -> None: file_exists = os.path.exists(fname) write_output("%s, exists: %r", fname, file_exists) if file_exists: - self.print_config_file_values(variant, fname) + self.print_config_file_values(variant) - def print_config_file_values(self, variant: Kind, fname: str) -> None: + def print_config_file_values(self, variant: Kind) -> None: """Get key-value pairs from the file of a variant""" for name, value in self.configuration.get_values_in_config(variant).items(): with indent_log(): - if name == fname: - for confname, confvalue in value.items(): - write_output("%s: %s", confname, confvalue) + write_output("%s: %s", name, value) def print_env_var_values(self) -> None: """Get key-values pairs present as environment variables""" @@ -230,7 +222,7 @@ def print_env_var_values(self) -> None: env_var = f"PIP_{key.upper()}" write_output("%s=%r", env_var, value) - def open_in_editor(self, options: Values, args: list[str]) -> None: + def open_in_editor(self, options: Values, args: List[str]) -> None: editor = self._determine_editor(options) fname = self.configuration.get_file_to_edit() @@ -250,15 +242,17 @@ def open_in_editor(self, options: Values, args: list[str]) -> None: e.filename = editor raise except subprocess.CalledProcessError as e: - raise PipError(f"Editor Subprocess exited with exit code {e.returncode}") + raise PipError( + "Editor Subprocess exited with exit code {}".format(e.returncode) + ) - def _get_n_args(self, args: list[str], example: str, n: int) -> Any: + def _get_n_args(self, args: List[str], example: str, n: int) -> Any: """Helper to make sure the command got the right number of arguments""" if len(args) != n: msg = ( - f"Got unexpected number of arguments, expected {n}. " - f'(example: "{get_prog()} config {example}")' - ) + "Got unexpected number of arguments, expected {}. " + '(example: "{} config {}")' + ).format(n, get_prog(), example) raise PipError(msg) if n == 1: diff --git a/venv1/Lib/site-packages/pip/_internal/commands/debug.py b/venv1/Lib/site-packages/pip/_internal/commands/debug.py index 0e187e79..2a3e7d29 100644 --- a/venv1/Lib/site-packages/pip/_internal/commands/debug.py +++ b/venv1/Lib/site-packages/pip/_internal/commands/debug.py @@ -1,12 +1,11 @@ -from __future__ import annotations - +import importlib.resources import locale import logging import os import sys from optparse import Values from types import ModuleType -from typing import Any +from typing import Any, Dict, List, Optional import pip._vendor from pip._vendor.certifi import where @@ -18,7 +17,6 @@ from pip._internal.cli.status_codes import SUCCESS from pip._internal.configuration import Configuration from pip._internal.metadata import get_environment -from pip._internal.utils.compat import open_text_resource from pip._internal.utils.logging import indent_log from pip._internal.utils.misc import get_pip_version @@ -36,8 +34,8 @@ def show_sys_implementation() -> None: show_value("name", implementation_name) -def create_vendor_txt_map() -> dict[str, str]: - with open_text_resource("pip._vendor", "vendor.txt") as f: +def create_vendor_txt_map() -> Dict[str, str]: + with importlib.resources.open_text("pip._vendor", "vendor.txt") as f: # Purge non version specifying lines. # Also, remove any space prefix or suffixes (including comments). lines = [ @@ -48,29 +46,22 @@ def create_vendor_txt_map() -> dict[str, str]: return dict(line.split("==", 1) for line in lines) -def get_module_from_module_name(module_name: str) -> ModuleType | None: +def get_module_from_module_name(module_name: str) -> ModuleType: # Module name can be uppercase in vendor.txt for some reason... module_name = module_name.lower().replace("-", "_") # PATCH: setuptools is actually only pkg_resources. if module_name == "setuptools": module_name = "pkg_resources" - try: - __import__(f"pip._vendor.{module_name}", globals(), locals(), level=0) - return getattr(pip._vendor, module_name) - except ImportError: - # We allow 'truststore' to fail to import due - # to being unavailable on Python 3.9 and earlier. - if module_name == "truststore" and sys.version_info < (3, 10): - return None - raise + __import__(f"pip._vendor.{module_name}", globals(), locals(), level=0) + return getattr(pip._vendor, module_name) -def get_vendor_version_from_module(module_name: str) -> str | None: +def get_vendor_version_from_module(module_name: str) -> Optional[str]: module = get_module_from_module_name(module_name) version = getattr(module, "__version__", None) - if module and not version: + if not version: # Try to find version in debundled module info. assert module.__file__ is not None env = get_environment([os.path.dirname(module.__file__)]) @@ -81,7 +72,7 @@ def get_vendor_version_from_module(module_name: str) -> str | None: return version -def show_actual_vendor_versions(vendor_txt_versions: dict[str, str]) -> None: +def show_actual_vendor_versions(vendor_txt_versions: Dict[str, str]) -> None: """Log the actual version and print extra info if there is a conflict or if the actual version could not be imported. """ @@ -97,7 +88,7 @@ def show_actual_vendor_versions(vendor_txt_versions: dict[str, str]) -> None: elif parse_version(actual_version) != parse_version(expected_version): extra_message = ( " (CONFLICT: vendor.txt suggests version should" - f" be {expected_version})" + " be {})".format(expected_version) ) logger.info("%s==%s%s", module_name, actual_version, extra_message) @@ -114,7 +105,7 @@ def show_tags(options: Values) -> None: tag_limit = 10 target_python = make_target_python(options) - tags = target_python.get_sorted_tags() + tags = target_python.get_tags() # Display the target options that were explicitly provided. formatted_target = target_python.format_given() @@ -122,7 +113,7 @@ def show_tags(options: Values) -> None: if formatted_target: suffix = f" (target: {formatted_target})" - msg = f"Compatible tags: {len(tags)}{suffix}" + msg = "Compatible tags: {}{}".format(len(tags), suffix) logger.info(msg) if options.verbose < 1 and len(tags) > tag_limit: @@ -136,12 +127,17 @@ def show_tags(options: Values) -> None: logger.info(str(tag)) if tags_limited: - msg = f"...\n[First {tag_limit} tags shown. Pass --verbose to show all.]" + msg = ( + "...\n[First {tag_limit} tags shown. Pass --verbose to show all.]" + ).format(tag_limit=tag_limit) logger.info(msg) def ca_bundle_info(config: Configuration) -> str: - levels = {key.split(".", 1)[0] for key, _ in config.items()} + levels = set() + for key, _ in config.items(): + levels.add(key.split(".")[0]) + if not levels: return "Not specified" @@ -171,7 +167,7 @@ def add_options(self) -> None: self.parser.insert_option_group(0, self.cmd_opts) self.parser.config.load() - def run(self, options: Values, args: list[str]) -> int: + def run(self, options: Values, args: List[str]) -> int: logger.warning( "This command is only meant for debugging. " "Do not use this with automation for parsing and getting these " diff --git a/venv1/Lib/site-packages/pip/_internal/commands/download.py b/venv1/Lib/site-packages/pip/_internal/commands/download.py index 903917b9..36e947c8 100644 --- a/venv1/Lib/site-packages/pip/_internal/commands/download.py +++ b/venv1/Lib/site-packages/pip/_internal/commands/download.py @@ -1,12 +1,14 @@ import logging import os from optparse import Values +from typing import List from pip._internal.cli import cmdoptions from pip._internal.cli.cmdoptions import make_target_python from pip._internal.cli.req_command import RequirementCommand, with_cleanup from pip._internal.cli.status_codes import SUCCESS from pip._internal.operations.build.build_tracker import get_build_tracker +from pip._internal.req.req_install import check_legacy_setup_py_options from pip._internal.utils.misc import ensure_dir, normalize_path, write_output from pip._internal.utils.temp_dir import TempDirectory @@ -35,9 +37,9 @@ class DownloadCommand(RequirementCommand): def add_options(self) -> None: self.cmd_opts.add_option(cmdoptions.constraints()) - self.cmd_opts.add_option(cmdoptions.build_constraints()) self.cmd_opts.add_option(cmdoptions.requirements()) self.cmd_opts.add_option(cmdoptions.no_deps()) + self.cmd_opts.add_option(cmdoptions.global_options()) self.cmd_opts.add_option(cmdoptions.no_binary()) self.cmd_opts.add_option(cmdoptions.only_binary()) self.cmd_opts.add_option(cmdoptions.prefer_binary()) @@ -47,6 +49,7 @@ def add_options(self) -> None: self.cmd_opts.add_option(cmdoptions.progress_bar()) self.cmd_opts.add_option(cmdoptions.no_build_isolation()) self.cmd_opts.add_option(cmdoptions.use_pep517()) + self.cmd_opts.add_option(cmdoptions.no_use_pep517()) self.cmd_opts.add_option(cmdoptions.check_build_deps()) self.cmd_opts.add_option(cmdoptions.ignore_requires_python()) @@ -72,14 +75,13 @@ def add_options(self) -> None: self.parser.insert_option_group(0, self.cmd_opts) @with_cleanup - def run(self, options: Values, args: list[str]) -> int: + def run(self, options: Values, args: List[str]) -> int: options.ignore_installed = True # editable doesn't really make sense for `pip download`, but the bowels # of the RequirementSet code require that property. options.editables = [] cmdoptions.check_dist_restriction(options) - cmdoptions.check_build_constraints(options) options.download_dir = normalize_path(options.download_dir) ensure_dir(options.download_dir) @@ -103,6 +105,7 @@ def run(self, options: Values, args: list[str]) -> int: ) reqs = self.get_requirements(args, options, finder, session) + check_legacy_setup_py_options(options, reqs) preparer = self.make_requirement_preparer( temp_build_dir=directory, @@ -120,6 +123,7 @@ def run(self, options: Values, args: list[str]) -> int: finder=finder, options=options, ignore_requires_python=options.ignore_requires_python, + use_pep517=options.use_pep517, py_version_info=options.python_version, ) @@ -127,15 +131,12 @@ def run(self, options: Values, args: list[str]) -> int: requirement_set = resolver.resolve(reqs, check_supported_wheels=True) - preparer.prepare_linked_requirements_more(requirement_set.requirements.values()) - - downloaded: list[str] = [] + downloaded: List[str] = [] for req in requirement_set.requirements.values(): if req.satisfied_by is None: assert req.name is not None preparer.save_linked_requirement(req) downloaded.append(req.name) - if downloaded: write_output("Successfully downloaded %s", " ".join(downloaded)) diff --git a/venv1/Lib/site-packages/pip/_internal/commands/freeze.py b/venv1/Lib/site-packages/pip/_internal/commands/freeze.py index 7794857c..5fa6d39b 100644 --- a/venv1/Lib/site-packages/pip/_internal/commands/freeze.py +++ b/venv1/Lib/site-packages/pip/_internal/commands/freeze.py @@ -1,5 +1,6 @@ import sys from optparse import Values +from typing import List from pip._internal.cli import cmdoptions from pip._internal.cli.base_command import Command @@ -7,18 +8,7 @@ from pip._internal.operations.freeze import freeze from pip._internal.utils.compat import stdlib_pkgs - -def _should_suppress_build_backends() -> bool: - return sys.version_info < (3, 12) - - -def _dev_pkgs() -> set[str]: - pkgs = {"pip"} - - if _should_suppress_build_backends(): - pkgs |= {"setuptools", "distribute", "wheel"} - - return pkgs +DEV_PKGS = {"pip", "setuptools", "distribute", "wheel"} class FreezeCommand(Command): @@ -28,9 +18,9 @@ class FreezeCommand(Command): packages are listed in a case-insensitive sorted order. """ - ignore_require_venv = True usage = """ %prog [options]""" + log_streams = ("ext://sys.stderr", "ext://sys.stderr") def add_options(self) -> None: self.cmd_opts.add_option( @@ -71,7 +61,7 @@ def add_options(self) -> None: action="store_true", help=( "Do not skip these packages in the output:" - " {}".format(", ".join(_dev_pkgs())) + " {}".format(", ".join(DEV_PKGS)) ), ) self.cmd_opts.add_option( @@ -84,10 +74,10 @@ def add_options(self) -> None: self.parser.insert_option_group(0, self.cmd_opts) - def run(self, options: Values, args: list[str]) -> int: + def run(self, options: Values, args: List[str]) -> int: skip = set(stdlib_pkgs) if not options.freeze_all: - skip.update(_dev_pkgs()) + skip.update(DEV_PKGS) if options.excludes: skip.update(options.excludes) diff --git a/venv1/Lib/site-packages/pip/_internal/commands/hash.py b/venv1/Lib/site-packages/pip/_internal/commands/hash.py index 271a4c91..042dac81 100644 --- a/venv1/Lib/site-packages/pip/_internal/commands/hash.py +++ b/venv1/Lib/site-packages/pip/_internal/commands/hash.py @@ -2,6 +2,7 @@ import logging import sys from optparse import Values +from typing import List from pip._internal.cli.base_command import Command from pip._internal.cli.status_codes import ERROR, SUCCESS @@ -36,7 +37,7 @@ def add_options(self) -> None: ) self.parser.insert_option_group(0, self.cmd_opts) - def run(self, options: Values, args: list[str]) -> int: + def run(self, options: Values, args: List[str]) -> int: if not args: self.parser.print_usage(sys.stderr) return ERROR diff --git a/venv1/Lib/site-packages/pip/_internal/commands/help.py b/venv1/Lib/site-packages/pip/_internal/commands/help.py index 2ae658ff..62066318 100644 --- a/venv1/Lib/site-packages/pip/_internal/commands/help.py +++ b/venv1/Lib/site-packages/pip/_internal/commands/help.py @@ -1,4 +1,5 @@ from optparse import Values +from typing import List from pip._internal.cli.base_command import Command from pip._internal.cli.status_codes import SUCCESS @@ -12,7 +13,7 @@ class HelpCommand(Command): %prog """ ignore_require_venv = True - def run(self, options: Values, args: list[str]) -> int: + def run(self, options: Values, args: List[str]) -> int: from pip._internal.commands import ( commands_dict, create_command, diff --git a/venv1/Lib/site-packages/pip/_internal/commands/index.py b/venv1/Lib/site-packages/pip/_internal/commands/index.py index ecac9988..7267effe 100644 --- a/venv1/Lib/site-packages/pip/_internal/commands/index.py +++ b/venv1/Lib/site-packages/pip/_internal/commands/index.py @@ -1,20 +1,13 @@ -from __future__ import annotations - -import json import logging -from collections.abc import Iterable from optparse import Values -from typing import Any, Callable +from typing import Any, Iterable, List, Optional, Union -from pip._vendor.packaging.version import Version +from pip._vendor.packaging.version import LegacyVersion, Version from pip._internal.cli import cmdoptions from pip._internal.cli.req_command import IndexGroupCommand from pip._internal.cli.status_codes import ERROR, SUCCESS -from pip._internal.commands.search import ( - get_installed_distribution, - print_dist_installation_info, -) +from pip._internal.commands.search import print_dist_installation_info from pip._internal.exceptions import CommandError, DistributionNotFound, PipError from pip._internal.index.collector import LinkCollector from pip._internal.index.package_finder import PackageFinder @@ -41,7 +34,6 @@ def add_options(self) -> None: self.cmd_opts.add_option(cmdoptions.ignore_requires_python()) self.cmd_opts.add_option(cmdoptions.pre()) - self.cmd_opts.add_option(cmdoptions.json()) self.cmd_opts.add_option(cmdoptions.no_binary()) self.cmd_opts.add_option(cmdoptions.only_binary()) @@ -53,19 +45,22 @@ def add_options(self) -> None: self.parser.insert_option_group(0, index_opts) self.parser.insert_option_group(0, self.cmd_opts) - def handler_map(self) -> dict[str, Callable[[Values, list[str]], None]]: - return { + def run(self, options: Values, args: List[str]) -> int: + handlers = { "versions": self.get_available_package_versions, } - def run(self, options: Values, args: list[str]) -> int: - handler_map = self.handler_map() + logger.warning( + "pip index is currently an experimental command. " + "It may be removed/changed in a future release " + "without prior warning." + ) # Determine action - if not args or args[0] not in handler_map: + if not args or args[0] not in handlers: logger.error( "Need an action (%s) to perform.", - ", ".join(sorted(handler_map)), + ", ".join(sorted(handlers)), ) return ERROR @@ -73,7 +68,7 @@ def run(self, options: Values, args: list[str]) -> int: # Error handling happens here, not in the action-handlers. try: - handler_map[action](options, args[1:]) + handlers[action](options, args[1:]) except PipError as e: logger.error(e.args[0]) return ERROR @@ -84,8 +79,8 @@ def _build_package_finder( self, options: Values, session: PipSession, - target_python: TargetPython | None = None, - ignore_requires_python: bool | None = None, + target_python: Optional[TargetPython] = None, + ignore_requires_python: Optional[bool] = None, ) -> PackageFinder: """ Create a package finder appropriate to the index command. @@ -105,7 +100,7 @@ def _build_package_finder( target_python=target_python, ) - def get_available_package_versions(self, options: Values, args: list[Any]) -> None: + def get_available_package_versions(self, options: Values, args: List[Any]) -> None: if len(args) != 1: raise CommandError("You need to specify exactly one argument") @@ -120,7 +115,7 @@ def get_available_package_versions(self, options: Values, args: list[Any]) -> No ignore_requires_python=options.ignore_requires_python, ) - versions: Iterable[Version] = ( + versions: Iterable[Union[LegacyVersion, Version]] = ( candidate.version for candidate in finder.find_all_candidates(query) ) @@ -133,27 +128,12 @@ def get_available_package_versions(self, options: Values, args: list[Any]) -> No if not versions: raise DistributionNotFound( - f"No matching distribution found for {query}" + "No matching distribution found for {}".format(query) ) formatted_versions = [str(ver) for ver in sorted(versions, reverse=True)] latest = formatted_versions[0] - dist = get_installed_distribution(query) - - if options.json: - structured_output = { - "name": query, - "versions": formatted_versions, - "latest": latest, - } - - if dist is not None: - structured_output["installed_version"] = str(dist.version) - - write_output(json.dumps(structured_output)) - - else: - write_output(f"{query} ({latest})") - write_output("Available versions: {}".format(", ".join(formatted_versions))) - print_dist_installation_info(latest, dist) + write_output("{} ({})".format(query, latest)) + write_output("Available versions: {}".format(", ".join(formatted_versions))) + print_dist_installation_info(query, latest) diff --git a/venv1/Lib/site-packages/pip/_internal/commands/inspect.py b/venv1/Lib/site-packages/pip/_internal/commands/inspect.py index e262012e..27c8fa3d 100644 --- a/venv1/Lib/site-packages/pip/_internal/commands/inspect.py +++ b/venv1/Lib/site-packages/pip/_internal/commands/inspect.py @@ -1,13 +1,13 @@ import logging from optparse import Values -from typing import Any +from typing import Any, Dict, List from pip._vendor.packaging.markers import default_environment from pip._vendor.rich import print_json from pip import __version__ from pip._internal.cli import cmdoptions -from pip._internal.cli.base_command import Command +from pip._internal.cli.req_command import Command from pip._internal.cli.status_codes import SUCCESS from pip._internal.metadata import BaseDistribution, get_environment from pip._internal.utils.compat import stdlib_pkgs @@ -45,7 +45,7 @@ def add_options(self) -> None: self.cmd_opts.add_option(cmdoptions.list_path()) self.parser.insert_option_group(0, self.cmd_opts) - def run(self, options: Values, args: list[str]) -> int: + def run(self, options: Values, args: List[str]) -> int: cmdoptions.check_list_path_option(options) dists = get_environment(options.path).iter_installed_distributions( local_only=options.local, @@ -62,8 +62,8 @@ def run(self, options: Values, args: list[str]) -> int: print_json(data=output) return SUCCESS - def _dist_to_dict(self, dist: BaseDistribution) -> dict[str, Any]: - res: dict[str, Any] = { + def _dist_to_dict(self, dist: BaseDistribution) -> Dict[str, Any]: + res: Dict[str, Any] = { "metadata": dist.metadata_dict, "metadata_location": dist.info_location, } diff --git a/venv1/Lib/site-packages/pip/_internal/commands/install.py b/venv1/Lib/site-packages/pip/_internal/commands/install.py index b16b8e3d..3c15ed41 100644 --- a/venv1/Lib/site-packages/pip/_internal/commands/install.py +++ b/venv1/Lib/site-packages/pip/_internal/commands/install.py @@ -1,5 +1,3 @@ -from __future__ import annotations - import errno import json import operator @@ -7,32 +5,20 @@ import shutil import site from optparse import SUPPRESS_HELP, Values -from pathlib import Path +from typing import List, Optional -from pip._vendor.packaging.utils import canonicalize_name -from pip._vendor.requests.exceptions import InvalidProxyURL from pip._vendor.rich import print_json -# Eagerly import self_outdated_check to avoid crashes. Otherwise, -# this module would be imported *after* pip was replaced, resulting -# in crashes if the new self_outdated_check module was incompatible -# with the rest of pip that's already imported, or allowing a -# wheel to execute arbitrary code on install by replacing -# self_outdated_check. -import pip._internal.self_outdated_check # noqa: F401 from pip._internal.cache import WheelCache from pip._internal.cli import cmdoptions from pip._internal.cli.cmdoptions import make_target_python from pip._internal.cli.req_command import ( RequirementCommand, + warn_if_run_as_root, with_cleanup, ) from pip._internal.cli.status_codes import ERROR, SUCCESS -from pip._internal.exceptions import ( - CommandError, - InstallationError, - InstallWheelBuildError, -) +from pip._internal.exceptions import CommandError, InstallationError from pip._internal.locations import get_scheme from pip._internal.metadata import get_environment from pip._internal.models.installation_report import InstallationReport @@ -41,6 +27,7 @@ from pip._internal.req import install_given_reqs from pip._internal.req.req_install import ( InstallRequirement, + check_legacy_setup_py_options, ) from pip._internal.utils.compat import WINDOWS from pip._internal.utils.filesystem import test_writable_dir @@ -50,7 +37,6 @@ ensure_dir, get_pip_version, protect_pip_from_modification_on_windows, - warn_if_run_as_root, write_output, ) from pip._internal.utils.temp_dir import TempDirectory @@ -58,7 +44,7 @@ running_under_virtualenv, virtualenv_no_global, ) -from pip._internal.wheel_builder import build +from pip._internal.wheel_builder import build, should_build_for_install_command logger = getLogger(__name__) @@ -86,7 +72,6 @@ class InstallCommand(RequirementCommand): def add_options(self) -> None: self.cmd_opts.add_option(cmdoptions.requirements()) self.cmd_opts.add_option(cmdoptions.constraints()) - self.cmd_opts.add_option(cmdoptions.build_constraints()) self.cmd_opts.add_option(cmdoptions.no_deps()) self.cmd_opts.add_option(cmdoptions.pre()) @@ -210,10 +195,12 @@ def add_options(self) -> None: self.cmd_opts.add_option(cmdoptions.ignore_requires_python()) self.cmd_opts.add_option(cmdoptions.no_build_isolation()) self.cmd_opts.add_option(cmdoptions.use_pep517()) + self.cmd_opts.add_option(cmdoptions.no_use_pep517()) self.cmd_opts.add_option(cmdoptions.check_build_deps()) self.cmd_opts.add_option(cmdoptions.override_externally_managed()) self.cmd_opts.add_option(cmdoptions.config_settings()) + self.cmd_opts.add_option(cmdoptions.global_options()) self.cmd_opts.add_option( "--compile", @@ -276,7 +263,7 @@ def add_options(self) -> None: ) @with_cleanup - def run(self, options: Values, args: list[str]) -> int: + def run(self, options: Values, args: List[str]) -> int: if options.use_user_site and options.target_dir is not None: raise CommandError("Can not combine '--user' and '--target'") @@ -301,7 +288,6 @@ def run(self, options: Values, args: list[str]) -> int: if options.upgrade: upgrade_strategy = options.upgrade_strategy - cmdoptions.check_build_constraints(options) cmdoptions.check_dist_restriction(options, check_target=True) logger.verbose("Using %s", get_pip_version()) @@ -313,8 +299,8 @@ def run(self, options: Values, args: list[str]) -> int: isolated_mode=options.isolated_mode, ) - target_temp_dir: TempDirectory | None = None - target_temp_dir_path: str | None = None + target_temp_dir: Optional[TempDirectory] = None + target_temp_dir_path: Optional[str] = None if options.target_dir: options.ignore_installed = True options.target_dir = os.path.abspath(options.target_dir) @@ -333,6 +319,8 @@ def run(self, options: Values, args: list[str]) -> int: target_temp_dir_path = target_temp_dir.path self.enter_context(target_temp_dir) + global_options = options.global_options or [] + session = self.get_default_session(options) target_python = make_target_python(options) @@ -352,6 +340,7 @@ def run(self, options: Values, args: list[str]) -> int: try: reqs = self.get_requirements(args, options, finder, session) + check_legacy_setup_py_options(options, reqs) wheel_cache = WheelCache(options.cache_dir) @@ -380,7 +369,7 @@ def run(self, options: Values, args: list[str]) -> int: ignore_requires_python=options.ignore_requires_python, force_reinstall=options.force_reinstall, upgrade_strategy=upgrade_strategy, - py_version_info=options.python_version, + use_pep517=options.use_pep517, ) self.trace_basic_info(finder) @@ -409,13 +398,6 @@ def run(self, options: Values, args: list[str]) -> int: ) return SUCCESS - # If there is any more preparation to do for the actual installation, do - # so now. This includes actually downloading the files in the case that - # we have been using PEP-658 metadata so far. - preparer.prepare_linked_requirements_more( - requirement_set.requirements.values() - ) - try: pip_req = requirement_set.get_requirement("pip") except KeyError: @@ -427,22 +409,31 @@ def run(self, options: Values, args: list[str]) -> int: protect_pip_from_modification_on_windows(modifying_pip=modifying_pip) reqs_to_build = [ - r for r in requirement_set.requirements_to_install if not r.is_wheel + r + for r in requirement_set.requirements.values() + if should_build_for_install_command(r) ] _, build_failures = build( reqs_to_build, wheel_cache=wheel_cache, verify=True, + build_options=[], + global_options=global_options, ) if build_failures: - raise InstallWheelBuildError(build_failures) + raise InstallationError( + "Could not build wheels for {}, which is required to " + "install pyproject.toml-based projects".format( + ", ".join(r.name for r in build_failures) # type: ignore + ) + ) to_install = resolver.get_installation_order(requirement_set) # Check for conflicts in the package set we're installing. - conflicts: ConflictDetails | None = None + conflicts: Optional[ConflictDetails] = None should_warn_about_conflicts = ( not options.ignore_dependencies and options.warn_about_conflicts ) @@ -457,13 +448,13 @@ def run(self, options: Values, args: list[str]) -> int: installed = install_given_reqs( to_install, + global_options, root=options.root_path, home=target_temp_dir_path, prefix=options.prefix_path, warn_script_location=warn_script_location, use_user_site=options.use_user_site, pycompile=options.compile, - progress_bar=options.progress_bar, ) lib_locations = get_lib_location_guesses( @@ -475,21 +466,17 @@ def run(self, options: Values, args: list[str]) -> int: ) env = get_environment(lib_locations) - # Display a summary of installed packages, with extra care to - # display a package name as it was requested by the user. installed.sort(key=operator.attrgetter("name")) - summary = [] - installed_versions = {} - for distribution in env.iter_all_distributions(): - installed_versions[distribution.canonical_name] = distribution.version - for package in installed: - display_name = package.name - version = installed_versions.get(canonicalize_name(display_name), None) - if version: - text = f"{display_name}-{version}" - else: - text = display_name - summary.append(text) + items = [] + for result in installed: + item = result.name + try: + installed_dist = env.get_distribution(item) + if installed_dist is not None: + item = f"{item}-{installed_dist.version}" + except Exception: + pass + items.append(item) if conflicts is not None: self._warn_about_conflicts( @@ -497,7 +484,7 @@ def run(self, options: Values, args: list[str]) -> int: resolver_variant=self.determine_resolver_variant(options), ) - installed_desc = " ".join(summary) + installed_desc = " ".join(items) if installed_desc: write_output( "Successfully installed %s", @@ -511,7 +498,7 @@ def run(self, options: Values, args: list[str]) -> int: show_traceback, options.use_user_site, ) - logger.error(message, exc_info=show_traceback) + logger.error(message, exc_info=show_traceback) # noqa return ERROR @@ -579,8 +566,8 @@ def _handle_target_dir( shutil.move(os.path.join(lib_dir, item), target_item_dir) def _determine_conflicts( - self, to_install: list[InstallRequirement] - ) -> ConflictDetails | None: + self, to_install: List[InstallRequirement] + ) -> Optional[ConflictDetails]: try: return check_install_conflicts(to_install) except Exception: @@ -597,7 +584,7 @@ def _warn_about_conflicts( if not missing and not conflicting: return - parts: list[str] = [] + parts: List[str] = [] if resolver_variant == "legacy": parts.append( "pip's legacy dependency resolver does not consider dependency " @@ -605,7 +592,7 @@ def _warn_about_conflicts( "source of the following dependency conflicts." ) else: - assert resolver_variant == "resolvelib" + assert resolver_variant == "2020-resolver" parts.append( "pip's dependency resolver does not currently take into account " "all the packages that are installed. This behaviour is the " @@ -617,8 +604,12 @@ def _warn_about_conflicts( version = package_set[project_name][0] for dependency in missing[project_name]: message = ( - f"{project_name} {version} requires {dependency[1]}, " + "{name} {version} requires {requirement}, " "which is not installed." + ).format( + name=project_name, + version=version, + requirement=dependency[1], ) parts.append(message) @@ -634,7 +625,7 @@ def _warn_about_conflicts( requirement=req, dep_name=dep_name, dep_version=dep_version, - you=("you" if resolver_variant == "resolvelib" else "you'll"), + you=("you" if resolver_variant == "2020-resolver" else "you'll"), ) parts.append(message) @@ -643,11 +634,11 @@ def _warn_about_conflicts( def get_lib_location_guesses( user: bool = False, - home: str | None = None, - root: str | None = None, + home: Optional[str] = None, + root: Optional[str] = None, isolated: bool = False, - prefix: str | None = None, -) -> list[str]: + prefix: Optional[str] = None, +) -> List[str]: scheme = get_scheme( "", user=user, @@ -659,7 +650,7 @@ def get_lib_location_guesses( return [scheme.purelib, scheme.platlib] -def site_packages_writable(root: str | None, isolated: bool) -> bool: +def site_packages_writable(root: Optional[str], isolated: bool) -> bool: return all( test_writable_dir(d) for d in set(get_lib_location_guesses(root=root, isolated=isolated)) @@ -667,10 +658,10 @@ def site_packages_writable(root: str | None, isolated: bool) -> bool: def decide_user_install( - use_user_site: bool | None, - prefix_path: str | None = None, - target_dir: str | None = None, - root_path: str | None = None, + use_user_site: Optional[bool], + prefix_path: Optional[str] = None, + target_dir: Optional[str] = None, + root_path: Optional[str] = None, isolated_mode: bool = False, ) -> bool: """Determine whether to do a user install based on the input options. @@ -687,7 +678,6 @@ def decide_user_install( logger.debug("Non-user install by explicit request") return False - # If we have been asked for a user install explicitly, check compatibility. if use_user_site: if prefix_path: raise CommandError( @@ -699,13 +689,6 @@ def decide_user_install( "Can not perform a '--user' install. User site-packages " "are not visible in this virtualenv." ) - # Catch all remaining cases which honour the site.ENABLE_USER_SITE - # value, such as a plain Python installation (e.g. no virtualenv). - if not site.ENABLE_USER_SITE: - raise InstallationError( - "Can not perform a '--user' install. User site-packages " - "are disabled for this Python." - ) logger.debug("User install by explicit request") return True @@ -773,31 +756,20 @@ def create_os_error_message( parts.append(permissions_part) parts.append(".\n") - # Suggest to check "pip config debug" in case of invalid proxy - if type(error) is InvalidProxyURL: + # Suggest the user to enable Long Paths if path length is + # more than 260 + if ( + WINDOWS + and error.errno == errno.ENOENT + and error.filename + and len(error.filename) > 260 + ): parts.append( - 'Consider checking your local proxy configuration with "pip config debug"' + "HINT: This error might have occurred since " + "this system does not have Windows Long Path " + "support enabled. You can find information on " + "how to enable this at " + "https://pip.pypa.io/warnings/enable-long-paths\n" ) - parts.append(".\n") - # On Windows, errors like EINVAL or ENOENT may occur - # if a file or folder name exceeds 255 characters, - # or if the full path exceeds 260 characters and long path support isn't enabled. - # This condition checks for such cases and adds a hint to the error output. - - if WINDOWS and error.errno in (errno.EINVAL, errno.ENOENT) and error.filename: - if any(len(part) > 255 for part in Path(error.filename).parts): - parts.append( - "HINT: This error might be caused by a file or folder name exceeding " - "255 characters, which is a Windows limitation even if long paths " - "are enabled.\n " - ) - if len(error.filename) > 260: - parts.append( - "HINT: This error might have occurred since " - "this system does not have Windows Long Path " - "support enabled. You can find information on " - "how to enable this at " - "https://pip.pypa.io/warnings/enable-long-paths\n" - ) return "".join(parts).strip() + "\n" diff --git a/venv1/Lib/site-packages/pip/_internal/commands/list.py b/venv1/Lib/site-packages/pip/_internal/commands/list.py index ad27e45c..8e1426db 100644 --- a/venv1/Lib/site-packages/pip/_internal/commands/list.py +++ b/venv1/Lib/site-packages/pip/_internal/commands/list.py @@ -1,27 +1,24 @@ -from __future__ import annotations - import json import logging -from collections.abc import Generator, Sequence -from email.parser import Parser from optparse import Values -from typing import TYPE_CHECKING, cast +from typing import TYPE_CHECKING, Generator, List, Optional, Sequence, Tuple, cast from pip._vendor.packaging.utils import canonicalize_name -from pip._vendor.packaging.version import InvalidVersion, Version from pip._internal.cli import cmdoptions -from pip._internal.cli.index_command import IndexGroupCommand +from pip._internal.cli.req_command import IndexGroupCommand from pip._internal.cli.status_codes import SUCCESS from pip._internal.exceptions import CommandError +from pip._internal.index.collector import LinkCollector +from pip._internal.index.package_finder import PackageFinder from pip._internal.metadata import BaseDistribution, get_environment from pip._internal.models.selection_prefs import SelectionPreferences +from pip._internal.network.session import PipSession from pip._internal.utils.compat import stdlib_pkgs from pip._internal.utils.misc import tabulate, write_output if TYPE_CHECKING: - from pip._internal.index.package_finder import PackageFinder - from pip._internal.network.session import PipSession + from pip._internal.metadata.base import DistributionVersion class _DistWithLatestInfo(BaseDistribution): """Give the distribution object a couple of extra fields. @@ -30,7 +27,7 @@ class _DistWithLatestInfo(BaseDistribution): makes the rest of the code much cleaner. """ - latest_version: Version + latest_version: DistributionVersion latest_filetype: str _ProcessedDists = Sequence[_DistWithLatestInfo] @@ -106,10 +103,7 @@ def add_options(self) -> None: dest="list_format", default="columns", choices=("columns", "freeze", "json"), - help=( - "Select the output format among: columns (default), freeze, or json. " - "The 'freeze' format cannot be used with the --outdated option." - ), + help="Select the output format among: columns (default), freeze, or json", ) self.cmd_opts.add_option( @@ -129,7 +123,7 @@ def add_options(self) -> None: "--include-editable", action="store_true", dest="include_editable", - help="Include editable package in output.", + help="Include editable package from output.", default=True, ) self.cmd_opts.add_option(cmdoptions.list_exclude()) @@ -138,20 +132,12 @@ def add_options(self) -> None: self.parser.insert_option_group(0, index_opts) self.parser.insert_option_group(0, self.cmd_opts) - def handle_pip_version_check(self, options: Values) -> None: - if options.outdated or options.uptodate: - super().handle_pip_version_check(options) - def _build_package_finder( self, options: Values, session: PipSession ) -> PackageFinder: """ Create a package finder appropriate to this list command. """ - # Lazy import the heavy index modules as most list invocations won't need 'em. - from pip._internal.index.collector import LinkCollector - from pip._internal.index.package_finder import PackageFinder - link_collector = LinkCollector.create(session, options=options) # Pass allow_yanked=False to ignore yanked versions. @@ -165,13 +151,13 @@ def _build_package_finder( selection_prefs=selection_prefs, ) - def run(self, options: Values, args: list[str]) -> int: + def run(self, options: Values, args: List[str]) -> int: if options.outdated and options.uptodate: raise CommandError("Options --outdated and --uptodate cannot be combined.") if options.outdated and options.list_format == "freeze": raise CommandError( - "List format 'freeze' cannot be used with the --outdated option." + "List format 'freeze' can not be used with the --outdated option." ) cmdoptions.check_list_path_option(options) @@ -180,7 +166,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, @@ -207,8 +193,8 @@ def run(self, options: Values, args: list[str]) -> int: return SUCCESS def get_outdated( - self, packages: _ProcessedDists, options: Values - ) -> _ProcessedDists: + self, packages: "_ProcessedDists", options: Values + ) -> "_ProcessedDists": return [ dist for dist in self.iter_packages_latest_infos(packages, options) @@ -216,8 +202,8 @@ def get_outdated( ] def get_uptodate( - self, packages: _ProcessedDists, options: Values - ) -> _ProcessedDists: + self, packages: "_ProcessedDists", options: Values + ) -> "_ProcessedDists": return [ dist for dist in self.iter_packages_latest_infos(packages, options) @@ -225,8 +211,8 @@ def get_uptodate( ] def get_not_required( - self, packages: _ProcessedDists, options: Values - ) -> _ProcessedDists: + self, packages: "_ProcessedDists", options: Values + ) -> "_ProcessedDists": dep_keys = { canonicalize_name(dep.name) for dist in packages @@ -239,14 +225,14 @@ def get_not_required( return list({pkg for pkg in packages if pkg.canonical_name not in dep_keys}) def iter_packages_latest_infos( - self, packages: _ProcessedDists, options: Values - ) -> Generator[_DistWithLatestInfo, None, None]: + self, packages: "_ProcessedDists", options: Values + ) -> Generator["_DistWithLatestInfo", None, None]: with self._build_session(options) as session: finder = self._build_package_finder(options, session) def latest_info( - dist: _DistWithLatestInfo, - ) -> _DistWithLatestInfo | None: + dist: "_DistWithLatestInfo", + ) -> Optional["_DistWithLatestInfo"]: all_candidates = finder.find_all_candidates(dist.canonical_name) if not options.pre: # Remove prereleases @@ -277,7 +263,7 @@ def latest_info( yield dist def output_package_listing( - self, packages: _ProcessedDists, options: Values + self, packages: "_ProcessedDists", options: Values ) -> None: packages = sorted( packages, @@ -288,19 +274,17 @@ def output_package_listing( self.output_package_listing_columns(data, header) elif options.list_format == "freeze": for dist in packages: - try: - req_string = f"{dist.raw_name}=={dist.version}" - except InvalidVersion: - req_string = f"{dist.raw_name}==={dist.raw_version}" if options.verbose >= 1: - write_output("%s (%s)", req_string, dist.location) + write_output( + "%s==%s (%s)", dist.raw_name, dist.version, dist.location + ) else: - write_output(req_string) + write_output("%s==%s", dist.raw_name, dist.version) elif options.list_format == "json": write_output(format_for_json(packages, options)) def output_package_listing_columns( - self, data: list[list[str]], header: list[str] + self, data: List[List[str]], header: List[str] ) -> None: # insert the header first: we need to know the size of column names if len(data) > 0: @@ -310,15 +294,15 @@ def output_package_listing_columns( # Create and add a separator. if len(data) > 0: - pkg_strings.insert(1, " ".join("-" * x for x in sizes)) + pkg_strings.insert(1, " ".join(map(lambda x: "-" * x, sizes))) for val in pkg_strings: write_output(val) def format_for_columns( - pkgs: _ProcessedDists, options: Values -) -> tuple[list[list[str]], list[str]]: + pkgs: "_ProcessedDists", options: Values +) -> Tuple[List[List[str]], List[str]]: """ Convert the package data into something usable by output_package_listing_columns. @@ -329,40 +313,25 @@ def format_for_columns( if running_outdated: header.extend(["Latest", "Type"]) - def wheel_build_tag(dist: BaseDistribution) -> str | None: - try: - wheel_file = dist.read_text("WHEEL") - except FileNotFoundError: - return None - return Parser().parsestr(wheel_file).get("Build") - - build_tags = [wheel_build_tag(p) for p in pkgs] - has_build_tags = any(build_tags) - if has_build_tags: - header.append("Build") + has_editables = any(x.editable for x in pkgs) + if has_editables: + header.append("Editable project location") if options.verbose >= 1: header.append("Location") if options.verbose >= 1: header.append("Installer") - has_editables = any(x.editable for x in pkgs) - if has_editables: - header.append("Editable project location") - data = [] - for i, proj in enumerate(pkgs): + for proj in pkgs: # if we're working on the 'outdated' list, separate out the # latest_version and type - row = [proj.raw_name, proj.raw_version] + row = [proj.raw_name, str(proj.version)] if running_outdated: row.append(str(proj.latest_version)) row.append(proj.latest_filetype) - if has_build_tags: - row.append(build_tags[i] or "") - if has_editables: row.append(proj.editable_project_location or "") @@ -376,16 +345,12 @@ def wheel_build_tag(dist: BaseDistribution) -> str | None: return data, header -def format_for_json(packages: _ProcessedDists, options: Values) -> str: +def format_for_json(packages: "_ProcessedDists", options: Values) -> str: data = [] for dist in packages: - try: - version = str(dist.version) - except InvalidVersion: - version = dist.raw_version info = { "name": dist.raw_name, - "version": version, + "version": str(dist.version), } if options.verbose >= 1: info["location"] = dist.location or "" diff --git a/venv1/Lib/site-packages/pip/_internal/commands/search.py b/venv1/Lib/site-packages/pip/_internal/commands/search.py index b8dbc27d..03ed925b 100644 --- a/venv1/Lib/site-packages/pip/_internal/commands/search.py +++ b/venv1/Lib/site-packages/pip/_internal/commands/search.py @@ -1,5 +1,3 @@ -from __future__ import annotations - import logging import shutil import sys @@ -7,7 +5,7 @@ import xmlrpc.client from collections import OrderedDict from optparse import Values -from typing import TypedDict +from typing import TYPE_CHECKING, Dict, List, Optional from pip._vendor.packaging.version import parse as parse_version @@ -16,17 +14,18 @@ from pip._internal.cli.status_codes import NO_MATCHES_FOUND, SUCCESS from pip._internal.exceptions import CommandError from pip._internal.metadata import get_default_environment -from pip._internal.metadata.base import BaseDistribution from pip._internal.models.index import PyPI from pip._internal.network.xmlrpc import PipXmlrpcTransport from pip._internal.utils.logging import indent_log from pip._internal.utils.misc import write_output +if TYPE_CHECKING: + from typing import TypedDict -class TransformedHit(TypedDict): - name: str - summary: str - versions: list[str] + class TransformedHit(TypedDict): + name: str + summary: str + versions: List[str] logger = logging.getLogger(__name__) @@ -51,7 +50,7 @@ def add_options(self) -> None: self.parser.insert_option_group(0, self.cmd_opts) - def run(self, options: Values, args: list[str]) -> int: + def run(self, options: Values, args: List[str]) -> int: if not args: raise CommandError("Missing required argument (search query).") query = args @@ -67,7 +66,7 @@ def run(self, options: Values, args: list[str]) -> int: return SUCCESS return NO_MATCHES_FOUND - def search(self, query: list[str], options: Values) -> list[dict[str, str]]: + def search(self, query: List[str], options: Values) -> List[Dict[str, str]]: index_url = options.index session = self.get_default_session(options) @@ -77,21 +76,22 @@ def search(self, query: list[str], options: Values) -> list[dict[str, str]]: try: hits = pypi.search({"name": query, "summary": query}, "or") except xmlrpc.client.Fault as fault: - message = ( - f"XMLRPC request failed [code: {fault.faultCode}]\n{fault.faultString}" + message = "XMLRPC request failed [code: {code}]\n{string}".format( + code=fault.faultCode, + string=fault.faultString, ) raise CommandError(message) assert isinstance(hits, list) return hits -def transform_hits(hits: list[dict[str, str]]) -> list[TransformedHit]: +def transform_hits(hits: List[Dict[str, str]]) -> List["TransformedHit"]: """ The list from pypi is really a list of versions. We want a list of 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"] @@ -113,7 +113,9 @@ def transform_hits(hits: list[dict[str, str]]) -> list[TransformedHit]: return list(packages.values()) -def print_dist_installation_info(latest: str, dist: BaseDistribution | None) -> None: +def print_dist_installation_info(name: str, latest: str) -> None: + env = get_default_environment() + dist = env.get_distribution(name) if dist is not None: with indent_log(): if dist.version == latest: @@ -130,15 +132,10 @@ def print_dist_installation_info(latest: str, dist: BaseDistribution | None) -> write_output("LATEST: %s", latest) -def get_installed_distribution(name: str) -> BaseDistribution | None: - env = get_default_environment() - return env.get_distribution(name) - - def print_results( - hits: list[TransformedHit], - name_column_width: int | None = None, - terminal_width: int | None = None, + hits: List["TransformedHit"], + name_column_width: Optional[int] = None, + terminal_width: Optional[int] = None, ) -> None: if not hits: return @@ -168,11 +165,10 @@ def print_results( line = f"{name_latest:{name_column_width}} - {summary}" try: write_output(line) - dist = get_installed_distribution(name) - print_dist_installation_info(latest, dist) + print_dist_installation_info(name, latest) except UnicodeEncodeError: pass -def highest_version(versions: list[str]) -> str: +def highest_version(versions: List[str]) -> str: return max(versions, key=parse_version) diff --git a/venv1/Lib/site-packages/pip/_internal/commands/show.py b/venv1/Lib/site-packages/pip/_internal/commands/show.py index f9fcfa60..3f10701f 100644 --- a/venv1/Lib/site-packages/pip/_internal/commands/show.py +++ b/venv1/Lib/site-packages/pip/_internal/commands/show.py @@ -1,12 +1,7 @@ -from __future__ import annotations - import logging -import string -from collections.abc import Generator, Iterable, Iterator from optparse import Values -from typing import NamedTuple +from typing import Generator, Iterable, Iterator, List, NamedTuple, Optional -from pip._vendor.packaging.requirements import InvalidRequirement from pip._vendor.packaging.utils import canonicalize_name from pip._internal.cli.base_command import Command @@ -17,13 +12,6 @@ logger = logging.getLogger(__name__) -def normalize_project_url_label(label: str) -> str: - # This logic is from PEP 753 (Well-known Project URLs in Metadata). - chars_to_remove = string.punctuation + string.whitespace - removal_map = str.maketrans("", "", chars_to_remove) - return label.translate(removal_map).lower() - - class ShowCommand(Command): """ Show information about one or more installed packages. @@ -47,7 +35,7 @@ def add_options(self) -> None: self.parser.insert_option_group(0, self.cmd_opts) - def run(self, options: Values, args: list[str]) -> int: + def run(self, options: Values, args: List[str]) -> int: if not args: logger.warning("ERROR: Please provide a package name or names.") return ERROR @@ -65,24 +53,23 @@ class _PackageInfo(NamedTuple): name: str version: str location: str - editable_project_location: str | None - requires: list[str] - required_by: list[str] + editable_project_location: Optional[str] + requires: List[str] + required_by: List[str] installer: str metadata_version: str - classifiers: list[str] + classifiers: List[str] summary: str homepage: str - project_urls: list[str] + project_urls: List[str] author: str author_email: str license: str - license_expression: str - entry_points: list[str] - files: list[str] | None + entry_points: List[str] + files: Optional[List[str]] -def search_packages_info(query: list[str]) -> Generator[_PackageInfo, None, None]: +def search_packages_info(query: List[str]) -> Generator[_PackageInfo, None, None]: """ Gather details from installed distributions. Print distribution name, version, location, and installed files. Installed files requires a @@ -113,19 +100,8 @@ def _get_requiring_packages(current_dist: BaseDistribution) -> Iterator[str]: except KeyError: continue - try: - requires = sorted( - # Avoid duplicates in requirements (e.g. due to environment markers). - {req.name for req in dist.iter_dependencies()}, - key=str.lower, - ) - except InvalidRequirement: - requires = sorted(dist.iter_raw_dependencies(), key=str.lower) - - try: - required_by = sorted(_get_requiring_packages(dist), key=str.lower) - except InvalidRequirement: - required_by = ["#N/A"] + requires = sorted((req.name for req in dist.iter_dependencies()), key=str.lower) + required_by = sorted(_get_requiring_packages(dist), key=str.lower) try: entry_points_text = dist.read_text("entry_points.txt") @@ -135,27 +111,15 @@ def _get_requiring_packages(current_dist: BaseDistribution) -> Iterator[str]: files_iter = dist.iter_declared_entries() if files_iter is None: - files: list[str] | None = None + files: Optional[List[str]] = None else: files = sorted(files_iter) metadata = dist.metadata - project_urls = metadata.get_all("Project-URL", []) - homepage = metadata.get("Home-page", "") - if not homepage: - # It's common that there is a "homepage" Project-URL, but Home-page - # remains unset (especially as PEP 621 doesn't surface the field). - for url in project_urls: - url_label, url = url.split(",", maxsplit=1) - normalized_label = normalize_project_url_label(url_label) - if normalized_label == "homepage": - homepage = url.strip() - break - yield _PackageInfo( name=dist.raw_name, - version=dist.raw_version, + version=str(dist.version), location=dist.location or "", editable_project_location=dist.editable_project_location, requires=requires, @@ -164,12 +128,11 @@ def _get_requiring_packages(current_dist: BaseDistribution) -> Iterator[str]: metadata_version=dist.metadata_version or "", classifiers=metadata.get_all("Classifier", []), summary=metadata.get("Summary", ""), - homepage=homepage, - project_urls=project_urls, + homepage=metadata.get("Home-page", ""), + project_urls=metadata.get_all("Project-URL", []), author=metadata.get("Author", ""), author_email=metadata.get("Author-email", ""), license=metadata.get("License", ""), - license_expression=metadata.get("License-Expression", ""), entry_points=entry_points, files=files, ) @@ -189,18 +152,13 @@ def print_results( if i > 0: write_output("---") - metadata_version_tuple = tuple(map(int, dist.metadata_version.split("."))) - write_output("Name: %s", dist.name) write_output("Version: %s", dist.version) write_output("Summary: %s", dist.summary) write_output("Home-page: %s", dist.homepage) write_output("Author: %s", dist.author) write_output("Author-email: %s", dist.author_email) - if metadata_version_tuple >= (2, 4) and dist.license_expression: - write_output("License-Expression: %s", dist.license_expression) - else: - write_output("License: %s", dist.license) + write_output("License: %s", dist.license) write_output("Location: %s", dist.location) if dist.editable_project_location is not None: write_output( diff --git a/venv1/Lib/site-packages/pip/_internal/commands/uninstall.py b/venv1/Lib/site-packages/pip/_internal/commands/uninstall.py index 9c4f031f..f198fc31 100644 --- a/venv1/Lib/site-packages/pip/_internal/commands/uninstall.py +++ b/venv1/Lib/site-packages/pip/_internal/commands/uninstall.py @@ -1,11 +1,12 @@ import logging from optparse import Values +from typing import List from pip._vendor.packaging.utils import canonicalize_name from pip._internal.cli import cmdoptions from pip._internal.cli.base_command import Command -from pip._internal.cli.index_command import SessionCommandMixin +from pip._internal.cli.req_command import SessionCommandMixin, warn_if_run_as_root from pip._internal.cli.status_codes import SUCCESS from pip._internal.exceptions import InstallationError from pip._internal.req import parse_requirements @@ -16,7 +17,6 @@ from pip._internal.utils.misc import ( check_externally_managed, protect_pip_from_modification_on_windows, - warn_if_run_as_root, ) logger = logging.getLogger(__name__) @@ -61,7 +61,7 @@ def add_options(self) -> None: self.cmd_opts.add_option(cmdoptions.override_externally_managed()) self.parser.insert_option_group(0, self.cmd_opts) - def run(self, options: Values, args: list[str]) -> int: + def run(self, options: Values, args: List[str]) -> int: session = self.get_default_session(options) reqs_to_uninstall = {} diff --git a/venv1/Lib/site-packages/pip/_internal/commands/wheel.py b/venv1/Lib/site-packages/pip/_internal/commands/wheel.py index 28503940..c6a588ff 100644 --- a/venv1/Lib/site-packages/pip/_internal/commands/wheel.py +++ b/venv1/Lib/site-packages/pip/_internal/commands/wheel.py @@ -2,6 +2,7 @@ import os import shutil from optparse import Values +from typing import List from pip._internal.cache import WheelCache from pip._internal.cli import cmdoptions @@ -11,10 +12,11 @@ from pip._internal.operations.build.build_tracker import get_build_tracker from pip._internal.req.req_install import ( InstallRequirement, + check_legacy_setup_py_options, ) from pip._internal.utils.misc import ensure_dir, normalize_path from pip._internal.utils.temp_dir import TempDirectory -from pip._internal.wheel_builder import build +from pip._internal.wheel_builder import build, should_build_for_wheel_command logger = logging.getLogger(__name__) @@ -56,9 +58,9 @@ def add_options(self) -> None: self.cmd_opts.add_option(cmdoptions.prefer_binary()) self.cmd_opts.add_option(cmdoptions.no_build_isolation()) self.cmd_opts.add_option(cmdoptions.use_pep517()) + self.cmd_opts.add_option(cmdoptions.no_use_pep517()) self.cmd_opts.add_option(cmdoptions.check_build_deps()) self.cmd_opts.add_option(cmdoptions.constraints()) - self.cmd_opts.add_option(cmdoptions.build_constraints()) self.cmd_opts.add_option(cmdoptions.editable()) self.cmd_opts.add_option(cmdoptions.requirements()) self.cmd_opts.add_option(cmdoptions.src()) @@ -75,6 +77,8 @@ def add_options(self) -> None: ) self.cmd_opts.add_option(cmdoptions.config_settings()) + self.cmd_opts.add_option(cmdoptions.build_options()) + self.cmd_opts.add_option(cmdoptions.global_options()) self.cmd_opts.add_option( "--pre", @@ -97,9 +101,7 @@ def add_options(self) -> None: self.parser.insert_option_group(0, self.cmd_opts) @with_cleanup - def run(self, options: Values, args: list[str]) -> int: - cmdoptions.check_build_constraints(options) - + def run(self, options: Values, args: List[str]) -> int: session = self.get_default_session(options) finder = self._build_package_finder(options, session) @@ -116,6 +118,7 @@ def run(self, options: Values, args: list[str]) -> int: ) reqs = self.get_requirements(args, options, finder, session) + check_legacy_setup_py_options(options, reqs) wheel_cache = WheelCache(options.cache_dir) @@ -136,19 +139,18 @@ def run(self, options: Values, args: list[str]) -> int: options=options, wheel_cache=wheel_cache, ignore_requires_python=options.ignore_requires_python, + use_pep517=options.use_pep517, ) self.trace_basic_info(finder) requirement_set = resolver.resolve(reqs, check_supported_wheels=True) - preparer.prepare_linked_requirements_more(requirement_set.requirements.values()) - - reqs_to_build: list[InstallRequirement] = [] + reqs_to_build: List[InstallRequirement] = [] for req in requirement_set.requirements.values(): if req.is_wheel: preparer.save_linked_requirement(req) - else: + elif should_build_for_wheel_command(req): reqs_to_build.append(req) # build wheels @@ -156,6 +158,8 @@ def run(self, options: Values, args: list[str]) -> int: reqs_to_build, wheel_cache=wheel_cache, verify=(not options.no_verify), + build_options=options.build_options or [], + global_options=options.global_options or [], ) for req in build_successes: assert req.link and req.link.is_wheel diff --git a/venv1/Lib/site-packages/pip/_internal/configuration.py b/venv1/Lib/site-packages/pip/_internal/configuration.py index e164653b..8fd46c9b 100644 --- a/venv1/Lib/site-packages/pip/_internal/configuration.py +++ b/venv1/Lib/site-packages/pip/_internal/configuration.py @@ -11,14 +11,11 @@ A single word describing where the configuration key-value pair came from """ -from __future__ import annotations - import configparser import locale import os import sys -from collections.abc import Iterable -from typing import Any, NewType +from typing import Any, Dict, Iterable, List, NewType, Optional, Tuple from pip._internal.exceptions import ( ConfigurationError, @@ -53,21 +50,22 @@ def _normalize_name(name: str) -> str: """Make a name consistent regardless of source (environment or file)""" name = name.lower().replace("_", "-") - name = name.removeprefix("--") # only prefer long opts + if name.startswith("--"): + name = name[2:] # only prefer long opts return name -def _disassemble_key(name: str) -> list[str]: +def _disassemble_key(name: str) -> List[str]: if "." not in name: error_message = ( "Key does not contain dot separated section and key. " - f"Perhaps you wanted to use 'global.{name}' instead?" - ) + "Perhaps you wanted to use 'global.{}' instead?" + ).format(name) raise ConfigurationError(error_message) return name.split(".", 1) -def get_configuration_files() -> dict[Kind, list[str]]: +def get_configuration_files() -> Dict[Kind, List[str]]: global_config_files = [ os.path.join(path, CONFIG_BASENAME) for path in appdirs.site_config_dirs("pip") ] @@ -100,7 +98,7 @@ class Configuration: and the data stored is also nice. """ - def __init__(self, isolated: bool, load_only: Kind | None = None) -> None: + def __init__(self, isolated: bool, load_only: Optional[Kind] = None) -> None: super().__init__() if load_only is not None and load_only not in VALID_LOAD_ONLY: @@ -113,13 +111,13 @@ def __init__(self, isolated: bool, load_only: Kind | None = None) -> None: self.load_only = load_only # Because we keep track of where we got the data from - self._parsers: dict[Kind, list[tuple[str, RawConfigParser]]] = { + self._parsers: Dict[Kind, List[Tuple[str, RawConfigParser]]] = { variant: [] for variant in OVERRIDE_ORDER } - self._config: dict[Kind, dict[str, dict[str, Any]]] = { + self._config: Dict[Kind, Dict[str, Any]] = { variant: {} for variant in OVERRIDE_ORDER } - self._modified_parsers: list[tuple[str, RawConfigParser]] = [] + self._modified_parsers: List[Tuple[str, RawConfigParser]] = [] def load(self) -> None: """Loads configuration from configuration files and environment""" @@ -127,7 +125,7 @@ def load(self) -> None: if not self.isolated: self._load_environment_vars() - def get_file_to_edit(self) -> str | None: + def get_file_to_edit(self) -> Optional[str]: """Returns the file with highest priority in configuration""" assert self.load_only is not None, "Need to be specified a file to be editing" @@ -136,7 +134,7 @@ def get_file_to_edit(self) -> str | None: except IndexError: return None - def items(self) -> Iterable[tuple[str, Any]]: + def items(self) -> Iterable[Tuple[str, Any]]: """Returns key-value pairs like dict.items() representing the loaded configuration """ @@ -147,10 +145,7 @@ def get_value(self, key: str) -> Any: orig_key = key key = _normalize_name(key) try: - clean_config: dict[str, Any] = {} - for file_values in self._dictionary.values(): - clean_config.update(file_values) - return clean_config[key] + return self._dictionary[key] except KeyError: # disassembling triggers a more useful error message than simply # "No such key" in the case that the key isn't in the form command.option @@ -173,8 +168,7 @@ def set_value(self, key: str, value: Any) -> None: parser.add_section(section) parser.set(section, name, value) - self._config[self.load_only].setdefault(fname, {}) - self._config[self.load_only][fname][key] = value + self._config[self.load_only][key] = value self._mark_as_modified(fname, parser) def unset_value(self, key: str) -> None: @@ -184,14 +178,11 @@ def unset_value(self, key: str) -> None: self._ensure_have_load_only() assert self.load_only - fname, parser = self._get_parser_to_modify() - - if ( - key not in self._config[self.load_only][fname] - and key not in self._config[self.load_only] - ): + if key not in self._config[self.load_only]: raise ConfigurationError(f"No such key - {orig_key}") + fname, parser = self._get_parser_to_modify() + if parser is not None: section, name = _disassemble_key(key) if not ( @@ -206,10 +197,8 @@ def unset_value(self, key: str) -> None: if not parser.items(section): parser.remove_section(section) self._mark_as_modified(fname, parser) - try: - del self._config[self.load_only][fname][key] - except KeyError: - del self._config[self.load_only][key] + + del self._config[self.load_only][key] def save(self) -> None: """Save the current in-memory state.""" @@ -221,15 +210,8 @@ def save(self) -> None: # Ensure directory exists. ensure_dir(os.path.dirname(fname)) - # Ensure directory's permission(need to be writeable) - try: - with open(fname, "w") as f: - parser.write(f) - except OSError as error: - raise ConfigurationError( - f"An error occurred while writing to the configuration file " - f"{fname}: {error}" - ) + with open(fname, "w") as f: + parser.write(f) # # Private routines @@ -241,7 +223,7 @@ def _ensure_have_load_only(self) -> None: logger.debug("Will be working with %s variant only", self.load_only) @property - def _dictionary(self) -> dict[str, dict[str, Any]]: + def _dictionary(self) -> Dict[str, Any]: """A dictionary representing the loaded configuration.""" # NOTE: Dictionaries are not populated if not loaded. So, conditionals # are not needed here. @@ -281,8 +263,7 @@ def _load_file(self, variant: Kind, fname: str) -> RawConfigParser: for section in parser.sections(): items = parser.items(section) - self._config[variant].setdefault(fname, {}) - self._config[variant][fname].update(self._normalized_keys(section, items)) + self._config[variant].update(self._normalized_keys(section, items)) return parser @@ -309,14 +290,13 @@ def _construct_parser(self, fname: str) -> RawConfigParser: def _load_environment_vars(self) -> None: """Loads configuration from environment variables""" - self._config[kinds.ENV_VAR].setdefault(":env:", {}) - self._config[kinds.ENV_VAR][":env:"].update( + self._config[kinds.ENV_VAR].update( self._normalized_keys(":env:", self.get_environ_vars()) ) def _normalized_keys( - self, section: str, items: Iterable[tuple[str, Any]] - ) -> dict[str, Any]: + self, section: str, items: Iterable[Tuple[str, Any]] + ) -> Dict[str, Any]: """Normalizes items to construct a dictionary with normalized keys. This routine is where the names become keys and are made the same @@ -328,7 +308,7 @@ def _normalized_keys( normalized[key] = val return normalized - def get_environ_vars(self) -> Iterable[tuple[str, str]]: + def get_environ_vars(self) -> Iterable[Tuple[str, str]]: """Returns a generator with all environmental vars with prefix PIP_""" for key, val in os.environ.items(): if key.startswith("PIP_"): @@ -337,43 +317,41 @@ def get_environ_vars(self) -> Iterable[tuple[str, str]]: yield name, val # XXX: This is patched in the tests. - def iter_config_files(self) -> Iterable[tuple[Kind, list[str]]]: + def iter_config_files(self) -> Iterable[Tuple[Kind, List[str]]]: """Yields variant and configuration files associated with it. - This should be treated like items of a dictionary. The order - here doesn't affect what gets overridden. That is controlled - by OVERRIDE_ORDER. However this does control the order they are - displayed to the user. It's probably most ergonomic to display - things in the same order as OVERRIDE_ORDER + This should be treated like items of a dictionary. """ # SMELL: Move the conditions out of this function - env_config_file = os.environ.get("PIP_CONFIG_FILE", None) + # environment variables have the lowest priority + config_file = os.environ.get("PIP_CONFIG_FILE", None) + if config_file is not None: + yield kinds.ENV, [config_file] + else: + yield kinds.ENV, [] + config_files = get_configuration_files() + # at the base we have any global configuration yield kinds.GLOBAL, config_files[kinds.GLOBAL] - # per-user config is not loaded when env_config_file exists + # per-user configuration next should_load_user_config = not self.isolated and not ( - env_config_file and os.path.exists(env_config_file) + config_file and os.path.exists(config_file) ) if should_load_user_config: # The legacy config file is overridden by the new config file yield kinds.USER, config_files[kinds.USER] - # virtualenv config + # finally virtualenv configuration first trumping others yield kinds.SITE, config_files[kinds.SITE] - if env_config_file is not None: - yield kinds.ENV, [env_config_file] - else: - yield kinds.ENV, [] - - def get_values_in_config(self, variant: Kind) -> dict[str, Any]: + def get_values_in_config(self, variant: Kind) -> Dict[str, Any]: """Get values present in a config file""" return self._config[variant] - def _get_parser_to_modify(self) -> tuple[str, RawConfigParser]: + def _get_parser_to_modify(self) -> Tuple[str, RawConfigParser]: # Determine which parser to modify assert self.load_only parsers = self._parsers[self.load_only] diff --git a/venv1/Lib/site-packages/pip/_internal/distributions/base.py b/venv1/Lib/site-packages/pip/_internal/distributions/base.py index ea61f350..75ce2dc9 100644 --- a/venv1/Lib/site-packages/pip/_internal/distributions/base.py +++ b/venv1/Lib/site-packages/pip/_internal/distributions/base.py @@ -1,14 +1,9 @@ -from __future__ import annotations - import abc -from typing import TYPE_CHECKING +from pip._internal.index.package_finder import PackageFinder from pip._internal.metadata.base import BaseDistribution from pip._internal.req import InstallRequirement -if TYPE_CHECKING: - from pip._internal.build_env import BuildEnvironmentInstaller - class AbstractDistribution(metaclass=abc.ABCMeta): """A base class for handling installable artifacts. @@ -24,23 +19,12 @@ class AbstractDistribution(metaclass=abc.ABCMeta): - we must be able to create a Distribution object exposing the above metadata. - - - if we need to do work in the build tracker, we must be able to generate a unique - string to identify the requirement in the build tracker. """ def __init__(self, req: InstallRequirement) -> None: super().__init__() self.req = req - @abc.abstractproperty - def build_tracker_id(self) -> str | None: - """A string that uniquely identifies this requirement to the build tracker. - - If None, then this dist has no work to do in the build tracker, and - ``.prepare_distribution_metadata()`` will not be called.""" - raise NotImplementedError() - @abc.abstractmethod def get_metadata_distribution(self) -> BaseDistribution: raise NotImplementedError() @@ -48,7 +32,7 @@ def get_metadata_distribution(self) -> BaseDistribution: @abc.abstractmethod def prepare_distribution_metadata( self, - build_env_installer: BuildEnvironmentInstaller, + finder: PackageFinder, build_isolation: bool, check_build_deps: bool, ) -> None: diff --git a/venv1/Lib/site-packages/pip/_internal/distributions/installed.py b/venv1/Lib/site-packages/pip/_internal/distributions/installed.py index b6a67df2..edb38aa1 100644 --- a/venv1/Lib/site-packages/pip/_internal/distributions/installed.py +++ b/venv1/Lib/site-packages/pip/_internal/distributions/installed.py @@ -1,13 +1,7 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING - from pip._internal.distributions.base import AbstractDistribution +from pip._internal.index.package_finder import PackageFinder from pip._internal.metadata import BaseDistribution -if TYPE_CHECKING: - from pip._internal.build_env import BuildEnvironmentInstaller - class InstalledDistribution(AbstractDistribution): """Represents an installed package. @@ -16,17 +10,13 @@ class InstalledDistribution(AbstractDistribution): been computed. """ - @property - def build_tracker_id(self) -> str | None: - return None - def get_metadata_distribution(self) -> BaseDistribution: assert self.req.satisfied_by is not None, "not actually installed" return self.req.satisfied_by def prepare_distribution_metadata( self, - build_env_installer: BuildEnvironmentInstaller, + finder: PackageFinder, build_isolation: bool, check_build_deps: bool, ) -> None: diff --git a/venv1/Lib/site-packages/pip/_internal/distributions/sdist.py b/venv1/Lib/site-packages/pip/_internal/distributions/sdist.py index f7bd7836..4c256479 100644 --- a/venv1/Lib/site-packages/pip/_internal/distributions/sdist.py +++ b/venv1/Lib/site-packages/pip/_internal/distributions/sdist.py @@ -1,18 +1,13 @@ -from __future__ import annotations - import logging -from collections.abc import Iterable -from typing import TYPE_CHECKING +from typing import Iterable, Set, Tuple from pip._internal.build_env import BuildEnvironment from pip._internal.distributions.base import AbstractDistribution from pip._internal.exceptions import InstallationError +from pip._internal.index.package_finder import PackageFinder from pip._internal.metadata import BaseDistribution from pip._internal.utils.subprocess import runner_with_spinner_message -if TYPE_CHECKING: - from pip._internal.build_env import BuildEnvironmentInstaller - logger = logging.getLogger(__name__) @@ -20,45 +15,40 @@ class SourceDistribution(AbstractDistribution): """Represents a source distribution. The preparation step for these needs metadata for the packages to be - generated. + generated, either using PEP 517 or using the legacy `setup.py egg_info`. """ - @property - def build_tracker_id(self) -> str | None: - """Identify this requirement uniquely by its link.""" - assert self.req.link - return self.req.link.url_without_fragment - def get_metadata_distribution(self) -> BaseDistribution: return self.req.get_dist() def prepare_distribution_metadata( self, - build_env_installer: BuildEnvironmentInstaller, + finder: PackageFinder, build_isolation: bool, check_build_deps: bool, ) -> None: - # Load pyproject.toml + # Load pyproject.toml, to determine whether PEP 517 is to be used self.req.load_pyproject_toml() # Set up the build isolation, if this requirement should be isolated - if build_isolation: + should_isolate = self.req.use_pep517 and build_isolation + if should_isolate: # Setup an isolated environment and install the build backend static # requirements in it. - self._prepare_build_backend(build_env_installer) - # Check that the build backend supports PEP 660. This cannot be done - # earlier because we need to setup the build backend to verify it - # supports build_editable, nor can it be done later, because we want - # to avoid installing build requirements needlessly. - self.req.editable_sanity_check() + self._prepare_build_backend(finder) + # Check that if the requirement is editable, it either supports PEP 660 or + # has a setup.py or a setup.cfg. This cannot be done earlier because we need + # to setup the build backend to verify it supports build_editable, nor can + # it be done later, because we want to avoid installing build requirements + # needlessly. Doing it here also works around setuptools generating + # UNKNOWN.egg-info when running get_requires_for_build_wheel on a directory + # without setup.py nor setup.cfg. + self.req.isolated_editable_sanity_check() # Install the dynamic build requirements. - self._install_build_reqs(build_env_installer) - else: - # When not using build isolation, we still need to check that - # the build backend supports PEP 660. - self.req.editable_sanity_check() + self._install_build_reqs(finder) # Check if the current environment provides build dependencies - if check_build_deps: + should_check_deps = self.req.use_pep517 and check_build_deps + if should_check_deps: pyproject_requires = self.req.pyproject_requires assert pyproject_requires is not None conflicting, missing = self.req.build_env.check_requirements( @@ -70,17 +60,15 @@ def prepare_distribution_metadata( self._raise_missing_reqs(missing) self.req.prepare_metadata() - def _prepare_build_backend( - self, build_env_installer: BuildEnvironmentInstaller - ) -> None: + def _prepare_build_backend(self, finder: PackageFinder) -> None: # Isolate in a BuildEnvironment and install the build-time # requirements. pyproject_requires = self.req.pyproject_requires assert pyproject_requires is not None - self.req.build_env = BuildEnvironment(build_env_installer) + self.req.build_env = BuildEnvironment() self.req.build_env.install_requirements( - pyproject_requires, "overlay", kind="build dependencies", for_req=self.req + finder, pyproject_requires, "overlay", kind="build dependencies" ) conflicting, missing = self.req.build_env.check_requirements( self.req.requirements_to_check @@ -116,16 +104,14 @@ def _get_build_requires_editable(self) -> Iterable[str]: with backend.subprocess_runner(runner): return backend.get_requires_for_build_editable() - def _install_build_reqs( - self, build_env_installer: BuildEnvironmentInstaller - ) -> None: + def _install_build_reqs(self, finder: PackageFinder) -> None: # Install any extra build dependencies that the backend requests. # This must be done in a second pass, as the pyproject.toml # dependencies must be installed before we can call the backend. if ( self.req.editable and self.req.permit_editable_wheels - and self.req.supports_pyproject_editable + and self.req.supports_pyproject_editable() ): build_reqs = self._get_build_requires_editable() else: @@ -134,11 +120,11 @@ def _install_build_reqs( if conflicting: self._raise_conflicts("the backend dependencies", conflicting) self.req.build_env.install_requirements( - missing, "normal", kind="backend dependencies", for_req=self.req + finder, missing, "normal", kind="backend dependencies" ) def _raise_conflicts( - self, conflicting_with: str, conflicting_reqs: set[tuple[str, str]] + self, conflicting_with: str, conflicting_reqs: Set[Tuple[str, str]] ) -> None: format_string = ( "Some build dependencies for {requirement} " @@ -154,7 +140,7 @@ def _raise_conflicts( ) raise InstallationError(error_message) - def _raise_missing_reqs(self, missing: set[str]) -> None: + def _raise_missing_reqs(self, missing: Set[str]) -> None: format_string = ( "Some build dependencies for {requirement} are missing: {missing}." ) diff --git a/venv1/Lib/site-packages/pip/_internal/distributions/wheel.py b/venv1/Lib/site-packages/pip/_internal/distributions/wheel.py index ee12bfad..03aac775 100644 --- a/venv1/Lib/site-packages/pip/_internal/distributions/wheel.py +++ b/venv1/Lib/site-packages/pip/_internal/distributions/wheel.py @@ -1,19 +1,13 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING - from pip._vendor.packaging.utils import canonicalize_name from pip._internal.distributions.base import AbstractDistribution +from pip._internal.index.package_finder import PackageFinder from pip._internal.metadata import ( BaseDistribution, FilesystemWheel, get_wheel_distribution, ) -if TYPE_CHECKING: - from pip._internal.build_env import BuildEnvironmentInstaller - class WheelDistribution(AbstractDistribution): """Represents a wheel distribution. @@ -21,10 +15,6 @@ class WheelDistribution(AbstractDistribution): This does not need any preparation as wheels can be directly unpacked. """ - @property - def build_tracker_id(self) -> str | None: - return None - def get_metadata_distribution(self) -> BaseDistribution: """Loads the metadata from the wheel file into memory and returns a Distribution that uses it, not relying on the wheel file or @@ -37,7 +27,7 @@ def get_metadata_distribution(self) -> BaseDistribution: def prepare_distribution_metadata( self, - build_env_installer: BuildEnvironmentInstaller, + finder: PackageFinder, build_isolation: bool, check_build_deps: bool, ) -> None: diff --git a/venv1/Lib/site-packages/pip/_internal/exceptions.py b/venv1/Lib/site-packages/pip/_internal/exceptions.py index d6e9095f..7d92ba69 100644 --- a/venv1/Lib/site-packages/pip/_internal/exceptions.py +++ b/venv1/Lib/site-packages/pip/_internal/exceptions.py @@ -5,8 +5,6 @@ subpackage and, thus, should not depend on them. """ -from __future__ import annotations - import configparser import contextlib import locale @@ -14,23 +12,19 @@ import pathlib import re import sys -from collections.abc import Iterator from itertools import chain, groupby, repeat -from typing import TYPE_CHECKING, Literal +from typing import TYPE_CHECKING, Dict, Iterator, List, Optional, Union -from pip._vendor.packaging.requirements import InvalidRequirement -from pip._vendor.packaging.version import InvalidVersion +from pip._vendor.requests.models import Request, Response from pip._vendor.rich.console import Console, ConsoleOptions, RenderResult from pip._vendor.rich.markup import escape from pip._vendor.rich.text import Text if TYPE_CHECKING: from hashlib import _Hash - - from pip._vendor.requests.models import Request, Response + from typing import Literal from pip._internal.metadata import BaseDistribution - from pip._internal.network.download import _FileDownload from pip._internal.req.req_install import InstallRequirement logger = logging.getLogger(__name__) @@ -44,7 +38,7 @@ def _is_kebab_case(s: str) -> bool: def _prefix_with_indent( - s: Text | str, + s: Union[Text, str], console: Console, *, prefix: str, @@ -80,13 +74,13 @@ class DiagnosticPipError(PipError): def __init__( self, *, - kind: Literal["error", "warning"] = "error", - reference: str | None = None, - message: str | Text, - context: str | Text | None, - hint_stmt: str | Text | None, - note_stmt: str | Text | None = None, - link: str | None = None, + kind: 'Literal["error", "warning"]' = "error", + reference: Optional[str] = None, + message: Union[str, Text], + context: Optional[Union[str, Text]], + hint_stmt: Optional[Union[str, Text]], + note_stmt: Optional[Union[str, Text]] = None, + link: Optional[str] = None, ) -> None: # Ensure a proper reference is provided. if reference is None: @@ -190,21 +184,8 @@ class InstallationError(PipError): """General exception during installation""" -class FailedToPrepareCandidate(InstallationError): - """Raised when we fail to prepare a candidate (i.e. fetch and generate metadata). - - This is intentionally not a diagnostic error, since the output will be presented - above this error, when this occurs. This should instead present information to the - user. - """ - - def __init__( - self, *, package_name: str, requirement_chain: str, failed_step: str - ) -> None: - super().__init__(f"Failed to build '{package_name}' when {failed_step.lower()}") - self.package_name = package_name - self.requirement_chain = requirement_chain - self.failed_step = failed_step +class UninstallationError(PipError): + """General exception during uninstallation""" class MissingPyProjectBuildRequires(DiagnosticPipError): @@ -252,7 +233,7 @@ class NoneMetadataError(PipError): def __init__( self, - dist: BaseDistribution, + dist: "BaseDistribution", metadata_name: str, ) -> None: """ @@ -266,7 +247,10 @@ def __init__( def __str__(self) -> str: # Use `dist` in the error message because its stringification # includes more information, like the version and location. - return f"None {self.metadata_name} metadata found for distribution: {self.dist}" + return "None {} metadata found for distribution: {}".format( + self.metadata_name, + self.dist, + ) class UserInstallationInvalid(InstallationError): @@ -313,8 +297,8 @@ class NetworkConnectionError(PipError): def __init__( self, error_msg: str, - response: Response | None = None, - request: Request | None = None, + response: Optional[Response] = None, + request: Optional[Request] = None, ) -> None: """ Initialize NetworkConnectionError with `request` and `response` @@ -363,7 +347,7 @@ class MetadataInconsistent(InstallationError): """ def __init__( - self, ireq: InstallRequirement, field: str, f_val: str, m_val: str + self, ireq: "InstallRequirement", field: str, f_val: str, m_val: str ) -> None: self.ireq = ireq self.field = field @@ -377,17 +361,6 @@ def __str__(self) -> str: ) -class MetadataInvalid(InstallationError): - """Metadata is invalid.""" - - def __init__(self, ireq: InstallRequirement, error: str) -> None: - self.ireq = ireq - self.error = error - - def __str__(self) -> str: - return f"Requested {self.ireq} has invalid metadata: {self.error}" - - class InstallationSubprocessError(DiagnosticPipError, InstallationError): """A subprocess call failed.""" @@ -398,10 +371,10 @@ def __init__( *, command_description: str, exit_code: int, - output_lines: list[str] | None, + output_lines: Optional[List[str]], ) -> None: if output_lines is None: - output_prompt = Text("No available output.") + output_prompt = Text("See above for output.") else: output_prompt = ( Text.from_markup(f"[red][{len(output_lines)} lines of output][/]\n") @@ -429,7 +402,7 @@ def __str__(self) -> str: return f"{self.command_description} exited with {self.exit_code}" -class MetadataGenerationFailed(DiagnosticPipError, InstallationError): +class MetadataGenerationFailed(InstallationSubprocessError, InstallationError): reference = "metadata-generation-failed" def __init__( @@ -437,7 +410,7 @@ def __init__( *, package_details: str, ) -> None: - super().__init__( + super(InstallationSubprocessError, self).__init__( message="Encountered error while generating package metadata.", context=escape(package_details), hint_stmt="See above for details.", @@ -452,9 +425,9 @@ 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: + def append(self, error: "HashError") -> None: self.errors.append(error) def __str__(self) -> str: @@ -488,7 +461,7 @@ class HashError(InstallationError): """ - req: InstallRequirement | None = None + req: Optional["InstallRequirement"] = None head = "" order: int = -1 @@ -571,7 +544,7 @@ def body(self) -> str: # so the output can be directly copied into the requirements file. package = ( self.req.original_link - if self.req.is_direct + if self.req.original_link # In case someone feeds something downright stupid # to InstallRequirement's constructor. else getattr(self.req, "req", None) @@ -610,7 +583,7 @@ class HashMismatch(HashError): "someone may have tampered with them." ) - def __init__(self, allowed: dict[str, list[str]], gots: dict[str, _Hash]) -> None: + def __init__(self, allowed: Dict[str, List[str]], gots: Dict[str, "_Hash"]) -> None: """ :param allowed: A dict of algorithm names pointing to lists of allowed hex digests @@ -621,7 +594,7 @@ def __init__(self, allowed: dict[str, list[str]], gots: dict[str, _Hash]) -> Non self.gots = gots def body(self) -> str: - return f" {self._requirement_name()}:\n{self._hash_comparison()}" + return " {}:\n{}".format(self._requirement_name(), self._hash_comparison()) def _hash_comparison(self) -> str: """ @@ -635,17 +608,19 @@ def _hash_comparison(self) -> str: """ - def hash_then_or(hash_name: str) -> chain[str]: + def hash_then_or(hash_name: str) -> "chain[str]": # For now, all the decent hashes have 6-char names, so we can get # away with hard-coding space literals. return chain([hash_name], repeat(" or")) - lines: list[str] = [] + lines: List[str] = [] for hash_name, expecteds in self.allowed.items(): prefix = hash_then_or(hash_name) - lines.extend((f" Expected {next(prefix)} {e}") for e in expecteds) + lines.extend( + (" Expected {} {}".format(next(prefix), e)) for e in expecteds + ) lines.append( - f" Got {self.gots[hash_name].hexdigest()}\n" + " Got {}\n".format(self.gots[hash_name].hexdigest()) ) return "\n".join(lines) @@ -661,8 +636,8 @@ class ConfigurationFileCouldNotBeLoaded(ConfigurationError): def __init__( self, reason: str = "could not be loaded", - fname: str | None = None, - error: configparser.Error | None = None, + fname: Optional[str] = None, + error: Optional[configparser.Error] = None, ) -> None: super().__init__(error) self.reason = reason @@ -697,7 +672,7 @@ class ExternallyManagedEnvironment(DiagnosticPipError): reference = "externally-managed-environment" - def __init__(self, error: str | None) -> None: + def __init__(self, error: Optional[str]) -> None: if error is None: context = Text(_DEFAULT_EXTERNALLY_MANAGED_ERROR) else: @@ -724,7 +699,7 @@ def _iter_externally_managed_error_keys() -> Iterator[str]: try: category = locale.LC_MESSAGES except AttributeError: - lang: str | None = None + lang: Optional[str] = None else: lang, _ = locale.getlocale(category) if lang is not None: @@ -739,8 +714,8 @@ def _iter_externally_managed_error_keys() -> Iterator[str]: @classmethod def from_config( cls, - config: pathlib.Path | str, - ) -> ExternallyManagedEnvironment: + config: Union[pathlib.Path, str], + ) -> "ExternallyManagedEnvironment": parser = configparser.ConfigParser(interpolation=None) try: parser.read(config, encoding="utf-8") @@ -756,143 +731,3 @@ def from_config( exc_info = logger.isEnabledFor(VERBOSE) logger.warning("Failed to read %s", config, exc_info=exc_info) return cls(None) - - -class UninstallMissingRecord(DiagnosticPipError): - reference = "uninstall-no-record-file" - - def __init__(self, *, distribution: BaseDistribution) -> None: - installer = distribution.installer - if not installer or installer == "pip": - dep = f"{distribution.raw_name}=={distribution.version}" - hint = Text.assemble( - "You might be able to recover from this via: ", - (f"pip install --force-reinstall --no-deps {dep}", "green"), - ) - else: - hint = Text( - f"The package was installed by {installer}. " - "You should check if it can uninstall the package." - ) - - super().__init__( - message=Text(f"Cannot uninstall {distribution}"), - context=( - "The package's contents are unknown: " - f"no RECORD file was found for {distribution.raw_name}." - ), - hint_stmt=hint, - ) - - -class LegacyDistutilsInstall(DiagnosticPipError): - reference = "uninstall-distutils-installed-package" - - def __init__(self, *, distribution: BaseDistribution) -> None: - super().__init__( - message=Text(f"Cannot uninstall {distribution}"), - context=( - "It is a distutils installed project and thus we cannot accurately " - "determine which files belong to it which would lead to only a partial " - "uninstall." - ), - hint_stmt=None, - ) - - -class InvalidInstalledPackage(DiagnosticPipError): - reference = "invalid-installed-package" - - def __init__( - self, - *, - dist: BaseDistribution, - invalid_exc: 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.", - ) - - -class IncompleteDownloadError(DiagnosticPipError): - """Raised when the downloader receives fewer bytes than advertised - in the Content-Length header.""" - - reference = "incomplete-download" - - def __init__(self, download: _FileDownload) -> None: - # Dodge circular import. - from pip._internal.utils.misc import format_size - - assert download.size is not None - download_status = ( - f"{format_size(download.bytes_received)}/{format_size(download.size)}" - ) - if download.reattempts: - retry_status = f"after {download.reattempts + 1} attempts " - hint = "Use --resume-retries to configure resume attempt limit." - else: - # Download retrying is not enabled. - retry_status = "" - hint = "Consider using --resume-retries to enable download resumption." - message = Text( - f"Download failed {retry_status}because not enough bytes " - f"were received ({download_status})" - ) - - super().__init__( - message=message, - context=f"URL: {download.link.redacted_url}", - hint_stmt=hint, - note_stmt="This is an issue with network connectivity, not pip.", - ) - - -class ResolutionTooDeepError(DiagnosticPipError): - """Raised when the dependency resolver exceeds the maximum recursion depth.""" - - reference = "resolution-too-deep" - - def __init__(self) -> None: - super().__init__( - message="Dependency resolution exceeded maximum depth", - context=( - "Pip cannot resolve the current dependencies as the dependency graph " - "is too complex for pip to solve efficiently." - ), - hint_stmt=( - "Try adding lower bounds to constrain your dependencies, " - "for example: 'package>=2.0.0' instead of just 'package'. " - ), - link="https://pip.pypa.io/en/stable/topics/dependency-resolution/#handling-resolution-too-deep-errors", - ) - - -class InstallWheelBuildError(DiagnosticPipError): - reference = "failed-wheel-build-for-install" - - def __init__(self, failed: list[InstallRequirement]) -> None: - super().__init__( - message=( - "Failed to build installable wheels for some " - "pyproject.toml based projects" - ), - context=", ".join(r.name for r in failed), # type: ignore - hint_stmt=None, - ) diff --git a/venv1/Lib/site-packages/pip/_internal/index/__init__.py b/venv1/Lib/site-packages/pip/_internal/index/__init__.py index 197dd757..7a17b7b3 100644 --- a/venv1/Lib/site-packages/pip/_internal/index/__init__.py +++ b/venv1/Lib/site-packages/pip/_internal/index/__init__.py @@ -1 +1,2 @@ -"""Index interaction code""" +"""Index interaction code +""" diff --git a/venv1/Lib/site-packages/pip/_internal/index/collector.py b/venv1/Lib/site-packages/pip/_internal/index/collector.py index 00d66daa..b3e293ea 100644 --- a/venv1/Lib/site-packages/pip/_internal/index/collector.py +++ b/venv1/Lib/site-packages/pip/_internal/index/collector.py @@ -2,8 +2,6 @@ The main purpose of this module is to expose LinkCollector.collect_sources(). """ -from __future__ import annotations - import collections import email.message import functools @@ -13,14 +11,20 @@ import os import urllib.parse import urllib.request -from collections.abc import Iterable, MutableMapping, Sequence -from dataclasses import dataclass from html.parser import HTMLParser from optparse import Values from typing import ( + TYPE_CHECKING, Callable, + Dict, + Iterable, + List, + MutableMapping, NamedTuple, - Protocol, + Optional, + Sequence, + Tuple, + Union, ) from pip._vendor import requests @@ -38,12 +42,17 @@ from .sources import CandidatesFromPage, LinkSource, build_source +if TYPE_CHECKING: + from typing import Protocol +else: + Protocol = object + logger = logging.getLogger(__name__) ResponseHeaders = MutableMapping[str, str] -def _match_vcs_scheme(url: str) -> str | None: +def _match_vcs_scheme(url: str) -> Optional[str]: """Look for VCS schemes in the URL. Returns the matched VCS scheme, or None if there's no match. @@ -168,7 +177,7 @@ def _get_simple_response(url: str, session: PipSession) -> Response: return resp -def _get_encoding_from_headers(headers: ResponseHeaders) -> str | None: +def _get_encoding_from_headers(headers: ResponseHeaders) -> Optional[str]: """Determine if we have any encoding information in our headers.""" if headers and "Content-Type" in headers: m = email.message.Message() @@ -180,7 +189,7 @@ def _get_encoding_from_headers(headers: ResponseHeaders) -> str | None: class CacheablePageContent: - def __init__(self, page: IndexContent) -> None: + def __init__(self, page: "IndexContent") -> None: assert page.cache_link_parsing self.page = page @@ -192,7 +201,8 @@ def __hash__(self) -> int: class ParseLinks(Protocol): - def __call__(self, page: IndexContent) -> Iterable[Link]: ... + def __call__(self, page: "IndexContent") -> Iterable[Link]: + ... def with_cached_index_content(fn: ParseLinks) -> ParseLinks: @@ -202,12 +212,12 @@ def with_cached_index_content(fn: ParseLinks) -> ParseLinks: `page` has `page.cache_link_parsing == False`. """ - @functools.cache - def wrapper(cacheable_page: CacheablePageContent) -> list[Link]: + @functools.lru_cache(maxsize=None) + def wrapper(cacheable_page: CacheablePageContent) -> List[Link]: return list(fn(cacheable_page.page)) @functools.wraps(fn) - def wrapper_wrapper(page: IndexContent) -> list[Link]: + def wrapper_wrapper(page: "IndexContent") -> List[Link]: if page.cache_link_parsing: return wrapper(CacheablePageContent(page)) return list(fn(page)) @@ -216,7 +226,7 @@ def wrapper_wrapper(page: IndexContent) -> list[Link]: @with_cached_index_content -def parse_links(page: IndexContent) -> Iterable[Link]: +def parse_links(page: "IndexContent") -> Iterable[Link]: """ Parse a Simple API's Index Content, and yield its anchor elements as Link objects. """ @@ -244,22 +254,29 @@ def parse_links(page: IndexContent) -> Iterable[Link]: yield link -@dataclass(frozen=True) class IndexContent: - """Represents one response (or page), along with its URL. - - :param encoding: the encoding to decode the given content. - :param url: the URL from which the HTML was downloaded. - :param cache_link_parsing: whether links parsed from this page's url - should be cached. PyPI index urls should - have this set to False, for example. - """ + """Represents one response (or page), along with its URL""" - content: bytes - content_type: str - encoding: str | None - url: str - cache_link_parsing: bool = True + def __init__( + self, + content: bytes, + content_type: str, + encoding: Optional[str], + url: str, + cache_link_parsing: bool = True, + ) -> None: + """ + :param encoding: the encoding to decode the given content. + :param url: the URL from which the HTML was downloaded. + :param cache_link_parsing: whether links parsed from this page's url + should be cached. PyPI index urls should + have this set to False, for example. + """ + self.content = content + self.content_type = content_type + self.encoding = encoding + self.url = url + self.cache_link_parsing = cache_link_parsing def __str__(self) -> str: return redact_auth_from_url(self.url) @@ -275,10 +292,10 @@ def __init__(self, url: str) -> None: super().__init__(convert_charrefs=True) self.url: str = url - self.base_url: str | None = None - self.anchors: list[dict[str, str | None]] = [] + self.base_url: Optional[str] = None + self.anchors: List[Dict[str, Optional[str]]] = [] - def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None: + def handle_starttag(self, tag: str, attrs: List[Tuple[str, Optional[str]]]) -> None: if tag == "base" and self.base_url is None: href = self.get_href(attrs) if href is not None: @@ -286,7 +303,7 @@ def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None elif tag == "a": self.anchors.append(dict(attrs)) - def get_href(self, attrs: list[tuple[str, str | None]]) -> str | None: + def get_href(self, attrs: List[Tuple[str, Optional[str]]]) -> Optional[str]: for name, value in attrs: if name == "href": return value @@ -295,8 +312,8 @@ def get_href(self, attrs: list[tuple[str, str | None]]) -> str | None: def _handle_get_simple_fail( link: Link, - reason: str | Exception, - meth: Callable[..., None] | None = None, + reason: Union[str, Exception], + meth: Optional[Callable[..., None]] = None, ) -> None: if meth is None: meth = logger.debug @@ -316,7 +333,7 @@ def _make_index_content( ) -def _get_index_content(link: Link, *, session: PipSession) -> IndexContent | None: +def _get_index_content(link: Link, *, session: PipSession) -> Optional["IndexContent"]: url = link.url.split("#", 1)[0] # Check for VCS schemes that do not support lookup as web pages. @@ -378,11 +395,12 @@ def _get_index_content(link: Link, *, session: PipSession) -> IndexContent | Non class CollectedSources(NamedTuple): - find_links: Sequence[LinkSource | None] - index_urls: Sequence[LinkSource | None] + find_links: Sequence[Optional[LinkSource]] + index_urls: Sequence[Optional[LinkSource]] class LinkCollector: + """ Responsible for collecting Link objects from all configured locations, making network requests as needed. @@ -404,7 +422,7 @@ def create( session: PipSession, options: Values, suppress_no_index: bool = False, - ) -> LinkCollector: + ) -> "LinkCollector": """ :param session: The Session to use to make requests. :param suppress_no_index: Whether to ignore the --no-index option @@ -433,10 +451,10 @@ def create( return link_collector @property - def find_links(self) -> list[str]: + def find_links(self) -> List[str]: return self.search_scope.find_links - def fetch_response(self, location: Link) -> IndexContent | None: + def fetch_response(self, location: Link) -> Optional[IndexContent]: """ Fetch an HTML page containing package links. """ @@ -455,7 +473,6 @@ def collect_sources( page_validator=self.session.is_secure_origin, expand_dir=False, cache_link_parsing=False, - project_name=project_name, ) for loc in self.search_scope.get_index_urls_locations(project_name) ).values() @@ -466,7 +483,6 @@ def collect_sources( page_validator=self.session.is_secure_origin, expand_dir=True, cache_link_parsing=True, - project_name=project_name, ) for loc in self.find_links ).values() diff --git a/venv1/Lib/site-packages/pip/_internal/index/package_finder.py b/venv1/Lib/site-packages/pip/_internal/index/package_finder.py index ae6f8962..b6f8d57e 100644 --- a/venv1/Lib/site-packages/pip/_internal/index/package_finder.py +++ b/venv1/Lib/site-packages/pip/_internal/index/package_finder.py @@ -1,24 +1,16 @@ """Routines related to PyPI, indexes""" -from __future__ import annotations - import enum import functools import itertools import logging import re -from collections.abc import Iterable -from dataclasses import dataclass -from typing import ( - TYPE_CHECKING, - Optional, - Union, -) +from typing import TYPE_CHECKING, FrozenSet, Iterable, List, Optional, Set, Tuple, Union from pip._vendor.packaging import specifiers from pip._vendor.packaging.tags import Tag -from pip._vendor.packaging.utils import NormalizedName, canonicalize_name -from pip._vendor.packaging.version import InvalidVersion, _BaseVersion +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.packaging.version import _BaseVersion from pip._vendor.packaging.version import parse as parse_version from pip._internal.exceptions import ( @@ -45,20 +37,20 @@ from pip._internal.utils.unpacking import SUPPORTED_EXTENSIONS if TYPE_CHECKING: - from typing_extensions import TypeGuard + from pip._vendor.typing_extensions import TypeGuard __all__ = ["FormatControl", "BestCandidateResult", "PackageFinder"] logger = getLogger(__name__) -BuildTag = Union[tuple[()], tuple[int, str]] -CandidateSortingKey = tuple[int, int, int, _BaseVersion, Optional[int], BuildTag] +BuildTag = Union[Tuple[()], Tuple[int, str]] +CandidateSortingKey = Tuple[int, int, int, _BaseVersion, Optional[int], BuildTag] def _check_link_requires_python( link: Link, - version_info: tuple[int, int, int], + version_info: Tuple[int, int, int], ignore_requires_python: bool = False, ) -> bool: """ @@ -114,6 +106,7 @@ class LinkType(enum.Enum): class LinkEvaluator: + """ Responsible for evaluating links for a particular project. """ @@ -127,11 +120,11 @@ class LinkEvaluator: def __init__( self, project_name: str, - canonical_name: NormalizedName, - formats: frozenset[str], + canonical_name: str, + formats: FrozenSet[str], target_python: TargetPython, allow_yanked: bool, - ignore_requires_python: bool | None = None, + ignore_requires_python: Optional[bool] = None, ) -> None: """ :param project_name: The user supplied package name. @@ -161,7 +154,7 @@ def __init__( self.project_name = project_name - def evaluate_link(self, link: Link) -> tuple[LinkType, str]: + def evaluate_link(self, link: Link) -> Tuple[LinkType, str]: """ Determine whether a link is a candidate for installation. @@ -201,11 +194,11 @@ def evaluate_link(self, link: Link) -> tuple[LinkType, str]: LinkType.format_invalid, "invalid wheel filename", ) - if wheel.name != self._canonical_name: + if canonicalize_name(wheel.name) != self._canonical_name: reason = f"wrong project name (not {self.project_name})" return (LinkType.different_project, reason) - supported_tags = self._target_python.get_unsorted_tags() + supported_tags = self._target_python.get_tags() if not wheel.supported(supported_tags): # Include the wheel's tags in the reason string to # simplify troubleshooting compatibility issues. @@ -248,19 +241,7 @@ def evaluate_link(self, link: Link) -> tuple[LinkType, str]: ignore_requires_python=self._ignore_requires_python, ) if not supports_python: - requires_python = link.requires_python - if requires_python: - - def get_version_sort_key(v: str) -> tuple[int, ...]: - return tuple(int(s) for s in v.split(".") if s.isdigit()) - - requires_python = ",".join( - sorted( - (str(s) for s in specifiers.SpecifierSet(requires_python)), - key=get_version_sort_key, - ) - ) - reason = f"{version} Requires-Python {requires_python}" + reason = f"{version} Requires-Python {link.requires_python}" return (LinkType.requires_python_mismatch, reason) logger.debug("Found link %s, version: %s", link, version) @@ -269,10 +250,10 @@ def get_version_sort_key(v: str) -> tuple[int, ...]: def filter_unallowed_hashes( - candidates: list[InstallationCandidate], - hashes: Hashes | None, + candidates: List[InstallationCandidate], + hashes: Optional[Hashes], project_name: str, -) -> list[InstallationCandidate]: +) -> List[InstallationCandidate]: """ Filter out candidates whose hashes aren't allowed, and return a new list of candidates. @@ -342,44 +323,67 @@ def filter_unallowed_hashes( return filtered -@dataclass class CandidatePreferences: + """ Encapsulates some of the preferences for filtering and sorting InstallationCandidate objects. """ - prefer_binary: bool = False - allow_all_prereleases: bool = False + def __init__( + self, + prefer_binary: bool = False, + allow_all_prereleases: bool = False, + ) -> None: + """ + :param allow_all_prereleases: Whether to allow all pre-releases. + """ + self.allow_all_prereleases = allow_all_prereleases + self.prefer_binary = prefer_binary -@dataclass(frozen=True) class BestCandidateResult: """A collection of candidates, returned by `PackageFinder.find_best_candidate`. This class is only intended to be instantiated by CandidateEvaluator's `compute_best_candidate()` method. - - :param all_candidates: A sequence of all available candidates found. - :param applicable_candidates: The applicable candidates. - :param best_candidate: The most preferred candidate found, or None - if no applicable candidates were found. """ - all_candidates: list[InstallationCandidate] - applicable_candidates: list[InstallationCandidate] - best_candidate: InstallationCandidate | None - - def __post_init__(self) -> None: - assert set(self.applicable_candidates) <= set(self.all_candidates) + def __init__( + self, + candidates: List[InstallationCandidate], + applicable_candidates: List[InstallationCandidate], + best_candidate: Optional[InstallationCandidate], + ) -> None: + """ + :param candidates: A sequence of all available candidates found. + :param applicable_candidates: The applicable candidates. + :param best_candidate: The most preferred candidate found, or None + if no applicable candidates were found. + """ + assert set(applicable_candidates) <= set(candidates) - if self.best_candidate is None: - assert not self.applicable_candidates + if best_candidate is None: + assert not applicable_candidates else: - assert self.best_candidate in self.applicable_candidates + assert best_candidate in applicable_candidates + + self._applicable_candidates = applicable_candidates + self._candidates = candidates + + self.best_candidate = best_candidate + + def iter_all(self) -> Iterable[InstallationCandidate]: + """Iterate through all candidates.""" + return iter(self._candidates) + + def iter_applicable(self) -> Iterable[InstallationCandidate]: + """Iterate through the applicable candidates.""" + return iter(self._applicable_candidates) class CandidateEvaluator: + """ Responsible for filtering and sorting candidates for installation based on what tags are valid. @@ -389,12 +393,12 @@ class CandidateEvaluator: def create( cls, project_name: str, - target_python: TargetPython | None = None, + target_python: Optional[TargetPython] = None, prefer_binary: bool = False, allow_all_prereleases: bool = False, - specifier: specifiers.BaseSpecifier | None = None, - hashes: Hashes | None = None, - ) -> CandidateEvaluator: + specifier: Optional[specifiers.BaseSpecifier] = None, + hashes: Optional[Hashes] = None, + ) -> "CandidateEvaluator": """Create a CandidateEvaluator object. :param target_python: The target Python interpreter to use when @@ -410,7 +414,7 @@ def create( if specifier is None: specifier = specifiers.SpecifierSet() - supported_tags = target_python.get_sorted_tags() + supported_tags = target_python.get_tags() return cls( project_name=project_name, @@ -424,11 +428,11 @@ def create( def __init__( self, project_name: str, - supported_tags: list[Tag], + supported_tags: List[Tag], specifier: specifiers.BaseSpecifier, prefer_binary: bool = False, allow_all_prereleases: bool = False, - hashes: Hashes | None = None, + hashes: Optional[Hashes] = None, ) -> None: """ :param supported_tags: The PEP 425 tags supported by the target @@ -449,31 +453,32 @@ def __init__( def get_applicable_candidates( self, - candidates: list[InstallationCandidate], - ) -> list[InstallationCandidate]: + candidates: List[InstallationCandidate], + ) -> List[InstallationCandidate]: """ Return the applicable candidates from a list of candidates. """ # Using None infers from the specifier instead. allow_prereleases = self._allow_all_prereleases or None specifier = self._specifier - - # We turn the version object into a str here because otherwise - # when we're debundled but setuptools isn't, Python will see - # packaging.version.Version and - # pkg_resources._vendor.packaging.version.Version as different - # types. This way we'll use a str as a common data interchange - # format. If we stop using the pkg_resources provided specifier - # and start using our own, we can drop the cast to str(). - candidates_and_versions = [(c, str(c.version)) for c in candidates] - versions = set( - specifier.filter( - (v for _, v in candidates_and_versions), + versions = { + str(v) + for v in specifier.filter( + # We turn the version object into a str here because otherwise + # when we're debundled but setuptools isn't, Python will see + # packaging.version.Version and + # pkg_resources._vendor.packaging.version.Version as different + # types. This way we'll use a str as a common data interchange + # format. If we stop using the pkg_resources provided specifier + # and start using our own, we can drop the cast to str(). + (str(c.version) for c in candidates), prereleases=allow_prereleases, ) - ) + } + + # Again, converting version to str to deal with debundling. + applicable_candidates = [c for c in candidates if str(c.version) in versions] - applicable_candidates = [c for c, v in candidates_and_versions if v in versions] filtered_applicable_candidates = filter_unallowed_hashes( candidates=applicable_candidates, hashes=self._hashes, @@ -528,12 +533,16 @@ def _sort_key(self, candidate: InstallationCandidate) -> CandidateSortingKey: ) except ValueError: raise UnsupportedWheel( - f"{wheel.filename} is not a supported wheel for this platform. It " - "can't be sorted." + "{} is not a supported wheel for this platform. It " + "can't be sorted.".format(wheel.filename) ) if self._prefer_binary: binary_preference = 1 - build_tag = wheel.build_tag + if wheel.build_tag is not None: + match = re.match(r"^(\d+)(.*)$", wheel.build_tag) + assert match is not None, "guaranteed by filename validation" + build_tag_groups = match.groups() + build_tag = (int(build_tag_groups[0]), build_tag_groups[1]) else: # sdist pri = -(support_num) has_allowed_hash = int(link.is_hash_allowed(self._hashes)) @@ -549,8 +558,8 @@ def _sort_key(self, candidate: InstallationCandidate) -> CandidateSortingKey: def sort_best_candidate( self, - candidates: list[InstallationCandidate], - ) -> InstallationCandidate | None: + candidates: List[InstallationCandidate], + ) -> Optional[InstallationCandidate]: """ Return the best candidate per the instance's sort order, or None if no candidate is acceptable. @@ -562,7 +571,7 @@ def sort_best_candidate( def compute_best_candidate( self, - candidates: list[InstallationCandidate], + candidates: List[InstallationCandidate], ) -> BestCandidateResult: """ Compute and return a `BestCandidateResult` instance. @@ -590,9 +599,9 @@ def __init__( link_collector: LinkCollector, target_python: TargetPython, allow_yanked: bool, - format_control: FormatControl | None = None, - candidate_prefs: CandidatePreferences | None = None, - ignore_requires_python: bool | None = None, + format_control: Optional[FormatControl] = None, + candidate_prefs: Optional[CandidatePreferences] = None, + ignore_requires_python: Optional[bool] = None, ) -> None: """ This constructor is primarily meant to be used by the create() class @@ -618,14 +627,7 @@ def __init__( self.format_control = format_control # These are boring links that have already been logged somehow. - self._logged_links: set[tuple[Link, LinkType, str]] = set() - - # Cache of the result of finding candidates - self._all_candidates: dict[str, list[InstallationCandidate]] = {} - self._best_candidates: dict[ - tuple[str, specifiers.BaseSpecifier | None, Hashes | None], - BestCandidateResult, - ] = {} + self._logged_links: Set[Tuple[Link, LinkType, str]] = set() # Don't include an allow_yanked default value to make sure each call # site considers whether yanked releases are allowed. This also causes @@ -636,8 +638,8 @@ def create( cls, link_collector: LinkCollector, selection_prefs: SelectionPreferences, - target_python: TargetPython | None = None, - ) -> PackageFinder: + target_python: Optional[TargetPython] = None, + ) -> "PackageFinder": """Create a PackageFinder. :param selection_prefs: The candidate selection preferences, as a @@ -676,36 +678,18 @@ def search_scope(self, search_scope: SearchScope) -> None: self._link_collector.search_scope = search_scope @property - def find_links(self) -> list[str]: + def find_links(self) -> List[str]: return self._link_collector.find_links @property - def index_urls(self) -> list[str]: + def index_urls(self) -> List[str]: return self.search_scope.index_urls - @property - def proxy(self) -> str | None: - return self._link_collector.session.pip_proxy - @property def trusted_hosts(self) -> Iterable[str]: for host_port in self._link_collector.session.pip_trusted_origins: yield build_netloc(*host_port) - @property - def custom_cert(self) -> str | None: - # session.verify is either a boolean (use default bundle/no SSL - # verification) or a string path to a custom CA bundle to use. We only - # care about the latter. - verify = self._link_collector.session.verify - return verify if isinstance(verify, str) else None - - @property - def client_cert(self) -> str | None: - cert = self._link_collector.session.cert - assert not isinstance(cert, tuple), "pip only supports PEM client certs" - return cert - @property def allow_all_prereleases(self) -> bool: return self._candidate_prefs.allow_all_prereleases @@ -720,7 +704,7 @@ def prefer_binary(self) -> bool: def set_prefer_binary(self) -> None: self._candidate_prefs.prefer_binary = True - def requires_python_skipped_reasons(self) -> list[str]: + def requires_python_skipped_reasons(self) -> List[str]: reasons = { detail for _, result, detail in self._logged_links @@ -741,13 +725,13 @@ def make_link_evaluator(self, project_name: str) -> LinkEvaluator: ignore_requires_python=self._ignore_requires_python, ) - def _sort_links(self, links: Iterable[Link]) -> list[Link]: + def _sort_links(self, links: Iterable[Link]) -> List[Link]: """ Returns elements of links in order, non-egg links first, egg links second, while eliminating duplicates """ eggs, no_eggs = [], [] - seen: set[Link] = set() + seen: Set[Link] = set() for link in links: if link not in seen: seen.add(link) @@ -767,7 +751,7 @@ def _log_skipped_link(self, link: Link, result: LinkType, detail: str) -> None: def get_install_candidate( self, link_evaluator: LinkEvaluator, link: Link - ) -> InstallationCandidate | None: + ) -> Optional[InstallationCandidate]: """ If the link is a candidate for install, convert it to an InstallationCandidate and return it. Otherwise, return None. @@ -777,18 +761,15 @@ def get_install_candidate( self._log_skipped_link(link, result, detail) return None - try: - return InstallationCandidate( - name=link_evaluator.project_name, - link=link, - version=detail, - ) - except InvalidVersion: - return None + return InstallationCandidate( + name=link_evaluator.project_name, + link=link, + version=detail, + ) def evaluate_links( self, link_evaluator: LinkEvaluator, links: Iterable[Link] - ) -> list[InstallationCandidate]: + ) -> List[InstallationCandidate]: """ Convert links that are candidates to InstallationCandidate objects. """ @@ -802,7 +783,7 @@ def evaluate_links( def process_project_url( self, project_url: Link, link_evaluator: LinkEvaluator - ) -> list[InstallationCandidate]: + ) -> List[InstallationCandidate]: logger.debug( "Fetching project page and analyzing links: %s", project_url, @@ -821,7 +802,8 @@ def process_project_url( return package_links - def find_all_candidates(self, project_name: str) -> list[InstallationCandidate]: + @functools.lru_cache(maxsize=None) + def find_all_candidates(self, project_name: str) -> List[InstallationCandidate]: """Find all available InstallationCandidate for project_name This checks index_urls and find_links. @@ -830,9 +812,6 @@ def find_all_candidates(self, project_name: str) -> list[InstallationCandidate]: See LinkEvaluator.evaluate_link() for details on which files are accepted. """ - if project_name in self._all_candidates: - return self._all_candidates[project_name] - link_evaluator = self.make_link_evaluator(project_name) collected_sources = self._link_collector.collect_sources( @@ -874,15 +853,13 @@ def find_all_candidates(self, project_name: str) -> list[InstallationCandidate]: logger.debug("Local files found: %s", ", ".join(paths)) # This is an intentional priority ordering - self._all_candidates[project_name] = file_candidates + page_candidates - - return self._all_candidates[project_name] + return file_candidates + page_candidates def make_candidate_evaluator( self, project_name: str, - specifier: specifiers.BaseSpecifier | None = None, - hashes: Hashes | None = None, + specifier: Optional[specifiers.BaseSpecifier] = None, + hashes: Optional[Hashes] = None, ) -> CandidateEvaluator: """Create a CandidateEvaluator object to use.""" candidate_prefs = self._candidate_prefs @@ -895,11 +872,12 @@ def make_candidate_evaluator( hashes=hashes, ) + @functools.lru_cache(maxsize=None) def find_best_candidate( self, project_name: str, - specifier: specifiers.BaseSpecifier | None = None, - hashes: Hashes | None = None, + specifier: Optional[specifiers.BaseSpecifier] = None, + hashes: Optional[Hashes] = None, ) -> BestCandidateResult: """Find matches for the given project and specifier. @@ -909,42 +887,32 @@ def find_best_candidate( :return: A `BestCandidateResult` instance. """ - if (project_name, specifier, hashes) in self._best_candidates: - return self._best_candidates[project_name, specifier, hashes] - candidates = self.find_all_candidates(project_name) candidate_evaluator = self.make_candidate_evaluator( project_name=project_name, specifier=specifier, hashes=hashes, ) - self._best_candidates[project_name, specifier, hashes] = ( - candidate_evaluator.compute_best_candidate(candidates) - ) - - return self._best_candidates[project_name, specifier, hashes] + return candidate_evaluator.compute_best_candidate(candidates) def find_requirement( self, req: InstallRequirement, upgrade: bool - ) -> InstallationCandidate | None: + ) -> Optional[InstallationCandidate]: """Try to find a Link matching req Expects req, an InstallRequirement and upgrade, a boolean Returns a InstallationCandidate if found, Raises DistributionNotFound or BestVersionAlreadyInstalled otherwise """ - name = req.name - assert name is not None, "find_requirement() called with no name" - hashes = req.hashes(trust_internet=False) best_candidate_result = self.find_best_candidate( - name, + req.name, specifier=req.specifier, hashes=hashes, ) best_candidate = best_candidate_result.best_candidate - installed_version: _BaseVersion | None = None + installed_version: Optional[_BaseVersion] = None if req.satisfied_by is not None: installed_version = req.satisfied_by.version @@ -968,14 +936,16 @@ def _format_versions(cand_iter: Iterable[InstallationCandidate]) -> str: "Could not find a version that satisfies the requirement %s " "(from versions: %s)", req, - _format_versions(best_candidate_result.all_candidates), + _format_versions(best_candidate_result.iter_all()), ) - raise DistributionNotFound(f"No matching distribution found for {req}") + raise DistributionNotFound( + "No matching distribution found for {}".format(req) + ) def _should_install_candidate( - candidate: InstallationCandidate | None, - ) -> TypeGuard[InstallationCandidate]: + candidate: Optional[InstallationCandidate], + ) -> "TypeGuard[InstallationCandidate]": if installed_version is None: return True if best_candidate is None: @@ -1002,7 +972,7 @@ def _should_install_candidate( logger.debug( "Using version %s (newest of versions: %s)", best_candidate.version, - _format_versions(best_candidate_result.applicable_candidates), + _format_versions(best_candidate_result.iter_applicable()), ) return best_candidate @@ -1010,7 +980,7 @@ def _should_install_candidate( logger.debug( "Installed version (%s) is most up-to-date (past versions: %s)", installed_version, - _format_versions(best_candidate_result.applicable_candidates), + _format_versions(best_candidate_result.iter_applicable()), ) raise BestVersionAlreadyInstalled @@ -1041,7 +1011,7 @@ def _find_name_version_sep(fragment: str, canonical_name: str) -> int: raise ValueError(f"{fragment} does not match {canonical_name}") -def _extract_version_from_fragment(fragment: str, canonical_name: str) -> str | None: +def _extract_version_from_fragment(fragment: str, canonical_name: str) -> Optional[str]: """Parse the version string from a + filename "fragment" (stem) or egg fragment. diff --git a/venv1/Lib/site-packages/pip/_internal/index/sources.py b/venv1/Lib/site-packages/pip/_internal/index/sources.py index c67c4d73..cd9cb8d4 100644 --- a/venv1/Lib/site-packages/pip/_internal/index/sources.py +++ b/venv1/Lib/site-packages/pip/_internal/index/sources.py @@ -1,19 +1,8 @@ -from __future__ import annotations - import logging import mimetypes import os -from collections import defaultdict -from collections.abc import Iterable -from typing import Callable - -from pip._vendor.packaging.utils import ( - InvalidSdistFilename, - InvalidWheelFilename, - canonicalize_name, - parse_sdist_filename, - parse_wheel_filename, -) +import pathlib +from typing import Callable, Iterable, Optional, Tuple from pip._internal.models.candidate import InstallationCandidate from pip._internal.models.link import Link @@ -30,7 +19,7 @@ class LinkSource: @property - def link(self) -> Link | None: + def link(self) -> Optional[Link]: """Returns the underlying link, if there's one.""" raise NotImplementedError() @@ -47,53 +36,6 @@ def _is_html_file(file_url: str) -> bool: return mimetypes.guess_type(file_url, strict=False)[0] == "text/html" -class _FlatDirectoryToUrls: - """Scans directory and caches results""" - - def __init__(self, path: str) -> None: - self._path = path - self._page_candidates: list[str] = [] - self._project_name_to_urls: dict[str, list[str]] = defaultdict(list) - self._scanned_directory = False - - def _scan_directory(self) -> None: - """Scans directory once and populates both page_candidates - and project_name_to_urls at the same time - """ - for entry in os.scandir(self._path): - url = path_to_url(entry.path) - if _is_html_file(url): - self._page_candidates.append(url) - continue - - # File must have a valid wheel or sdist name, - # otherwise not worth considering as a package - try: - project_filename = parse_wheel_filename(entry.name)[0] - except InvalidWheelFilename: - try: - project_filename = parse_sdist_filename(entry.name)[0] - except InvalidSdistFilename: - continue - - self._project_name_to_urls[project_filename].append(url) - self._scanned_directory = True - - @property - def page_candidates(self) -> list[str]: - if not self._scanned_directory: - self._scan_directory() - - return self._page_candidates - - @property - def project_name_to_urls(self) -> dict[str, list[str]]: - if not self._scanned_directory: - self._scan_directory() - - return self._project_name_to_urls - - class _FlatDirectorySource(LinkSource): """Link source specified by ``--find-links=``. @@ -103,34 +45,30 @@ class _FlatDirectorySource(LinkSource): * ``file_candidates``: Archives in the directory. """ - _paths_to_urls: dict[str, _FlatDirectoryToUrls] = {} - def __init__( self, candidates_from_page: CandidatesFromPage, path: str, - project_name: str, ) -> None: self._candidates_from_page = candidates_from_page - self._project_name = canonicalize_name(project_name) - - # Get existing instance of _FlatDirectoryToUrls if it exists - if path in self._paths_to_urls: - self._path_to_urls = self._paths_to_urls[path] - else: - self._path_to_urls = _FlatDirectoryToUrls(path=path) - self._paths_to_urls[path] = self._path_to_urls + self._path = pathlib.Path(os.path.realpath(path)) @property - def link(self) -> Link | None: + def link(self) -> Optional[Link]: return None def page_candidates(self) -> FoundCandidates: - for url in self._path_to_urls.page_candidates: + for path in self._path.iterdir(): + url = path_to_url(str(path)) + if not _is_html_file(url): + continue yield from self._candidates_from_page(Link(url)) def file_links(self) -> FoundLinks: - for url in self._path_to_urls.project_name_to_urls[self._project_name]: + for path in self._path.iterdir(): + url = path_to_url(str(path)) + if _is_html_file(url): + continue yield Link(url) @@ -153,7 +91,7 @@ def __init__( self._link = link @property - def link(self) -> Link | None: + def link(self) -> Optional[Link]: return self._link def page_candidates(self) -> FoundCandidates: @@ -187,7 +125,7 @@ def __init__( self._link = link @property - def link(self) -> Link | None: + def link(self) -> Optional[Link]: return self._link def page_candidates(self) -> FoundCandidates: @@ -215,7 +153,7 @@ def __init__( self._link = link @property - def link(self) -> Link | None: + def link(self) -> Optional[Link]: return self._link def page_candidates(self) -> FoundCandidates: @@ -232,10 +170,9 @@ def build_source( page_validator: PageValidator, expand_dir: bool, cache_link_parsing: bool, - project_name: str, -) -> tuple[str | None, LinkSource | None]: - path: str | None = None - url: str | None = None +) -> Tuple[Optional[str], Optional[LinkSource]]: + path: Optional[str] = None + url: Optional[str] = None if os.path.exists(location): # Is a local path. url = path_to_url(location) path = location @@ -266,7 +203,6 @@ def build_source( source = _FlatDirectorySource( candidates_from_page=candidates_from_page, path=path, - project_name=project_name, ) else: source = _IndexDirectorySource( diff --git a/venv1/Lib/site-packages/pip/_internal/locations/__init__.py b/venv1/Lib/site-packages/pip/_internal/locations/__init__.py index 9f2c4fe3..d54bc63e 100644 --- a/venv1/Lib/site-packages/pip/_internal/locations/__init__.py +++ b/venv1/Lib/site-packages/pip/_internal/locations/__init__.py @@ -1,12 +1,10 @@ -from __future__ import annotations - import functools import logging import os import pathlib import sys import sysconfig -from typing import Any +from typing import Any, Dict, Generator, Optional, Tuple from pip._internal.models.scheme import SCHEME_KEYS, Scheme from pip._internal.utils.compat import WINDOWS @@ -89,7 +87,7 @@ def _looks_like_bpo_44860() -> bool: return unix_user_platlib == "$usersite" -def _looks_like_red_hat_patched_platlib_purelib(scheme: dict[str, str]) -> bool: +def _looks_like_red_hat_patched_platlib_purelib(scheme: Dict[str, str]) -> bool: platlib = scheme["platlib"] if "/$platlibdir/" in platlib: platlib = platlib.replace("/$platlibdir/", f"/{_PLATLIBDIR}/") @@ -99,7 +97,7 @@ def _looks_like_red_hat_patched_platlib_purelib(scheme: dict[str, str]) -> bool: return unpatched.replace("$platbase/", "$base/") == scheme["purelib"] -@functools.cache +@functools.lru_cache(maxsize=None) def _looks_like_red_hat_lib() -> bool: """Red Hat patches platlib in unix_prefix and unix_home, but not purelib. @@ -114,7 +112,7 @@ def _looks_like_red_hat_lib() -> bool: ) -@functools.cache +@functools.lru_cache(maxsize=None) def _looks_like_debian_scheme() -> bool: """Debian adds two additional schemes.""" from distutils.command.install import INSTALL_SCHEMES @@ -122,7 +120,7 @@ def _looks_like_debian_scheme() -> bool: return "deb_system" in INSTALL_SCHEMES and "unix_local" in INSTALL_SCHEMES -@functools.cache +@functools.lru_cache(maxsize=None) def _looks_like_red_hat_scheme() -> bool: """Red Hat patches ``sys.prefix`` and ``sys.exec_prefix``. @@ -142,7 +140,7 @@ def _looks_like_red_hat_scheme() -> bool: ) -@functools.cache +@functools.lru_cache(maxsize=None) def _looks_like_slackware_scheme() -> bool: """Slackware patches sysconfig but fails to patch distutils and site. @@ -158,7 +156,7 @@ def _looks_like_slackware_scheme() -> bool: return "/lib64/" in paths["purelib"] and "/lib64/" not in user_site -@functools.cache +@functools.lru_cache(maxsize=None) def _looks_like_msys2_mingw_scheme() -> bool: """MSYS2 patches distutils and sysconfig to use a UNIX-like scheme. @@ -176,7 +174,23 @@ def _looks_like_msys2_mingw_scheme() -> bool: ) -@functools.cache +def _fix_abiflags(parts: Tuple[str]) -> Generator[str, None, None]: + ldversion = sysconfig.get_config_var("LDVERSION") + abiflags = getattr(sys, "abiflags", None) + + # LDVERSION does not end with sys.abiflags. Just return the path unchanged. + if not ldversion or not abiflags or not ldversion.endswith(abiflags): + yield from parts + return + + # Strip sys.abiflags from LDVERSION-based path components. + for part in parts: + if part.endswith(ldversion): + part = part[: (0 - len(abiflags))] + yield part + + +@functools.lru_cache(maxsize=None) def _warn_mismatched(old: pathlib.Path, new: pathlib.Path, *, key: str) -> None: issue_url = "https://github.com/pypa/pip/issues/10151" message = ( @@ -194,13 +208,13 @@ def _warn_if_mismatch(old: pathlib.Path, new: pathlib.Path, *, key: str) -> bool return True -@functools.cache +@functools.lru_cache(maxsize=None) def _log_context( *, user: bool = False, - home: str | None = None, - root: str | None = None, - prefix: str | None = None, + home: Optional[str] = None, + root: Optional[str] = None, + prefix: Optional[str] = None, ) -> None: parts = [ "Additional context:", @@ -216,10 +230,10 @@ def _log_context( def get_scheme( dist_name: str, user: bool = False, - home: str | None = None, - root: str | None = None, + home: Optional[str] = None, + root: Optional[str] = None, isolated: bool = False, - prefix: str | None = None, + prefix: Optional[str] = None, ) -> Scheme: new = _sysconfig.get_scheme( dist_name, @@ -283,13 +297,14 @@ def get_scheme( continue # On Python 3.9+, sysconfig's posix_user scheme sets platlib against - # sys.platlibdir, but distutils's unix_user incorrectly continues + # sys.platlibdir, but distutils's unix_user incorrectly coninutes # using the same $usersite for both platlib and purelib. This creates a # mismatch when sys.platlibdir is not "lib". skip_bpo_44860 = ( user and k == "platlib" and not WINDOWS + and sys.version_info >= (3, 9) and _PLATLIBDIR != "lib" and _looks_like_bpo_44860() ) @@ -321,6 +336,17 @@ def get_scheme( if skip_linux_system_special_case: continue + # On Python 3.7 and earlier, sysconfig does not include sys.abiflags in + # the "pythonX.Y" part of the path, but distutils does. + skip_sysconfig_abiflag_bug = ( + sys.version_info < (3, 8) + and not WINDOWS + and k in ("headers", "platlib", "purelib") + and tuple(_fix_abiflags(old_v.parts)) == new_v.parts + ) + if skip_sysconfig_abiflag_bug: + continue + # MSYS2 MINGW's sysconfig patch does not include the "site-packages" # part of the path. This is incorrect and will be fixed in MSYS. skip_msys2_mingw_bug = ( diff --git a/venv1/Lib/site-packages/pip/_internal/locations/_distutils.py b/venv1/Lib/site-packages/pip/_internal/locations/_distutils.py index 28c066bc..92bd9317 100644 --- a/venv1/Lib/site-packages/pip/_internal/locations/_distutils.py +++ b/venv1/Lib/site-packages/pip/_internal/locations/_distutils.py @@ -9,8 +9,6 @@ # # See https://github.com/pypa/pip/issues/8761 for the original discussion and # rationale for why this is done within pip. -from __future__ import annotations - try: __import__("_distutils_hack").remove_shim() except (ImportError, AttributeError): @@ -23,6 +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 pip._internal.models.scheme import Scheme from pip._internal.utils.compat import WINDOWS @@ -36,19 +35,19 @@ def distutils_scheme( dist_name: str, user: bool = False, - home: str | None = None, - root: str | None = None, + home: Optional[str] = None, + root: Optional[str] = None, isolated: bool = False, - prefix: str | None = None, + prefix: Optional[str] = None, *, ignore_config_files: bool = False, -) -> dict[str, str]: +) -> Dict[str, str]: """ Return a distutils install scheme """ from distutils.dist import Distribution - dist_args: dict[str, str | list[str]] = {"name": dist_name} + dist_args: Dict[str, Union[str, List[str]]] = {"name": dist_name} if isolated: dist_args["script_args"] = ["--no-user-cfg"] @@ -57,15 +56,16 @@ def distutils_scheme( try: d.parse_config_files() except UnicodeDecodeError: - paths = d.find_config_files() + # Typeshed does not include find_config_files() for some reason. + paths = d.find_config_files() # type: ignore logger.warning( "Ignore distutils configs in %s due to encoding errors.", ", ".join(os.path.basename(p) for p in paths), ) - obj: DistutilsCommand | None = None + obj: Optional[DistutilsCommand] = None obj = d.get_command_obj("install", create=True) assert obj is not None - i: distutils_install_command = obj + i = cast(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. @@ -79,7 +79,7 @@ def distutils_scheme( i.root = root or i.root i.finalize_options() - scheme: dict[str, str] = {} + scheme = {} for key in SCHEME_KEYS: scheme[key] = getattr(i, "install_" + key) @@ -89,7 +89,7 @@ def distutils_scheme( # finalize_options(); we only want to override here if the user # has explicitly requested it hence going back to the config if "install_lib" in d.get_option_dict("install"): - scheme.update({"purelib": i.install_lib, "platlib": i.install_lib}) + scheme.update(dict(purelib=i.install_lib, platlib=i.install_lib)) if running_under_virtualenv(): if home: @@ -116,10 +116,10 @@ def distutils_scheme( def get_scheme( dist_name: str, user: bool = False, - home: str | None = None, - root: str | None = None, + home: Optional[str] = None, + root: Optional[str] = None, isolated: bool = False, - prefix: str | None = None, + prefix: Optional[str] = None, ) -> Scheme: """ Get the "scheme" corresponding to the input parameters. The distutils diff --git a/venv1/Lib/site-packages/pip/_internal/locations/_sysconfig.py b/venv1/Lib/site-packages/pip/_internal/locations/_sysconfig.py index d4a448ec..97aef1f1 100644 --- a/venv1/Lib/site-packages/pip/_internal/locations/_sysconfig.py +++ b/venv1/Lib/site-packages/pip/_internal/locations/_sysconfig.py @@ -1,9 +1,8 @@ -from __future__ import annotations - import logging import os import sys import sysconfig +import typing from pip._internal.exceptions import InvalidSchemeCombination, UserInstallationInvalid from pip._internal.models.scheme import SCHEME_KEYS, Scheme @@ -125,10 +124,10 @@ def _infer_home() -> str: def get_scheme( dist_name: str, user: bool = False, - home: str | None = None, - root: str | None = None, + home: typing.Optional[str] = None, + root: typing.Optional[str] = None, isolated: bool = False, - prefix: str | None = None, + prefix: typing.Optional[str] = None, ) -> Scheme: """ Get the "scheme" corresponding to the input parameters. @@ -193,10 +192,9 @@ def get_scheme( data=paths["data"], ) if root is not None: - converted_keys = {} for key in SCHEME_KEYS: - converted_keys[key] = change_root(root, getattr(scheme, key)) - scheme = Scheme(**converted_keys) + value = change_root(root, getattr(scheme, key)) + setattr(scheme, key, value) return scheme diff --git a/venv1/Lib/site-packages/pip/_internal/locations/base.py b/venv1/Lib/site-packages/pip/_internal/locations/base.py index 17cd0e87..3f9f896e 100644 --- a/venv1/Lib/site-packages/pip/_internal/locations/base.py +++ b/venv1/Lib/site-packages/pip/_internal/locations/base.py @@ -1,10 +1,9 @@ -from __future__ import annotations - import functools import os import site import sys import sysconfig +import typing from pip._internal.exceptions import InstallationError from pip._internal.utils import appdirs @@ -72,11 +71,11 @@ def get_src_prefix() -> str: try: # Use getusersitepackages if this is present, as it ensures that the # value is initialised properly. - user_site: str | None = site.getusersitepackages() + user_site: typing.Optional[str] = site.getusersitepackages() except AttributeError: user_site = site.USER_SITE -@functools.cache +@functools.lru_cache(maxsize=None) def is_osx_framework() -> bool: return bool(sysconfig.get_config_var("PYTHONFRAMEWORK")) diff --git a/venv1/Lib/site-packages/pip/_internal/main.py b/venv1/Lib/site-packages/pip/_internal/main.py index ec52c4e0..33c6d24c 100644 --- a/venv1/Lib/site-packages/pip/_internal/main.py +++ b/venv1/Lib/site-packages/pip/_internal/main.py @@ -1,7 +1,7 @@ -from __future__ import annotations +from typing import List, Optional -def main(args: list[str] | None = None) -> int: +def main(args: Optional[List[str]] = None) -> int: """This is preserved for old console scripts that may still be referencing it. diff --git a/venv1/Lib/site-packages/pip/_internal/metadata/__init__.py b/venv1/Lib/site-packages/pip/_internal/metadata/__init__.py index 1c24efcd..9f73ca71 100644 --- a/venv1/Lib/site-packages/pip/_internal/metadata/__init__.py +++ b/venv1/Lib/site-packages/pip/_internal/metadata/__init__.py @@ -1,18 +1,17 @@ -from __future__ import annotations - import contextlib import functools import os import sys -from typing import TYPE_CHECKING, Literal, Protocol, cast +from typing import TYPE_CHECKING, List, Optional, Type, cast -from pip._internal.utils.deprecation import deprecated from pip._internal.utils.misc import strtobool from .base import BaseDistribution, BaseEnvironment, FilesystemWheel, MemoryWheel, Wheel if TYPE_CHECKING: - from pip._vendor.packaging.utils import NormalizedName + from typing import Protocol +else: + Protocol = object __all__ = [ "BaseDistribution", @@ -31,75 +30,36 @@ def _should_use_importlib_metadata() -> bool: """Whether to use the ``importlib.metadata`` or ``pkg_resources`` backend. By default, pip uses ``importlib.metadata`` on Python 3.11+, and - ``pkg_resources`` otherwise. Up to Python 3.13, This can be - overridden by a couple of ways: + ``pkg_resourcess`` otherwise. This can be overridden by a couple of ways: * If environment variable ``_PIP_USE_IMPORTLIB_METADATA`` is set, it - dictates whether ``importlib.metadata`` is used, for Python <3.14. - * On Python 3.11, 3.12 and 3.13, Python distributors can patch - ``importlib.metadata`` to add a global constant - ``_PIP_USE_IMPORTLIB_METADATA = False``. This makes pip use - ``pkg_resources`` (unless the user set the aforementioned environment - variable to *True*). - - On Python 3.14+, the ``pkg_resources`` backend cannot be used. + dictates whether ``importlib.metadata`` is used, regardless of Python + version. + * On Python 3.11+, Python distributors can patch ``importlib.metadata`` + to add a global constant ``_PIP_USE_IMPORTLIB_METADATA = False``. This + makes pip use ``pkg_resources`` (unless the user set the aforementioned + environment variable to *True*). """ - if sys.version_info >= (3, 14): - # On Python >=3.14 we only support importlib.metadata. - return True with contextlib.suppress(KeyError, ValueError): - # On Python <3.14, if the environment variable is set, we obey what it says. return bool(strtobool(os.environ["_PIP_USE_IMPORTLIB_METADATA"])) if sys.version_info < (3, 11): - # On Python <3.11, we always use pkg_resources, unless the environment - # variable was set. return False - # On Python 3.11, 3.12 and 3.13, we check if the global constant is set. import importlib.metadata return bool(getattr(importlib.metadata, "_PIP_USE_IMPORTLIB_METADATA", True)) -def _emit_pkg_resources_deprecation_if_needed() -> None: - if sys.version_info < (3, 11): - # All pip versions supporting Python<=3.11 will support pkg_resources, - # and pkg_resources is the default for these, so let's not bother users. - return - - import importlib.metadata - - if hasattr(importlib.metadata, "_PIP_USE_IMPORTLIB_METADATA"): - # The Python distributor has set the global constant, so we don't - # warn, since it is not a user decision. - return - - # The user has decided to use pkg_resources, so we warn. - deprecated( - reason="Using the pkg_resources metadata backend is deprecated.", - replacement=( - "to use the default importlib.metadata backend, " - "by unsetting the _PIP_USE_IMPORTLIB_METADATA environment variable" - ), - gone_in="26.3", - issue=13317, - ) - - class Backend(Protocol): - NAME: Literal["importlib", "pkg_resources"] - Distribution: type[BaseDistribution] - Environment: type[BaseEnvironment] + Distribution: Type[BaseDistribution] + Environment: Type[BaseEnvironment] -@functools.cache +@functools.lru_cache(maxsize=None) def select_backend() -> Backend: if _should_use_importlib_metadata(): from . import importlib return cast(Backend, importlib) - - _emit_pkg_resources_deprecation_if_needed() - from . import pkg_resources return cast(Backend, pkg_resources) @@ -110,12 +70,12 @@ def get_default_environment() -> BaseEnvironment: This returns an Environment instance from the chosen backend. The default Environment instance should be built from ``sys.path`` and may use caching - to share instance state across calls. + to share instance state accorss calls. """ return select_backend().Environment.default() -def get_environment(paths: list[str] | None) -> BaseEnvironment: +def get_environment(paths: Optional[List[str]]) -> BaseEnvironment: """Get a representation of the environment specified by ``paths``. This returns an Environment instance from the chosen backend based on the @@ -134,9 +94,7 @@ def get_directory_distribution(directory: str) -> BaseDistribution: return select_backend().Distribution.from_directory(directory) -def get_wheel_distribution( - wheel: Wheel, canonical_name: NormalizedName -) -> BaseDistribution: +def get_wheel_distribution(wheel: Wheel, canonical_name: str) -> BaseDistribution: """Get the representation of the specified wheel's distribution metadata. This returns a Distribution instance from the chosen backend based on diff --git a/venv1/Lib/site-packages/pip/_internal/metadata/_json.py b/venv1/Lib/site-packages/pip/_internal/metadata/_json.py index b39ac054..336b52f1 100644 --- a/venv1/Lib/site-packages/pip/_internal/metadata/_json.py +++ b/venv1/Lib/site-packages/pip/_internal/metadata/_json.py @@ -1,9 +1,8 @@ # Extracted from https://github.com/pfmoore/pkg_metadata -from __future__ import annotations from email.header import Header, decode_header, make_header from email.message import Message -from typing import Any, cast +from typing import Any, Dict, List, Union METADATA_FIELDS = [ # Name, Multiple-Use @@ -24,8 +23,6 @@ ("Maintainer", False), ("Maintainer-email", False), ("License", False), - ("License-Expression", False), - ("License-File", True), ("Classifier", True), ("Requires-Dist", True), ("Requires-Python", False), @@ -41,10 +38,10 @@ def json_name(field: str) -> str: return field.lower().replace("-", "_") -def msg_to_json(msg: Message) -> dict[str, Any]: +def msg_to_json(msg: Message) -> Dict[str, Any]: """Convert a Message object into a JSON-compatible dictionary.""" - def sanitise_header(h: Header | str) -> str: + def sanitise_header(h: Union[Header, str]) -> str: if isinstance(h, Header): chunks = [] for bytes, encoding in decode_header(h): @@ -66,11 +63,11 @@ def sanitise_header(h: Header | str) -> str: continue key = json_name(field) if multi: - value: str | list[str] = [ - sanitise_header(v) for v in msg.get_all(field) # type: ignore + value: Union[str, List[str]] = [ + sanitise_header(v) for v in msg.get_all(field) ] else: - value = sanitise_header(msg.get(field)) # type: ignore + value = sanitise_header(msg.get(field)) if key == "keywords": # Accept both comma-separated and space-separated # forms, for better compatibility with old data. @@ -80,7 +77,7 @@ def sanitise_header(h: Header | str) -> str: value = value.split() result[key] = value - payload = cast(str, msg.get_payload()) + payload = msg.get_payload() if payload: result["description"] = payload diff --git a/venv1/Lib/site-packages/pip/_internal/metadata/base.py b/venv1/Lib/site-packages/pip/_internal/metadata/base.py index 230e1147..cafb79fb 100644 --- a/venv1/Lib/site-packages/pip/_internal/metadata/base.py +++ b/venv1/Lib/site-packages/pip/_internal/metadata/base.py @@ -1,5 +1,3 @@ -from __future__ import annotations - import csv import email.message import functools @@ -8,19 +6,26 @@ import pathlib import re import zipfile -from collections.abc import Collection, Container, Iterable, Iterator from typing import ( IO, + TYPE_CHECKING, Any, + Collection, + Container, + Dict, + Iterable, + Iterator, + List, NamedTuple, - Protocol, + Optional, + Tuple, Union, ) from pip._vendor.packaging.requirements import Requirement from pip._vendor.packaging.specifiers import InvalidSpecifier, SpecifierSet -from pip._vendor.packaging.utils import NormalizedName, canonicalize_name -from pip._vendor.packaging.version import Version +from pip._vendor.packaging.utils import NormalizedName +from pip._vendor.packaging.version import LegacyVersion, Version from pip._internal.exceptions import NoneMetadataError from pip._internal.locations import site_packages, user_site @@ -32,10 +37,18 @@ from pip._internal.utils.compat import stdlib_pkgs # TODO: Move definition here. from pip._internal.utils.egg_link import egg_link_path_from_sys_path from pip._internal.utils.misc import is_local, normalize_path +from pip._internal.utils.packaging import safe_extra from pip._internal.utils.urls import url_to_path from ._json import msg_to_json +if TYPE_CHECKING: + from typing import Protocol +else: + Protocol = object + +DistributionVersion = Union[LegacyVersion, Version] + InfoPath = Union[str, pathlib.PurePath] logger = logging.getLogger(__name__) @@ -56,8 +69,8 @@ def group(self) -> str: def _convert_installed_files_path( - entry: tuple[str, ...], - info: tuple[str, ...], + entry: Tuple[str, ...], + info: Tuple[str, ...], ) -> str: """Convert a legacy installed-files.txt path into modern RECORD path. @@ -93,7 +106,7 @@ class RequiresEntry(NamedTuple): class BaseDistribution(Protocol): @classmethod - def from_directory(cls, directory: str) -> BaseDistribution: + def from_directory(cls, directory: str) -> "BaseDistribution": """Load the distribution from a metadata directory. :param directory: Path to a metadata directory, e.g. ``.dist-info``. @@ -106,7 +119,7 @@ def from_metadata_file_contents( metadata_contents: bytes, filename: str, project_name: str, - ) -> BaseDistribution: + ) -> "BaseDistribution": """Load the distribution from the contents of a METADATA file. This is used to implement PEP 658 by generating a "shallow" dist object that can @@ -119,7 +132,7 @@ def from_metadata_file_contents( raise NotImplementedError() @classmethod - def from_wheel(cls, wheel: Wheel, name: str) -> BaseDistribution: + def from_wheel(cls, wheel: "Wheel", name: str) -> "BaseDistribution": """Load the distribution from a given wheel. :param wheel: A concrete wheel definition. @@ -133,13 +146,13 @@ def from_wheel(cls, wheel: Wheel, name: str) -> BaseDistribution: raise NotImplementedError() def __repr__(self) -> str: - return f"{self.raw_name} {self.raw_version} ({self.location})" + return f"{self.raw_name} {self.version} ({self.location})" def __str__(self) -> str: - return f"{self.raw_name} {self.raw_version}" + return f"{self.raw_name} {self.version}" @property - def location(self) -> str | None: + def location(self) -> Optional[str]: """Where the distribution is loaded from. A string value is not necessarily a filesystem path, since distributions @@ -153,7 +166,7 @@ def location(self) -> str | None: raise NotImplementedError() @property - def editable_project_location(self) -> str | None: + def editable_project_location(self) -> Optional[str]: """The project location for editable distributions. This is the directory where pyproject.toml or setup.py is located. @@ -175,7 +188,7 @@ def editable_project_location(self) -> str | None: return None @property - def installed_location(self) -> str | None: + def installed_location(self) -> Optional[str]: """The distribution's "installed" location. This should generally be a ``site-packages`` directory. This is @@ -188,7 +201,7 @@ def installed_location(self) -> str | None: raise NotImplementedError() @property - def info_location(self) -> str | None: + def info_location(self) -> Optional[str]: """Location of the .[egg|dist]-info directory or file. Similarly to ``location``, a string value is not necessarily a @@ -226,9 +239,7 @@ def installed_as_egg(self) -> bool: location = self.location if not location: return False - # XXX if the distribution is a zipped egg, location has a trailing / - # so we resort to pathlib.Path to check the suffix in a reliable way. - return pathlib.Path(location).suffix == ".egg" + return location.endswith(".egg") @property def installed_with_setuptools_egg_info(self) -> bool: @@ -269,11 +280,7 @@ def canonical_name(self) -> NormalizedName: raise NotImplementedError() @property - def version(self) -> Version: - raise NotImplementedError() - - @property - def raw_version(self) -> str: + def version(self) -> DistributionVersion: raise NotImplementedError() @property @@ -285,7 +292,7 @@ def setuptools_filename(self) -> str: return self.raw_name.replace("-", "_") @property - def direct_url(self) -> DirectUrl | None: + def direct_url(self) -> Optional[DirectUrl]: """Obtain a DirectUrl from this distribution. Returns None if the distribution has no `direct_url.json` metadata, @@ -379,7 +386,15 @@ def iter_entry_points(self) -> Iterable[BaseEntryPoint]: def _metadata_impl(self) -> email.message.Message: raise NotImplementedError() - @functools.cached_property + @functools.lru_cache(maxsize=1) + def _metadata_cached(self) -> email.message.Message: + # When we drop python 3.7 support, move this to the metadata property and use + # functools.cached_property instead of lru_cache. + metadata = self._metadata_impl() + self._add_egg_info_requires(metadata) + return metadata + + @property def metadata(self) -> email.message.Message: """Metadata of distribution parsed from e.g. METADATA or PKG-INFO. @@ -388,12 +403,10 @@ def metadata(self) -> email.message.Message: :raises NoneMetadataError: If the metadata file is available, but does not contain valid metadata. """ - metadata = self._metadata_impl() - self._add_egg_info_requires(metadata) - return metadata + return self._metadata_cached() @property - def metadata_dict(self) -> dict[str, Any]: + def metadata_dict(self) -> Dict[str, Any]: """PEP 566 compliant JSON-serializable representation of METADATA or PKG-INFO. This should return an empty dict if the metadata file is unavailable. @@ -404,7 +417,7 @@ def metadata_dict(self) -> dict[str, Any]: return msg_to_json(self.metadata) @property - def metadata_version(self) -> str | None: + def metadata_version(self) -> Optional[str]: """Value of "Metadata-Version:" in distribution metadata, if available.""" return self.metadata.get("Metadata-Version") @@ -442,23 +455,15 @@ def iter_dependencies(self, extras: Collection[str] = ()) -> Iterable[Requiremen """ raise NotImplementedError() - def iter_raw_dependencies(self) -> Iterable[str]: - """Raw Requires-Dist metadata.""" - return self.metadata.get_all("Requires-Dist", []) - - def iter_provided_extras(self) -> Iterable[NormalizedName]: + def iter_provided_extras(self) -> Iterable[str]: """Extras provided by this distribution. For modern .dist-info distributions, this is the collection of "Provides-Extra:" entries in distribution metadata. - - The return value of this function is expected to be normalised names, - per PEP 685, with the returned value being handled appropriately by - `iter_dependencies`. """ raise NotImplementedError() - def _iter_declared_entries_from_record(self) -> Iterator[str] | None: + def _iter_declared_entries_from_record(self) -> Optional[Iterator[str]]: try: text = self.read_text("RECORD") except FileNotFoundError: @@ -466,7 +471,7 @@ def _iter_declared_entries_from_record(self) -> Iterator[str] | None: # This extra Path-str cast normalizes entries. return (str(pathlib.Path(row[0])) for row in csv.reader(text.splitlines())) - def _iter_declared_entries_from_legacy(self) -> Iterator[str] | None: + def _iter_declared_entries_from_legacy(self) -> Optional[Iterator[str]]: try: text = self.read_text("installed-files.txt") except FileNotFoundError: @@ -487,7 +492,7 @@ def _iter_declared_entries_from_legacy(self) -> Iterator[str] | None: for p in paths ) - def iter_declared_entries(self) -> Iterator[str] | None: + def iter_declared_entries(self) -> Optional[Iterator[str]]: """Iterate through file entries declared in this distribution. For modern .dist-info distributions, this is the files listed in the @@ -532,11 +537,10 @@ def _iter_egg_info_extras(self) -> Iterable[str]: """Get extras from the egg-info directory.""" known_extras = {""} for entry in self._iter_requires_txt_entries(): - extra = canonicalize_name(entry.extra) - if extra in known_extras: + if entry.extra in known_extras: continue - known_extras.add(extra) - yield extra + known_extras.add(entry.extra) + yield entry.extra def _iter_egg_info_dependencies(self) -> Iterable[str]: """Get distribution dependencies from the egg-info directory. @@ -552,11 +556,10 @@ def _iter_egg_info_dependencies(self) -> Iterable[str]: all currently available PEP 517 backends, although not standardized. """ for entry in self._iter_requires_txt_entries(): - extra = canonicalize_name(entry.extra) - if extra and entry.marker: - marker = f'({entry.marker}) and extra == "{extra}"' - elif extra: - marker = f'extra == "{extra}"' + if entry.extra and entry.marker: + marker = f'({entry.marker}) and extra == "{safe_extra(entry.extra)}"' + elif entry.extra: + marker = f'extra == "{safe_extra(entry.extra)}"' elif entry.marker: marker = entry.marker else: @@ -580,14 +583,14 @@ class BaseEnvironment: """An environment containing distributions to introspect.""" @classmethod - def default(cls) -> BaseEnvironment: + def default(cls) -> "BaseEnvironment": raise NotImplementedError() @classmethod - def from_paths(cls, paths: list[str] | None) -> BaseEnvironment: + def from_paths(cls, paths: Optional[List[str]]) -> "BaseEnvironment": raise NotImplementedError() - def get_distribution(self, name: str) -> BaseDistribution | None: + def get_distribution(self, name: str) -> Optional["BaseDistribution"]: """Given a requirement name, return the installed distributions. The name may not be normalized. The implementation must canonicalize @@ -595,7 +598,7 @@ def get_distribution(self, name: str) -> BaseDistribution | None: """ raise NotImplementedError() - def _iter_distributions(self) -> Iterator[BaseDistribution]: + def _iter_distributions(self) -> Iterator["BaseDistribution"]: """Iterate through installed distributions. This function should be implemented by subclass, but never called diff --git a/venv1/Lib/site-packages/pip/_internal/metadata/importlib/__init__.py b/venv1/Lib/site-packages/pip/_internal/metadata/importlib/__init__.py index a779138d..5e7af9fe 100644 --- a/venv1/Lib/site-packages/pip/_internal/metadata/importlib/__init__.py +++ b/venv1/Lib/site-packages/pip/_internal/metadata/importlib/__init__.py @@ -1,6 +1,4 @@ from ._dists import Distribution from ._envs import Environment -__all__ = ["NAME", "Distribution", "Environment"] - -NAME = "importlib" +__all__ = ["Distribution", "Environment"] diff --git a/venv1/Lib/site-packages/pip/_internal/metadata/importlib/_compat.py b/venv1/Lib/site-packages/pip/_internal/metadata/importlib/_compat.py index 7de614d7..593bff23 100644 --- a/venv1/Lib/site-packages/pip/_internal/metadata/importlib/_compat.py +++ b/venv1/Lib/site-packages/pip/_internal/metadata/importlib/_compat.py @@ -1,10 +1,5 @@ -from __future__ import annotations - import importlib.metadata -import os -from typing import Any, Protocol, cast - -from pip._vendor.packaging.utils import NormalizedName, canonicalize_name +from typing import Any, Optional, Protocol, cast class BadMetadata(ValueError): @@ -32,11 +27,11 @@ def name(self) -> str: raise NotImplementedError() @property - def parent(self) -> BasePath: + def parent(self) -> "BasePath": raise NotImplementedError() -def get_info_location(d: importlib.metadata.Distribution) -> BasePath | None: +def get_info_location(d: importlib.metadata.Distribution) -> Optional[BasePath]: """Find the path to the distribution's metadata directory. HACK: This relies on importlib.metadata's private ``_path`` attribute. Not @@ -48,40 +43,13 @@ def get_info_location(d: importlib.metadata.Distribution) -> BasePath | None: return getattr(d, "_path", None) -def parse_name_and_version_from_info_directory( - dist: importlib.metadata.Distribution, -) -> tuple[str | None, str | None]: - """Get a name and version from the metadata directory name. - - This is much faster than reading distribution metadata. - """ - info_location = get_info_location(dist) - if info_location is None: - return None, None - - stem, suffix = os.path.splitext(info_location.name) - if suffix == ".dist-info": - name, sep, version = stem.partition("-") - if sep: - return name, version - - if suffix == ".egg-info": - name = stem.split("-", 1)[0] - return name, None - - return None, None - - -def get_dist_canonical_name(dist: importlib.metadata.Distribution) -> NormalizedName: - """Get the distribution's normalized name. +def get_dist_name(dist: importlib.metadata.Distribution) -> str: + """Get the distribution's project name. The ``name`` attribute is only available in Python 3.10 or later. We are targeting exactly that, but Mypy does not know this. """ - if name := parse_name_and_version_from_info_directory(dist)[0]: - return canonicalize_name(name) - name = cast(Any, dist).name if not isinstance(name, str): raise BadMetadata(dist, reason="invalid metadata entry 'name'") - return canonicalize_name(name) + return name diff --git a/venv1/Lib/site-packages/pip/_internal/metadata/importlib/_dists.py b/venv1/Lib/site-packages/pip/_internal/metadata/importlib/_dists.py index 89364b8b..65c043c8 100644 --- a/venv1/Lib/site-packages/pip/_internal/metadata/importlib/_dists.py +++ b/venv1/Lib/site-packages/pip/_internal/metadata/importlib/_dists.py @@ -1,38 +1,37 @@ -from __future__ import annotations - import email.message import importlib.metadata +import os import pathlib import zipfile -from collections.abc import Collection, Iterable, Iterator, Mapping, Sequence -from os import PathLike from typing import ( + Collection, + Dict, + Iterable, + Iterator, + Mapping, + Optional, + Sequence, cast, ) from pip._vendor.packaging.requirements import Requirement from pip._vendor.packaging.utils import NormalizedName, canonicalize_name -from pip._vendor.packaging.version import Version from pip._vendor.packaging.version import parse as parse_version from pip._internal.exceptions import InvalidWheel, UnsupportedWheel from pip._internal.metadata.base import ( BaseDistribution, BaseEntryPoint, + DistributionVersion, InfoPath, Wheel, ) from pip._internal.utils.misc import normalize_path -from pip._internal.utils.packaging import get_requirement +from pip._internal.utils.packaging import safe_extra from pip._internal.utils.temp_dir import TempDirectory from pip._internal.utils.wheel import parse_wheel, read_wheel_metadata_file -from ._compat import ( - BadMetadata, - BasePath, - get_dist_canonical_name, - parse_name_and_version_from_info_directory, -) +from ._compat import BasePath, get_dist_name class WheelDistribution(importlib.metadata.Distribution): @@ -60,7 +59,7 @@ def from_zipfile( zf: zipfile.ZipFile, name: str, location: str, - ) -> WheelDistribution: + ) -> "WheelDistribution": info_dir, _ = parse_wheel(zf, name) paths = ( (name, pathlib.PurePosixPath(name.split("/", 1)[-1])) @@ -80,7 +79,7 @@ def iterdir(self, path: InfoPath) -> Iterator[pathlib.PurePosixPath]: return iter(self._files) raise FileNotFoundError(path) - def read_text(self, filename: str) -> str | None: + def read_text(self, filename: str) -> Optional[str]: try: data = self._files[pathlib.PurePosixPath(filename)] except KeyError: @@ -93,18 +92,13 @@ def read_text(self, filename: str) -> str | None: raise UnsupportedWheel(error) return text - def locate_file(self, path: str | PathLike[str]) -> pathlib.Path: - # This method doesn't make sense for our in-memory wheel, but the API - # requires us to define it. - raise NotImplementedError - class Distribution(BaseDistribution): def __init__( self, dist: importlib.metadata.Distribution, - info_location: BasePath | None, - installed_location: BasePath | None, + info_location: Optional[BasePath], + installed_location: Optional[BasePath], ) -> None: self._dist = dist self._info_location = info_location @@ -140,44 +134,48 @@ def from_wheel(cls, wheel: Wheel, name: str) -> BaseDistribution: dist = WheelDistribution.from_zipfile(zf, name, wheel.location) except zipfile.BadZipFile as e: raise InvalidWheel(wheel.location, name) from e + except UnsupportedWheel as e: + raise UnsupportedWheel(f"{name} has an invalid wheel, {e}") return cls(dist, dist.info_location, pathlib.PurePosixPath(wheel.location)) @property - def location(self) -> str | None: + def location(self) -> Optional[str]: if self._info_location is None: return None return str(self._info_location.parent) @property - def info_location(self) -> str | None: + def info_location(self) -> Optional[str]: if self._info_location is None: return None return str(self._info_location) @property - def installed_location(self) -> str | None: + def installed_location(self) -> Optional[str]: if self._installed_location is None: return None return normalize_path(str(self._installed_location)) - @property - def canonical_name(self) -> NormalizedName: - return get_dist_canonical_name(self._dist) + def _get_dist_name_from_location(self) -> Optional[str]: + """Try to get the name from the metadata directory name. + + This is much faster than reading metadata. + """ + if self._info_location is None: + return None + stem, suffix = os.path.splitext(self._info_location.name) + if suffix not in (".dist-info", ".egg-info"): + return None + return stem.split("-", 1)[0] @property - def version(self) -> Version: - try: - version = ( - parse_name_and_version_from_info_directory(self._dist)[1] - or self._dist.version - ) - return parse_version(version) - except TypeError: - raise BadMetadata(self._dist, reason="invalid metadata entry `version`") + def canonical_name(self) -> NormalizedName: + name = self._get_dist_name_from_location() or get_dist_name(self._dist) + return canonicalize_name(name) @property - def raw_version(self) -> str: - return self._dist.version + def version(self) -> DistributionVersion: + return parse_version(self._dist.version) def is_file(self, path: InfoPath) -> bool: return self._dist.read_text(str(path)) is not None @@ -198,7 +196,7 @@ def read_text(self, path: InfoPath) -> str: return content def iter_entry_points(self) -> Iterable[BaseEntryPoint]: - # importlib.metadata's EntryPoint structure satisfies BaseEntryPoint. + # importlib.metadata's EntryPoint structure sasitfies BaseEntryPoint. return self._dist.entry_points def _metadata_impl(self) -> email.message.Message: @@ -209,18 +207,15 @@ def _metadata_impl(self) -> email.message.Message: # until upstream can improve the protocol. (python/cpython#94952) return cast(email.message.Message, self._dist.metadata) - def iter_provided_extras(self) -> Iterable[NormalizedName]: - return [ - canonicalize_name(extra) - for extra in self.metadata.get_all("Provides-Extra", []) - ] + def iter_provided_extras(self) -> Iterable[str]: + return ( + safe_extra(extra) for extra in self.metadata.get_all("Provides-Extra", []) + ) def iter_dependencies(self, extras: Collection[str] = ()) -> Iterable[Requirement]: - contexts: Sequence[dict[str, str]] = [{"extra": e} for e in extras] + contexts: Sequence[Dict[str, str]] = [{"extra": safe_extra(e)} for e in extras] for req_string in self.metadata.get_all("Requires-Dist", []): - # strip() because email.message.Message.get_all() may return a leading \n - # in case a long header was wrapped. - req = get_requirement(req_string.strip()) + req = Requirement(req_string) if not req.marker: yield req elif not extras and req.marker.evaluate({"extra": ""}): diff --git a/venv1/Lib/site-packages/pip/_internal/metadata/importlib/_envs.py b/venv1/Lib/site-packages/pip/_internal/metadata/importlib/_envs.py index 71a73b73..cbec59e2 100644 --- a/venv1/Lib/site-packages/pip/_internal/metadata/importlib/_envs.py +++ b/venv1/Lib/site-packages/pip/_internal/metadata/importlib/_envs.py @@ -1,25 +1,21 @@ -from __future__ import annotations - +import functools import importlib.metadata import logging import os import pathlib import sys import zipfile -from collections.abc import Iterator, Sequence -from typing import Optional +import zipimport +from typing import Iterator, List, Optional, Sequence, Set, Tuple -from pip._vendor.packaging.utils import ( - InvalidWheelFilename, - NormalizedName, - canonicalize_name, - parse_wheel_filename, -) +from pip._vendor.packaging.utils import NormalizedName, canonicalize_name from pip._internal.metadata.base import BaseDistribution, BaseEnvironment +from pip._internal.models.wheel import Wheel +from pip._internal.utils.deprecation import deprecated from pip._internal.utils.filetypes import WHEEL_EXTENSION -from ._compat import BadMetadata, BasePath, get_dist_canonical_name, get_info_location +from ._compat import BadMetadata, BasePath, get_dist_name, get_info_location from ._dists import Distribution logger = logging.getLogger(__name__) @@ -30,9 +26,7 @@ def _looks_like_wheel(location: str) -> bool: return False if not os.path.isfile(location): return False - try: - parse_wheel_filename(os.path.basename(location)) - except InvalidWheelFilename: + if not Wheel.wheel_file_re.match(os.path.basename(location)): return False return zipfile.is_zipfile(location) @@ -50,10 +44,10 @@ class _DistributionFinder: installations as well. It's useful feature, after all. """ - FoundResult = tuple[importlib.metadata.Distribution, Optional[BasePath]] + FoundResult = Tuple[importlib.metadata.Distribution, Optional[BasePath]] def __init__(self) -> None: - self._found_names: set[NormalizedName] = set() + self._found_names: Set[NormalizedName] = set() def _find_impl(self, location: str) -> Iterator[FoundResult]: """Find distributions in a location.""" @@ -67,13 +61,14 @@ def _find_impl(self, location: str) -> Iterator[FoundResult]: for dist in importlib.metadata.distributions(path=[location]): info_location = get_info_location(dist) try: - name = get_dist_canonical_name(dist) + raw_name = get_dist_name(dist) except BadMetadata as e: logger.warning("Skipping %s due to %s", info_location, e.reason) continue - if name in self._found_names: + normalized_name = canonicalize_name(raw_name) + if normalized_name in self._found_names: continue - self._found_names.add(name) + self._found_names.add(normalized_name) yield dist, info_location def find(self, location: str) -> Iterator[BaseDistribution]: @@ -83,12 +78,12 @@ def find(self, location: str) -> Iterator[BaseDistribution]: """ for dist, info_location in self._find_impl(location): if info_location is None: - installed_location: BasePath | None = None + installed_location: Optional[BasePath] = None else: installed_location = info_location.parent yield Distribution(dist, info_location, installed_location) - def find_legacy_editables(self, location: str) -> Iterator[BaseDistribution]: + def find_linked(self, location: str) -> Iterator[BaseDistribution]: """Read location in egg-link files and return distributions in there. The path should be a directory; otherwise this returns nothing. This @@ -112,6 +107,53 @@ def find_legacy_editables(self, location: str) -> Iterator[BaseDistribution]: for dist, info_location in self._find_impl(target_location): yield Distribution(dist, info_location, path) + def _find_eggs_in_dir(self, location: str) -> Iterator[BaseDistribution]: + from pip._vendor.pkg_resources import find_distributions + + from pip._internal.metadata import pkg_resources as legacy + + with os.scandir(location) as it: + for entry in it: + if not entry.name.endswith(".egg"): + continue + for dist in find_distributions(entry.path): + yield legacy.Distribution(dist) + + def _find_eggs_in_zip(self, location: str) -> Iterator[BaseDistribution]: + from pip._vendor.pkg_resources import find_eggs_in_zip + + from pip._internal.metadata import pkg_resources as legacy + + try: + importer = zipimport.zipimporter(location) + except zipimport.ZipImportError: + return + for dist in find_eggs_in_zip(importer, location): + yield legacy.Distribution(dist) + + def find_eggs(self, location: str) -> Iterator[BaseDistribution]: + """Find eggs in a location. + + This actually uses the old *pkg_resources* backend. We likely want to + deprecate this so we can eventually remove the *pkg_resources* + dependency entirely. Before that, this should first emit a deprecation + warning for some versions when using the fallback since importing + *pkg_resources* is slow for those who don't need it. + """ + if os.path.isdir(location): + yield from self._find_eggs_in_dir(location) + if zipfile.is_zipfile(location): + yield from self._find_eggs_in_zip(location) + + +@functools.lru_cache(maxsize=None) # Warn a distribution exactly once. +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=None, + ) + class Environment(BaseEnvironment): def __init__(self, paths: Sequence[str]) -> None: @@ -122,7 +164,7 @@ def default(cls) -> BaseEnvironment: return cls(sys.path) @classmethod - def from_paths(cls, paths: list[str] | None) -> BaseEnvironment: + def from_paths(cls, paths: Optional[List[str]]) -> BaseEnvironment: if paths is None: return cls(sys.path) return cls(paths) @@ -131,13 +173,16 @@ def _iter_distributions(self) -> Iterator[BaseDistribution]: finder = _DistributionFinder() for location in self._paths: yield from finder.find(location) - yield from finder.find_legacy_editables(location) + for dist in finder.find_eggs(location): + # _emit_egg_deprecation(dist.location) # TODO: Enable this. + yield dist + # This must go last because that's how pkg_resources tie-breaks. + yield from finder.find_linked(location) - def get_distribution(self, name: str) -> BaseDistribution | None: - canonical_name = canonicalize_name(name) + def get_distribution(self, name: str) -> Optional[BaseDistribution]: matches = ( distribution for distribution in self.iter_all_distributions() - if distribution.canonical_name == canonical_name + if distribution.canonical_name == canonicalize_name(name) ) return next(matches, None) diff --git a/venv1/Lib/site-packages/pip/_internal/metadata/pkg_resources.py b/venv1/Lib/site-packages/pip/_internal/metadata/pkg_resources.py index 89fce8b6..f330ef12 100644 --- a/venv1/Lib/site-packages/pip/_internal/metadata/pkg_resources.py +++ b/venv1/Lib/site-packages/pip/_internal/metadata/pkg_resources.py @@ -1,19 +1,13 @@ -from __future__ import annotations - import email.message import email.parser import logging import os import zipfile -from collections.abc import Collection, Iterable, Iterator, Mapping -from typing import ( - NamedTuple, -) +from typing import Collection, Iterable, Iterator, List, Mapping, NamedTuple, Optional from pip._vendor import pkg_resources from pip._vendor.packaging.requirements import Requirement from pip._vendor.packaging.utils import NormalizedName, canonicalize_name -from pip._vendor.packaging.version import Version from pip._vendor.packaging.version import parse as parse_version from pip._internal.exceptions import InvalidWheel, NoneMetadataError, UnsupportedWheel @@ -25,16 +19,13 @@ BaseDistribution, BaseEntryPoint, BaseEnvironment, + DistributionVersion, InfoPath, Wheel, ) -__all__ = ["NAME", "Distribution", "Environment"] - logger = logging.getLogger(__name__) -NAME = "pkg_resources" - class EntryPoint(NamedTuple): name: str @@ -70,7 +61,7 @@ def get_metadata_lines(self, name: str) -> Iterable[str]: def metadata_isdir(self, name: str) -> bool: return False - def metadata_listdir(self, name: str) -> list[str]: + def metadata_listdir(self, name: str) -> List[str]: return [] def run_script(self, script_name: str, namespace: str) -> None: @@ -80,18 +71,6 @@ def run_script(self, script_name: str, namespace: str) -> None: class Distribution(BaseDistribution): def __init__(self, dist: pkg_resources.Distribution) -> None: self._dist = dist - # This is populated lazily, to avoid loading metadata for all possible - # distributions eagerly. - self.__extra_mapping: Mapping[NormalizedName, str] | None = None - - @property - def _extra_mapping(self) -> Mapping[NormalizedName, str]: - if self.__extra_mapping is None: - self.__extra_mapping = { - canonicalize_name(extra): extra for extra in self._dist.extras - } - - return self.__extra_mapping @classmethod def from_directory(cls, directory: str) -> BaseDistribution: @@ -152,11 +131,11 @@ def from_wheel(cls, wheel: Wheel, name: str) -> BaseDistribution: return cls(dist) @property - def location(self) -> str | None: + def location(self) -> Optional[str]: return self._dist.location @property - def installed_location(self) -> str | None: + def installed_location(self) -> Optional[str]: egg_link = egg_link_path_from_location(self.raw_name) if egg_link: location = egg_link @@ -167,7 +146,7 @@ def installed_location(self) -> str | None: return normalize_path(location) @property - def info_location(self) -> str | None: + def info_location(self) -> Optional[str]: return self._dist.egg_info @property @@ -185,13 +164,9 @@ def canonical_name(self) -> NormalizedName: return canonicalize_name(self._dist.project_name) @property - def version(self) -> Version: + def version(self) -> DistributionVersion: return parse_version(self._dist.version) - @property - def raw_version(self) -> str: - return self._dist.version - def is_file(self, path: InfoPath) -> bool: return self._dist.has_metadata(str(path)) @@ -236,15 +211,12 @@ def _metadata_impl(self) -> email.message.Message: return feed_parser.close() def iter_dependencies(self, extras: Collection[str] = ()) -> Iterable[Requirement]: - if extras: - relevant_extras = set(self._extra_mapping) & set( - map(canonicalize_name, extras) - ) - extras = [self._extra_mapping[extra] for extra in relevant_extras] + if extras: # pkg_resources raises on invalid extras, so we sanitize. + extras = frozenset(extras).intersection(self._dist.extras) return self._dist.requires(extras) - def iter_provided_extras(self) -> Iterable[NormalizedName]: - return self._extra_mapping.keys() + def iter_provided_extras(self) -> Iterable[str]: + return self._dist.extras class Environment(BaseEnvironment): @@ -256,14 +228,14 @@ def default(cls) -> BaseEnvironment: return cls(pkg_resources.working_set) @classmethod - def from_paths(cls, paths: list[str] | None) -> BaseEnvironment: + def from_paths(cls, paths: Optional[List[str]]) -> BaseEnvironment: return cls(pkg_resources.WorkingSet(paths)) def _iter_distributions(self) -> Iterator[BaseDistribution]: for dist in self._ws: yield Distribution(dist) - def _search_distribution(self, name: str) -> BaseDistribution | None: + def _search_distribution(self, name: str) -> Optional[BaseDistribution]: """Find a distribution matching the ``name`` in the environment. This searches from *all* distributions available in the environment, to @@ -275,7 +247,7 @@ def _search_distribution(self, name: str) -> BaseDistribution | None: return dist return None - def get_distribution(self, name: str) -> BaseDistribution | None: + def get_distribution(self, name: str) -> Optional[BaseDistribution]: # Search the distribution by looking through the working set. dist = self._search_distribution(name) if dist: diff --git a/venv1/Lib/site-packages/pip/_internal/models/__init__.py b/venv1/Lib/site-packages/pip/_internal/models/__init__.py index 7b1fc295..7855226e 100644 --- a/venv1/Lib/site-packages/pip/_internal/models/__init__.py +++ b/venv1/Lib/site-packages/pip/_internal/models/__init__.py @@ -1 +1,2 @@ -"""A package that contains models that represent entities.""" +"""A package that contains models that represent entities. +""" diff --git a/venv1/Lib/site-packages/pip/_internal/models/candidate.py b/venv1/Lib/site-packages/pip/_internal/models/candidate.py index f27f2831..a4963aec 100644 --- a/venv1/Lib/site-packages/pip/_internal/models/candidate.py +++ b/venv1/Lib/site-packages/pip/_internal/models/candidate.py @@ -1,25 +1,34 @@ -from dataclasses import dataclass - -from pip._vendor.packaging.version import Version from pip._vendor.packaging.version import parse as parse_version from pip._internal.models.link import Link +from pip._internal.utils.models import KeyBasedCompareMixin -@dataclass(frozen=True) -class InstallationCandidate: +class InstallationCandidate(KeyBasedCompareMixin): """Represents a potential "candidate" for installation.""" __slots__ = ["name", "version", "link"] - name: str - version: Version - link: Link - def __init__(self, name: str, version: str, link: Link) -> None: - object.__setattr__(self, "name", name) - object.__setattr__(self, "version", parse_version(version)) - object.__setattr__(self, "link", link) + self.name = name + self.version = parse_version(version) + self.link = link + + super().__init__( + key=(self.name, self.version, self.link), + defining_class=InstallationCandidate, + ) + + def __repr__(self) -> str: + return "".format( + self.name, + self.version, + self.link, + ) def __str__(self) -> str: - return f"{self.name!r} candidate (version {self.version} at {self.link})" + return "{!r} candidate (version {} at {})".format( + self.name, + self.version, + self.link, + ) diff --git a/venv1/Lib/site-packages/pip/_internal/models/direct_url.py b/venv1/Lib/site-packages/pip/_internal/models/direct_url.py index aefc670c..e219d738 100644 --- a/venv1/Lib/site-packages/pip/_internal/models/direct_url.py +++ b/venv1/Lib/site-packages/pip/_internal/models/direct_url.py @@ -1,13 +1,8 @@ -"""PEP 610""" - -from __future__ import annotations - +""" PEP 610 """ import json import re import urllib.parse -from collections.abc import Iterable -from dataclasses import dataclass -from typing import Any, ClassVar, TypeVar, Union +from typing import Any, Dict, Iterable, Optional, Type, TypeVar, Union __all__ = [ "DirectUrl", @@ -28,21 +23,23 @@ class DirectUrlValidationError(Exception): def _get( - d: dict[str, Any], expected_type: type[T], key: str, default: T | None = None -) -> T | None: + d: Dict[str, Any], expected_type: Type[T], key: str, default: Optional[T] = None +) -> Optional[T]: """Get value from dictionary and verify expected type.""" if key not in d: return default value = d[key] if not isinstance(value, expected_type): raise DirectUrlValidationError( - f"{value!r} has unexpected type for {key} (expected {expected_type})" + "{!r} has unexpected type for {} (expected {})".format( + value, key, expected_type + ) ) return value def _get_required( - d: dict[str, Any], expected_type: type[T], key: str, default: T | None = None + d: Dict[str, Any], expected_type: Type[T], key: str, default: Optional[T] = None ) -> T: value = _get(d, expected_type, key, default) if value is None: @@ -50,7 +47,7 @@ def _get_required( return value -def _exactly_one_of(infos: Iterable[InfoType | None]) -> InfoType: +def _exactly_one_of(infos: Iterable[Optional["InfoType"]]) -> "InfoType": infos = [info for info in infos if info is not None] if not infos: raise DirectUrlValidationError( @@ -64,21 +61,26 @@ def _exactly_one_of(infos: Iterable[InfoType | None]) -> InfoType: return infos[0] -def _filter_none(**kwargs: Any) -> dict[str, Any]: +def _filter_none(**kwargs: Any) -> Dict[str, Any]: """Make dict excluding None values.""" return {k: v for k, v in kwargs.items() if v is not None} -@dataclass class VcsInfo: - name: ClassVar = "vcs_info" + name = "vcs_info" - vcs: str - commit_id: str - requested_revision: str | None = None + def __init__( + self, + vcs: str, + commit_id: str, + requested_revision: Optional[str] = None, + ) -> None: + self.vcs = vcs + self.requested_revision = requested_revision + self.commit_id = commit_id @classmethod - def _from_dict(cls, d: dict[str, Any] | None) -> VcsInfo | None: + def _from_dict(cls, d: Optional[Dict[str, Any]]) -> Optional["VcsInfo"]: if d is None: return None return cls( @@ -87,7 +89,7 @@ def _from_dict(cls, d: dict[str, Any] | None) -> VcsInfo | None: requested_revision=_get(d, str, "requested_revision"), ) - def _to_dict(self) -> dict[str, Any]: + def _to_dict(self) -> Dict[str, Any]: return _filter_none( vcs=self.vcs, requested_revision=self.requested_revision, @@ -100,19 +102,19 @@ class ArchiveInfo: def __init__( self, - hash: str | None = None, - hashes: dict[str, str] | None = None, + hash: Optional[str] = None, + hashes: Optional[Dict[str, str]] = None, ) -> None: # set hashes before hash, since the hash setter will further populate hashes self.hashes = hashes self.hash = hash @property - def hash(self) -> str | None: + def hash(self) -> Optional[str]: return self._hash @hash.setter - def hash(self, value: str | None) -> None: + def hash(self, value: Optional[str]) -> None: if value is not None: # Auto-populate the hashes key to upgrade to the new format automatically. # We don't back-populate the legacy hash key from hashes. @@ -130,39 +132,47 @@ def hash(self, value: str | None) -> None: self._hash = value @classmethod - def _from_dict(cls, d: dict[str, Any] | None) -> ArchiveInfo | None: + def _from_dict(cls, d: Optional[Dict[str, Any]]) -> Optional["ArchiveInfo"]: if d is None: return None return cls(hash=_get(d, str, "hash"), hashes=_get(d, dict, "hashes")) - def _to_dict(self) -> dict[str, Any]: + def _to_dict(self) -> Dict[str, Any]: return _filter_none(hash=self.hash, hashes=self.hashes) -@dataclass class DirInfo: - name: ClassVar = "dir_info" + name = "dir_info" - editable: bool = False + def __init__( + self, + editable: bool = False, + ) -> None: + self.editable = editable @classmethod - def _from_dict(cls, d: dict[str, Any] | None) -> DirInfo | None: + def _from_dict(cls, d: Optional[Dict[str, Any]]) -> Optional["DirInfo"]: if d is None: return None return cls(editable=_get_required(d, bool, "editable", default=False)) - def _to_dict(self) -> dict[str, Any]: + def _to_dict(self) -> Dict[str, Any]: return _filter_none(editable=self.editable or None) InfoType = Union[ArchiveInfo, DirInfo, VcsInfo] -@dataclass class DirectUrl: - url: str - info: InfoType - subdirectory: str | None = None + def __init__( + self, + url: str, + info: InfoType, + subdirectory: Optional[str] = None, + ) -> None: + self.url = url + self.info = info + self.subdirectory = subdirectory def _remove_auth_from_netloc(self, netloc: str) -> str: if "@" not in netloc: @@ -195,7 +205,7 @@ def validate(self) -> None: self.from_dict(self.to_dict()) @classmethod - def from_dict(cls, d: dict[str, Any]) -> DirectUrl: + def from_dict(cls, d: Dict[str, Any]) -> "DirectUrl": return DirectUrl( url=_get_required(d, str, "url"), subdirectory=_get(d, str, "subdirectory"), @@ -208,7 +218,7 @@ def from_dict(cls, d: dict[str, Any]) -> DirectUrl: ), ) - def to_dict(self) -> dict[str, Any]: + def to_dict(self) -> Dict[str, Any]: res = _filter_none( url=self.redacted_url, subdirectory=self.subdirectory, @@ -217,7 +227,7 @@ def to_dict(self) -> dict[str, Any]: return res @classmethod - def from_json(cls, s: str) -> DirectUrl: + def from_json(cls, s: str) -> "DirectUrl": return cls.from_dict(json.loads(s)) def to_json(self) -> str: diff --git a/venv1/Lib/site-packages/pip/_internal/models/format_control.py b/venv1/Lib/site-packages/pip/_internal/models/format_control.py index 9f07e3f3..db3995ea 100644 --- a/venv1/Lib/site-packages/pip/_internal/models/format_control.py +++ b/venv1/Lib/site-packages/pip/_internal/models/format_control.py @@ -1,4 +1,4 @@ -from __future__ import annotations +from typing import FrozenSet, Optional, Set from pip._vendor.packaging.utils import canonicalize_name @@ -12,8 +12,8 @@ class FormatControl: def __init__( self, - no_binary: set[str] | None = None, - only_binary: set[str] | None = None, + no_binary: Optional[Set[str]] = None, + only_binary: Optional[Set[str]] = None, ) -> None: if no_binary is None: no_binary = set() @@ -33,10 +33,12 @@ def __eq__(self, other: object) -> bool: return all(getattr(self, k) == getattr(other, k) for k in self.__slots__) def __repr__(self) -> str: - return f"{self.__class__.__name__}({self.no_binary}, {self.only_binary})" + return "{}({}, {})".format( + self.__class__.__name__, self.no_binary, self.only_binary + ) @staticmethod - def handle_mutual_excludes(value: str, target: set[str], other: set[str]) -> None: + def handle_mutual_excludes(value: str, target: Set[str], other: Set[str]) -> None: if value.startswith("-"): raise CommandError( "--no-binary / --only-binary option requires 1 argument." @@ -58,7 +60,7 @@ def handle_mutual_excludes(value: str, target: set[str], other: set[str]) -> Non other.discard(name) target.add(name) - def get_allowed_formats(self, canonical_name: str) -> frozenset[str]: + def get_allowed_formats(self, canonical_name: str) -> FrozenSet[str]: result = {"binary", "source"} if canonical_name in self.only_binary: result.discard("source") diff --git a/venv1/Lib/site-packages/pip/_internal/models/installation_report.py b/venv1/Lib/site-packages/pip/_internal/models/installation_report.py index 3e8e9683..fef3757f 100644 --- a/venv1/Lib/site-packages/pip/_internal/models/installation_report.py +++ b/venv1/Lib/site-packages/pip/_internal/models/installation_report.py @@ -1,5 +1,4 @@ -from collections.abc import Sequence -from typing import Any +from typing import Any, Dict, Sequence from pip._vendor.packaging.markers import default_environment @@ -12,7 +11,7 @@ def __init__(self, install_requirements: Sequence[InstallRequirement]): self._install_requirements = install_requirements @classmethod - def _install_req_to_dict(cls, ireq: InstallRequirement) -> dict[str, Any]: + def _install_req_to_dict(cls, ireq: InstallRequirement) -> Dict[str, Any]: assert ireq.download_info, f"No download_info for {ireq}" res = { # PEP 610 json for the download URL. download_info.archive_info.hashes may @@ -23,10 +22,7 @@ def _install_req_to_dict(cls, ireq: InstallRequirement) -> dict[str, Any]: # is_direct is true if the requirement was a direct URL reference (which # includes editable requirements), and false if the requirement was # downloaded from a PEP 503 index or --find-links. - "is_direct": ireq.is_direct, - # is_yanked is true if the requirement was yanked from the index, but - # was still selected by pip to conform to PEP 592. - "is_yanked": ireq.link.is_yanked if ireq.link else False, + "is_direct": bool(ireq.original_link), # requested is true if the requirement was specified by the user (aka # top level requirement), and false if it was installed as a dependency of a # requirement. https://peps.python.org/pep-0376/#requested @@ -37,10 +33,10 @@ def _install_req_to_dict(cls, ireq: InstallRequirement) -> dict[str, Any]: } if ireq.user_supplied and ireq.extras: # For top level requirements, the list of requested extras, if any. - res["requested_extras"] = sorted(ireq.extras) + res["requested_extras"] = list(sorted(ireq.extras)) return res - def to_dict(self) -> dict[str, Any]: + def to_dict(self) -> Dict[str, Any]: return { "version": "1", "pip_version": __version__, diff --git a/venv1/Lib/site-packages/pip/_internal/models/link.py b/venv1/Lib/site-packages/pip/_internal/models/link.py index 295035fc..e741c328 100644 --- a/venv1/Lib/site-packages/pip/_internal/models/link.py +++ b/venv1/Lib/site-packages/pip/_internal/models/link.py @@ -1,5 +1,3 @@ -from __future__ import annotations - import functools import itertools import logging @@ -7,12 +5,17 @@ import posixpath import re import urllib.parse -from collections.abc import Mapping from dataclasses import dataclass from typing import ( TYPE_CHECKING, Any, + Dict, + List, + Mapping, NamedTuple, + Optional, + Tuple, + Union, ) from pip._internal.utils.deprecation import deprecated @@ -24,6 +27,7 @@ split_auth_from_netloc, splitext, ) +from pip._internal.utils.models import KeyBasedCompareMixin from pip._internal.utils.urls import path_to_url, url_to_path if TYPE_CHECKING: @@ -66,8 +70,20 @@ def __post_init__(self) -> None: assert self.name in _SUPPORTED_HASHES @classmethod - @functools.cache - def find_hash_url_fragment(cls, url: str) -> LinkHash | None: + def parse_pep658_hash(cls, dist_info_metadata: str) -> Optional["LinkHash"]: + """Parse a PEP 658 data-dist-info-metadata hash.""" + if dist_info_metadata == "true": + return None + name, sep, value = dist_info_metadata.partition("=") + if not sep: + return None + if name not in _SUPPORTED_HASHES: + return None + return cls(name=name, value=value) + + @classmethod + @functools.lru_cache(maxsize=None) + def find_hash_url_fragment(cls, url: str) -> Optional["LinkHash"]: """Search a string for a checksum algorithm name and encoded output value.""" match = cls._hash_url_fragment_re.search(url) if match is None: @@ -75,14 +91,14 @@ def find_hash_url_fragment(cls, url: str) -> LinkHash | None: name, value = match.groups() return cls(name=name, value=value) - def as_dict(self) -> dict[str, str]: + def as_dict(self) -> Dict[str, str]: return {self.name: self.value} def as_hashes(self) -> Hashes: """Return a Hashes instance which checks only for the current hash.""" return Hashes({self.name: [self.value]}) - def is_hash_allowed(self, hashes: Hashes | None) -> bool: + def is_hash_allowed(self, hashes: Optional[Hashes]) -> bool: """ Return True if the current hash is allowed by `hashes`. """ @@ -91,28 +107,6 @@ def is_hash_allowed(self, hashes: Hashes | None) -> bool: return hashes.is_hash_allowed(self.name, hex_digest=self.value) -@dataclass(frozen=True) -class MetadataFile: - """Information about a core metadata file associated with a distribution.""" - - hashes: dict[str, str] | None - - def __post_init__(self) -> None: - if self.hashes is not None: - assert all(name in _SUPPORTED_HASHES for name in self.hashes) - - -def supported_hashes(hashes: dict[str, str] | None) -> dict[str, str] | None: - # Remove any unsupported hash types from the mapping. If this leaves no - # supported hashes, return None - if hashes is None: - return None - hashes = {n: v for n, v in hashes.items() if n in _SUPPORTED_HASHES} - if not hashes: - return None - return hashes - - def _clean_url_path_part(part: str) -> str: """ Clean a "part" of a URL path (i.e. after splitting on "@" characters). @@ -131,11 +125,7 @@ def _clean_file_url_path(part: str) -> str: # should not be quoted. On Linux where drive letters do not # exist, the colon should be quoted. We rely on urllib.request # to do the right thing here. - ret = urllib.request.pathname2url(urllib.request.url2pathname(part)) - if ret.startswith("///"): - # Remove any URL authority section, leaving only the URL path. - ret = ret.removeprefix("//") - return ret + return urllib.request.pathname2url(urllib.request.url2pathname(part)) # percent-encoded: / @@ -171,42 +161,25 @@ def _ensure_quoted_url(url: str) -> str: and without double-quoting other characters. """ # Split the URL into parts according to the general structure - # `scheme://netloc/path?query#fragment`. - result = urllib.parse.urlsplit(url) + # `scheme://netloc/path;parameters?query#fragment`. + result = urllib.parse.urlparse(url) # If the netloc is empty, then the URL refers to a local filesystem path. is_local_path = not result.netloc path = _clean_url_path(result.path, is_local_path=is_local_path) - # Temporarily replace scheme with file to ensure the URL generated by - # urlunsplit() contains an empty netloc (file://) as per RFC 1738. - ret = urllib.parse.urlunsplit(result._replace(scheme="file", path=path)) - ret = result.scheme + ret[4:] # Restore original scheme. - return ret - - -def _absolute_link_url(base_url: str, url: str) -> str: - """ - A faster implementation of urllib.parse.urljoin with a shortcut - for absolute http/https URLs. - """ - if url.startswith(("https://", "http://")): - return url - else: - return urllib.parse.urljoin(base_url, url) + return urllib.parse.urlunparse(result._replace(path=path)) -@functools.total_ordering -class Link: +class Link(KeyBasedCompareMixin): """Represents a parsed link from a Package Index's simple URL""" __slots__ = [ "_parsed_url", "_url", - "_path", "_hashes", "comes_from", "requires_python", "yanked_reason", - "metadata_file_data", + "dist_info_metadata", "cache_link_parsing", "egg_fragment", ] @@ -214,12 +187,12 @@ class Link: def __init__( self, url: str, - comes_from: str | IndexContent | None = None, - requires_python: str | None = None, - yanked_reason: str | None = None, - metadata_file_data: MetadataFile | None = None, + comes_from: Optional[Union[str, "IndexContent"]] = None, + requires_python: Optional[str] = None, + yanked_reason: Optional[str] = None, + dist_info_metadata: Optional[str] = None, cache_link_parsing: bool = True, - hashes: Mapping[str, str] | None = None, + hashes: Optional[Mapping[str, str]] = None, ) -> None: """ :param url: url of the resource pointed to (href of the link) @@ -235,10 +208,11 @@ def __init__( a simple repository HTML link. If the file has been yanked but no reason was provided, this should be the empty string. See PEP 592 for more information and the specification. - :param metadata_file_data: the metadata attached to the file, or None if - no such metadata is provided. This argument, if not None, indicates - that a separate metadata file exists, and also optionally supplies - hashes for that file. + :param dist_info_metadata: the metadata attached to the file, or None if no such + metadata is provided. This is the value of the "data-dist-info-metadata" + attribute, if present, in a simple repository HTML link. This may be parsed + into its own `Link` by `self.metadata_link()`. See PEP 658 for more + information and the specification. :param cache_link_parsing: A flag that is used elsewhere to determine whether resources retrieved from this link should be cached. PyPI URLs should generally have this set to False, for example. @@ -246,10 +220,6 @@ def __init__( determine the validity of a download. """ - # The comes_from, requires_python, and metadata_file_data arguments are - # only used by classmethods of this class, and are not used in client - # code directly. - # url can be a UNC windows share if url.startswith("\\\\"): url = path_to_url(url) @@ -258,8 +228,6 @@ def __init__( # Store the url as a private attribute to prevent accidentally # trying to set a new value. self._url = url - # The .path property is hot, so calculate its value ahead of time. - self._path = urllib.parse.unquote(self._parsed_url.path) link_hash = LinkHash.find_hash_url_fragment(url) hashes_from_link = {} if link_hash is None else link_hash.as_dict() @@ -271,7 +239,9 @@ def __init__( self.comes_from = comes_from self.requires_python = requires_python if requires_python else None self.yanked_reason = yanked_reason - self.metadata_file_data = metadata_file_data + self.dist_info_metadata = dist_info_metadata + + super().__init__(key=url, defining_class=Link) self.cache_link_parsing = cache_link_parsing self.egg_fragment = self._egg_fragment() @@ -279,9 +249,9 @@ def __init__( @classmethod def from_json( cls, - file_data: dict[str, Any], + file_data: Dict[str, Any], page_url: str, - ) -> Link | None: + ) -> Optional["Link"]: """ Convert an pypi json document from a simple repository page into a Link. """ @@ -289,28 +259,12 @@ def from_json( if file_url is None: return None - url = _ensure_quoted_url(_absolute_link_url(page_url, file_url)) + url = _ensure_quoted_url(urllib.parse.urljoin(page_url, file_url)) pyrequire = file_data.get("requires-python") yanked_reason = file_data.get("yanked") + dist_info_metadata = file_data.get("dist-info-metadata") hashes = file_data.get("hashes", {}) - # PEP 714: Indexes must use the name core-metadata, but - # clients should support the old name as a fallback for compatibility. - metadata_info = file_data.get("core-metadata") - if metadata_info is None: - metadata_info = file_data.get("dist-info-metadata") - - # The metadata info value may be a boolean, or a dict of hashes. - if isinstance(metadata_info, dict): - # The file exists, and hashes have been supplied - metadata_file_data = MetadataFile(supported_hashes(metadata_info)) - elif metadata_info: - # The file exists, but there are no hashes - metadata_file_data = MetadataFile(None) - else: - # False or not present: the file does not exist - metadata_file_data = None - # The Link.yanked_reason expects an empty string instead of a boolean. if yanked_reason and not isinstance(yanked_reason, str): yanked_reason = "" @@ -324,16 +278,16 @@ def from_json( requires_python=pyrequire, yanked_reason=yanked_reason, hashes=hashes, - metadata_file_data=metadata_file_data, + dist_info_metadata=dist_info_metadata, ) @classmethod def from_element( cls, - anchor_attribs: dict[str, str | None], + anchor_attribs: Dict[str, Optional[str]], page_url: str, base_url: str, - ) -> Link | None: + ) -> Optional["Link"]: """ Convert an anchor element's attributes in a simple repository page to a Link. """ @@ -341,42 +295,17 @@ def from_element( if not href: return None - url = _ensure_quoted_url(_absolute_link_url(base_url, href)) + url = _ensure_quoted_url(urllib.parse.urljoin(base_url, href)) pyrequire = anchor_attribs.get("data-requires-python") yanked_reason = anchor_attribs.get("data-yanked") - - # PEP 714: Indexes must use the name data-core-metadata, but - # clients should support the old name as a fallback for compatibility. - metadata_info = anchor_attribs.get("data-core-metadata") - if metadata_info is None: - metadata_info = anchor_attribs.get("data-dist-info-metadata") - # The metadata info value may be the string "true", or a string of - # the form "hashname=hashval" - if metadata_info == "true": - # The file exists, but there are no hashes - metadata_file_data = MetadataFile(None) - elif metadata_info is None: - # The file does not exist - metadata_file_data = None - else: - # The file exists, and hashes have been supplied - hashname, sep, hashval = metadata_info.partition("=") - if sep == "=": - metadata_file_data = MetadataFile(supported_hashes({hashname: hashval})) - else: - # Error - data is wrong. Treat as no hashes supplied. - logger.debug( - "Index returned invalid data-dist-info-metadata value: %s", - metadata_info, - ) - metadata_file_data = MetadataFile(None) + dist_info_metadata = anchor_attribs.get("data-dist-info-metadata") return cls( url, comes_from=page_url, requires_python=pyrequire, yanked_reason=yanked_reason, - metadata_file_data=metadata_file_data, + dist_info_metadata=dist_info_metadata, ) def __str__(self) -> str: @@ -385,34 +314,19 @@ def __str__(self) -> str: else: rp = "" if self.comes_from: - return f"{self.redacted_url} (from {self.comes_from}){rp}" + return "{} (from {}){}".format( + redact_auth_from_url(self._url), self.comes_from, rp + ) else: - return self.redacted_url + return redact_auth_from_url(str(self._url)) def __repr__(self) -> str: return f"" - def __hash__(self) -> int: - return hash(self.url) - - def __eq__(self, other: Any) -> bool: - if not isinstance(other, Link): - return NotImplemented - return self.url == other.url - - def __lt__(self, other: Any) -> bool: - if not isinstance(other, Link): - return NotImplemented - return self.url < other.url - @property def url(self) -> str: return self._url - @property - def redacted_url(self) -> str: - return redact_auth_from_url(self.url) - @property def filename(self) -> str: path = self.path.rstrip("/") @@ -444,9 +358,9 @@ def netloc(self) -> str: @property def path(self) -> str: - return self._path + return urllib.parse.unquote(self._parsed_url.path) - def splitext(self) -> tuple[str, str]: + def splitext(self) -> Tuple[str, str]: return splitext(posixpath.basename(self.path.rstrip("/"))) @property @@ -465,7 +379,7 @@ def url_without_fragment(self) -> str: r"^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$", re.IGNORECASE ) - def _egg_fragment(self) -> str | None: + def _egg_fragment(self) -> Optional[str]: match = self._egg_fragment_re.search(self._url) if not match: return None @@ -475,10 +389,10 @@ def _egg_fragment(self) -> str | None: project_name = match.group(1) if not self._project_name_re.match(project_name): deprecated( - reason=f"{self} contains an egg fragment with a non-PEP 508 name.", + reason=f"{self} contains an egg fragment with a non-PEP 508 name", replacement="to use the req @ url syntax, and remove the egg fragment", - gone_in="26.0", - issue=13157, + gone_in="25.0", + issue=11617, ) return project_name @@ -486,30 +400,34 @@ def _egg_fragment(self) -> str | None: _subdirectory_fragment_re = re.compile(r"[#&]subdirectory=([^&]*)") @property - def subdirectory_fragment(self) -> str | None: + def subdirectory_fragment(self) -> Optional[str]: match = self._subdirectory_fragment_re.search(self._url) if not match: return None return match.group(1) - def metadata_link(self) -> Link | None: - """Return a link to the associated core metadata file (if any).""" - if self.metadata_file_data is None: + def metadata_link(self) -> Optional["Link"]: + """Implementation of PEP 658 parsing.""" + # Note that Link.from_element() parsing the "data-dist-info-metadata" attribute + # from an HTML anchor tag is typically how the Link.dist_info_metadata attribute + # gets set. + if self.dist_info_metadata is None: return None metadata_url = f"{self.url_without_fragment}.metadata" - if self.metadata_file_data.hashes is None: + metadata_link_hash = LinkHash.parse_pep658_hash(self.dist_info_metadata) + if metadata_link_hash is None: return Link(metadata_url) - return Link(metadata_url, hashes=self.metadata_file_data.hashes) + return Link(metadata_url, hashes=metadata_link_hash.as_dict()) def as_hashes(self) -> Hashes: return Hashes({k: [v] for k, v in self._hashes.items()}) @property - def hash(self) -> str | None: + def hash(self) -> Optional[str]: return next(iter(self._hashes.values()), None) @property - def hash_name(self) -> str | None: + def hash_name(self) -> Optional[str]: return next(iter(self._hashes), None) @property @@ -541,7 +459,7 @@ def is_yanked(self) -> bool: def has_hash(self) -> bool: return bool(self._hashes) - def is_hash_allowed(self, hashes: Hashes | None) -> bool: + def is_hash_allowed(self, hashes: Optional[Hashes]) -> bool: """ Return True if the link has a hash and it is allowed by `hashes`. """ @@ -577,9 +495,9 @@ class _CleanResult(NamedTuple): """ parsed: urllib.parse.SplitResult - query: dict[str, list[str]] + query: Dict[str, List[str]] subdirectory: str - hashes: dict[str, str] + hashes: Dict[str, str] def _clean_link(link: Link) -> _CleanResult: @@ -608,6 +526,6 @@ def _clean_link(link: Link) -> _CleanResult: ) -@functools.cache +@functools.lru_cache(maxsize=None) def links_equivalent(link1: Link, link2: Link) -> bool: return _clean_link(link1) == _clean_link(link2) diff --git a/venv1/Lib/site-packages/pip/_internal/models/scheme.py b/venv1/Lib/site-packages/pip/_internal/models/scheme.py index 06a9a550..f51190ac 100644 --- a/venv1/Lib/site-packages/pip/_internal/models/scheme.py +++ b/venv1/Lib/site-packages/pip/_internal/models/scheme.py @@ -5,12 +5,10 @@ https://docs.python.org/3/install/index.html#alternate-installation. """ -from dataclasses import dataclass SCHEME_KEYS = ["platlib", "purelib", "headers", "scripts", "data"] -@dataclass(frozen=True) class Scheme: """A Scheme holds paths which are used as the base directories for artifacts associated with a Python package. @@ -18,8 +16,16 @@ class Scheme: __slots__ = SCHEME_KEYS - platlib: str - purelib: str - headers: str - scripts: str - data: str + def __init__( + self, + platlib: str, + purelib: str, + headers: str, + scripts: str, + data: str, + ) -> None: + self.platlib = platlib + self.purelib = purelib + self.headers = headers + self.scripts = scripts + self.data = data diff --git a/venv1/Lib/site-packages/pip/_internal/models/search_scope.py b/venv1/Lib/site-packages/pip/_internal/models/search_scope.py index 136163ca..fe61e811 100644 --- a/venv1/Lib/site-packages/pip/_internal/models/search_scope.py +++ b/venv1/Lib/site-packages/pip/_internal/models/search_scope.py @@ -3,7 +3,7 @@ import os import posixpath import urllib.parse -from dataclasses import dataclass +from typing import List from pip._vendor.packaging.utils import canonicalize_name @@ -14,23 +14,19 @@ logger = logging.getLogger(__name__) -@dataclass(frozen=True) class SearchScope: + """ Encapsulates the locations that pip is configured to search. """ __slots__ = ["find_links", "index_urls", "no_index"] - find_links: list[str] - index_urls: list[str] - no_index: bool - @classmethod def create( cls, - find_links: list[str], - index_urls: list[str], + find_links: List[str], + index_urls: List[str], no_index: bool, ) -> "SearchScope": """ @@ -41,7 +37,7 @@ def create( # it and if it exists, use the normalized version. # This is deliberately conservative - it might be fine just to # blindly normalize anything starting with a ~... - built_find_links: list[str] = [] + built_find_links: List[str] = [] for link in find_links: if link.startswith("~"): new_link = normalize_path(link) @@ -68,6 +64,16 @@ def create( no_index=no_index, ) + def __init__( + self, + find_links: List[str], + index_urls: List[str], + no_index: bool, + ) -> None: + self.find_links = find_links + self.index_urls = index_urls + self.no_index = no_index + def get_formatted_locations(self) -> str: lines = [] redacted_index_urls = [] @@ -103,7 +109,7 @@ def get_formatted_locations(self) -> str: ) return "\n".join(lines) - def get_index_urls_locations(self, project_name: str) -> list[str]: + def get_index_urls_locations(self, project_name: str) -> List[str]: """Returns the locations found via self.index_urls Checks the url_name on the main (first in the list) index and diff --git a/venv1/Lib/site-packages/pip/_internal/models/selection_prefs.py b/venv1/Lib/site-packages/pip/_internal/models/selection_prefs.py index 8d5b42df..977bc4ca 100644 --- a/venv1/Lib/site-packages/pip/_internal/models/selection_prefs.py +++ b/venv1/Lib/site-packages/pip/_internal/models/selection_prefs.py @@ -1,10 +1,8 @@ -from __future__ import annotations +from typing import Optional from pip._internal.models.format_control import FormatControl -# TODO: This needs Python 3.10's improved slots support for dataclasses -# to be converted into a dataclass. class SelectionPreferences: """ Encapsulates the candidate selection preferences for downloading @@ -27,9 +25,9 @@ def __init__( self, allow_yanked: bool, allow_all_prereleases: bool = False, - format_control: FormatControl | None = None, + format_control: Optional[FormatControl] = None, prefer_binary: bool = False, - ignore_requires_python: bool | None = None, + ignore_requires_python: Optional[bool] = None, ) -> None: """Create a SelectionPreferences object. diff --git a/venv1/Lib/site-packages/pip/_internal/models/target_python.py b/venv1/Lib/site-packages/pip/_internal/models/target_python.py index 8c38392d..744bd7ef 100644 --- a/venv1/Lib/site-packages/pip/_internal/models/target_python.py +++ b/venv1/Lib/site-packages/pip/_internal/models/target_python.py @@ -1,6 +1,5 @@ -from __future__ import annotations - import sys +from typing import List, Optional, Tuple from pip._vendor.packaging.tags import Tag @@ -9,6 +8,7 @@ class TargetPython: + """ Encapsulates the properties of a Python interpreter one is targeting for a package install, download, etc. @@ -22,15 +22,14 @@ class TargetPython: "py_version", "py_version_info", "_valid_tags", - "_valid_tags_set", ] def __init__( self, - platforms: list[str] | None = None, - py_version_info: tuple[int, ...] | None = None, - abis: list[str] | None = None, - implementation: str | None = None, + platforms: Optional[List[str]] = None, + py_version_info: Optional[Tuple[int, ...]] = None, + abis: Optional[List[str]] = None, + implementation: Optional[str] = None, ) -> None: """ :param platforms: A list of strings or None. If None, searches for @@ -62,9 +61,8 @@ def __init__( self.py_version = py_version self.py_version_info = py_version_info - # This is used to cache the return value of get_(un)sorted_tags. - self._valid_tags: list[Tag] | None = None - self._valid_tags_set: set[Tag] | None = None + # This is used to cache the return value of get_tags(). + self._valid_tags: Optional[List[Tag]] = None def format_given(self) -> str: """ @@ -86,7 +84,7 @@ def format_given(self) -> str: f"{key}={value!r}" for key, value in key_values if value is not None ) - def get_sorted_tags(self) -> list[Tag]: + def get_tags(self) -> List[Tag]: """ Return the supported PEP 425 tags to check wheel candidates against. @@ -110,13 +108,3 @@ def get_sorted_tags(self) -> list[Tag]: self._valid_tags = tags return self._valid_tags - - def get_unsorted_tags(self) -> set[Tag]: - """Exactly the same as get_sorted_tags, but returns a set. - - This is important for performance. - """ - if self._valid_tags_set is None: - self._valid_tags_set = set(self.get_sorted_tags()) - - return self._valid_tags_set diff --git a/venv1/Lib/site-packages/pip/_internal/models/wheel.py b/venv1/Lib/site-packages/pip/_internal/models/wheel.py index fbd4902d..a5dc12bd 100644 --- a/venv1/Lib/site-packages/pip/_internal/models/wheel.py +++ b/venv1/Lib/site-packages/pip/_internal/models/wheel.py @@ -1,16 +1,10 @@ """Represents a wheel file and provides access to the various parts of the name that have meaning. """ - -from __future__ import annotations - -from collections.abc import Iterable +import re +from typing import Dict, Iterable, List from pip._vendor.packaging.tags import Tag -from pip._vendor.packaging.utils import ( - InvalidWheelFilename as _PackagingInvalidWheelFilename, -) -from pip._vendor.packaging.utils import parse_wheel_filename from pip._internal.exceptions import InvalidWheelFilename @@ -18,22 +12,40 @@ class Wheel: """A wheel file""" + wheel_file_re = re.compile( + r"""^(?P(?P[^\s-]+?)-(?P[^\s-]*?)) + ((-(?P\d[^-]*?))?-(?P[^\s-]+?)-(?P[^\s-]+?)-(?P[^\s-]+?) + \.whl|\.dist-info)$""", + re.VERBOSE, + ) + def __init__(self, filename: str) -> None: + """ + :raises InvalidWheelFilename: when the filename is invalid for a wheel + """ + wheel_info = self.wheel_file_re.match(filename) + if not wheel_info: + raise InvalidWheelFilename(f"{filename} is not a valid wheel filename.") self.filename = filename - - try: - wheel_info = parse_wheel_filename(filename) - except _PackagingInvalidWheelFilename as e: - raise InvalidWheelFilename(e.args[0]) from None - - self.name, _version, self.build_tag, self.file_tags = wheel_info - self.version = str(_version) - - def get_formatted_file_tags(self) -> list[str]: + 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("_", "-") + self.build_tag = wheel_info.group("build") + self.pyversions = wheel_info.group("pyver").split(".") + self.abis = wheel_info.group("abi").split(".") + self.plats = wheel_info.group("plat").split(".") + + # All the tag combinations from this file + self.file_tags = { + Tag(x, y, z) for x in self.pyversions for y in self.abis for z in self.plats + } + + def get_formatted_file_tags(self) -> List[str]: """Return the wheel's tags as a sorted list of strings.""" return sorted(str(tag) for tag in self.file_tags) - def support_index_min(self, tags: list[Tag]) -> int: + def support_index_min(self, tags: List[Tag]) -> int: """Return the lowest index that one of the wheel's file_tag combinations achieves in the given list of supported tags. @@ -52,7 +64,7 @@ def support_index_min(self, tags: list[Tag]) -> int: raise ValueError() def find_most_preferred_tag( - self, tags: list[Tag], tag_to_priority: dict[Tag, int] + self, tags: List[Tag], tag_to_priority: Dict[Tag, int] ) -> int: """Return the priority of the most preferred tag that one of the wheel's file tag combinations achieves in the given list of supported tags using the given diff --git a/venv1/Lib/site-packages/pip/_internal/network/__init__.py b/venv1/Lib/site-packages/pip/_internal/network/__init__.py index 0ae1f562..b51bde91 100644 --- a/venv1/Lib/site-packages/pip/_internal/network/__init__.py +++ b/venv1/Lib/site-packages/pip/_internal/network/__init__.py @@ -1 +1,2 @@ -"""Contains purely network-related utilities.""" +"""Contains purely network-related utilities. +""" diff --git a/venv1/Lib/site-packages/pip/_internal/network/auth.py b/venv1/Lib/site-packages/pip/_internal/network/auth.py index a42f7024..c0efa765 100644 --- a/venv1/Lib/site-packages/pip/_internal/network/auth.py +++ b/venv1/Lib/site-packages/pip/_internal/network/auth.py @@ -3,9 +3,6 @@ Contains interface (MultiDomainBasicAuth) and associated glue code for providing credentials in the context of network requests. """ - -from __future__ import annotations - import logging import os import shutil @@ -14,10 +11,10 @@ import typing import urllib.parse from abc import ABC, abstractmethod -from functools import cache +from functools import lru_cache from os.path import commonprefix from pathlib import Path -from typing import Any, NamedTuple +from typing import Any, Dict, List, NamedTuple, Optional, Tuple from pip._vendor.requests.auth import AuthBase, HTTPBasicAuth from pip._vendor.requests.models import Request, Response @@ -50,10 +47,12 @@ class KeyRingBaseProvider(ABC): has_keyring: bool @abstractmethod - def get_auth_info(self, url: str, username: str | None) -> AuthInfo | None: ... + def get_auth_info(self, url: str, username: Optional[str]) -> Optional[AuthInfo]: + ... @abstractmethod - def save_auth_info(self, url: str, username: str, password: str) -> None: ... + def save_auth_info(self, url: str, username: str, password: str) -> None: + ... class KeyRingNullProvider(KeyRingBaseProvider): @@ -61,7 +60,7 @@ class KeyRingNullProvider(KeyRingBaseProvider): has_keyring = False - def get_auth_info(self, url: str, username: str | None) -> AuthInfo | None: + def get_auth_info(self, url: str, username: Optional[str]) -> Optional[AuthInfo]: return None def save_auth_info(self, url: str, username: str, password: str) -> None: @@ -78,7 +77,7 @@ def __init__(self) -> None: self.keyring = keyring - def get_auth_info(self, url: str, username: str | None) -> AuthInfo | None: + def get_auth_info(self, url: str, username: Optional[str]) -> Optional[AuthInfo]: # Support keyring's get_credential interface which supports getting # credentials without a username. This is only available for # keyring>=15.2.0. @@ -114,7 +113,7 @@ class KeyRingCliProvider(KeyRingBaseProvider): def __init__(self, cmd: str) -> None: self.keyring = cmd - def get_auth_info(self, url: str, username: str | None) -> AuthInfo | None: + def get_auth_info(self, url: str, username: Optional[str]) -> Optional[AuthInfo]: # This is the default implementation of keyring.get_credential # https://github.com/jaraco/keyring/blob/97689324abcf01bd1793d49063e7ca01e03d7d07/keyring/backend.py#L134-L139 if username is not None: @@ -126,7 +125,7 @@ def get_auth_info(self, url: str, username: str | None) -> AuthInfo | None: def save_auth_info(self, url: str, username: str, password: str) -> None: return self._set_password(url, username, password) - def _get_password(self, service_name: str, username: str) -> str | None: + def _get_password(self, service_name: str, username: str) -> Optional[str]: """Mirror the implementation of keyring.get_password using cli""" if self.keyring is None: return None @@ -152,14 +151,14 @@ def _set_password(self, service_name: str, username: str, password: str) -> None env["PYTHONIOENCODING"] = "utf-8" subprocess.run( [self.keyring, "set", service_name, username], - input=f"{password}{os.linesep}".encode(), + input=f"{password}{os.linesep}".encode("utf-8"), env=env, check=True, ) return None -@cache +@lru_cache(maxsize=None) def get_keyring_provider(provider: str) -> KeyRingBaseProvider: logger.verbose("Keyring provider requested: %s", provider) @@ -225,19 +224,19 @@ class MultiDomainBasicAuth(AuthBase): def __init__( self, prompting: bool = True, - index_urls: list[str] | None = None, + index_urls: Optional[List[str]] = None, keyring_provider: str = "auto", ) -> None: self.prompting = prompting self.index_urls = index_urls - self.keyring_provider = keyring_provider - self.passwords: dict[str, AuthInfo] = {} + self.keyring_provider = keyring_provider # type: ignore[assignment] + self.passwords: Dict[str, AuthInfo] = {} # When the user is prompted to enter credentials and keyring is # available, we will offer to save them. If the user accepts, # this value is set to the credentials they entered. After the # request authenticates, the caller should call # ``save_credentials`` to save these. - self._credentials_to_save: Credentials | None = None + self._credentials_to_save: Optional[Credentials] = None @property def keyring_provider(self) -> KeyRingBaseProvider: @@ -260,9 +259,9 @@ def use_keyring(self) -> bool: def _get_keyring_auth( self, - url: str | None, - username: str | None, - ) -> AuthInfo | None: + url: Optional[str], + username: Optional[str], + ) -> Optional[AuthInfo]: """Return the tuple auth for a given url from keyring.""" # Do nothing if no url was provided if not url: @@ -271,10 +270,6 @@ def _get_keyring_auth( try: return self.keyring_provider.get_auth_info(url, username) except Exception as exc: - # Log the full exception (with stacktrace) at debug, so it'll only - # show up when running in verbose mode. - logger.debug("Keyring is skipped due to an exception", exc_info=True) - # Always log a shortened version of the exception. logger.warning( "Keyring is skipped due to an exception: %s", str(exc), @@ -284,7 +279,7 @@ def _get_keyring_auth( get_keyring_provider.cache_clear() return None - def _get_index_url(self, url: str) -> str | None: + def _get_index_url(self, url: str) -> Optional[str]: """Return the original index URL matching the requested URL. Cached or dynamically generated credentials may work against @@ -391,7 +386,7 @@ def _get_new_credentials( def _get_url_and_credentials( self, original_url: str - ) -> tuple[str, str | None, str | None]: + ) -> Tuple[str, Optional[str], Optional[str]]: """Return the credentials to use for the provided URL. If allowed, netrc and keyring may be used to obtain the @@ -454,7 +449,9 @@ def __call__(self, req: Request) -> Request: return req # Factored out to allow for easy patching in tests - def _prompt_for_password(self, netloc: str) -> tuple[str | None, str | None, bool]: + def _prompt_for_password( + self, netloc: str + ) -> Tuple[Optional[str], Optional[str], bool]: username = ask_input(f"User for {netloc}: ") if self.prompting else None if not username: return None, None, False @@ -517,9 +514,7 @@ def handle_401(self, resp: Response, **kwargs: Any) -> Response: # Consume content and release the original connection to allow our new # request to reuse the same one. - # The result of the assignment isn't used, it's just needed to consume - # the content. - _ = resp.content + resp.content resp.raw.release_conn() # Add our new username and password to the request diff --git a/venv1/Lib/site-packages/pip/_internal/network/cache.py b/venv1/Lib/site-packages/pip/_internal/network/cache.py index 2a372f2e..a81a2398 100644 --- a/venv1/Lib/site-packages/pip/_internal/network/cache.py +++ b/venv1/Lib/site-packages/pip/_internal/network/cache.py @@ -1,23 +1,15 @@ -"""HTTP cache implementation.""" - -from __future__ import annotations +"""HTTP cache implementation. +""" import os -import shutil -from collections.abc import Generator from contextlib import contextmanager -from datetime import datetime -from typing import Any, BinaryIO, Callable +from typing import Generator, Optional -from pip._vendor.cachecontrol.cache import SeparateBodyBaseCache -from pip._vendor.cachecontrol.caches import SeparateBodyFileCache +from pip._vendor.cachecontrol.cache import BaseCache +from pip._vendor.cachecontrol.caches import FileCache from pip._vendor.requests.models import Response -from pip._internal.utils.filesystem import ( - adjacent_tmp_file, - copy_directory_permissions, - replace, -) +from pip._internal.utils.filesystem import adjacent_tmp_file, replace from pip._internal.utils.misc import ensure_dir @@ -36,22 +28,10 @@ def suppressed_cache_errors() -> Generator[None, None, None]: pass -class SafeFileCache(SeparateBodyBaseCache): +class SafeFileCache(BaseCache): """ A file based cache which is safe to use even when the target directory may not be accessible or writable. - - There is a race condition when two processes try to write and/or read the - same entry at the same time, since each entry consists of two separate - files (https://github.com/psf/cachecontrol/issues/324). We therefore have - additional logic that makes sure that both files to be present before - returning an entry; this fixes the read side of the race condition. - - For the write side, we assume that the server will only ever return the - same data for the same URL, which ought to be the case for files pip is - downloading. PyPI does not have a mechanism to swap out a wheel for - another wheel, for example. If this assumption is not true, the - CacheControl issue will need to be fixed. """ def __init__(self, directory: str) -> None: @@ -63,66 +43,27 @@ def _get_cache_path(self, name: str) -> str: # From cachecontrol.caches.file_cache.FileCache._fn, brought into our # class for backwards-compatibility and to avoid using a non-public # method. - hashed = SeparateBodyFileCache.encode(name) + hashed = FileCache.encode(name) parts = list(hashed[:5]) + [hashed] return os.path.join(self.directory, *parts) - def get(self, key: str) -> bytes | None: - # The cache entry is only valid if both metadata and body exist. - metadata_path = self._get_cache_path(key) - body_path = metadata_path + ".body" - if not (os.path.exists(metadata_path) and os.path.exists(body_path)): - return None + def get(self, key: str) -> Optional[bytes]: + path = self._get_cache_path(key) with suppressed_cache_errors(): - with open(metadata_path, "rb") as f: + with open(path, "rb") as f: return f.read() - def _write_to_file(self, path: str, writer_func: Callable[[BinaryIO], Any]) -> None: - """Common file writing logic with proper permissions and atomic replacement.""" + def set(self, key: str, value: bytes, expires: Optional[int] = None) -> None: + path = self._get_cache_path(key) with suppressed_cache_errors(): ensure_dir(os.path.dirname(path)) with adjacent_tmp_file(path) as f: - writer_func(f) - # Inherit the read/write permissions of the cache directory - # to enable multi-user cache use-cases. - copy_directory_permissions(self.directory, f) + f.write(value) replace(f.name, path) - def _write(self, path: str, data: bytes) -> None: - self._write_to_file(path, lambda f: f.write(data)) - - def _write_from_io(self, path: str, source_file: BinaryIO) -> None: - self._write_to_file(path, lambda f: shutil.copyfileobj(source_file, f)) - - def set( - self, key: str, value: bytes, expires: int | datetime | None = None - ) -> None: - path = self._get_cache_path(key) - self._write(path, value) - def delete(self, key: str) -> None: path = self._get_cache_path(key) with suppressed_cache_errors(): os.remove(path) - with suppressed_cache_errors(): - os.remove(path + ".body") - - def get_body(self, key: str) -> BinaryIO | None: - # The cache entry is only valid if both metadata and body exist. - metadata_path = self._get_cache_path(key) - body_path = metadata_path + ".body" - if not (os.path.exists(metadata_path) and os.path.exists(body_path)): - return None - with suppressed_cache_errors(): - return open(body_path, "rb") - - def set_body(self, key: str, body: bytes) -> None: - path = self._get_cache_path(key) + ".body" - self._write(path, body) - - def set_body_from_io(self, key: str, body_file: BinaryIO) -> None: - """Set the body of the cache entry from a file object.""" - path = self._get_cache_path(key) + ".body" - self._write_from_io(path, body_file) diff --git a/venv1/Lib/site-packages/pip/_internal/network/download.py b/venv1/Lib/site-packages/pip/_internal/network/download.py index 9881cc28..79b82a57 100644 --- a/venv1/Lib/site-packages/pip/_internal/network/download.py +++ b/venv1/Lib/site-packages/pip/_internal/network/download.py @@ -1,56 +1,39 @@ -"""Download files with progress indicators.""" - -from __future__ import annotations - +"""Download files with progress indicators. +""" import email.message import logging import mimetypes import os -from collections.abc import Iterable, Mapping -from dataclasses import dataclass -from http import HTTPStatus -from typing import BinaryIO - -from pip._vendor.requests import PreparedRequest -from pip._vendor.requests.models import Response -from pip._vendor.urllib3 import HTTPResponse as URLlib3Response -from pip._vendor.urllib3._collections import HTTPHeaderDict -from pip._vendor.urllib3.exceptions import ReadTimeoutError - -from pip._internal.cli.progress_bars import BarType, get_download_progress_renderer -from pip._internal.exceptions import IncompleteDownloadError, NetworkConnectionError +from typing import Iterable, Optional, Tuple + +from pip._vendor.requests.models import CONTENT_CHUNK_SIZE, Response + +from pip._internal.cli.progress_bars import get_download_progress_renderer +from pip._internal.exceptions import NetworkConnectionError from pip._internal.models.index import PyPI from pip._internal.models.link import Link -from pip._internal.network.cache import SafeFileCache, is_from_cache -from pip._internal.network.session import CacheControlAdapter, PipSession +from pip._internal.network.cache import is_from_cache +from pip._internal.network.session import PipSession from pip._internal.network.utils import HEADERS, raise_for_status, response_chunks from pip._internal.utils.misc import format_size, redact_auth_from_url, splitext logger = logging.getLogger(__name__) -def _get_http_response_size(resp: Response) -> int | None: +def _get_http_response_size(resp: Response) -> Optional[int]: try: return int(resp.headers["content-length"]) except (ValueError, KeyError, TypeError): return None -def _get_http_response_etag_or_last_modified(resp: Response) -> str | None: - """ - Return either the ETag or Last-Modified header (or None if neither exists). - The return value can be used in an If-Range header. - """ - return resp.headers.get("etag", resp.headers.get("last-modified")) - - -def _log_download( +def _prepare_download( resp: Response, link: Link, - progress_bar: BarType, - total_length: int | None, - range_start: int | None = 0, + progress_bar: str, ) -> Iterable[bytes]: + total_length = _get_http_response_size(resp) + if link.netloc == PyPI.file_storage_domain: url = link.show_url else: @@ -59,17 +42,10 @@ def _log_download( logged_url = redact_auth_from_url(url) if total_length: - if range_start: - logged_url = ( - f"{logged_url} ({format_size(range_start)}/{format_size(total_length)})" - ) - else: - logged_url = f"{logged_url} ({format_size(total_length)})" + logged_url = "{} ({})".format(logged_url, format_size(total_length)) if is_from_cache(resp): logger.info("Using cached %s", logged_url) - elif range_start: - logger.info("Resuming download %s", logged_url) else: logger.info("Downloading %s", logged_url) @@ -79,19 +55,17 @@ def _log_download( show_progress = False elif not total_length: show_progress = True - elif total_length > (512 * 1024): + elif total_length > (40 * 1000): show_progress = True else: show_progress = False - chunks = response_chunks(resp) + chunks = response_chunks(resp, CONTENT_CHUNK_SIZE) if not show_progress: return chunks - renderer = get_download_progress_renderer( - bar_type=progress_bar, size=total_length, initial_progress=range_start - ) + renderer = get_download_progress_renderer(bar_type=progress_bar, size=total_length) return renderer(chunks) @@ -126,7 +100,7 @@ def _get_http_response_filename(resp: Response, link: Link) -> str: content_disposition = resp.headers.get("content-disposition") if content_disposition: filename = parse_content_disposition(content_disposition, filename) - ext: str | None = splitext(filename)[1] + ext: Optional[str] = splitext(filename)[1] if not ext: ext = mimetypes.guess_extension(resp.headers.get("content-type", "")) if ext: @@ -138,205 +112,75 @@ def _get_http_response_filename(resp: Response, link: Link) -> str: return filename -@dataclass -class _FileDownload: - """Stores the state of a single link download.""" - - link: Link - output_file: BinaryIO - size: int | None - bytes_received: int = 0 - reattempts: int = 0 - - def is_incomplete(self) -> bool: - return bool(self.size is not None and self.bytes_received < self.size) - - def write_chunk(self, data: bytes) -> None: - self.bytes_received += len(data) - self.output_file.write(data) - - def reset_file(self) -> None: - """Delete any saved data and reset progress to zero.""" - self.output_file.seek(0) - self.output_file.truncate() - self.bytes_received = 0 +def _http_get_download(session: PipSession, link: Link) -> Response: + target_url = link.url.split("#", 1)[0] + resp = session.get(target_url, headers=HEADERS, stream=True) + raise_for_status(resp) + return resp class Downloader: def __init__( self, session: PipSession, - progress_bar: BarType, - resume_retries: int, + progress_bar: str, ) -> None: - assert ( - resume_retries >= 0 - ), "Number of max resume retries must be bigger or equal to zero" self._session = session self._progress_bar = progress_bar - self._resume_retries = resume_retries - def batch( - self, links: Iterable[Link], location: str - ) -> Iterable[tuple[Link, tuple[str, str]]]: - """Convenience method to download multiple links.""" - for link in links: - filepath, content_type = self(link, location) - yield link, (filepath, content_type) + def __call__(self, link: Link, location: str) -> Tuple[str, str]: + """Download the file given by link into location.""" + try: + resp = _http_get_download(self._session, link) + except NetworkConnectionError as e: + assert e.response is not None + logger.critical( + "HTTP error %s while getting %s", e.response.status_code, link + ) + raise - def __call__(self, link: Link, location: str) -> tuple[str, str]: - """Download a link and save it under location.""" - resp = self._http_get(link) - download_size = _get_http_response_size(resp) + filename = _get_http_response_filename(resp, link) + filepath = os.path.join(location, filename) - filepath = os.path.join(location, _get_http_response_filename(resp, link)) + chunks = _prepare_download(resp, link, self._progress_bar) with open(filepath, "wb") as content_file: - download = _FileDownload(link, content_file, download_size) - self._process_response(download, resp) - if download.is_incomplete(): - self._attempt_resumes_or_redownloads(download, resp) - + for chunk in chunks: + content_file.write(chunk) content_type = resp.headers.get("Content-Type", "") return filepath, content_type - def _process_response(self, download: _FileDownload, resp: Response) -> None: - """Download and save chunks from a response.""" - chunks = _log_download( - resp, - download.link, - self._progress_bar, - download.size, - range_start=download.bytes_received, - ) - try: - for chunk in chunks: - download.write_chunk(chunk) - except ReadTimeoutError as e: - # If the download size is not known, then give up downloading the file. - if download.size is None: - raise e - - logger.warning("Connection timed out while downloading.") - def _attempt_resumes_or_redownloads( - self, download: _FileDownload, first_resp: Response +class BatchDownloader: + def __init__( + self, + session: PipSession, + progress_bar: str, ) -> None: - """Attempt to resume/restart the download if connection was dropped.""" - - while download.reattempts < self._resume_retries and download.is_incomplete(): - assert download.size is not None - download.reattempts += 1 - logger.warning( - "Attempting to resume incomplete download (%s/%s, attempt %d)", - format_size(download.bytes_received), - format_size(download.size), - download.reattempts, - ) + self._session = session + self._progress_bar = progress_bar + def __call__( + self, links: Iterable[Link], location: str + ) -> Iterable[Tuple[Link, Tuple[str, str]]]: + """Download the files given by links into location.""" + for link in links: try: - resume_resp = self._http_get_resume(download, should_match=first_resp) - # Fallback: if the server responded with 200 (i.e., the file has - # since been modified or range requests are unsupported) or any - # other unexpected status, restart the download from the beginning. - must_restart = resume_resp.status_code != HTTPStatus.PARTIAL_CONTENT - if must_restart: - download.reset_file() - download.size = _get_http_response_size(resume_resp) - first_resp = resume_resp - - self._process_response(download, resume_resp) - except (ConnectionError, ReadTimeoutError, OSError): - continue - - # No more resume attempts. Raise an error if the download is still incomplete. - if download.is_incomplete(): - os.remove(download.output_file.name) - raise IncompleteDownloadError(download) - - # If we successfully completed the download via resume, manually cache it - # as a complete response to enable future caching - if download.reattempts > 0: - self._cache_resumed_download(download, first_resp) - - def _cache_resumed_download( - self, download: _FileDownload, original_response: Response - ) -> None: - """ - Manually cache a file that was successfully downloaded via resume retries. - - cachecontrol doesn't cache 206 (Partial Content) responses, since they - are not complete files. This method manually adds the final file to the - cache as though it was downloaded in a single request, so that future - requests can use the cache. - """ - url = download.link.url_without_fragment - adapter = self._session.get_adapter(url) - - # Check if the adapter is the CacheControlAdapter (i.e. caching is enabled) - if not isinstance(adapter, CacheControlAdapter): - logger.debug( - "Skipping resume download caching: no cache controller for %s", url - ) - return - - # Check SafeFileCache is being used - assert isinstance( - adapter.cache, SafeFileCache - ), "separate body cache not in use!" - - synthetic_request = PreparedRequest() - synthetic_request.prepare(method="GET", url=url, headers={}) - - synthetic_response_headers = HTTPHeaderDict() - for key, value in original_response.headers.items(): - if key.lower() not in ["content-range", "content-length"]: - synthetic_response_headers[key] = value - synthetic_response_headers["content-length"] = str(download.size) - - synthetic_response = URLlib3Response( - body="", - headers=synthetic_response_headers, - status=200, - preload_content=False, - ) - - # Save metadata and then stream the file contents to cache. - cache_url = adapter.controller.cache_url(url) - metadata_blob = adapter.controller.serializer.dumps( - synthetic_request, synthetic_response, b"" - ) - adapter.cache.set(cache_url, metadata_blob) - download.output_file.flush() - with open(download.output_file.name, "rb") as f: - adapter.cache.set_body_from_io(cache_url, f) - - logger.debug( - "Cached resumed download as complete response for future use: %s", url - ) - - def _http_get_resume( - self, download: _FileDownload, should_match: Response - ) -> Response: - """Issue a HTTP range request to resume the download.""" - # To better understand the download resumption logic, see the mdn web docs: - # https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Range_requests - headers = HEADERS.copy() - headers["Range"] = f"bytes={download.bytes_received}-" - # If possible, use a conditional range request to avoid corrupted - # downloads caused by the remote file changing in-between. - if identifier := _get_http_response_etag_or_last_modified(should_match): - headers["If-Range"] = identifier - return self._http_get(download.link, headers) - - def _http_get(self, link: Link, headers: Mapping[str, str] = HEADERS) -> Response: - target_url = link.url_without_fragment - try: - resp = self._session.get(target_url, headers=headers, stream=True) - raise_for_status(resp) - except NetworkConnectionError as e: - assert e.response is not None - logger.critical( - "HTTP error %s while getting %s", e.response.status_code, link - ) - raise - return resp + resp = _http_get_download(self._session, link) + except NetworkConnectionError as e: + assert e.response is not None + logger.critical( + "HTTP error %s while getting %s", + e.response.status_code, + link, + ) + raise + + filename = _get_http_response_filename(resp, link) + filepath = os.path.join(location, filename) + + chunks = _prepare_download(resp, link, self._progress_bar) + with open(filepath, "wb") as content_file: + for chunk in chunks: + content_file.write(chunk) + content_type = resp.headers.get("Content-Type", "") + yield link, (filepath, content_type) diff --git a/venv1/Lib/site-packages/pip/_internal/network/lazy_wheel.py b/venv1/Lib/site-packages/pip/_internal/network/lazy_wheel.py index 00398337..82ec50d5 100644 --- a/venv1/Lib/site-packages/pip/_internal/network/lazy_wheel.py +++ b/venv1/Lib/site-packages/pip/_internal/network/lazy_wheel.py @@ -1,17 +1,14 @@ """Lazy ZIP over HTTP""" -from __future__ import annotations - __all__ = ["HTTPRangeRequestUnsupported", "dist_from_wheel_url"] from bisect import bisect_left, bisect_right -from collections.abc import Generator from contextlib import contextmanager from tempfile import NamedTemporaryFile -from typing import Any +from typing import Any, Dict, Generator, List, Optional, Tuple from zipfile import BadZipFile, ZipFile -from pip._vendor.packaging.utils import NormalizedName +from pip._vendor.packaging.utils import canonicalize_name from pip._vendor.requests.models import CONTENT_CHUNK_SIZE, Response from pip._internal.metadata import BaseDistribution, MemoryWheel, get_wheel_distribution @@ -23,9 +20,7 @@ class HTTPRangeRequestUnsupported(Exception): pass -def dist_from_wheel_url( - name: NormalizedName, url: str, session: PipSession -) -> BaseDistribution: +def dist_from_wheel_url(name: str, url: str, session: PipSession) -> BaseDistribution: """Return a distribution object from the given wheel URL. This uses HTTP range requests to only fetch the portion of the wheel @@ -39,7 +34,7 @@ def dist_from_wheel_url( wheel = MemoryWheel(zf.name, zf) # type: ignore # After context manager exit, wheel.name # is an invalid file by intention. - return get_wheel_distribution(wheel, name) + return get_wheel_distribution(wheel, canonicalize_name(name)) class LazyZipOverHTTP: @@ -61,8 +56,8 @@ def __init__( self._length = int(head.headers["Content-Length"]) self._file = NamedTemporaryFile() self.truncate(self._length) - self._left: list[int] = [] - self._right: list[int] = [] + self._left: List[int] = [] + self._right: List[int] = [] if "bytes" not in head.headers.get("Accept-Ranges", "none"): raise HTTPRangeRequestUnsupported("range request is not supported") self._check_zip() @@ -122,7 +117,7 @@ def tell(self) -> int: """Return the current position.""" return self._file.tell() - def truncate(self, size: int | None = None) -> int: + def truncate(self, size: Optional[int] = None) -> int: """Resize the stream to the given size in bytes. If size is unspecified resize to the current position. @@ -136,7 +131,7 @@ def writable(self) -> bool: """Return False.""" return False - def __enter__(self) -> LazyZipOverHTTP: + def __enter__(self) -> "LazyZipOverHTTP": self._file.__enter__() return self @@ -164,14 +159,14 @@ def _check_zip(self) -> None: try: # For read-only ZIP files, ZipFile only needs # methods read, seek, seekable and tell. - ZipFile(self) + ZipFile(self) # type: ignore except BadZipFile: pass else: break def _stream_response( - self, start: int, end: int, base_headers: dict[str, str] = HEADERS + self, start: int, end: int, base_headers: Dict[str, str] = HEADERS ) -> Response: """Return HTTP response to a range request from start to end.""" headers = base_headers.copy() @@ -182,7 +177,7 @@ def _stream_response( def _merge( self, start: int, end: int, left: int, right: int - ) -> Generator[tuple[int, int], None, None]: + ) -> Generator[Tuple[int, int], None, None]: """Return a generator of intervals to be fetched. Args: diff --git a/venv1/Lib/site-packages/pip/_internal/network/session.py b/venv1/Lib/site-packages/pip/_internal/network/session.py index a1f9444e..6c40ade1 100644 --- a/venv1/Lib/site-packages/pip/_internal/network/session.py +++ b/venv1/Lib/site-packages/pip/_internal/network/session.py @@ -2,10 +2,7 @@ network request configuration and behavior. """ -from __future__ import annotations - import email.utils -import functools import io import ipaddress import json @@ -18,11 +15,16 @@ import sys import urllib.parse import warnings -from collections.abc import Generator, Mapping, Sequence from typing import ( TYPE_CHECKING, Any, + Dict, + Generator, + List, + Mapping, Optional, + Sequence, + Tuple, Union, ) @@ -51,19 +53,18 @@ from ssl import SSLContext from pip._vendor.urllib3.poolmanager import PoolManager - from pip._vendor.urllib3.proxymanager import ProxyManager logger = logging.getLogger(__name__) -SecureOrigin = tuple[str, str, Optional[Union[int, str]]] +SecureOrigin = Tuple[str, str, Optional[Union[int, str]]] # Ignore warning raised when using --trusted-host. warnings.filterwarnings("ignore", category=InsecureRequestWarning) -SECURE_ORIGINS: list[SecureOrigin] = [ +SECURE_ORIGINS: List[SecureOrigin] = [ # protocol, hostname, port # Taken from Chrome's list of secure origins (See: http://bit.ly/1qrySKC) ("https", "*", "*"), @@ -105,12 +106,11 @@ def looks_like_ci() -> bool: return any(name in os.environ for name in CI_ENVIRONMENT_VARIABLES) -@functools.lru_cache(maxsize=1) def user_agent() -> str: """ Return a string representing the user agent. """ - data: dict[str, Any] = { + data: Dict[str, Any] = { "installer": {"name": "pip", "version": __version__}, "python": platform.python_version(), "implementation": { @@ -138,7 +138,7 @@ def user_agent() -> str: from pip._vendor import distro linux_distribution = distro.name(), distro.version(), distro.codename() - distro_infos: dict[str, Any] = dict( + distro_infos: Dict[str, Any] = dict( filter( lambda x: x[1], zip(["name", "version", "id"], linux_distribution), @@ -212,10 +212,10 @@ def send( self, request: PreparedRequest, stream: bool = False, - timeout: float | tuple[float, float] | None = None, - verify: bool | str = True, - cert: str | tuple[str, str] | None = None, - proxies: Mapping[str, str] | None = None, + timeout: Optional[Union[float, Tuple[float, float]]] = None, + verify: Union[bool, str] = True, + cert: Optional[Union[str, Tuple[str, str]]] = None, + proxies: Optional[Mapping[str, str]] = None, ) -> Response: pathname = url_to_path(request.url) @@ -230,7 +230,7 @@ def send( # to return a better error message: resp.status_code = 404 resp.reason = type(exc).__name__ - resp.raw = io.BytesIO(f"{resp.reason}: {exc}".encode()) + resp.raw = io.BytesIO(f"{resp.reason}: {exc}".encode("utf8")) else: modified = email.utils.formatdate(stats.st_mtime, usegmt=True) content_type = mimetypes.guess_type(pathname)[0] or "text/plain" @@ -262,7 +262,7 @@ class _SSLContextAdapterMixin: def __init__( self, *, - ssl_context: SSLContext | None = None, + ssl_context: Optional["SSLContext"] = None, **kwargs: Any, ) -> None: self._ssl_context = ssl_context @@ -274,7 +274,7 @@ def init_poolmanager( maxsize: int, block: bool = DEFAULT_POOLBLOCK, **pool_kwargs: Any, - ) -> PoolManager: + ) -> "PoolManager": if self._ssl_context is not None: pool_kwargs.setdefault("ssl_context", self._ssl_context) return super().init_poolmanager( # type: ignore[misc] @@ -284,13 +284,6 @@ def init_poolmanager( **pool_kwargs, ) - def proxy_manager_for(self, proxy: str, **proxy_kwargs: Any) -> ProxyManager: - # Proxy manager replaces the pool manager, so inject our SSL - # context here too. https://github.com/pypa/pip/issues/13288 - if self._ssl_context is not None: - proxy_kwargs.setdefault("ssl_context", self._ssl_context) - return super().proxy_manager_for(proxy, **proxy_kwargs) # type: ignore[misc] - class HTTPAdapter(_SSLContextAdapterMixin, _BaseHTTPAdapter): pass @@ -305,8 +298,8 @@ def cert_verify( self, conn: ConnectionPool, url: str, - verify: bool | str, - cert: str | tuple[str, str] | None, + verify: Union[bool, str], + cert: Optional[Union[str, Tuple[str, str]]], ) -> None: super().cert_verify(conn=conn, url=url, verify=False, cert=cert) @@ -316,23 +309,23 @@ def cert_verify( self, conn: ConnectionPool, url: str, - verify: bool | str, - cert: str | tuple[str, str] | None, + verify: Union[bool, str], + cert: Optional[Union[str, Tuple[str, str]]], ) -> None: super().cert_verify(conn=conn, url=url, verify=False, cert=cert) class PipSession(requests.Session): - timeout: int | None = None + timeout: Optional[int] = None def __init__( self, *args: Any, retries: int = 0, - cache: str | None = None, + cache: Optional[str] = None, trusted_hosts: Sequence[str] = (), - index_urls: list[str] | None = None, - ssl_context: SSLContext | None = None, + index_urls: Optional[List[str]] = None, + ssl_context: Optional["SSLContext"] = None, **kwargs: Any, ) -> None: """ @@ -343,8 +336,7 @@ def __init__( # Namespace the attribute with "pip_" just in case to prevent # possible conflicts with the base class. - self.pip_trusted_origins: list[tuple[str, int | None]] = [] - self.pip_proxy = None + self.pip_trusted_origins: List[Tuple[str, Optional[int]]] = [] # Attach our User Agent to the request self.headers["User-Agent"] = user_agent() @@ -363,9 +355,8 @@ def __init__( # is typically considered a transient error so we'll go ahead and # retry it. # A 500 may indicate transient error in Amazon S3 - # A 502 may be a transient error from a CDN like CloudFlare or CloudFront # A 520 or 527 - may indicate transient error in CloudFlare - status_forcelist=[500, 502, 503, 520, 527], + status_forcelist=[500, 503, 520, 527], # Add a small amount of back off between failed requests in # order to prevent hammering the service. backoff_factor=0.25, @@ -406,7 +397,7 @@ def __init__( for host in trusted_hosts: self.add_trusted_host(host, suppress_logging=True) - def update_index_urls(self, new_index_urls: list[str]) -> None: + def update_index_urls(self, new_index_urls: List[str]) -> None: """ :param new_index_urls: New index urls to update the authentication handler with. @@ -414,7 +405,7 @@ def update_index_urls(self, new_index_urls: list[str]) -> None: self.auth.index_urls = new_index_urls def add_trusted_host( - self, host: str, source: str | None = None, suppress_logging: bool = False + self, host: str, source: Optional[str] = None, suppress_logging: bool = False ) -> None: """ :param host: It is okay to provide a host that has previously been @@ -428,17 +419,15 @@ def add_trusted_host( msg += f" (from {source})" logger.info(msg) - parsed_host, parsed_port = parse_netloc(host) - if parsed_host is None: - raise ValueError(f"Trusted host URL must include a host part: {host!r}") - if (parsed_host, parsed_port) not in self.pip_trusted_origins: - self.pip_trusted_origins.append((parsed_host, parsed_port)) + host_port = parse_netloc(host) + if host_port not in self.pip_trusted_origins: + self.pip_trusted_origins.append(host_port) self.mount( build_url_from_netloc(host, scheme="http") + "/", self._trusted_host_adapter ) self.mount(build_url_from_netloc(host) + "/", self._trusted_host_adapter) - if not parsed_port: + if not host_port[1]: self.mount( build_url_from_netloc(host, scheme="http") + ":", self._trusted_host_adapter, diff --git a/venv1/Lib/site-packages/pip/_internal/network/utils.py b/venv1/Lib/site-packages/pip/_internal/network/utils.py index 74d3111c..134848ae 100644 --- a/venv1/Lib/site-packages/pip/_internal/network/utils.py +++ b/venv1/Lib/site-packages/pip/_internal/network/utils.py @@ -1,6 +1,6 @@ -from collections.abc import Generator +from typing import Dict, Generator -from pip._vendor.requests.models import Response +from pip._vendor.requests.models import CONTENT_CHUNK_SIZE, Response from pip._internal.exceptions import NetworkConnectionError @@ -23,9 +23,7 @@ # you're not asking for a compressed file and will then decompress it # before sending because if that's the case I don't think it'll ever be # possible to make this work. -HEADERS: dict[str, str] = {"Accept-Encoding": "identity"} - -DOWNLOAD_CHUNK_SIZE = 256 * 1024 +HEADERS: Dict[str, str] = {"Accept-Encoding": "identity"} def raise_for_status(resp: Response) -> None: @@ -57,7 +55,7 @@ def raise_for_status(resp: Response) -> None: def response_chunks( - response: Response, chunk_size: int = DOWNLOAD_CHUNK_SIZE + response: Response, chunk_size: int = CONTENT_CHUNK_SIZE ) -> Generator[bytes, None, None]: """Given a requests Response, provide the data chunks.""" try: diff --git a/venv1/Lib/site-packages/pip/_internal/network/xmlrpc.py b/venv1/Lib/site-packages/pip/_internal/network/xmlrpc.py index f4bddb48..4a7d55d0 100644 --- a/venv1/Lib/site-packages/pip/_internal/network/xmlrpc.py +++ b/venv1/Lib/site-packages/pip/_internal/network/xmlrpc.py @@ -1,9 +1,10 @@ -"""xmlrpclib.Transport implementation""" +"""xmlrpclib.Transport implementation +""" import logging import urllib.parse import xmlrpc.client -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Tuple from pip._internal.exceptions import NetworkConnectionError from pip._internal.network.session import PipSession @@ -12,8 +13,6 @@ if TYPE_CHECKING: from xmlrpc.client import _HostType, _Marshallable - from _typeshed import SizedBuffer - logger = logging.getLogger(__name__) @@ -34,9 +33,9 @@ def request( self, host: "_HostType", handler: str, - request_body: "SizedBuffer", + request_body: bytes, verbose: bool = False, - ) -> tuple["_Marshallable", ...]: + ) -> Tuple["_Marshallable", ...]: assert isinstance(host, str) parts = (self._scheme, host, handler, None, None, None) url = urllib.parse.urlunparse(parts) diff --git a/venv1/Lib/site-packages/pip/_internal/operations/build/build_tracker.py b/venv1/Lib/site-packages/pip/_internal/operations/build/build_tracker.py index cbb4e4f0..6621549b 100644 --- a/venv1/Lib/site-packages/pip/_internal/operations/build/build_tracker.py +++ b/venv1/Lib/site-packages/pip/_internal/operations/build/build_tracker.py @@ -1,12 +1,11 @@ -from __future__ import annotations - import contextlib import hashlib import logging import os -from collections.abc import Generator from types import TracebackType +from typing import Dict, Generator, Optional, Set, Type, Union +from pip._internal.models.link import Link from pip._internal.req.req_install import InstallRequirement from pip._internal.utils.temp_dir import TempDirectory @@ -19,7 +18,7 @@ def update_env_context_manager(**changes: str) -> Generator[None, None, None]: # Save values from the target and change them. non_existent_marker = object() - saved_values: dict[str, object | str] = {} + saved_values: Dict[str, Union[object, str]] = {} for name, new_value in changes.items(): try: saved_values[name] = target[name] @@ -40,7 +39,7 @@ def update_env_context_manager(**changes: str) -> Generator[None, None, None]: @contextlib.contextmanager -def get_build_tracker() -> Generator[BuildTracker, None, None]: +def get_build_tracker() -> Generator["BuildTracker", None, None]: root = os.environ.get("PIP_BUILD_TRACKER") with contextlib.ExitStack() as ctx: if root is None: @@ -52,45 +51,34 @@ def get_build_tracker() -> Generator[BuildTracker, None, None]: yield tracker -class TrackerId(str): - """Uniquely identifying string provided to the build tracker.""" - - class BuildTracker: - """Ensure that an sdist cannot request itself as a setup requirement. - - When an sdist is prepared, it identifies its setup requirements in the - context of ``BuildTracker.track()``. If a requirement shows up recursively, this - raises an exception. - - This stops fork bombs embedded in malicious packages.""" - def __init__(self, root: str) -> None: self._root = root - self._entries: dict[TrackerId, InstallRequirement] = {} + self._entries: Set[InstallRequirement] = set() logger.debug("Created build tracker: %s", self._root) - def __enter__(self) -> BuildTracker: + def __enter__(self) -> "BuildTracker": logger.debug("Entered build tracker: %s", self._root) return self def __exit__( self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], ) -> None: self.cleanup() - def _entry_path(self, key: TrackerId) -> str: - hashed = hashlib.sha224(key.encode()).hexdigest() + def _entry_path(self, link: Link) -> str: + hashed = hashlib.sha224(link.url_without_fragment.encode()).hexdigest() return os.path.join(self._root, hashed) - def add(self, req: InstallRequirement, key: TrackerId) -> None: + def add(self, req: InstallRequirement) -> None: """Add an InstallRequirement to build tracking.""" + assert req.link # Get the file to write information about this requirement. - entry_path = self._entry_path(key) + entry_path = self._entry_path(req.link) # Try reading from the file. If it exists and can be read from, a build # is already in progress, so a LookupError is raised. @@ -100,41 +88,37 @@ def add(self, req: InstallRequirement, key: TrackerId) -> None: except FileNotFoundError: pass else: - message = f"{req.link} is already being built: {contents}" + message = "{} is already being built: {}".format(req.link, contents) raise LookupError(message) # If we're here, req should really not be building already. - assert key not in self._entries + assert req not in self._entries # Start tracking this requirement. with open(entry_path, "w", encoding="utf-8") as fp: fp.write(str(req)) - self._entries[key] = req + self._entries.add(req) logger.debug("Added %s to build tracker %r", req, self._root) - def remove(self, req: InstallRequirement, key: TrackerId) -> None: + def remove(self, req: InstallRequirement) -> None: """Remove an InstallRequirement from build tracking.""" - # Delete the created file and the corresponding entry. - os.unlink(self._entry_path(key)) - del self._entries[key] + assert req.link + # Delete the created file and the corresponding entries. + os.unlink(self._entry_path(req.link)) + self._entries.remove(req) logger.debug("Removed %s from build tracker %r", req, self._root) def cleanup(self) -> None: - for key, req in list(self._entries.items()): - self.remove(req, key) + for req in set(self._entries): + self.remove(req) logger.debug("Removed build tracker: %r", self._root) @contextlib.contextmanager - def track(self, req: InstallRequirement, key: str) -> Generator[None, None, None]: - """Ensure that `key` cannot install itself as a setup requirement. - - :raises LookupError: If `key` was already provided in a parent invocation of - the context introduced by this method.""" - tracker_id = TrackerId(key) - self.add(req, tracker_id) + def track(self, req: InstallRequirement) -> Generator[None, None, None]: + self.add(req) yield - self.remove(req, tracker_id) + self.remove(req) diff --git a/venv1/Lib/site-packages/pip/_internal/operations/build/metadata.py b/venv1/Lib/site-packages/pip/_internal/operations/build/metadata.py index a546809e..c66ac354 100644 --- a/venv1/Lib/site-packages/pip/_internal/operations/build/metadata.py +++ b/venv1/Lib/site-packages/pip/_internal/operations/build/metadata.py @@ -1,4 +1,5 @@ -"""Metadata generation logic for source distributions.""" +"""Metadata generation logic for source distributions. +""" import os diff --git a/venv1/Lib/site-packages/pip/_internal/operations/build/metadata_editable.py b/venv1/Lib/site-packages/pip/_internal/operations/build/metadata_editable.py index 27ecd7d3..27c69f0d 100644 --- a/venv1/Lib/site-packages/pip/_internal/operations/build/metadata_editable.py +++ b/venv1/Lib/site-packages/pip/_internal/operations/build/metadata_editable.py @@ -1,4 +1,5 @@ -"""Metadata generation logic for source distributions.""" +"""Metadata generation logic for source distributions. +""" import os @@ -37,5 +38,4 @@ def generate_editable_metadata( except InstallationSubprocessError as error: raise MetadataGenerationFailed(package_details=details) from error - assert distinfo_dir is not None return os.path.join(metadata_dir, distinfo_dir) diff --git a/venv1/Lib/site-packages/pip/_internal/operations/build/wheel.py b/venv1/Lib/site-packages/pip/_internal/operations/build/wheel.py index 8595e45c..064811ad 100644 --- a/venv1/Lib/site-packages/pip/_internal/operations/build/wheel.py +++ b/venv1/Lib/site-packages/pip/_internal/operations/build/wheel.py @@ -1,7 +1,6 @@ -from __future__ import annotations - import logging import os +from typing import Optional from pip._vendor.pyproject_hooks import BuildBackendHookCaller @@ -14,25 +13,25 @@ def build_wheel_pep517( name: str, backend: BuildBackendHookCaller, metadata_directory: str, - wheel_directory: str, -) -> str | None: + tempd: str, +) -> Optional[str]: """Build one InstallRequirement using the PEP 517 build process. Returns path to wheel if successfully built. Otherwise, returns None. """ assert metadata_directory is not None try: - logger.debug("Destination directory: %s", wheel_directory) + logger.debug("Destination directory: %s", tempd) runner = runner_with_spinner_message( f"Building wheel for {name} (pyproject.toml)" ) with backend.subprocess_runner(runner): wheel_name = backend.build_wheel( - wheel_directory=wheel_directory, + tempd, metadata_directory=metadata_directory, ) except Exception: logger.error("Failed building wheel for %s", name) return None - return os.path.join(wheel_directory, wheel_name) + return os.path.join(tempd, wheel_name) diff --git a/venv1/Lib/site-packages/pip/_internal/operations/build/wheel_editable.py b/venv1/Lib/site-packages/pip/_internal/operations/build/wheel_editable.py index f00d9b27..719d69dd 100644 --- a/venv1/Lib/site-packages/pip/_internal/operations/build/wheel_editable.py +++ b/venv1/Lib/site-packages/pip/_internal/operations/build/wheel_editable.py @@ -1,7 +1,6 @@ -from __future__ import annotations - import logging import os +from typing import Optional from pip._vendor.pyproject_hooks import BuildBackendHookCaller, HookMissing @@ -14,15 +13,15 @@ def build_wheel_editable( name: str, backend: BuildBackendHookCaller, metadata_directory: str, - wheel_directory: str, -) -> str | None: + tempd: str, +) -> Optional[str]: """Build one InstallRequirement using the PEP 660 build process. Returns path to wheel if successfully built. Otherwise, returns None. """ assert metadata_directory is not None try: - logger.debug("Destination directory: %s", wheel_directory) + logger.debug("Destination directory: %s", tempd) runner = runner_with_spinner_message( f"Building editable for {name} (pyproject.toml)" @@ -30,7 +29,7 @@ def build_wheel_editable( with backend.subprocess_runner(runner): try: wheel_name = backend.build_editable( - wheel_directory=wheel_directory, + tempd, metadata_directory=metadata_directory, ) except HookMissing as e: @@ -44,4 +43,4 @@ def build_wheel_editable( except Exception: logger.error("Failed building editable for %s", name) return None - return os.path.join(wheel_directory, wheel_name) + return os.path.join(tempd, wheel_name) diff --git a/venv1/Lib/site-packages/pip/_internal/operations/check.py b/venv1/Lib/site-packages/pip/_internal/operations/check.py index 2d71fa5f..e3bce69b 100644 --- a/venv1/Lib/site-packages/pip/_internal/operations/check.py +++ b/venv1/Lib/site-packages/pip/_internal/operations/check.py @@ -1,47 +1,37 @@ -"""Validation of dependencies of packages""" - -from __future__ import annotations +"""Validation of dependencies of packages +""" import logging -from collections.abc import Generator, Iterable -from contextlib import suppress -from email.parser import Parser -from functools import reduce -from typing import ( - Callable, - NamedTuple, -) +from typing import Callable, Dict, List, NamedTuple, Optional, Set, Tuple from pip._vendor.packaging.requirements import Requirement -from pip._vendor.packaging.tags import Tag, parse_tag from pip._vendor.packaging.utils import NormalizedName, canonicalize_name -from pip._vendor.packaging.version import Version from pip._internal.distributions import make_distribution_for_install_requirement from pip._internal.metadata import get_default_environment -from pip._internal.metadata.base import BaseDistribution +from pip._internal.metadata.base import DistributionVersion from pip._internal.req.req_install import InstallRequirement logger = logging.getLogger(__name__) class PackageDetails(NamedTuple): - version: Version - dependencies: list[Requirement] + version: DistributionVersion + dependencies: List[Requirement] # Shorthands -PackageSet = dict[NormalizedName, PackageDetails] -Missing = tuple[NormalizedName, Requirement] -Conflicting = tuple[NormalizedName, Version, Requirement] +PackageSet = Dict[NormalizedName, PackageDetails] +Missing = Tuple[NormalizedName, Requirement] +Conflicting = Tuple[NormalizedName, DistributionVersion, Requirement] -MissingDict = dict[NormalizedName, list[Missing]] -ConflictingDict = dict[NormalizedName, list[Conflicting]] -CheckResult = tuple[MissingDict, ConflictingDict] -ConflictDetails = tuple[PackageSet, CheckResult] +MissingDict = Dict[NormalizedName, List[Missing]] +ConflictingDict = Dict[NormalizedName, List[Conflicting]] +CheckResult = Tuple[MissingDict, ConflictingDict] +ConflictDetails = Tuple[PackageSet, CheckResult] -def create_package_set_from_installed() -> tuple[PackageSet, bool]: +def create_package_set_from_installed() -> Tuple[PackageSet, bool]: """Converts a list of distributions into a PackageSet.""" package_set = {} problems = False @@ -53,13 +43,13 @@ def create_package_set_from_installed() -> tuple[PackageSet, bool]: package_set[name] = PackageDetails(dist.version, dependencies) except (OSError, ValueError) as e: # Don't crash on unreadable or broken metadata. - logger.warning("Error parsing dependencies of %s: %s", name, e) + logger.warning("Error parsing requirements for %s: %s", name, e) problems = True return package_set, problems def check_package_set( - package_set: PackageSet, should_ignore: Callable[[str], bool] | None = None + package_set: PackageSet, should_ignore: Optional[Callable[[str], bool]] = None ) -> CheckResult: """Check if a package set is consistent @@ -72,8 +62,8 @@ def check_package_set( for package_name, package_detail in package_set.items(): # Info about dependencies of package_name - missing_deps: set[Missing] = set() - conflicting_deps: set[Conflicting] = set() + missing_deps: Set[Missing] = set() + conflicting_deps: Set[Conflicting] = set() if should_ignore and should_ignore(package_name): continue @@ -103,7 +93,7 @@ def check_package_set( return missing, conflicting -def check_install_conflicts(to_install: list[InstallRequirement]) -> ConflictDetails: +def check_install_conflicts(to_install: List[InstallRequirement]) -> ConflictDetails: """For checking if the dependency graph would be consistent after \ installing given requirements """ @@ -123,25 +113,9 @@ def check_install_conflicts(to_install: list[InstallRequirement]) -> ConflictDet ) -def check_unsupported( - packages: Iterable[BaseDistribution], - supported_tags: Iterable[Tag], -) -> Generator[BaseDistribution, None, None]: - for p in packages: - with suppress(FileNotFoundError): - wheel_file = p.read_text("WHEEL") - wheel_tags: frozenset[Tag] = reduce( - frozenset.union, - map(parse_tag, Parser().parsestr(wheel_file).get_all("Tag", [])), - frozenset(), - ) - if wheel_tags.isdisjoint(supported_tags): - yield p - - def _simulate_installation_of( - to_install: list[InstallRequirement], package_set: PackageSet -) -> set[NormalizedName]: + to_install: List[InstallRequirement], package_set: PackageSet +) -> Set[NormalizedName]: """Computes the version of packages after installing to_install.""" # Keep track of packages that were installed installed = set() @@ -159,8 +133,8 @@ def _simulate_installation_of( def _create_whitelist( - would_be_installed: set[NormalizedName], package_set: PackageSet -) -> set[NormalizedName]: + would_be_installed: Set[NormalizedName], package_set: PackageSet +) -> Set[NormalizedName]: packages_affected = set(would_be_installed) for package_name in package_set: diff --git a/venv1/Lib/site-packages/pip/_internal/operations/freeze.py b/venv1/Lib/site-packages/pip/_internal/operations/freeze.py index 486a8332..35445684 100644 --- a/venv1/Lib/site-packages/pip/_internal/operations/freeze.py +++ b/venv1/Lib/site-packages/pip/_internal/operations/freeze.py @@ -1,14 +1,10 @@ -from __future__ import annotations - import collections import logging import os -from collections.abc import Container, Generator, Iterable -from dataclasses import dataclass, field -from typing import NamedTuple +from typing import Container, Dict, Generator, Iterable, List, NamedTuple, Optional, Set -from pip._vendor.packaging.utils import NormalizedName, canonicalize_name -from pip._vendor.packaging.version import InvalidVersion +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.packaging.version import Version from pip._internal.exceptions import BadCommand, InstallationError from pip._internal.metadata import BaseDistribution, get_environment @@ -24,19 +20,19 @@ class _EditableInfo(NamedTuple): requirement: str - comments: list[str] + comments: List[str] def freeze( - requirement: list[str] | None = None, + requirement: Optional[List[str]] = None, local_only: bool = False, user_only: bool = False, - paths: list[str] | None = None, + paths: Optional[List[str]] = None, isolated: bool = False, exclude_editable: bool = False, skip: Container[str] = (), ) -> Generator[str, None, None]: - installations: dict[str, FrozenRequirement] = {} + installations: Dict[str, FrozenRequirement] = {} dists = get_environment(paths).iter_installed_distributions( local_only=local_only, @@ -54,10 +50,10 @@ def freeze( # should only be emitted once, even if the same option is in multiple # requirements files, so we need to keep track of what has been emitted # so that we don't emit it again if it's seen again - emitted_options: set[str] = set() + emitted_options: Set[str] = set() # keep track of which files a requirement is in so that we can # give an accurate warning if a requirement appears multiple times. - req_files: dict[str, list[str]] = collections.defaultdict(list) + req_files: Dict[str, List[str]] = collections.defaultdict(list) for req_file_path in requirement: with open(req_file_path) as req_file: for line in req_file: @@ -86,7 +82,7 @@ def freeze( yield line continue - if line.startswith(("-e", "--editable")): + if line.startswith("-e") or line.startswith("--editable"): if line.startswith("-e"): line = line[2:].strip() else: @@ -149,13 +145,10 @@ def freeze( def _format_as_name_version(dist: BaseDistribution) -> str: - try: - dist_version = dist.version - except InvalidVersion: - # legacy version - return f"{dist.raw_name}==={dist.raw_version}" - else: + dist_version = dist.version + if isinstance(dist_version, Version): return f"{dist.raw_name}=={dist_version}" + return f"{dist.raw_name}==={dist_version}" def _get_editable_info(dist: BaseDistribution) -> _EditableInfo: @@ -224,19 +217,22 @@ def _get_editable_info(dist: BaseDistribution) -> _EditableInfo: ) -@dataclass(frozen=True) class FrozenRequirement: - name: str - req: str - editable: bool - comments: Iterable[str] = field(default_factory=tuple) - - @property - def canonical_name(self) -> NormalizedName: - return canonicalize_name(self.name) + def __init__( + self, + name: str, + req: str, + editable: bool, + comments: Iterable[str] = (), + ) -> None: + self.name = name + self.canonical_name = canonicalize_name(name) + self.req = req + self.editable = editable + self.comments = comments @classmethod - def from_dist(cls, dist: BaseDistribution) -> FrozenRequirement: + def from_dist(cls, dist: BaseDistribution) -> "FrozenRequirement": editable = dist.editable if editable: req, comments = _get_editable_info(dist) diff --git a/venv1/Lib/site-packages/pip/_internal/operations/install/__init__.py b/venv1/Lib/site-packages/pip/_internal/operations/install/__init__.py index 2645a4ac..24d6a5dd 100644 --- a/venv1/Lib/site-packages/pip/_internal/operations/install/__init__.py +++ b/venv1/Lib/site-packages/pip/_internal/operations/install/__init__.py @@ -1 +1,2 @@ -"""For modules related to installing packages.""" +"""For modules related to installing packages. +""" diff --git a/venv1/Lib/site-packages/pip/_internal/operations/install/wheel.py b/venv1/Lib/site-packages/pip/_internal/operations/install/wheel.py index 2724f150..a8cd1330 100644 --- a/venv1/Lib/site-packages/pip/_internal/operations/install/wheel.py +++ b/venv1/Lib/site-packages/pip/_internal/operations/install/wheel.py @@ -1,6 +1,5 @@ -"""Support for installing and building the "wheel" binary package format.""" - -from __future__ import annotations +"""Support for installing and building the "wheel" binary package format. +""" import collections import compileall @@ -12,19 +11,26 @@ import re import shutil import sys -import textwrap import warnings from base64 import urlsafe_b64encode -from collections.abc import Generator, Iterable, Iterator, Sequence from email.message import Message from itertools import chain, filterfalse, starmap from typing import ( IO, + TYPE_CHECKING, Any, BinaryIO, Callable, + Dict, + Generator, + Iterable, + Iterator, + List, NewType, - Protocol, + Optional, + Sequence, + Set, + Tuple, Union, cast, ) @@ -44,7 +50,7 @@ from pip._internal.models.direct_url import DIRECT_URL_METADATA_NAME, DirectUrl from pip._internal.models.scheme import SCHEME_KEYS, Scheme from pip._internal.utils.filesystem import adjacent_tmp_file, replace -from pip._internal.utils.misc import StreamWrapper, ensure_dir, hash_file, partition +from pip._internal.utils.misc import captured_stdout, ensure_dir, hash_file, partition from pip._internal.utils.unpacking import ( current_umask, is_within_directory, @@ -53,30 +59,32 @@ ) from pip._internal.utils.wheel import parse_wheel +if TYPE_CHECKING: + from typing import Protocol -class File(Protocol): - src_record_path: RecordPath - dest_path: str - changed: bool + class File(Protocol): + src_record_path: "RecordPath" + dest_path: str + changed: bool - def save(self) -> None: - pass + def save(self) -> None: + pass logger = logging.getLogger(__name__) RecordPath = NewType("RecordPath", str) -InstalledCSVRow = tuple[RecordPath, str, Union[int, str]] +InstalledCSVRow = Tuple[RecordPath, str, Union[int, str]] -def rehash(path: str, blocksize: int = 1 << 20) -> tuple[str, str]: +def rehash(path: str, blocksize: int = 1 << 20) -> Tuple[str, str]: """Return (encoded_digest, length) for path using hashlib.sha256()""" h, length = hash_file(path, blocksize) digest = "sha256=" + urlsafe_b64encode(h.digest()).decode("latin1").rstrip("=") return (digest, str(length)) -def csv_io_kwargs(mode: str) -> dict[str, Any]: +def csv_io_kwargs(mode: str) -> Dict[str, Any]: """Return keyword arguments to properly open a CSV file in the given mode. """ @@ -107,7 +115,7 @@ def wheel_root_is_purelib(metadata: Message) -> bool: return metadata.get("Root-Is-Purelib", "").lower() == "true" -def get_entrypoints(dist: BaseDistribution) -> tuple[dict[str, str], dict[str, str]]: +def get_entrypoints(dist: BaseDistribution) -> Tuple[Dict[str, str], Dict[str, str]]: console_scripts = {} gui_scripts = {} for entry_point in dist.iter_entry_points(): @@ -118,7 +126,7 @@ def get_entrypoints(dist: BaseDistribution) -> tuple[dict[str, str], dict[str, s return console_scripts, gui_scripts -def message_about_scripts_not_on_PATH(scripts: Sequence[str]) -> str | None: +def message_about_scripts_not_on_PATH(scripts: Sequence[str]) -> Optional[str]: """Determine if any scripts are not on PATH and format a warning. Returns a warning message if one or more scripts are not on PATH, otherwise None. @@ -127,7 +135,7 @@ def message_about_scripts_not_on_PATH(scripts: Sequence[str]) -> str | None: return None # Group scripts by the path they were installed in - grouped_by_dir: dict[str, set[str]] = collections.defaultdict(set) + grouped_by_dir: Dict[str, Set[str]] = collections.defaultdict(set) for destfile in scripts: parent_dir = os.path.dirname(destfile) script_name = os.path.basename(destfile) @@ -143,7 +151,7 @@ def message_about_scripts_not_on_PATH(scripts: Sequence[str]) -> str | None: not_warn_dirs.append( os.path.normcase(os.path.normpath(os.path.dirname(sys.executable))) ) - warn_for: dict[str, set[str]] = { + warn_for: Dict[str, Set[str]] = { parent_dir: scripts for parent_dir, scripts in grouped_by_dir.items() if os.path.normcase(os.path.normpath(parent_dir)) not in not_warn_dirs @@ -154,16 +162,18 @@ def message_about_scripts_not_on_PATH(scripts: Sequence[str]) -> str | None: # Format a message msg_lines = [] for parent_dir, dir_scripts in warn_for.items(): - sorted_scripts: list[str] = sorted(dir_scripts) + sorted_scripts: List[str] = sorted(dir_scripts) if len(sorted_scripts) == 1: - start_text = f"script {sorted_scripts[0]} is" + start_text = "script {} is".format(sorted_scripts[0]) else: start_text = "scripts {} are".format( ", ".join(sorted_scripts[:-1]) + " and " + sorted_scripts[-1] ) msg_lines.append( - f"The {start_text} installed in '{parent_dir}' which is not on PATH." + "The {} installed in '{}' which is not on PATH.".format( + start_text, parent_dir + ) ) last_line_fmt = ( @@ -192,7 +202,7 @@ def message_about_scripts_not_on_PATH(scripts: Sequence[str]) -> str | None: def _normalized_outrows( outrows: Iterable[InstalledCSVRow], -) -> list[tuple[str, str, str]]: +) -> List[Tuple[str, str, str]]: """Normalize the given rows of a RECORD file. Items in each row are converted into str. Rows are then sorted to make @@ -231,17 +241,17 @@ def _fs_to_record_path(path: str, lib_dir: str) -> RecordPath: def get_csv_rows_for_installed( - old_csv_rows: list[list[str]], - installed: dict[RecordPath, RecordPath], - changed: set[RecordPath], - generated: list[str], + old_csv_rows: List[List[str]], + installed: Dict[RecordPath, RecordPath], + changed: Set[RecordPath], + generated: List[str], lib_dir: str, -) -> list[InstalledCSVRow]: +) -> List[InstalledCSVRow]: """ :param installed: A map from archive RECORD path to installation RECORD path. """ - installed_rows: list[InstalledCSVRow] = [] + installed_rows: List[InstalledCSVRow] = [] for row in old_csv_rows: if len(row) > 3: logger.warning("RECORD line has more than three elements: %s", row) @@ -257,12 +267,12 @@ def get_csv_rows_for_installed( path = _fs_to_record_path(f, lib_dir) digest, length = rehash(f) installed_rows.append((path, digest, length)) - return installed_rows + [ - (installed_record_path, "", "") for installed_record_path in installed.values() - ] + for installed_record_path in installed.values(): + installed_rows.append((installed_record_path, "", "")) + return installed_rows -def get_console_script_specs(console: dict[str, str]) -> list[str]: +def get_console_script_specs(console: Dict[str, str]) -> List[str]: """ Given the mapping from entrypoint name to callable, return the relevant console script specs. @@ -280,15 +290,17 @@ def get_console_script_specs(console: dict[str, str]) -> list[str]: # the wheel metadata at build time, and so if the wheel is installed with # a *different* version of Python the entry points will be wrong. The # correct fix for this is to enhance the metadata to be able to describe - # such versioned entry points. - # Currently, projects using versioned entry points will either have + # such versioned entry points, but that won't happen till Metadata 2.0 is + # available. + # In the meantime, projects using versioned entry points will either have # incorrect versioned entry points, or they will not be able to distribute # "universal" wheels (i.e., they will need a wheel per Python version). # # Because setuptools and pip are bundled with _ensurepip and virtualenv, - # we need to use universal wheels. As a workaround, we + # we need to use universal wheels. So, as a stopgap until Metadata 2.0, we # override the versioned entry points in the wheel and generate the - # correct ones. + # correct ones. This code is purely a short-term measure until Metadata 2.0 + # is available. # # To add the level of hack in this section of code, in order to support # ensurepip this code will look for an ``ENSUREPIP_OPTIONS`` environment @@ -309,7 +321,9 @@ def get_console_script_specs(console: dict[str, str]) -> list[str]: scripts_to_generate.append("pip = " + pip_script) if os.environ.get("ENSUREPIP_OPTIONS", "") != "altinstall": - scripts_to_generate.append(f"pip{sys.version_info[0]} = {pip_script}") + scripts_to_generate.append( + "pip{} = {}".format(sys.version_info[0], pip_script) + ) scripts_to_generate.append(f"pip{get_major_minor_version()} = {pip_script}") # Delete any other versioned pip entry points @@ -322,7 +336,9 @@ def get_console_script_specs(console: dict[str, str]) -> list[str]: scripts_to_generate.append("easy_install = " + easy_install_script) scripts_to_generate.append( - f"easy_install-{get_major_minor_version()} = {easy_install_script}" + "easy_install-{} = {}".format( + get_major_minor_version(), easy_install_script + ) ) # Delete any other versioned easy_install entry points easy_install_ep = [ @@ -350,6 +366,12 @@ def _getinfo(self) -> ZipInfo: return self._zip_file.getinfo(self.src_record_path) def save(self) -> None: + # directory creation is lazy and after file filtering + # to ensure we don't install empty dirs; empty dirs can't be + # uninstalled. + parent_dir = os.path.dirname(self.dest_path) + ensure_dir(parent_dir) + # When we open the output file below, any existing file is truncated # before we start writing the new contents. This is fine in most # cases, but can cause a segfault if pip has loaded a shared @@ -363,20 +385,16 @@ def save(self) -> None: zipinfo = self._getinfo() - # optimization: the file is created by open(), - # skip the decompression when there is 0 bytes to decompress. - with open(self.dest_path, "wb") as dest: - if zipinfo.file_size > 0: - with self._zip_file.open(zipinfo) as f: - blocksize = min(zipinfo.file_size, 1024 * 1024) - shutil.copyfileobj(f, dest, blocksize) + with self._zip_file.open(zipinfo) as f: + with open(self.dest_path, "wb") as dest: + shutil.copyfileobj(f, dest) if zip_item_is_executable(zipinfo): set_extracted_file_to_default_mode_plus_executable(self.dest_path) class ScriptFile: - def __init__(self, file: File) -> None: + def __init__(self, file: "File") -> None: self._file = file self.src_record_path = self._file.src_record_path self.dest_path = self._file.dest_path @@ -390,10 +408,10 @@ def save(self) -> None: class MissingCallableSuffix(InstallationError): def __init__(self, entry_point: str) -> None: super().__init__( - f"Invalid script entry point: {entry_point} - A callable " - "suffix is required. See https://packaging.python.org/" + "Invalid script entry point: {} - A callable " + "suffix is required. Cf https://packaging.python.org/" "specifications/entry-points/#use-for-scripts for more " - "information." + "information.".format(entry_point) ) @@ -404,34 +422,21 @@ def _raise_for_invalid_entrypoint(specification: str) -> None: class PipScriptMaker(ScriptMaker): - # Override distlib's default script template with one that - # doesn't import `re` module, allowing scripts to load faster. - script_template = textwrap.dedent( - """\ - import sys - from %(module)s import %(import_name)s - if __name__ == '__main__': - if sys.argv[0].endswith('.exe'): - sys.argv[0] = sys.argv[0][:-4] - sys.exit(%(func)s()) -""" - ) - def make( - self, specification: str, options: dict[str, Any] | None = None - ) -> list[str]: + self, specification: str, options: Optional[Dict[str, Any]] = None + ) -> List[str]: _raise_for_invalid_entrypoint(specification) return super().make(specification, options) -def _install_wheel( # noqa: C901, PLR0915 function is too long +def _install_wheel( name: str, wheel_zip: ZipFile, wheel_path: str, scheme: Scheme, pycompile: bool = True, warn_script_location: bool = True, - direct_url: DirectUrl | None = None, + direct_url: Optional[DirectUrl] = None, requested: bool = False, ) -> None: """Install a wheel. @@ -460,9 +465,9 @@ def _install_wheel( # noqa: C901, PLR0915 function is too long # installed = files copied from the wheel to the destination # changed = files changed while installing (scripts #! line typically) # generated = files newly generated during the install (script wrappers) - installed: dict[RecordPath, RecordPath] = {} - changed: set[RecordPath] = set() - generated: list[str] = [] + installed: Dict[RecordPath, RecordPath] = {} + changed: Set[RecordPath] = set() + generated: List[str] = [] def record_installed( srcfile: RecordPath, destfile: str, modified: bool = False @@ -488,8 +493,8 @@ def assert_no_path_traversal(dest_dir_path: str, target_path: str) -> None: def root_scheme_file_maker( zip_file: ZipFile, dest: str - ) -> Callable[[RecordPath], File]: - def make_root_scheme_file(record_path: RecordPath) -> File: + ) -> Callable[[RecordPath], "File"]: + def make_root_scheme_file(record_path: RecordPath) -> "File": normed_path = os.path.normpath(record_path) dest_path = os.path.join(dest, normed_path) assert_no_path_traversal(dest, dest_path) @@ -499,18 +504,18 @@ def make_root_scheme_file(record_path: RecordPath) -> File: def data_scheme_file_maker( zip_file: ZipFile, scheme: Scheme - ) -> Callable[[RecordPath], File]: + ) -> Callable[[RecordPath], "File"]: scheme_paths = {key: getattr(scheme, key) for key in SCHEME_KEYS} - def make_data_scheme_file(record_path: RecordPath) -> File: + def make_data_scheme_file(record_path: RecordPath) -> "File": normed_path = os.path.normpath(record_path) try: _, scheme_key, dest_subpath = normed_path.split(os.path.sep, 2) except ValueError: message = ( - f"Unexpected file in {wheel_path}: {record_path!r}. .data directory" - " contents should be named like: '/'." - ) + "Unexpected file in {}: {!r}. .data directory contents" + " should be named like: '/'." + ).format(wheel_path, record_path) raise InstallationError(message) try: @@ -518,11 +523,10 @@ def make_data_scheme_file(record_path: RecordPath) -> File: except KeyError: valid_scheme_keys = ", ".join(sorted(scheme_paths)) message = ( - f"Unknown scheme key used in {wheel_path}: {scheme_key} " - f"(for file {record_path!r}). .data directory contents " - f"should be in subdirectories named with a valid scheme " - f"key ({valid_scheme_keys})" - ) + "Unknown scheme key used in {}: {} (for file {!r}). .data" + " directory contents should be in subdirectories named" + " with a valid scheme key ({})" + ).format(wheel_path, scheme_key, record_path, valid_scheme_keys) raise InstallationError(message) dest_path = os.path.join(scheme_path, dest_subpath) @@ -534,7 +538,7 @@ def make_data_scheme_file(record_path: RecordPath) -> File: def is_data_scheme_path(path: RecordPath) -> bool: return path.split("/", 1)[0].endswith(".data") - paths = cast(list[RecordPath], wheel_zip.namelist()) + paths = cast(List[RecordPath], wheel_zip.namelist()) file_paths = filterfalse(is_dir_path, paths) root_scheme_paths, data_scheme_paths = partition(is_data_scheme_path, file_paths) @@ -560,7 +564,7 @@ def is_script_scheme_path(path: RecordPath) -> bool: ) console, gui = get_entrypoints(distribution) - def is_entrypoint_wrapper(file: File) -> bool: + def is_entrypoint_wrapper(file: "File") -> bool: # EP, EP.exe and EP-script.py are scripts generated for # entry point EP by setuptools path = file.dest_path @@ -583,15 +587,7 @@ def is_entrypoint_wrapper(file: File) -> bool: script_scheme_files = map(ScriptFile, script_scheme_files) files = chain(files, script_scheme_files) - existing_parents = set() for file in files: - # directory creation is lazy and after file filtering - # to ensure we don't install empty dirs; empty dirs can't be - # uninstalled. - parent_dir = os.path.dirname(file.dest_path) - if parent_dir not in existing_parents: - ensure_dir(parent_dir) - existing_parents.add(parent_dir) file.save() record_installed(file.src_record_path, file.dest_path, file.changed) @@ -614,9 +610,7 @@ def pyc_output_path(path: str) -> str: # Compile all of the pyc files for the installed files if pycompile: - with contextlib.redirect_stdout( - StreamWrapper.from_stream(sys.stdout) - ) as stdout: + with captured_stdout() as stdout: with warnings.catch_warnings(): warnings.filterwarnings("ignore") for path in pyc_source_file_paths(): @@ -718,7 +712,7 @@ def req_error_context(req_description: str) -> Generator[None, None, None]: try: yield except InstallationError as e: - message = f"For req: {req_description}. {e.args[0]}" + message = "For req: {}. {}".format(req_description, e.args[0]) raise InstallationError(message) from e @@ -729,7 +723,7 @@ def install_wheel( req_description: str, pycompile: bool = True, warn_script_location: bool = True, - direct_url: DirectUrl | None = None, + direct_url: Optional[DirectUrl] = None, requested: bool = False, ) -> None: with ZipFile(wheel_path, allowZip64=True) as z: diff --git a/venv1/Lib/site-packages/pip/_internal/operations/prepare.py b/venv1/Lib/site-packages/pip/_internal/operations/prepare.py index a72e0e47..22733152 100644 --- a/venv1/Lib/site-packages/pip/_internal/operations/prepare.py +++ b/venv1/Lib/site-packages/pip/_internal/operations/prepare.py @@ -1,20 +1,17 @@ -"""Prepares a distribution for installation""" +"""Prepares a distribution for installation +""" # The following comment should be removed at some point in the future. # mypy: strict-optional=False -from __future__ import annotations +import logging import mimetypes import os import shutil -from collections.abc import Iterable -from dataclasses import dataclass -from pathlib import Path -from typing import TYPE_CHECKING +from typing import Dict, Iterable, List, Optional from pip._vendor.packaging.utils import canonicalize_name -from pip._internal.build_env import BuildEnvironmentInstaller from pip._internal.distributions import make_distribution_for_install_requirement from pip._internal.distributions.installed import InstalledDistribution from pip._internal.exceptions import ( @@ -24,6 +21,7 @@ InstallationError, MetadataInconsistent, NetworkConnectionError, + PreviousBuildDirError, VcsHashUnsupported, ) from pip._internal.index.package_finder import PackageFinder @@ -31,7 +29,7 @@ from pip._internal.models.direct_url import ArchiveInfo from pip._internal.models.link import Link from pip._internal.models.wheel import Wheel -from pip._internal.network.download import Downloader +from pip._internal.network.download import BatchDownloader, Downloader from pip._internal.network.lazy_wheel import ( HTTPRangeRequestUnsupported, dist_from_wheel_url, @@ -39,7 +37,6 @@ from pip._internal.network.session import PipSession from pip._internal.operations.build.build_tracker import BuildTracker from pip._internal.req.req_install import InstallRequirement -from pip._internal.utils._log import getLogger from pip._internal.utils.direct_url_helpers import ( direct_url_for_editable, direct_url_from_link, @@ -50,33 +47,28 @@ display_path, hash_file, hide_url, - redact_auth_from_requirement, + is_installable_dir, ) from pip._internal.utils.temp_dir import TempDirectory from pip._internal.utils.unpacking import unpack_file from pip._internal.vcs import vcs -if TYPE_CHECKING: - from pip._internal.cli.progress_bars import BarType - -logger = getLogger(__name__) +logger = logging.getLogger(__name__) def _get_prepared_distribution( req: InstallRequirement, build_tracker: BuildTracker, - build_env_installer: BuildEnvironmentInstaller, + finder: PackageFinder, build_isolation: bool, check_build_deps: bool, ) -> BaseDistribution: """Prepare a distribution for installation.""" abstract_dist = make_distribution_for_install_requirement(req) - tracker_id = abstract_dist.build_tracker_id - if tracker_id is not None: - with build_tracker.track(req, tracker_id): - abstract_dist.prepare_distribution_metadata( - build_env_installer, build_isolation, check_build_deps - ) + with build_tracker.track(req): + abstract_dist.prepare_distribution_metadata( + finder, build_isolation, check_build_deps + ) return abstract_dist.get_metadata_distribution() @@ -86,26 +78,20 @@ def unpack_vcs_link(link: Link, location: str, verbosity: int) -> None: vcs_backend.unpack(location, url=hide_url(link.url), verbosity=verbosity) -@dataclass class File: - path: str - content_type: str | None = None - - def __post_init__(self) -> None: - if self.content_type is None: - # Try to guess the file's MIME type. If the system MIME tables - # can't be loaded, give up. - try: - self.content_type = mimetypes.guess_type(self.path)[0] - except OSError: - pass + def __init__(self, path: str, content_type: Optional[str]) -> None: + self.path = path + if content_type is None: + self.content_type = mimetypes.guess_type(path)[0] + else: + self.content_type = content_type def get_http_url( link: Link, download: Downloader, - download_dir: str | None = None, - hashes: Hashes | None = None, + download_dir: Optional[str] = None, + hashes: Optional[Hashes] = None, ) -> File: temp_dir = TempDirectory(kind="unpack", globally_managed=True) # If a download dir is specified, is the file already downloaded there? @@ -126,7 +112,7 @@ def get_http_url( def get_file_url( - link: Link, download_dir: str | None = None, hashes: Hashes | None = None + link: Link, download_dir: Optional[str] = None, hashes: Optional[Hashes] = None ) -> File: """Get file and optionally check its hash.""" # If a download dir is specified, is the file already there and valid? @@ -154,9 +140,9 @@ def unpack_url( location: str, download: Downloader, verbosity: int, - download_dir: str | None = None, - hashes: Hashes | None = None, -) -> File | None: + download_dir: Optional[str] = None, + hashes: Optional[Hashes] = None, +) -> Optional[File]: """Unpack link into location, downloading if required. :param hashes: A Hashes object, one of whose embedded hashes must match, @@ -195,9 +181,9 @@ def unpack_url( def _check_download_dir( link: Link, download_dir: str, - hashes: Hashes | None, + hashes: Optional[Hashes], warn_on_hash_mismatch: bool = True, -) -> str | None: +) -> Optional[str]: """Check download_dir for previously downloaded file with correct hash If a correct file is found return its path else None """ @@ -225,25 +211,21 @@ def _check_download_dir( class RequirementPreparer: """Prepares a Requirement""" - def __init__( # noqa: PLR0913 (too many parameters) + def __init__( self, - *, build_dir: str, - download_dir: str | None, + download_dir: Optional[str], src_dir: str, build_isolation: bool, - build_isolation_installer: BuildEnvironmentInstaller, check_build_deps: bool, build_tracker: BuildTracker, session: PipSession, - progress_bar: BarType, + progress_bar: str, finder: PackageFinder, require_hashes: bool, use_user_site: bool, lazy_wheel: bool, verbosity: int, - legacy_resolver: bool, - resume_retries: int, ) -> None: super().__init__() @@ -251,7 +233,8 @@ def __init__( # noqa: PLR0913 (too many parameters) self.build_dir = build_dir self.build_tracker = build_tracker self._session = session - self._download = Downloader(session, progress_bar, resume_retries) + self._download = Downloader(session, progress_bar) + self._batch_download = BatchDownloader(session, progress_bar) self.finder = finder # Where still-packed archives should be written to. If None, they are @@ -260,7 +243,6 @@ def __init__( # noqa: PLR0913 (too many parameters) # Is build isolation allowed? self.build_isolation = build_isolation - self.build_env_installer = build_isolation_installer # Should check build dependencies? self.check_build_deps = check_build_deps @@ -277,11 +259,8 @@ def __init__( # noqa: PLR0913 (too many parameters) # How verbose should underlying tooling be? self.verbosity = verbosity - # Are we using the legacy resolver? - self.legacy_resolver = legacy_resolver - # Memoized downloaded files, as mapping of url: path. - self._downloaded: dict[str, str] = {} + self._downloaded: Dict[str, str] = {} # Previous "header" printed for a link-based InstallRequirement self._previous_requirement_header = ("", "") @@ -293,13 +272,13 @@ def _log_preparing_link(self, req: InstallRequirement) -> None: information = str(display_path(req.link.file_path)) else: message = "Collecting %s" - information = redact_auth_from_requirement(req.req) if req.req else str(req) + information = str(req.req or req) # If we used req.req, inject requirement source if available (this # would already be included if we used req directly) if req.req and req.comes_from: if isinstance(req.comes_from, str): - comes_from: str | None = req.comes_from + comes_from: Optional[str] = req.comes_from else: comes_from = req.comes_from.from_path() if comes_from: @@ -334,7 +313,21 @@ def _ensure_link_req_src_dir( autodelete=True, parallel_builds=parallel_builds, ) - req.ensure_pristine_source_checkout() + + # If a checkout exists, it's unwise to keep going. version + # inconsistencies are logged later, but do not fail the + # installation. + # FIXME: this won't upgrade when there's an existing + # package unpacked in `req.source_dir` + # TODO: this check is now probably dead code + if is_installable_dir(req.source_dir): + raise PreviousBuildDirError( + "pip can't proceed with requirements '{}' due to a" + "pre-existing build directory ({}). This is likely " + "due to a previous installation that failed . pip is " + "being responsible and not assuming it can delete this. " + "Please delete it and try again.".format(req, req.source_dir) + ) def _get_linked_req_hashes(self, req: InstallRequirement) -> Hashes: # By the time this is called, the requirement's link should have @@ -359,7 +352,7 @@ def _get_linked_req_hashes(self, req: InstallRequirement) -> Hashes: # a surprising hash mismatch in the future. # file:/// URLs aren't pinnable, so don't complain about them # not being pinned. - if not req.is_direct and not req.is_pinned: + if req.original_link is None and not req.is_pinned: raise HashUnpinned() # If known-good hashes are missing for this requirement, @@ -371,12 +364,7 @@ def _get_linked_req_hashes(self, req: InstallRequirement) -> Hashes: def _fetch_metadata_only( self, req: InstallRequirement, - ) -> BaseDistribution | None: - if self.legacy_resolver: - logger.debug( - "Metadata-only fetching is not used in the legacy resolver", - ) - return None + ) -> Optional[BaseDistribution]: if self.require_hashes: logger.debug( "Metadata-only fetching is not used as hash checking is required", @@ -390,14 +378,14 @@ def _fetch_metadata_only( def _fetch_metadata_using_link_data_attr( self, req: InstallRequirement, - ) -> BaseDistribution | None: + ) -> Optional[BaseDistribution]: """Fetch metadata from the data-dist-info-metadata attribute, if possible.""" # (1) Get the link to the metadata file, if provided by the backend. metadata_link = req.link.metadata_link() if metadata_link is None: return None assert req.req is not None - logger.verbose( + logger.info( "Obtaining dependency information for %s from %s", req.req, metadata_link, @@ -422,7 +410,7 @@ def _fetch_metadata_using_link_data_attr( # NB: raw_name will fall back to the name from the install requirement if # the Name: field is not present, but it's noted in the raw_name docstring # that that should NEVER happen anyway. - if canonicalize_name(metadata_dist.raw_name) != canonicalize_name(req.req.name): + if metadata_dist.raw_name != req.req.name: raise MetadataInconsistent( req, "Name", req.req.name, metadata_dist.raw_name ) @@ -431,7 +419,7 @@ def _fetch_metadata_using_link_data_attr( def _fetch_metadata_using_lazy_wheel( self, link: Link, - ) -> BaseDistribution | None: + ) -> Optional[BaseDistribution]: """Fetch metadata using lazy wheel, if possible.""" # --use-feature=fast-deps must be provided. if not self.use_lazy_wheel: @@ -444,7 +432,7 @@ def _fetch_metadata_using_lazy_wheel( return None wheel = Wheel(link.filename) - name = wheel.name + name = canonicalize_name(wheel.name) logger.info( "Obtaining dependency information from %s %s", name, @@ -470,28 +458,19 @@ def _complete_partial_requirements( # Map each link to the requirement that owns it. This allows us to set # `req.local_file_path` on the appropriate requirement after passing # all the links at once into BatchDownloader. - links_to_fully_download: dict[Link, InstallRequirement] = {} + links_to_fully_download: Dict[Link, InstallRequirement] = {} for req in partially_downloaded_reqs: assert req.link links_to_fully_download[req.link] = req - batch_download = self._download.batch(links_to_fully_download.keys(), temp_dir) + batch_download = self._batch_download( + links_to_fully_download.keys(), + temp_dir, + ) for link, (filepath, _) in batch_download: logger.debug("Downloading link %s to %s", link, filepath) req = links_to_fully_download[link] - # Record the downloaded file path so wheel reqs can extract a Distribution - # in .get_dist(). req.local_file_path = filepath - # Record that the file is downloaded so we don't do it again in - # _prepare_linked_requirement(). - self._downloaded[req.link.url] = filepath - - # If this is an sdist, we need to unpack it after downloading, but the - # .source_dir won't be set up until we are in _prepare_linked_requirement(). - # Add the downloaded archive to the install requirement to unpack after - # preparing the source dir. - if not req.is_wheel: - req.needs_unpacked_archive(Path(filepath)) # This step is necessary to ensure all lazy wheels are processed # successfully by the 'download', 'wheel', and 'install' commands. @@ -531,12 +510,6 @@ def prepare_linked_requirement( metadata_dist = self._fetch_metadata_only(req) if metadata_dist is not None: req.needs_more_preparation = True - req.set_dist(metadata_dist) - # Ensure download_info is available even in dry-run mode - if req.download_info is None: - req.download_info = direct_url_from_link( - req.link, req.source_dir - ) return metadata_dist # None of the optimizations worked, fully prepare the requirement @@ -558,7 +531,7 @@ def prepare_linked_requirements_more( # Prepare requirements we found were already downloaded for some # reason. The other downloads will be completed separately. - partially_downloaded_reqs: list[InstallRequirement] = [] + partially_downloaded_reqs: List[InstallRequirement] = [] for req in reqs: if req.needs_more_preparation: partially_downloaded_reqs.append(req) @@ -621,8 +594,8 @@ def _prepare_linked_requirement( ) except NetworkConnectionError as exc: raise InstallationError( - f"Could not install requirement {req} because of HTTP " - f"error {exc} for URL {link}" + "Could not install requirement {} because of HTTP " + "error {} for URL {}".format(req, exc, link) ) else: file_path = self._downloaded[link.url] @@ -658,7 +631,7 @@ def _prepare_linked_requirement( dist = _get_prepared_distribution( req, self.build_tracker, - self.build_env_installer, + self.finder, self.build_isolation, self.check_build_deps, ) @@ -702,9 +675,9 @@ def prepare_editable_requirement( with indent_log(): if self.require_hashes: raise InstallationError( - f"The editable requirement {req} cannot be installed when " + "The editable requirement {} cannot be installed when " "requiring hashes, because there is no single file to " - "hash." + "hash.".format(req) ) req.ensure_has_source_dir(self.src_dir) req.update_editable() @@ -714,7 +687,7 @@ def prepare_editable_requirement( dist = _get_prepared_distribution( req, self.build_tracker, - self.build_env_installer, + self.finder, self.build_isolation, self.check_build_deps, ) @@ -732,7 +705,7 @@ def prepare_installed_requirement( assert req.satisfied_by, "req should have been satisfied but isn't" assert skip_reason is not None, ( "did not get skip reason skipped but req.satisfied_by " - f"is set to {req.satisfied_by}" + "is set to {}".format(req.satisfied_by) ) logger.info( "Requirement %s: %s (%s)", skip_reason, req, req.satisfied_by.version diff --git a/venv1/Lib/site-packages/pip/_internal/pyproject.py b/venv1/Lib/site-packages/pip/_internal/pyproject.py index 8c2f7221..eb8e12b2 100644 --- a/venv1/Lib/site-packages/pip/_internal/pyproject.py +++ b/venv1/Lib/site-packages/pip/_internal/pyproject.py @@ -1,18 +1,16 @@ -from __future__ import annotations - +import importlib.util import os from collections import namedtuple -from typing import Any +from typing import Any, List, Optional -from pip._vendor.packaging.requirements import InvalidRequirement +from pip._vendor import tomli +from pip._vendor.packaging.requirements import InvalidRequirement, Requirement from pip._internal.exceptions import ( InstallationError, InvalidPyProjectBuildRequires, MissingPyProjectBuildRequires, ) -from pip._internal.utils.compat import tomllib -from pip._internal.utils.packaging import get_requirement def _is_list_of_str(obj: Any) -> bool: @@ -29,11 +27,13 @@ def make_pyproject_path(unpacked_source_directory: str) -> str: def load_pyproject_toml( - pyproject_toml: str, setup_py: str, req_name: str -) -> BuildSystemDetails: + use_pep517: Optional[bool], pyproject_toml: str, setup_py: str, req_name: str +) -> Optional[BuildSystemDetails]: """Load the pyproject.toml file. Parameters: + use_pep517 - Has the user requested PEP 517 processing? None + means the user hasn't explicitly specified. pyproject_toml - Location of the project's pyproject.toml file setup_py - Location of the project's setup.py file req_name - The name of the requirement we're processing (for @@ -61,22 +61,78 @@ def load_pyproject_toml( if has_pyproject: with open(pyproject_toml, encoding="utf-8") as f: - pp_toml = tomllib.loads(f.read()) + pp_toml = tomli.loads(f.read()) build_system = pp_toml.get("build-system") else: build_system = None + # The following cases must use PEP 517 + # We check for use_pep517 being non-None and falsey because that means + # the user explicitly requested --no-use-pep517. The value 0 as + # opposed to False can occur when the value is provided via an + # environment variable or config file option (due to the quirk of + # strtobool() returning an integer in pip's configuration code). + if has_pyproject and not has_setup: + if use_pep517 is not None and not use_pep517: + raise InstallationError( + "Disabling PEP 517 processing is invalid: " + "project does not have a setup.py" + ) + use_pep517 = True + elif build_system and "build-backend" in build_system: + if use_pep517 is not None and not use_pep517: + raise InstallationError( + "Disabling PEP 517 processing is invalid: " + "project specifies a build backend of {} " + "in pyproject.toml".format(build_system["build-backend"]) + ) + use_pep517 = True + + # If we haven't worked out whether to use PEP 517 yet, + # and the user hasn't explicitly stated a preference, + # we do so if the project has a pyproject.toml file + # or if we cannot import setuptools or wheels. + + # We fallback to PEP 517 when without setuptools or without the wheel package, + # so setuptools can be installed as a default build backend. + # For more info see: + # https://discuss.python.org/t/pip-without-setuptools-could-the-experience-be-improved/11810/9 + # https://github.com/pypa/pip/issues/8559 + elif use_pep517 is None: + use_pep517 = ( + has_pyproject + or not importlib.util.find_spec("setuptools") + or not importlib.util.find_spec("wheel") + ) + + # At this point, we know whether we're going to use PEP 517. + assert use_pep517 is not None + + # If we're using the legacy code path, there is nothing further + # for us to do here. + if not use_pep517: + return None + if build_system is None: + # Either the user has a pyproject.toml with no build-system + # section, or the user has no pyproject.toml, but has opted in + # explicitly via --use-pep517. # In the absence of any explicit backend specification, we # assume the setuptools backend that most closely emulates the # traditional direct setup.py execution, and require wheel and # a version of setuptools that supports that backend. build_system = { - "requires": ["setuptools>=40.8.0"], + "requires": ["setuptools>=40.8.0", "wheel"], "build-backend": "setuptools.build_meta:__legacy__", } + # If we're using PEP 517, we have build system information (either + # from pyproject.toml, or defaulted by the code above). + # Note that at this point, we do not know if the user has actually + # specified a backend, though. + assert build_system is not None + # Ensure that the build-system section in pyproject.toml conforms # to PEP 518. @@ -95,7 +151,7 @@ def load_pyproject_toml( # Each requirement must be valid as per PEP 508 for requirement in requires: try: - get_requirement(requirement) + Requirement(requirement) except InvalidRequirement as error: raise InvalidPyProjectBuildRequires( package=req_name, @@ -104,7 +160,7 @@ def load_pyproject_toml( backend = build_system.get("build-backend") backend_path = build_system.get("backend-path", []) - check: list[str] = [] + check: List[str] = [] if backend is None: # If the user didn't specify a backend, we assume they want to use # the setuptools backend. But we can't be sure they have included diff --git a/venv1/Lib/site-packages/pip/_internal/req/__init__.py b/venv1/Lib/site-packages/pip/_internal/req/__init__.py index 5fc8752d..16de903a 100644 --- a/venv1/Lib/site-packages/pip/_internal/req/__init__.py +++ b/venv1/Lib/site-packages/pip/_internal/req/__init__.py @@ -1,11 +1,7 @@ -from __future__ import annotations - import collections import logging -from collections.abc import Generator -from dataclasses import dataclass +from typing import Generator, List, Optional, Sequence, Tuple -from pip._internal.cli.progress_bars import BarType, get_install_progress_renderer from pip._internal.utils.logging import indent_log from .req_file import parse_requirements @@ -22,29 +18,32 @@ logger = logging.getLogger(__name__) -@dataclass(frozen=True) class InstallationResult: - name: str + def __init__(self, name: str) -> None: + self.name = name + + def __repr__(self) -> str: + return f"InstallationResult(name={self.name!r})" def _validate_requirements( - requirements: list[InstallRequirement], -) -> Generator[tuple[str, InstallRequirement], None, None]: + requirements: List[InstallRequirement], +) -> Generator[Tuple[str, InstallRequirement], None, None]: for req in requirements: assert req.name, f"invalid to-be-installed requirement: {req}" yield req.name, req def install_given_reqs( - requirements: list[InstallRequirement], - root: str | None, - home: str | None, - prefix: str | None, + requirements: List[InstallRequirement], + global_options: Sequence[str], + root: Optional[str], + home: Optional[str], + prefix: Optional[str], warn_script_location: bool, use_user_site: bool, pycompile: bool, - progress_bar: BarType, -) -> list[InstallationResult]: +) -> List[InstallationResult]: """ Install everything in the given list. @@ -60,19 +59,8 @@ def install_given_reqs( installed = [] - show_progress = logger.isEnabledFor(logging.INFO) and len(to_install) > 1 - - items = iter(to_install.values()) - if show_progress: - renderer = get_install_progress_renderer( - bar_type=progress_bar, total=len(to_install) - ) - items = renderer(items) - with indent_log(): - for requirement in items: - req_name = requirement.name - assert req_name is not None + for req_name, requirement in to_install.items(): if requirement.should_reinstall: logger.info("Attempting uninstall: %s", req_name) with indent_log(): @@ -82,6 +70,7 @@ def install_given_reqs( try: requirement.install( + global_options, root=root, home=home, prefix=prefix, diff --git a/venv1/Lib/site-packages/pip/_internal/req/constructors.py b/venv1/Lib/site-packages/pip/_internal/req/constructors.py index 08b92cf5..c5ca2d85 100644 --- a/venv1/Lib/site-packages/pip/_internal/req/constructors.py +++ b/venv1/Lib/site-packages/pip/_internal/req/constructors.py @@ -8,14 +8,10 @@ InstallRequirement. """ -from __future__ import annotations - -import copy import logging import os import re -from collections.abc import Collection -from dataclasses import dataclass +from typing import Dict, List, Optional, Set, Tuple, Union from pip._vendor.packaging.markers import Marker from pip._vendor.packaging.requirements import InvalidRequirement, Requirement @@ -43,11 +39,11 @@ operators = Specifier._operators.keys() -def _strip_extras(path: str) -> tuple[str, str | None]: +def _strip_extras(path: str) -> Tuple[str, Optional[str]]: m = re.match(r"^(.+)(\[[^\]]+\])$", path) extras = None if m: - path_no_extras = m.group(1).rstrip() + path_no_extras = m.group(1) extras = m.group(2) else: path_no_extras = path @@ -55,56 +51,23 @@ def _strip_extras(path: str) -> tuple[str, str | None]: return path_no_extras, extras -def convert_extras(extras: str | None) -> set[str]: +def convert_extras(extras: Optional[str]) -> Set[str]: if not extras: return set() return get_requirement("placeholder" + extras.lower()).extras -def _set_requirement_extras(req: Requirement, new_extras: set[str]) -> Requirement: - """ - Returns a new requirement based on the given one, with the supplied extras. If the - given requirement already has extras those are replaced (or dropped if no new extras - are given). +def parse_editable(editable_req: str) -> Tuple[Optional[str], str, Set[str]]: + """Parses an editable requirement into: + - a requirement name + - an URL + - extras + - editable options + Accepted requirements: + svn+http://blahblah@rev#egg=Foobar[baz]&subdirectory=version_subdir + .[some_extra] """ - match: re.Match[str] | None = re.fullmatch( - # see https://peps.python.org/pep-0508/#complete-grammar - r"([\w\t .-]+)(\[[^\]]*\])?(.*)", - str(req), - flags=re.ASCII, - ) - # ireq.req is a valid requirement so the regex should always match - assert ( - match is not None - ), f"regex match on requirement {req} failed, this should never happen" - pre: str | None = match.group(1) - post: str | None = match.group(3) - assert ( - pre is not None and post is not None - ), f"regex group selection for requirement {req} failed, this should never happen" - extras: str = "[{}]".format(",".join(sorted(new_extras)) if new_extras else "") - return get_requirement(f"{pre}{extras}{post}") - - -def _parse_direct_url_editable(editable_req: str) -> tuple[str | None, str, set[str]]: - try: - req = Requirement(editable_req) - except InvalidRequirement: - pass - else: - if req.url: - # Join the marker back into the name part. This will be parsed out - # later into a Requirement again. - if req.marker: - name = f"{req.name} ; {req.marker}" - else: - name = req.name - return (name, req.url, req.extras) - raise ValueError - - -def _parse_pip_syntax_editable(editable_req: str) -> tuple[str | None, str, set[str]]: url = editable_req # If a file path is specified with extras, strip off the extras. @@ -130,27 +93,9 @@ def _parse_pip_syntax_editable(editable_req: str) -> tuple[str | None, str, set[ url = f"{version_control}+{url}" break - return Link(url).egg_fragment, url, set() - - -def parse_editable(editable_req: str) -> tuple[str | None, str, set[str]]: - """Parses an editable requirement into: - - a requirement name with environment markers - - an URL - - extras - Accepted requirements: - - svn+http://blahblah@rev#egg=Foobar[baz]&subdirectory=version_subdir - - local_path[some_extra] - - Foobar[extra] @ svn+http://blahblah@rev#subdirectory=subdir ; markers - """ - try: - package_name, url, extras = _parse_direct_url_editable(editable_req) - except ValueError: - package_name, url, extras = _parse_pip_syntax_editable(editable_req) - link = Link(url) - if not link.is_vcs and not link.url.startswith("file:"): + if not link.is_vcs: backends = ", ".join(vcs.all_schemes) raise InstallationError( f"{editable_req} is not a valid editable requirement. " @@ -158,13 +103,13 @@ def parse_editable(editable_req: str) -> tuple[str | None, str, set[str]]: f"(beginning with {backends})." ) - # The project name can be inferred from local file URIs easily. - if not package_name and not link.url.startswith("file:"): + package_name = link.egg_fragment + if not package_name: raise InstallationError( - f"Could not detect requirement name for '{editable_req}', " - "please specify one with your_package_name @ URL" + "Could not detect requirement name for '{}', please specify one " + "with #egg=your_package_name".format(editable_req) ) - return package_name, url, extras + return package_name, url, set() def check_first_requirement_in_file(filename: str) -> None: @@ -191,7 +136,7 @@ def check_first_requirement_in_file(filename: str) -> None: # If there is a line continuation, drop it, and append the next line. if line.endswith("\\"): line = line[:-2].strip() + next(lines, "") - get_requirement(line) + Requirement(line) return @@ -220,12 +165,18 @@ def deduce_helpful_msg(req: str) -> str: return msg -@dataclass(frozen=True) class RequirementParts: - requirement: Requirement | None - link: Link | None - markers: Marker | None - extras: set[str] + def __init__( + self, + requirement: Optional[Requirement], + link: Optional[Link], + markers: Optional[Marker], + extras: Set[str], + ): + self.requirement = requirement + self.link = link + self.markers = markers + self.extras = extras def parse_req_from_editable(editable_req: str) -> RequirementParts: @@ -233,9 +184,9 @@ def parse_req_from_editable(editable_req: str) -> RequirementParts: if name is not None: try: - req: Requirement | None = get_requirement(name) - except InvalidRequirement as exc: - raise InstallationError(f"Invalid requirement: {name!r}: {exc}") + req: Optional[Requirement] = Requirement(name) + except InvalidRequirement: + raise InstallationError(f"Invalid requirement: '{name}'") else: req = None @@ -249,14 +200,16 @@ def parse_req_from_editable(editable_req: str) -> RequirementParts: def install_req_from_editable( editable_req: str, - comes_from: InstallRequirement | str | None = None, + comes_from: Optional[Union[InstallRequirement, str]] = None, *, + use_pep517: Optional[bool] = None, isolated: bool = False, - hash_options: dict[str, list[str]] | None = None, + global_options: Optional[List[str]] = None, + hash_options: Optional[Dict[str, List[str]]] = None, constraint: bool = False, user_supplied: bool = False, permit_editable_wheels: bool = False, - config_settings: dict[str, str | list[str]] | None = None, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, ) -> InstallRequirement: parts = parse_req_from_editable(editable_req) @@ -268,7 +221,9 @@ def install_req_from_editable( permit_editable_wheels=permit_editable_wheels, link=parts.link, constraint=constraint, + use_pep517=use_pep517, isolated=isolated, + global_options=global_options, hash_options=hash_options, config_settings=config_settings, extras=parts.extras, @@ -294,7 +249,7 @@ def _looks_like_path(name: str) -> bool: return False -def _get_url_from_path(path: str, name: str) -> str | None: +def _get_url_from_path(path: str, name: str) -> Optional[str]: """ First, it checks whether a provided path is an installable directory. If it is, returns the path. @@ -328,7 +283,7 @@ def _get_url_from_path(path: str, name: str) -> str | None: return path_to_url(path) -def parse_req_from_line(name: str, line_source: str | None) -> RequirementParts: +def parse_req_from_line(name: str, line_source: Optional[str]) -> RequirementParts: if is_url(name): marker_sep = "; " else: @@ -383,8 +338,8 @@ def with_source(text: str) -> str: def _parse_req_string(req_as_string: str) -> Requirement: try: - return get_requirement(req_as_string) - except InvalidRequirement as exc: + req = get_requirement(req_as_string) + except InvalidRequirement: if os.path.sep in req_as_string: add_msg = "It looks like a path." add_msg += deduce_helpful_msg(req_as_string) @@ -394,13 +349,24 @@ def _parse_req_string(req_as_string: str) -> Requirement: add_msg = "= is not a valid operator. Did you mean == ?" else: add_msg = "" - msg = with_source(f"Invalid requirement: {req_as_string!r}: {exc}") + msg = with_source(f"Invalid requirement: {req_as_string!r}") if add_msg: msg += f"\nHint: {add_msg}" raise InstallationError(msg) + else: + # Deprecate extras after specifiers: "name>=1.0[extras]" + # This currently works by accident because _strip_extras() parses + # any extras in the end of the string and those are saved in + # RequirementParts + for spec in req.specifier: + spec_str = str(spec) + if spec_str.endswith("]"): + msg = f"Extras after version '{spec_str}'." + raise InstallationError(msg) + return req if req_as_string is not None: - req: Requirement | None = _parse_req_string(req_as_string) + req: Optional[Requirement] = _parse_req_string(req_as_string) else: req = None @@ -409,14 +375,16 @@ def _parse_req_string(req_as_string: str) -> Requirement: def install_req_from_line( name: str, - comes_from: str | InstallRequirement | None = None, + comes_from: Optional[Union[str, InstallRequirement]] = None, *, + use_pep517: Optional[bool] = None, isolated: bool = False, - hash_options: dict[str, list[str]] | None = None, + global_options: Optional[List[str]] = None, + hash_options: Optional[Dict[str, List[str]]] = None, constraint: bool = False, - line_source: str | None = None, + line_source: Optional[str] = None, user_supplied: bool = False, - config_settings: dict[str, str | list[str]] | None = None, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, ) -> InstallRequirement: """Creates an InstallRequirement from a name, which might be a requirement, directory containing 'setup.py', filename, or URL. @@ -431,7 +399,9 @@ def install_req_from_line( comes_from, link=parts.link, markers=parts.markers, + use_pep517=use_pep517, isolated=isolated, + global_options=global_options, hash_options=hash_options, config_settings=config_settings, constraint=constraint, @@ -442,14 +412,15 @@ def install_req_from_line( def install_req_from_req_string( req_string: str, - comes_from: InstallRequirement | None = None, + comes_from: Optional[InstallRequirement] = None, isolated: bool = False, + use_pep517: Optional[bool] = None, user_supplied: bool = False, ) -> InstallRequirement: try: req = get_requirement(req_string) - except InvalidRequirement as exc: - raise InstallationError(f"Invalid requirement: {req_string!r}: {exc}") + except InvalidRequirement: + raise InstallationError(f"Invalid requirement: '{req_string}'") domains_not_allowed = [ PyPI.file_storage_domain, @@ -465,13 +436,14 @@ def install_req_from_req_string( raise InstallationError( "Packages installed from PyPI cannot depend on packages " "which are not also hosted on PyPI.\n" - f"{comes_from.name} depends on {req} " + "{} depends on {} ".format(comes_from.name, req) ) return InstallRequirement( req, comes_from, isolated=isolated, + use_pep517=use_pep517, user_supplied=user_supplied, ) @@ -479,13 +451,15 @@ def install_req_from_req_string( def install_req_from_parsed_requirement( parsed_req: ParsedRequirement, isolated: bool = False, + use_pep517: Optional[bool] = None, user_supplied: bool = False, - config_settings: dict[str, str | list[str]] | None = None, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, ) -> InstallRequirement: if parsed_req.is_editable: req = install_req_from_editable( parsed_req.requirement, comes_from=parsed_req.comes_from, + use_pep517=use_pep517, constraint=parsed_req.constraint, isolated=isolated, user_supplied=user_supplied, @@ -496,7 +470,13 @@ def install_req_from_parsed_requirement( req = install_req_from_line( parsed_req.requirement, comes_from=parsed_req.comes_from, + use_pep517=use_pep517, isolated=isolated, + global_options=( + parsed_req.options.get("global_options", []) + if parsed_req.options + else [] + ), hash_options=( parsed_req.options.get("hashes", {}) if parsed_req.options else {} ), @@ -517,50 +497,10 @@ def install_req_from_link_and_ireq( editable=ireq.editable, link=link, markers=ireq.markers, + use_pep517=ireq.use_pep517, isolated=ireq.isolated, + global_options=ireq.global_options, hash_options=ireq.hash_options, config_settings=ireq.config_settings, user_supplied=ireq.user_supplied, ) - - -def install_req_drop_extras(ireq: InstallRequirement) -> InstallRequirement: - """ - Creates a new InstallationRequirement using the given template but without - any extras. Sets the original requirement as the new one's parent - (comes_from). - """ - return InstallRequirement( - req=( - _set_requirement_extras(ireq.req, set()) if ireq.req is not None else None - ), - comes_from=ireq, - editable=ireq.editable, - link=ireq.link, - markers=ireq.markers, - isolated=ireq.isolated, - hash_options=ireq.hash_options, - constraint=ireq.constraint, - extras=[], - config_settings=ireq.config_settings, - user_supplied=ireq.user_supplied, - permit_editable_wheels=ireq.permit_editable_wheels, - ) - - -def install_req_extend_extras( - ireq: InstallRequirement, - extras: Collection[str], -) -> InstallRequirement: - """ - Returns a copy of an installation requirement with some additional extras. - Makes a shallow copy of the ireq object. - """ - result = copy.copy(ireq) - result.extras = {*ireq.extras, *extras} - result.req = ( - _set_requirement_extras(ireq.req, result.extras) - if ireq.req is not None - else None - ) - return result diff --git a/venv1/Lib/site-packages/pip/_internal/req/req_file.py b/venv1/Lib/site-packages/pip/_internal/req/req_file.py index a4f54b43..f717c1cc 100644 --- a/venv1/Lib/site-packages/pip/_internal/req/req_file.py +++ b/venv1/Lib/site-packages/pip/_internal/req/req_file.py @@ -2,40 +2,45 @@ Requirements file parsing """ -from __future__ import annotations - -import codecs -import locale import logging import optparse import os import re import shlex -import sys import urllib.parse -from collections.abc import Generator, Iterable -from dataclasses import dataclass from optparse import Values from typing import ( TYPE_CHECKING, Any, Callable, - NoReturn, + Dict, + Generator, + Iterable, + List, + Optional, + Tuple, ) from pip._internal.cli import cmdoptions from pip._internal.exceptions import InstallationError, RequirementsFileParseError from pip._internal.models.search_scope import SearchScope +from pip._internal.network.session import PipSession +from pip._internal.network.utils import raise_for_status +from pip._internal.utils.encoding import auto_decode +from pip._internal.utils.urls import get_url_scheme if TYPE_CHECKING: + # NoReturn introduced in 3.6.2; imported only for type checking to maintain + # pip compatibility with older patch versions of Python 3.6 + from typing import NoReturn + from pip._internal.index.package_finder import PackageFinder - from pip._internal.network.session import PipSession __all__ = ["parse_requirements"] -ReqFileLines = Iterable[tuple[int, str]] +ReqFileLines = Iterable[Tuple[int, str]] -LineParser = Callable[[str], tuple[str, Values]] +LineParser = Callable[[str], Tuple[str, Values]] SCHEME_RE = re.compile(r"^(http|https|file):", re.I) COMMENT_RE = re.compile(r"(^|\s+)#.*$") @@ -46,7 +51,7 @@ # 2013 Edition. ENV_VAR_RE = re.compile(r"(?P\$\{(?P[A-Z0-9_]+)\})") -SUPPORTED_OPTIONS: list[Callable[..., optparse.Option]] = [ +SUPPORTED_OPTIONS: List[Callable[..., optparse.Option]] = [ cmdoptions.index_url, cmdoptions.extra_index_url, cmdoptions.no_index, @@ -64,89 +69,68 @@ ] # options to be passed to requirements -SUPPORTED_OPTIONS_REQ: list[Callable[..., optparse.Option]] = [ +SUPPORTED_OPTIONS_REQ: List[Callable[..., optparse.Option]] = [ + cmdoptions.global_options, cmdoptions.hash, cmdoptions.config_settings, ] -SUPPORTED_OPTIONS_EDITABLE_REQ: list[Callable[..., optparse.Option]] = [ - cmdoptions.config_settings, -] - - # the 'dest' string values SUPPORTED_OPTIONS_REQ_DEST = [str(o().dest) for o in SUPPORTED_OPTIONS_REQ] -SUPPORTED_OPTIONS_EDITABLE_REQ_DEST = [ - str(o().dest) for o in SUPPORTED_OPTIONS_EDITABLE_REQ -] - -# order of BOMS is important: codecs.BOM_UTF16_LE is a prefix of codecs.BOM_UTF32_LE -# so data.startswith(BOM_UTF16_LE) would be true for UTF32_LE data -BOMS: list[tuple[bytes, str]] = [ - (codecs.BOM_UTF8, "utf-8"), - (codecs.BOM_UTF32, "utf-32"), - (codecs.BOM_UTF32_BE, "utf-32-be"), - (codecs.BOM_UTF32_LE, "utf-32-le"), - (codecs.BOM_UTF16, "utf-16"), - (codecs.BOM_UTF16_BE, "utf-16-be"), - (codecs.BOM_UTF16_LE, "utf-16-le"), -] - -PEP263_ENCODING_RE = re.compile(rb"coding[:=]\s*([-\w.]+)") -DEFAULT_ENCODING = "utf-8" logger = logging.getLogger(__name__) -@dataclass(frozen=True) class ParsedRequirement: - # TODO: replace this with slots=True when dropping Python 3.9 support. - __slots__ = ( - "requirement", - "is_editable", - "comes_from", - "constraint", - "options", - "line_source", - ) - - requirement: str - is_editable: bool - comes_from: str - constraint: bool - options: dict[str, Any] | None - line_source: str | None + def __init__( + self, + requirement: str, + is_editable: bool, + comes_from: str, + constraint: bool, + options: Optional[Dict[str, Any]] = None, + line_source: Optional[str] = None, + ) -> None: + self.requirement = requirement + self.is_editable = is_editable + self.comes_from = comes_from + self.options = options + self.constraint = constraint + self.line_source = line_source -@dataclass(frozen=True) class ParsedLine: - __slots__ = ("filename", "lineno", "args", "opts", "constraint") - - filename: str - lineno: int - args: str - opts: Values - constraint: bool - - @property - def is_editable(self) -> bool: - return bool(self.opts.editables) - - @property - def requirement(self) -> str | None: - if self.args: - return self.args - elif self.is_editable: + def __init__( + self, + filename: str, + lineno: int, + args: str, + opts: Values, + constraint: bool, + ) -> None: + self.filename = filename + self.lineno = lineno + self.opts = opts + self.constraint = constraint + + if args: + self.is_requirement = True + self.is_editable = False + self.requirement = args + elif opts.editables: + self.is_requirement = True + self.is_editable = True # We don't support multiple -e on one line - return self.opts.editables[0] - return None + self.requirement = opts.editables[0] + else: + self.is_requirement = False def parse_requirements( filename: str, session: PipSession, - finder: PackageFinder | None = None, - options: optparse.Values | None = None, + finder: Optional["PackageFinder"] = None, + options: Optional[optparse.Values] = None, constraint: bool = False, ) -> Generator[ParsedRequirement, None, None]: """Parse a requirements file and yield ParsedRequirement instances. @@ -183,7 +167,7 @@ def preprocess(content: str) -> ReqFileLines: def handle_requirement_line( line: ParsedLine, - options: optparse.Values | None = None, + options: Optional[optparse.Values] = None, ) -> ParsedRequirement: # preserve for the nested code path line_comes_from = "{} {} (line {})".format( @@ -192,36 +176,42 @@ def handle_requirement_line( line.lineno, ) - assert line.requirement is not None + assert line.is_requirement - # get the options that apply to requirements if line.is_editable: - supported_dest = SUPPORTED_OPTIONS_EDITABLE_REQ_DEST + # For editable requirements, we don't support per-requirement + # options, so just return the parsed requirement. + return ParsedRequirement( + requirement=line.requirement, + is_editable=line.is_editable, + comes_from=line_comes_from, + constraint=line.constraint, + ) else: - supported_dest = SUPPORTED_OPTIONS_REQ_DEST - req_options = {} - for dest in supported_dest: - if dest in line.opts.__dict__ and line.opts.__dict__[dest]: - req_options[dest] = line.opts.__dict__[dest] - - line_source = f"line {line.lineno} of {line.filename}" - return ParsedRequirement( - requirement=line.requirement, - is_editable=line.is_editable, - comes_from=line_comes_from, - constraint=line.constraint, - options=req_options, - line_source=line_source, - ) + # get the options that apply to requirements + req_options = {} + for dest in SUPPORTED_OPTIONS_REQ_DEST: + if dest in line.opts.__dict__ and line.opts.__dict__[dest]: + req_options[dest] = line.opts.__dict__[dest] + + line_source = f"line {line.lineno} of {line.filename}" + return ParsedRequirement( + requirement=line.requirement, + is_editable=line.is_editable, + comes_from=line_comes_from, + constraint=line.constraint, + options=req_options, + line_source=line_source, + ) def handle_option_line( opts: Values, filename: str, lineno: int, - finder: PackageFinder | None = None, - options: optparse.Values | None = None, - session: PipSession | None = None, + finder: Optional["PackageFinder"] = None, + options: Optional[optparse.Values] = None, + session: Optional[PipSession] = None, ) -> None: if opts.hashes: logger.warning( @@ -287,10 +277,10 @@ def handle_option_line( def handle_line( line: ParsedLine, - options: optparse.Values | None = None, - finder: PackageFinder | None = None, - session: PipSession | None = None, -) -> ParsedRequirement | None: + options: Optional[optparse.Values] = None, + finder: Optional["PackageFinder"] = None, + session: Optional[PipSession] = None, +) -> Optional[ParsedRequirement]: """Handle a single parsed requirements line; This can result in creating/yielding requirements, or updating the finder. @@ -314,7 +304,7 @@ def handle_line( affect the finder. """ - if line.requirement is not None: + if line.is_requirement: parsed_req = handle_requirement_line(line, options) return parsed_req else: @@ -342,18 +332,13 @@ 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, [{os.path.abspath(filename): None}] - ) + yield from self._parse_and_recurse(filename, constraint) def _parse_and_recurse( - self, - filename: str, - constraint: bool, - parsed_files_stack: list[dict[str, str | None]], + self, filename: str, constraint: bool ) -> Generator[ParsedLine, None, None]: for line in self._parse_file(filename, constraint): - if line.requirement is None and ( + if not line.is_requirement and ( line.opts.requirements or line.opts.constraints ): # parse a nested requirements file @@ -371,30 +356,12 @@ 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 - # and then abspath so that we can identify recursive references - req_path = os.path.abspath( - os.path.join( - os.path.dirname(filename), - req_path, - ) - ) - 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}" + req_path = os.path.join( + os.path.dirname(filename), + req_path, ) - # 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] - ) + + yield from self._parse_and_recurse(req_path, nested_constraint) else: yield line @@ -422,8 +389,8 @@ def _parse_file( ) -def get_line_parser(finder: PackageFinder | None) -> LineParser: - def parse_line(line: str) -> tuple[str, Values]: +def get_line_parser(finder: Optional["PackageFinder"]) -> LineParser: + def parse_line(line: str) -> Tuple[str, Values]: # Build new parser for each line since it accumulates appendable # options. parser = build_parser() @@ -446,7 +413,7 @@ def parse_line(line: str) -> tuple[str, Values]: return parse_line -def break_args_options(line: str) -> tuple[str, str]: +def break_args_options(line: str) -> Tuple[str, str]: """Break up the line into an args and options string. We only want to shlex (and then optparse) the options, not the args. args can contain markers which are corrupted by shlex. @@ -455,7 +422,7 @@ def break_args_options(line: str) -> tuple[str, str]: args = [] options = tokens[:] for token in tokens: - if token.startswith(("-", "--")): + if token.startswith("-") or token.startswith("--"): break else: args.append(token) @@ -481,7 +448,7 @@ def build_parser() -> optparse.OptionParser: # By default optparse sys.exits on parsing errors. We want to wrap # that in our own exception. - def parser_exit(self: Any, msg: str) -> NoReturn: + def parser_exit(self: Any, msg: str) -> "NoReturn": raise OptionParsingError(msg) # NOTE: mypy disallows assigning to a method @@ -496,7 +463,7 @@ def join_lines(lines_enum: ReqFileLines) -> ReqFileLines: comments). The joined line takes on the index of the first line. """ primary_line_number = None - new_line: list[str] = [] + new_line: List[str] = [] for line_number, line in lines_enum: if not line.endswith("\\") or COMMENT_RE.match(line): if COMMENT_RE.match(line): @@ -560,7 +527,7 @@ def expand_env_variables(lines_enum: ReqFileLines) -> ReqFileLines: yield line_number, line -def get_file_content(url: str, session: PipSession) -> tuple[str, str]: +def get_file_content(url: str, session: PipSession) -> Tuple[str, str]: """Gets the content of a file; it may be a filename, file: URL, or http: URL. Returns (location, content). Content is unicode. Respects # -*- coding: declarations on the retrieved files. @@ -568,12 +535,10 @@ def get_file_content(url: str, session: PipSession) -> tuple[str, str]: :param url: File path or url. :param session: PipSession instance. """ - scheme = urllib.parse.urlsplit(url).scheme + scheme = get_url_scheme(url) + # Pip has special support for file:// URLs (LocalFSAdapter). if scheme in ["http", "https", "file"]: - # Delay importing heavy network modules until absolutely necessary. - from pip._internal.network.utils import raise_for_status - resp = session.get(url) raise_for_status(resp) return resp.url, resp.text @@ -581,39 +546,7 @@ def get_file_content(url: str, session: PipSession) -> tuple[str, str]: # Assume this is a bare path. try: with open(url, "rb") as f: - raw_content = f.read() + content = auto_decode(f.read()) except OSError as exc: raise InstallationError(f"Could not open requirements file: {exc}") - - content = _decode_req_file(raw_content, url) - return url, content - - -def _decode_req_file(data: bytes, url: str) -> str: - for bom, encoding in BOMS: - if data.startswith(bom): - return data[len(bom) :].decode(encoding) - - for line in data.split(b"\n")[:2]: - if line[0:1] == b"#": - result = PEP263_ENCODING_RE.search(line) - if result is not None: - encoding = result.groups()[0].decode("ascii") - return data.decode(encoding) - - try: - return data.decode(DEFAULT_ENCODING) - except UnicodeDecodeError: - locale_encoding = locale.getpreferredencoding(False) or sys.getdefaultencoding() - logging.warning( - "unable to decode data from %s with default encoding %s, " - "falling back to encoding from locale: %s. " - "If this is intentional you should specify the encoding with a " - "PEP-263 style comment, e.g. '# -*- coding: %s -*-'", - url, - DEFAULT_ENCODING, - locale_encoding, - locale_encoding, - ) - return data.decode(locale_encoding) diff --git a/venv1/Lib/site-packages/pip/_internal/req/req_install.py b/venv1/Lib/site-packages/pip/_internal/req/req_install.py index bd4fb071..d01b24a9 100644 --- a/venv1/Lib/site-packages/pip/_internal/req/req_install.py +++ b/venv1/Lib/site-packages/pip/_internal/req/req_install.py @@ -1,4 +1,5 @@ -from __future__ import annotations +# The following comment should be removed at some point in the future. +# mypy: strict-optional=False import functools import logging @@ -7,10 +8,8 @@ import sys import uuid import zipfile -from collections.abc import Collection, Iterable from optparse import Values -from pathlib import Path -from typing import Any +from typing import Any, Collection, Dict, Iterable, List, Optional, Sequence, Union from pip._vendor.packaging.markers import Marker from pip._vendor.packaging.requirements import Requirement @@ -21,7 +20,7 @@ from pip._vendor.pyproject_hooks import BuildBackendHookCaller from pip._internal.build_env import BuildEnvironment, NoOpBuildEnvironment -from pip._internal.exceptions import InstallationError, PreviousBuildDirError +from pip._internal.exceptions import InstallationError from pip._internal.locations import get_scheme from pip._internal.metadata import ( BaseDistribution, @@ -34,6 +33,12 @@ from pip._internal.models.link import Link from pip._internal.operations.build.metadata import generate_metadata from pip._internal.operations.build.metadata_editable import generate_editable_metadata +from pip._internal.operations.build.metadata_legacy import ( + generate_metadata as generate_metadata_legacy, +) +from pip._internal.operations.install.editable_legacy import ( + install_editable as install_editable_legacy, +) from pip._internal.operations.install.wheel import install_wheel from pip._internal.pyproject import load_pyproject_toml, make_pyproject_path from pip._internal.req.req_uninstall import UninstallPathSet @@ -45,14 +50,11 @@ backup_dir, display_path, hide_url, - is_installable_dir, - redact_auth_from_requirement, redact_auth_from_url, ) -from pip._internal.utils.packaging import get_requirement +from pip._internal.utils.packaging import safe_extra from pip._internal.utils.subprocess import runner_with_spinner_message from pip._internal.utils.temp_dir import TempDirectory, tempdir_kinds -from pip._internal.utils.unpacking import unpack_file from pip._internal.utils.virtualenv import running_under_virtualenv from pip._internal.vcs import vcs @@ -68,15 +70,17 @@ class InstallRequirement: def __init__( self, - req: Requirement | None, - comes_from: str | InstallRequirement | None, + req: Optional[Requirement], + comes_from: Optional[Union[str, "InstallRequirement"]], editable: bool = False, - link: Link | None = None, - markers: Marker | None = None, + link: Optional[Link] = None, + markers: Optional[Marker] = None, + use_pep517: Optional[bool] = None, isolated: bool = False, *, - hash_options: dict[str, list[str]] | None = None, - config_settings: dict[str, str | list[str]] | None = None, + global_options: Optional[List[str]] = None, + hash_options: Optional[Dict[str, List[str]]] = None, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, constraint: bool = False, extras: Collection[str] = (), user_supplied: bool = False, @@ -94,14 +98,12 @@ def __init__( # populating source_dir is done by the RequirementPreparer. Note this # is not necessarily the directory where pyproject.toml or setup.py is # located - that one is obtained via unpacked_source_directory. - self.source_dir: str | None = None + self.source_dir: Optional[str] = None if self.editable: assert link if link.is_file: self.source_dir = os.path.normpath(os.path.abspath(link.file_path)) - # original_link is the direct URL that was provided by the user for the - # requirement, either directly or via a constraints file. if link is None and req and req.url: # PEP 508 URL requirement link = Link(req.url) @@ -110,21 +112,21 @@ def __init__( # When this InstallRequirement is a wheel obtained from the cache of locally # built wheels, this is the source link corresponding to the cache entry, which # was used to download and build the cached wheel. - self.cached_wheel_source_link: Link | None = None + self.cached_wheel_source_link: Optional[Link] = None # Information about the location of the artifact that was downloaded . This # property is guaranteed to be set in resolver results. - self.download_info: DirectUrl | None = None + self.download_info: Optional[DirectUrl] = None # Path to any downloaded or already-existing package. - self.local_file_path: str | None = None + self.local_file_path: Optional[str] = None if self.link and self.link.is_file: self.local_file_path = self.link.file_path if extras: self.extras = extras elif req: - self.extras = req.extras + self.extras = {safe_extra(extra) for extra in req.extras} else: self.extras = set() if markers is None and req: @@ -132,15 +134,16 @@ def __init__( self.markers = markers # This holds the Distribution object if this requirement is already installed. - self.satisfied_by: BaseDistribution | None = None + self.satisfied_by: Optional[BaseDistribution] = None # Whether the installation process should try to uninstall an existing # distribution before installing this requirement. self.should_reinstall = False # Temporary build location - self._temp_build_dir: TempDirectory | None = None + self._temp_build_dir: Optional[TempDirectory] = None # Set to True after successful installation - self.install_succeeded: bool | None = None + self.install_succeeded: Optional[bool] = None # Supplied options + self.global_options = global_options if global_options else [] self.hash_options = hash_options if hash_options else {} self.config_settings = config_settings # Set to True after successful preparation of this requirement @@ -157,32 +160,32 @@ def __init__( # gets stored. We need this to pass to build_wheel, so the backend # can ensure that the wheel matches the metadata (see the PEP for # details). - self.metadata_directory: str | None = None - - # The cached metadata distribution that this requirement represents. - # See get_dist / set_dist. - self._distribution: BaseDistribution | None = None + self.metadata_directory: Optional[str] = None # The static build requirements (from pyproject.toml) - self.pyproject_requires: list[str] | None = None + self.pyproject_requires: Optional[List[str]] = None # Build requirements that we will check are available - self.requirements_to_check: list[str] = [] + self.requirements_to_check: List[str] = [] # The PEP 517 backend we should use to build the project - self.pep517_backend: BuildBackendHookCaller | None = None + self.pep517_backend: Optional[BuildBackendHookCaller] = None + + # Are we using PEP 517 for this requirement? + # After pyproject.toml has been loaded, the only valid values are True + # and False. Before loading, None is valid (meaning "use the default"). + # Setting an explicit value before loading pyproject.toml is supported, + # but after loading this flag should be treated as read only. + self.use_pep517 = use_pep517 # This requirement needs more preparation before it can be built self.needs_more_preparation = False - # This requirement needs to be unpacked before it can be installed. - self._archive_source: Path | None = None - def __str__(self) -> str: if self.req: - s = redact_auth_from_requirement(self.req) + s = str(self.req) if self.link: - s += f" from {redact_auth_from_url(self.link.url)}" + s += " from {}".format(redact_auth_from_url(self.link.url)) elif self.link: s = redact_auth_from_url(self.link.url) else: @@ -195,7 +198,7 @@ def __str__(self) -> str: s += f" in {location}" if self.comes_from: if isinstance(self.comes_from, str): - comes_from: str | None = self.comes_from + comes_from: Optional[str] = self.comes_from else: comes_from = self.comes_from.from_path() if comes_from: @@ -203,9 +206,8 @@ def __str__(self) -> str: return s def __repr__(self) -> str: - return ( - f"<{self.__class__.__name__} object: " - f"{str(self)} editable={self.editable!r}>" + return "<{} object: {} editable={!r}>".format( + self.__class__.__name__, str(self), self.editable ) def format_debug(self) -> str: @@ -213,7 +215,7 @@ def format_debug(self) -> str: attributes = vars(self) names = sorted(attributes) - state = (f"{attr}={attributes[attr]!r}" for attr in sorted(names)) + state = ("{}={!r}".format(attr, attributes[attr]) for attr in sorted(names)) return "<{name} object: {{{state}}}>".format( name=self.__class__.__name__, state=", ".join(state), @@ -221,13 +223,15 @@ def format_debug(self) -> str: # Things that are valid for all kinds of requirements? @property - def name(self) -> str | None: + def name(self) -> Optional[str]: if self.req is None: return None return self.req.name - @functools.cached_property + @functools.lru_cache() # use cached_property in python 3.8+ def supports_pyproject_editable(self) -> bool: + if not self.use_pep517: + return False assert self.pep517_backend with self.build_env: runner = runner_with_spinner_message( @@ -238,25 +242,18 @@ def supports_pyproject_editable(self) -> bool: @property def specifier(self) -> SpecifierSet: - assert self.req is not None return self.req.specifier - @property - def is_direct(self) -> bool: - """Whether this requirement was specified as a direct URL.""" - return self.original_link is not None - @property def is_pinned(self) -> bool: """Return whether I am pinned to an exact version. For example, some-package==1.2 is pinned; some-package>1.2 is not. """ - assert self.req is not None - specifiers = self.req.specifier + specifiers = self.specifier return len(specifiers) == 1 and next(iter(specifiers)).operator in {"==", "==="} - def match_markers(self, extras_requested: Iterable[str] | None = None) -> bool: + def match_markers(self, extras_requested: Optional[Iterable[str]] = None) -> bool: if not extras_requested: # Provide an extra to safely evaluate the markers # without matching any extra @@ -296,22 +293,20 @@ def hashes(self, trust_internet: bool = True) -> Hashes: good_hashes = self.hash_options.copy() if trust_internet: link = self.link - elif self.is_direct and self.user_supplied: + elif self.original_link and self.user_supplied: link = self.original_link else: link = None if link and link.hash: - assert link.hash_name is not None good_hashes.setdefault(link.hash_name, []).append(link.hash) return Hashes(good_hashes) - def from_path(self) -> str | None: + def from_path(self) -> Optional[str]: """Format a nice indicator to show where this "comes from" """ if self.req is None: return None s = str(self.req) if self.comes_from: - comes_from: str | None if isinstance(self.comes_from, str): comes_from = self.comes_from else: @@ -343,7 +338,7 @@ def ensure_build_location( # When parallel builds are enabled, add a UUID to the build directory # name so multiple builds do not interfere with each other. - dir_name: str = canonicalize_name(self.req.name) + dir_name: str = canonicalize_name(self.name) if parallel_builds: dir_name = f"{dir_name}_{uuid.uuid4().hex}" @@ -375,7 +370,7 @@ def _set_requirement(self) -> None: else: op = "===" - self.req = get_requirement( + self.req = Requirement( "".join( [ self.metadata["Name"], @@ -386,7 +381,6 @@ def _set_requirement(self) -> None: ) def warn_on_mismatching_name(self) -> None: - assert self.req is not None metadata_name = canonicalize_name(self.metadata["Name"]) if canonicalize_name(self.req.name) == metadata_name: # Everything is fine. @@ -401,7 +395,7 @@ def warn_on_mismatching_name(self) -> None: metadata_name, self.name, ) - self.req = get_requirement(metadata_name) + self.req = Requirement(metadata_name) def check_if_exists(self, use_user_site: bool) -> None: """Find an installed distribution that satisfies or conflicts @@ -456,7 +450,6 @@ def is_wheel_from_cache(self) -> bool: # Things valid for sdists @property def unpacked_source_directory(self) -> str: - assert self.source_dir, f"No source dir for {self}" return os.path.join( self.source_dir, self.link and self.link.subdirectory_fragment or "" ) @@ -468,6 +461,13 @@ def setup_py_path(self) -> str: return setup_py + @property + def setup_cfg_path(self) -> str: + assert self.source_dir, f"No source dir for {self}" + setup_cfg = os.path.join(self.unpacked_source_directory, "setup.cfg") + + return setup_cfg + @property def pyproject_toml_path(self) -> str: assert self.source_dir, f"No source dir for {self}" @@ -477,12 +477,28 @@ def load_pyproject_toml(self) -> None: """Load the pyproject.toml file. After calling this routine, all of the attributes related to PEP 517 - processing for this requirement have been set. + processing for this requirement have been set. In particular, the + use_pep517 attribute can be used to determine whether we should + follow the PEP 517 or legacy (setup.py) code path. """ pyproject_toml_data = load_pyproject_toml( - self.pyproject_toml_path, self.setup_py_path, str(self) + self.use_pep517, self.pyproject_toml_path, self.setup_py_path, str(self) ) - assert pyproject_toml_data + + if pyproject_toml_data is None: + if self.config_settings: + deprecated( + reason=f"Config settings are ignored for project {self}.", + replacement=( + "to use --use-pep517 or add a " + "pyproject.toml file to the project" + ), + gone_in="23.3", + ) + self.use_pep517 = False + return + + self.use_pep517 = True requires, backend, check, backend_path = pyproject_toml_data self.requirements_to_check = check self.pyproject_requires = requires @@ -493,15 +509,23 @@ def load_pyproject_toml(self) -> None: backend_path=backend_path, ) - def editable_sanity_check(self) -> None: + def isolated_editable_sanity_check(self) -> None: """Check that an editable requirement if valid for use with PEP 517/518. - This verifies that an editable has a build backend that supports PEP 660. + This verifies that an editable that has a pyproject.toml either supports PEP 660 + or as a setup.py or a setup.cfg """ - if self.editable and not self.supports_pyproject_editable: + if ( + self.editable + and self.use_pep517 + and not self.supports_pyproject_editable() + and not os.path.isfile(self.setup_py_path) + and not os.path.isfile(self.setup_cfg_path) + ): raise InstallationError( - f"Project {self} uses a build backend " - f"that is missing the 'build_editable' hook, so " + f"Project {self} has a 'pyproject.toml' and its build " + f"backend is missing the 'build_editable' hook. Since it does not " + f"have a 'setup.py' nor a 'setup.cfg', " f"it cannot be installed in editable mode. " f"Consider using a build backend that supports PEP 660." ) @@ -512,24 +536,33 @@ def prepare_metadata(self) -> None: Under PEP 517 and PEP 660, call the backend hook to prepare the metadata. Under legacy processing, call setup.py egg-info. """ - assert self.source_dir, f"No source dir for {self}" + assert self.source_dir details = self.name or f"from {self.link}" - assert self.pep517_backend is not None - if ( - self.editable - and self.permit_editable_wheels - and self.supports_pyproject_editable - ): - self.metadata_directory = generate_editable_metadata( - build_env=self.build_env, - backend=self.pep517_backend, - details=details, - ) + if self.use_pep517: + assert self.pep517_backend is not None + if ( + self.editable + and self.permit_editable_wheels + and self.supports_pyproject_editable() + ): + self.metadata_directory = generate_editable_metadata( + build_env=self.build_env, + backend=self.pep517_backend, + details=details, + ) + else: + self.metadata_directory = generate_metadata( + build_env=self.build_env, + backend=self.pep517_backend, + details=details, + ) else: - self.metadata_directory = generate_metadata( + self.metadata_directory = generate_metadata_legacy( build_env=self.build_env, - backend=self.pep517_backend, + setup_py_path=self.setup_py_path, + source_dir=self.unpacked_source_directory, + isolated=self.isolated, details=details, ) @@ -548,19 +581,12 @@ def metadata(self) -> Any: return self._metadata - def set_dist(self, distribution: BaseDistribution) -> None: - self._distribution = distribution - def get_dist(self) -> BaseDistribution: - if self._distribution is not None: - return self._distribution - elif self.metadata_directory: + if self.metadata_directory: return get_directory_distribution(self.metadata_directory) elif self.local_file_path and self.is_wheel: - assert self.req is not None return get_wheel_distribution( - FilesystemWheel(self.local_file_path), - canonicalize_name(self.req.name), + FilesystemWheel(self.local_file_path), canonicalize_name(self.name) ) raise AssertionError( f"InstallRequirement {self} has no metadata directory and no wheel: " @@ -568,9 +594,9 @@ def get_dist(self) -> BaseDistribution: ) def assert_source_matches_version(self) -> None: - assert self.source_dir, f"No source dir for {self}" + assert self.source_dir version = self.metadata["version"] - if self.req and self.req.specifier and version not in self.req.specifier: + if self.req.specifier and version not in self.req.specifier: logger.warning( "Requested %s, but installing version %s", self, @@ -607,27 +633,6 @@ def ensure_has_source_dir( parallel_builds=parallel_builds, ) - def needs_unpacked_archive(self, archive_source: Path) -> None: - assert self._archive_source is None - self._archive_source = archive_source - - def ensure_pristine_source_checkout(self) -> None: - """Ensure the source directory has not yet been built in.""" - assert self.source_dir is not None - if self._archive_source is not None: - unpack_file(str(self._archive_source), self.source_dir) - elif is_installable_dir(self.source_dir): - # If a checkout exists, it's unwise to keep going. - # version inconsistencies are logged later, but do not fail - # the installation. - raise PreviousBuildDirError( - f"pip can't proceed with requirements '{self}' due to a " - f"pre-existing build directory ({self.source_dir}). This is likely " - "due to a previous installation that failed . pip is " - "being responsible and not assuming it can delete this. " - "Please delete it and try again." - ) - # For editable installations def update_editable(self) -> None: if not self.link: @@ -651,7 +656,7 @@ def update_editable(self) -> None: # Top-level Actions def uninstall( self, auto_confirm: bool = False, verbose: bool = False - ) -> UninstallPathSet | None: + ) -> Optional[UninstallPathSet]: """ Uninstall the distribution currently satisfying this requirement. @@ -684,12 +689,11 @@ def _clean_zip_name(name: str, prefix: str) -> str: name = name.replace(os.path.sep, "/") return name - assert self.req is not None path = os.path.join(parentdir, path) name = _clean_zip_name(path, rootdir) - return self.req.name + "/" + name + return self.name + "/" + name - def archive(self, build_dir: str | None) -> None: + def archive(self, build_dir: Optional[str]) -> None: """Saves archive to provided build_dir. Used for saving downloaded VCS requirements as part of `pip download`. @@ -704,8 +708,8 @@ def archive(self, build_dir: str | None) -> None: if os.path.exists(archive_path): response = ask_path_exists( - f"The file {display_path(archive_path)} exists. (i)gnore, (w)ipe, " - "(b)ackup, (a)bort ", + "The file {} exists. (i)gnore, (w)ipe, " + "(b)ackup, (a)bort ".format(display_path(archive_path)), ("i", "w", "b", "a"), ) if response == "i": @@ -758,16 +762,16 @@ def archive(self, build_dir: str | None) -> None: def install( self, - root: str | None = None, - home: str | None = None, - prefix: str | None = None, + global_options: Optional[Sequence[str]] = None, + root: Optional[str] = None, + home: Optional[str] = None, + prefix: Optional[str] = None, warn_script_location: bool = True, use_user_site: bool = False, pycompile: bool = True, ) -> None: - assert self.req is not None scheme = get_scheme( - self.req.name, + self.name, user=use_user_site, home=home, root=root, @@ -775,17 +779,32 @@ def install( prefix=prefix, ) + if self.editable and not self.is_wheel: + install_editable_legacy( + global_options=global_options if global_options is not None else [], + prefix=prefix, + home=home, + use_user_site=use_user_site, + name=self.name, + setup_py_path=self.setup_py_path, + isolated=self.isolated, + build_env=self.build_env, + unpacked_source_directory=self.unpacked_source_directory, + ) + self.install_succeeded = True + return + assert self.is_wheel assert self.local_file_path install_wheel( - self.req.name, + self.name, self.local_file_path, scheme=scheme, req_description=str(self.req), pycompile=pycompile, warn_script_location=warn_script_location, - direct_url=self.download_info if self.is_direct else None, + direct_url=self.download_info if self.original_link else None, requested=self.user_supplied, ) self.install_succeeded = True @@ -819,10 +838,30 @@ def check_invalid_constraint_type(req: InstallRequirement) -> str: return problem -def _has_option(options: Values, reqs: list[InstallRequirement], option: str) -> bool: +def _has_option(options: Values, reqs: List[InstallRequirement], option: str) -> bool: if getattr(options, option, None): return True for req in reqs: if getattr(req, option, None): return True return False + + +def check_legacy_setup_py_options( + options: Values, + reqs: List[InstallRequirement], +) -> None: + has_build_options = _has_option(options, reqs, "build_options") + has_global_options = _has_option(options, reqs, "global_options") + if has_build_options or has_global_options: + deprecated( + reason="--build-option and --global-option are deprecated.", + issue=11859, + replacement="to use --config-settings", + gone_in="23.3", + ) + logger.warning( + "Implying --no-binary=:all: due to the presence of " + "--build-option / --global-option. " + ) + options.format_control.disallow_binaries() diff --git a/venv1/Lib/site-packages/pip/_internal/req/req_set.py b/venv1/Lib/site-packages/pip/_internal/req/req_set.py index 3451b24f..ec7a6e07 100644 --- a/venv1/Lib/site-packages/pip/_internal/req/req_set.py +++ b/venv1/Lib/site-packages/pip/_internal/req/req_set.py @@ -1,5 +1,6 @@ import logging from collections import OrderedDict +from typing import Dict, List from pip._vendor.packaging.utils import canonicalize_name @@ -12,10 +13,10 @@ class RequirementSet: def __init__(self, check_supported_wheels: bool = True) -> None: """Create a RequirementSet.""" - self.requirements: dict[str, InstallRequirement] = OrderedDict() + self.requirements: Dict[str, InstallRequirement] = OrderedDict() self.check_supported_wheels = check_supported_wheels - self.unnamed_requirements: list[InstallRequirement] = [] + self.unnamed_requirements: List[InstallRequirement] = [] def __str__(self) -> str: requirements = sorted( @@ -64,11 +65,11 @@ def get_requirement(self, name: str) -> InstallRequirement: raise KeyError(f"No project with the name {name!r}") @property - def all_requirements(self) -> list[InstallRequirement]: + def all_requirements(self) -> List[InstallRequirement]: return self.unnamed_requirements + list(self.requirements.values()) @property - def requirements_to_install(self) -> list[InstallRequirement]: + def requirements_to_install(self) -> List[InstallRequirement]: """Return the list of requirements that need to be installed. TODO remove this property together with the legacy resolver, since the new diff --git a/venv1/Lib/site-packages/pip/_internal/req/req_uninstall.py b/venv1/Lib/site-packages/pip/_internal/req/req_uninstall.py index 3f3dde2f..ad5178e7 100644 --- a/venv1/Lib/site-packages/pip/_internal/req/req_uninstall.py +++ b/venv1/Lib/site-packages/pip/_internal/req/req_uninstall.py @@ -1,14 +1,11 @@ -from __future__ import annotations - import functools import os import sys import sysconfig -from collections.abc import Generator, Iterable from importlib.util import cache_from_source -from typing import Any, Callable +from typing import Any, Callable, Dict, Generator, Iterable, List, Optional, Set, Tuple -from pip._internal.exceptions import LegacyDistutilsInstall, UninstallMissingRecord +from pip._internal.exceptions import UninstallationError from pip._internal.locations import get_bin_prefix, get_bin_user from pip._internal.metadata import BaseDistribution from pip._internal.utils.compat import WINDOWS @@ -41,11 +38,11 @@ def _script_names( def _unique( - fn: Callable[..., Generator[Any, None, None]], + fn: Callable[..., Generator[Any, None, None]] ) -> Callable[..., Generator[Any, None, None]]: @functools.wraps(fn) def unique(*args: Any, **kw: Any) -> Generator[Any, None, None]: - seen: set[Any] = set() + seen: Set[Any] = set() for item in fn(*args, **kw): if item not in seen: seen.add(item) @@ -64,7 +61,7 @@ def uninstallation_paths(dist: BaseDistribution) -> Generator[str, None, None]: UninstallPathSet.add() takes care of the __pycache__ .py[co]. - If RECORD is not found, raises an error, + If RECORD is not found, raises UninstallationError, with possible information from the INSTALLER file. https://packaging.python.org/specifications/recording-installed-packages/ @@ -74,7 +71,17 @@ def uninstallation_paths(dist: BaseDistribution) -> Generator[str, None, None]: entries = dist.iter_declared_entries() if entries is None: - raise UninstallMissingRecord(distribution=dist) + msg = "Cannot uninstall {dist}, RECORD file not found.".format(dist=dist) + installer = dist.installer + if not installer or installer == "pip": + dep = "{}=={}".format(dist.raw_name, dist.version) + msg += ( + " You might be able to recover from this via: " + "'pip install --force-reinstall --no-deps {}'.".format(dep) + ) + else: + msg += " Hint: The package was installed by {}.".format(installer) + raise UninstallationError(msg) for entry in entries: path = os.path.join(location, entry) @@ -88,14 +95,14 @@ def uninstallation_paths(dist: BaseDistribution) -> Generator[str, None, None]: yield path -def compact(paths: Iterable[str]) -> set[str]: +def compact(paths: Iterable[str]) -> Set[str]: """Compact a path set to contain the minimal number of paths necessary to contain all paths in the set. If /a/path/ and /a/path/to/a/file.txt are both in the set, leave only the shorter path.""" sep = os.path.sep - short_paths: set[str] = set() + short_paths: Set[str] = set() for path in sorted(paths, key=len): should_skip = any( path.startswith(shortpath.rstrip("*")) @@ -107,7 +114,7 @@ def compact(paths: Iterable[str]) -> set[str]: return short_paths -def compress_for_rename(paths: Iterable[str]) -> set[str]: +def compress_for_rename(paths: Iterable[str]) -> Set[str]: """Returns a set containing the paths that need to be renamed. This set may include directories when the original sequence of paths @@ -116,7 +123,7 @@ def compress_for_rename(paths: Iterable[str]) -> set[str]: case_map = {os.path.normcase(p): p for p in paths} remaining = set(case_map) unchecked = sorted({os.path.split(p)[0] for p in case_map.values()}, key=len) - wildcards: set[str] = set() + wildcards: Set[str] = set() def norm_join(*a: str) -> str: return os.path.normcase(os.path.join(*a)) @@ -126,8 +133,8 @@ def norm_join(*a: str) -> str: # This directory has already been handled. continue - all_files: set[str] = set() - all_subdirs: set[str] = set() + all_files: Set[str] = set() + all_subdirs: Set[str] = set() for dirname, subdirs, files in os.walk(root): all_subdirs.update(norm_join(root, dirname, d) for d in subdirs) all_files.update(norm_join(root, dirname, f) for f in files) @@ -141,7 +148,7 @@ def norm_join(*a: str) -> str: return set(map(case_map.__getitem__, remaining)) | wildcards -def compress_for_output_listing(paths: Iterable[str]) -> tuple[set[str], set[str]]: +def compress_for_output_listing(paths: Iterable[str]) -> Tuple[Set[str], Set[str]]: """Returns a tuple of 2 sets of which paths to display to user The first set contains paths that would be deleted. Files of a package @@ -165,7 +172,8 @@ def compress_for_output_listing(paths: Iterable[str]) -> tuple[set[str], set[str folders.add(os.path.dirname(path)) files.add(path) - _normcased_files = set(map(os.path.normcase, files)) + # probably this one https://github.com/python/mypy/issues/390 + _normcased_files = set(map(os.path.normcase, files)) # type: ignore folders = compact(folders) @@ -197,10 +205,10 @@ class StashedUninstallPathSet: def __init__(self) -> None: # Mapping from source file root to [Adjacent]TempDirectory # for files under that directory. - self._save_dirs: dict[str, TempDirectory] = {} + self._save_dirs: Dict[str, TempDirectory] = {} # (old path, new path) tuples for each move that may need # to be undone. - self._moves: list[tuple[str, str]] = [] + self._moves: List[Tuple[str, str]] = [] def _get_directory_stash(self, path: str) -> str: """Stashes a directory. @@ -266,7 +274,7 @@ def stash(self, path: str) -> str: def commit(self) -> None: """Commits the uninstall by removing stashed files.""" - for save_dir in self._save_dirs.values(): + for _, save_dir in self._save_dirs.items(): save_dir.cleanup() self._moves = [] self._save_dirs = {} @@ -300,15 +308,15 @@ class UninstallPathSet: requirement.""" def __init__(self, dist: BaseDistribution) -> None: - self._paths: set[str] = set() - self._refuse: set[str] = set() - self._pth: dict[str, UninstallPthEntries] = {} + self._paths: Set[str] = set() + self._refuse: Set[str] = set() + self._pth: Dict[str, UninstallPthEntries] = {} self._dist = dist self._moved_paths = StashedUninstallPathSet() # Create local cache of normalize_path results. Creating an UninstallPathSet # can result in hundreds/thousands of redundant calls to normalize_path with # the same args, which hurts performance. - self._normalize_path_cached = functools.lru_cache(normalize_path) + self._normalize_path_cached = functools.lru_cache()(normalize_path) def _permitted(self, path: str) -> bool: """ @@ -360,7 +368,7 @@ def remove(self, auto_confirm: bool = False, verbose: bool = False) -> None: ) return - dist_name_version = f"{self._dist.raw_name}-{self._dist.raw_version}" + dist_name_version = f"{self._dist.raw_name}-{self._dist.version}" logger.info("Uninstalling %s:", dist_name_version) with indent_log(): @@ -424,7 +432,7 @@ def commit(self) -> None: self._moved_paths.commit() @classmethod - def from_dist(cls, dist: BaseDistribution) -> UninstallPathSet: + def from_dist(cls, dist: BaseDistribution) -> "UninstallPathSet": dist_location = dist.location info_location = dist.info_location if dist_location is None: @@ -502,19 +510,22 @@ def from_dist(cls, dist: BaseDistribution) -> UninstallPathSet: paths_to_remove.add(f"{path}.pyo") elif dist.installed_by_distutils: - raise LegacyDistutilsInstall(distribution=dist) + raise UninstallationError( + "Cannot uninstall {!r}. It is a distutils installed project " + "and thus we cannot accurately determine which files belong " + "to it which would lead to only a partial uninstall.".format( + dist.raw_name, + ) + ) elif dist.installed_as_egg: # package installed by easy_install # We cannot match on dist.egg_name because it can slightly vary # i.e. setuptools-0.6c11-py2.6.egg vs setuptools-0.6rc11-py2.6.egg - # XXX We use normalized_dist_location because dist_location my contain - # a trailing / if the distribution is a zipped egg - # (which is not a directory). - paths_to_remove.add(normalized_dist_location) - easy_install_egg = os.path.split(normalized_dist_location)[1] + paths_to_remove.add(dist_location) + easy_install_egg = os.path.split(dist_location)[1] easy_install_pth = os.path.join( - os.path.dirname(normalized_dist_location), + os.path.dirname(dist_location), "easy-install.pth", ) paths_to_remove.add_pth(easy_install_pth, "./" + easy_install_egg) @@ -584,8 +595,8 @@ def iter_scripts_to_remove( class UninstallPthEntries: def __init__(self, pth_file: str) -> None: self.file = pth_file - self.entries: set[str] = set() - self._saved_lines: list[bytes] | None = None + self.entries: Set[str] = set() + self._saved_lines: Optional[List[bytes]] = None def add(self, entry: str) -> None: entry = os.path.normcase(entry) diff --git a/venv1/Lib/site-packages/pip/_internal/resolution/base.py b/venv1/Lib/site-packages/pip/_internal/resolution/base.py index 5ec4d96a..42dade18 100644 --- a/venv1/Lib/site-packages/pip/_internal/resolution/base.py +++ b/venv1/Lib/site-packages/pip/_internal/resolution/base.py @@ -1,4 +1,4 @@ -from typing import Callable, Optional +from typing import Callable, List, Optional from pip._internal.req.req_install import InstallRequirement from pip._internal.req.req_set import RequirementSet @@ -10,11 +10,11 @@ class BaseResolver: def resolve( - self, root_reqs: list[InstallRequirement], check_supported_wheels: bool + self, root_reqs: List[InstallRequirement], check_supported_wheels: bool ) -> RequirementSet: raise NotImplementedError() def get_installation_order( self, req_set: RequirementSet - ) -> list[InstallRequirement]: + ) -> List[InstallRequirement]: raise NotImplementedError() diff --git a/venv1/Lib/site-packages/pip/_internal/resolution/legacy/resolver.py b/venv1/Lib/site-packages/pip/_internal/resolution/legacy/resolver.py index 33a4fdc3..b17b7e45 100644 --- a/venv1/Lib/site-packages/pip/_internal/resolution/legacy/resolver.py +++ b/venv1/Lib/site-packages/pip/_internal/resolution/legacy/resolver.py @@ -10,14 +10,14 @@ a. "first found, wins" (where the order is breadth first) """ -from __future__ import annotations +# The following comment should be removed at some point in the future. +# mypy: strict-optional=False import logging import sys from collections import defaultdict -from collections.abc import Iterable from itertools import chain -from typing import Optional +from typing import DefaultDict, Iterable, List, Optional, Set, Tuple from pip._vendor.packaging import specifiers from pip._vendor.packaging.requirements import Requirement @@ -52,12 +52,12 @@ logger = logging.getLogger(__name__) -DiscoveredDependencies = defaultdict[Optional[str], list[InstallRequirement]] +DiscoveredDependencies = DefaultDict[str, List[InstallRequirement]] def _check_dist_requires_python( dist: BaseDistribution, - version_info: tuple[int, int, int], + version_info: Tuple[int, int, int], ignore_requires_python: bool = False, ) -> None: """ @@ -104,8 +104,9 @@ def _check_dist_requires_python( return raise UnsupportedPythonVersion( - f"Package {dist.raw_name!r} requires a different Python: " - f"{version} not in {requires_python!r}" + "Package {!r} requires a different Python: {} not in {!r}".format( + dist.raw_name, version, requires_python + ) ) @@ -120,7 +121,7 @@ def __init__( self, preparer: RequirementPreparer, finder: PackageFinder, - wheel_cache: WheelCache | None, + wheel_cache: Optional[WheelCache], make_install_req: InstallRequirementProvider, use_user_site: bool, ignore_dependencies: bool, @@ -128,7 +129,7 @@ def __init__( ignore_requires_python: bool, force_reinstall: bool, upgrade_strategy: str, - py_version_info: tuple[int, ...] | None = None, + py_version_info: Optional[Tuple[int, ...]] = None, ) -> None: super().__init__() assert upgrade_strategy in self._allowed_strategies @@ -155,7 +156,7 @@ def __init__( self._discovered_dependencies: DiscoveredDependencies = defaultdict(list) def resolve( - self, root_reqs: list[InstallRequirement], check_supported_wheels: bool + self, root_reqs: List[InstallRequirement], check_supported_wheels: bool ) -> RequirementSet: """Resolve what operations need to be done @@ -177,7 +178,7 @@ def resolve( # exceptions cannot be checked ahead of time, because # _populate_link() needs to be called before we can make decisions # based on link type. - discovered_reqs: list[InstallRequirement] = [] + discovered_reqs: List[InstallRequirement] = [] hash_errors = HashErrors() for req in chain(requirement_set.all_requirements, discovered_reqs): try: @@ -195,9 +196,9 @@ def _add_requirement_to_set( self, requirement_set: RequirementSet, install_req: InstallRequirement, - parent_req_name: str | None = None, - extras_requested: Iterable[str] | None = None, - ) -> tuple[list[InstallRequirement], InstallRequirement | None]: + parent_req_name: Optional[str] = None, + extras_requested: Optional[Iterable[str]] = None, + ) -> Tuple[List[InstallRequirement], Optional[InstallRequirement]]: """Add install_req as a requirement to install. :param parent_req_name: The name of the requirement that needed this @@ -230,7 +231,9 @@ def _add_requirement_to_set( tags = compatibility_tags.get_supported() if requirement_set.check_supported_wheels and not wheel.supported(tags): raise InstallationError( - f"{wheel.filename} is not a supported wheel on this platform." + "{} is not a supported wheel on this platform.".format( + wheel.filename + ) ) # This next bit is really a sanity check. @@ -245,9 +248,9 @@ def _add_requirement_to_set( return [install_req], None try: - existing_req: InstallRequirement | None = requirement_set.get_requirement( - install_req.name - ) + existing_req: Optional[ + InstallRequirement + ] = requirement_set.get_requirement(install_req.name) except KeyError: existing_req = None @@ -262,8 +265,9 @@ def _add_requirement_to_set( ) if has_conflicting_requirement: raise InstallationError( - f"Double requirement given: {install_req} " - f"(already in {existing_req}, name={install_req.name!r})" + "Double requirement given: {} (already in {}, name={!r})".format( + install_req, existing_req, install_req.name + ) ) # When no existing requirement exists, add the requirement as a @@ -283,9 +287,9 @@ def _add_requirement_to_set( ) if does_not_satisfy_constraint: raise InstallationError( - f"Could not satisfy constraints for '{install_req.name}': " + "Could not satisfy constraints for '{}': " "installation from path or url cannot be " - "constrained to a version" + "constrained to a version".format(install_req.name) ) # If we're now installing a constraint, mark the existing # object for real installation. @@ -321,12 +325,13 @@ def _set_req_to_reinstall(self, req: InstallRequirement) -> None: """ # Don't uninstall the conflict if doing a user install and the # conflict is not a user install. - assert req.satisfied_by is not None if not self.use_user_site or req.satisfied_by.in_usersite: req.should_reinstall = True req.satisfied_by = None - def _check_skip_installed(self, req_to_install: InstallRequirement) -> str | None: + def _check_skip_installed( + self, req_to_install: InstallRequirement + ) -> Optional[str]: """Check if req_to_install should be skipped. This will check if the req is installed, and whether we should upgrade @@ -378,7 +383,7 @@ def _check_skip_installed(self, req_to_install: InstallRequirement) -> str | Non self._set_req_to_reinstall(req_to_install) return None - def _find_requirement_link(self, req: InstallRequirement) -> Link | None: + def _find_requirement_link(self, req: InstallRequirement) -> Optional[Link]: upgrade = self._is_upgrade_allowed(req) best_candidate = self.finder.find_requirement(req, upgrade) if not best_candidate: @@ -393,9 +398,9 @@ def _find_requirement_link(self, req: InstallRequirement) -> Link | None: # "UnicodeEncodeError: 'ascii' codec can't encode character" # in Python 2 when the reason contains non-ascii characters. "The candidate selected for download or install is a " - f"yanked version: {best_candidate}\n" - f"Reason for being yanked: {reason}" - ) + "yanked version: {candidate}\n" + "Reason for being yanked: {reason}" + ).format(candidate=best_candidate, reason=reason) logger.warning(msg) return link @@ -418,8 +423,6 @@ def _populate_link(self, req: InstallRequirement) -> None: if self.wheel_cache is None or self.preparer.require_hashes: return - - assert req.link is not None, "_find_requirement_link unexpectedly returned None" cache_entry = self.wheel_cache.get_cache_entry( link=req.link, package_name=req.name, @@ -489,7 +492,7 @@ def _resolve_one( self, requirement_set: RequirementSet, req_to_install: InstallRequirement, - ) -> list[InstallRequirement]: + ) -> List[InstallRequirement]: """Prepare a single requirements file. :return: A list of additional InstallRequirements to also install. @@ -512,7 +515,7 @@ def _resolve_one( ignore_requires_python=self.ignore_requires_python, ) - more_reqs: list[InstallRequirement] = [] + more_reqs: List[InstallRequirement] = [] def add_req(subreq: Requirement, extras_requested: Iterable[str]) -> None: # This idiosyncratically converts the Requirement to str and let @@ -533,7 +536,6 @@ def add_req(subreq: Requirement, extras_requested: Iterable[str]) -> None: with indent_log(): # We add req_to_install before its dependencies, so that we # can refer to it when adding dependencies. - assert req_to_install.name is not None if not requirement_set.has_requirement(req_to_install.name): # 'unnamed' requirements will get added here # 'unnamed' requirements can only come from being directly @@ -570,7 +572,7 @@ def add_req(subreq: Requirement, extras_requested: Iterable[str]) -> None: def get_installation_order( self, req_set: RequirementSet - ) -> list[InstallRequirement]: + ) -> List[InstallRequirement]: """Create the installation order. The installation order is topological - requirements are installed @@ -581,7 +583,7 @@ def get_installation_order( # installs the user specified things in the order given, except when # dependencies must come earlier to achieve topological order. order = [] - ordered_reqs: set[InstallRequirement] = set() + ordered_reqs: Set[InstallRequirement] = set() def schedule(req: InstallRequirement) -> None: if req.satisfied_by or req in ordered_reqs: diff --git a/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/base.py b/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/base.py index 03877b6c..b206692a 100644 --- a/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/base.py +++ b/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/base.py @@ -1,46 +1,45 @@ -from __future__ import annotations - -from collections.abc import Iterable -from dataclasses import dataclass -from typing import Optional +from typing import FrozenSet, Iterable, Optional, Tuple, Union from pip._vendor.packaging.specifiers import SpecifierSet -from pip._vendor.packaging.utils import NormalizedName -from pip._vendor.packaging.version import Version +from pip._vendor.packaging.utils import NormalizedName, canonicalize_name +from pip._vendor.packaging.version import LegacyVersion, Version from pip._internal.models.link import Link, links_equivalent from pip._internal.req.req_install import InstallRequirement from pip._internal.utils.hashes import Hashes -CandidateLookup = tuple[Optional["Candidate"], Optional[InstallRequirement]] +CandidateLookup = Tuple[Optional["Candidate"], Optional[InstallRequirement]] +CandidateVersion = Union[LegacyVersion, Version] -def format_name(project: NormalizedName, extras: frozenset[NormalizedName]) -> str: +def format_name(project: str, extras: FrozenSet[str]) -> str: if not extras: return project - extras_expr = ",".join(sorted(extras)) - return f"{project}[{extras_expr}]" + canonical_extras = sorted(canonicalize_name(e) for e in extras) + return "{}[{}]".format(project, ",".join(canonical_extras)) -@dataclass(frozen=True) class Constraint: - specifier: SpecifierSet - hashes: Hashes - links: frozenset[Link] + def __init__( + self, specifier: SpecifierSet, hashes: Hashes, links: FrozenSet[Link] + ) -> None: + self.specifier = specifier + self.hashes = hashes + self.links = links @classmethod - def empty(cls) -> Constraint: + def empty(cls) -> "Constraint": return Constraint(SpecifierSet(), Hashes(), frozenset()) @classmethod - def from_ireq(cls, ireq: InstallRequirement) -> Constraint: + def from_ireq(cls, ireq: InstallRequirement) -> "Constraint": links = frozenset([ireq.link]) if ireq.link else frozenset() return Constraint(ireq.specifier, ireq.hashes(trust_internet=False), links) def __bool__(self) -> bool: return bool(self.specifier) or bool(self.hashes) or bool(self.links) - def __and__(self, other: InstallRequirement) -> Constraint: + def __and__(self, other: InstallRequirement) -> "Constraint": if not isinstance(other, InstallRequirement): return NotImplemented specifier = self.specifier & other.specifier @@ -50,7 +49,7 @@ def __and__(self, other: InstallRequirement) -> Constraint: links = links.union([other.link]) return Constraint(specifier, hashes, links) - def is_satisfied_by(self, candidate: Candidate) -> bool: + def is_satisfied_by(self, candidate: "Candidate") -> bool: # Reject if there are any mismatched URL constraints on this package. if self.links and not all(_match_link(link, candidate) for link in self.links): return False @@ -80,7 +79,7 @@ def name(self) -> str: """ raise NotImplementedError("Subclass should override") - def is_satisfied_by(self, candidate: Candidate) -> bool: + def is_satisfied_by(self, candidate: "Candidate") -> bool: return False def get_candidate_lookup(self) -> CandidateLookup: @@ -90,7 +89,7 @@ def format_for_error(self) -> str: raise NotImplementedError("Subclass should override") -def _match_link(link: Link, candidate: Candidate) -> bool: +def _match_link(link: Link, candidate: "Candidate") -> bool: if candidate.source_link: return links_equivalent(link, candidate.source_link) return False @@ -117,7 +116,7 @@ def name(self) -> str: raise NotImplementedError("Override in subclass") @property - def version(self) -> Version: + def version(self) -> CandidateVersion: raise NotImplementedError("Override in subclass") @property @@ -129,13 +128,13 @@ def is_editable(self) -> bool: raise NotImplementedError("Override in subclass") @property - def source_link(self) -> Link | None: + def source_link(self) -> Optional[Link]: raise NotImplementedError("Override in subclass") - def iter_dependencies(self, with_requires: bool) -> Iterable[Requirement | None]: + def iter_dependencies(self, with_requires: bool) -> Iterable[Optional[Requirement]]: raise NotImplementedError("Override in subclass") - def get_install_requirement(self) -> InstallRequirement | None: + def get_install_requirement(self) -> Optional[InstallRequirement]: raise NotImplementedError("Override in subclass") def format_for_error(self) -> str: diff --git a/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py b/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py index aa126d48..31020e27 100644 --- a/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py +++ b/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py @@ -1,21 +1,14 @@ -from __future__ import annotations - import logging import sys -from collections.abc import Iterable -from typing import TYPE_CHECKING, Any, Union, cast +from typing import TYPE_CHECKING, Any, FrozenSet, Iterable, Optional, Tuple, Union, cast -from pip._vendor.packaging.requirements import InvalidRequirement from pip._vendor.packaging.utils import NormalizedName, canonicalize_name from pip._vendor.packaging.version import Version from pip._internal.exceptions import ( - FailedToPrepareCandidate, HashError, InstallationSubprocessError, - InvalidInstalledPackage, MetadataInconsistent, - MetadataInvalid, ) from pip._internal.metadata import BaseDistribution from pip._internal.models.link import Link, links_equivalent @@ -28,7 +21,7 @@ from pip._internal.utils.direct_url_helpers import direct_url_from_link from pip._internal.utils.misc import normalize_version_info -from .base import Candidate, Requirement, format_name +from .base import Candidate, CandidateVersion, Requirement, format_name if TYPE_CHECKING: from .factory import Factory @@ -45,7 +38,7 @@ REQUIRES_PYTHON_IDENTIFIER = cast(NormalizedName, "") -def as_base_candidate(candidate: Candidate) -> BaseCandidate | None: +def as_base_candidate(candidate: Candidate) -> Optional[BaseCandidate]: """The runtime version of BaseCandidate.""" base_candidate_classes = ( AlreadyInstalledCandidate, @@ -69,8 +62,10 @@ def make_install_req_from_link( line, user_supplied=template.user_supplied, comes_from=template.comes_from, + use_pep517=template.use_pep517, isolated=template.isolated, constraint=template.constraint, + global_options=template.global_options, hash_options=template.hash_options, config_settings=template.config_settings, ) @@ -84,17 +79,15 @@ def make_install_req_from_editable( link: Link, template: InstallRequirement ) -> InstallRequirement: assert template.editable, "template not editable" - if template.name: - req_string = f"{template.name} @ {link.url}" - else: - req_string = link.url ireq = install_req_from_editable( - req_string, + link.url, user_supplied=template.user_supplied, comes_from=template.comes_from, + use_pep517=template.use_pep517, isolated=template.isolated, constraint=template.constraint, permit_editable_wheels=template.permit_editable_wheels, + global_options=template.global_options, hash_options=template.hash_options, config_settings=template.config_settings, ) @@ -115,8 +108,10 @@ def _make_install_req_from_dist( line, user_supplied=template.user_supplied, comes_from=template.comes_from, + use_pep517=template.use_pep517, isolated=template.isolated, constraint=template.constraint, + global_options=template.global_options, hash_options=template.hash_options, config_settings=template.config_settings, ) @@ -148,9 +143,9 @@ def __init__( link: Link, source_link: Link, ireq: InstallRequirement, - factory: Factory, - name: NormalizedName | None = None, - version: Version | None = None, + factory: "Factory", + name: Optional[NormalizedName] = None, + version: Optional[CandidateVersion] = None, ) -> None: self._link = link self._source_link = source_link @@ -159,20 +154,18 @@ def __init__( self._name = name self._version = version self.dist = self._prepare() - self._hash: int | None = None def __str__(self) -> str: return f"{self.name} {self.version}" def __repr__(self) -> str: - return f"{self.__class__.__name__}({str(self._link)!r})" + return "{class_name}({link!r})".format( + class_name=self.__class__.__name__, + link=str(self._link), + ) def __hash__(self) -> int: - if self._hash is not None: - return self._hash - - self._hash = hash((self.__class__, self._link)) - return self._hash + return hash((self.__class__, self._link)) def __eq__(self, other: Any) -> bool: if isinstance(other, self.__class__): @@ -180,7 +173,7 @@ def __eq__(self, other: Any) -> bool: return False @property - def source_link(self) -> Link | None: + def source_link(self) -> Optional[Link]: return self._source_link @property @@ -195,15 +188,16 @@ def name(self) -> str: return self.project_name @property - def version(self) -> Version: + def version(self) -> CandidateVersion: if self._version is None: self._version = self.dist.version return self._version def format_for_error(self) -> str: - return ( - f"{self.name} {self.version} " - f"(from {self._link.file_path if self._link.is_file else self._link})" + return "{} {} (from {})".format( + self.name, + self.version, + self._link.file_path if self._link.is_file else self._link, ) def _prepare_distribution(self) -> BaseDistribution: @@ -225,13 +219,6 @@ def _check_metadata_consistency(self, dist: BaseDistribution) -> None: str(self._version), str(dist.version), ) - # check dependencies are valid - # TODO performance: this means we iterate the dependencies at least twice, - # we may want to cache parsed Requires-Dist - try: - list(dist.iter_dependencies(list(dist.iter_provided_extras()))) - except InvalidRequirement as e: - raise MetadataInvalid(self._ireq, str(e)) def _prepare(self) -> BaseDistribution: try: @@ -243,32 +230,20 @@ def _prepare(self) -> BaseDistribution: e.req = self._ireq raise except InstallationSubprocessError as exc: - if isinstance(self._ireq.comes_from, InstallRequirement): - request_chain = self._ireq.comes_from.from_path() - else: - request_chain = self._ireq.comes_from - - if request_chain is None: - request_chain = "directly requested" - - raise FailedToPrepareCandidate( - package_name=self._ireq.name or str(self._link), - requirement_chain=request_chain, - failed_step=exc.command_description, - ) + # The output has been presented already, so don't duplicate it. + exc.context = "See above for output." + raise self._check_metadata_consistency(dist) return dist - def iter_dependencies(self, with_requires: bool) -> Iterable[Requirement | None]: - # Emit the Requires-Python requirement first to fail fast on - # unsupported candidates and avoid pointless downloads/preparation. - yield self._factory.make_requires_python_requirement(self.dist.requires_python) + def iter_dependencies(self, with_requires: bool) -> Iterable[Optional[Requirement]]: requires = self.dist.iter_dependencies() if with_requires else () for r in requires: - yield from self._factory.make_requirements_from_spec(str(r), self._ireq) + yield self._factory.make_requirement_from_spec(str(r), self._ireq) + yield self._factory.make_requires_python_requirement(self.dist.requires_python) - def get_install_requirement(self) -> InstallRequirement | None: + def get_install_requirement(self) -> Optional[InstallRequirement]: return self._ireq @@ -279,9 +254,9 @@ def __init__( self, link: Link, template: InstallRequirement, - factory: Factory, - name: NormalizedName | None = None, - version: Version | None = None, + factory: "Factory", + name: Optional[NormalizedName] = None, + version: Optional[CandidateVersion] = None, ) -> None: source_link = link cache_entry = factory.get_wheel_cache_entry(source_link, name) @@ -292,14 +267,14 @@ def __init__( assert ireq.link == link if ireq.link.is_wheel and not ireq.link.is_file: wheel = Wheel(ireq.link.filename) - wheel_name = wheel.name + wheel_name = canonicalize_name(wheel.name) assert name == wheel_name, f"{name!r} != {wheel_name!r} for wheel" # Version may not be present for PEP 508 direct URLs if version is not None: wheel_version = Version(wheel.version) - assert ( - version == wheel_version - ), f"{version!r} != {wheel_version!r} for wheel {name}" + assert version == wheel_version, "{!r} != {!r} for wheel {}".format( + version, wheel_version, name + ) if cache_entry is not None: assert ireq.link.is_wheel @@ -336,9 +311,9 @@ def __init__( self, link: Link, template: InstallRequirement, - factory: Factory, - name: NormalizedName | None = None, - version: Version | None = None, + factory: "Factory", + name: Optional[NormalizedName] = None, + version: Optional[CandidateVersion] = None, ) -> None: super().__init__( link=link, @@ -361,12 +336,11 @@ def __init__( self, dist: BaseDistribution, template: InstallRequirement, - factory: Factory, + factory: "Factory", ) -> None: self.dist = dist self._ireq = _make_install_req_from_dist(dist, template) self._factory = factory - self._version = None # This is just logging some messages, so we can do it eagerly. # The returned dist would be exactly the same as self.dist because we @@ -379,15 +353,18 @@ def __str__(self) -> str: return str(self.dist) def __repr__(self) -> str: - return f"{self.__class__.__name__}({self.dist!r})" - - def __eq__(self, other: object) -> bool: - if not isinstance(other, AlreadyInstalledCandidate): - return NotImplemented - return self.name == other.name and self.version == other.version + return "{class_name}({distribution!r})".format( + class_name=self.__class__.__name__, + distribution=self.dist, + ) def __hash__(self) -> int: - return hash((self.name, self.version)) + return hash((self.__class__, self.name, self.version)) + + def __eq__(self, other: Any) -> bool: + if isinstance(other, self.__class__): + return self.name == other.name and self.version == other.version + return False @property def project_name(self) -> NormalizedName: @@ -398,10 +375,8 @@ def name(self) -> str: return self.project_name @property - def version(self) -> Version: - if self._version is None: - self._version = self.dist.version - return self._version + def version(self) -> CandidateVersion: + return self.dist.version @property def is_editable(self) -> bool: @@ -410,17 +385,13 @@ def is_editable(self) -> bool: def format_for_error(self) -> str: return f"{self.name} {self.version} (Installed)" - def iter_dependencies(self, with_requires: bool) -> Iterable[Requirement | None]: + def iter_dependencies(self, with_requires: bool) -> Iterable[Optional[Requirement]]: if not with_requires: return + for r in self.dist.iter_dependencies(): + yield self._factory.make_requirement_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) -> InstallRequirement | None: + def get_install_requirement(self) -> Optional[InstallRequirement]: return None @@ -452,28 +423,21 @@ class ExtrasCandidate(Candidate): def __init__( self, base: BaseCandidate, - extras: frozenset[str], - *, - comes_from: InstallRequirement | None = None, + extras: FrozenSet[str], ) -> None: - """ - :param comes_from: the InstallRequirement that led to this candidate if it - differs from the base's InstallRequirement. This will often be the - case in the sense that this candidate's requirement has the extras - while the base's does not. Unlike the InstallRequirement backed - candidates, this requirement is used solely for reporting purposes, - it does not do any leg work. - """ self.base = base - self.extras = frozenset(canonicalize_name(e) for e in extras) - self._comes_from = comes_from if comes_from is not None else self.base._ireq + self.extras = extras def __str__(self) -> str: name, rest = str(self.base).split(" ", 1) return "{}[{}] {}".format(name, ",".join(self.extras), rest) def __repr__(self) -> str: - return f"{self.__class__.__name__}(base={self.base!r}, extras={self.extras!r})" + return "{class_name}(base={base!r}, extras={extras!r})".format( + class_name=self.__class__.__name__, + base=self.base, + extras=self.extras, + ) def __hash__(self) -> int: return hash((self.base, self.extras)) @@ -493,7 +457,7 @@ def name(self) -> str: return format_name(self.base.project_name, self.extras) @property - def version(self) -> Version: + def version(self) -> CandidateVersion: return self.base.version def format_for_error(self) -> str: @@ -510,10 +474,10 @@ def is_editable(self) -> bool: return self.base.is_editable @property - def source_link(self) -> Link | None: + def source_link(self) -> Optional[Link]: return self.base.source_link - def iter_dependencies(self, with_requires: bool) -> Iterable[Requirement | None]: + def iter_dependencies(self, with_requires: bool) -> Iterable[Optional[Requirement]]: factory = self.base._factory # Add a dependency on the exact base @@ -535,13 +499,13 @@ def iter_dependencies(self, with_requires: bool) -> Iterable[Requirement | None] ) for r in self.base.dist.iter_dependencies(valid_extras): - yield from factory.make_requirements_from_spec( - str(r), - self._comes_from, - valid_extras, + requirement = factory.make_requirement_from_spec( + str(r), self.base._ireq, valid_extras ) + if requirement: + yield requirement - def get_install_requirement(self) -> InstallRequirement | None: + def get_install_requirement(self) -> Optional[InstallRequirement]: # We don't return anything here, because we always # depend on the base candidate, and we'll get the # install requirement from that. @@ -552,7 +516,7 @@ class RequiresPythonCandidate(Candidate): is_installed = False source_link = None - def __init__(self, py_version_info: tuple[int, ...] | None) -> None: + def __init__(self, py_version_info: Optional[Tuple[int, ...]]) -> None: if py_version_info is not None: version_info = normalize_version_info(py_version_info) else: @@ -566,9 +530,6 @@ def __init__(self, py_version_info: tuple[int, ...] | None) -> None: def __str__(self) -> str: return f"Python {self._version}" - def __repr__(self) -> str: - return f"{self.__class__.__name__}({self._version!r})" - @property def project_name(self) -> NormalizedName: return REQUIRES_PYTHON_IDENTIFIER @@ -578,14 +539,14 @@ def name(self) -> str: return REQUIRES_PYTHON_IDENTIFIER @property - def version(self) -> Version: + def version(self) -> CandidateVersion: return self._version def format_for_error(self) -> str: return f"Python {self.version}" - def iter_dependencies(self, with_requires: bool) -> Iterable[Requirement | None]: + def iter_dependencies(self, with_requires: bool) -> Iterable[Optional[Requirement]]: return () - def get_install_requirement(self) -> InstallRequirement | None: + def get_install_requirement(self) -> Optional[InstallRequirement]: return None diff --git a/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py b/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py index 07be5693..0331297b 100644 --- a/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py +++ b/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py @@ -1,14 +1,19 @@ -from __future__ import annotations - import contextlib import functools import logging -from collections.abc import Iterable, Iterator, Mapping, Sequence from typing import ( TYPE_CHECKING, - Callable, + Dict, + FrozenSet, + Iterable, + Iterator, + List, + Mapping, NamedTuple, - Protocol, + Optional, + Sequence, + Set, + Tuple, TypeVar, cast, ) @@ -16,16 +21,13 @@ 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 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, UnsupportedWheel, ) @@ -34,10 +36,7 @@ from pip._internal.models.link import Link from pip._internal.models.wheel import Wheel from pip._internal.operations.prepare import RequirementPreparer -from pip._internal.req.constructors import ( - install_req_drop_extras, - install_req_from_link_and_ireq, -) +from pip._internal.req.constructors import install_req_from_link_and_ireq from pip._internal.req.req_install import ( InstallRequirement, check_invalid_constraint_type, @@ -48,7 +47,7 @@ from pip._internal.utils.packaging import get_requirement from pip._internal.utils.virtualenv import running_under_virtualenv -from .base import Candidate, Constraint, Requirement +from .base import Candidate, CandidateVersion, Constraint, Requirement from .candidates import ( AlreadyInstalledCandidate, BaseCandidate, @@ -63,11 +62,11 @@ ExplicitRequirement, RequiresPythonRequirement, SpecifierRequirement, - SpecifierWithoutExtrasRequirement, UnsatisfiableRequirement, ) if TYPE_CHECKING: + from typing import Protocol class ConflictCause(Protocol): requirement: RequiresPythonRequirement @@ -77,13 +76,13 @@ class ConflictCause(Protocol): logger = logging.getLogger(__name__) C = TypeVar("C") -Cache = dict[Link, C] +Cache = Dict[Link, C] class CollectedRootRequirements(NamedTuple): - requirements: list[Requirement] - constraints: dict[str, Constraint] - user_requested: dict[str, int] + requirements: List[Requirement] + constraints: Dict[str, Constraint] + user_requested: Dict[str, int] class Factory: @@ -92,12 +91,12 @@ def __init__( finder: PackageFinder, preparer: RequirementPreparer, make_install_req: InstallRequirementProvider, - wheel_cache: WheelCache | None, + wheel_cache: Optional[WheelCache], use_user_site: bool, force_reinstall: bool, ignore_installed: bool, ignore_requires_python: bool, - py_version_info: tuple[int, ...] | None = None, + py_version_info: Optional[Tuple[int, ...]] = None, ) -> None: self._finder = finder self.preparer = preparer @@ -111,11 +110,10 @@ def __init__( self._build_failures: Cache[InstallationError] = {} self._link_candidate_cache: Cache[LinkCandidate] = {} self._editable_candidate_cache: Cache[EditableCandidate] = {} - self._installed_candidate_cache: dict[str, AlreadyInstalledCandidate] = {} - self._extras_candidate_cache: dict[ - tuple[int, frozenset[NormalizedName]], ExtrasCandidate + self._installed_candidate_cache: Dict[str, AlreadyInstalledCandidate] = {} + self._extras_candidate_cache: Dict[ + Tuple[int, FrozenSet[str]], ExtrasCandidate ] = {} - self._supported_tags_cache = get_supported() if not ignore_installed: env = get_default_environment() @@ -134,30 +132,26 @@ def _fail_if_link_is_unsupported_wheel(self, link: Link) -> None: if not link.is_wheel: return wheel = Wheel(link.filename) - if wheel.supported(self._finder.target_python.get_unsorted_tags()): + if wheel.supported(self._finder.target_python.get_tags()): return msg = f"{link.filename} is not a supported wheel on this platform." raise UnsupportedWheel(msg) def _make_extras_candidate( - self, - base: BaseCandidate, - extras: frozenset[str], - *, - comes_from: InstallRequirement | None = None, + self, base: BaseCandidate, extras: FrozenSet[str] ) -> ExtrasCandidate: - cache_key = (id(base), frozenset(canonicalize_name(e) for e in extras)) + cache_key = (id(base), extras) try: candidate = self._extras_candidate_cache[cache_key] except KeyError: - candidate = ExtrasCandidate(base, extras, comes_from=comes_from) + candidate = ExtrasCandidate(base, extras) self._extras_candidate_cache[cache_key] = candidate return candidate def _make_candidate_from_dist( self, dist: BaseDistribution, - extras: frozenset[str], + extras: FrozenSet[str], template: InstallRequirement, ) -> Candidate: try: @@ -167,30 +161,16 @@ def _make_candidate_from_dist( self._installed_candidate_cache[dist.canonical_name] = base if not extras: return base - return self._make_extras_candidate(base, extras, comes_from=template) + return self._make_extras_candidate(base, extras) def _make_candidate_from_link( self, link: Link, - extras: frozenset[str], - template: InstallRequirement, - name: NormalizedName | None, - version: Version | None, - ) -> Candidate | None: - base: BaseCandidate | None = self._make_base_candidate_from_link( - link, template, name, version - ) - if not extras or base is None: - return base - return self._make_extras_candidate(base, extras, comes_from=template) - - def _make_base_candidate_from_link( - self, - link: Link, + extras: FrozenSet[str], template: InstallRequirement, - name: NormalizedName | None, - version: Version | None, - ) -> BaseCandidate | None: + name: Optional[NormalizedName], + version: Optional[CandidateVersion], + ) -> Optional[Candidate]: # TODO: Check already installed candidate, and use it if the link and # editable flag match. @@ -209,7 +189,7 @@ def _make_base_candidate_from_link( name=name, version=version, ) - except (MetadataInconsistent, MetadataInvalid) as e: + except MetadataInconsistent as e: logger.info( "Discarding [blue underline]%s[/]: [yellow]%s[reset]", link, @@ -219,7 +199,7 @@ def _make_base_candidate_from_link( self._build_failures[link] = e return None - return self._editable_candidate_cache[link] + base: BaseCandidate = self._editable_candidate_cache[link] else: if link not in self._link_candidate_cache: try: @@ -239,7 +219,11 @@ def _make_base_candidate_from_link( ) self._build_failures[link] = e return None - return self._link_candidate_cache[link] + base = self._link_candidate_cache[link] + + if not extras: + return base + return self._make_extras_candidate(base, extras) def _iter_found_candidates( self, @@ -247,7 +231,7 @@ def _iter_found_candidates( specifier: SpecifierSet, hashes: Hashes, prefers_installed: bool, - incompatible_ids: set[int], + incompatible_ids: Set[int], ) -> Iterable[Candidate]: if not ireqs: return () @@ -260,14 +244,14 @@ def _iter_found_candidates( assert template.req, "Candidates found on index must be PEP 508" name = canonicalize_name(template.req.name) - extras: frozenset[str] = frozenset() + extras: FrozenSet[str] = frozenset() for ireq in ireqs: assert ireq.req, "Candidates found on index must be PEP 508" specifier &= ireq.req.specifier hashes &= ireq.hashes(trust_internet=False) extras |= frozenset(ireq.extras) - def _get_installed_candidate() -> Candidate | None: + def _get_installed_candidate() -> Optional[Candidate]: """Get the candidate for the currently-installed version.""" # If --force-reinstall is set, we want the version from the index # instead, so we "pretend" there is nothing installed. @@ -277,15 +261,10 @@ def _get_installed_candidate() -> Candidate | None: installed_dist = self._installed_dists[name] except KeyError: 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) - + # 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 candidate = self._make_candidate_from_dist( dist=installed_dist, extras=extras, @@ -302,7 +281,7 @@ def iter_index_candidate_infos() -> Iterator[IndexCandidateInfo]: specifier=specifier, hashes=hashes, ) - icans = result.applicable_candidates + icans = list(result.iter_applicable()) # PEP 592: Yanked releases are ignored unless the specifier # explicitly pins a version (via '==' or '===') that can be @@ -346,7 +325,7 @@ def is_pinned(specifier: SpecifierSet) -> bool: def _iter_explicit_candidates_from_base( self, base_requirements: Iterable[Requirement], - extras: frozenset[str], + extras: FrozenSet[str], ) -> Iterator[Candidate]: """Produce explicit candidates from the base given an extra-ed package. @@ -378,8 +357,9 @@ def _iter_candidates_from_constraints( """ for link in constraint.links: self._fail_if_link_is_unsupported_wheel(link) - candidate = self._make_base_candidate_from_link( + candidate = self._make_candidate_from_link( link, + extras=frozenset(), template=install_req_from_link_and_ireq(link, template), name=canonicalize_name(identifier), version=None, @@ -394,11 +374,10 @@ def find_candidates( incompatibilities: Mapping[str, Iterator[Candidate]], constraint: Constraint, prefers_installed: bool, - is_satisfied_by: Callable[[Requirement, Candidate], bool], ) -> Iterable[Candidate]: # Collect basic lookup information from the requirements. - explicit_candidates: set[Candidate] = set() - ireqs: list[InstallRequirement] = [] + explicit_candidates: Set[Candidate] = set() + ireqs: List[InstallRequirement] = [] for req in requirements[identifier]: cand, ireq = req.get_candidate_lookup() if cand is not None: @@ -406,21 +385,16 @@ def find_candidates( if ireq is not None: ireqs.append(ireq) - # If the current identifier contains extras, add requires and explicit - # candidates from entries from extra-less identifier. + # If the current identifier contains extras, add explicit candidates + # from entries from extra-less identifier. with contextlib.suppress(InvalidRequirement): parsed_requirement = get_requirement(identifier) - if parsed_requirement.name != identifier: - explicit_candidates.update( - self._iter_explicit_candidates_from_base( - requirements.get(parsed_requirement.name, ()), - frozenset(parsed_requirement.extras), - ), - ) - for req in requirements.get(parsed_requirement.name, []): - _, ireq = req.get_candidate_lookup() - if ireq is not None: - ireqs.append(ireq) + explicit_candidates.update( + self._iter_explicit_candidates_from_base( + requirements.get(parsed_requirement.name, ()), + frozenset(parsed_requirement.extras), + ), + ) # Add explicit candidates from constraints. We only do this if there are # known ireqs, which represent requirements not already explicit. If @@ -460,64 +434,43 @@ def find_candidates( for c in explicit_candidates if id(c) not in incompat_ids and constraint.is_satisfied_by(c) - and all(is_satisfied_by(req, c) for req in requirements[identifier]) + and all(req.is_satisfied_by(c) for req in requirements[identifier]) ) - def _make_requirements_from_install_req( + def _make_requirement_from_install_req( self, ireq: InstallRequirement, requested_extras: Iterable[str] - ) -> Iterator[Requirement]: - """ - Returns requirement objects associated with the given InstallRequirement. In - most cases this will be a single object but the following special cases exist: - - the InstallRequirement has markers that do not apply -> result is empty - - the InstallRequirement has both a constraint (or link) and extras - -> result is split in two requirement objects: one with the constraint - (or link) and one with the extra. This allows centralized constraint - handling for the base, resulting in fewer candidate rejections. - """ + ) -> Optional[Requirement]: if not ireq.match_markers(requested_extras): logger.info( "Ignoring %s: markers '%s' don't match your environment", ireq.name, ireq.markers, ) - elif not ireq.link: - if ireq.extras and ireq.req is not None and ireq.req.specifier: - yield SpecifierWithoutExtrasRequirement(ireq) - yield SpecifierRequirement(ireq) - else: - self._fail_if_link_is_unsupported_wheel(ireq.link) - # Always make the link candidate for the base requirement to make it - # available to `find_candidates` for explicit candidate lookup for any - # set of extras. - # The extras are required separately via a second requirement. - cand = self._make_base_candidate_from_link( - ireq.link, - template=install_req_drop_extras(ireq) if ireq.extras else ireq, - name=canonicalize_name(ireq.name) if ireq.name else None, - version=None, - ) - if cand is None: - # There's no way we can satisfy a URL requirement if the underlying - # candidate fails to build. An unnamed URL must be user-supplied, so - # we fail eagerly. If the URL is named, an unsatisfiable requirement - # can make the resolver do the right thing, either backtrack (and - # maybe find some other requirement that's buildable) or raise a - # ResolutionImpossible eventually. - if not ireq.name: - raise self._build_failures[ireq.link] - yield UnsatisfiableRequirement(canonicalize_name(ireq.name)) - else: - # require the base from the link - yield self.make_requirement_from_candidate(cand) - if ireq.extras: - # require the extras on top of the base candidate - yield self.make_requirement_from_candidate( - self._make_extras_candidate(cand, frozenset(ireq.extras)) - ) + return None + if not ireq.link: + return SpecifierRequirement(ireq) + self._fail_if_link_is_unsupported_wheel(ireq.link) + cand = self._make_candidate_from_link( + ireq.link, + extras=frozenset(ireq.extras), + template=ireq, + name=canonicalize_name(ireq.name) if ireq.name else None, + version=None, + ) + if cand is None: + # There's no way we can satisfy a URL requirement if the underlying + # candidate fails to build. An unnamed URL must be user-supplied, so + # we fail eagerly. If the URL is named, an unsatisfiable requirement + # can make the resolver do the right thing, either backtrack (and + # maybe find some other requirement that's buildable) or raise a + # ResolutionImpossible eventually. + if not ireq.name: + raise self._build_failures[ireq.link] + return UnsatisfiableRequirement(canonicalize_name(ireq.name)) + return self.make_requirement_from_candidate(cand) def collect_root_requirements( - self, root_ireqs: list[InstallRequirement] + self, root_ireqs: List[InstallRequirement] ) -> CollectedRootRequirements: collected = CollectedRootRequirements([], {}, {}) for i, ireq in enumerate(root_ireqs): @@ -535,27 +488,15 @@ def collect_root_requirements( else: collected.constraints[name] = Constraint.from_ireq(ireq) else: - reqs = list( - self._make_requirements_from_install_req( - ireq, - requested_extras=(), - ) + req = self._make_requirement_from_install_req( + ireq, + requested_extras=(), ) - if not reqs: + if req is None: continue - template = reqs[0] - if ireq.user_supplied and template.name not in collected.user_requested: - collected.user_requested[template.name] = i - collected.requirements.extend(reqs) - # Put requirements with extras at the end of the root requires. This does not - # affect resolvelib's picking preference but it does affect its initial criteria - # population: by putting extras at the end we enable the candidate finder to - # present resolvelib with a smaller set of candidates to resolvelib, already - # taking into account any non-transient constraints on the associated base. This - # means resolvelib will have fewer candidates to visit and reject. - # Python's list sort is stable, meaning relative order is kept for objects with - # the same key. - collected.requirements.sort(key=lambda r: r.name != r.project_name) + if ireq.user_supplied and req.name not in collected.user_requested: + collected.user_requested[req.name] = i + collected.requirements.append(req) return collected def make_requirement_from_candidate( @@ -563,28 +504,19 @@ def make_requirement_from_candidate( ) -> ExplicitRequirement: return ExplicitRequirement(candidate) - def make_requirements_from_spec( + def make_requirement_from_spec( self, specifier: str, - comes_from: InstallRequirement | None, + comes_from: Optional[InstallRequirement], requested_extras: Iterable[str] = (), - ) -> Iterator[Requirement]: - """ - Returns requirement objects associated with the given specifier. In most cases - this will be a single object but the following special cases exist: - - the specifier has markers that do not apply -> result is empty - - the specifier has both a constraint and extras -> result is split - in two requirement objects: one with the constraint and one with the - extra. This allows centralized constraint handling for the base, - resulting in fewer candidate rejections. - """ + ) -> Optional[Requirement]: ireq = self._make_install_req_from_spec(specifier, comes_from) - return self._make_requirements_from_install_req(ireq, requested_extras) + return self._make_requirement_from_install_req(ireq, requested_extras) def make_requires_python_requirement( self, specifier: SpecifierSet, - ) -> Requirement | None: + ) -> Optional[Requirement]: if self._ignore_requires_python: return None # Don't bother creating a dependency for an empty Requires-Python. @@ -592,7 +524,9 @@ def make_requires_python_requirement( return None return RequiresPythonRequirement(specifier, self._python_candidate) - def get_wheel_cache_entry(self, link: Link, name: str | None) -> CacheEntry | None: + def get_wheel_cache_entry( + self, link: Link, name: Optional[str] + ) -> Optional[CacheEntry]: """Look up the link in the wheel cache. If ``preparer.require_hashes`` is True, don't use the wheel cache, @@ -606,10 +540,10 @@ def get_wheel_cache_entry(self, link: Link, name: str | None) -> CacheEntry | No return self._wheel_cache.get_cache_entry( link=link, package_name=name, - supported_tags=self._supported_tags_cache, + supported_tags=get_supported(), ) - def get_dist_to_uninstall(self, candidate: Candidate) -> BaseDistribution | None: + def get_dist_to_uninstall(self, candidate: Candidate) -> Optional[BaseDistribution]: # TODO: Are there more cases this needs to return True? Editable? dist = self._installed_dists.get(candidate.project_name) if dist is None: # Not installed, no uninstallation required. @@ -638,7 +572,7 @@ def get_dist_to_uninstall(self, candidate: Candidate) -> BaseDistribution | None return None def _report_requires_python_error( - self, causes: Sequence[ConflictCause] + self, causes: Sequence["ConflictCause"] ) -> UnsupportedPythonVersion: assert causes, "Requires-Python error reported with no cause" @@ -660,7 +594,7 @@ def _report_requires_python_error( return UnsupportedPythonVersion(message) def _report_single_requirement_conflict( - self, req: Requirement, parent: Candidate | None + self, req: Requirement, parent: Optional[Candidate] ) -> DistributionNotFound: if parent is None: req_disp = str(req) @@ -669,26 +603,8 @@ def _report_single_requirement_conflict( cands = self._finder.find_all_candidates(req.project_name) skipped_by_requires_python = self._finder.requires_python_skipped_reasons() + versions = [str(v) for v in sorted({c.version for c in cands})] - versions_set: set[Version] = set() - yanked_versions_set: set[Version] = set() - for c in cands: - is_yanked = c.link.is_yanked if c.link else False - if is_yanked: - yanked_versions_set.add(c.version) - else: - versions_set.add(c.version) - - versions = [str(v) for v in sorted(versions_set)] - yanked_versions = [str(v) for v in sorted(yanked_versions_set)] - - if yanked_versions: - # Saying "version X is yanked" isn't entirely accurate. - # https://github.com/pypa/pip/issues/11745#issuecomment-1402805842 - logger.critical( - "Ignored the following yanked versions: %s", - ", ".join(yanked_versions) or "none", - ) if skipped_by_requires_python: logger.critical( "Ignored the following versions that require a different python " @@ -711,25 +627,10 @@ def _report_single_requirement_conflict( return DistributionNotFound(f"No matching distribution found for {req}") - def _has_any_candidates(self, project_name: str) -> bool: - """ - Check if there are any candidates available for the project name. - """ - return any( - self.find_candidates( - project_name, - requirements={project_name: []}, - incompatibilities={}, - constraint=Constraint.empty(), - prefers_installed=True, - is_satisfied_by=lambda r, c: True, - ) - ) - def get_installation_error( self, - e: ResolutionImpossible[Requirement, Candidate], - constraints: dict[str, Constraint], + e: "ResolutionImpossible[Requirement, Candidate]", + constraints: Dict[str, Constraint], ) -> InstallationError: assert e.causes, "Installation error reported with no cause" @@ -754,7 +655,7 @@ def get_installation_error( # The simplest case is when we have *one* cause that can't be # satisfied. We just report that case. if len(e.causes) == 1: - req, parent = next(iter(e.causes)) + req, parent = e.causes[0] if req.name not in constraints: return self._report_single_requirement_conflict(req, parent) @@ -762,7 +663,7 @@ def get_installation_error( # satisfied at once. # A couple of formatting helpers - def text_join(parts: list[str]) -> str: + def text_join(parts: List[str]) -> str: if len(parts) == 1: return parts[0] @@ -791,8 +692,8 @@ def describe_trigger(parent: Candidate) -> str: info = "the requested packages" msg = ( - f"Cannot install {info} because these package versions " - "have conflicting dependencies." + "Cannot install {} because these package versions " + "have conflicting dependencies.".format(info) ) logger.critical(msg) msg = "\nThe conflict is caused by:" @@ -811,28 +712,12 @@ def describe_trigger(parent: Candidate) -> str: spec = constraints[key].specifier msg += f"\n The user requested (constraint) {key}{spec}" - # Check for causes that had no candidates - causes = set() - for req, _ in e.causes: - causes.add(req.name) - - no_candidates = {c for c in causes if not self._has_any_candidates(c)} - if no_candidates: - msg = ( - msg - + "\n\n" - + "Additionally, some packages in these conflicts have no " - + "matching distributions available for your environment:" - + "\n " - + "\n ".join(sorted(no_candidates)) - ) - msg = ( msg + "\n\n" + "To fix this you could try to:\n" + "1. loosen the range of package versions you've specified\n" - + "2. remove package versions to allow pip to attempt to solve " + + "2. remove package versions to allow pip attempt to solve " + "the dependency conflict\n" ) diff --git a/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py b/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py index f60653d2..8663097b 100644 --- a/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py +++ b/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py @@ -8,21 +8,30 @@ something. """ -from __future__ import annotations - -import logging -from collections.abc import Iterator, Sequence -from typing import Any, Callable, Optional +import functools +from collections.abc import Sequence +from typing import TYPE_CHECKING, Any, Callable, Iterator, Optional, Set, Tuple from pip._vendor.packaging.version import _BaseVersion -from pip._internal.exceptions import MetadataInvalid - from .base import Candidate -logger = logging.getLogger(__name__) +IndexCandidateInfo = Tuple[_BaseVersion, Callable[[], Optional[Candidate]]] -IndexCandidateInfo = tuple[_BaseVersion, Callable[[], Optional[Candidate]]] +if TYPE_CHECKING: + SequenceCandidate = Sequence[Candidate] +else: + # For compatibility: Python before 3.9 does not support using [] on the + # Sequence class. + # + # >>> from collections.abc import Sequence + # >>> Sequence[str] + # Traceback (most recent call last): + # File "", line 1, in + # TypeError: 'ABCMeta' object is not subscriptable + # + # TODO: Remove this block after dropping Python 3.8 support. + SequenceCandidate = Sequence def _iter_built(infos: Iterator[IndexCandidateInfo]) -> Iterator[Candidate]: @@ -31,29 +40,15 @@ def _iter_built(infos: Iterator[IndexCandidateInfo]) -> Iterator[Candidate]: This iterator is used when the package is not already installed. Candidates from index come later in their normal ordering. """ - versions_found: set[_BaseVersion] = set() + versions_found: Set[_BaseVersion] = set() for version, func in infos: if version in versions_found: continue - try: - candidate = func() - except MetadataInvalid as e: - logger.warning( - "Ignoring version %s of %s since it has invalid metadata:\n" - "%s\n" - "Please use pip<24.1 if you need to use this version.", - version, - e.ireq.name, - e, - ) - # Mark version as found to avoid trying other candidates with the same - # version, since they most likely have invalid metadata as well. - versions_found.add(version) - else: - if candidate is None: - continue - yield candidate - versions_found.add(version) + candidate = func() + if candidate is None: + continue + yield candidate + versions_found.add(version) def _iter_built_with_prepended( @@ -67,7 +62,7 @@ def _iter_built_with_prepended( normal ordering, except skipped when the version is already installed. """ yield installed - versions_found: set[_BaseVersion] = {installed.version} + versions_found: Set[_BaseVersion] = {installed.version} for version, func in infos: if version in versions_found: continue @@ -91,7 +86,7 @@ def _iter_built_with_inserted( the installed candidate exactly once before we start yielding older or equivalent candidates, or after all other candidates if they are all newer. """ - versions_found: set[_BaseVersion] = set() + versions_found: Set[_BaseVersion] = set() for version, func in infos: if version in versions_found: continue @@ -110,7 +105,7 @@ def _iter_built_with_inserted( yield installed -class FoundCandidates(Sequence[Candidate]): +class FoundCandidates(SequenceCandidate): """A lazy sequence to provide candidates to the resolver. The intended usage is to return this from `find_matches()` so the resolver @@ -122,15 +117,14 @@ class FoundCandidates(Sequence[Candidate]): def __init__( self, get_infos: Callable[[], Iterator[IndexCandidateInfo]], - installed: Candidate | None, + installed: Optional[Candidate], prefers_installed: bool, - incompatible_ids: set[int], + incompatible_ids: Set[int], ): self._get_infos = get_infos self._installed = installed self._prefers_installed = prefers_installed self._incompatible_ids = incompatible_ids - self._bool: bool | None = None def __getitem__(self, index: Any) -> Any: # Implemented to satisfy the ABC check. This is not needed by the @@ -154,13 +148,8 @@ def __len__(self) -> int: # performance reasons). raise NotImplementedError("don't do this") + @functools.lru_cache(maxsize=1) def __bool__(self) -> bool: - if self._bool is not None: - return self._bool - if self._prefers_installed and self._installed: - self._bool = True return True - - self._bool = any(self) - return self._bool + return any(self) diff --git a/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/provider.py b/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/provider.py index 994748db..315fb9c8 100644 --- a/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/provider.py +++ b/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/provider.py @@ -1,21 +1,21 @@ -from __future__ import annotations - +import collections import math -from collections.abc import Iterable, Iterator, Mapping, Sequence -from functools import cache from typing import ( TYPE_CHECKING, + Dict, + Iterable, + Iterator, + Mapping, + Sequence, TypeVar, + Union, ) from pip._vendor.resolvelib.providers import AbstractProvider -from pip._internal.req.req_install import InstallRequirement - from .base import Candidate, Constraint, Requirement from .candidates import REQUIRES_PYTHON_IDENTIFIER from .factory import Factory -from .requirements import ExplicitRequirement if TYPE_CHECKING: from pip._vendor.resolvelib.providers import Preference @@ -54,7 +54,7 @@ def _get_with_identifier( mapping: Mapping[str, V], identifier: str, default: D, -) -> D | V: +) -> Union[D, V]: """Get item from a package name lookup mapping with a resolver identifier. This extra logic is needed when the target mapping is keyed by package @@ -89,80 +89,29 @@ class PipProvider(_ProviderBase): def __init__( self, factory: Factory, - constraints: dict[str, Constraint], + constraints: Dict[str, Constraint], ignore_dependencies: bool, upgrade_strategy: str, - user_requested: dict[str, int], + user_requested: Dict[str, int], ) -> None: self._factory = factory self._constraints = constraints self._ignore_dependencies = ignore_dependencies self._upgrade_strategy = upgrade_strategy self._user_requested = user_requested + self._known_depths: Dict[str, float] = collections.defaultdict(lambda: math.inf) - @property - def constraints(self) -> dict[str, Constraint]: - """Public view of user-specified constraints. - - Exposes the provider's constraints mapping without encouraging - external callers to reach into private attributes. - """ - return self._constraints - - def identify(self, requirement_or_candidate: Requirement | Candidate) -> str: + def identify(self, requirement_or_candidate: Union[Requirement, Candidate]) -> str: return requirement_or_candidate.name - def narrow_requirement_selection( - self, - identifiers: Iterable[str], - resolutions: Mapping[str, Candidate], - candidates: Mapping[str, Iterator[Candidate]], - information: Mapping[str, Iterator[PreferenceInformation]], - backtrack_causes: Sequence[PreferenceInformation], - ) -> Iterable[str]: - """Produce a subset of identifiers that should be considered before others. - - Currently pip narrows the following selection: - * Requires-Python, if present is always returned by itself - * Backtrack causes are considered next because they can be identified - in linear time here, whereas because get_preference() is called - for each identifier, it would be quadratic to check for them there. - Further, the current backtrack causes likely need to be resolved - before other requirements as a resolution can't be found while - there is a conflict. - """ - backtrack_identifiers = set() - for info in backtrack_causes: - backtrack_identifiers.add(info.requirement.name) - if info.parent is not None: - backtrack_identifiers.add(info.parent.name) - - current_backtrack_causes = [] - for identifier in identifiers: - # Requires-Python has only one candidate and the check is basically - # free, so we always do it first to avoid needless work if it fails. - # This skips calling get_preference() for all other identifiers. - if identifier == REQUIRES_PYTHON_IDENTIFIER: - return [identifier] - - # Check if this identifier is a backtrack cause - if identifier in backtrack_identifiers: - current_backtrack_causes.append(identifier) - continue - - if current_backtrack_causes: - return current_backtrack_causes - - return identifiers - def get_preference( self, identifier: str, resolutions: Mapping[str, Candidate], candidates: Mapping[str, Iterator[Candidate]], - information: Mapping[str, Iterable[PreferenceInformation]], - backtrack_causes: Sequence[PreferenceInformation], - ) -> Preference: + information: Mapping[str, Iterable["PreferenceInformation"]], + backtrack_causes: Sequence["PreferenceInformation"], + ) -> "Preference": """Produce a sort key for given requirement based on preference. The lower the return value is, the more preferred this group of @@ -170,20 +119,18 @@ def get_preference( Currently pip considers the following in order: - * Any requirement that is "direct", e.g., points to an explicit URL. - * Any requirement that is "pinned", i.e., contains the operator ``===`` - or ``==`` without a wildcard. - * Any requirement that imposes an upper version limit, i.e., contains the - operator ``<``, ``<=``, ``~=``, or ``==`` with a wildcard. Because - pip prioritizes the latest version, preferring explicit upper bounds - can rule out infeasible candidates sooner. This does not imply that - upper bounds are good practice; they can make dependency management - and resolution harder. - * Order user-specified requirements as they are specified, placing - other requirements afterward. - * Any "non-free" requirement, i.e., one that contains at least one - operator, such as ``>=`` or ``!=``. - * Alphabetical order for consistency (aids debuggability). + * Prefer if any of the known requirements is "direct", e.g. points to an + explicit URL. + * If equal, prefer if any requirement is "pinned", i.e. contains + operator ``===`` or ``==``. + * If equal, calculate an approximate "depth" and resolve requirements + closer to the user-specified requirements first. If the depth cannot + by determined (eg: due to no matching parents), it is considered + infinite. + * Order user-specified requirements by the order they are specified. + * If equal, prefers "non-free" requirements, i.e. contains at least one + operator, such as ``>=`` or ``<``. + * If equal, order alphabetically for consistency (helps debuggability). """ try: next(iter(information[identifier])) @@ -194,39 +141,55 @@ def get_preference( else: has_information = True - if not has_information: - direct = False - ireqs: tuple[InstallRequirement | None, ...] = () + if has_information: + lookups = (r.get_candidate_lookup() for r, _ in information[identifier]) + candidate, ireqs = zip(*lookups) else: - # Go through the information and for each requirement, - # check if it's explicit (e.g., a direct link) and get the - # InstallRequirement (the second element) from get_candidate_lookup() - directs, ireqs = zip( - *( - (isinstance(r, ExplicitRequirement), r.get_candidate_lookup()[1]) - for r, _ in information[identifier] - ) - ) - direct = any(directs) + candidate, ireqs = None, () - operators: list[tuple[str, str]] = [ - (specifier.operator, specifier.version) + operators = [ + specifier.operator for specifier_set in (ireq.specifier for ireq in ireqs if ireq) for specifier in specifier_set ] - pinned = any(((op[:2] == "==") and ("*" not in ver)) for op, ver in operators) - upper_bounded = any( - ((op in ("<", "<=", "~=")) or (op == "==" and "*" in ver)) - for op, ver in operators - ) + direct = candidate is not None + pinned = any(op[:2] == "==" for op in operators) unfree = bool(operators) + + try: + requested_order: Union[int, float] = self._user_requested[identifier] + except KeyError: + requested_order = math.inf + if has_information: + parent_depths = ( + self._known_depths[parent.name] if parent is not None else 0.0 + for _, parent in information[identifier] + ) + inferred_depth = min(d for d in parent_depths) + 1.0 + else: + inferred_depth = math.inf + else: + inferred_depth = 1.0 + self._known_depths[identifier] = inferred_depth + requested_order = self._user_requested.get(identifier, math.inf) + # Requires-Python has only one candidate and the check is basically + # free, so we always do it first to avoid needless work if it fails. + requires_python = identifier == REQUIRES_PYTHON_IDENTIFIER + + # Prefer the causes of backtracking on the assumption that the problem + # resolving the dependency tree is related to the failures that caused + # the backtracking + backtrack_cause = self.is_backtrack_cause(identifier, backtrack_causes) + return ( + not requires_python, not direct, not pinned, - not upper_bounded, + not backtrack_cause, + inferred_depth, requested_order, not unfree, identifier, @@ -271,15 +234,22 @@ def _eligible_for_upgrade(identifier: str) -> bool: constraint=constraint, prefers_installed=(not _eligible_for_upgrade(identifier)), incompatibilities=incompatibilities, - is_satisfied_by=self.is_satisfied_by, ) - @staticmethod - @cache - def is_satisfied_by(requirement: Requirement, candidate: Candidate) -> bool: + def is_satisfied_by(self, requirement: Requirement, candidate: Candidate) -> bool: return requirement.is_satisfied_by(candidate) - def get_dependencies(self, candidate: Candidate) -> Iterable[Requirement]: + def get_dependencies(self, candidate: Candidate) -> Sequence[Requirement]: with_requires = not self._ignore_dependencies - # iter_dependencies() can perform nontrivial work so delay until needed. - return (r for r in candidate.iter_dependencies(with_requires) if r is not None) + return [r for r in candidate.iter_dependencies(with_requires) if r is not None] + + @staticmethod + def is_backtrack_cause( + identifier: str, backtrack_causes: Sequence["PreferenceInformation"] + ) -> bool: + for backtrack_cause in backtrack_causes: + if identifier == backtrack_cause.requirement.name: + return True + if backtrack_cause.parent and identifier == backtrack_cause.parent.name: + return True + return False diff --git a/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/reporter.py b/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/reporter.py index 6ba9bbd7..3c724238 100644 --- a/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/reporter.py +++ b/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/reporter.py @@ -1,21 +1,17 @@ -from __future__ import annotations - from collections import defaultdict -from collections.abc import Mapping from logging import getLogger -from typing import Any +from typing import Any, DefaultDict from pip._vendor.resolvelib.reporters import BaseReporter -from .base import Candidate, Constraint, Requirement +from .base import Candidate, Requirement logger = getLogger(__name__) -class PipReporter(BaseReporter[Requirement, Candidate, str]): - def __init__(self, constraints: Mapping[str, Constraint] | None = None) -> None: - self.reject_count_by_package: defaultdict[str, int] = defaultdict(int) - self._constraints = constraints or {} +class PipReporter(BaseReporter): + def __init__(self) -> None: + self.reject_count_by_package: DefaultDict[str, int] = defaultdict(int) self._messages_at_reject_count = { 1: ( @@ -24,7 +20,7 @@ def __init__(self, constraints: Mapping[str, Constraint] | None = None) -> None: "requirements. This could take a while." ), 8: ( - "pip is still looking at multiple versions of {package_name} to " + "pip is looking at multiple versions of {package_name} to " "determine which version is compatible with other " "requirements. This could take a while." ), @@ -37,40 +33,29 @@ def __init__(self, constraints: Mapping[str, Constraint] | None = None) -> None: } def rejecting_candidate(self, criterion: Any, candidate: Candidate) -> None: - """Report a candidate being rejected. - - Logs both the rejection count message (if applicable) and details about - the requirements and constraints that caused the rejection. - """ self.reject_count_by_package[candidate.name] += 1 count = self.reject_count_by_package[candidate.name] - if count in self._messages_at_reject_count: - message = self._messages_at_reject_count[count] - logger.info("INFO: %s", message.format(package_name=candidate.name)) + if count not in self._messages_at_reject_count: + return + + message = self._messages_at_reject_count[count] + logger.info("INFO: %s", message.format(package_name=candidate.name)) msg = "Will try a different candidate, due to conflict:" for req_info in criterion.information: req, parent = req_info.requirement, req_info.parent + # Inspired by Factory.get_installation_error msg += "\n " if parent: msg += f"{parent.name} {parent.version} depends on " else: msg += "The user requested " msg += req.format_for_error() - - # Add any relevant constraints - if self._constraints: - name = candidate.name - constraint = self._constraints.get(name) - if constraint and constraint.specifier: - constraint_text = f"{name}{constraint.specifier}" - msg += f"\n The user requested (constraint) {constraint_text}" - logger.debug(msg) -class PipDebuggingReporter(BaseReporter[Requirement, Candidate, str]): +class PipDebuggingReporter(BaseReporter): """A reporter that does an info log for every event it sees.""" def starting(self) -> None: @@ -81,14 +66,11 @@ def starting_round(self, index: int) -> None: def ending_round(self, index: int, state: Any) -> None: logger.info("Reporter.ending_round(%r, state)", index) - logger.debug("Reporter.ending_round(%r, %r)", index, state) def ending(self, state: Any) -> None: logger.info("Reporter.ending(%r)", state) - def adding_requirement( - self, requirement: Requirement, parent: Candidate | None - ) -> None: + def adding_requirement(self, requirement: Requirement, parent: Candidate) -> None: logger.info("Reporter.adding_requirement(%r, %r)", requirement, parent) def rejecting_candidate(self, criterion: Any, candidate: Candidate) -> None: diff --git a/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/requirements.py b/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/requirements.py index 447e36b5..06addc0d 100644 --- a/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/requirements.py +++ b/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/requirements.py @@ -1,11 +1,6 @@ -from __future__ import annotations - -from typing import Any - from pip._vendor.packaging.specifiers import SpecifierSet from pip._vendor.packaging.utils import NormalizedName, canonicalize_name -from pip._internal.req.constructors import install_req_drop_extras from pip._internal.req.req_install import InstallRequirement from .base import Candidate, CandidateLookup, Requirement, format_name @@ -19,15 +14,10 @@ def __str__(self) -> str: return str(self.candidate) def __repr__(self) -> str: - return f"{self.__class__.__name__}({self.candidate!r})" - - def __hash__(self) -> int: - return hash(self.candidate) - - def __eq__(self, other: Any) -> bool: - if not isinstance(other, ExplicitRequirement): - return False - return self.candidate == other.candidate + return "{class_name}({candidate!r})".format( + class_name=self.__class__.__name__, + candidate=self.candidate, + ) @property def project_name(self) -> NormalizedName: @@ -53,35 +43,16 @@ class SpecifierRequirement(Requirement): def __init__(self, ireq: InstallRequirement) -> None: assert ireq.link is None, "This is a link, not a specifier" self._ireq = ireq - self._equal_cache: str | None = None - self._hash: int | None = None - self._extras = frozenset(canonicalize_name(e) for e in self._ireq.extras) - - @property - def _equal(self) -> str: - if self._equal_cache is not None: - return self._equal_cache - - self._equal_cache = str(self._ireq) - return self._equal_cache + self._extras = frozenset(ireq.extras) def __str__(self) -> str: return str(self._ireq.req) def __repr__(self) -> str: - return f"{self.__class__.__name__}({str(self._ireq.req)!r})" - - def __eq__(self, other: object) -> bool: - if not isinstance(other, SpecifierRequirement): - return NotImplemented - return self._equal == other._equal - - def __hash__(self) -> int: - if self._hash is not None: - return self._hash - - self._hash = hash(self._equal) - return self._hash + return "{class_name}({requirement!r})".format( + class_name=self.__class__.__name__, + requirement=str(self._ireq.req), + ) @property def project_name(self) -> NormalizedName: @@ -121,68 +92,20 @@ def is_satisfied_by(self, candidate: Candidate) -> bool: return spec.contains(candidate.version, prereleases=True) -class SpecifierWithoutExtrasRequirement(SpecifierRequirement): - """ - Requirement backed by an install requirement on a base package. - Trims extras from its install requirement if there are any. - """ - - def __init__(self, ireq: InstallRequirement) -> None: - assert ireq.link is None, "This is a link, not a specifier" - self._ireq = install_req_drop_extras(ireq) - self._equal_cache: str | None = None - self._hash: int | None = None - self._extras = frozenset(canonicalize_name(e) for e in self._ireq.extras) - - @property - def _equal(self) -> str: - if self._equal_cache is not None: - return self._equal_cache - - self._equal_cache = str(self._ireq) - return self._equal_cache - - def __eq__(self, other: object) -> bool: - if not isinstance(other, SpecifierWithoutExtrasRequirement): - return NotImplemented - return self._equal == other._equal - - def __hash__(self) -> int: - if self._hash is not None: - return self._hash - - self._hash = hash(self._equal) - return self._hash - - class RequiresPythonRequirement(Requirement): """A requirement representing Requires-Python metadata.""" def __init__(self, specifier: SpecifierSet, match: Candidate) -> None: self.specifier = specifier - self._specifier_string = str(specifier) # for faster __eq__ - self._hash: int | None = None self._candidate = match def __str__(self) -> str: return f"Python {self.specifier}" def __repr__(self) -> str: - return f"{self.__class__.__name__}({str(self.specifier)!r})" - - def __hash__(self) -> int: - if self._hash is not None: - return self._hash - - self._hash = hash((self._specifier_string, self._candidate)) - return self._hash - - def __eq__(self, other: Any) -> bool: - if not isinstance(other, RequiresPythonRequirement): - return False - return ( - self._specifier_string == other._specifier_string - and self._candidate == other._candidate + return "{class_name}({specifier!r})".format( + class_name=self.__class__.__name__, + specifier=str(self.specifier), ) @property @@ -219,15 +142,10 @@ def __str__(self) -> str: return f"{self._name} (unavailable)" def __repr__(self) -> str: - return f"{self.__class__.__name__}({str(self._name)!r})" - - def __eq__(self, other: object) -> bool: - if not isinstance(other, UnsatisfiableRequirement): - return NotImplemented - return self._name == other._name - - def __hash__(self) -> int: - return hash(self._name) + return "{class_name}({name!r})".format( + class_name=self.__class__.__name__, + name=str(self._name), + ) @property def project_name(self) -> NormalizedName: diff --git a/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/resolver.py b/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/resolver.py index 7e44c173..47bbfecc 100644 --- a/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/resolver.py +++ b/venv1/Lib/site-packages/pip/_internal/resolution/resolvelib/resolver.py @@ -1,21 +1,16 @@ -from __future__ import annotations - -import contextlib import functools import logging import os -from typing import TYPE_CHECKING, cast +from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple, cast from pip._vendor.packaging.utils import canonicalize_name -from pip._vendor.resolvelib import BaseReporter, ResolutionImpossible, ResolutionTooDeep +from pip._vendor.resolvelib import BaseReporter, ResolutionImpossible from pip._vendor.resolvelib import Resolver as RLResolver from pip._vendor.resolvelib.structs import DirectedGraph from pip._internal.cache import WheelCache -from pip._internal.exceptions import ResolutionTooDeepError from pip._internal.index.package_finder import PackageFinder from pip._internal.operations.prepare import RequirementPreparer -from pip._internal.req.constructors import install_req_extend_extras from pip._internal.req.req_install import InstallRequirement from pip._internal.req.req_set import RequirementSet from pip._internal.resolution.base import BaseResolver, InstallRequirementProvider @@ -24,7 +19,6 @@ PipDebuggingReporter, PipReporter, ) -from pip._internal.utils.packaging import get_requirement from .base import Candidate, Requirement from .factory import Factory @@ -45,7 +39,7 @@ def __init__( self, preparer: RequirementPreparer, finder: PackageFinder, - wheel_cache: WheelCache | None, + wheel_cache: Optional[WheelCache], make_install_req: InstallRequirementProvider, use_user_site: bool, ignore_dependencies: bool, @@ -53,7 +47,7 @@ def __init__( ignore_requires_python: bool, force_reinstall: bool, upgrade_strategy: str, - py_version_info: tuple[int, ...] | None = None, + py_version_info: Optional[Tuple[int, ...]] = None, ): super().__init__() assert upgrade_strategy in self._allowed_strategies @@ -71,10 +65,10 @@ def __init__( ) self.ignore_dependencies = ignore_dependencies self.upgrade_strategy = upgrade_strategy - self._result: Result | None = None + self._result: Optional[Result] = None def resolve( - self, root_reqs: list[InstallRequirement], check_supported_wheels: bool + self, root_reqs: List[InstallRequirement], check_supported_wheels: bool ) -> RequirementSet: collected = self.factory.collect_root_requirements(root_reqs) provider = PipProvider( @@ -85,10 +79,9 @@ def resolve( user_requested=collected.user_requested, ) if "PIP_RESOLVER_DEBUG" in os.environ: - reporter: BaseReporter[Requirement, Candidate, str] = PipDebuggingReporter() + reporter: BaseReporter = PipDebuggingReporter() else: - reporter = PipReporter(constraints=provider.constraints) - + reporter = PipReporter() resolver: RLResolver[Requirement, Candidate, str] = RLResolver( provider, reporter, @@ -106,28 +99,11 @@ def resolve( collected.constraints, ) raise error from e - except ResolutionTooDeep: - raise ResolutionTooDeepError from None req_set = RequirementSet(check_supported_wheels=check_supported_wheels) - # process candidates with extras last to ensure their base equivalent is - # already in the req_set if appropriate. - # Python's sort is stable so using a binary key function keeps relative order - # within both subsets. - for candidate in sorted( - result.mapping.values(), key=lambda c: c.name != c.project_name - ): + for candidate in result.mapping.values(): ireq = candidate.get_install_requirement() if ireq is None: - if candidate.name != candidate.project_name: - # extend existing req's extras - with contextlib.suppress(KeyError): - req = req_set.get_requirement(candidate.project_name) - req_set.add_named_requirement( - install_req_extend_extras( - req, get_requirement(candidate.name).extras - ) - ) continue # Check if there is already an installation under the same name, @@ -181,11 +157,13 @@ def resolve( req_set.add_named_requirement(ireq) + reqs = req_set.all_requirements + self.factory.preparer.prepare_linked_requirements_more(reqs) return req_set def get_installation_order( self, req_set: RequirementSet - ) -> list[InstallRequirement]: + ) -> List[InstallRequirement]: """Get order for installation of requirements in RequirementSet. The returned list contains a requirement before another that depends on @@ -216,8 +194,8 @@ def get_installation_order( def get_topological_weights( - graph: DirectedGraph[str | None], requirement_keys: set[str] -) -> dict[str | None, int]: + graph: "DirectedGraph[Optional[str]]", requirement_keys: Set[str] +) -> Dict[Optional[str], int]: """Assign weights to each node based on how "deep" they are. This implementation may change at any point in the future without prior @@ -243,25 +221,14 @@ def get_topological_weights( We are only interested in the weights of packages that are in the requirement_keys. """ - path: set[str | None] = set() - weights: dict[str | None, list[int]] = {} + path: Set[Optional[str]] = set() + weights: Dict[Optional[str], int] = {} - def visit(node: str | None) -> None: + def visit(node: Optional[str]) -> None: if node in path: # We hit a cycle, so we'll break it here. return - # The walk is exponential and for pathologically connected graphs (which - # are the ones most likely to contain cycles in the first place) it can - # take until the heat-death of the universe. To counter this we limit - # the number of attempts to visit (i.e. traverse through) any given - # node. We choose a value here which gives decent enough coverage for - # fairly well behaved graphs, and still limits the walk complexity to be - # linear in nature. - cur_weights = weights.get(node, []) - if len(cur_weights) >= 5: - return - # Time to visit the children! path.add(node) for child in graph.iter_children(node): @@ -271,14 +238,14 @@ def visit(node: str | None) -> None: if node not in requirement_keys: return - cur_weights.append(len(path)) - weights[node] = cur_weights + last_known_parent_count = weights.get(node, 0) + weights[node] = max(last_known_parent_count, len(path)) - # Simplify the graph, pruning leaves that have no dependencies. This is - # needed for large graphs (say over 200 packages) because the `visit` - # function is slower for large/densely connected graphs, taking minutes. + # Simplify the graph, pruning leaves that have no dependencies. + # This is needed for large graphs (say over 200 packages) because the + # `visit` function is exponentially slower then, taking minutes. # See https://github.com/pypa/pip/issues/10557 - # We repeat the pruning step until we have no more leaves to remove. + # We will loop until we explicitly break the loop. while True: leaves = set() for key in graph: @@ -298,13 +265,12 @@ def visit(node: str | None) -> None: for leaf in leaves: if leaf not in requirement_keys: continue - weights[leaf] = [weight] + weights[leaf] = weight # Remove the leaves from the graph, making it simpler. for leaf in leaves: graph.remove(leaf) - # Visit the remaining graph, this will only have nodes to handle if the - # graph had a cycle in it, which the pruning step above could not handle. + # Visit the remaining graph. # `None` is guaranteed to be the root node by resolvelib. visit(None) @@ -313,15 +279,13 @@ def visit(node: str | None) -> None: difference = set(weights.keys()).difference(requirement_keys) assert not difference, difference - # Now give back all the weights, choosing the largest ones from what we - # accumulated. - return {node: max(wgts) for (node, wgts) in weights.items()} + return weights def _req_set_item_sorter( - item: tuple[str, InstallRequirement], - weights: dict[str | None, int], -) -> tuple[int, str]: + item: Tuple[str, InstallRequirement], + weights: Dict[Optional[str], int], +) -> Tuple[int, str]: """Key function used to sort install requirements for installation. Based on the "weight" mapping calculated in ``get_installation_order()``. diff --git a/venv1/Lib/site-packages/pip/_internal/self_outdated_check.py b/venv1/Lib/site-packages/pip/_internal/self_outdated_check.py index 5999ddb3..41cc42c5 100644 --- a/venv1/Lib/site-packages/pip/_internal/self_outdated_check.py +++ b/venv1/Lib/site-packages/pip/_internal/self_outdated_check.py @@ -1,5 +1,3 @@ -from __future__ import annotations - import datetime import functools import hashlib @@ -9,9 +7,8 @@ import os.path import sys from dataclasses import dataclass -from typing import Any, Callable +from typing import Any, Callable, Dict, Optional -from pip._vendor.packaging.version import Version from pip._vendor.packaging.version import parse as parse_version from pip._vendor.rich.console import Group from pip._vendor.rich.markup import escape @@ -20,6 +17,7 @@ from pip._internal.index.collector import LinkCollector from pip._internal.index.package_finder import PackageFinder from pip._internal.metadata import get_default_environment +from pip._internal.metadata.base import DistributionVersion from pip._internal.models.selection_prefs import SelectionPreferences from pip._internal.network.session import PipSession from pip._internal.utils.compat import WINDOWS @@ -27,19 +25,11 @@ get_best_invocation_for_this_pip, get_best_invocation_for_this_python, ) -from pip._internal.utils.filesystem import ( - adjacent_tmp_file, - check_path_owner, - copy_directory_permissions, - replace, -) -from pip._internal.utils.misc import ( - ExternallyManagedEnvironment, - check_externally_managed, - ensure_dir, -) +from pip._internal.utils.filesystem import adjacent_tmp_file, check_path_owner, replace +from pip._internal.utils.misc import ensure_dir + +_DATE_FMT = "%Y-%m-%dT%H:%M:%SZ" -_WEEK = datetime.timedelta(days=7) logger = logging.getLogger(__name__) @@ -50,18 +40,9 @@ def _get_statefile_name(key: str) -> str: return name -def _convert_date(isodate: str) -> datetime.datetime: - """Convert an ISO format string to a date. - - Handles the format 2020-01-22T14:24:01Z (trailing Z) - which is not supported by older versions of fromisoformat. - """ - return datetime.datetime.fromisoformat(isodate.replace("Z", "+00:00")) - - class SelfCheckState: def __init__(self, cache_dir: str) -> None: - self._state: dict[str, Any] = {} + self._state: Dict[str, Any] = {} self._statefile_path = None # Try to load the existing state @@ -81,7 +62,7 @@ def __init__(self, cache_dir: str) -> None: def key(self) -> str: return sys.prefix - def get(self, current_time: datetime.datetime) -> str | None: + def get(self, current_time: datetime.datetime) -> Optional[str]: """Check if we have a not-outdated version loaded already.""" if not self._state: return None @@ -92,10 +73,12 @@ def get(self, current_time: datetime.datetime) -> str | None: if "pypi_version" not in self._state: return None + seven_days_in_seconds = 7 * 24 * 60 * 60 + # Determine if we need to refresh the state - last_check = _convert_date(self._state["last_check"]) - time_since_last_check = current_time - last_check - if time_since_last_check > _WEEK: + last_check = datetime.datetime.strptime(self._state["last_check"], _DATE_FMT) + seconds_since_last_check = (current_time - last_check).total_seconds() + if seconds_since_last_check > seven_days_in_seconds: return None return self._state["pypi_version"] @@ -105,21 +88,19 @@ def set(self, pypi_version: str, current_time: datetime.datetime) -> None: if not self._statefile_path: return - statefile_directory = os.path.dirname(self._statefile_path) - # Check to make sure that we own the directory - if not check_path_owner(statefile_directory): + if not check_path_owner(os.path.dirname(self._statefile_path)): return # Now that we've ensured the directory is owned by this user, we'll go # ahead and make sure that all our directories are created. - ensure_dir(statefile_directory) + ensure_dir(os.path.dirname(self._statefile_path)) state = { # Include the key so it's easy to tell which pip wrote the # file. "key": self.key, - "last_check": current_time.isoformat(), + "last_check": current_time.strftime(_DATE_FMT), "pypi_version": pypi_version, } @@ -127,7 +108,6 @@ def set(self, pypi_version: str, current_time: datetime.datetime) -> None: with adjacent_tmp_file(self._statefile_path) as f: f.write(text.encode()) - copy_directory_permissions(statefile_directory, f) try: # Since we have a prefix-specific state file, we can just @@ -175,7 +155,7 @@ def was_installed_by_pip(pkg: str) -> bool: def _get_current_remote_pip_version( session: PipSession, options: optparse.Values -) -> str | None: +) -> Optional[str]: # Lets use PackageFinder to see what the latest pip version is link_collector = LinkCollector.create( session, @@ -205,9 +185,9 @@ def _self_version_check_logic( *, state: SelfCheckState, current_time: datetime.datetime, - local_version: Version, - get_remote_version: Callable[[], str | None], -) -> UpgradePrompt | None: + local_version: DistributionVersion, + get_remote_version: Callable[[], Optional[str]], +) -> Optional[UpgradePrompt]: remote_version_str = state.get(current_time) if remote_version_str is None: remote_version_str = get_remote_version() @@ -245,18 +225,18 @@ def pip_self_version_check(session: PipSession, options: optparse.Values) -> Non installed_dist = get_default_environment().get_distribution("pip") if not installed_dist: return - try: - check_externally_managed() - except ExternallyManagedEnvironment: - return - upgrade_prompt = _self_version_check_logic( - state=SelfCheckState(cache_dir=options.cache_dir), - current_time=datetime.datetime.now(datetime.timezone.utc), - local_version=installed_dist.version, - get_remote_version=functools.partial( - _get_current_remote_pip_version, session, options - ), - ) - if upgrade_prompt is not None: - logger.warning("%s", upgrade_prompt, extra={"rich": True}) + try: + upgrade_prompt = _self_version_check_logic( + state=SelfCheckState(cache_dir=options.cache_dir), + current_time=datetime.datetime.utcnow(), + local_version=installed_dist.version, + get_remote_version=functools.partial( + _get_current_remote_pip_version, session, options + ), + ) + if upgrade_prompt is not None: + logger.warning("[present-rich] %s", upgrade_prompt) + except Exception: + logger.warning("There was an error checking the latest version of pip.") + logger.debug("See below for error", exc_info=True) diff --git a/venv1/Lib/site-packages/pip/_internal/utils/_jaraco_text.py b/venv1/Lib/site-packages/pip/_internal/utils/_jaraco_text.py index 6ccf53b7..e06947c0 100644 --- a/venv1/Lib/site-packages/pip/_internal/utils/_jaraco_text.py +++ b/venv1/Lib/site-packages/pip/_internal/utils/_jaraco_text.py @@ -88,7 +88,7 @@ def join_continuation(lines): ['foobarbaz'] Not sure why, but... - The character preceding the backslash is also elided. + The character preceeding the backslash is also elided. >>> list(join_continuation(['goo\\', 'dly'])) ['godly'] diff --git a/venv1/Lib/site-packages/pip/_internal/utils/appdirs.py b/venv1/Lib/site-packages/pip/_internal/utils/appdirs.py index 4152528f..16933bf8 100644 --- a/venv1/Lib/site-packages/pip/_internal/utils/appdirs.py +++ b/venv1/Lib/site-packages/pip/_internal/utils/appdirs.py @@ -8,6 +8,7 @@ import os import sys +from typing import List from pip._vendor import platformdirs as _appdirs @@ -39,10 +40,9 @@ def user_config_dir(appname: str, roaming: bool = True) -> str: # for the discussion regarding site_config_dir locations # see -def site_config_dirs(appname: str) -> list[str]: +def site_config_dirs(appname: str) -> List[str]: if sys.platform == "darwin": - dirval = _appdirs.site_data_dir(appname, appauthor=False, multipath=True) - return dirval.split(os.pathsep) + return [_appdirs.site_data_dir(appname, appauthor=False, multipath=True)] dirval = _appdirs.site_config_dir(appname, appauthor=False, multipath=True) if sys.platform == "win32": diff --git a/venv1/Lib/site-packages/pip/_internal/utils/compat.py b/venv1/Lib/site-packages/pip/_internal/utils/compat.py index 324789f1..3f4d300c 100644 --- a/venv1/Lib/site-packages/pip/_internal/utils/compat.py +++ b/venv1/Lib/site-packages/pip/_internal/utils/compat.py @@ -1,13 +1,11 @@ """Stuff that differs in different Python versions and platform distributions.""" -import importlib.resources import logging import os import sys -from typing import IO -__all__ = ["get_path_uid", "stdlib_pkgs", "tomllib", "WINDOWS"] +__all__ = ["get_path_uid", "stdlib_pkgs", "WINDOWS"] logger = logging.getLogger(__name__) @@ -53,26 +51,6 @@ def get_path_uid(path: str) -> int: return file_uid -# The importlib.resources.open_text function was deprecated in 3.11 with suggested -# replacement we use below. -if sys.version_info < (3, 11): - open_text_resource = importlib.resources.open_text -else: - - def open_text_resource( - package: str, resource: str, encoding: str = "utf-8", errors: str = "strict" - ) -> IO[str]: - return (importlib.resources.files(package) / resource).open( - "r", encoding=encoding, errors=errors - ) - - -if sys.version_info >= (3, 11): - import tomllib -else: - from pip._vendor import tomli as tomllib - - # packages in the stdlib that may have installation metadata, but should not be # considered 'installed'. this theoretically could be determined based on # dist.location (py27:`sysconfig.get_paths()['stdlib']`, diff --git a/venv1/Lib/site-packages/pip/_internal/utils/compatibility_tags.py b/venv1/Lib/site-packages/pip/_internal/utils/compatibility_tags.py index 6d98171d..b6ed9a78 100644 --- a/venv1/Lib/site-packages/pip/_internal/utils/compatibility_tags.py +++ b/venv1/Lib/site-packages/pip/_internal/utils/compatibility_tags.py @@ -1,32 +1,30 @@ -"""Generate and work with PEP 425 Compatibility Tags.""" - -from __future__ import annotations +"""Generate and work with PEP 425 Compatibility Tags. +""" import re +from typing import List, Optional, Tuple from pip._vendor.packaging.tags import ( PythonVersion, Tag, - android_platforms, compatible_tags, cpython_tags, generic_tags, interpreter_name, interpreter_version, - ios_platforms, mac_platforms, ) -_apple_arch_pat = re.compile(r"(.+)_(\d+)_(\d+)_(.+)") +_osx_arch_pat = re.compile(r"(.+)_(\d+)_(\d+)_(.+)") -def version_info_to_nodot(version_info: tuple[int, ...]) -> str: +def version_info_to_nodot(version_info: Tuple[int, ...]) -> str: # Only use up to the first two numbers. return "".join(map(str, version_info[:2])) -def _mac_platforms(arch: str) -> list[str]: - match = _apple_arch_pat.match(arch) +def _mac_platforms(arch: str) -> List[str]: + match = _osx_arch_pat.match(arch) if match: name, major, minor, actual_arch = match.groups() mac_version = (int(major), int(minor)) @@ -45,37 +43,7 @@ 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 _android_platforms(arch: str) -> list[str]: - match = re.fullmatch(r"android_(\d+)_(.+)", arch) - if match: - api_level, abi = match.groups() - return list(android_platforms(int(api_level), abi)) - else: - # arch pattern didn't match (?!) - return [arch] - - -def _custom_manylinux_platforms(arch: str) -> list[str]: +def _custom_manylinux_platforms(arch: str) -> List[str]: arches = [arch] arch_prefix, arch_sep, arch_suffix = arch.partition("_") if arch_prefix == "manylinux2014": @@ -96,14 +64,10 @@ def _custom_manylinux_platforms(arch: str) -> list[str]: return arches -def _get_custom_platforms(arch: str) -> list[str]: +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 == "android": - arches = _android_platforms(arch) elif arch_prefix in ["manylinux2014", "manylinux2010"]: arches = _custom_manylinux_platforms(arch) else: @@ -111,7 +75,7 @@ def _get_custom_platforms(arch: str) -> list[str]: return arches -def _expand_allowed_platforms(platforms: list[str] | None) -> list[str] | None: +def _expand_allowed_platforms(platforms: Optional[List[str]]) -> Optional[List[str]]: if not platforms: return None @@ -136,7 +100,7 @@ def _get_python_version(version: str) -> PythonVersion: def _get_custom_interpreter( - implementation: str | None = None, version: str | None = None + implementation: Optional[str] = None, version: Optional[str] = None ) -> str: if implementation is None: implementation = interpreter_name() @@ -146,11 +110,11 @@ def _get_custom_interpreter( def get_supported( - version: str | None = None, - platforms: list[str] | None = None, - impl: str | None = None, - abis: list[str] | None = None, -) -> list[Tag]: + version: Optional[str] = None, + platforms: Optional[List[str]] = None, + impl: Optional[str] = None, + abis: Optional[List[str]] = None, +) -> List[Tag]: """Return a list of supported tags for each version specified in `versions`. @@ -163,9 +127,9 @@ def get_supported( :param abis: specify a list of abis you want valid tags for, or None. If None, use the local interpreter abi. """ - supported: list[Tag] = [] + supported: List[Tag] = [] - python_version: PythonVersion | None = None + python_version: Optional[PythonVersion] = None if version is not None: python_version = _get_python_version(version) diff --git a/venv1/Lib/site-packages/pip/_internal/utils/datetime.py b/venv1/Lib/site-packages/pip/_internal/utils/datetime.py index 776e4989..8668b3b0 100644 --- a/venv1/Lib/site-packages/pip/_internal/utils/datetime.py +++ b/venv1/Lib/site-packages/pip/_internal/utils/datetime.py @@ -1,4 +1,5 @@ -"""For when pip wants to check the date or time.""" +"""For when pip wants to check the date or time. +""" import datetime diff --git a/venv1/Lib/site-packages/pip/_internal/utils/deprecation.py b/venv1/Lib/site-packages/pip/_internal/utils/deprecation.py index 96e7783f..72bd6f25 100644 --- a/venv1/Lib/site-packages/pip/_internal/utils/deprecation.py +++ b/venv1/Lib/site-packages/pip/_internal/utils/deprecation.py @@ -2,11 +2,9 @@ A module that implements tooling to enable easy warnings about deprecations. """ -from __future__ import annotations - import logging import warnings -from typing import Any, TextIO +from typing import Any, Optional, TextIO, Type, Union from pip._vendor.packaging.version import parse @@ -24,12 +22,12 @@ class PipDeprecationWarning(Warning): # Warnings <-> Logging Integration def _showwarning( - message: Warning | str, - category: type[Warning], + message: Union[Warning, str], + category: Type[Warning], filename: str, lineno: int, - file: TextIO | None = None, - line: str | None = None, + file: Optional[TextIO] = None, + line: Optional[str] = None, ) -> None: if file is not None: if _original_showwarning is not None: @@ -57,10 +55,10 @@ def install_warning_logger() -> None: def deprecated( *, reason: str, - replacement: str | None, - gone_in: str | None, - feature_flag: str | None = None, - issue: int | None = None, + replacement: Optional[str], + gone_in: Optional[str], + feature_flag: Optional[str] = None, + issue: Optional[int] = None, ) -> None: """Helper to deprecate existing functionality. @@ -89,11 +87,9 @@ def deprecated( (reason, f"{DEPRECATION_MSG_PREFIX}{{}}"), ( gone_in, - ( - "pip {} will enforce this behaviour change." - if not is_gone - else "Since pip {}, this is no longer supported." - ), + "pip {} will enforce this behaviour change." + if not is_gone + else "Since pip {}, this is no longer supported.", ), ( replacement, @@ -101,11 +97,9 @@ def deprecated( ), ( feature_flag, - ( - "You can use the flag --use-feature={} to test the upcoming behaviour." - if not is_gone - else None - ), + "You can use the flag --use-feature={} to test the upcoming behaviour." + if not is_gone + else None, ), ( issue, diff --git a/venv1/Lib/site-packages/pip/_internal/utils/direct_url_helpers.py b/venv1/Lib/site-packages/pip/_internal/utils/direct_url_helpers.py index 3cbc1e76..0e8e5e16 100644 --- a/venv1/Lib/site-packages/pip/_internal/utils/direct_url_helpers.py +++ b/venv1/Lib/site-packages/pip/_internal/utils/direct_url_helpers.py @@ -1,4 +1,4 @@ -from __future__ import annotations +from typing import Optional from pip._internal.models.direct_url import ArchiveInfo, DirectUrl, DirInfo, VcsInfo from pip._internal.models.link import Link @@ -12,8 +12,8 @@ def direct_url_as_pep440_direct_reference(direct_url: DirectUrl, name: str) -> s requirement = name + " @ " fragments = [] if isinstance(direct_url.info, VcsInfo): - requirement += ( - f"{direct_url.info.vcs}+{direct_url.url}@{direct_url.info.commit_id}" + requirement += "{}+{}@{}".format( + direct_url.info.vcs, direct_url.url, direct_url.info.commit_id ) elif isinstance(direct_url.info, ArchiveInfo): requirement += direct_url.url @@ -37,7 +37,7 @@ def direct_url_for_editable(source_dir: str) -> DirectUrl: def direct_url_from_link( - link: Link, source_dir: str | None = None, link_is_in_wheel_cache: bool = False + link: Link, source_dir: Optional[str] = None, link_is_in_wheel_cache: bool = False ) -> DirectUrl: if link.is_vcs: vcs_backend = vcs.get_backend_for_scheme(link.scheme) diff --git a/venv1/Lib/site-packages/pip/_internal/utils/egg_link.py b/venv1/Lib/site-packages/pip/_internal/utils/egg_link.py index dc85a58b..eb57ed15 100644 --- a/venv1/Lib/site-packages/pip/_internal/utils/egg_link.py +++ b/venv1/Lib/site-packages/pip/_internal/utils/egg_link.py @@ -1,8 +1,7 @@ -from __future__ import annotations - import os import re import sys +from typing import List, Optional from pip._internal.locations import site_packages, user_site from pip._internal.utils.virtualenv import ( @@ -16,35 +15,28 @@ ] -def _egg_link_names(raw_name: str) -> list[str]: +def _egg_link_name(raw_name: str) -> str: """ Convert a Name metadata value to a .egg-link name, by applying the same substitution as pkg_resources's safe_name function. Note: we cannot use canonicalize_name because it has a different logic. - - We also look for the raw name (without normalization) as setuptools 69 changed - the way it names .egg-link files (https://github.com/pypa/setuptools/issues/4167). """ - return [ - re.sub("[^A-Za-z0-9.]+", "-", raw_name) + ".egg-link", - f"{raw_name}.egg-link", - ] + return re.sub("[^A-Za-z0-9.]+", "-", raw_name) + ".egg-link" -def egg_link_path_from_sys_path(raw_name: str) -> str | None: +def egg_link_path_from_sys_path(raw_name: str) -> Optional[str]: """ Look for a .egg-link file for project name, by walking sys.path. """ - egg_link_names = _egg_link_names(raw_name) + egg_link_name = _egg_link_name(raw_name) for path_item in sys.path: - for egg_link_name in egg_link_names: - egg_link = os.path.join(path_item, egg_link_name) - if os.path.isfile(egg_link): - return egg_link + egg_link = os.path.join(path_item, egg_link_name) + if os.path.isfile(egg_link): + return egg_link return None -def egg_link_path_from_location(raw_name: str) -> str | None: +def egg_link_path_from_location(raw_name: str) -> Optional[str]: """ Return the path for the .egg-link file if it exists, otherwise, None. @@ -62,7 +54,7 @@ def egg_link_path_from_location(raw_name: str) -> str | None: This method will just return the first one found. """ - sites: list[str] = [] + sites: List[str] = [] if running_under_virtualenv(): sites.append(site_packages) if not virtualenv_no_global() and user_site: @@ -72,10 +64,9 @@ def egg_link_path_from_location(raw_name: str) -> str | None: sites.append(user_site) sites.append(site_packages) - egg_link_names = _egg_link_names(raw_name) + egg_link_name = _egg_link_name(raw_name) for site in sites: - for egg_link_name in egg_link_names: - egglink = os.path.join(site, egg_link_name) - if os.path.isfile(egglink): - return egglink + egglink = os.path.join(site, egg_link_name) + if os.path.isfile(egglink): + return egglink return None diff --git a/venv1/Lib/site-packages/pip/_internal/utils/entrypoints.py b/venv1/Lib/site-packages/pip/_internal/utils/entrypoints.py index e3a150ee..15013693 100644 --- a/venv1/Lib/site-packages/pip/_internal/utils/entrypoints.py +++ b/venv1/Lib/site-packages/pip/_internal/utils/entrypoints.py @@ -1,9 +1,8 @@ -from __future__ import annotations - import itertools import os import shutil import sys +from typing import List, Optional from pip._internal.cli.main import main from pip._internal.utils.compat import WINDOWS @@ -21,7 +20,7 @@ ] -def _wrapper(args: list[str] | None = None) -> int: +def _wrapper(args: Optional[List[str]] = None) -> int: """Central wrapper for all old entrypoints. Historically pip has had several entrypoints defined. Because of issues @@ -78,10 +77,7 @@ def get_best_invocation_for_this_python() -> str: # Try to use the basename, if it's the first executable. found_executable = shutil.which(exe_name) - # Virtual environments often symlink to their parent Python binaries, but we don't - # want to treat the Python binaries as equivalent when the environment's Python is - # not on PATH (not activated). Thus, we don't follow symlinks. - if found_executable and os.path.samestat(os.lstat(found_executable), os.lstat(exe)): + if found_executable and os.path.samefile(found_executable, exe): return exe_name # Use the full executable name, because we couldn't find something simpler. diff --git a/venv1/Lib/site-packages/pip/_internal/utils/filesystem.py b/venv1/Lib/site-packages/pip/_internal/utils/filesystem.py index e34ffcf6..83c2df75 100644 --- a/venv1/Lib/site-packages/pip/_internal/utils/filesystem.py +++ b/venv1/Lib/site-packages/pip/_internal/utils/filesystem.py @@ -1,18 +1,16 @@ -from __future__ import annotations - import fnmatch import os import os.path import random import sys -from collections.abc import Generator from contextlib import contextmanager from tempfile import NamedTemporaryFile -from typing import Any, BinaryIO, cast +from typing import Any, BinaryIO, Generator, List, Union, cast + +from pip._vendor.tenacity import retry, stop_after_delay, wait_fixed from pip._internal.utils.compat import get_path_uid from pip._internal.utils.misc import format_size -from pip._internal.utils.retry import retry def check_path_owner(path: str) -> bool: @@ -67,7 +65,10 @@ def adjacent_tmp_file(path: str, **kwargs: Any) -> Generator[BinaryIO, None, Non os.fsync(result.fileno()) -replace = retry(stop_after_delay=1, wait=0.25)(os.replace) +# Tenacity raises RetryError by default, explicitly raise the original exception +_replace_retry = retry(reraise=True, stop=stop_after_delay(1), wait=wait_fixed(0.25)) + +replace = _replace_retry(os.replace) # test_writable_dir and _test_writable_dir_win are copied from Flit, @@ -118,17 +119,17 @@ def _test_writable_dir_win(path: str) -> bool: raise OSError("Unexpected condition testing for writable directory") -def find_files(path: str, pattern: str) -> list[str]: +def find_files(path: str, pattern: str) -> List[str]: """Returns a list of absolute paths of files beneath path, recursively, with filenames which match the UNIX-style shell glob pattern.""" - result: list[str] = [] + result: List[str] = [] for root, _, files in os.walk(path): matches = fnmatch.filter(files, pattern) result.extend(os.path.join(root, f) for f in matches) return result -def file_size(path: str) -> int | float: +def file_size(path: str) -> Union[int, float]: # If it's a symlink, return 0. if os.path.islink(path): return 0 @@ -139,7 +140,7 @@ def format_file_size(path: str) -> str: return format_size(file_size(path)) -def directory_size(path: str) -> int | float: +def directory_size(path: str) -> Union[int, float]: size = 0.0 for root, _dirs, files in os.walk(path): for filename in files: @@ -150,15 +151,3 @@ def directory_size(path: str) -> int | float: def format_directory_size(path: str) -> str: return format_size(directory_size(path)) - - -def copy_directory_permissions(directory: str, target_file: BinaryIO) -> None: - mode = ( - os.stat(directory).st_mode & 0o666 # select read/write permissions of directory - | 0o600 # set owner read/write permissions - ) - # Change permissions only if there is no risk of following a symlink. - if os.chmod in os.supports_fd: - os.chmod(target_file.fileno(), mode) - elif os.chmod in os.supports_follow_symlinks: - os.chmod(target_file.name, mode, follow_symlinks=False) diff --git a/venv1/Lib/site-packages/pip/_internal/utils/filetypes.py b/venv1/Lib/site-packages/pip/_internal/utils/filetypes.py index 2b8baad7..59485701 100644 --- a/venv1/Lib/site-packages/pip/_internal/utils/filetypes.py +++ b/venv1/Lib/site-packages/pip/_internal/utils/filetypes.py @@ -1,18 +1,21 @@ -"""Filetype information.""" +"""Filetype information. +""" + +from typing import Tuple from pip._internal.utils.misc import splitext WHEEL_EXTENSION = ".whl" -BZ2_EXTENSIONS: tuple[str, ...] = (".tar.bz2", ".tbz") -XZ_EXTENSIONS: tuple[str, ...] = ( +BZ2_EXTENSIONS: Tuple[str, ...] = (".tar.bz2", ".tbz") +XZ_EXTENSIONS: Tuple[str, ...] = ( ".tar.xz", ".txz", ".tlz", ".tar.lz", ".tar.lzma", ) -ZIP_EXTENSIONS: tuple[str, ...] = (".zip", WHEEL_EXTENSION) -TAR_EXTENSIONS: tuple[str, ...] = (".tar.gz", ".tgz", ".tar") +ZIP_EXTENSIONS: Tuple[str, ...] = (".zip", WHEEL_EXTENSION) +TAR_EXTENSIONS: Tuple[str, ...] = (".tar.gz", ".tgz", ".tar") ARCHIVE_EXTENSIONS = ZIP_EXTENSIONS + BZ2_EXTENSIONS + TAR_EXTENSIONS + XZ_EXTENSIONS diff --git a/venv1/Lib/site-packages/pip/_internal/utils/glibc.py b/venv1/Lib/site-packages/pip/_internal/utils/glibc.py index 2cb3013c..7bd3c206 100644 --- a/venv1/Lib/site-packages/pip/_internal/utils/glibc.py +++ b/venv1/Lib/site-packages/pip/_internal/utils/glibc.py @@ -1,15 +1,17 @@ -from __future__ import annotations +# The following comment should be removed at some point in the future. +# mypy: strict-optional=False import os import sys +from typing import Optional, Tuple -def glibc_version_string() -> str | None: +def glibc_version_string() -> Optional[str]: "Returns glibc version string, or None if not using glibc." return glibc_version_string_confstr() or glibc_version_string_ctypes() -def glibc_version_string_confstr() -> str | None: +def glibc_version_string_confstr() -> Optional[str]: "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 @@ -18,18 +20,15 @@ def glibc_version_string_confstr() -> str | None: if sys.platform == "win32": return None try: - gnu_libc_version = os.confstr("CS_GNU_LIBC_VERSION") - if gnu_libc_version is None: - return None # os.confstr("CS_GNU_LIBC_VERSION") returns a string like "glibc 2.17": - _, version = gnu_libc_version.split() + _, version = os.confstr("CS_GNU_LIBC_VERSION").split() except (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: +def glibc_version_string_ctypes() -> Optional[str]: "Fallback implementation of glibc_version_string using ctypes." try: @@ -41,20 +40,7 @@ def glibc_version_string_ctypes() -> str | None: # 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't proceed, so we bail on our attempt. - try: - process_namespace = ctypes.CDLL(None) - except OSError: - return None - + process_namespace = ctypes.CDLL(None) try: gnu_get_libc_version = process_namespace.gnu_get_libc_version except AttributeError: @@ -64,7 +50,7 @@ def glibc_version_string_ctypes() -> str | 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() + version_str = gnu_get_libc_version() # py2 / py3 compatibility: if not isinstance(version_str, str): version_str = version_str.decode("ascii") @@ -89,7 +75,7 @@ def glibc_version_string_ctypes() -> str | None: # versions that was generated by pip 8.1.2 and earlier is useless and # misleading. Solution: instead of using platform, use our code that actually # works. -def libc_ver() -> tuple[str, str]: +def libc_ver() -> Tuple[str, str]: """Try to determine the glibc version Returns a tuple of strings (lib, version) which default to empty strings diff --git a/venv1/Lib/site-packages/pip/_internal/utils/hashes.py b/venv1/Lib/site-packages/pip/_internal/utils/hashes.py index 3d8c125a..843cffc6 100644 --- a/venv1/Lib/site-packages/pip/_internal/utils/hashes.py +++ b/venv1/Lib/site-packages/pip/_internal/utils/hashes.py @@ -1,8 +1,5 @@ -from __future__ import annotations - import hashlib -from collections.abc import Iterable -from typing import TYPE_CHECKING, BinaryIO, NoReturn +from typing import TYPE_CHECKING, BinaryIO, Dict, Iterable, List, Optional from pip._internal.exceptions import HashMismatch, HashMissing, InstallationError from pip._internal.utils.misc import read_chunks @@ -10,6 +7,10 @@ if TYPE_CHECKING: from hashlib import _Hash + # NoReturn introduced in 3.6.2; imported only for type checking to maintain + # pip compatibility with older patch versions of Python 3.6 + from typing import NoReturn + # The recommended hash algo of the moment. Change this whenever the state of # the art changes; it won't hurt backward compatibility. @@ -27,7 +28,7 @@ class Hashes: """ - def __init__(self, hashes: dict[str, list[str]] | None = None) -> None: + def __init__(self, hashes: Optional[Dict[str, List[str]]] = None) -> None: """ :param hashes: A dict of algorithm names pointing to lists of allowed hex digests @@ -36,10 +37,10 @@ def __init__(self, hashes: dict[str, list[str]] | None = None) -> None: if hashes is not None: for alg, keys in hashes.items(): # Make sure values are always sorted (to ease equality checks) - allowed[alg] = [k.lower() for k in sorted(keys)] + allowed[alg] = sorted(keys) self._allowed = allowed - def __and__(self, other: Hashes) -> Hashes: + def __and__(self, other: "Hashes") -> "Hashes": if not isinstance(other, Hashes): return NotImplemented @@ -89,7 +90,7 @@ def check_against_chunks(self, chunks: Iterable[bytes]) -> None: return self._raise(gots) - def _raise(self, gots: dict[str, _Hash]) -> NoReturn: + def _raise(self, gots: Dict[str, "_Hash"]) -> "NoReturn": raise HashMismatch(self._allowed, gots) def check_against_file(self, file: BinaryIO) -> None: @@ -104,7 +105,7 @@ def check_against_path(self, path: str) -> None: with open(path, "rb") as file: return self.check_against_file(file) - def has_one_of(self, hashes: dict[str, str]) -> bool: + def has_one_of(self, hashes: Dict[str, str]) -> bool: """Return whether any of the given hashes are allowed.""" for hash_name, hex_digest in hashes.items(): if self.is_hash_allowed(hash_name, hex_digest): @@ -146,5 +147,5 @@ def __init__(self) -> None: # empty list, it will never match, so an error will always raise. super().__init__(hashes={FAVORITE_HASH: []}) - def _raise(self, gots: dict[str, _Hash]) -> NoReturn: + def _raise(self, gots: Dict[str, "_Hash"]) -> "NoReturn": raise HashMissing(gots[FAVORITE_HASH].hexdigest()) diff --git a/venv1/Lib/site-packages/pip/_internal/utils/logging.py b/venv1/Lib/site-packages/pip/_internal/utils/logging.py index 5cdbeb7f..c10e1f4c 100644 --- a/venv1/Lib/site-packages/pip/_internal/utils/logging.py +++ b/venv1/Lib/site-packages/pip/_internal/utils/logging.py @@ -1,5 +1,3 @@ -from __future__ import annotations - import contextlib import errno import logging @@ -7,11 +5,10 @@ import os import sys import threading -from collections.abc import Generator from dataclasses import dataclass from io import TextIOWrapper from logging import Filter -from typing import Any, ClassVar +from typing import Any, ClassVar, Generator, List, Optional, TextIO, Type from pip._vendor.rich.console import ( Console, @@ -32,8 +29,6 @@ from pip._internal.utils.misc import ensure_dir _log_state = threading.local() -_stdout_console = None -_stderr_console = None subprocess_logger = getLogger("pip.subprocessor") @@ -43,7 +38,7 @@ class BrokenStdoutLoggingError(Exception): """ -def _is_broken_pipe_error(exc_class: type[BaseException], exc: BaseException) -> bool: +def _is_broken_pipe_error(exc_class: Type[BaseException], exc: BaseException) -> bool: if exc_class is BrokenPipeError: return True @@ -142,28 +137,12 @@ def __rich_console__( yield Segment("\n") -class PipConsole(Console): - def on_broken_pipe(self) -> None: - # Reraise the original exception, rich 13.8.0+ exits by default - # instead, preventing our handler from firing. - raise BrokenPipeError() from None - - -def get_console(*, stderr: bool = False) -> Console: - if stderr: - assert _stderr_console is not None, "stderr rich console is missing!" - return _stderr_console - else: - assert _stdout_console is not None, "stdout rich console is missing!" - return _stdout_console - - class RichPipStreamHandler(RichHandler): - KEYWORDS: ClassVar[list[str] | None] = [] + KEYWORDS: ClassVar[Optional[List[str]]] = [] - def __init__(self, console: Console) -> None: + def __init__(self, stream: Optional[TextIO], no_color: bool) -> None: super().__init__( - console=console, + console=Console(file=stream, no_color=no_color, soft_wrap=True), show_time=False, show_level=False, show_path=False, @@ -172,12 +151,12 @@ def __init__(self, console: Console) -> None: # Our custom override on Rich's logger, to make things work as we need them to. def emit(self, record: logging.LogRecord) -> None: - style: Style | None = None + style: Optional[Style] = None # If we are given a diagnostic error to present, present it with indentation. - if getattr(record, "rich", False): - assert isinstance(record.args, tuple) - (rich_renderable,) = record.args + assert isinstance(record.args, tuple) + if record.msg == "[present-rich] %s" and len(record.args) == 1: + rich_renderable = record.args[0] assert isinstance( rich_renderable, (ConsoleRenderable, RichCast, str) ), f"{rich_renderable} is not rich-console-renderable" @@ -233,6 +212,7 @@ def filter(self, record: logging.LogRecord) -> bool: class ExcludeLoggerFilter(Filter): + """ A logging Filter that excludes records from a logger (or its children). """ @@ -243,7 +223,7 @@ def filter(self, record: logging.LogRecord) -> bool: return not super().filter(record) -def setup_logging(verbosity: int, no_color: bool, user_log_file: str | None) -> int: +def setup_logging(verbosity: int, no_color: bool, user_log_file: Optional[str]) -> int: """Configures and sets up all of the logging Returns the requested logging level, as its integer value. @@ -280,6 +260,10 @@ def setup_logging(verbosity: int, no_color: bool, user_log_file: str | None) -> vendored_log_level = "WARNING" if level in ["INFO", "ERROR"] else "DEBUG" # Shorthands for clarity + log_streams = { + "stdout": "ext://sys.stdout", + "stderr": "ext://sys.stderr", + } handler_classes = { "stream": "pip._internal.utils.logging.RichPipStreamHandler", "file": "pip._internal.utils.logging.BetterRotatingFileHandler", @@ -287,9 +271,6 @@ def setup_logging(verbosity: int, no_color: bool, user_log_file: str | None) -> handlers = ["console", "console_errors", "console_subprocess"] + ( ["user_log"] if include_user_log else [] ) - global _stdout_console, stderr_console - _stdout_console = PipConsole(file=sys.stdout, no_color=no_color, soft_wrap=True) - _stderr_console = PipConsole(file=sys.stderr, no_color=no_color, soft_wrap=True) logging.config.dictConfig( { @@ -324,14 +305,16 @@ def setup_logging(verbosity: int, no_color: bool, user_log_file: str | None) -> "console": { "level": level, "class": handler_classes["stream"], - "console": _stdout_console, + "no_color": no_color, + "stream": log_streams["stdout"], "filters": ["exclude_subprocess", "exclude_warnings"], "formatter": "indent", }, "console_errors": { "level": "WARNING", "class": handler_classes["stream"], - "console": _stderr_console, + "no_color": no_color, + "stream": log_streams["stderr"], "filters": ["exclude_subprocess"], "formatter": "indent", }, @@ -340,7 +323,8 @@ def setup_logging(verbosity: int, no_color: bool, user_log_file: str | None) -> "console_subprocess": { "level": level, "class": handler_classes["stream"], - "console": _stderr_console, + "stream": log_streams["stderr"], + "no_color": no_color, "filters": ["restrict_to_subprocess"], "formatter": "indent", }, diff --git a/venv1/Lib/site-packages/pip/_internal/utils/misc.py b/venv1/Lib/site-packages/pip/_internal/utils/misc.py index 3a28e844..bfed8270 100644 --- a/venv1/Lib/site-packages/pip/_internal/utils/misc.py +++ b/venv1/Lib/site-packages/pip/_internal/utils/misc.py @@ -1,8 +1,11 @@ -from __future__ import annotations +# The following comment should be removed at some point in the future. +# mypy: strict-optional=False +import contextlib import errno import getpass import hashlib +import io import logging import os import posixpath @@ -11,31 +14,35 @@ import sys import sysconfig import urllib.parse -from collections.abc import Generator, Iterable, Iterator, Mapping, Sequence -from dataclasses import dataclass -from functools import partial from io import StringIO from itertools import filterfalse, tee, zip_longest -from pathlib import Path -from types import FunctionType, TracebackType +from types import TracebackType from typing import ( Any, BinaryIO, Callable, + ContextManager, + Dict, + Generator, + Iterable, + Iterator, + List, Optional, TextIO, + Tuple, + Type, TypeVar, + Union, cast, ) -from pip._vendor.packaging.requirements import Requirement from pip._vendor.pyproject_hooks import BuildBackendHookCaller +from pip._vendor.tenacity import retry, stop_after_delay, wait_fixed from pip import __version__ from pip._internal.exceptions import CommandError, ExternallyManagedEnvironment from pip._internal.locations import get_major_minor_version from pip._internal.utils.compat import WINDOWS -from pip._internal.utils.retry import retry from pip._internal.utils.virtualenv import running_under_virtualenv __all__ = [ @@ -49,6 +56,7 @@ "normalize_path", "renames", "get_prog", + "captured_stdout", "ensure_dir", "remove_auth_from_url", "check_externally_managed", @@ -58,23 +66,23 @@ logger = logging.getLogger(__name__) T = TypeVar("T") -ExcInfo = tuple[type[BaseException], BaseException, TracebackType] -VersionInfo = tuple[int, int, int] -NetlocTuple = tuple[str, tuple[Optional[str], Optional[str]]] -OnExc = Callable[[FunctionType, Path, BaseException], Any] -OnErr = Callable[[FunctionType, Path, ExcInfo], Any] - -FILE_CHUNK_SIZE = 1024 * 1024 +ExcInfo = Tuple[Type[BaseException], BaseException, TracebackType] +VersionInfo = Tuple[int, int, int] +NetlocTuple = Tuple[str, Tuple[Optional[str], Optional[str]]] def get_pip_version() -> str: pip_pkg_dir = os.path.join(os.path.dirname(__file__), "..", "..") pip_pkg_dir = os.path.abspath(pip_pkg_dir) - return f"pip {__version__} from {pip_pkg_dir} (python {get_major_minor_version()})" + return "pip {} from {} (python {})".format( + __version__, + pip_pkg_dir, + get_major_minor_version(), + ) -def normalize_version_info(py_version_info: tuple[int, ...]) -> tuple[int, int, int]: +def normalize_version_info(py_version_info: Tuple[int, ...]) -> Tuple[int, int, int]: """ Convert a tuple of ints representing a Python version to one of length three. @@ -116,67 +124,30 @@ def get_prog() -> str: # Retry every half second for up to 3 seconds -@retry(stop_after_delay=3, wait=0.5) -def rmtree(dir: str, ignore_errors: bool = False, onexc: OnExc | None = None) -> None: - if ignore_errors: - onexc = _onerror_ignore - if onexc is None: - onexc = _onerror_reraise - 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 - else: - shutil.rmtree(dir, onerror=handler) # type: ignore - - -def _onerror_ignore(*_args: Any) -> None: - pass - +# Tenacity raises RetryError by default, explicitly raise the original exception +@retry(reraise=True, stop=stop_after_delay(3), wait=wait_fixed(0.5)) +def rmtree(dir: str, ignore_errors: bool = False) -> None: + shutil.rmtree(dir, ignore_errors=ignore_errors, onerror=rmtree_errorhandler) -def _onerror_reraise(*_args: Any) -> None: - raise # noqa: PLE0704 - Bare exception used to reraise existing exception - -def rmtree_errorhandler( - func: FunctionType, - path: Path, - exc_info: ExcInfo | BaseException, - *, - onexc: OnExc = _onerror_reraise, -) -> None: - """ - `rmtree` error handler to 'force' a file remove (i.e. like `rm -f`). - - * If a file is readonly then it's write flag is set and operation is - retried. - - * `onerror` is the original callback from `rmtree(... onerror=onerror)` - that is chained at the end if the "rm -f" still fails. - """ +def rmtree_errorhandler(func: Callable[..., Any], path: str, exc_info: ExcInfo) -> None: + """On Windows, the files in .svn are read-only, so when rmtree() tries to + remove them, an exception is thrown. We catch that here, remove the + read-only attribute, and hopefully continue without problems.""" try: - st_mode = os.stat(path).st_mode + has_attr_readonly = not (os.stat(path).st_mode & stat.S_IWRITE) except OSError: # it's equivalent to os.path.exists return - if not st_mode & stat.S_IWRITE: + if has_attr_readonly: # convert to read/write - try: - os.chmod(path, st_mode | stat.S_IWRITE) - except OSError: - pass - else: - # use the original function to repeat the operation - try: - func(path) - return - except OSError: - pass - - if not isinstance(exc_info, BaseException): - _, exc_info, _ = exc_info - onexc(func, path, exc_info) + os.chmod(path, stat.S_IWRITE) + # use the original function to repeat the operation + func(path) + return + else: + raise def display_path(path: str) -> str: @@ -259,16 +230,16 @@ def strtobool(val: str) -> int: def format_size(bytes: float) -> str: if bytes > 1000 * 1000: - return f"{bytes / 1000.0 / 1000:.1f} MB" + return "{:.1f} MB".format(bytes / 1000.0 / 1000) elif bytes > 10 * 1000: - return f"{int(bytes / 1000)} kB" + return "{} kB".format(int(bytes / 1000)) elif bytes > 1000: - return f"{bytes / 1000.0:.1f} kB" + return "{:.1f} kB".format(bytes / 1000.0) else: - return f"{int(bytes)} bytes" + return "{} bytes".format(int(bytes)) -def tabulate(rows: Iterable[Iterable[Any]]) -> tuple[list[str], list[int]]: +def tabulate(rows: Iterable[Iterable[Any]]) -> Tuple[List[str], List[int]]: """Return a list of formatted rows and a list of column sizes. For example:: @@ -300,7 +271,7 @@ def is_installable_dir(path: str) -> bool: def read_chunks( - file: BinaryIO, size: int = FILE_CHUNK_SIZE + file: BinaryIO, size: int = io.DEFAULT_BUFFER_SIZE ) -> Generator[bytes, None, None]: """Yield pieces of data from a file-like object until EOF.""" while True: @@ -323,7 +294,7 @@ def normalize_path(path: str, resolve_symlinks: bool = True) -> str: return os.path.normcase(path) -def splitext(path: str) -> tuple[str, str]: +def splitext(path: str) -> Tuple[str, str]: """Like os.path.splitext, but take off .tar too""" base, ext = posixpath.splitext(path) if base.lower().endswith(".tar"): @@ -368,30 +339,63 @@ def write_output(msg: Any, *args: Any) -> None: class StreamWrapper(StringIO): - orig_stream: TextIO + orig_stream: TextIO = None @classmethod - def from_stream(cls, orig_stream: TextIO) -> StreamWrapper: - ret = cls() - ret.orig_stream = orig_stream - return ret + def from_stream(cls, orig_stream: TextIO) -> "StreamWrapper": + cls.orig_stream = orig_stream + return cls() # compileall.compile_dir() needs stdout.encoding to print to stdout - # type ignore is because TextIOBase.encoding is writeable + # https://github.com/python/mypy/issues/4125 @property - def encoding(self) -> str: # type: ignore + def encoding(self): # type: ignore return self.orig_stream.encoding +@contextlib.contextmanager +def captured_output(stream_name: str) -> Generator[StreamWrapper, None, None]: + """Return a context manager used by captured_stdout/stdin/stderr + that temporarily replaces the sys stream *stream_name* with a StringIO. + + Taken from Lib/support/__init__.py in the CPython repo. + """ + orig_stdout = getattr(sys, stream_name) + setattr(sys, stream_name, StreamWrapper.from_stream(orig_stdout)) + try: + yield getattr(sys, stream_name) + finally: + setattr(sys, stream_name, orig_stdout) + + +def captured_stdout() -> ContextManager[StreamWrapper]: + """Capture the output of sys.stdout: + + with captured_stdout() as stdout: + print('hello') + self.assertEqual(stdout.getvalue(), 'hello\n') + + Taken from Lib/support/__init__.py in the CPython repo. + """ + return captured_output("stdout") + + +def captured_stderr() -> ContextManager[StreamWrapper]: + """ + See captured_stdout(). + """ + return captured_output("stderr") + + # Simulates an enum -def enum(*sequential: Any, **named: Any) -> type[Any]: +def enum(*sequential: Any, **named: Any) -> Type[Any]: enums = dict(zip(sequential, range(len(sequential))), **named) reverse = {value: key for key, value in enums.items()} enums["reverse_mapping"] = reverse return type("Enum", (), enums) -def build_netloc(host: str, port: int | None) -> str: +def build_netloc(host: str, port: Optional[int]) -> str: """ Build a netloc from a host-port pair """ @@ -413,7 +417,7 @@ def build_url_from_netloc(netloc: str, scheme: str = "https") -> str: return f"{scheme}://{netloc}" -def parse_netloc(netloc: str) -> tuple[str | None, int | None]: +def parse_netloc(netloc: str) -> Tuple[str, Optional[int]]: """ Return the host-port pair from a netloc. """ @@ -435,7 +439,7 @@ def split_auth_from_netloc(netloc: str) -> NetlocTuple: # behaves if more than one @ is present (which can be checked using # the password attribute of urlsplit()'s return value). auth, netloc = netloc.rsplit("@", 1) - pw: str | None = None + pw: Optional[str] = None if ":" in auth: # Split from the left because that's how urllib.parse.urlsplit() # behaves if more than one : is present (which again can be checked @@ -468,12 +472,14 @@ def redact_netloc(netloc: str) -> str: else: user = urllib.parse.quote(user) password = ":****" - return f"{user}{password}@{netloc}" + return "{user}{password}@{netloc}".format( + user=user, password=password, netloc=netloc + ) def _transform_url( - url: str, transform_netloc: Callable[[str], tuple[Any, ...]] -) -> tuple[str, NetlocTuple]: + url: str, transform_netloc: Callable[[str], Tuple[Any, ...]] +) -> Tuple[str, NetlocTuple]: """Transform and replace netloc in a url. transform_netloc is a function taking the netloc and returning a @@ -495,13 +501,11 @@ def _get_netloc(netloc: str) -> NetlocTuple: return split_auth_from_netloc(netloc) -def _redact_netloc(netloc: str) -> tuple[str]: +def _redact_netloc(netloc: str) -> Tuple[str]: return (redact_netloc(netloc),) -def split_auth_netloc_from_url( - url: str, -) -> tuple[str, str, tuple[str | None, str | None]]: +def split_auth_netloc_from_url(url: str) -> Tuple[str, str, Tuple[str, str]]: """ Parse a url into separate netloc, auth, and url with no auth. @@ -523,27 +527,20 @@ def redact_auth_from_url(url: str) -> str: return _transform_url(url, _redact_netloc)[0] -def redact_auth_from_requirement(req: Requirement) -> str: - """Replace the password in a given requirement url with ****.""" - if not req.url: - return str(req) - return str(req).replace(req.url, redact_auth_from_url(req.url)) - - -@dataclass(frozen=True) class HiddenText: - secret: str - redacted: str + def __init__(self, secret: str, redacted: str) -> None: + self.secret = secret + self.redacted = redacted def __repr__(self) -> str: - return f"" + return "".format(str(self)) def __str__(self) -> str: return self.redacted # This is useful for testing. def __eq__(self, other: Any) -> bool: - if type(self) is not type(other): + if type(self) != type(other): return False # The string being used for redaction doesn't also have to match, @@ -606,7 +603,7 @@ def is_console_interactive() -> bool: return sys.stdin is not None and sys.stdin.isatty() -def hash_file(path: str, blocksize: int = 1 << 20) -> tuple[Any, int]: +def hash_file(path: str, blocksize: int = 1 << 20) -> Tuple[Any, int]: """Return (hash, length) for path using hashlib.sha256()""" h = hashlib.sha256() @@ -618,7 +615,7 @@ def hash_file(path: str, blocksize: int = 1 << 20) -> tuple[Any, int]: return h, length -def pairwise(iterable: Iterable[Any]) -> Iterator[tuple[Any, Any]]: +def pairwise(iterable: Iterable[Any]) -> Iterator[Tuple[Any, Any]]: """ Return paired elements. @@ -630,8 +627,9 @@ def pairwise(iterable: Iterable[Any]) -> Iterator[tuple[Any, Any]]: def partition( - pred: Callable[[T], bool], iterable: Iterable[T] -) -> tuple[Iterable[T], Iterable[T]]: + pred: Callable[[T], bool], + iterable: Iterable[T], +) -> Tuple[Iterable[T], Iterable[T]]: """ Use a predicate to partition entries into false entries and true entries, like @@ -648,9 +646,9 @@ def __init__( config_holder: Any, source_dir: str, build_backend: str, - backend_path: str | None = None, - runner: Callable[..., None] | None = None, - python_executable: str | None = None, + backend_path: Optional[str] = None, + runner: Optional[Callable[..., None]] = None, + python_executable: Optional[str] = None, ): super().__init__( source_dir, build_backend, backend_path, runner, python_executable @@ -660,8 +658,8 @@ def __init__( def build_wheel( self, wheel_directory: str, - config_settings: Mapping[str, Any] | None = None, - metadata_directory: str | None = None, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, + metadata_directory: Optional[str] = None, ) -> str: cs = self.config_holder.config_settings return super().build_wheel( @@ -671,7 +669,7 @@ def build_wheel( def build_sdist( self, sdist_directory: str, - config_settings: Mapping[str, Any] | None = None, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, ) -> str: cs = self.config_holder.config_settings return super().build_sdist(sdist_directory, config_settings=cs) @@ -679,8 +677,8 @@ def build_sdist( def build_editable( self, wheel_directory: str, - config_settings: Mapping[str, Any] | None = None, - metadata_directory: str | None = None, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, + metadata_directory: Optional[str] = None, ) -> str: cs = self.config_holder.config_settings return super().build_editable( @@ -688,27 +686,27 @@ def build_editable( ) def get_requires_for_build_wheel( - self, config_settings: Mapping[str, Any] | None = None - ) -> Sequence[str]: + self, config_settings: Optional[Dict[str, Union[str, List[str]]]] = None + ) -> List[str]: cs = self.config_holder.config_settings return super().get_requires_for_build_wheel(config_settings=cs) def get_requires_for_build_sdist( - self, config_settings: Mapping[str, Any] | None = None - ) -> Sequence[str]: + self, config_settings: Optional[Dict[str, Union[str, List[str]]]] = None + ) -> List[str]: cs = self.config_holder.config_settings return super().get_requires_for_build_sdist(config_settings=cs) def get_requires_for_build_editable( - self, config_settings: Mapping[str, Any] | None = None - ) -> Sequence[str]: + self, config_settings: Optional[Dict[str, Union[str, List[str]]]] = None + ) -> List[str]: cs = self.config_holder.config_settings return super().get_requires_for_build_editable(config_settings=cs) def prepare_metadata_for_build_wheel( self, metadata_directory: str, - config_settings: Mapping[str, Any] | None = None, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, _allow_fallback: bool = True, ) -> str: cs = self.config_holder.config_settings @@ -721,45 +719,12 @@ def prepare_metadata_for_build_wheel( def prepare_metadata_for_build_editable( self, metadata_directory: str, - config_settings: Mapping[str, Any] | None = None, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, _allow_fallback: bool = True, - ) -> str | None: + ) -> str: cs = self.config_holder.config_settings return super().prepare_metadata_for_build_editable( metadata_directory=metadata_directory, config_settings=cs, _allow_fallback=_allow_fallback, ) - - -def warn_if_run_as_root() -> None: - """Output a warning for sudo users on Unix. - - In a virtual environment, sudo pip still writes to virtualenv. - On Windows, users may run pip as Administrator without issues. - This warning only applies to Unix root users outside of virtualenv. - """ - if running_under_virtualenv(): - return - if not hasattr(os, "getuid"): - return - # On Windows, there are no "system managed" Python packages. Installing as - # Administrator via pip is the correct way of updating system environments. - # - # We choose sys.platform over utils.compat.WINDOWS here to enable Mypy platform - # checks: https://mypy.readthedocs.io/en/stable/common_issues.html - if sys.platform == "win32" or sys.platform == "cygwin": - return - - if os.getuid() != 0: - return - - logger.warning( - "Running pip as the 'root' user can result in broken permissions and " - "conflicting behaviour with the system package manager, possibly " - "rendering your system unusable. " - "It is recommended to use a virtual environment instead: " - "https://pip.pypa.io/warnings/venv. " - "Use the --root-user-action option if you know what you are doing and " - "want to suppress this warning." - ) diff --git a/venv1/Lib/site-packages/pip/_internal/utils/packaging.py b/venv1/Lib/site-packages/pip/_internal/utils/packaging.py index 3cbc0490..b9f6af4d 100644 --- a/venv1/Lib/site-packages/pip/_internal/utils/packaging.py +++ b/venv1/Lib/site-packages/pip/_internal/utils/packaging.py @@ -1,17 +1,18 @@ -from __future__ import annotations - import functools import logging +import re +from typing import NewType, Optional, Tuple, cast from pip._vendor.packaging import specifiers, version from pip._vendor.packaging.requirements import Requirement +NormalizedExtra = NewType("NormalizedExtra", str) + logger = logging.getLogger(__name__) -@functools.lru_cache(maxsize=32) def check_requires_python( - requires_python: str | None, version_info: tuple[int, ...] + requires_python: Optional[str], version_info: Tuple[int, ...] ) -> bool: """ Check if the given Python version matches a "Requires-Python" specifier. @@ -33,7 +34,7 @@ def check_requires_python( return python_version in requires_python_specifier -@functools.lru_cache(maxsize=10000) +@functools.lru_cache(maxsize=512) def get_requirement(req_string: str) -> Requirement: """Construct a packaging.Requirement object with caching""" # Parsing requirement strings is expensive, and is also expected to happen @@ -42,3 +43,15 @@ def get_requirement(req_string: str) -> Requirement: # minimize repeated parsing of the same string to construct equivalent # Requirement objects. return Requirement(req_string) + + +def safe_extra(extra: str) -> NormalizedExtra: + """Convert an arbitrary string to a standard 'extra' name + + Any runs of non-alphanumeric characters are replaced with a single '_', + and the result is always lowercased. + + This function is duplicated from ``pkg_resources``. Note that this is not + the same to either ``canonicalize_name`` or ``_egg_link_name``. + """ + return cast(NormalizedExtra, re.sub("[^A-Za-z0-9.-]+", "_", extra).lower()) diff --git a/venv1/Lib/site-packages/pip/_internal/utils/retry.py b/venv1/Lib/site-packages/pip/_internal/utils/retry.py deleted file mode 100644 index 27d3b6e7..00000000 --- a/venv1/Lib/site-packages/pip/_internal/utils/retry.py +++ /dev/null @@ -1,45 +0,0 @@ -from __future__ import annotations - -import functools -from time import perf_counter, sleep -from typing import TYPE_CHECKING, Callable, TypeVar - -if TYPE_CHECKING: - from typing_extensions import ParamSpec - - T = TypeVar("T") - P = ParamSpec("P") - - -def retry( - wait: float, stop_after_delay: float -) -> Callable[[Callable[P, T]], Callable[P, T]]: - """Decorator to automatically retry a function on error. - - If the function raises, the function is recalled with the same arguments - until it returns or the time limit is reached. When the time limit is - surpassed, the last exception raised is reraised. - - :param wait: The time to wait after an error before retrying, in seconds. - :param stop_after_delay: The time limit after which retries will cease, - in seconds. - """ - - def wrapper(func: Callable[P, T]) -> Callable[P, T]: - - @functools.wraps(func) - def retry_wrapped(*args: P.args, **kwargs: P.kwargs) -> T: - # The performance counter is monotonic on all platforms we care - # about and has much better resolution than time.monotonic(). - start_time = perf_counter() - while True: - try: - return func(*args, **kwargs) - except Exception: - if perf_counter() - start_time > stop_after_delay: - raise - sleep(wait) - - return retry_wrapped - - return wrapper diff --git a/venv1/Lib/site-packages/pip/_internal/utils/subprocess.py b/venv1/Lib/site-packages/pip/_internal/utils/subprocess.py index 3e7b83f3..1e8ff50e 100644 --- a/venv1/Lib/site-packages/pip/_internal/utils/subprocess.py +++ b/venv1/Lib/site-packages/pip/_internal/utils/subprocess.py @@ -1,11 +1,17 @@ -from __future__ import annotations - import logging import os import shlex import subprocess -from collections.abc import Iterable, Mapping -from typing import Any, Callable, Literal, Union +from typing import ( + TYPE_CHECKING, + Any, + Callable, + Iterable, + List, + Mapping, + Optional, + Union, +) from pip._vendor.rich.markup import escape @@ -14,10 +20,16 @@ from pip._internal.utils.logging import VERBOSE, subprocess_logger from pip._internal.utils.misc import HiddenText -CommandArgs = list[Union[str, HiddenText]] +if TYPE_CHECKING: + # Literal was introduced in Python 3.8. + # + # TODO: Remove `if TYPE_CHECKING` when dropping support for Python 3.7. + from typing import Literal + +CommandArgs = List[Union[str, HiddenText]] -def make_command(*args: str | HiddenText | CommandArgs) -> CommandArgs: +def make_command(*args: Union[str, HiddenText, CommandArgs]) -> CommandArgs: """ Create a CommandArgs object. """ @@ -34,7 +46,7 @@ def make_command(*args: str | HiddenText | CommandArgs) -> CommandArgs: return command_args -def format_command_args(args: list[str] | CommandArgs) -> str: +def format_command_args(args: Union[List[str], CommandArgs]) -> str: """ Format command arguments for display. """ @@ -49,7 +61,7 @@ def format_command_args(args: list[str] | CommandArgs) -> str: ) -def reveal_command_args(args: list[str] | CommandArgs) -> list[str]: +def reveal_command_args(args: Union[List[str], CommandArgs]) -> List[str]: """ Return the arguments in their raw, unredacted form. """ @@ -57,16 +69,16 @@ def reveal_command_args(args: list[str] | CommandArgs) -> list[str]: def call_subprocess( - cmd: list[str] | CommandArgs, + cmd: Union[List[str], CommandArgs], show_stdout: bool = False, - cwd: str | None = None, - on_returncode: Literal["raise", "warn", "ignore"] = "raise", - extra_ok_returncodes: Iterable[int] | None = None, - extra_environ: Mapping[str, Any] | None = None, - unset_environ: Iterable[str] | None = None, - spinner: SpinnerInterface | None = None, - log_failed_cmd: bool | None = True, - stdout_only: bool | None = False, + cwd: Optional[str] = None, + on_returncode: 'Literal["raise", "warn", "ignore"]' = "raise", + extra_ok_returncodes: Optional[Iterable[int]] = None, + extra_environ: Optional[Mapping[str, Any]] = None, + unset_environ: Optional[Iterable[str]] = None, + spinner: Optional[SpinnerInterface] = None, + log_failed_cmd: Optional[bool] = True, + stdout_only: Optional[bool] = False, *, command_desc: str, ) -> str: @@ -197,7 +209,7 @@ def call_subprocess( output_lines=all_output if not showing_subprocess else None, ) if log_failed_cmd: - subprocess_logger.error("%s", error, extra={"rich": True}) + subprocess_logger.error("[present-rich] %s", error) subprocess_logger.verbose( "[bold magenta]full command[/]: [blue]%s[/]", escape(format_command_args(cmd)), @@ -232,9 +244,9 @@ def runner_with_spinner_message(message: str) -> Callable[..., None]: """ def runner( - cmd: list[str], - cwd: str | None = None, - extra_environ: Mapping[str, Any] | None = None, + cmd: List[str], + cwd: Optional[str] = None, + extra_environ: Optional[Mapping[str, Any]] = None, ) -> None: with open_spinner(message) as spinner: call_subprocess( diff --git a/venv1/Lib/site-packages/pip/_internal/utils/temp_dir.py b/venv1/Lib/site-packages/pip/_internal/utils/temp_dir.py index a9afa76c..8ee8a1cb 100644 --- a/venv1/Lib/site-packages/pip/_internal/utils/temp_dir.py +++ b/venv1/Lib/site-packages/pip/_internal/utils/temp_dir.py @@ -1,19 +1,10 @@ -from __future__ import annotations - import errno import itertools import logging import os.path import tempfile -import traceback -from collections.abc import Generator from contextlib import ExitStack, contextmanager -from pathlib import Path -from typing import ( - Any, - Callable, - TypeVar, -) +from typing import Any, Dict, Generator, Optional, TypeVar, Union from pip._internal.utils.misc import enum, rmtree @@ -31,7 +22,7 @@ ) -_tempdir_manager: ExitStack | None = None +_tempdir_manager: Optional[ExitStack] = None @contextmanager @@ -49,7 +40,7 @@ class TempDirectoryTypeRegistry: """Manages temp directory behavior""" def __init__(self) -> None: - self._should_delete: dict[str, bool] = {} + self._should_delete: Dict[str, bool] = {} def set_delete(self, kind: str, value: bool) -> None: """Indicate whether a TempDirectory of the given kind should be @@ -64,7 +55,7 @@ def get_delete(self, kind: str) -> bool: return self._should_delete.get(kind, True) -_tempdir_registry: TempDirectoryTypeRegistry | None = None +_tempdir_registry: Optional[TempDirectoryTypeRegistry] = None @contextmanager @@ -111,11 +102,10 @@ class TempDirectory: def __init__( self, - path: str | None = None, - delete: bool | None | _Default = _default, + path: Optional[str] = None, + delete: Union[bool, None, _Default] = _default, kind: str = "temp", globally_managed: bool = False, - ignore_cleanup_errors: bool = True, ): super().__init__() @@ -138,7 +128,6 @@ def __init__( self._deleted = False self.delete = delete self.kind = kind - self.ignore_cleanup_errors = ignore_cleanup_errors if globally_managed: assert _tempdir_manager is not None @@ -181,44 +170,7 @@ def cleanup(self) -> None: self._deleted = True if not os.path.exists(self._path): return - - errors: list[BaseException] = [] - - def onerror( - func: Callable[..., Any], - path: Path, - exc_val: BaseException, - ) -> None: - """Log a warning for a `rmtree` error and continue""" - formatted_exc = "\n".join( - traceback.format_exception_only(type(exc_val), exc_val) - ) - formatted_exc = formatted_exc.rstrip() # remove trailing new line - if func in (os.unlink, os.remove, os.rmdir): - logger.debug( - "Failed to remove a temporary file '%s' due to %s.\n", - path, - formatted_exc, - ) - else: - logger.debug("%s failed with %s.", func.__qualname__, formatted_exc) - errors.append(exc_val) - - if self.ignore_cleanup_errors: - try: - # first try with @retry; retrying to handle ephemeral errors - rmtree(self._path, ignore_errors=False) - except OSError: - # last pass ignore/log all errors - rmtree(self._path, onexc=onerror) - if errors: - logger.warning( - "Failed to remove contents in a temporary directory '%s'.\n" - "You can safely remove it manually.", - self._path, - ) - else: - rmtree(self._path) + rmtree(self._path) class AdjacentTempDirectory(TempDirectory): @@ -243,7 +195,7 @@ class AdjacentTempDirectory(TempDirectory): # with leading '-' and invalid metadata LEADING_CHARS = "-~.=%0123456789" - def __init__(self, original: str, delete: bool | None = None) -> None: + def __init__(self, original: str, delete: Optional[bool] = None) -> None: self.original = original.rstrip("/\\") super().__init__(delete=delete) diff --git a/venv1/Lib/site-packages/pip/_internal/utils/unpacking.py b/venv1/Lib/site-packages/pip/_internal/utils/unpacking.py index bc950ac9..78b5c13c 100644 --- a/venv1/Lib/site-packages/pip/_internal/utils/unpacking.py +++ b/venv1/Lib/site-packages/pip/_internal/utils/unpacking.py @@ -1,15 +1,13 @@ -"""Utilities related archives.""" - -from __future__ import annotations +"""Utilities related archives. +""" import logging import os import shutil import stat -import sys import tarfile import zipfile -from collections.abc import Iterable +from typing import Iterable, List, Optional from zipfile import ZipInfo from pip._internal.exceptions import InstallationError @@ -49,7 +47,7 @@ def current_umask() -> int: return mask -def split_leading_dir(path: str) -> list[str]: +def split_leading_dir(path: str) -> List[str]: path = path.lstrip("/").lstrip("\\") if "/" in path and ( ("\\" in path and path.find("/") < path.find("\\")) or "\\" not in path @@ -87,16 +85,12 @@ def is_within_directory(directory: str, target: str) -> bool: return prefix == abs_directory -def _get_default_mode_plus_executable() -> int: - return 0o777 & ~current_umask() | 0o111 - - def set_extracted_file_to_default_mode_plus_executable(path: str) -> None: """ Make file present at path have execute for user/group/world (chmod +x) is no-op on windows per python docs """ - os.chmod(path, _get_default_mode_plus_executable()) + os.chmod(path, (0o777 & ~current_umask() | 0o111)) def zip_item_is_executable(info: ZipInfo) -> bool: @@ -133,7 +127,7 @@ def unzip_file(filename: str, location: str, flatten: bool = True) -> None: "outside target directory ({})" ) raise InstallationError(message.format(filename, fn, location)) - if fn.endswith(("/", "\\")): + if fn.endswith("/") or fn.endswith("\\"): # A directory ensure_dir(fn) else: @@ -157,8 +151,8 @@ def untar_file(filename: str, location: str) -> None: Untar the file (with path `filename`) to the destination `location`. All files are written based on system defaults and umask (i.e. permissions are not preserved), except that regular file members with any execute - permissions (user, group, or world) have "chmod +x" applied on top of the - default. Note that for windows, any execute changes using os.chmod are + permissions (user, group, or world) have "chmod +x" applied after being + written. Note that for windows, any execute changes using os.chmod are no-ops per the python docs. """ ensure_dir(location) @@ -176,165 +170,66 @@ def untar_file(filename: str, location: str) -> None: filename, ) mode = "r:*" - - tar = tarfile.open(filename, mode, encoding="utf-8") # type: ignore + tar = tarfile.open(filename, mode, encoding="utf-8") try: leading = has_leading_dir([member.name for member in tar.getmembers()]) - - # PEP 706 added `tarfile.data_filter`, and made some other changes to - # Python's tarfile module (see below). The features were backported to - # security releases. - try: - data_filter = tarfile.data_filter - except AttributeError: - _untar_without_filter(filename, location, tar, leading) - else: - default_mode_plus_executable = _get_default_mode_plus_executable() - + for member in tar.getmembers(): + fn = member.name if leading: - # Strip the leading directory from all files in the archive, - # including hardlink targets (which are relative to the - # unpack location). - for member in tar.getmembers(): - name_lead, name_rest = split_leading_dir(member.name) - member.name = name_rest - if member.islnk(): - lnk_lead, lnk_rest = split_leading_dir(member.linkname) - if lnk_lead == name_lead: - member.linkname = lnk_rest - - def pip_filter(member: tarfile.TarInfo, path: str) -> tarfile.TarInfo: - orig_mode = member.mode - try: - try: - member = data_filter(member, location) - except tarfile.LinkOutsideDestinationError: - if sys.version_info[:3] in { - (3, 9, 17), - (3, 10, 12), - (3, 11, 4), - }: - # The tarfile filter in specific Python versions - # raises LinkOutsideDestinationError on valid input - # (https://github.com/python/cpython/issues/107845) - # Ignore the error there, but do use the - # more lax `tar_filter` - member = tarfile.tar_filter(member, location) - else: - raise - except tarfile.TarError as exc: - message = "Invalid member in the tar file {}: {}" - # Filter error messages mention the member name. - # No need to add it here. - raise InstallationError( - message.format( - filename, - exc, - ) - ) - if member.isfile() and orig_mode & 0o111: - member.mode = default_mode_plus_executable - else: - # See PEP 706 note above. - # The PEP changed this from `int` to `Optional[int]`, - # where None means "use the default". Mypy doesn't - # know this yet. - member.mode = None # type: ignore [assignment] - return member - - tar.extractall(location, filter=pip_filter) - - finally: - tar.close() - - -def is_symlink_target_in_tar(tar: tarfile.TarFile, tarinfo: tarfile.TarInfo) -> bool: - """Check if the file pointed to by the symbolic link is in the tar archive""" - linkname = os.path.join(os.path.dirname(tarinfo.name), tarinfo.linkname) - - linkname = os.path.normpath(linkname) - linkname = linkname.replace("\\", "/") - - try: - tar.getmember(linkname) - return True - except KeyError: - return False - - -def _untar_without_filter( - filename: str, - location: str, - tar: tarfile.TarFile, - leading: bool, -) -> None: - """Fallback for Python without tarfile.data_filter""" - # NOTE: This function can be removed once pip requires CPython ≥ 3.12.​ - # PEP 706 added tarfile.data_filter, made tarfile extraction operations more secure. - # This feature is fully supported from CPython 3.12 onward. - for member in tar.getmembers(): - fn = member.name - if leading: - fn = split_leading_dir(fn)[1] - path = os.path.join(location, fn) - if not is_within_directory(location, path): - message = ( - "The tar file ({}) has a file ({}) trying to install " - "outside target directory ({})" - ) - raise InstallationError(message.format(filename, path, location)) - if member.isdir(): - ensure_dir(path) - elif member.issym(): - if not is_symlink_target_in_tar(tar, member): + fn = split_leading_dir(fn)[1] + path = os.path.join(location, fn) + if not is_within_directory(location, path): message = ( "The tar file ({}) has a file ({}) trying to install " "outside target directory ({})" ) - raise InstallationError( - message.format(filename, member.name, member.linkname) - ) - try: - tar._extract_member(member, path) - except Exception as exc: - # Some corrupt tar files seem to produce this - # (specifically bad symlinks) - logger.warning( - "In the tar file %s the member %s is invalid: %s", - filename, - member.name, - exc, - ) - continue - else: - try: - fp = tar.extractfile(member) - except (KeyError, AttributeError) as exc: - # Some corrupt tar files seem to produce this - # (specifically bad symlinks) - logger.warning( - "In the tar file %s the member %s is invalid: %s", - filename, - member.name, - exc, - ) - continue - ensure_dir(os.path.dirname(path)) - assert fp is not None - with open(path, "wb") as destfp: - shutil.copyfileobj(fp, destfp) - fp.close() - # Update the timestamp (useful for cython compiled files) - tar.utime(member, path) - # member have any execute permissions for user/group/world? - if member.mode & 0o111: - set_extracted_file_to_default_mode_plus_executable(path) + raise InstallationError(message.format(filename, path, location)) + if member.isdir(): + ensure_dir(path) + elif member.issym(): + try: + tar._extract_member(member, path) + except Exception as exc: + # Some corrupt tar files seem to produce this + # (specifically bad symlinks) + logger.warning( + "In the tar file %s the member %s is invalid: %s", + filename, + member.name, + exc, + ) + continue + else: + try: + fp = tar.extractfile(member) + except (KeyError, AttributeError) as exc: + # Some corrupt tar files seem to produce this + # (specifically bad symlinks) + logger.warning( + "In the tar file %s the member %s is invalid: %s", + filename, + member.name, + exc, + ) + continue + ensure_dir(os.path.dirname(path)) + assert fp is not None + with open(path, "wb") as destfp: + shutil.copyfileobj(fp, destfp) + fp.close() + # Update the timestamp (useful for cython compiled files) + tar.utime(member, path) + # member have any execute permissions for user/group/world? + if member.mode & 0o111: + set_extracted_file_to_default_mode_plus_executable(path) + finally: + tar.close() def unpack_file( filename: str, location: str, - content_type: str | None = None, + content_type: Optional[str] = None, ) -> None: filename = os.path.realpath(filename) if ( diff --git a/venv1/Lib/site-packages/pip/_internal/utils/urls.py b/venv1/Lib/site-packages/pip/_internal/utils/urls.py index e951a5e4..6ba2e04f 100644 --- a/venv1/Lib/site-packages/pip/_internal/utils/urls.py +++ b/venv1/Lib/site-packages/pip/_internal/utils/urls.py @@ -2,17 +2,24 @@ import string import urllib.parse import urllib.request +from typing import Optional from .compat import WINDOWS +def get_url_scheme(url: str) -> Optional[str]: + if ":" not in url: + return None + return url.split(":", 1)[0].lower() + + def path_to_url(path: str) -> str: """ Convert a path to a file: URL. The path will be made absolute and have quoted path parts. """ path = os.path.normpath(os.path.abspath(path)) - url = urllib.parse.urljoin("file://", urllib.request.pathname2url(path)) + url = urllib.parse.urljoin("file:", urllib.request.pathname2url(path)) return url diff --git a/venv1/Lib/site-packages/pip/_internal/utils/virtualenv.py b/venv1/Lib/site-packages/pip/_internal/utils/virtualenv.py index b1742a3e..882e36f5 100644 --- a/venv1/Lib/site-packages/pip/_internal/utils/virtualenv.py +++ b/venv1/Lib/site-packages/pip/_internal/utils/virtualenv.py @@ -1,10 +1,9 @@ -from __future__ import annotations - import logging import os import re import site import sys +from typing import List, Optional logger = logging.getLogger(__name__) _INCLUDE_SYSTEM_SITE_PACKAGES_REGEX = re.compile( @@ -34,7 +33,7 @@ def running_under_virtualenv() -> bool: return _running_under_venv() or _running_under_legacy_virtualenv() -def _get_pyvenv_cfg_lines() -> list[str] | None: +def _get_pyvenv_cfg_lines() -> Optional[List[str]]: """Reads {sys.prefix}/pyvenv.cfg and returns its contents as list of lines Returns None, if it could not read/access the file. diff --git a/venv1/Lib/site-packages/pip/_internal/utils/wheel.py b/venv1/Lib/site-packages/pip/_internal/utils/wheel.py index 789e7362..e5e3f34e 100644 --- a/venv1/Lib/site-packages/pip/_internal/utils/wheel.py +++ b/venv1/Lib/site-packages/pip/_internal/utils/wheel.py @@ -1,8 +1,10 @@ -"""Support functions for working with wheel files.""" +"""Support functions for working with wheel files. +""" import logging from email.message import Message from email.parser import Parser +from typing import Tuple from zipfile import BadZipFile, ZipFile from pip._vendor.packaging.utils import canonicalize_name @@ -15,7 +17,7 @@ logger = logging.getLogger(__name__) -def parse_wheel(wheel_zip: ZipFile, name: str) -> tuple[str, Message]: +def parse_wheel(wheel_zip: ZipFile, name: str) -> Tuple[str, Message]: """Extract information from the provided wheel, ensuring it meets basic standards. @@ -26,7 +28,7 @@ def parse_wheel(wheel_zip: ZipFile, name: str) -> tuple[str, Message]: metadata = wheel_metadata(wheel_zip, info_dir) version = wheel_version(metadata) except UnsupportedWheel as e: - raise UnsupportedWheel(f"{name} has an invalid wheel, {e}") + raise UnsupportedWheel("{} has an invalid wheel, {}".format(name, str(e))) check_compatibility(version, name) @@ -58,7 +60,9 @@ def wheel_dist_info_dir(source: ZipFile, name: str) -> str: canonical_name = canonicalize_name(name) if not info_dir_name.startswith(canonical_name): raise UnsupportedWheel( - f".dist-info directory {info_dir!r} does not start with {canonical_name!r}" + ".dist-info directory {!r} does not start with {!r}".format( + info_dir, canonical_name + ) ) return info_dir @@ -92,7 +96,7 @@ def wheel_metadata(source: ZipFile, dist_info_dir: str) -> Message: return Parser().parsestr(wheel_text) -def wheel_version(wheel_data: Message) -> tuple[int, ...]: +def wheel_version(wheel_data: Message) -> Tuple[int, ...]: """Given WHEEL metadata, return the parsed Wheel-Version. Otherwise, raise UnsupportedWheel. """ @@ -108,7 +112,7 @@ def wheel_version(wheel_data: Message) -> tuple[int, ...]: raise UnsupportedWheel(f"invalid Wheel-Version: {version!r}") -def check_compatibility(version: tuple[int, ...], name: str) -> None: +def check_compatibility(version: Tuple[int, ...], name: str) -> None: """Raises errors or warns if called with an incompatible Wheel-Version. pip should refuse to install a Wheel-Version that's a major series diff --git a/venv1/Lib/site-packages/pip/_internal/vcs/bazaar.py b/venv1/Lib/site-packages/pip/_internal/vcs/bazaar.py index 3a8a21e6..20a17ed0 100644 --- a/venv1/Lib/site-packages/pip/_internal/vcs/bazaar.py +++ b/venv1/Lib/site-packages/pip/_internal/vcs/bazaar.py @@ -1,6 +1,5 @@ -from __future__ import annotations - import logging +from typing import List, Optional, Tuple from pip._internal.utils.misc import HiddenText, display_path from pip._internal.utils.subprocess import make_command @@ -31,7 +30,7 @@ class Bazaar(VersionControl): ) @staticmethod - def get_base_rev_args(rev: str) -> list[str]: + def get_base_rev_args(rev: str) -> List[str]: return ["-r", rev] def fetch_new( @@ -45,51 +44,34 @@ def fetch_new( display_path(dest), ) if verbosity <= 0: - flags = ["--quiet"] + flag = "--quiet" elif verbosity == 1: - flags = [] + flag = "" else: - flags = [f"-{'v'*verbosity}"] + flag = f"-{'v'*verbosity}" cmd_args = make_command( - "checkout", "--lightweight", *flags, rev_options.to_args(), url, dest + "checkout", "--lightweight", flag, rev_options.to_args(), url, dest ) self.run_command(cmd_args) - def switch( - self, - dest: str, - url: HiddenText, - rev_options: RevOptions, - verbosity: int = 0, - ) -> None: + def switch(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: self.run_command(make_command("switch", url), cwd=dest) - def update( - self, - dest: str, - url: HiddenText, - rev_options: RevOptions, - verbosity: int = 0, - ) -> None: - flags = [] - - if verbosity <= 0: - flags.append("-q") - + def update(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: output = self.run_command( make_command("info"), show_stdout=False, stdout_only=True, cwd=dest ) if output.startswith("Standalone "): # Older versions of pip used to create standalone branches. # Convert the standalone branch to a checkout by calling "bzr bind". - cmd_args = make_command("bind", *flags, url) + cmd_args = make_command("bind", "-q", url) self.run_command(cmd_args, cwd=dest) - cmd_args = make_command("update", *flags, rev_options.to_args()) + cmd_args = make_command("update", "-q", rev_options.to_args()) self.run_command(cmd_args, cwd=dest) @classmethod - def get_url_rev_and_auth(cls, url: str) -> tuple[str, str | None, AuthInfo]: + def get_url_rev_and_auth(cls, url: str) -> Tuple[str, Optional[str], AuthInfo]: # hotfix the URL scheme after removing bzr+ from bzr+ssh:// re-add it url, rev, user_pass = super().get_url_rev_and_auth(url) if url.startswith("ssh://"): @@ -122,7 +104,7 @@ def get_revision(cls, location: str) -> str: return revision.splitlines()[-1] @classmethod - def is_commit_id_equal(cls, dest: str, name: str | None) -> bool: + def is_commit_id_equal(cls, dest: str, name: Optional[str]) -> bool: """Always assume the versions don't match""" return False diff --git a/venv1/Lib/site-packages/pip/_internal/vcs/git.py b/venv1/Lib/site-packages/pip/_internal/vcs/git.py index 1769da79..8d1d4993 100644 --- a/venv1/Lib/site-packages/pip/_internal/vcs/git.py +++ b/venv1/Lib/site-packages/pip/_internal/vcs/git.py @@ -1,13 +1,10 @@ -from __future__ import annotations - import logging import os.path import pathlib import re import urllib.parse import urllib.request -from dataclasses import replace -from typing import Any +from typing import List, Optional, Tuple from pip._internal.exceptions import BadCommand, InstallationError from pip._internal.utils.misc import HiddenText, display_path, hide_url @@ -76,18 +73,9 @@ class Git(VersionControl): default_arg_rev = "HEAD" @staticmethod - def get_base_rev_args(rev: str) -> list[str]: + def get_base_rev_args(rev: str) -> List[str]: return [rev] - @classmethod - def run_command(cls, *args: Any, **kwargs: Any) -> str: - if os.environ.get("PIP_NO_INPUT"): - extra_environ = kwargs.get("extra_environ", {}) - extra_environ["GIT_TERMINAL_PROMPT"] = "0" - extra_environ["GIT_SSH_COMMAND"] = "ssh -oBatchMode=yes" - kwargs["extra_environ"] = extra_environ - return super().run_command(*args, **kwargs) - def is_immutable_rev_checkout(self, url: str, dest: str) -> bool: _, rev_options = self.get_url_rev_options(hide_url(url)) if not rev_options.rev: @@ -102,7 +90,7 @@ def is_immutable_rev_checkout(self, url: str, dest: str) -> bool: is_tag_or_branch = bool(self.get_revision_sha(dest, rev_options.rev)[0]) return not is_tag_or_branch - def get_git_version(self) -> tuple[int, ...]: + def get_git_version(self) -> Tuple[int, ...]: version = self.run_command( ["version"], command_desc="git version", @@ -113,10 +101,10 @@ def get_git_version(self) -> tuple[int, ...]: if not match: logger.warning("Can't parse git version: %s", version) return () - return (int(match.group(1)), int(match.group(2))) + return tuple(int(c) for c in match.groups()) @classmethod - def get_current_branch(cls, location: str) -> str | None: + def get_current_branch(cls, location: str) -> Optional[str]: """ Return the current branch, or None if HEAD isn't at a branch (e.g. detached HEAD). @@ -141,7 +129,7 @@ def get_current_branch(cls, location: str) -> str | None: return None @classmethod - def get_revision_sha(cls, dest: str, rev: str) -> tuple[str | None, bool]: + def get_revision_sha(cls, dest: str, rev: str) -> Tuple[Optional[str], bool]: """ Return (sha_or_none, is_branch), where sha_or_none is a commit hash if the revision names a remote branch or tag, otherwise None. @@ -229,14 +217,14 @@ def resolve_revision( if sha is not None: rev_options = rev_options.make_new(sha) - rev_options = replace(rev_options, branch_name=(rev if is_branch else None)) + rev_options.branch_name = rev if is_branch else None return rev_options # Do not show a warning for the common case of something that has # the form of a Git commit hash. if not looks_like_hash(rev): - logger.info( + logger.warning( "Did not find branch or tag '%s', assuming revision or ref.", rev, ) @@ -256,7 +244,7 @@ def resolve_revision( return rev_options @classmethod - def is_commit_id_equal(cls, dest: str, name: str | None) -> bool: + def is_commit_id_equal(cls, dest: str, name: Optional[str]) -> bool: """ Return whether the current commit hash equals the given name. @@ -276,7 +264,7 @@ def fetch_new( rev_display = rev_options.to_display() logger.info("Cloning %s%s to %s", url, rev_display, display_path(dest)) if verbosity <= 0: - flags: tuple[str, ...] = ("--quiet",) + flags: Tuple[str, ...] = ("--quiet",) elif verbosity == 1: flags = () else: @@ -331,59 +319,31 @@ def fetch_new( logger.info("Resolved %s to commit %s", url, rev_options.rev) #: repo may contain submodules - self.update_submodules(dest, verbosity=verbosity) - - def switch( - self, - dest: str, - url: HiddenText, - rev_options: RevOptions, - verbosity: int = 0, - ) -> None: + self.update_submodules(dest) + + def switch(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: self.run_command( make_command("config", "remote.origin.url", url), cwd=dest, ) - - extra_flags = [] - - if verbosity <= 0: - extra_flags.append("-q") - - cmd_args = make_command("checkout", *extra_flags, rev_options.to_args()) + cmd_args = make_command("checkout", "-q", rev_options.to_args()) self.run_command(cmd_args, cwd=dest) - self.update_submodules(dest, verbosity=verbosity) - - def update( - self, - dest: str, - url: HiddenText, - rev_options: RevOptions, - verbosity: int = 0, - ) -> None: - extra_flags = [] - - if verbosity <= 0: - extra_flags.append("-q") + self.update_submodules(dest) + def update(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: # First fetch changes from the default remote if self.get_git_version() >= (1, 9): # fetch tags in addition to everything else - self.run_command(["fetch", "--tags", *extra_flags], cwd=dest) + self.run_command(["fetch", "-q", "--tags"], cwd=dest) else: - self.run_command(["fetch", *extra_flags], cwd=dest) + self.run_command(["fetch", "-q"], cwd=dest) # Then reset to wanted revision (maybe even origin/master) rev_options = self.resolve_revision(dest, url, rev_options) - cmd_args = make_command( - "reset", - "--hard", - *extra_flags, - rev_options.to_args(), - ) + cmd_args = make_command("reset", "--hard", "-q", rev_options.to_args()) self.run_command(cmd_args, cwd=dest) #: update submodules - self.update_submodules(dest, verbosity=verbosity) + self.update_submodules(dest) @classmethod def get_remote_url(cls, location: str) -> str: @@ -463,7 +423,7 @@ def has_commit(cls, location: str, rev: str) -> bool: return True @classmethod - def get_revision(cls, location: str, rev: str | None = None) -> str: + def get_revision(cls, location: str, rev: Optional[str] = None) -> str: if rev is None: rev = "HEAD" current_rev = cls.run_command( @@ -475,7 +435,7 @@ def get_revision(cls, location: str, rev: str | None = None) -> str: return current_rev.strip() @classmethod - def get_subdirectory(cls, location: str) -> str | None: + def get_subdirectory(cls, location: str) -> Optional[str]: """ Return the path to Python project root, relative to the repo root. Return None if the project root is in the repo root. @@ -493,7 +453,7 @@ def get_subdirectory(cls, location: str) -> str | None: return find_path_to_project_root_from_repo_root(location, repo_root) @classmethod - def get_url_rev_and_auth(cls, url: str) -> tuple[str, str | None, AuthInfo]: + def get_url_rev_and_auth(cls, url: str) -> Tuple[str, Optional[str], AuthInfo]: """ Prefixes stub URLs like 'user@hostname:user/repo.git' with 'ssh://'. That's required because although they use SSH they sometimes don't @@ -524,21 +484,16 @@ def get_url_rev_and_auth(cls, url: str) -> tuple[str, str | None, AuthInfo]: return url, rev, user_pass @classmethod - def update_submodules(cls, location: str, verbosity: int = 0) -> None: - argv = ["submodule", "update", "--init", "--recursive"] - - if verbosity <= 0: - argv.append("-q") - + def update_submodules(cls, location: str) -> None: if not os.path.exists(os.path.join(location, ".gitmodules")): return cls.run_command( - argv, + ["submodule", "update", "--init", "--recursive", "-q"], cwd=location, ) @classmethod - def get_repository_root(cls, location: str) -> str | None: + def get_repository_root(cls, location: str) -> Optional[str]: loc = super().get_repository_root(location) if loc: return loc diff --git a/venv1/Lib/site-packages/pip/_internal/vcs/mercurial.py b/venv1/Lib/site-packages/pip/_internal/vcs/mercurial.py index c8758031..2a005e0a 100644 --- a/venv1/Lib/site-packages/pip/_internal/vcs/mercurial.py +++ b/venv1/Lib/site-packages/pip/_internal/vcs/mercurial.py @@ -1,8 +1,7 @@ -from __future__ import annotations - import configparser import logging import os +from typing import List, Optional, Tuple from pip._internal.exceptions import BadCommand, InstallationError from pip._internal.utils.misc import HiddenText, display_path @@ -31,8 +30,8 @@ class Mercurial(VersionControl): ) @staticmethod - def get_base_rev_args(rev: str) -> list[str]: - return [f"--rev={rev}"] + def get_base_rev_args(rev: str) -> List[str]: + return [rev] def fetch_new( self, dest: str, url: HiddenText, rev_options: RevOptions, verbosity: int @@ -45,7 +44,7 @@ def fetch_new( display_path(dest), ) if verbosity <= 0: - flags: tuple[str, ...] = ("--quiet",) + flags: Tuple[str, ...] = ("--quiet",) elif verbosity == 1: flags = () elif verbosity == 2: @@ -58,20 +57,9 @@ def fetch_new( cwd=dest, ) - def switch( - self, - dest: str, - url: HiddenText, - rev_options: RevOptions, - verbosity: int = 0, - ) -> None: - extra_flags = [] + def switch(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: repo_config = os.path.join(dest, self.dirname, "hgrc") config = configparser.RawConfigParser() - - if verbosity <= 0: - extra_flags.append("-q") - try: config.read(repo_config) config.set("paths", "default", url.secret) @@ -80,23 +68,12 @@ def switch( except (OSError, configparser.NoSectionError) as exc: logger.warning("Could not switch Mercurial repository to %s: %s", url, exc) else: - cmd_args = make_command("update", *extra_flags, rev_options.to_args()) + cmd_args = make_command("update", "-q", rev_options.to_args()) self.run_command(cmd_args, cwd=dest) - def update( - self, - dest: str, - url: HiddenText, - rev_options: RevOptions, - verbosity: int = 0, - ) -> None: - extra_flags = [] - - if verbosity <= 0: - extra_flags.append("-q") - - self.run_command(["pull", *extra_flags], cwd=dest) - cmd_args = make_command("update", *extra_flags, rev_options.to_args()) + def update(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: + self.run_command(["pull", "-q"], cwd=dest) + cmd_args = make_command("update", "-q", rev_options.to_args()) self.run_command(cmd_args, cwd=dest) @classmethod @@ -139,12 +116,12 @@ def get_requirement_revision(cls, location: str) -> str: return current_rev_hash @classmethod - def is_commit_id_equal(cls, dest: str, name: str | None) -> bool: + def is_commit_id_equal(cls, dest: str, name: Optional[str]) -> bool: """Always assume the versions don't match""" return False @classmethod - def get_subdirectory(cls, location: str) -> str | None: + def get_subdirectory(cls, location: str) -> Optional[str]: """ Return the path to Python project root, relative to the repo root. Return None if the project root is in the repo root. @@ -158,7 +135,7 @@ def get_subdirectory(cls, location: str) -> str | None: return find_path_to_project_root_from_repo_root(location, repo_root) @classmethod - def get_repository_root(cls, location: str) -> str | None: + def get_repository_root(cls, location: str) -> Optional[str]: loc = super().get_repository_root(location) if loc: return loc diff --git a/venv1/Lib/site-packages/pip/_internal/vcs/subversion.py b/venv1/Lib/site-packages/pip/_internal/vcs/subversion.py index 579f428c..16d93a67 100644 --- a/venv1/Lib/site-packages/pip/_internal/vcs/subversion.py +++ b/venv1/Lib/site-packages/pip/_internal/vcs/subversion.py @@ -1,8 +1,7 @@ -from __future__ import annotations - import logging import os import re +from typing import List, Optional, Tuple from pip._internal.utils.misc import ( HiddenText, @@ -39,7 +38,7 @@ def should_add_vcs_url_prefix(cls, remote_url: str) -> bool: return True @staticmethod - def get_base_rev_args(rev: str) -> list[str]: + def get_base_rev_args(rev: str) -> List[str]: return ["-r", rev] @classmethod @@ -74,7 +73,7 @@ def get_revision(cls, location: str) -> str: @classmethod def get_netloc_and_auth( cls, netloc: str, scheme: str - ) -> tuple[str, tuple[str | None, str | None]]: + ) -> Tuple[str, Tuple[Optional[str], Optional[str]]]: """ This override allows the auth information to be passed to svn via the --username and --password options instead of via the URL. @@ -87,7 +86,7 @@ def get_netloc_and_auth( return split_auth_from_netloc(netloc) @classmethod - def get_url_rev_and_auth(cls, url: str) -> tuple[str, str | None, AuthInfo]: + def get_url_rev_and_auth(cls, url: str) -> Tuple[str, Optional[str], AuthInfo]: # hotfix the URL scheme after removing svn+ from svn+ssh:// re-add it url, rev, user_pass = super().get_url_rev_and_auth(url) if url.startswith("ssh://"): @@ -95,7 +94,9 @@ def get_url_rev_and_auth(cls, url: str) -> tuple[str, str | None, AuthInfo]: return url, rev, user_pass @staticmethod - def make_rev_args(username: str | None, password: HiddenText | None) -> CommandArgs: + def make_rev_args( + username: Optional[str], password: Optional[HiddenText] + ) -> CommandArgs: extra_args: CommandArgs = [] if username: extra_args += ["--username", username] @@ -129,7 +130,7 @@ def get_remote_url(cls, location: str) -> str: return url @classmethod - def _get_svn_url_rev(cls, location: str) -> tuple[str | None, int]: + def _get_svn_url_rev(cls, location: str) -> Tuple[Optional[str], int]: from pip._internal.exceptions import InstallationError entries_path = os.path.join(location, cls.dirname, "entries") @@ -140,7 +141,7 @@ def _get_svn_url_rev(cls, location: str) -> tuple[str | None, int]: data = "" url = None - if data.startswith(("8", "9", "10")): + if data.startswith("8") or data.startswith("9") or data.startswith("10"): entries = list(map(str.splitlines, data.split("\n\x0c\n"))) del entries[0][0] # get rid of the '8' url = entries[0][3] @@ -179,11 +180,11 @@ def _get_svn_url_rev(cls, location: str) -> tuple[str | None, int]: return url, rev @classmethod - def is_commit_id_equal(cls, dest: str, name: str | None) -> bool: + def is_commit_id_equal(cls, dest: str, name: Optional[str]) -> bool: """Always assume the versions don't match""" return False - def __init__(self, use_interactive: bool | None = None) -> None: + def __init__(self, use_interactive: Optional[bool] = None) -> None: if use_interactive is None: use_interactive = is_console_interactive() self.use_interactive = use_interactive @@ -193,11 +194,11 @@ def __init__(self, use_interactive: bool | None = None) -> None: # Special value definitions: # None: Not evaluated yet. # Empty tuple: Could not parse version. - self._vcs_version: tuple[int, ...] | None = None + self._vcs_version: Optional[Tuple[int, ...]] = None super().__init__() - def call_vcs_version(self) -> tuple[int, ...]: + def call_vcs_version(self) -> Tuple[int, ...]: """Query the version of the currently installed Subversion client. :return: A tuple containing the parts of the version information or @@ -225,7 +226,7 @@ def call_vcs_version(self) -> tuple[int, ...]: return parsed_version - def get_vcs_version(self) -> tuple[int, ...]: + def get_vcs_version(self) -> Tuple[int, ...]: """Return the version of the currently installed Subversion client. If the version of the Subversion client has already been queried, @@ -287,12 +288,12 @@ def fetch_new( display_path(dest), ) if verbosity <= 0: - flags = ["--quiet"] + flag = "--quiet" else: - flags = [] + flag = "" cmd_args = make_command( "checkout", - *flags, + flag, self.get_remote_call_options(), rev_options.to_args(), url, @@ -300,13 +301,7 @@ def fetch_new( ) self.run_command(cmd_args) - def switch( - self, - dest: str, - url: HiddenText, - rev_options: RevOptions, - verbosity: int = 0, - ) -> None: + def switch(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: cmd_args = make_command( "switch", self.get_remote_call_options(), @@ -316,13 +311,7 @@ def switch( ) self.run_command(cmd_args) - def update( - self, - dest: str, - url: HiddenText, - rev_options: RevOptions, - verbosity: int = 0, - ) -> None: + def update(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: cmd_args = make_command( "update", self.get_remote_call_options(), diff --git a/venv1/Lib/site-packages/pip/_internal/vcs/versioncontrol.py b/venv1/Lib/site-packages/pip/_internal/vcs/versioncontrol.py index 4e91ccd4..02bbf68e 100644 --- a/venv1/Lib/site-packages/pip/_internal/vcs/versioncontrol.py +++ b/venv1/Lib/site-packages/pip/_internal/vcs/versioncontrol.py @@ -1,18 +1,22 @@ """Handles all VCS (version control) support""" -from __future__ import annotations - import logging import os import shutil import sys import urllib.parse -from collections.abc import Iterable, Iterator, Mapping -from dataclasses import dataclass, field from typing import ( + TYPE_CHECKING, Any, - Literal, + Dict, + Iterable, + Iterator, + List, + Mapping, Optional, + Tuple, + Type, + Union, ) from pip._internal.cli.spinners import SpinnerInterface @@ -33,27 +37,35 @@ format_command_args, make_command, ) +from pip._internal.utils.urls import get_url_scheme + +if TYPE_CHECKING: + # Literal was introduced in Python 3.8. + # + # TODO: Remove `if TYPE_CHECKING` when dropping support for Python 3.7. + from typing import Literal + __all__ = ["vcs"] logger = logging.getLogger(__name__) -AuthInfo = tuple[Optional[str], Optional[str]] +AuthInfo = Tuple[Optional[str], Optional[str]] def is_url(name: str) -> bool: """ Return true if the name looks like a URL. """ - scheme = urllib.parse.urlsplit(name).scheme - if not scheme: + scheme = get_url_scheme(name) + if scheme is None: return False return scheme in ["http", "https", "file", "ftp"] + vcs.all_schemes def make_vcs_requirement_url( - repo_url: str, rev: str, project_name: str, subdir: str | None = None + repo_url: str, rev: str, project_name: str, subdir: Optional[str] = None ) -> str: """ Return the URL for a VCS requirement. @@ -72,7 +84,7 @@ def make_vcs_requirement_url( def find_path_to_project_root_from_repo_root( location: str, repo_root: str -) -> str | None: +) -> Optional[str]: """ Find the the Python project's root by searching up the filesystem from `location`. Return the path to project root relative to `repo_root`. @@ -109,28 +121,40 @@ def __init__(self, url: str): self.url = url -@dataclass(frozen=True) class RevOptions: + """ Encapsulates a VCS-specific revision to install, along with any VCS install options. - Args: - vc_class: a VersionControl subclass. - rev: the name of the revision to install. - extra_args: a list of extra options. + Instances of this class should be treated as if immutable. """ - vc_class: type[VersionControl] - rev: str | None = None - extra_args: CommandArgs = field(default_factory=list) - branch_name: str | None = None + def __init__( + self, + vc_class: Type["VersionControl"], + rev: Optional[str] = None, + extra_args: Optional[CommandArgs] = None, + ) -> None: + """ + Args: + vc_class: a VersionControl subclass. + rev: the name of the revision to install. + extra_args: a list of extra options. + """ + if extra_args is None: + extra_args = [] + + self.extra_args = extra_args + self.rev = rev + self.vc_class = vc_class + self.branch_name: Optional[str] = None def __repr__(self) -> str: return f"" @property - def arg_rev(self) -> str | None: + def arg_rev(self) -> Optional[str]: if self.rev is None: return self.vc_class.default_arg_rev @@ -154,7 +178,7 @@ def to_display(self) -> str: return f" (to revision {self.rev})" - def make_new(self, rev: str) -> RevOptions: + def make_new(self, rev: str) -> "RevOptions": """ Make a copy of the current instance, but with a new rev. @@ -165,7 +189,7 @@ def make_new(self, rev: str) -> RevOptions: class VcsSupport: - _registry: dict[str, VersionControl] = {} + _registry: Dict[str, "VersionControl"] = {} schemes = ["ssh", "git", "hg", "bzr", "sftp", "svn"] def __init__(self) -> None: @@ -178,21 +202,21 @@ def __iter__(self) -> Iterator[str]: return self._registry.__iter__() @property - def backends(self) -> list[VersionControl]: + def backends(self) -> List["VersionControl"]: return list(self._registry.values()) @property - def dirnames(self) -> list[str]: + def dirnames(self) -> List[str]: return [backend.dirname for backend in self.backends] @property - def all_schemes(self) -> list[str]: - schemes: list[str] = [] + def all_schemes(self) -> List[str]: + schemes: List[str] = [] for backend in self.backends: schemes.extend(backend.schemes) return schemes - def register(self, cls: type[VersionControl]) -> None: + def register(self, cls: Type["VersionControl"]) -> None: if not hasattr(cls, "name"): logger.warning("Cannot register VCS %s", cls.__name__) return @@ -204,7 +228,7 @@ def unregister(self, name: str) -> None: if name in self._registry: del self._registry[name] - def get_backend_for_dir(self, location: str) -> VersionControl | None: + def get_backend_for_dir(self, location: str) -> Optional["VersionControl"]: """ Return a VersionControl object if a repository of that type is found at the given directory. @@ -227,7 +251,7 @@ def get_backend_for_dir(self, location: str) -> VersionControl | None: inner_most_repo_path = max(vcs_backends, key=len) return vcs_backends[inner_most_repo_path] - def get_backend_for_scheme(self, scheme: str) -> VersionControl | None: + def get_backend_for_scheme(self, scheme: str) -> Optional["VersionControl"]: """ Return a VersionControl object or None. """ @@ -236,7 +260,7 @@ def get_backend_for_scheme(self, scheme: str) -> VersionControl | None: return vcs_backend return None - def get_backend(self, name: str) -> VersionControl | None: + def get_backend(self, name: str) -> Optional["VersionControl"]: """ Return a VersionControl object or None. """ @@ -252,10 +276,10 @@ class VersionControl: dirname = "" repo_name = "" # List of supported schemes for this Version Control - schemes: tuple[str, ...] = () + schemes: Tuple[str, ...] = () # Iterable of environment variable names to pass to call_subprocess(). - unset_environ: tuple[str, ...] = () - default_arg_rev: str | None = None + unset_environ: Tuple[str, ...] = () + default_arg_rev: Optional[str] = None @classmethod def should_add_vcs_url_prefix(cls, remote_url: str) -> bool: @@ -266,7 +290,7 @@ def should_add_vcs_url_prefix(cls, remote_url: str) -> bool: return not remote_url.lower().startswith(f"{cls.name}:") @classmethod - def get_subdirectory(cls, location: str) -> str | None: + def get_subdirectory(cls, location: str) -> Optional[str]: """ Return the path to Python project root, relative to the repo root. Return None if the project root is in the repo root. @@ -305,7 +329,7 @@ def get_src_requirement(cls, repo_dir: str, project_name: str) -> str: return req @staticmethod - def get_base_rev_args(rev: str) -> list[str]: + def get_base_rev_args(rev: str) -> List[str]: """ Return the base revision arguments for a vcs command. @@ -329,7 +353,7 @@ def is_immutable_rev_checkout(self, url: str, dest: str) -> bool: @classmethod def make_rev_options( - cls, rev: str | None = None, extra_args: CommandArgs | None = None + cls, rev: Optional[str] = None, extra_args: Optional[CommandArgs] = None ) -> RevOptions: """ Return a RevOptions object. @@ -338,7 +362,7 @@ def make_rev_options( rev: the name of a revision to install. extra_args: a list of extra options. """ - return RevOptions(cls, rev, extra_args=extra_args or []) + return RevOptions(cls, rev, extra_args=extra_args) @classmethod def _is_local_repository(cls, repo: str) -> bool: @@ -352,7 +376,7 @@ def _is_local_repository(cls, repo: str) -> bool: @classmethod def get_netloc_and_auth( cls, netloc: str, scheme: str - ) -> tuple[str, tuple[str | None, str | None]]: + ) -> Tuple[str, Tuple[Optional[str], Optional[str]]]: """ Parse the repository URL's netloc, and return the new netloc to use along with auth information. @@ -371,7 +395,7 @@ def get_netloc_and_auth( return netloc, (None, None) @classmethod - def get_url_rev_and_auth(cls, url: str) -> tuple[str, str | None, AuthInfo]: + def get_url_rev_and_auth(cls, url: str) -> Tuple[str, Optional[str], AuthInfo]: """ Parse the repository URL to use, and return the URL, revision, and auth info to use. @@ -381,9 +405,9 @@ def get_url_rev_and_auth(cls, url: str) -> tuple[str, str | None, AuthInfo]: scheme, netloc, path, query, frag = urllib.parse.urlsplit(url) if "+" not in scheme: raise ValueError( - f"Sorry, {url!r} is a malformed VCS url. " + "Sorry, {!r} is a malformed VCS url. " "The format is +://, " - "e.g. svn+http://myrepo/svn/MyApp#egg=MyApp" + "e.g. svn+http://myrepo/svn/MyApp#egg=MyApp".format(url) ) # Remove the vcs prefix. scheme = scheme.split("+", 1)[1] @@ -393,28 +417,30 @@ def get_url_rev_and_auth(cls, url: str) -> tuple[str, str | None, AuthInfo]: path, rev = path.rsplit("@", 1) if not rev: raise InstallationError( - f"The URL {url!r} has an empty revision (after @) " + "The URL {!r} has an empty revision (after @) " "which is not supported. Include a revision after @ " - "or remove @ from the URL." + "or remove @ from the URL.".format(url) ) url = urllib.parse.urlunsplit((scheme, netloc, path, query, "")) return url, rev, user_pass @staticmethod - def make_rev_args(username: str | None, password: HiddenText | None) -> CommandArgs: + def make_rev_args( + username: Optional[str], password: Optional[HiddenText] + ) -> CommandArgs: """ Return the RevOptions "extra arguments" to use in obtain(). """ return [] - def get_url_rev_options(self, url: HiddenText) -> tuple[HiddenText, RevOptions]: + def get_url_rev_options(self, url: HiddenText) -> Tuple[HiddenText, RevOptions]: """ Return the URL and RevOptions object to use in obtain(), as a tuple (url, rev_options). """ secret_url, rev, user_pass = self.get_url_rev_and_auth(url.secret) username, secret_password = user_pass - password: HiddenText | None = None + password: Optional[HiddenText] = None if secret_password is not None: password = hide_value(secret_password) extra_args = self.make_rev_args(username, password) @@ -451,13 +477,7 @@ def fetch_new( """ raise NotImplementedError - def switch( - self, - dest: str, - url: HiddenText, - rev_options: RevOptions, - verbosity: int = 0, - ) -> None: + def switch(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: """ Switch the repo at ``dest`` to point to ``URL``. @@ -466,13 +486,7 @@ def switch( """ raise NotImplementedError - def update( - self, - dest: str, - url: HiddenText, - rev_options: RevOptions, - verbosity: int = 0, - ) -> None: + def update(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: """ Update an already-existing repo to the given ``rev_options``. @@ -482,7 +496,7 @@ def update( raise NotImplementedError @classmethod - def is_commit_id_equal(cls, dest: str, name: str | None) -> bool: + def is_commit_id_equal(cls, dest: str, name: Optional[str]) -> bool: """ Return whether the id of the current commit equals the given name. @@ -524,7 +538,7 @@ def obtain(self, dest: str, url: HiddenText, verbosity: int) -> None: self.repo_name, rev_display, ) - self.update(dest, url, rev_options, verbosity=verbosity) + self.update(dest, url, rev_options) else: logger.info("Skipping because already up-to-date.") return @@ -552,7 +566,7 @@ def obtain(self, dest: str, url: HiddenText, verbosity: int) -> None: self.name, url, ) - response = ask_path_exists(f"What to do? {prompt[0]}", prompt[1]) + response = ask_path_exists("What to do? {}".format(prompt[0]), prompt[1]) if response == "a": sys.exit(-1) @@ -579,7 +593,7 @@ def obtain(self, dest: str, url: HiddenText, verbosity: int) -> None: url, rev_display, ) - self.switch(dest, url, rev_options, verbosity=verbosity) + self.switch(dest, url, rev_options) def unpack(self, location: str, url: HiddenText, verbosity: int) -> None: """ @@ -613,14 +627,14 @@ def get_revision(cls, location: str) -> str: @classmethod def run_command( cls, - cmd: list[str] | CommandArgs, + cmd: Union[List[str], CommandArgs], show_stdout: bool = True, - cwd: str | None = None, - on_returncode: Literal["raise", "warn", "ignore"] = "raise", - extra_ok_returncodes: Iterable[int] | None = None, - command_desc: str | None = None, - extra_environ: Mapping[str, Any] | None = None, - spinner: SpinnerInterface | None = None, + cwd: Optional[str] = None, + on_returncode: 'Literal["raise", "warn", "ignore"]' = "raise", + extra_ok_returncodes: Optional[Iterable[int]] = None, + command_desc: Optional[str] = None, + extra_environ: Optional[Mapping[str, Any]] = None, + spinner: Optional[SpinnerInterface] = None, log_failed_cmd: bool = True, stdout_only: bool = False, ) -> str: @@ -646,8 +660,6 @@ def run_command( log_failed_cmd=log_failed_cmd, stdout_only=stdout_only, ) - except NotADirectoryError: - raise BadCommand(f"Cannot find command {cls.name!r} - invalid PATH") except FileNotFoundError: # errno.ENOENT = no such file or directory # In other words, the VCS executable isn't available @@ -677,7 +689,7 @@ def is_repository_directory(cls, path: str) -> bool: return os.path.exists(os.path.join(path, cls.dirname)) @classmethod - def get_repository_root(cls, location: str) -> str | None: + def get_repository_root(cls, location: str) -> Optional[str]: """ Return the "root" (top-level) directory controlled by the vcs, or `None` if the directory is not in any. diff --git a/venv1/Lib/site-packages/pip/_internal/wheel_builder.py b/venv1/Lib/site-packages/pip/_internal/wheel_builder.py index 4dbf7677..60d75dd1 100644 --- a/venv1/Lib/site-packages/pip/_internal/wheel_builder.py +++ b/venv1/Lib/site-packages/pip/_internal/wheel_builder.py @@ -1,12 +1,11 @@ -"""Orchestrator for building wheels from InstallRequirements.""" - -from __future__ import annotations +"""Orchestrator for building wheels from InstallRequirements. +""" import logging import os.path import re -from collections.abc import Iterable -from tempfile import TemporaryDirectory +import shutil +from typing import Iterable, List, Optional, Tuple from pip._vendor.packaging.utils import canonicalize_name, canonicalize_version from pip._vendor.packaging.version import InvalidVersion, Version @@ -18,9 +17,13 @@ from pip._internal.models.wheel import Wheel from pip._internal.operations.build.wheel import build_wheel_pep517 from pip._internal.operations.build.wheel_editable import build_wheel_editable +from pip._internal.operations.build.wheel_legacy import build_wheel_legacy from pip._internal.req.req_install import InstallRequirement from pip._internal.utils.logging import indent_log from pip._internal.utils.misc import ensure_dir, hash_file +from pip._internal.utils.setuptools_build import make_setuptools_clean_args +from pip._internal.utils.subprocess import call_subprocess +from pip._internal.utils.temp_dir import TempDirectory from pip._internal.utils.urls import path_to_url from pip._internal.vcs import vcs @@ -28,7 +31,7 @@ _egg_info_re = re.compile(r"([a-z0-9_.]+)-([a-z0-9_.!+-]+)", re.IGNORECASE) -BuildResult = tuple[list[InstallRequirement], list[InstallRequirement]] +BuildResult = Tuple[List[InstallRequirement], List[InstallRequirement]] def _contains_egg_info(s: str) -> bool: @@ -39,12 +42,58 @@ def _contains_egg_info(s: str) -> bool: return bool(_egg_info_re.search(s)) +def _should_build( + req: InstallRequirement, + need_wheel: bool, +) -> bool: + """Return whether an InstallRequirement should be built into a wheel.""" + if req.constraint: + # never build requirements that are merely constraints + return False + if req.is_wheel: + if need_wheel: + logger.info( + "Skipping %s, due to already being wheel.", + req.name, + ) + return False + + if need_wheel: + # i.e. pip wheel, not pip install + return True + + # From this point, this concerns the pip install command only + # (need_wheel=False). + + if not req.source_dir: + return False + + if req.editable: + # we only build PEP 660 editable requirements + return req.supports_pyproject_editable() + + return True + + +def should_build_for_wheel_command( + req: InstallRequirement, +) -> bool: + return _should_build(req, need_wheel=True) + + +def should_build_for_install_command( + req: InstallRequirement, +) -> bool: + return _should_build(req, need_wheel=False) + + def _should_cache( req: InstallRequirement, -) -> bool | None: +) -> Optional[bool]: """ Return whether a built InstallRequirement can be stored in the persistent - wheel cache, assuming the wheel cache is available. + wheel cache, assuming the wheel cache is available, and _should_build() + has determined a wheel needs to be built. """ if req.editable or not req.source_dir: # never cache editable requirements @@ -89,17 +138,17 @@ def _get_cache_dir( def _verify_one(req: InstallRequirement, wheel_path: str) -> None: canonical_name = canonicalize_name(req.name or "") w = Wheel(os.path.basename(wheel_path)) - if w.name != canonical_name: + if canonicalize_name(w.name) != canonical_name: raise InvalidWheelFilename( - f"Wheel has unexpected file name: expected {canonical_name!r}, " - f"got {w.name!r}", + "Wheel has unexpected file name: expected {!r}, " + "got {!r}".format(canonical_name, w.name), ) dist = get_wheel_distribution(FilesystemWheel(wheel_path), canonical_name) dist_verstr = str(dist.version) if canonicalize_version(dist_verstr) != canonicalize_version(w.version): raise InvalidWheelFilename( - f"Wheel has unexpected file name: expected {dist_verstr!r}, " - f"got {w.version!r}", + "Wheel has unexpected file name: expected {!r}, " + "got {!r}".format(dist_verstr, w.version), ) metadata_version_value = dist.metadata_version if metadata_version_value is None: @@ -111,7 +160,8 @@ def _verify_one(req: InstallRequirement, wheel_path: str) -> None: raise UnsupportedWheel(msg) if metadata_version >= Version("1.2") and not isinstance(dist.version, Version): raise UnsupportedWheel( - f"Metadata 1.2 mandates PEP 440 version, but {dist_verstr!r} is not" + "Metadata 1.2 mandates PEP 440 version, " + "but {!r} is not".format(dist_verstr) ) @@ -119,8 +169,10 @@ def _build_one( req: InstallRequirement, output_dir: str, verify: bool, + build_options: List[str], + global_options: List[str], editable: bool, -) -> str | None: +) -> Optional[str]: """Build one wheel. :return: The filename of the built wheel, or None if the build failed. @@ -139,7 +191,9 @@ def _build_one( # Install build deps into temporary directory (PEP 518) with req.build_env: - wheel_path = _build_one_inside_env(req, output_dir, editable) + wheel_path = _build_one_inside_env( + req, output_dir, build_options, global_options, editable + ) if wheel_path and verify: try: _verify_one(req, wheel_path) @@ -152,25 +206,45 @@ def _build_one( def _build_one_inside_env( req: InstallRequirement, output_dir: str, + build_options: List[str], + global_options: List[str], editable: bool, -) -> str | None: - with TemporaryDirectory(dir=output_dir) as wheel_directory: +) -> Optional[str]: + with TempDirectory(kind="wheel") as temp_dir: assert req.name - assert req.metadata_directory - assert req.pep517_backend - if editable: - wheel_path = build_wheel_editable( - name=req.name, - backend=req.pep517_backend, - metadata_directory=req.metadata_directory, - wheel_directory=wheel_directory, - ) + if req.use_pep517: + assert req.metadata_directory + assert req.pep517_backend + if global_options: + logger.warning( + "Ignoring --global-option when building %s using PEP 517", req.name + ) + if build_options: + logger.warning( + "Ignoring --build-option when building %s using PEP 517", req.name + ) + if editable: + wheel_path = build_wheel_editable( + name=req.name, + backend=req.pep517_backend, + metadata_directory=req.metadata_directory, + tempd=temp_dir.path, + ) + else: + wheel_path = build_wheel_pep517( + name=req.name, + backend=req.pep517_backend, + metadata_directory=req.metadata_directory, + tempd=temp_dir.path, + ) else: - wheel_path = build_wheel_pep517( + wheel_path = build_wheel_legacy( name=req.name, - backend=req.pep517_backend, - metadata_directory=req.metadata_directory, - wheel_directory=wheel_directory, + setup_py_path=req.setup_py_path, + source_dir=req.unpacked_source_directory, + global_options=global_options, + build_options=build_options, + tempd=temp_dir.path, ) if wheel_path is not None: @@ -178,11 +252,7 @@ def _build_one_inside_env( dest_path = os.path.join(output_dir, wheel_name) try: wheel_hash, length = hash_file(wheel_path) - # We can do a replace here because wheel_path is guaranteed to - # be in the same filesystem as output_dir. This will perform an - # atomic rename, which is necessary to avoid concurrency issues - # when populating the cache. - os.replace(wheel_path, dest_path) + shutil.move(wheel_path, dest_path) logger.info( "Created wheel for %s: filename=%s size=%d sha256=%s", req.name, @@ -198,13 +268,35 @@ def _build_one_inside_env( req.name, e, ) + # Ignore return, we can't do anything else useful. + if not req.use_pep517: + _clean_one_legacy(req, global_options) return None +def _clean_one_legacy(req: InstallRequirement, global_options: List[str]) -> bool: + clean_args = make_setuptools_clean_args( + req.setup_py_path, + global_options=global_options, + ) + + logger.info("Running setup.py clean for %s", req.name) + try: + call_subprocess( + clean_args, command_desc="python setup.py clean", cwd=req.source_dir + ) + return True + except Exception: + logger.error("Failed cleaning build dir for %s", req.name) + return False + + def build( requirements: Iterable[InstallRequirement], wheel_cache: WheelCache, verify: bool, + build_options: List[str], + global_options: List[str], ) -> BuildResult: """Build wheels. @@ -229,6 +321,8 @@ def build( req, cache_dir, verify, + build_options, + global_options, req.editable and req.permit_editable_wheels, ) if wheel_file: diff --git a/venv1/Lib/site-packages/pip/_vendor/__init__.py b/venv1/Lib/site-packages/pip/_vendor/__init__.py index 34ccb990..b22f7abb 100644 --- a/venv1/Lib/site-packages/pip/_vendor/__init__.py +++ b/venv1/Lib/site-packages/pip/_vendor/__init__.py @@ -60,16 +60,20 @@ def vendored(modulename): # Actually alias all of our vendored dependencies. vendored("cachecontrol") vendored("certifi") - vendored("dependency-groups") + vendored("colorama") vendored("distlib") vendored("distro") + vendored("six") + vendored("six.moves") + vendored("six.moves.urllib") + vendored("six.moves.urllib.parse") vendored("packaging") vendored("packaging.version") vendored("packaging.specifiers") + vendored("pep517") vendored("pkg_resources") vendored("platformdirs") vendored("progress") - vendored("pyproject_hooks") vendored("requests") vendored("requests.exceptions") vendored("requests.packages") @@ -111,7 +115,6 @@ def vendored(modulename): vendored("rich.style") vendored("rich.text") vendored("rich.traceback") - if sys.version_info < (3, 11): - vendored("tomli") - vendored("truststore") + vendored("tenacity") + vendored("tomli") vendored("urllib3") diff --git a/venv1/Lib/site-packages/pip/_vendor/cachecontrol/__init__.py b/venv1/Lib/site-packages/pip/_vendor/cachecontrol/__init__.py index 67888db0..f631ae6d 100644 --- a/venv1/Lib/site-packages/pip/_vendor/cachecontrol/__init__.py +++ b/venv1/Lib/site-packages/pip/_vendor/cachecontrol/__init__.py @@ -6,24 +6,13 @@ Make it easy to import from cachecontrol without long namespaces. """ - __author__ = "Eric Larson" __email__ = "eric@ionrock.org" -__version__ = "0.14.3" - -from pip._vendor.cachecontrol.adapter import CacheControlAdapter -from pip._vendor.cachecontrol.controller import CacheController -from pip._vendor.cachecontrol.wrapper import CacheControl +__version__ = "0.12.11" -__all__ = [ - "__author__", - "__email__", - "__version__", - "CacheControlAdapter", - "CacheController", - "CacheControl", -] +from .wrapper import CacheControl +from .adapter import CacheControlAdapter +from .controller import CacheController import logging - logging.getLogger(__name__).addHandler(logging.NullHandler()) diff --git a/venv1/Lib/site-packages/pip/_vendor/cachecontrol/_cmd.py b/venv1/Lib/site-packages/pip/_vendor/cachecontrol/_cmd.py index 2c84208a..4266b5ee 100644 --- a/venv1/Lib/site-packages/pip/_vendor/cachecontrol/_cmd.py +++ b/venv1/Lib/site-packages/pip/_vendor/cachecontrol/_cmd.py @@ -1,11 +1,8 @@ # SPDX-FileCopyrightText: 2015 Eric Larson # # SPDX-License-Identifier: Apache-2.0 -from __future__ import annotations import logging -from argparse import ArgumentParser -from typing import TYPE_CHECKING from pip._vendor import requests @@ -13,19 +10,16 @@ from pip._vendor.cachecontrol.cache import DictCache from pip._vendor.cachecontrol.controller import logger -if TYPE_CHECKING: - from argparse import Namespace - - from pip._vendor.cachecontrol.controller import CacheController +from argparse import ArgumentParser -def setup_logging() -> None: +def setup_logging(): logger.setLevel(logging.DEBUG) handler = logging.StreamHandler() logger.addHandler(handler) -def get_session() -> requests.Session: +def get_session(): adapter = CacheControlAdapter( DictCache(), cache_etags=True, serializer=None, heuristic=None ) @@ -33,17 +27,17 @@ def get_session() -> requests.Session: sess.mount("http://", adapter) sess.mount("https://", adapter) - sess.cache_controller = adapter.controller # type: ignore[attr-defined] + sess.cache_controller = adapter.controller return sess -def get_args() -> Namespace: +def get_args(): parser = ArgumentParser() parser.add_argument("url", help="The URL to try and cache") return parser.parse_args() -def main() -> None: +def main(args=None): args = get_args() sess = get_session() @@ -54,13 +48,10 @@ def main() -> None: setup_logging() # try setting the cache - cache_controller: CacheController = ( - sess.cache_controller # type: ignore[attr-defined] - ) - cache_controller.cache_response(resp.request, resp.raw) + sess.cache_controller.cache_response(resp.request, resp.raw) # Now try to get it - if cache_controller.cached_request(resp.request): + if sess.cache_controller.cached_request(resp.request): print("Cached!") else: print("Not cached :(") diff --git a/venv1/Lib/site-packages/pip/_vendor/cachecontrol/adapter.py b/venv1/Lib/site-packages/pip/_vendor/cachecontrol/adapter.py index 18084d12..94c75e1a 100644 --- a/venv1/Lib/site-packages/pip/_vendor/cachecontrol/adapter.py +++ b/venv1/Lib/site-packages/pip/_vendor/cachecontrol/adapter.py @@ -1,27 +1,16 @@ # SPDX-FileCopyrightText: 2015 Eric Larson # # SPDX-License-Identifier: Apache-2.0 -from __future__ import annotations -import functools import types -import weakref +import functools import zlib -from typing import TYPE_CHECKING, Any, Collection, Mapping from pip._vendor.requests.adapters import HTTPAdapter -from pip._vendor.cachecontrol.cache import DictCache -from pip._vendor.cachecontrol.controller import PERMANENT_REDIRECT_STATUSES, CacheController -from pip._vendor.cachecontrol.filewrapper import CallbackFileWrapper - -if TYPE_CHECKING: - from pip._vendor.requests import PreparedRequest, Response - from pip._vendor.urllib3 import HTTPResponse - - from pip._vendor.cachecontrol.cache import BaseCache - from pip._vendor.cachecontrol.heuristics import BaseHeuristic - from pip._vendor.cachecontrol.serialize import Serializer +from .controller import CacheController, PERMANENT_REDIRECT_STATUSES +from .cache import DictCache +from .filewrapper import CallbackFileWrapper class CacheControlAdapter(HTTPAdapter): @@ -29,16 +18,16 @@ class CacheControlAdapter(HTTPAdapter): def __init__( self, - cache: BaseCache | None = None, - cache_etags: bool = True, - controller_class: type[CacheController] | None = None, - serializer: Serializer | None = None, - heuristic: BaseHeuristic | None = None, - cacheable_methods: Collection[str] | None = None, - *args: Any, - **kw: Any, - ) -> None: - super().__init__(*args, **kw) + cache=None, + cache_etags=True, + controller_class=None, + serializer=None, + heuristic=None, + cacheable_methods=None, + *args, + **kw + ): + super(CacheControlAdapter, self).__init__(*args, **kw) self.cache = DictCache() if cache is None else cache self.heuristic = heuristic self.cacheable_methods = cacheable_methods or ("GET",) @@ -48,16 +37,7 @@ def __init__( self.cache, cache_etags=cache_etags, serializer=serializer ) - def send( - self, - request: PreparedRequest, - stream: bool = False, - timeout: None | float | tuple[float, float] | tuple[float, None] = None, - verify: bool | str = True, - cert: (None | bytes | str | tuple[bytes | str, bytes | str]) = None, - proxies: Mapping[str, str] | None = None, - cacheable_methods: Collection[str] | None = None, - ) -> Response: + def send(self, request, cacheable_methods=None, **kw): """ Send a request. Use the request information to see if it exists in the cache and cache the response if we need to and can. @@ -74,17 +54,13 @@ def send( # check for etags and add headers if appropriate request.headers.update(self.controller.conditional_headers(request)) - resp = super().send(request, stream, timeout, verify, cert, proxies) + resp = super(CacheControlAdapter, self).send(request, **kw) return resp - def build_response( # type: ignore[override] - self, - request: PreparedRequest, - response: HTTPResponse, - from_cache: bool = False, - cacheable_methods: Collection[str] | None = None, - ) -> Response: + def build_response( + self, request, response, from_cache=False, cacheable_methods=None + ): """ Build a response by making a request or using the cache. @@ -126,43 +102,36 @@ def build_response( # type: ignore[override] else: # Wrap the response file with a wrapper that will cache the # response when the stream has been consumed. - response._fp = CallbackFileWrapper( # type: ignore[assignment] - response._fp, # type: ignore[arg-type] + response._fp = CallbackFileWrapper( + response._fp, functools.partial( - self.controller.cache_response, request, weakref.ref(response) + self.controller.cache_response, request, response ), ) if response.chunked: - super_update_chunk_length = response.__class__._update_chunk_length - - def _update_chunk_length( - weak_self: weakref.ReferenceType[HTTPResponse], - ) -> None: - self = weak_self() - if self is None: - return + super_update_chunk_length = response._update_chunk_length - super_update_chunk_length(self) + def _update_chunk_length(self): + super_update_chunk_length() if self.chunk_left == 0: - self._fp._close() # type: ignore[union-attr] + self._fp._close() - response._update_chunk_length = functools.partial( # type: ignore[method-assign] - _update_chunk_length, weakref.ref(response) + response._update_chunk_length = types.MethodType( + _update_chunk_length, response ) - resp: Response = super().build_response(request, response) + resp = super(CacheControlAdapter, self).build_response(request, response) # See if we should invalidate the cache. if request.method in self.invalidating_methods and resp.ok: - assert request.url is not None cache_url = self.controller.cache_url(request.url) self.cache.delete(cache_url) # Give the request a from_cache attr to let people use it - resp.from_cache = from_cache # type: ignore[attr-defined] + resp.from_cache = from_cache return resp - def close(self) -> None: + def close(self): self.cache.close() - super().close() # type: ignore[no-untyped-call] + super(CacheControlAdapter, self).close() diff --git a/venv1/Lib/site-packages/pip/_vendor/cachecontrol/cache.py b/venv1/Lib/site-packages/pip/_vendor/cachecontrol/cache.py index 91598e92..2a965f59 100644 --- a/venv1/Lib/site-packages/pip/_vendor/cachecontrol/cache.py +++ b/venv1/Lib/site-packages/pip/_vendor/cachecontrol/cache.py @@ -6,47 +6,38 @@ The cache object API for implementing caches. The default is a thread safe in-memory dictionary. """ - -from __future__ import annotations - from threading import Lock -from typing import IO, TYPE_CHECKING, MutableMapping -if TYPE_CHECKING: - from datetime import datetime +class BaseCache(object): -class BaseCache: - def get(self, key: str) -> bytes | None: + def get(self, key): raise NotImplementedError() - def set( - self, key: str, value: bytes, expires: int | datetime | None = None - ) -> None: + def set(self, key, value, expires=None): raise NotImplementedError() - def delete(self, key: str) -> None: + def delete(self, key): raise NotImplementedError() - def close(self) -> None: + def close(self): pass class DictCache(BaseCache): - def __init__(self, init_dict: MutableMapping[str, bytes] | None = None) -> None: + + def __init__(self, init_dict=None): self.lock = Lock() self.data = init_dict or {} - def get(self, key: str) -> bytes | None: + def get(self, key): return self.data.get(key, None) - def set( - self, key: str, value: bytes, expires: int | datetime | None = None - ) -> None: + def set(self, key, value, expires=None): with self.lock: self.data.update({key: value}) - def delete(self, key: str) -> None: + def delete(self, key): with self.lock: if key in self.data: self.data.pop(key) @@ -64,11 +55,10 @@ class SeparateBodyBaseCache(BaseCache): Similarly, the body should be loaded separately via ``get_body()``. """ - - def set_body(self, key: str, body: bytes) -> None: + def set_body(self, key, body): raise NotImplementedError() - def get_body(self, key: str) -> IO[bytes] | None: + def get_body(self, key): """ Return the body as file-like object. """ diff --git a/venv1/Lib/site-packages/pip/_vendor/cachecontrol/caches/__init__.py b/venv1/Lib/site-packages/pip/_vendor/cachecontrol/caches/__init__.py index 24ff469f..37827291 100644 --- a/venv1/Lib/site-packages/pip/_vendor/cachecontrol/caches/__init__.py +++ b/venv1/Lib/site-packages/pip/_vendor/cachecontrol/caches/__init__.py @@ -2,7 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 -from pip._vendor.cachecontrol.caches.file_cache import FileCache, SeparateBodyFileCache -from pip._vendor.cachecontrol.caches.redis_cache import RedisCache +from .file_cache import FileCache, SeparateBodyFileCache +from .redis_cache import RedisCache + __all__ = ["FileCache", "SeparateBodyFileCache", "RedisCache"] diff --git a/venv1/Lib/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py b/venv1/Lib/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py index 45c632c7..f1ddb2eb 100644 --- a/venv1/Lib/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py +++ b/venv1/Lib/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py @@ -1,22 +1,60 @@ # SPDX-FileCopyrightText: 2015 Eric Larson # # SPDX-License-Identifier: Apache-2.0 -from __future__ import annotations import hashlib import os -import tempfile from textwrap import dedent -from typing import IO, TYPE_CHECKING -from pathlib import Path -from pip._vendor.cachecontrol.cache import BaseCache, SeparateBodyBaseCache -from pip._vendor.cachecontrol.controller import CacheController - -if TYPE_CHECKING: - from datetime import datetime - - from filelock import BaseFileLock +from ..cache import BaseCache, SeparateBodyBaseCache +from ..controller import CacheController + +try: + FileNotFoundError +except NameError: + # py2.X + FileNotFoundError = (IOError, OSError) + + +def _secure_open_write(filename, fmode): + # We only want to write to this file, so open it in write only mode + flags = os.O_WRONLY + + # os.O_CREAT | os.O_EXCL will fail if the file already exists, so we only + # will open *new* files. + # We specify this because we want to ensure that the mode we pass is the + # mode of the file. + flags |= os.O_CREAT | os.O_EXCL + + # Do not follow symlinks to prevent someone from making a symlink that + # we follow and insecurely open a cache file. + if hasattr(os, "O_NOFOLLOW"): + flags |= os.O_NOFOLLOW + + # On Windows we'll mark this file as binary + if hasattr(os, "O_BINARY"): + flags |= os.O_BINARY + + # Before we open our file, we want to delete any existing file that is + # there + try: + os.remove(filename) + except (IOError, OSError): + # The file must not exist already, so we can just skip ahead to opening + pass + + # Open our file, the use of os.O_CREAT | os.O_EXCL will ensure that if a + # race condition happens between the os.remove and this line, that an + # error will be raised. Because we utilize a lockfile this should only + # happen if someone is attempting to attack us. + fd = os.open(filename, flags, fmode) + try: + return os.fdopen(fd, "wb") + + except: + # An error occurred wrapping our FD in a file object + os.close(fd) + raise class _FileCacheMixin: @@ -24,27 +62,37 @@ class _FileCacheMixin: def __init__( self, - directory: str | Path, - forever: bool = False, - filemode: int = 0o0600, - dirmode: int = 0o0700, - lock_class: type[BaseFileLock] | None = None, - ) -> None: - try: - if lock_class is None: - from filelock import FileLock + directory, + forever=False, + filemode=0o0600, + dirmode=0o0700, + use_dir_lock=None, + lock_class=None, + ): - lock_class = FileLock + if use_dir_lock is not None and lock_class is not None: + raise ValueError("Cannot use use_dir_lock and lock_class together") + + try: + from lockfile import LockFile + from lockfile.mkdirlockfile import MkdirLockFile except ImportError: notice = dedent( """ NOTE: In order to use the FileCache you must have - filelock installed. You can install it via pip: - pip install cachecontrol[filecache] + lockfile installed. You can install it via pip: + pip install lockfile """ ) raise ImportError(notice) + else: + if use_dir_lock: + lock_class = MkdirLockFile + + elif lock_class is None: + lock_class = LockFile + self.directory = directory self.forever = forever self.filemode = filemode @@ -52,17 +100,17 @@ def __init__( self.lock_class = lock_class @staticmethod - def encode(x: str) -> str: + def encode(x): return hashlib.sha224(x.encode()).hexdigest() - def _fn(self, name: str) -> str: + def _fn(self, name): # NOTE: This method should not change as some may depend on it. # See: https://github.com/ionrock/cachecontrol/issues/63 hashed = self.encode(name) parts = list(hashed[:5]) + [hashed] return os.path.join(self.directory, *parts) - def get(self, key: str) -> bytes | None: + def get(self, key): name = self._fn(key) try: with open(name, "rb") as fh: @@ -71,31 +119,26 @@ def get(self, key: str) -> bytes | None: except FileNotFoundError: return None - def set( - self, key: str, value: bytes, expires: int | datetime | None = None - ) -> None: + def set(self, key, value, expires=None): name = self._fn(key) self._write(name, value) - def _write(self, path: str, data: bytes) -> None: + def _write(self, path, data: bytes): """ Safely write the data to the given path. """ # Make sure the directory exists - dirname = os.path.dirname(path) - os.makedirs(dirname, self.dirmode, exist_ok=True) + try: + os.makedirs(os.path.dirname(path), self.dirmode) + except (IOError, OSError): + pass - with self.lock_class(path + ".lock"): + with self.lock_class(path) as lock: # Write our actual file - (fd, name) = tempfile.mkstemp(dir=dirname) - try: - os.write(fd, data) - finally: - os.close(fd) - os.chmod(name, self.filemode) - os.replace(name, path) + with _secure_open_write(lock.path, self.filemode) as fh: + fh.write(data) - def _delete(self, key: str, suffix: str) -> None: + def _delete(self, key, suffix): name = self._fn(key) + suffix if not self.forever: try: @@ -110,7 +153,7 @@ class FileCache(_FileCacheMixin, BaseCache): downloads. """ - def delete(self, key: str) -> None: + def delete(self, key): self._delete(key, "") @@ -120,23 +163,23 @@ class SeparateBodyFileCache(_FileCacheMixin, SeparateBodyBaseCache): peak memory usage. """ - def get_body(self, key: str) -> IO[bytes] | None: + def get_body(self, key): name = self._fn(key) + ".body" try: return open(name, "rb") except FileNotFoundError: return None - def set_body(self, key: str, body: bytes) -> None: + def set_body(self, key, body): name = self._fn(key) + ".body" self._write(name, body) - def delete(self, key: str) -> None: + def delete(self, key): self._delete(key, "") self._delete(key, ".body") -def url_to_file_path(url: str, filecache: FileCache) -> str: +def url_to_file_path(url, filecache): """Return the file cache path based on the URL. This does not ensure the file exists! diff --git a/venv1/Lib/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py b/venv1/Lib/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py index f4f68c47..2cba4b07 100644 --- a/venv1/Lib/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py +++ b/venv1/Lib/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py @@ -1,48 +1,39 @@ # SPDX-FileCopyrightText: 2015 Eric Larson # # SPDX-License-Identifier: Apache-2.0 -from __future__ import annotations +from __future__ import division -from datetime import datetime, timezone -from typing import TYPE_CHECKING - +from datetime import datetime from pip._vendor.cachecontrol.cache import BaseCache -if TYPE_CHECKING: - from redis import Redis - class RedisCache(BaseCache): - def __init__(self, conn: Redis[bytes]) -> None: + + def __init__(self, conn): self.conn = conn - def get(self, key: str) -> bytes | None: + def get(self, key): return self.conn.get(key) - def set( - self, key: str, value: bytes, expires: int | datetime | None = None - ) -> None: + def set(self, key, value, expires=None): if not expires: self.conn.set(key, value) elif isinstance(expires, datetime): - now_utc = datetime.now(timezone.utc) - if expires.tzinfo is None: - now_utc = now_utc.replace(tzinfo=None) - delta = expires - now_utc - self.conn.setex(key, int(delta.total_seconds()), value) + expires = expires - datetime.utcnow() + self.conn.setex(key, int(expires.total_seconds()), value) else: self.conn.setex(key, expires, value) - def delete(self, key: str) -> None: + def delete(self, key): self.conn.delete(key) - def clear(self) -> None: + def clear(self): """Helper for clearing all the keys in a database. Use with caution!""" for key in self.conn.keys(): self.conn.delete(key) - def close(self) -> None: + def close(self): """Redis uses connection pooling, no need to close the connection.""" pass diff --git a/venv1/Lib/site-packages/pip/_vendor/cachecontrol/controller.py b/venv1/Lib/site-packages/pip/_vendor/cachecontrol/controller.py index d92d991c..7f23529f 100644 --- a/venv1/Lib/site-packages/pip/_vendor/cachecontrol/controller.py +++ b/venv1/Lib/site-packages/pip/_vendor/cachecontrol/controller.py @@ -5,29 +5,17 @@ """ The httplib2 algorithms ported for use with requests. """ - -from __future__ import annotations - -import calendar import logging import re +import calendar import time -import weakref from email.utils import parsedate_tz -from typing import TYPE_CHECKING, Collection, Mapping from pip._vendor.requests.structures import CaseInsensitiveDict -from pip._vendor.cachecontrol.cache import DictCache, SeparateBodyBaseCache -from pip._vendor.cachecontrol.serialize import Serializer - -if TYPE_CHECKING: - from typing import Literal +from .cache import DictCache, SeparateBodyBaseCache +from .serialize import Serializer - from pip._vendor.requests import PreparedRequest - from pip._vendor.urllib3 import HTTPResponse - - from pip._vendor.cachecontrol.cache import BaseCache logger = logging.getLogger(__name__) @@ -36,26 +24,20 @@ PERMANENT_REDIRECT_STATUSES = (301, 308) -def parse_uri(uri: str) -> tuple[str, str, str, str, str]: +def parse_uri(uri): """Parses a URI using the regex given in Appendix B of RFC 3986. (scheme, authority, path, query, fragment) = parse_uri(uri) """ - match = URI.match(uri) - assert match is not None - groups = match.groups() + groups = URI.match(uri).groups() return (groups[1], groups[3], groups[4], groups[6], groups[8]) -class CacheController: +class CacheController(object): """An interface to see if request should cached or not.""" def __init__( - self, - cache: BaseCache | None = None, - cache_etags: bool = True, - serializer: Serializer | None = None, - status_codes: Collection[int] | None = None, + self, cache=None, cache_etags=True, serializer=None, status_codes=None ): self.cache = DictCache() if cache is None else cache self.cache_etags = cache_etags @@ -63,7 +45,7 @@ def __init__( self.cacheable_status_codes = status_codes or (200, 203, 300, 301, 308) @classmethod - def _urlnorm(cls, uri: str) -> str: + def _urlnorm(cls, uri): """Normalize the URL to create a safe key for the cache""" (scheme, authority, path, query, fragment) = parse_uri(uri) if not scheme or not authority: @@ -83,10 +65,10 @@ def _urlnorm(cls, uri: str) -> str: return defrag_uri @classmethod - def cache_url(cls, uri: str) -> str: + def cache_url(cls, uri): return cls._urlnorm(uri) - def parse_cache_control(self, headers: Mapping[str, str]) -> dict[str, int | None]: + def parse_cache_control(self, headers): known_directives = { # https://tools.ietf.org/html/rfc7234#section-5.2 "max-age": (int, True), @@ -105,7 +87,7 @@ def parse_cache_control(self, headers: Mapping[str, str]) -> dict[str, int | Non cc_headers = headers.get("cache-control", headers.get("Cache-Control", "")) - retval: dict[str, int | None] = {} + retval = {} for cc_directive in cc_headers.split(","): if not cc_directive.strip(): @@ -140,38 +122,11 @@ def parse_cache_control(self, headers: Mapping[str, str]) -> dict[str, int | Non return retval - def _load_from_cache(self, request: PreparedRequest) -> HTTPResponse | None: - """ - Load a cached response, or return None if it's not available. - """ - # We do not support caching of partial content: so if the request contains a - # Range header then we don't want to load anything from the cache. - if "Range" in request.headers: - return None - - cache_url = request.url - assert cache_url is not None - cache_data = self.cache.get(cache_url) - if cache_data is None: - logger.debug("No cache entry available") - return None - - if isinstance(self.cache, SeparateBodyBaseCache): - body_file = self.cache.get_body(cache_url) - else: - body_file = None - - result = self.serializer.loads(request, cache_data, body_file) - if result is None: - logger.warning("Cache entry deserialization failed, entry ignored") - return result - - def cached_request(self, request: PreparedRequest) -> HTTPResponse | Literal[False]: + def cached_request(self, request): """ Return a cached response if it exists in the cache, otherwise return False. """ - assert request.url is not None cache_url = self.cache_url(request.url) logger.debug('Looking up "%s" in the cache', cache_url) cc = self.parse_cache_control(request.headers) @@ -185,9 +140,21 @@ def cached_request(self, request: PreparedRequest) -> HTTPResponse | Literal[Fal logger.debug('Request header has "max_age" as 0, cache bypassed') return False - # Check whether we can load the response from the cache: - resp = self._load_from_cache(request) + # Request allows serving from the cache, let's see if we find something + cache_data = self.cache.get(cache_url) + if cache_data is None: + logger.debug("No cache entry available") + return False + + if isinstance(self.cache, SeparateBodyBaseCache): + body_file = self.cache.get_body(cache_url) + else: + body_file = None + + # Check whether it can be deserialized + resp = self.serializer.loads(request, cache_data, body_file) if not resp: + logger.warning("Cache entry deserialization failed, entry ignored") return False # If we have a cached permanent redirect, return it immediately. We @@ -207,7 +174,7 @@ def cached_request(self, request: PreparedRequest) -> HTTPResponse | Literal[Fal logger.debug(msg) return resp - headers: CaseInsensitiveDict[str] = CaseInsensitiveDict(resp.headers) + headers = CaseInsensitiveDict(resp.headers) if not headers or "date" not in headers: if "etag" not in headers: # Without date or etag, the cached response can never be used @@ -218,9 +185,7 @@ def cached_request(self, request: PreparedRequest) -> HTTPResponse | Literal[Fal return False now = time.time() - time_tuple = parsedate_tz(headers["date"]) - assert time_tuple is not None - date = calendar.timegm(time_tuple[:6]) + date = calendar.timegm(parsedate_tz(headers["date"])) current_age = max(0, now - date) logger.debug("Current age based on date: %i", current_age) @@ -234,30 +199,28 @@ def cached_request(self, request: PreparedRequest) -> HTTPResponse | Literal[Fal freshness_lifetime = 0 # Check the max-age pragma in the cache control header - max_age = resp_cc.get("max-age") - if max_age is not None: - freshness_lifetime = max_age + if "max-age" in resp_cc: + freshness_lifetime = resp_cc["max-age"] logger.debug("Freshness lifetime from max-age: %i", freshness_lifetime) # If there isn't a max-age, check for an expires header elif "expires" in headers: expires = parsedate_tz(headers["expires"]) if expires is not None: - expire_time = calendar.timegm(expires[:6]) - date + expire_time = calendar.timegm(expires) - date freshness_lifetime = max(0, expire_time) logger.debug("Freshness lifetime from expires: %i", freshness_lifetime) # Determine if we are setting freshness limit in the # request. Note, this overrides what was in the response. - max_age = cc.get("max-age") - if max_age is not None: - freshness_lifetime = max_age + if "max-age" in cc: + freshness_lifetime = cc["max-age"] logger.debug( "Freshness lifetime from request max-age: %i", freshness_lifetime ) - min_fresh = cc.get("min-fresh") - if min_fresh is not None: + if "min-fresh" in cc: + min_fresh = cc["min-fresh"] # adjust our current age by our min fresh current_age += min_fresh logger.debug("Adjusted current age from min-fresh: %i", current_age) @@ -276,12 +239,13 @@ def cached_request(self, request: PreparedRequest) -> HTTPResponse | Literal[Fal # return the original handler return False - def conditional_headers(self, request: PreparedRequest) -> dict[str, str]: - resp = self._load_from_cache(request) + def conditional_headers(self, request): + cache_url = self.cache_url(request.url) + resp = self.serializer.loads(request, self.cache.get(cache_url)) new_headers = {} if resp: - headers: CaseInsensitiveDict[str] = CaseInsensitiveDict(resp.headers) + headers = CaseInsensitiveDict(resp.headers) if "etag" in headers: new_headers["If-None-Match"] = headers["ETag"] @@ -291,14 +255,7 @@ def conditional_headers(self, request: PreparedRequest) -> dict[str, str]: return new_headers - def _cache_set( - self, - cache_url: str, - request: PreparedRequest, - response: HTTPResponse, - body: bytes | None = None, - expires_time: int | None = None, - ) -> None: + def _cache_set(self, cache_url, request, response, body=None, expires_time=None): """ Store the data in the cache. """ @@ -310,10 +267,7 @@ def _cache_set( self.serializer.dumps(request, response, b""), expires=expires_time, ) - # body is None can happen when, for example, we're only updating - # headers, as is the case in update_cached_response(). - if body is not None: - self.cache.set_body(cache_url, body) + self.cache.set_body(cache_url, body) else: self.cache.set( cache_url, @@ -321,28 +275,12 @@ def _cache_set( expires=expires_time, ) - def cache_response( - self, - request: PreparedRequest, - response_or_ref: HTTPResponse | weakref.ReferenceType[HTTPResponse], - body: bytes | None = None, - status_codes: Collection[int] | None = None, - ) -> None: + def cache_response(self, request, response, body=None, status_codes=None): """ Algorithm for caching requests. This assumes a requests Response object. """ - if isinstance(response_or_ref, weakref.ReferenceType): - response = response_or_ref() - if response is None: - # The weakref can be None only in case the user used streamed request - # and did not consume or close it, and holds no reference to requests.Response. - # In such case, we don't want to cache the response. - return - else: - response = response_or_ref - # From httplib2: Don't cache 206's since we aren't going to # handle byte range requests cacheable_status_codes = status_codes or self.cacheable_status_codes @@ -352,14 +290,10 @@ def cache_response( ) return - response_headers: CaseInsensitiveDict[str] = CaseInsensitiveDict( - response.headers - ) + response_headers = CaseInsensitiveDict(response.headers) if "date" in response_headers: - time_tuple = parsedate_tz(response_headers["date"]) - assert time_tuple is not None - date = calendar.timegm(time_tuple[:6]) + date = calendar.timegm(parsedate_tz(response_headers["date"])) else: date = 0 @@ -378,7 +312,6 @@ def cache_response( cc_req = self.parse_cache_control(request.headers) cc = self.parse_cache_control(response_headers) - assert request.url is not None cache_url = self.cache_url(request.url) logger.debug('Updating cache with response from "%s"', cache_url) @@ -411,11 +344,11 @@ def cache_response( if response_headers.get("expires"): expires = parsedate_tz(response_headers["expires"]) if expires is not None: - expires_time = calendar.timegm(expires[:6]) - date + expires_time = calendar.timegm(expires) - date expires_time = max(expires_time, 14 * 86400) - logger.debug(f"etag object cached for {expires_time} seconds") + logger.debug("etag object cached for {0} seconds".format(expires_time)) logger.debug("Caching due to etag") self._cache_set(cache_url, request, response, body, expires_time) @@ -429,14 +362,11 @@ def cache_response( # is no date header then we can't do anything about expiring # the cache. elif "date" in response_headers: - time_tuple = parsedate_tz(response_headers["date"]) - assert time_tuple is not None - date = calendar.timegm(time_tuple[:6]) + date = calendar.timegm(parsedate_tz(response_headers["date"])) # cache when there is a max-age > 0 - max_age = cc.get("max-age") - if max_age is not None and max_age > 0: + if "max-age" in cc and cc["max-age"] > 0: logger.debug("Caching b/c date exists and max-age > 0") - expires_time = max_age + expires_time = cc["max-age"] self._cache_set( cache_url, request, @@ -451,12 +381,12 @@ def cache_response( if response_headers["expires"]: expires = parsedate_tz(response_headers["expires"]) if expires is not None: - expires_time = calendar.timegm(expires[:6]) - date + expires_time = calendar.timegm(expires) - date else: expires_time = None logger.debug( - "Caching b/c of expires header. expires in {} seconds".format( + "Caching b/c of expires header. expires in {0} seconds".format( expires_time ) ) @@ -468,18 +398,16 @@ def cache_response( expires_time, ) - def update_cached_response( - self, request: PreparedRequest, response: HTTPResponse - ) -> HTTPResponse: + def update_cached_response(self, request, response): """On a 304 we will get a new set of headers that we want to update our cached value with, assuming we have one. This should only ever be called when we've sent an ETag and gotten a 304 as the response. """ - assert request.url is not None cache_url = self.cache_url(request.url) - cached_response = self._load_from_cache(request) + + cached_response = self.serializer.loads(request, self.cache.get(cache_url)) if not cached_response: # we didn't have a cached response @@ -495,11 +423,11 @@ def update_cached_response( excluded_headers = ["content-length"] cached_response.headers.update( - { - k: v + dict( + (k, v) for k, v in response.headers.items() if k.lower() not in excluded_headers - } + ) ) # we want a 200 b/c we have content via the cache diff --git a/venv1/Lib/site-packages/pip/_vendor/cachecontrol/filewrapper.py b/venv1/Lib/site-packages/pip/_vendor/cachecontrol/filewrapper.py index 37d2fa59..f5ed5f6f 100644 --- a/venv1/Lib/site-packages/pip/_vendor/cachecontrol/filewrapper.py +++ b/venv1/Lib/site-packages/pip/_vendor/cachecontrol/filewrapper.py @@ -1,17 +1,12 @@ # SPDX-FileCopyrightText: 2015 Eric Larson # # SPDX-License-Identifier: Apache-2.0 -from __future__ import annotations -import mmap from tempfile import NamedTemporaryFile -from typing import TYPE_CHECKING, Any, Callable - -if TYPE_CHECKING: - from http.client import HTTPResponse +import mmap -class CallbackFileWrapper: +class CallbackFileWrapper(object): """ Small wrapper around a fp object which will tee everything read into a buffer, and when that file is closed it will execute a callback with the @@ -30,18 +25,16 @@ class CallbackFileWrapper: performance impact. """ - def __init__( - self, fp: HTTPResponse, callback: Callable[[bytes], None] | None - ) -> None: + def __init__(self, fp, callback): self.__buf = NamedTemporaryFile("rb+", delete=True) self.__fp = fp self.__callback = callback - def __getattr__(self, name: str) -> Any: - # The vagaries of garbage collection means that self.__fp is + def __getattr__(self, name): + # The vaguaries of garbage collection means that self.__fp is # not always set. By using __getattribute__ and the private # name[0] allows looking up the attribute value and raising an - # AttributeError when it doesn't exist. This stop things from + # AttributeError when it doesn't exist. This stop thigns from # infinitely recursing calls to getattr in the case where # self.__fp hasn't been set. # @@ -49,7 +42,7 @@ def __getattr__(self, name: str) -> Any: fp = self.__getattribute__("_CallbackFileWrapper__fp") return getattr(fp, name) - def __is_fp_closed(self) -> bool: + def __is_fp_closed(self): try: return self.__fp.fp is None @@ -57,8 +50,7 @@ def __is_fp_closed(self) -> bool: pass try: - closed: bool = self.__fp.closed - return closed + return self.__fp.closed except AttributeError: pass @@ -67,7 +59,7 @@ def __is_fp_closed(self) -> bool: # TODO: Add some logging here... return False - def _close(self) -> None: + def _close(self): if self.__callback: if self.__buf.tell() == 0: # Empty file: @@ -94,8 +86,8 @@ def _close(self) -> None: # Important when caching big files. self.__buf.close() - def read(self, amt: int | None = None) -> bytes: - data: bytes = self.__fp.read(amt) + def read(self, amt=None): + data = self.__fp.read(amt) if data: # We may be dealing with b'', a sign that things are over: # it's passed e.g. after we've already closed self.__buf. @@ -105,8 +97,8 @@ def read(self, amt: int | None = None) -> bytes: return data - def _safe_read(self, amt: int) -> bytes: - data: bytes = self.__fp._safe_read(amt) # type: ignore[attr-defined] + def _safe_read(self, amt): + data = self.__fp._safe_read(amt) if amt == 2 and data == b"\r\n": # urllib executes this read to toss the CRLF at the end # of the chunk. diff --git a/venv1/Lib/site-packages/pip/_vendor/cachecontrol/heuristics.py b/venv1/Lib/site-packages/pip/_vendor/cachecontrol/heuristics.py index b778c4f3..ebe4a96f 100644 --- a/venv1/Lib/site-packages/pip/_vendor/cachecontrol/heuristics.py +++ b/venv1/Lib/site-packages/pip/_vendor/cachecontrol/heuristics.py @@ -1,31 +1,29 @@ # SPDX-FileCopyrightText: 2015 Eric Larson # # SPDX-License-Identifier: Apache-2.0 -from __future__ import annotations import calendar import time -from datetime import datetime, timedelta, timezone + from email.utils import formatdate, parsedate, parsedate_tz -from typing import TYPE_CHECKING, Any, Mapping -if TYPE_CHECKING: - from pip._vendor.urllib3 import HTTPResponse +from datetime import datetime, timedelta TIME_FMT = "%a, %d %b %Y %H:%M:%S GMT" -def expire_after(delta: timedelta, date: datetime | None = None) -> datetime: - date = date or datetime.now(timezone.utc) +def expire_after(delta, date=None): + date = date or datetime.utcnow() return date + delta -def datetime_to_header(dt: datetime) -> str: +def datetime_to_header(dt): return formatdate(calendar.timegm(dt.timetuple())) -class BaseHeuristic: - def warning(self, response: HTTPResponse) -> str | None: +class BaseHeuristic(object): + + def warning(self, response): """ Return a valid 1xx warning header value describing the cache adjustments. @@ -36,7 +34,7 @@ def warning(self, response: HTTPResponse) -> str | None: """ return '110 - "Response is Stale"' - def update_headers(self, response: HTTPResponse) -> dict[str, str]: + def update_headers(self, response): """Update the response headers with any new headers. NOTE: This SHOULD always include some Warning header to @@ -45,7 +43,7 @@ def update_headers(self, response: HTTPResponse) -> dict[str, str]: """ return {} - def apply(self, response: HTTPResponse) -> HTTPResponse: + def apply(self, response): updated_headers = self.update_headers(response) if updated_headers: @@ -63,15 +61,12 @@ class OneDayCache(BaseHeuristic): future. """ - def update_headers(self, response: HTTPResponse) -> dict[str, str]: + def update_headers(self, response): headers = {} if "expires" not in response.headers: date = parsedate(response.headers["date"]) - expires = expire_after( - timedelta(days=1), - date=datetime(*date[:6], tzinfo=timezone.utc), # type: ignore[index,misc] - ) + expires = expire_after(timedelta(days=1), date=datetime(*date[:6])) headers["expires"] = datetime_to_header(expires) headers["cache-control"] = "public" return headers @@ -82,14 +77,14 @@ class ExpiresAfter(BaseHeuristic): Cache **all** requests for a defined time period. """ - def __init__(self, **kw: Any) -> None: + def __init__(self, **kw): self.delta = timedelta(**kw) - def update_headers(self, response: HTTPResponse) -> dict[str, str]: + def update_headers(self, response): expires = expire_after(self.delta) return {"expires": datetime_to_header(expires), "cache-control": "public"} - def warning(self, response: HTTPResponse) -> str | None: + def warning(self, response): tmpl = "110 - Automatically cached for %s. Response might be stale" return tmpl % self.delta @@ -106,23 +101,12 @@ class LastModified(BaseHeuristic): http://lxr.mozilla.org/mozilla-release/source/netwerk/protocol/http/nsHttpResponseHead.cpp#397 Unlike mozilla we limit this to 24-hr. """ - cacheable_by_default_statuses = { - 200, - 203, - 204, - 206, - 300, - 301, - 404, - 405, - 410, - 414, - 501, + 200, 203, 204, 206, 300, 301, 404, 405, 410, 414, 501 } - def update_headers(self, resp: HTTPResponse) -> dict[str, str]: - headers: Mapping[str, str] = resp.headers + def update_headers(self, resp): + headers = resp.headers if "expires" in headers: return {} @@ -136,11 +120,9 @@ def update_headers(self, resp: HTTPResponse) -> dict[str, str]: if "date" not in headers or "last-modified" not in headers: return {} - time_tuple = parsedate_tz(headers["date"]) - assert time_tuple is not None - date = calendar.timegm(time_tuple[:6]) + date = calendar.timegm(parsedate_tz(headers["date"])) last_modified = parsedate(headers["last-modified"]) - if last_modified is None: + if date is None or last_modified is None: return {} now = time.time() @@ -153,5 +135,5 @@ def update_headers(self, resp: HTTPResponse) -> dict[str, str]: expires = date + freshness_lifetime return {"expires": time.strftime(TIME_FMT, time.gmtime(expires))} - def warning(self, resp: HTTPResponse) -> str | None: + def warning(self, resp): return None diff --git a/venv1/Lib/site-packages/pip/_vendor/cachecontrol/py.typed b/venv1/Lib/site-packages/pip/_vendor/cachecontrol/py.typed deleted file mode 100644 index e69de29b..00000000 diff --git a/venv1/Lib/site-packages/pip/_vendor/cachecontrol/serialize.py b/venv1/Lib/site-packages/pip/_vendor/cachecontrol/serialize.py index a49487a1..7fe1a3e3 100644 --- a/venv1/Lib/site-packages/pip/_vendor/cachecontrol/serialize.py +++ b/venv1/Lib/site-packages/pip/_vendor/cachecontrol/serialize.py @@ -1,91 +1,105 @@ # SPDX-FileCopyrightText: 2015 Eric Larson # # SPDX-License-Identifier: Apache-2.0 -from __future__ import annotations +import base64 import io -from typing import IO, TYPE_CHECKING, Any, Mapping, cast +import json +import zlib from pip._vendor import msgpack from pip._vendor.requests.structures import CaseInsensitiveDict -from pip._vendor.urllib3 import HTTPResponse -if TYPE_CHECKING: - from pip._vendor.requests import PreparedRequest +from .compat import HTTPResponse, pickle, text_type -class Serializer: - serde_version = "4" +def _b64_decode_bytes(b): + return base64.b64decode(b.encode("ascii")) - def dumps( - self, - request: PreparedRequest, - response: HTTPResponse, - body: bytes | None = None, - ) -> bytes: - response_headers: CaseInsensitiveDict[str] = CaseInsensitiveDict( - response.headers - ) + +def _b64_decode_str(s): + return _b64_decode_bytes(s).decode("utf8") + + +_default_body_read = object() + + +class Serializer(object): + def dumps(self, request, response, body=None): + response_headers = CaseInsensitiveDict(response.headers) if body is None: # When a body isn't passed in, we'll read the response. We # also update the response with a new file handler to be # sure it acts as though it was never read. body = response.read(decode_content=False) - response._fp = io.BytesIO(body) # type: ignore[assignment] - response.length_remaining = len(body) - + response._fp = io.BytesIO(body) + + # NOTE: This is all a bit weird, but it's really important that on + # Python 2.x these objects are unicode and not str, even when + # they contain only ascii. The problem here is that msgpack + # understands the difference between unicode and bytes and we + # have it set to differentiate between them, however Python 2 + # doesn't know the difference. Forcing these to unicode will be + # enough to have msgpack know the difference. data = { - "response": { - "body": body, # Empty bytestring if body is stored separately - "headers": {str(k): str(v) for k, v in response.headers.items()}, - "status": response.status, - "version": response.version, - "reason": str(response.reason), - "decode_content": response.decode_content, + u"response": { + u"body": body, # Empty bytestring if body is stored separately + u"headers": dict( + (text_type(k), text_type(v)) for k, v in response.headers.items() + ), + u"status": response.status, + u"version": response.version, + u"reason": text_type(response.reason), + u"strict": response.strict, + u"decode_content": response.decode_content, } } # Construct our vary headers - data["vary"] = {} - if "vary" in response_headers: - varied_headers = response_headers["vary"].split(",") + data[u"vary"] = {} + if u"vary" in response_headers: + varied_headers = response_headers[u"vary"].split(",") for header in varied_headers: - header = str(header).strip() + header = text_type(header).strip() header_value = request.headers.get(header, None) if header_value is not None: - header_value = str(header_value) - data["vary"][header] = header_value - - return b",".join([f"cc={self.serde_version}".encode(), self.serialize(data)]) + header_value = text_type(header_value) + data[u"vary"][header] = header_value - def serialize(self, data: dict[str, Any]) -> bytes: - return cast(bytes, msgpack.dumps(data, use_bin_type=True)) + return b",".join([b"cc=4", msgpack.dumps(data, use_bin_type=True)]) - def loads( - self, - request: PreparedRequest, - data: bytes, - body_file: IO[bytes] | None = None, - ) -> HTTPResponse | None: + def loads(self, request, data, body_file=None): # Short circuit if we've been given an empty set of data if not data: - return None - - # Previous versions of this library supported other serialization - # formats, but these have all been removed. - if not data.startswith(f"cc={self.serde_version},".encode()): - return None - - data = data[5:] - return self._loads_v4(request, data, body_file) - - def prepare_response( - self, - request: PreparedRequest, - cached: Mapping[str, Any], - body_file: IO[bytes] | None = None, - ) -> HTTPResponse | None: + return + + # Determine what version of the serializer the data was serialized + # with + try: + ver, data = data.split(b",", 1) + except ValueError: + ver = b"cc=0" + + # Make sure that our "ver" is actually a version and isn't a false + # positive from a , being in the data stream. + if ver[:3] != b"cc=": + data = ver + data + ver = b"cc=0" + + # Get the version number out of the cc=N + ver = ver.split(b"=", 1)[-1].decode("ascii") + + # Dispatch to the actual load method for the given version + try: + return getattr(self, "_loads_v{}".format(ver))(request, data, body_file) + + except AttributeError: + # This is a version we don't have a loads function for, so we'll + # just treat it as a miss and return None + return + + def prepare_response(self, request, cached, body_file=None): """Verify our vary headers match and construct a real urllib3 HTTPResponse object. """ @@ -94,26 +108,23 @@ def prepare_response( # This case is also handled in the controller code when creating # a cache entry, but is left here for backwards compatibility. if "*" in cached.get("vary", {}): - return None + return # Ensure that the Vary headers for the cached response match our # request for header, value in cached.get("vary", {}).items(): if request.headers.get(header, None) != value: - return None + return body_raw = cached["response"].pop("body") - headers: CaseInsensitiveDict[str] = CaseInsensitiveDict( - data=cached["response"]["headers"] - ) + headers = CaseInsensitiveDict(data=cached["response"]["headers"]) if headers.get("transfer-encoding", "") == "chunked": headers.pop("transfer-encoding") cached["response"]["headers"] = headers try: - body: IO[bytes] if body_file is None: body = io.BytesIO(body_raw) else: @@ -127,20 +138,53 @@ def prepare_response( # TypeError: 'str' does not support the buffer interface body = io.BytesIO(body_raw.encode("utf8")) - # Discard any `strict` parameter serialized by older version of cachecontrol. - cached["response"].pop("strict", None) - return HTTPResponse(body=body, preload_content=False, **cached["response"]) - def _loads_v4( - self, - request: PreparedRequest, - data: bytes, - body_file: IO[bytes] | None = None, - ) -> HTTPResponse | None: + def _loads_v0(self, request, data, body_file=None): + # The original legacy cache data. This doesn't contain enough + # information to construct everything we need, so we'll treat this as + # a miss. + return + + def _loads_v1(self, request, data, body_file=None): + try: + cached = pickle.loads(data) + except ValueError: + return + + return self.prepare_response(request, cached, body_file) + + def _loads_v2(self, request, data, body_file=None): + assert body_file is None + try: + cached = json.loads(zlib.decompress(data).decode("utf8")) + except (ValueError, zlib.error): + return + + # We need to decode the items that we've base64 encoded + cached["response"]["body"] = _b64_decode_bytes(cached["response"]["body"]) + cached["response"]["headers"] = dict( + (_b64_decode_str(k), _b64_decode_str(v)) + for k, v in cached["response"]["headers"].items() + ) + cached["response"]["reason"] = _b64_decode_str(cached["response"]["reason"]) + cached["vary"] = dict( + (_b64_decode_str(k), _b64_decode_str(v) if v is not None else v) + for k, v in cached["vary"].items() + ) + + return self.prepare_response(request, cached, body_file) + + def _loads_v3(self, request, data, body_file): + # Due to Python 2 encoding issues, it's impossible to know for sure + # exactly how to load v3 entries, thus we'll treat these as a miss so + # that they get rewritten out as v4 entries. + return + + def _loads_v4(self, request, data, body_file=None): try: cached = msgpack.loads(data, raw=False) except ValueError: - return None + return return self.prepare_response(request, cached, body_file) diff --git a/venv1/Lib/site-packages/pip/_vendor/cachecontrol/wrapper.py b/venv1/Lib/site-packages/pip/_vendor/cachecontrol/wrapper.py index f618bc36..b6ee7f20 100644 --- a/venv1/Lib/site-packages/pip/_vendor/cachecontrol/wrapper.py +++ b/venv1/Lib/site-packages/pip/_vendor/cachecontrol/wrapper.py @@ -1,32 +1,22 @@ # SPDX-FileCopyrightText: 2015 Eric Larson # # SPDX-License-Identifier: Apache-2.0 -from __future__ import annotations -from typing import TYPE_CHECKING, Collection - -from pip._vendor.cachecontrol.adapter import CacheControlAdapter -from pip._vendor.cachecontrol.cache import DictCache - -if TYPE_CHECKING: - from pip._vendor import requests - - from pip._vendor.cachecontrol.cache import BaseCache - from pip._vendor.cachecontrol.controller import CacheController - from pip._vendor.cachecontrol.heuristics import BaseHeuristic - from pip._vendor.cachecontrol.serialize import Serializer +from .adapter import CacheControlAdapter +from .cache import DictCache def CacheControl( - sess: requests.Session, - cache: BaseCache | None = None, - cache_etags: bool = True, - serializer: Serializer | None = None, - heuristic: BaseHeuristic | None = None, - controller_class: type[CacheController] | None = None, - adapter_class: type[CacheControlAdapter] | None = None, - cacheable_methods: Collection[str] | None = None, -) -> requests.Session: + sess, + cache=None, + cache_etags=True, + serializer=None, + heuristic=None, + controller_class=None, + adapter_class=None, + cacheable_methods=None, +): + cache = DictCache() if cache is None else cache adapter_class = adapter_class or CacheControlAdapter adapter = adapter_class( diff --git a/venv1/Lib/site-packages/pip/_vendor/certifi/__init__.py b/venv1/Lib/site-packages/pip/_vendor/certifi/__init__.py index c4b6c0bb..a3546f12 100644 --- a/venv1/Lib/site-packages/pip/_vendor/certifi/__init__.py +++ b/venv1/Lib/site-packages/pip/_vendor/certifi/__init__.py @@ -1,4 +1,4 @@ from .core import contents, where __all__ = ["contents", "where"] -__version__ = "2025.10.05" +__version__ = "2022.12.07" diff --git a/venv1/Lib/site-packages/pip/_vendor/certifi/cacert.pem b/venv1/Lib/site-packages/pip/_vendor/certifi/cacert.pem index 0b68ebfe..df9e4e3c 100644 --- a/venv1/Lib/site-packages/pip/_vendor/certifi/cacert.pem +++ b/venv1/Lib/site-packages/pip/_vendor/certifi/cacert.pem @@ -1,4 +1,95 @@ +# Issuer: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA +# Subject: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA +# Label: "GlobalSign Root CA" +# Serial: 4835703278459707669005204 +# MD5 Fingerprint: 3e:45:52:15:09:51:92:e1:b7:5d:37:9f:b1:87:29:8a +# SHA1 Fingerprint: b1:bc:96:8b:d4:f4:9d:62:2a:a8:9a:81:f2:15:01:52:a4:1d:82:9c +# SHA256 Fingerprint: eb:d4:10:40:e4:bb:3e:c7:42:c9:e3:81:d3:1e:f2:a4:1a:48:b6:68:5c:96:e7:ce:f3:c1:df:6c:d4:33:1c:99 +-----BEGIN CERTIFICATE----- +MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG +A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv +b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw +MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i +YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT +aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ +jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp +xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp +1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG +snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ +U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 +9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E +BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B +AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz +yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE +38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP +AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad +DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME +HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== +-----END CERTIFICATE----- + +# Issuer: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited +# Subject: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited +# Label: "Entrust.net Premium 2048 Secure Server CA" +# Serial: 946069240 +# MD5 Fingerprint: ee:29:31:bc:32:7e:9a:e6:e8:b5:f7:51:b4:34:71:90 +# SHA1 Fingerprint: 50:30:06:09:1d:97:d4:f5:ae:39:f7:cb:e7:92:7d:7d:65:2d:34:31 +# SHA256 Fingerprint: 6d:c4:71:72:e0:1c:bc:b0:bf:62:58:0d:89:5f:e2:b8:ac:9a:d4:f8:73:80:1e:0c:10:b9:c8:37:d2:1e:b1:77 +-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML +RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp +bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 +IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3 +MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 +LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp +YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG +A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq +K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe +sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX +MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT +XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ +HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH +4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub +j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo +U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf +zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b +u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+ +bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er +fF6adulZkMV8gzURZVE= +-----END CERTIFICATE----- + +# Issuer: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust +# Subject: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust +# Label: "Baltimore CyberTrust Root" +# Serial: 33554617 +# MD5 Fingerprint: ac:b6:94:a5:9c:17:e0:d7:91:52:9b:b1:97:06:a6:e4 +# SHA1 Fingerprint: d4:de:20:d0:5e:66:fc:53:fe:1a:50:88:2c:78:db:28:52:ca:e4:74 +# SHA256 Fingerprint: 16:af:57:a9:f6:76:b0:ab:12:60:95:aa:5e:ba:de:f2:2a:b3:11:19:d6:44:ac:95:cd:4b:93:db:f3:f2:6a:eb +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ +RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD +VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX +DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y +ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy +VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr +mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr +IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK +mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu +XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy +dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye +jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 +BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 +DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 +9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx +jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 +Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz +ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS +R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +-----END CERTIFICATE----- + # Issuer: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc. # Subject: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc. # Label: "Entrust Root Certification Authority" @@ -34,6 +125,39 @@ eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m 0vdXcDazv/wor3ElhVsT/h5/WrQ8 -----END CERTIFICATE----- +# Issuer: CN=AAA Certificate Services O=Comodo CA Limited +# Subject: CN=AAA Certificate Services O=Comodo CA Limited +# Label: "Comodo AAA Services root" +# Serial: 1 +# MD5 Fingerprint: 49:79:04:b0:eb:87:19:ac:47:b0:bc:11:51:9b:74:d0 +# SHA1 Fingerprint: d1:eb:23:a4:6d:17:d6:8f:d9:25:64:c2:f1:f1:60:17:64:d8:e3:49 +# SHA256 Fingerprint: d7:a7:a0:fb:5d:7e:27:31:d7:71:e9:48:4e:bc:de:f7:1d:5f:0c:3e:0a:29:48:78:2b:c8:3e:e0:ea:69:9e:f4 +-----BEGIN CERTIFICATE----- +MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb +MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow +GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj +YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL +MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE +BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM +GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua +BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe +3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 +YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR +rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm +ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU +oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF +MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v +QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t +b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF +AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q +GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz +Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 +G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi +l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 +smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== +-----END CERTIFICATE----- + # Issuer: CN=QuoVadis Root CA 2 O=QuoVadis Limited # Subject: CN=QuoVadis Root CA 2 O=QuoVadis Limited # Label: "QuoVadis Root CA 2" @@ -121,6 +245,131 @@ mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK 4SVhM7JZG+Ju1zdXtg2pEto= -----END CERTIFICATE----- +# Issuer: O=SECOM Trust.net OU=Security Communication RootCA1 +# Subject: O=SECOM Trust.net OU=Security Communication RootCA1 +# Label: "Security Communication Root CA" +# Serial: 0 +# MD5 Fingerprint: f1:bc:63:6a:54:e0:b5:27:f5:cd:e7:1a:e3:4d:6e:4a +# SHA1 Fingerprint: 36:b1:2b:49:f9:81:9e:d7:4c:9e:bc:38:0f:c6:56:8f:5d:ac:b2:f7 +# SHA256 Fingerprint: e7:5e:72:ed:9f:56:0e:ec:6e:b4:80:00:73:a4:3f:c3:ad:19:19:5a:39:22:82:01:78:95:97:4a:99:02:6b:6c +-----BEGIN CERTIFICATE----- +MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEY +MBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21t +dW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5 +WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYD +VQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw8yl8 +9f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJ +DKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9 +Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/N +QV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJ +xrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0G +A1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0T +AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vG +kl3g0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfr +Uj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5 +Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJU +JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot +RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw== +-----END CERTIFICATE----- + +# Issuer: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com +# Subject: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com +# Label: "XRamp Global CA Root" +# Serial: 107108908803651509692980124233745014957 +# MD5 Fingerprint: a1:0b:44:b3:ca:10:d8:00:6e:9d:0f:d8:0f:92:0a:d1 +# SHA1 Fingerprint: b8:01:86:d1:eb:9c:86:a5:41:04:cf:30:54:f3:4c:52:b7:e5:58:c6 +# SHA256 Fingerprint: ce:cd:dc:90:50:99:d8:da:df:c5:b1:d2:09:b7:37:cb:e2:c1:8c:fb:2c:10:c0:ff:0b:cf:0d:32:86:fc:1a:a2 +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB +gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk +MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY +UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx +NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3 +dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy +dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6 +38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP +KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q +DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4 +qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa +JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi +PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P +BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs +jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0 +eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD +ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR +vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt +qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa +IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy +i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ +O+7ETPTsJ3xCwnR8gooJybQDJbw= +-----END CERTIFICATE----- + +# Issuer: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority +# Subject: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority +# Label: "Go Daddy Class 2 CA" +# Serial: 0 +# MD5 Fingerprint: 91:de:06:25:ab:da:fd:32:17:0c:bb:25:17:2a:84:67 +# SHA1 Fingerprint: 27:96:ba:e6:3f:18:01:e2:77:26:1b:a0:d7:77:70:02:8f:20:ee:e4 +# SHA256 Fingerprint: c3:84:6b:f2:4b:9e:93:ca:64:27:4c:0e:c6:7c:1e:cc:5e:02:4f:fc:ac:d2:d7:40:19:35:0e:81:fe:54:6a:e4 +-----BEGIN CERTIFICATE----- +MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh +MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE +YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3 +MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo +ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg +MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN +ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA +PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w +wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi +EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY +avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+ +YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE +sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h +/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5 +IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD +ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy +OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P +TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ +HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER +dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf +ReYNnyicsbkqWletNw+vHX/bvZ8= +-----END CERTIFICATE----- + +# Issuer: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority +# Subject: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority +# Label: "Starfield Class 2 CA" +# Serial: 0 +# MD5 Fingerprint: 32:4a:4b:bb:c8:63:69:9b:be:74:9a:c6:dd:1d:46:24 +# SHA1 Fingerprint: ad:7e:1c:28:b0:64:ef:8f:60:03:40:20:14:c3:d0:e3:37:0e:b5:8a +# SHA256 Fingerprint: 14:65:fa:20:53:97:b8:76:fa:a6:f0:a9:95:8e:55:90:e4:0f:cc:7f:aa:4f:b7:c2:c8:67:75:21:fb:5f:b6:58 +-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl +MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp +U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw +NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE +ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp +ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3 +DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf +8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN ++lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0 +X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa +K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA +1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G +A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR +zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0 +YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD +bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w +DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3 +L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D +eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl +xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp +VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY +WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q= +-----END CERTIFICATE----- + # Issuer: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com # Subject: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com # Label: "DigiCert Assured ID Root CA" @@ -253,6 +502,47 @@ ZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6LqjviOvrv1vA+ACOzB2+htt Qc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ -----END CERTIFICATE----- +# Issuer: CN=SwissSign Silver CA - G2 O=SwissSign AG +# Subject: CN=SwissSign Silver CA - G2 O=SwissSign AG +# Label: "SwissSign Silver CA - G2" +# Serial: 5700383053117599563 +# MD5 Fingerprint: e0:06:a1:c9:7d:cf:c9:fc:0d:c0:56:75:96:d8:62:13 +# SHA1 Fingerprint: 9b:aa:e5:9f:56:ee:21:cb:43:5a:be:25:93:df:a7:f0:40:d1:1d:cb +# SHA256 Fingerprint: be:6c:4d:a2:bb:b9:ba:59:b6:f3:93:97:68:37:42:46:c3:c0:05:99:3f:a9:8f:02:0d:1d:ed:be:d4:8a:81:d5 +-----BEGIN CERTIFICATE----- +MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UE +BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWdu +IFNpbHZlciBDQSAtIEcyMB4XDTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0Nlow +RzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMY +U3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644N0Mv +Fz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7br +YT7QbNHm+/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieF +nbAVlDLaYQ1HTWBCrpJH6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH +6ATK72oxh9TAtvmUcXtnZLi2kUpCe2UuMGoM9ZDulebyzYLs2aFK7PayS+VFheZt +eJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5hqAaEuSh6XzjZG6k4sIN/ +c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5FZGkECwJ +MoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRH +HTBsROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTf +jNFusB3hB48IHpmccelM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb6 +5i/4z3GcRm25xBWNOHkDRUjvxF3XCO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOB +rDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU +F6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRBtjpbO8tFnb0c +wpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0 +cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIB +AHPGgeAn0i0P4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShp +WJHckRE1qTodvBqlYJ7YH39FkWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9 +xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L3XWgwF15kIwb4FDm3jH+mHtwX6WQ +2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx/uNncqCxv1yL5PqZ +IseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFaDGi8 +aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2X +em1ZqSqPe97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQR +dAtq/gsD/KNVV4n+SsuuWxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/ +OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJDIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+ +hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ubDgEj8Z+7fNzcbBGXJbLy +tGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u +-----END CERTIFICATE----- + # Issuer: CN=SecureTrust CA O=SecureTrust Corporation # Subject: CN=SecureTrust CA O=SecureTrust Corporation # Label: "SecureTrust CA" @@ -501,6 +791,63 @@ uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2 XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= -----END CERTIFICATE----- +# Issuer: CN=Hongkong Post Root CA 1 O=Hongkong Post +# Subject: CN=Hongkong Post Root CA 1 O=Hongkong Post +# Label: "Hongkong Post Root CA 1" +# Serial: 1000 +# MD5 Fingerprint: a8:0d:6f:39:78:b9:43:6d:77:42:6d:98:5a:cc:23:ca +# SHA1 Fingerprint: d6:da:a8:20:8d:09:d2:15:4d:24:b5:2f:cb:34:6e:b2:58:b2:8a:58 +# SHA256 Fingerprint: f9:e6:7d:33:6c:51:00:2a:c0:54:c6:32:02:2d:66:dd:a2:e7:e3:ff:f1:0a:d0:61:ed:31:d8:bb:b4:10:cf:b2 +-----BEGIN CERTIFICATE----- +MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsx +FjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3Qg +Um9vdCBDQSAxMB4XDTAzMDUxNTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkG +A1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdr +b25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1ApzQ +jVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEn +PzlTCeqrauh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjh +ZY4bXSNmO7ilMlHIhqqhqZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9 +nnV0ttgCXjqQesBCNnLsak3c78QA3xMYV18meMjWCnl3v/evt3a5pQuEF10Q6m/h +q5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNVHRMBAf8ECDAGAQH/AgED +MA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7ih9legYsC +mEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI3 +7piol7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clB +oiMBdDhViw+5LmeiIAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJs +EhTkYY2sEJCehFC78JZvRZ+K88psT/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpO +fMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilTc4afU9hDDl3WY4JxHYB0yvbi +AmvZWg== +-----END CERTIFICATE----- + +# Issuer: CN=SecureSign RootCA11 O=Japan Certification Services, Inc. +# Subject: CN=SecureSign RootCA11 O=Japan Certification Services, Inc. +# Label: "SecureSign RootCA11" +# Serial: 1 +# MD5 Fingerprint: b7:52:74:e2:92:b4:80:93:f2:75:e4:cc:d7:f2:ea:26 +# SHA1 Fingerprint: 3b:c4:9f:48:f8:f3:73:a0:9c:1e:bd:f8:5b:b1:c3:65:c7:d8:11:b3 +# SHA256 Fingerprint: bf:0f:ee:fb:9e:3a:58:1a:d5:f9:e9:db:75:89:98:57:43:d2:61:08:5c:4d:31:4f:6f:5d:72:59:aa:42:16:12 +-----BEGIN CERTIFICATE----- +MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDEr +MCkGA1UEChMiSmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoG +A1UEAxMTU2VjdXJlU2lnbiBSb290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0 +MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSswKQYDVQQKEyJKYXBhbiBDZXJ0aWZp +Y2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1cmVTaWduIFJvb3RD +QTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvLTJsz +i1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8 +h9uuywGOwvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOV +MdrAG/LuYpmGYz+/3ZMqg6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9 +UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rPO7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni +8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitAbpSACW22s293bzUIUPsC +h8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZXt94wDgYD +VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEB +AKChOBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xm +KbabfSVSSUOrTC4rbnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQ +X5Ucv+2rIrVls4W6ng+4reV6G4pQOh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWr +QbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01y8hSyn+B/tlr0/cR7SXf+Of5 +pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061lgeLKBObjBmN +QSdJQO7e5iNEOdyhIta6A/I= +-----END CERTIFICATE----- + # Issuer: CN=Microsec e-Szigno Root CA 2009 O=Microsec Ltd. # Subject: CN=Microsec e-Szigno Root CA 2009 O=Microsec Ltd. # Label: "Microsec e-Szigno Root CA 2009" @@ -562,6 +909,49 @@ Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH WD9f -----END CERTIFICATE----- +# Issuer: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 +# Subject: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 +# Label: "Autoridad de Certificacion Firmaprofesional CIF A62634068" +# Serial: 6047274297262753887 +# MD5 Fingerprint: 73:3a:74:7a:ec:bb:a3:96:a6:c2:e4:e2:c8:9b:c0:c3 +# SHA1 Fingerprint: ae:c5:fb:3f:c8:e1:bf:c4:e5:4f:03:07:5a:9a:e8:00:b7:f7:b6:fa +# SHA256 Fingerprint: 04:04:80:28:bf:1f:28:64:d4:8f:9a:d4:d8:32:94:36:6a:82:88:56:55:3f:3b:14:30:3f:90:14:7f:5d:40:ef +-----BEGIN CERTIFICATE----- +MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UE +BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h +cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEy +MzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg +Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9 +thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM +cas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefG +L9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i +NA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/h +X68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2b +m8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCy +Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja +EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T +KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF +6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh +OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYD +VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNHDhpkLzCBpgYD +VR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp +cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBv +ACAAZABlACAAbABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBl +AGwAbwBuAGEAIAAwADgAMAAxADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF +661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx51tkljYyGOylMnfX40S2wBEqgLk9 +am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qkR71kMrv2JYSiJ0L1 +ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaPT481 +PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS +3a/DTg4fJl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5k +SeTy36LssUzAKh3ntLFlosS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF +3dvd6qJ2gHN99ZwExEWN57kci57q13XRcrHedUTnQn3iV2t93Jm8PYMo6oCTjcVM +ZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoRsaS8I8nkvof/uZS2+F0g +StRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTDKCOM/icz +Q0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQB +jLMi6Et8Vcad+qMUu2WFbm5PEn4KPJ2V +-----END CERTIFICATE----- + # Issuer: CN=Izenpe.com O=IZENPE S.A. # Subject: CN=Izenpe.com O=IZENPE S.A. # Label: "Izenpe.com" @@ -1286,6 +1676,50 @@ HL/EVlP6Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVx SK236thZiNSQvxaz2emsWWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= -----END CERTIFICATE----- +# Issuer: CN=E-Tugra Certification Authority O=E-Tu\u011fra EBG Bili\u015fim Teknolojileri ve Hizmetleri A.\u015e. OU=E-Tugra Sertifikasyon Merkezi +# Subject: CN=E-Tugra Certification Authority O=E-Tu\u011fra EBG Bili\u015fim Teknolojileri ve Hizmetleri A.\u015e. OU=E-Tugra Sertifikasyon Merkezi +# Label: "E-Tugra Certification Authority" +# Serial: 7667447206703254355 +# MD5 Fingerprint: b8:a1:03:63:b0:bd:21:71:70:8a:6f:13:3a:bb:79:49 +# SHA1 Fingerprint: 51:c6:e7:08:49:06:6e:f3:92:d4:5c:a0:0d:6d:a3:62:8f:c3:52:39 +# SHA256 Fingerprint: b0:bf:d5:2b:b0:d7:d9:bd:92:bf:5d:4d:c1:3d:a2:55:c0:2c:54:2f:37:83:65:ea:89:39:11:f5:5e:55:f2:3c +-----BEGIN CERTIFICATE----- +MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNV +BAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBC +aWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNV +BAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQDDB9FLVR1 +Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMwNTEyMDk0OFoXDTIz +MDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+ +BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhp +em1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN +ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4vU/kwVRHoViVF56C/UY +B4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vdhQd2h8y/L5VMzH2nPbxH +D5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5KCKpbknSF +Q9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEo +q1+gElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3D +k14opz8n8Y4e0ypQBaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcH +fC425lAcP9tDJMW/hkd5s3kc91r0E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsut +dEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gzrt48Ue7LE3wBf4QOXVGUnhMM +ti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAqjqFGOjGY5RH8 +zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn +rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUX +U8u3Zg5mTPj5dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6 +Jyr+zE7S6E5UMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5 +XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAF +Nzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAKkEh47U6YA5n+KGCR +HTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jOXKqY +GwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c +77NCR807VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3 ++GbHeJAAFS6LrVE1Uweoa2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WK +vJUawSg5TB9D0pH0clmKuVb8P7Sd2nCcdlqMQ1DujjByTd//SffGqWfZbawCEeI6 +FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEVKV0jq9BgoRJP3vQXzTLl +yb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gTDx4JnW2P +AJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpD +y4Q08ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8d +NL/+I5c30jn6PQ0GC7TbO6Orb1wdtn7os4I07QZcJA== +-----END CERTIFICATE----- + # Issuer: CN=T-TeleSec GlobalRoot Class 2 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center # Subject: CN=T-TeleSec GlobalRoot Class 2 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center # Label: "T-TeleSec GlobalRoot Class 2" @@ -2809,6 +3243,50 @@ LJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fqdBb9HxEG mpv0 -----END CERTIFICATE----- +# Issuer: CN=Entrust Root Certification Authority - G4 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2015 Entrust, Inc. - for authorized use only +# Subject: CN=Entrust Root Certification Authority - G4 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2015 Entrust, Inc. - for authorized use only +# Label: "Entrust Root Certification Authority - G4" +# Serial: 289383649854506086828220374796556676440 +# MD5 Fingerprint: 89:53:f1:83:23:b7:7c:8e:05:f1:8c:71:38:4e:1f:88 +# SHA1 Fingerprint: 14:88:4e:86:26:37:b0:26:af:59:62:5c:40:77:ec:35:29:ba:96:01 +# SHA256 Fingerprint: db:35:17:d1:f6:73:2a:2d:5a:b9:7c:53:3e:c7:07:79:ee:32:70:a6:2f:b4:ac:42:38:37:24:60:e6:f0:1e:88 +-----BEGIN CERTIFICATE----- +MIIGSzCCBDOgAwIBAgIRANm1Q3+vqTkPAAAAAFVlrVgwDQYJKoZIhvcNAQELBQAw +gb4xCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQL +Ex9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykg +MjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMjAw +BgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEc0 +MB4XDTE1MDUyNzExMTExNloXDTM3MTIyNzExNDExNlowgb4xCzAJBgNVBAYTAlVT +MRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1 +c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJ +bmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3Qg +Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEc0MIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEAsewsQu7i0TD/pZJH4i3DumSXbcr3DbVZwbPLqGgZ +2K+EbTBwXX7zLtJTmeH+H17ZSK9dE43b/2MzTdMAArzE+NEGCJR5WIoV3imz/f3E +T+iq4qA7ec2/a0My3dl0ELn39GjUu9CH1apLiipvKgS1sqbHoHrmSKvS0VnM1n4j +5pds8ELl3FFLFUHtSUrJ3hCX1nbB76W1NhSXNdh4IjVS70O92yfbYVaCNNzLiGAM +C1rlLAHGVK/XqsEQe9IFWrhAnoanw5CGAlZSCXqc0ieCU0plUmr1POeo8pyvi73T +DtTUXm6Hnmo9RR3RXRv06QqsYJn7ibT/mCzPfB3pAqoEmh643IhuJbNsZvc8kPNX +wbMv9W3y+8qh+CmdRouzavbmZwe+LGcKKh9asj5XxNMhIWNlUpEbsZmOeX7m640A +2Vqq6nPopIICR5b+W45UYaPrL0swsIsjdXJ8ITzI9vF01Bx7owVV7rtNOzK+mndm +nqxpkCIHH2E6lr7lmk/MBTwoWdPBDFSoWWG9yHJM6Nyfh3+9nEg2XpWjDrk4JFX8 +dWbrAuMINClKxuMrLzOg2qOGpRKX/YAr2hRC45K9PvJdXmd0LhyIRyk0X+IyqJwl +N4y6mACXi0mWHv0liqzc2thddG5msP9E36EYxr5ILzeUePiVSj9/E15dWf10hkNj +c0kCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD +VR0OBBYEFJ84xFYjwznooHFs6FRM5Og6sb9nMA0GCSqGSIb3DQEBCwUAA4ICAQAS +5UKme4sPDORGpbZgQIeMJX6tuGguW8ZAdjwD+MlZ9POrYs4QjbRaZIxowLByQzTS +Gwv2LFPSypBLhmb8qoMi9IsabyZIrHZ3CL/FmFz0Jomee8O5ZDIBf9PD3Vht7LGr +hFV0d4QEJ1JrhkzO3bll/9bGXp+aEJlLdWr+aumXIOTkdnrG0CSqkM0gkLpHZPt/ +B7NTeLUKYvJzQ85BK4FqLoUWlFPUa19yIqtRLULVAJyZv967lDtX/Zr1hstWO1uI +AeV8KEsD+UmDfLJ/fOPtjqF/YFOOVZ1QNBIPt5d7bIdKROf1beyAN/BYGW5KaHbw +H5Lk6rWS02FREAutp9lfx1/cH6NcjKF+m7ee01ZvZl4HliDtC3T7Zk6LERXpgUl+ +b7DUUH8i119lAg2m9IUe2K4GS0qn0jFmwvjO5QimpAKWRGhXxNUzzxkvFMSUHHuk +2fCfDrGA4tGeEWSpiBE6doLlYsKA2KSD7ZPvfC+QsDJMlhVoSFLUmQjAJOgc47Ol +IQ6SwJAfzyBfyjs4x7dtOvPmRLgOMWuIjnDrnBdSqEGULoe256YSxXXfW8AKbnuk +5F6G+TaU33fD6Q3AOfF5u0aOq0NZJ7cguyPpVkAh7DE9ZapD8j3fcEThuk0mEDuY +n/PIjhs4ViFqUZPTkcpG2om3PVODLAgfi49T3f+sHw== +-----END CERTIFICATE----- + # Issuer: CN=Microsoft ECC Root Certificate Authority 2017 O=Microsoft Corporation # Subject: CN=Microsoft ECC Root Certificate Authority 2017 O=Microsoft Corporation # Label: "Microsoft ECC Root Certificate Authority 2017" @@ -3150,6 +3628,46 @@ DgQWBBQxCpCPtsad0kRLgLWi5h+xEk8blTAKBggqhkjOPQQDAwNoADBlAjEA31SQ +RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+CAezNIm8BZ/3Hobui3A= -----END CERTIFICATE----- +# Issuer: CN=GLOBALTRUST 2020 O=e-commerce monitoring GmbH +# Subject: CN=GLOBALTRUST 2020 O=e-commerce monitoring GmbH +# Label: "GLOBALTRUST 2020" +# Serial: 109160994242082918454945253 +# MD5 Fingerprint: 8a:c7:6f:cb:6d:e3:cc:a2:f1:7c:83:fa:0e:78:d7:e8 +# SHA1 Fingerprint: d0:67:c1:13:51:01:0c:aa:d0:c7:6a:65:37:31:16:26:4f:53:71:a2 +# SHA256 Fingerprint: 9a:29:6a:51:82:d1:d4:51:a2:e3:7f:43:9b:74:da:af:a2:67:52:33:29:f9:0f:9a:0d:20:07:c3:34:e2:3c:9a +-----BEGIN CERTIFICATE----- +MIIFgjCCA2qgAwIBAgILWku9WvtPilv6ZeUwDQYJKoZIhvcNAQELBQAwTTELMAkG +A1UEBhMCQVQxIzAhBgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkw +FwYDVQQDExBHTE9CQUxUUlVTVCAyMDIwMB4XDTIwMDIxMDAwMDAwMFoXDTQwMDYx +MDAwMDAwMFowTTELMAkGA1UEBhMCQVQxIzAhBgNVBAoTGmUtY29tbWVyY2UgbW9u +aXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVTVCAyMDIwMIICIjANBgkq +hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAri5WrRsc7/aVj6B3GyvTY4+ETUWiD59b +RatZe1E0+eyLinjF3WuvvcTfk0Uev5E4C64OFudBc/jbu9G4UeDLgztzOG53ig9Z +YybNpyrOVPu44sB8R85gfD+yc/LAGbaKkoc1DZAoouQVBGM+uq/ufF7MpotQsjj3 +QWPKzv9pj2gOlTblzLmMCcpL3TGQlsjMH/1WljTbjhzqLL6FLmPdqqmV0/0plRPw +yJiT2S0WR5ARg6I6IqIoV6Lr/sCMKKCmfecqQjuCgGOlYx8ZzHyyZqjC0203b+J+ +BlHZRYQfEs4kUmSFC0iAToexIiIwquuuvuAC4EDosEKAA1GqtH6qRNdDYfOiaxaJ +SaSjpCuKAsR49GiKweR6NrFvG5Ybd0mN1MkGco/PU+PcF4UgStyYJ9ORJitHHmkH +r96i5OTUawuzXnzUJIBHKWk7buis/UDr2O1xcSvy6Fgd60GXIsUf1DnQJ4+H4xj0 +4KlGDfV0OoIu0G4skaMxXDtG6nsEEFZegB31pWXogvziB4xiRfUg3kZwhqG8k9Me +dKZssCz3AwyIDMvUclOGvGBG85hqwvG/Q/lwIHfKN0F5VVJjjVsSn8VoxIidrPIw +q7ejMZdnrY8XD2zHc+0klGvIg5rQmjdJBKuxFshsSUktq6HQjJLyQUp5ISXbY9e2 +nKd+Qmn7OmMCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwHQYDVR0OBBYEFNwuH9FhN3nkq9XVsxJxaD1qaJwiMB8GA1UdIwQYMBaAFNwu +H9FhN3nkq9XVsxJxaD1qaJwiMA0GCSqGSIb3DQEBCwUAA4ICAQCR8EICaEDuw2jA +VC/f7GLDw56KoDEoqoOOpFaWEhCGVrqXctJUMHytGdUdaG/7FELYjQ7ztdGl4wJC +XtzoRlgHNQIw4Lx0SsFDKv/bGtCwr2zD/cuz9X9tAy5ZVp0tLTWMstZDFyySCstd +6IwPS3BD0IL/qMy/pJTAvoe9iuOTe8aPmxadJ2W8esVCgmxcB9CpwYhgROmYhRZf ++I/KARDOJcP5YBugxZfD0yyIMaK9MOzQ0MAS8cE54+X1+NZK3TTN+2/BT+MAi1bi +kvcoskJ3ciNnxz8RFbLEAwW+uxF7Cr+obuf/WEPPm2eggAe2HcqtbepBEX4tdJP7 +wry+UUTF72glJ4DjyKDUEuzZpTcdN3y0kcra1LGWge9oXHYQSa9+pTeAsRxSvTOB +TI/53WXZFM2KJVj04sWDpQmQ1GwUY7VA3+vA/MRYfg0UFodUJ25W5HCEuGwyEn6C +MUO+1918oa2u1qsgEu8KwxCMSZY13At1XrFP1U80DhEgB3VDRemjEdqso5nCtnkn +4rnvyOL2NSl6dPrFf4IFYqYK6miyeUcGbvJXqBUzxvd4Sj1Ce2t+/vdG6tHrju+I +aFvowdlxfv1k7/9nR4hYJS8+hge9+6jlgqispdNpQ80xiEmEU5LAsTkbOYMBMMTy +qfrQA71yN2BWHzZ8vTmR9W0Nv3vXkg== +-----END CERTIFICATE----- + # Issuer: CN=ANF Secure Server Root CA O=ANF Autoridad de Certificacion OU=ANF CA Raiz # Subject: CN=ANF Secure Server Root CA O=ANF Autoridad de Certificacion OU=ANF CA Raiz # Label: "ANF Secure Server Root CA" @@ -3879,6 +4397,113 @@ ut6Dacpps6kFtZaSF4fC0urQe87YQVt8rgIwRt7qy12a7DLCZRawTDBcMPPaTnOG BtjOiQRINzf43TNRnXCve1XYAS59BWQOhriR -----END CERTIFICATE----- +# Issuer: CN=E-Tugra Global Root CA RSA v3 O=E-Tugra EBG A.S. OU=E-Tugra Trust Center +# Subject: CN=E-Tugra Global Root CA RSA v3 O=E-Tugra EBG A.S. OU=E-Tugra Trust Center +# Label: "E-Tugra Global Root CA RSA v3" +# Serial: 75951268308633135324246244059508261641472512052 +# MD5 Fingerprint: 22:be:10:f6:c2:f8:03:88:73:5f:33:29:47:28:47:a4 +# SHA1 Fingerprint: e9:a8:5d:22:14:52:1c:5b:aa:0a:b4:be:24:6a:23:8a:c9:ba:e2:a9 +# SHA256 Fingerprint: ef:66:b0:b1:0a:3c:db:9f:2e:36:48:c7:6b:d2:af:18:ea:d2:bf:e6:f1:17:65:5e:28:c4:06:0d:a1:a3:f4:c2 +-----BEGIN CERTIFICATE----- +MIIF8zCCA9ugAwIBAgIUDU3FzRYilZYIfrgLfxUGNPt5EDQwDQYJKoZIhvcNAQEL +BQAwgYAxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHEwZBbmthcmExGTAXBgNVBAoTEEUt +VHVncmEgRUJHIEEuUy4xHTAbBgNVBAsTFEUtVHVncmEgVHJ1c3QgQ2VudGVyMSYw +JAYDVQQDEx1FLVR1Z3JhIEdsb2JhbCBSb290IENBIFJTQSB2MzAeFw0yMDAzMTgw +OTA3MTdaFw00NTAzMTIwOTA3MTdaMIGAMQswCQYDVQQGEwJUUjEPMA0GA1UEBxMG +QW5rYXJhMRkwFwYDVQQKExBFLVR1Z3JhIEVCRyBBLlMuMR0wGwYDVQQLExRFLVR1 +Z3JhIFRydXN0IENlbnRlcjEmMCQGA1UEAxMdRS1UdWdyYSBHbG9iYWwgUm9vdCBD +QSBSU0EgdjMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCiZvCJt3J7 +7gnJY9LTQ91ew6aEOErxjYG7FL1H6EAX8z3DeEVypi6Q3po61CBxyryfHUuXCscx +uj7X/iWpKo429NEvx7epXTPcMHD4QGxLsqYxYdE0PD0xesevxKenhOGXpOhL9hd8 +7jwH7eKKV9y2+/hDJVDqJ4GohryPUkqWOmAalrv9c/SF/YP9f4RtNGx/ardLAQO/ +rWm31zLZ9Vdq6YaCPqVmMbMWPcLzJmAy01IesGykNz709a/r4d+ABs8qQedmCeFL +l+d3vSFtKbZnwy1+7dZ5ZdHPOrbRsV5WYVB6Ws5OUDGAA5hH5+QYfERaxqSzO8bG +wzrwbMOLyKSRBfP12baqBqG3q+Sx6iEUXIOk/P+2UNOMEiaZdnDpwA+mdPy70Bt4 +znKS4iicvObpCdg604nmvi533wEKb5b25Y08TVJ2Glbhc34XrD2tbKNSEhhw5oBO +M/J+JjKsBY04pOZ2PJ8QaQ5tndLBeSBrW88zjdGUdjXnXVXHt6woq0bM5zshtQoK +5EpZ3IE1S0SVEgpnpaH/WwAH0sDM+T/8nzPyAPiMbIedBi3x7+PmBvrFZhNb/FAH +nnGGstpvdDDPk1Po3CLW3iAfYY2jLqN4MpBs3KwytQXk9TwzDdbgh3cXTJ2w2Amo +DVf3RIXwyAS+XF1a4xeOVGNpf0l0ZAWMowIDAQABo2MwYTAPBgNVHRMBAf8EBTAD +AQH/MB8GA1UdIwQYMBaAFLK0ruYt9ybVqnUtdkvAG1Mh0EjvMB0GA1UdDgQWBBSy +tK7mLfcm1ap1LXZLwBtTIdBI7zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEL +BQADggIBAImocn+M684uGMQQgC0QDP/7FM0E4BQ8Tpr7nym/Ip5XuYJzEmMmtcyQ +6dIqKe6cLcwsmb5FJ+Sxce3kOJUxQfJ9emN438o2Fi+CiJ+8EUdPdk3ILY7r3y18 +Tjvarvbj2l0Upq7ohUSdBm6O++96SmotKygY/r+QLHUWnw/qln0F7psTpURs+APQ +3SPh/QMSEgj0GDSz4DcLdxEBSL9htLX4GdnLTeqjjO/98Aa1bZL0SmFQhO3sSdPk +vmjmLuMxC1QLGpLWgti2omU8ZgT5Vdps+9u1FGZNlIM7zR6mK7L+d0CGq+ffCsn9 +9t2HVhjYsCxVYJb6CH5SkPVLpi6HfMsg2wY+oF0Dd32iPBMbKaITVaA9FCKvb7jQ +mhty3QUBjYZgv6Rn7rWlDdF/5horYmbDB7rnoEgcOMPpRfunf/ztAmgayncSd6YA +VSgU7NbHEqIbZULpkejLPoeJVF3Zr52XnGnnCv8PWniLYypMfUeUP95L6VPQMPHF +9p5J3zugkaOj/s1YzOrfr28oO6Bpm4/srK4rVJ2bBLFHIK+WEj5jlB0E5y67hscM +moi/dkfv97ALl2bSRM9gUgfh1SxKOidhd8rXj+eHDjD/DLsE4mHDosiXYY60MGo8 +bcIHX0pzLz/5FooBZu+6kcpSV3uu1OYP3Qt6f4ueJiDPO++BcYNZ +-----END CERTIFICATE----- + +# Issuer: CN=E-Tugra Global Root CA ECC v3 O=E-Tugra EBG A.S. OU=E-Tugra Trust Center +# Subject: CN=E-Tugra Global Root CA ECC v3 O=E-Tugra EBG A.S. OU=E-Tugra Trust Center +# Label: "E-Tugra Global Root CA ECC v3" +# Serial: 218504919822255052842371958738296604628416471745 +# MD5 Fingerprint: 46:bc:81:bb:f1:b5:1e:f7:4b:96:bc:14:e2:e7:27:64 +# SHA1 Fingerprint: 8a:2f:af:57:53:b1:b0:e6:a1:04:ec:5b:6a:69:71:6d:f6:1c:e2:84 +# SHA256 Fingerprint: 87:3f:46:85:fa:7f:56:36:25:25:2e:6d:36:bc:d7:f1:6f:c2:49:51:f2:64:e4:7e:1b:95:4f:49:08:cd:ca:13 +-----BEGIN CERTIFICATE----- +MIICpTCCAiqgAwIBAgIUJkYZdzHhT28oNt45UYbm1JeIIsEwCgYIKoZIzj0EAwMw +gYAxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHEwZBbmthcmExGTAXBgNVBAoTEEUtVHVn +cmEgRUJHIEEuUy4xHTAbBgNVBAsTFEUtVHVncmEgVHJ1c3QgQ2VudGVyMSYwJAYD +VQQDEx1FLVR1Z3JhIEdsb2JhbCBSb290IENBIEVDQyB2MzAeFw0yMDAzMTgwOTQ2 +NThaFw00NTAzMTIwOTQ2NThaMIGAMQswCQYDVQQGEwJUUjEPMA0GA1UEBxMGQW5r +YXJhMRkwFwYDVQQKExBFLVR1Z3JhIEVCRyBBLlMuMR0wGwYDVQQLExRFLVR1Z3Jh +IFRydXN0IENlbnRlcjEmMCQGA1UEAxMdRS1UdWdyYSBHbG9iYWwgUm9vdCBDQSBF +Q0MgdjMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASOmCm/xxAeJ9urA8woLNheSBkQ +KczLWYHMjLiSF4mDKpL2w6QdTGLVn9agRtwcvHbB40fQWxPa56WzZkjnIZpKT4YK +fWzqTTKACrJ6CZtpS5iB4i7sAnCWH/31Rs7K3IKjYzBhMA8GA1UdEwEB/wQFMAMB +Af8wHwYDVR0jBBgwFoAU/4Ixcj75xGZsrTie0bBRiKWQzPUwHQYDVR0OBBYEFP+C +MXI++cRmbK04ntGwUYilkMz1MA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNp +ADBmAjEA5gVYaWHlLcoNy/EZCL3W/VGSGn5jVASQkZo1kTmZ+gepZpO6yGjUij/6 +7W4WAie3AjEA3VoXK3YdZUKWpqxdinlW2Iob35reX8dQj7FbcQwm32pAAOwzkSFx +vmjkI6TZraE3 +-----END CERTIFICATE----- + +# Issuer: CN=Security Communication RootCA3 O=SECOM Trust Systems CO.,LTD. +# Subject: CN=Security Communication RootCA3 O=SECOM Trust Systems CO.,LTD. +# Label: "Security Communication RootCA3" +# Serial: 16247922307909811815 +# MD5 Fingerprint: 1c:9a:16:ff:9e:5c:e0:4d:8a:14:01:f4:35:5d:29:26 +# SHA1 Fingerprint: c3:03:c8:22:74:92:e5:61:a2:9c:5f:79:91:2b:1e:44:13:91:30:3a +# SHA256 Fingerprint: 24:a5:5c:2a:b0:51:44:2d:06:17:76:65:41:23:9a:4a:d0:32:d7:c5:51:75:aa:34:ff:de:2f:bc:4f:5c:52:94 +-----BEGIN CERTIFICATE----- +MIIFfzCCA2egAwIBAgIJAOF8N0D9G/5nMA0GCSqGSIb3DQEBDAUAMF0xCzAJBgNV +BAYTAkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMScw +JQYDVQQDEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTMwHhcNMTYwNjE2 +MDYxNzE2WhcNMzgwMTE4MDYxNzE2WjBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc +U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UEAxMeU2VjdXJpdHkg +Q29tbXVuaWNhdGlvbiBSb290Q0EzMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC +CgKCAgEA48lySfcw3gl8qUCBWNO0Ot26YQ+TUG5pPDXC7ltzkBtnTCHsXzW7OT4r +CmDvu20rhvtxosis5FaU+cmvsXLUIKx00rgVrVH+hXShuRD+BYD5UpOzQD11EKzA +lrenfna84xtSGc4RHwsENPXY9Wk8d/Nk9A2qhd7gCVAEF5aEt8iKvE1y/By7z/MG +TfmfZPd+pmaGNXHIEYBMwXFAWB6+oHP2/D5Q4eAvJj1+XCO1eXDe+uDRpdYMQXF7 +9+qMHIjH7Iv10S9VlkZ8WjtYO/u62C21Jdp6Ts9EriGmnpjKIG58u4iFW/vAEGK7 +8vknR+/RiTlDxN/e4UG/VHMgly1s2vPUB6PmudhvrvyMGS7TZ2crldtYXLVqAvO4 +g160a75BflcJdURQVc1aEWEhCmHCqYj9E7wtiS/NYeCVvsq1e+F7NGcLH7YMx3we +GVPKp7FKFSBWFHA9K4IsD50VHUeAR/94mQ4xr28+j+2GaR57GIgUssL8gjMunEst ++3A7caoreyYn8xrC3PsXuKHqy6C0rtOUfnrQq8PsOC0RLoi/1D+tEjtCrI8Cbn3M +0V9hvqG8OmpI6iZVIhZdXw3/JzOfGAN0iltSIEdrRU0id4xVJ/CvHozJgyJUt5rQ +T9nO/NkuHJYosQLTA70lUhw0Zk8jq/R3gpYd0VcwCBEF/VfR2ccCAwEAAaNCMEAw +HQYDVR0OBBYEFGQUfPxYchamCik0FW8qy7z8r6irMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBDAUAA4ICAQDcAiMI4u8hOscNtybS +YpOnpSNyByCCYN8Y11StaSWSntkUz5m5UoHPrmyKO1o5yGwBQ8IibQLwYs1OY0PA +FNr0Y/Dq9HHuTofjcan0yVflLl8cebsjqodEV+m9NU1Bu0soo5iyG9kLFwfl9+qd +9XbXv8S2gVj/yP9kaWJ5rW4OH3/uHWnlt3Jxs/6lATWUVCvAUm2PVcTJ0rjLyjQI +UYWg9by0F1jqClx6vWPGOi//lkkZhOpn2ASxYfQAW0q3nHE3GYV5v4GwxxMOdnE+ +OoAGrgYWp421wsTL/0ClXI2lyTrtcoHKXJg80jQDdwj98ClZXSEIx2C/pHF7uNke +gr4Jr2VvKKu/S7XuPghHJ6APbw+LP6yVGPO5DtxnVW5inkYO0QR4ynKudtml+LLf +iAlhi+8kTtFZP1rUPcmTPCtk9YENFpb3ksP+MW/oKjJ0DvRMmEoYDjBU1cXrvMUV +nuiZIesnKwkK2/HmcBhWuwzkvvnoEKQTkrgc4NtnHVMDpCKn3F2SEDzq//wbEBrD +2NCcnWXL0CsnMQMeNuE9dnUM/0Umud1RvCPHX9jYhxBAEg09ODfnRDwYwFMJZI// +1ZqmfHAuc1Uh6N//g7kdPjIe1qZ9LPFm6Vwdp6POXiUyK+OVrCoHzrQoeIY8Laad +TdJ0MN1kURXbg4NR16/9M51NZg== +-----END CERTIFICATE----- + # Issuer: CN=Security Communication ECC RootCA1 O=SECOM Trust Systems CO.,LTD. # Subject: CN=Security Communication ECC RootCA1 O=SECOM Trust Systems CO.,LTD. # Label: "Security Communication ECC RootCA1" @@ -3900,901 +4525,3 @@ BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjAVXUI9/Lbu 9zuxNuie9sRGKEkz0FhDKmMpzE2xtHqiuQ04pV1IKv3LsnNdo4gIxwwCMQDAqy0O be0YottT6SXbVQjgUMzfRGEWgqtJsLKB7HOHeLRMsmIbEvoWTSVLY70eN9k= -----END CERTIFICATE----- - -# Issuer: CN=BJCA Global Root CA1 O=BEIJING CERTIFICATE AUTHORITY -# Subject: CN=BJCA Global Root CA1 O=BEIJING CERTIFICATE AUTHORITY -# Label: "BJCA Global Root CA1" -# Serial: 113562791157148395269083148143378328608 -# MD5 Fingerprint: 42:32:99:76:43:33:36:24:35:07:82:9b:28:f9:d0:90 -# SHA1 Fingerprint: d5:ec:8d:7b:4c:ba:79:f4:e7:e8:cb:9d:6b:ae:77:83:10:03:21:6a -# SHA256 Fingerprint: f3:89:6f:88:fe:7c:0a:88:27:66:a7:fa:6a:d2:74:9f:b5:7a:7f:3e:98:fb:76:9c:1f:a7:b0:9c:2c:44:d5:ae ------BEGIN CERTIFICATE----- -MIIFdDCCA1ygAwIBAgIQVW9l47TZkGobCdFsPsBsIDANBgkqhkiG9w0BAQsFADBU -MQswCQYDVQQGEwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRI -T1JJVFkxHTAbBgNVBAMMFEJKQ0EgR2xvYmFsIFJvb3QgQ0ExMB4XDTE5MTIxOTAz -MTYxN1oXDTQ0MTIxMjAzMTYxN1owVDELMAkGA1UEBhMCQ04xJjAkBgNVBAoMHUJF -SUpJTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRCSkNBIEdsb2Jh -bCBSb290IENBMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAPFmCL3Z -xRVhy4QEQaVpN3cdwbB7+sN3SJATcmTRuHyQNZ0YeYjjlwE8R4HyDqKYDZ4/N+AZ -spDyRhySsTphzvq3Rp4Dhtczbu33RYx2N95ulpH3134rhxfVizXuhJFyV9xgw8O5 -58dnJCNPYwpj9mZ9S1WnP3hkSWkSl+BMDdMJoDIwOvqfwPKcxRIqLhy1BDPapDgR -at7GGPZHOiJBhyL8xIkoVNiMpTAK+BcWyqw3/XmnkRd4OJmtWO2y3syJfQOcs4ll -5+M7sSKGjwZteAf9kRJ/sGsciQ35uMt0WwfCyPQ10WRjeulumijWML3mG90Vr4Tq -nMfK9Q7q8l0ph49pczm+LiRvRSGsxdRpJQaDrXpIhRMsDQa4bHlW/KNnMoH1V6XK -V0Jp6VwkYe/iMBhORJhVb3rCk9gZtt58R4oRTklH2yiUAguUSiz5EtBP6DF+bHq/ -pj+bOT0CFqMYs2esWz8sgytnOYFcuX6U1WTdno9uruh8W7TXakdI136z1C2OVnZO -z2nxbkRs1CTqjSShGL+9V/6pmTW12xB3uD1IutbB5/EjPtffhZ0nPNRAvQoMvfXn -jSXWgXSHRtQpdaJCbPdzied9v3pKH9MiyRVVz99vfFXQpIsHETdfg6YmV6YBW37+ -WGgHqel62bno/1Afq8K0wM7o6v0PvY1NuLxxAgMBAAGjQjBAMB0GA1UdDgQWBBTF -7+3M2I0hxkjk49cULqcWk+WYATAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE -AwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAUoKsITQfI/Ki2Pm4rzc2IInRNwPWaZ+4 -YRC6ojGYWUfo0Q0lHhVBDOAqVdVXUsv45Mdpox1NcQJeXyFFYEhcCY5JEMEE3Kli -awLwQ8hOnThJdMkycFRtwUf8jrQ2ntScvd0g1lPJGKm1Vrl2i5VnZu69mP6u775u -+2D2/VnGKhs/I0qUJDAnyIm860Qkmss9vk/Ves6OF8tiwdneHg56/0OGNFK8YT88 -X7vZdrRTvJez/opMEi4r89fO4aL/3Xtw+zuhTaRjAv04l5U/BXCga99igUOLtFkN -SoxUnMW7gZ/NfaXvCyUeOiDbHPwfmGcCCtRzRBPbUYQaVQNW4AB+dAb/OMRyHdOo -P2gxXdMJxy6MW2Pg6Nwe0uxhHvLe5e/2mXZgLR6UcnHGCyoyx5JO1UbXHfmpGQrI -+pXObSOYqgs4rZpWDW+N8TEAiMEXnM0ZNjX+VVOg4DwzX5Ze4jLp3zO7Bkqp2IRz -znfSxqxx4VyjHQy7Ct9f4qNx2No3WqB4K/TUfet27fJhcKVlmtOJNBir+3I+17Q9 -eVzYH6Eze9mCUAyTF6ps3MKCuwJXNq+YJyo5UOGwifUll35HaBC07HPKs5fRJNz2 -YqAo07WjuGS3iGJCz51TzZm+ZGiPTx4SSPfSKcOYKMryMguTjClPPGAyzQWWYezy -r/6zcCwupvI= ------END CERTIFICATE----- - -# Issuer: CN=BJCA Global Root CA2 O=BEIJING CERTIFICATE AUTHORITY -# Subject: CN=BJCA Global Root CA2 O=BEIJING CERTIFICATE AUTHORITY -# Label: "BJCA Global Root CA2" -# Serial: 58605626836079930195615843123109055211 -# MD5 Fingerprint: 5e:0a:f6:47:5f:a6:14:e8:11:01:95:3f:4d:01:eb:3c -# SHA1 Fingerprint: f4:27:86:eb:6e:b8:6d:88:31:67:02:fb:ba:66:a4:53:00:aa:7a:a6 -# SHA256 Fingerprint: 57:4d:f6:93:1e:27:80:39:66:7b:72:0a:fd:c1:60:0f:c2:7e:b6:6d:d3:09:29:79:fb:73:85:64:87:21:28:82 ------BEGIN CERTIFICATE----- -MIICJTCCAaugAwIBAgIQLBcIfWQqwP6FGFkGz7RK6zAKBggqhkjOPQQDAzBUMQsw -CQYDVQQGEwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRIT1JJ -VFkxHTAbBgNVBAMMFEJKQ0EgR2xvYmFsIFJvb3QgQ0EyMB4XDTE5MTIxOTAzMTgy -MVoXDTQ0MTIxMjAzMTgyMVowVDELMAkGA1UEBhMCQ04xJjAkBgNVBAoMHUJFSUpJ -TkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRCSkNBIEdsb2JhbCBS -b290IENBMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABJ3LgJGNU2e1uVCxA/jlSR9B -IgmwUVJY1is0j8USRhTFiy8shP8sbqjV8QnjAyEUxEM9fMEsxEtqSs3ph+B99iK+ -+kpRuDCK/eHeGBIK9ke35xe/J4rUQUyWPGCWwf0VHKNCMEAwHQYDVR0OBBYEFNJK -sVF/BvDRgh9Obl+rg/xI1LCRMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD -AgEGMAoGCCqGSM49BAMDA2gAMGUCMBq8W9f+qdJUDkpd0m2xQNz0Q9XSSpkZElaA -94M04TVOSG0ED1cxMDAtsaqdAzjbBgIxAMvMh1PLet8gUXOQwKhbYdDFUDn9hf7B -43j4ptZLvZuHjw/l1lOWqzzIQNph91Oj9w== ------END CERTIFICATE----- - -# Issuer: CN=Sectigo Public Server Authentication Root E46 O=Sectigo Limited -# Subject: CN=Sectigo Public Server Authentication Root E46 O=Sectigo Limited -# Label: "Sectigo Public Server Authentication Root E46" -# Serial: 88989738453351742415770396670917916916 -# MD5 Fingerprint: 28:23:f8:b2:98:5c:37:16:3b:3e:46:13:4e:b0:b3:01 -# SHA1 Fingerprint: ec:8a:39:6c:40:f0:2e:bc:42:75:d4:9f:ab:1c:1a:5b:67:be:d2:9a -# SHA256 Fingerprint: c9:0f:26:f0:fb:1b:40:18:b2:22:27:51:9b:5c:a2:b5:3e:2c:a5:b3:be:5c:f1:8e:fe:1b:ef:47:38:0c:53:83 ------BEGIN CERTIFICATE----- -MIICOjCCAcGgAwIBAgIQQvLM2htpN0RfFf51KBC49DAKBggqhkjOPQQDAzBfMQsw -CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1T -ZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwHhcN -MjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEYMBYG -A1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBT -ZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA -IgNiAAR2+pmpbiDt+dd34wc7qNs9Xzjoq1WmVk/WSOrsfy2qw7LFeeyZYX8QeccC -WvkEN/U0NSt3zn8gj1KjAIns1aeibVvjS5KToID1AZTc8GgHHs3u/iVStSBDHBv+ -6xnOQ6OjQjBAMB0GA1UdDgQWBBTRItpMWfFLXyY4qp3W7usNw/upYTAOBgNVHQ8B -Af8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNnADBkAjAn7qRa -qCG76UeXlImldCBteU/IvZNeWBj7LRoAasm4PdCkT0RHlAFWovgzJQxC36oCMB3q -4S6ILuH5px0CMk7yn2xVdOOurvulGu7t0vzCAxHrRVxgED1cf5kDW21USAGKcw== ------END CERTIFICATE----- - -# Issuer: CN=Sectigo Public Server Authentication Root R46 O=Sectigo Limited -# Subject: CN=Sectigo Public Server Authentication Root R46 O=Sectigo Limited -# Label: "Sectigo Public Server Authentication Root R46" -# Serial: 156256931880233212765902055439220583700 -# MD5 Fingerprint: 32:10:09:52:00:d5:7e:6c:43:df:15:c0:b1:16:93:e5 -# SHA1 Fingerprint: ad:98:f9:f3:e4:7d:75:3b:65:d4:82:b3:a4:52:17:bb:6e:f5:e4:38 -# SHA256 Fingerprint: 7b:b6:47:a6:2a:ee:ac:88:bf:25:7a:a5:22:d0:1f:fe:a3:95:e0:ab:45:c7:3f:93:f6:56:54:ec:38:f2:5a:06 ------BEGIN CERTIFICATE----- -MIIFijCCA3KgAwIBAgIQdY39i658BwD6qSWn4cetFDANBgkqhkiG9w0BAQwFADBf -MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQD -Ey1TZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYw -HhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEY -MBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1Ymxp -YyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB -AQUAA4ICDwAwggIKAoICAQCTvtU2UnXYASOgHEdCSe5jtrch/cSV1UgrJnwUUxDa -ef0rty2k1Cz66jLdScK5vQ9IPXtamFSvnl0xdE8H/FAh3aTPaE8bEmNtJZlMKpnz -SDBh+oF8HqcIStw+KxwfGExxqjWMrfhu6DtK2eWUAtaJhBOqbchPM8xQljeSM9xf -iOefVNlI8JhD1mb9nxc4Q8UBUQvX4yMPFF1bFOdLvt30yNoDN9HWOaEhUTCDsG3X -ME6WW5HwcCSrv0WBZEMNvSE6Lzzpng3LILVCJ8zab5vuZDCQOc2TZYEhMbUjUDM3 -IuM47fgxMMxF/mL50V0yeUKH32rMVhlATc6qu/m1dkmU8Sf4kaWD5QazYw6A3OAS -VYCmO2a0OYctyPDQ0RTp5A1NDvZdV3LFOxxHVp3i1fuBYYzMTYCQNFu31xR13NgE -SJ/AwSiItOkcyqex8Va3e0lMWeUgFaiEAin6OJRpmkkGj80feRQXEgyDet4fsZfu -+Zd4KKTIRJLpfSYFplhym3kT2BFfrsU4YjRosoYwjviQYZ4ybPUHNs2iTG7sijbt -8uaZFURww3y8nDnAtOFr94MlI1fZEoDlSfB1D++N6xybVCi0ITz8fAr/73trdf+L -HaAZBav6+CuBQug4urv7qv094PPK306Xlynt8xhW6aWWrL3DkJiy4Pmi1KZHQ3xt -zwIDAQABo0IwQDAdBgNVHQ4EFgQUVnNYZJX5khqwEioEYnmhQBWIIUkwDgYDVR0P -AQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAC9c -mTz8Bl6MlC5w6tIyMY208FHVvArzZJ8HXtXBc2hkeqK5Duj5XYUtqDdFqij0lgVQ -YKlJfp/imTYpE0RHap1VIDzYm/EDMrraQKFz6oOht0SmDpkBm+S8f74TlH7Kph52 -gDY9hAaLMyZlbcp+nv4fjFg4exqDsQ+8FxG75gbMY/qB8oFM2gsQa6H61SilzwZA -Fv97fRheORKkU55+MkIQpiGRqRxOF3yEvJ+M0ejf5lG5Nkc/kLnHvALcWxxPDkjB -JYOcCj+esQMzEhonrPcibCTRAUH4WAP+JWgiH5paPHxsnnVI84HxZmduTILA7rpX -DhjvLpr3Etiga+kFpaHpaPi8TD8SHkXoUsCjvxInebnMMTzD9joiFgOgyY9mpFui -TdaBJQbpdqQACj7LzTWb4OE4y2BThihCQRxEV+ioratF4yUQvNs+ZUH7G6aXD+u5 -dHn5HrwdVw1Hr8Mvn4dGp+smWg9WY7ViYG4A++MnESLn/pmPNPW56MORcr3Ywx65 -LvKRRFHQV80MNNVIIb/bE/FmJUNS0nAiNs2fxBx1IK1jcmMGDw4nztJqDby1ORrp -0XZ60Vzk50lJLVU3aPAaOpg+VBeHVOmmJ1CJeyAvP/+/oYtKR5j/K3tJPsMpRmAY -QqszKbrAKbkTidOIijlBO8n9pu0f9GBj39ItVQGL ------END CERTIFICATE----- - -# Issuer: CN=SSL.com TLS RSA Root CA 2022 O=SSL Corporation -# Subject: CN=SSL.com TLS RSA Root CA 2022 O=SSL Corporation -# Label: "SSL.com TLS RSA Root CA 2022" -# Serial: 148535279242832292258835760425842727825 -# MD5 Fingerprint: d8:4e:c6:59:30:d8:fe:a0:d6:7a:5a:2c:2c:69:78:da -# SHA1 Fingerprint: ec:2c:83:40:72:af:26:95:10:ff:0e:f2:03:ee:31:70:f6:78:9d:ca -# SHA256 Fingerprint: 8f:af:7d:2e:2c:b4:70:9b:b8:e0:b3:36:66:bf:75:a5:dd:45:b5:de:48:0f:8e:a8:d4:bf:e6:be:bc:17:f2:ed ------BEGIN CERTIFICATE----- -MIIFiTCCA3GgAwIBAgIQb77arXO9CEDii02+1PdbkTANBgkqhkiG9w0BAQsFADBO -MQswCQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQD -DBxTU0wuY29tIFRMUyBSU0EgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzQyMloX -DTQ2MDgxOTE2MzQyMVowTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jw -b3JhdGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgUlNBIFJvb3QgQ0EgMjAyMjCC -AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANCkCXJPQIgSYT41I57u9nTP -L3tYPc48DRAokC+X94xI2KDYJbFMsBFMF3NQ0CJKY7uB0ylu1bUJPiYYf7ISf5OY -t6/wNr/y7hienDtSxUcZXXTzZGbVXcdotL8bHAajvI9AI7YexoS9UcQbOcGV0ins -S657Lb85/bRi3pZ7QcacoOAGcvvwB5cJOYF0r/c0WRFXCsJbwST0MXMwgsadugL3 -PnxEX4MN8/HdIGkWCVDi1FW24IBydm5MR7d1VVm0U3TZlMZBrViKMWYPHqIbKUBO -L9975hYsLfy/7PO0+r4Y9ptJ1O4Fbtk085zx7AGL0SDGD6C1vBdOSHtRwvzpXGk3 -R2azaPgVKPC506QVzFpPulJwoxJF3ca6TvvC0PeoUidtbnm1jPx7jMEWTO6Af77w -dr5BUxIzrlo4QqvXDz5BjXYHMtWrifZOZ9mxQnUjbvPNQrL8VfVThxc7wDNY8VLS -+YCk8OjwO4s4zKTGkH8PnP2L0aPP2oOnaclQNtVcBdIKQXTbYxE3waWglksejBYS -d66UNHsef8JmAOSqg+qKkK3ONkRN0VHpvB/zagX9wHQfJRlAUW7qglFA35u5CCoG -AtUjHBPW6dvbxrB6y3snm/vg1UYk7RBLY0ulBY+6uB0rpvqR4pJSvezrZ5dtmi2f -gTIFZzL7SAg/2SW4BCUvAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j -BBgwFoAU+y437uOEeicuzRk1sTN8/9REQrkwHQYDVR0OBBYEFPsuN+7jhHonLs0Z -NbEzfP/UREK5MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAjYlt -hEUY8U+zoO9opMAdrDC8Z2awms22qyIZZtM7QbUQnRC6cm4pJCAcAZli05bg4vsM -QtfhWsSWTVTNj8pDU/0quOr4ZcoBwq1gaAafORpR2eCNJvkLTqVTJXojpBzOCBvf -R4iyrT7gJ4eLSYwfqUdYe5byiB0YrrPRpgqU+tvT5TgKa3kSM/tKWTcWQA673vWJ -DPFs0/dRa1419dvAJuoSc06pkZCmF8NsLzjUo3KUQyxi4U5cMj29TH0ZR6LDSeeW -P4+a0zvkEdiLA9z2tmBVGKaBUfPhqBVq6+AL8BQx1rmMRTqoENjwuSfr98t67wVy -lrXEj5ZzxOhWc5y8aVFjvO9nHEMaX3cZHxj4HCUp+UmZKbaSPaKDN7EgkaibMOlq -bLQjk2UEqxHzDh1TJElTHaE/nUiSEeJ9DU/1172iWD54nR4fK/4huxoTtrEoZP2w -AgDHbICivRZQIA9ygV/MlP+7mea6kMvq+cYMwq7FGc4zoWtcu358NFcXrfA/rs3q -r5nsLFR+jM4uElZI7xc7P0peYNLcdDa8pUNjyw9bowJWCZ4kLOGGgYz+qxcs+sji -Mho6/4UIyYOf8kpIEFR3N+2ivEC+5BB09+Rbu7nzifmPQdjH5FCQNYA+HLhNkNPU -98OwoX6EyneSMSy4kLGCenROmxMmtNVQZlR4rmA= ------END CERTIFICATE----- - -# Issuer: CN=SSL.com TLS ECC Root CA 2022 O=SSL Corporation -# Subject: CN=SSL.com TLS ECC Root CA 2022 O=SSL Corporation -# Label: "SSL.com TLS ECC Root CA 2022" -# Serial: 26605119622390491762507526719404364228 -# MD5 Fingerprint: 99:d7:5c:f1:51:36:cc:e9:ce:d9:19:2e:77:71:56:c5 -# SHA1 Fingerprint: 9f:5f:d9:1a:54:6d:f5:0c:71:f0:ee:7a:bd:17:49:98:84:73:e2:39 -# SHA256 Fingerprint: c3:2f:fd:9f:46:f9:36:d1:6c:36:73:99:09:59:43:4b:9a:d6:0a:af:bb:9e:7c:f3:36:54:f1:44:cc:1b:a1:43 ------BEGIN CERTIFICATE----- -MIICOjCCAcCgAwIBAgIQFAP1q/s3ixdAW+JDsqXRxDAKBggqhkjOPQQDAzBOMQsw -CQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxT -U0wuY29tIFRMUyBFQ0MgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzM0OFoXDTQ2 -MDgxOTE2MzM0N1owTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jwb3Jh -dGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgRUNDIFJvb3QgQ0EgMjAyMjB2MBAG -ByqGSM49AgEGBSuBBAAiA2IABEUpNXP6wrgjzhR9qLFNoFs27iosU8NgCTWyJGYm -acCzldZdkkAZDsalE3D07xJRKF3nzL35PIXBz5SQySvOkkJYWWf9lCcQZIxPBLFN -SeR7T5v15wj4A4j3p8OSSxlUgaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSME -GDAWgBSJjy+j6CugFFR781a4Jl9nOAuc0DAdBgNVHQ4EFgQUiY8vo+groBRUe/NW -uCZfZzgLnNAwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2gAMGUCMFXjIlbp -15IkWE8elDIPDAI2wv2sdDJO4fscgIijzPvX6yv/N33w7deedWo1dlJF4AIxAMeN -b0Igj762TVntd00pxCAgRWSGOlDGxK0tk/UYfXLtqc/ErFc2KAhl3zx5Zn6g6g== ------END CERTIFICATE----- - -# Issuer: CN=Atos TrustedRoot Root CA ECC TLS 2021 O=Atos -# Subject: CN=Atos TrustedRoot Root CA ECC TLS 2021 O=Atos -# Label: "Atos TrustedRoot Root CA ECC TLS 2021" -# Serial: 81873346711060652204712539181482831616 -# MD5 Fingerprint: 16:9f:ad:f1:70:ad:79:d6:ed:29:b4:d1:c5:79:70:a8 -# SHA1 Fingerprint: 9e:bc:75:10:42:b3:02:f3:81:f4:f7:30:62:d4:8f:c3:a7:51:b2:dd -# SHA256 Fingerprint: b2:fa:e5:3e:14:cc:d7:ab:92:12:06:47:01:ae:27:9c:1d:89:88:fa:cb:77:5f:a8:a0:08:91:4e:66:39:88:a8 ------BEGIN CERTIFICATE----- -MIICFTCCAZugAwIBAgIQPZg7pmY9kGP3fiZXOATvADAKBggqhkjOPQQDAzBMMS4w -LAYDVQQDDCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgRUNDIFRMUyAyMDIxMQ0w -CwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0yMTA0MjIwOTI2MjNaFw00MTA0 -MTcwOTI2MjJaMEwxLjAsBgNVBAMMJUF0b3MgVHJ1c3RlZFJvb3QgUm9vdCBDQSBF -Q0MgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYTAkRFMHYwEAYHKoZI -zj0CAQYFK4EEACIDYgAEloZYKDcKZ9Cg3iQZGeHkBQcfl+3oZIK59sRxUM6KDP/X -tXa7oWyTbIOiaG6l2b4siJVBzV3dscqDY4PMwL502eCdpO5KTlbgmClBk1IQ1SQ4 -AjJn8ZQSb+/Xxd4u/RmAo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR2 -KCXWfeBmmnoJsmo7jjPXNtNPojAOBgNVHQ8BAf8EBAMCAYYwCgYIKoZIzj0EAwMD -aAAwZQIwW5kp85wxtolrbNa9d+F851F+uDrNozZffPc8dz7kUK2o59JZDCaOMDtu -CCrCp1rIAjEAmeMM56PDr9NJLkaCI2ZdyQAUEv049OGYa3cpetskz2VAv9LcjBHo -9H1/IISpQuQo ------END CERTIFICATE----- - -# Issuer: CN=Atos TrustedRoot Root CA RSA TLS 2021 O=Atos -# Subject: CN=Atos TrustedRoot Root CA RSA TLS 2021 O=Atos -# Label: "Atos TrustedRoot Root CA RSA TLS 2021" -# Serial: 111436099570196163832749341232207667876 -# MD5 Fingerprint: d4:d3:46:b8:9a:c0:9c:76:5d:9e:3a:c3:b9:99:31:d2 -# SHA1 Fingerprint: 18:52:3b:0d:06:37:e4:d6:3a:df:23:e4:98:fb:5b:16:fb:86:74:48 -# SHA256 Fingerprint: 81:a9:08:8e:a5:9f:b3:64:c5:48:a6:f8:55:59:09:9b:6f:04:05:ef:bf:18:e5:32:4e:c9:f4:57:ba:00:11:2f ------BEGIN CERTIFICATE----- -MIIFZDCCA0ygAwIBAgIQU9XP5hmTC/srBRLYwiqipDANBgkqhkiG9w0BAQwFADBM -MS4wLAYDVQQDDCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgUlNBIFRMUyAyMDIx -MQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0yMTA0MjIwOTIxMTBaFw00 -MTA0MTcwOTIxMDlaMEwxLjAsBgNVBAMMJUF0b3MgVHJ1c3RlZFJvb3QgUm9vdCBD -QSBSU0EgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYTAkRFMIICIjAN -BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtoAOxHm9BYx9sKOdTSJNy/BBl01Z -4NH+VoyX8te9j2y3I49f1cTYQcvyAh5x5en2XssIKl4w8i1mx4QbZFc4nXUtVsYv -Ye+W/CBGvevUez8/fEc4BKkbqlLfEzfTFRVOvV98r61jx3ncCHvVoOX3W3WsgFWZ -kmGbzSoXfduP9LVq6hdKZChmFSlsAvFr1bqjM9xaZ6cF4r9lthawEO3NUDPJcFDs -GY6wx/J0W2tExn2WuZgIWWbeKQGb9Cpt0xU6kGpn8bRrZtkh68rZYnxGEFzedUln -nkL5/nWpo63/dgpnQOPF943HhZpZnmKaau1Fh5hnstVKPNe0OwANwI8f4UDErmwh -3El+fsqyjW22v5MvoVw+j8rtgI5Y4dtXz4U2OLJxpAmMkokIiEjxQGMYsluMWuPD -0xeqqxmjLBvk1cbiZnrXghmmOxYsL3GHX0WelXOTwkKBIROW1527k2gV+p2kHYzy -geBYBr3JtuP2iV2J+axEoctr+hbxx1A9JNr3w+SH1VbxT5Aw+kUJWdo0zuATHAR8 -ANSbhqRAvNncTFd+rrcztl524WWLZt+NyteYr842mIycg5kDcPOvdO3GDjbnvezB -c6eUWsuSZIKmAMFwoW4sKeFYV+xafJlrJaSQOoD0IJ2azsct+bJLKZWD6TWNp0lI -pw9MGZHQ9b8Q4HECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU -dEmZ0f+0emhFdcN+tNzMzjkz2ggwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB -DAUAA4ICAQAjQ1MkYlxt/T7Cz1UAbMVWiLkO3TriJQ2VSpfKgInuKs1l+NsW4AmS -4BjHeJi78+xCUvuppILXTdiK/ORO/auQxDh1MoSf/7OwKwIzNsAQkG8dnK/haZPs -o0UvFJ/1TCplQ3IM98P4lYsU84UgYt1UU90s3BiVaU+DR3BAM1h3Egyi61IxHkzJ -qM7F78PRreBrAwA0JrRUITWXAdxfG/F851X6LWh3e9NpzNMOa7pNdkTWwhWaJuyw -xfW70Xp0wmzNxbVe9kzmWy2B27O3Opee7c9GslA9hGCZcbUztVdF5kJHdWoOsAgM -rr3e97sPWD2PAzHoPYJQyi9eDF20l74gNAf0xBLh7tew2VktafcxBPTy+av5EzH4 -AXcOPUIjJsyacmdRIXrMPIWo6iFqO9taPKU0nprALN+AnCng33eU0aKAQv9qTFsR -0PXNor6uzFFcw9VUewyu1rkGd4Di7wcaaMxZUa1+XGdrudviB0JbuAEFWDlN5LuY -o7Ey7Nmj1m+UI/87tyll5gfp77YZ6ufCOB0yiJA8EytuzO+rdwY0d4RPcuSBhPm5 -dDTedk+SKlOxJTnbPP/lPqYO5Wue/9vsL3SD3460s6neFE3/MaNFcyT6lSnMEpcE -oji2jbDwN/zIIX8/syQbPYtuzE2wFg2WHYMfRsCbvUOZ58SWLs5fyQ== ------END CERTIFICATE----- - -# Issuer: CN=TrustAsia Global Root CA G3 O=TrustAsia Technologies, Inc. -# Subject: CN=TrustAsia Global Root CA G3 O=TrustAsia Technologies, Inc. -# Label: "TrustAsia Global Root CA G3" -# Serial: 576386314500428537169965010905813481816650257167 -# MD5 Fingerprint: 30:42:1b:b7:bb:81:75:35:e4:16:4f:53:d2:94:de:04 -# SHA1 Fingerprint: 63:cf:b6:c1:27:2b:56:e4:88:8e:1c:23:9a:b6:2e:81:47:24:c3:c7 -# SHA256 Fingerprint: e0:d3:22:6a:eb:11:63:c2:e4:8f:f9:be:3b:50:b4:c6:43:1b:e7:bb:1e:ac:c5:c3:6b:5d:5e:c5:09:03:9a:08 ------BEGIN CERTIFICATE----- -MIIFpTCCA42gAwIBAgIUZPYOZXdhaqs7tOqFhLuxibhxkw8wDQYJKoZIhvcNAQEM -BQAwWjELMAkGA1UEBhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dp -ZXMsIEluYy4xJDAiBgNVBAMMG1RydXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHMzAe -Fw0yMTA1MjAwMjEwMTlaFw00NjA1MTkwMjEwMTlaMFoxCzAJBgNVBAYTAkNOMSUw -IwYDVQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSQwIgYDVQQDDBtU -cnVzdEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzMwggIiMA0GCSqGSIb3DQEBAQUAA4IC -DwAwggIKAoICAQDAMYJhkuSUGwoqZdC+BqmHO1ES6nBBruL7dOoKjbmzTNyPtxNS -T1QY4SxzlZHFZjtqz6xjbYdT8PfxObegQ2OwxANdV6nnRM7EoYNl9lA+sX4WuDqK -AtCWHwDNBSHvBm3dIZwZQ0WhxeiAysKtQGIXBsaqvPPW5vxQfmZCHzyLpnl5hkA1 -nyDvP+uLRx+PjsXUjrYsyUQE49RDdT/VP68czH5GX6zfZBCK70bwkPAPLfSIC7Ep -qq+FqklYqL9joDiR5rPmd2jE+SoZhLsO4fWvieylL1AgdB4SQXMeJNnKziyhWTXA -yB1GJ2Faj/lN03J5Zh6fFZAhLf3ti1ZwA0pJPn9pMRJpxx5cynoTi+jm9WAPzJMs -hH/x/Gr8m0ed262IPfN2dTPXS6TIi/n1Q1hPy8gDVI+lhXgEGvNz8teHHUGf59gX -zhqcD0r83ERoVGjiQTz+LISGNzzNPy+i2+f3VANfWdP3kXjHi3dqFuVJhZBFcnAv -kV34PmVACxmZySYgWmjBNb9Pp1Hx2BErW+Canig7CjoKH8GB5S7wprlppYiU5msT -f9FkPz2ccEblooV7WIQn3MSAPmeamseaMQ4w7OYXQJXZRe0Blqq/DPNL0WP3E1jA -uPP6Z92bfW1K/zJMtSU7/xxnD4UiWQWRkUF3gdCFTIcQcf+eQxuulXUtgQIDAQAB -o2MwYTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFEDk5PIj7zjKsK5Xf/Ih -MBY027ySMB0GA1UdDgQWBBRA5OTyI+84yrCuV3/yITAWNNu8kjAOBgNVHQ8BAf8E -BAMCAQYwDQYJKoZIhvcNAQEMBQADggIBACY7UeFNOPMyGLS0XuFlXsSUT9SnYaP4 -wM8zAQLpw6o1D/GUE3d3NZ4tVlFEbuHGLige/9rsR82XRBf34EzC4Xx8MnpmyFq2 -XFNFV1pF1AWZLy4jVe5jaN/TG3inEpQGAHUNcoTpLrxaatXeL1nHo+zSh2bbt1S1 -JKv0Q3jbSwTEb93mPmY+KfJLaHEih6D4sTNjduMNhXJEIlU/HHzp/LgV6FL6qj6j -ITk1dImmasI5+njPtqzn59ZW/yOSLlALqbUHM/Q4X6RJpstlcHboCoWASzY9M/eV -VHUl2qzEc4Jl6VL1XP04lQJqaTDFHApXB64ipCz5xUG3uOyfT0gA+QEEVcys+TIx -xHWVBqB/0Y0n3bOppHKH/lmLmnp0Ft0WpWIp6zqW3IunaFnT63eROfjXy9mPX1on -AX1daBli2MjN9LdyR75bl87yraKZk62Uy5P2EgmVtqvXO9A/EcswFi55gORngS1d -7XB4tmBZrOFdRWOPyN9yaFvqHbgB8X7754qz41SgOAngPN5C8sLtLpvzHzW2Ntjj -gKGLzZlkD8Kqq7HK9W+eQ42EVJmzbsASZthwEPEGNTNDqJwuuhQxzhB/HIbjj9LV -+Hfsm6vxL2PZQl/gZ4FkkfGXL/xuJvYz+NO1+MRiqzFRJQJ6+N1rZdVtTTDIZbpo -FGWsJwt0ivKH ------END CERTIFICATE----- - -# Issuer: CN=TrustAsia Global Root CA G4 O=TrustAsia Technologies, Inc. -# Subject: CN=TrustAsia Global Root CA G4 O=TrustAsia Technologies, Inc. -# Label: "TrustAsia Global Root CA G4" -# Serial: 451799571007117016466790293371524403291602933463 -# MD5 Fingerprint: 54:dd:b2:d7:5f:d8:3e:ed:7c:e0:0b:2e:cc:ed:eb:eb -# SHA1 Fingerprint: 57:73:a5:61:5d:80:b2:e6:ac:38:82:fc:68:07:31:ac:9f:b5:92:5a -# SHA256 Fingerprint: be:4b:56:cb:50:56:c0:13:6a:52:6d:f4:44:50:8d:aa:36:a0:b5:4f:42:e4:ac:38:f7:2a:f4:70:e4:79:65:4c ------BEGIN CERTIFICATE----- -MIICVTCCAdygAwIBAgIUTyNkuI6XY57GU4HBdk7LKnQV1tcwCgYIKoZIzj0EAwMw -WjELMAkGA1UEBhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dpZXMs -IEluYy4xJDAiBgNVBAMMG1RydXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHNDAeFw0y -MTA1MjAwMjEwMjJaFw00NjA1MTkwMjEwMjJaMFoxCzAJBgNVBAYTAkNOMSUwIwYD -VQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSQwIgYDVQQDDBtUcnVz -dEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATx -s8045CVD5d4ZCbuBeaIVXxVjAd7Cq92zphtnS4CDr5nLrBfbK5bKfFJV4hrhPVbw -LxYI+hW8m7tH5j/uqOFMjPXTNvk4XatwmkcN4oFBButJ+bAp3TPsUKV/eSm4IJij -YzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUpbtKl86zK3+kMd6Xg1mD -pm9xy94wHQYDVR0OBBYEFKW7SpfOsyt/pDHel4NZg6ZvccveMA4GA1UdDwEB/wQE -AwIBBjAKBggqhkjOPQQDAwNnADBkAjBe8usGzEkxn0AAbbd+NvBNEU/zy4k6LHiR -UKNbwMp1JvK/kF0LgoxgKJ/GcJpo5PECMFxYDlZ2z1jD1xCMuo6u47xkdUfFVZDj -/bpV6wfEU6s3qe4hsiFbYI89MvHVI5TWWA== ------END CERTIFICATE----- - -# Issuer: CN=CommScope Public Trust ECC Root-01 O=CommScope -# Subject: CN=CommScope Public Trust ECC Root-01 O=CommScope -# Label: "CommScope Public Trust ECC Root-01" -# Serial: 385011430473757362783587124273108818652468453534 -# MD5 Fingerprint: 3a:40:a7:fc:03:8c:9c:38:79:2f:3a:a2:6c:b6:0a:16 -# SHA1 Fingerprint: 07:86:c0:d8:dd:8e:c0:80:98:06:98:d0:58:7a:ef:de:a6:cc:a2:5d -# SHA256 Fingerprint: 11:43:7c:da:7b:b4:5e:41:36:5f:45:b3:9a:38:98:6b:0d:e0:0d:ef:34:8e:0c:7b:b0:87:36:33:80:0b:c3:8b ------BEGIN CERTIFICATE----- -MIICHTCCAaOgAwIBAgIUQ3CCd89NXTTxyq4yLzf39H91oJ4wCgYIKoZIzj0EAwMw -TjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29t -bVNjb3BlIFB1YmxpYyBUcnVzdCBFQ0MgUm9vdC0wMTAeFw0yMTA0MjgxNzM1NDNa -Fw00NjA0MjgxNzM1NDJaME4xCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlDb21tU2Nv -cGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3QgRUNDIFJvb3QtMDEw -djAQBgcqhkjOPQIBBgUrgQQAIgNiAARLNumuV16ocNfQj3Rid8NeeqrltqLxeP0C -flfdkXmcbLlSiFS8LwS+uM32ENEp7LXQoMPwiXAZu1FlxUOcw5tjnSCDPgYLpkJE -hRGnSjot6dZoL0hOUysHP029uax3OVejQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD -VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSOB2LAUN3GGQYARnQE9/OufXVNMDAKBggq -hkjOPQQDAwNoADBlAjEAnDPfQeMjqEI2Jpc1XHvr20v4qotzVRVcrHgpD7oh2MSg -2NED3W3ROT3Ek2DS43KyAjB8xX6I01D1HiXo+k515liWpDVfG2XqYZpwI7UNo5uS -Um9poIyNStDuiw7LR47QjRE= ------END CERTIFICATE----- - -# Issuer: CN=CommScope Public Trust ECC Root-02 O=CommScope -# Subject: CN=CommScope Public Trust ECC Root-02 O=CommScope -# Label: "CommScope Public Trust ECC Root-02" -# Serial: 234015080301808452132356021271193974922492992893 -# MD5 Fingerprint: 59:b0:44:d5:65:4d:b8:5c:55:19:92:02:b6:d1:94:b2 -# SHA1 Fingerprint: 3c:3f:ef:57:0f:fe:65:93:86:9e:a0:fe:b0:f6:ed:8e:d1:13:c7:e5 -# SHA256 Fingerprint: 2f:fb:7f:81:3b:bb:b3:c8:9a:b4:e8:16:2d:0f:16:d7:15:09:a8:30:cc:9d:73:c2:62:e5:14:08:75:d1:ad:4a ------BEGIN CERTIFICATE----- -MIICHDCCAaOgAwIBAgIUKP2ZYEFHpgE6yhR7H+/5aAiDXX0wCgYIKoZIzj0EAwMw -TjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29t -bVNjb3BlIFB1YmxpYyBUcnVzdCBFQ0MgUm9vdC0wMjAeFw0yMTA0MjgxNzQ0NTRa -Fw00NjA0MjgxNzQ0NTNaME4xCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlDb21tU2Nv -cGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3QgRUNDIFJvb3QtMDIw -djAQBgcqhkjOPQIBBgUrgQQAIgNiAAR4MIHoYx7l63FRD/cHB8o5mXxO1Q/MMDAL -j2aTPs+9xYa9+bG3tD60B8jzljHz7aRP+KNOjSkVWLjVb3/ubCK1sK9IRQq9qEmU -v4RDsNuESgMjGWdqb8FuvAY5N9GIIvejQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD -VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTmGHX/72DehKT1RsfeSlXjMjZ59TAKBggq -hkjOPQQDAwNnADBkAjAmc0l6tqvmSfR9Uj/UQQSugEODZXW5hYA4O9Zv5JOGq4/n -ich/m35rChJVYaoR4HkCMHfoMXGsPHED1oQmHhS48zs73u1Z/GtMMH9ZzkXpc2AV -mkzw5l4lIhVtwodZ0LKOag== ------END CERTIFICATE----- - -# Issuer: CN=CommScope Public Trust RSA Root-01 O=CommScope -# Subject: CN=CommScope Public Trust RSA Root-01 O=CommScope -# Label: "CommScope Public Trust RSA Root-01" -# Serial: 354030733275608256394402989253558293562031411421 -# MD5 Fingerprint: 0e:b4:15:bc:87:63:5d:5d:02:73:d4:26:38:68:73:d8 -# SHA1 Fingerprint: 6d:0a:5f:f7:b4:23:06:b4:85:b3:b7:97:64:fc:ac:75:f5:33:f2:93 -# SHA256 Fingerprint: 02:bd:f9:6e:2a:45:dd:9b:f1:8f:c7:e1:db:df:21:a0:37:9b:a3:c9:c2:61:03:44:cf:d8:d6:06:fe:c1:ed:81 ------BEGIN CERTIFICATE----- -MIIFbDCCA1SgAwIBAgIUPgNJgXUWdDGOTKvVxZAplsU5EN0wDQYJKoZIhvcNAQEL -BQAwTjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwi -Q29tbVNjb3BlIFB1YmxpYyBUcnVzdCBSU0EgUm9vdC0wMTAeFw0yMTA0MjgxNjQ1 -NTRaFw00NjA0MjgxNjQ1NTNaME4xCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlDb21t -U2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3QgUlNBIFJvb3Qt -MDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwSGWjDR1C45FtnYSk -YZYSwu3D2iM0GXb26v1VWvZVAVMP8syMl0+5UMuzAURWlv2bKOx7dAvnQmtVzslh -suitQDy6uUEKBU8bJoWPQ7VAtYXR1HHcg0Hz9kXHgKKEUJdGzqAMxGBWBB0HW0al -DrJLpA6lfO741GIDuZNqihS4cPgugkY4Iw50x2tBt9Apo52AsH53k2NC+zSDO3Oj -WiE260f6GBfZumbCk6SP/F2krfxQapWsvCQz0b2If4b19bJzKo98rwjyGpg/qYFl -P8GMicWWMJoKz/TUyDTtnS+8jTiGU+6Xn6myY5QXjQ/cZip8UlF1y5mO6D1cv547 -KI2DAg+pn3LiLCuz3GaXAEDQpFSOm117RTYm1nJD68/A6g3czhLmfTifBSeolz7p -UcZsBSjBAg/pGG3svZwG1KdJ9FQFa2ww8esD1eo9anbCyxooSU1/ZOD6K9pzg4H/ -kQO9lLvkuI6cMmPNn7togbGEW682v3fuHX/3SZtS7NJ3Wn2RnU3COS3kuoL4b/JO -Hg9O5j9ZpSPcPYeoKFgo0fEbNttPxP/hjFtyjMcmAyejOQoBqsCyMWCDIqFPEgkB -Ea801M/XrmLTBQe0MXXgDW1XT2mH+VepuhX2yFJtocucH+X8eKg1mp9BFM6ltM6U -CBwJrVbl2rZJmkrqYxhTnCwuwwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G -A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUN12mmnQywsL5x6YVEFm45P3luG0wDQYJ -KoZIhvcNAQELBQADggIBAK+nz97/4L1CjU3lIpbfaOp9TSp90K09FlxD533Ahuh6 -NWPxzIHIxgvoLlI1pKZJkGNRrDSsBTtXAOnTYtPZKdVUvhwQkZyybf5Z/Xn36lbQ -nmhUQo8mUuJM3y+Xpi/SB5io82BdS5pYV4jvguX6r2yBS5KPQJqTRlnLX3gWsWc+ -QgvfKNmwrZggvkN80V4aCRckjXtdlemrwWCrWxhkgPut4AZ9HcpZuPN4KWfGVh2v -trV0KnahP/t1MJ+UXjulYPPLXAziDslg+MkfFoom3ecnf+slpoq9uC02EJqxWE2a -aE9gVOX2RhOOiKy8IUISrcZKiX2bwdgt6ZYD9KJ0DLwAHb/WNyVntHKLr4W96ioD -j8z7PEQkguIBpQtZtjSNMgsSDesnwv1B10A8ckYpwIzqug/xBpMu95yo9GA+o/E4 -Xo4TwbM6l4c/ksp4qRyv0LAbJh6+cOx69TOY6lz/KwsETkPdY34Op054A5U+1C0w -lREQKC6/oAI+/15Z0wUOlV9TRe9rh9VIzRamloPh37MG88EU26fsHItdkJANclHn -YfkUyq+Dj7+vsQpZXdxc1+SWrVtgHdqul7I52Qb1dgAT+GhMIbA1xNxVssnBQVoc -icCMb3SgazNNtQEo/a2tiRc7ppqEvOuM6sRxJKi6KfkIsidWNTJf6jn7MZrVGczw ------END CERTIFICATE----- - -# Issuer: CN=CommScope Public Trust RSA Root-02 O=CommScope -# Subject: CN=CommScope Public Trust RSA Root-02 O=CommScope -# Label: "CommScope Public Trust RSA Root-02" -# Serial: 480062499834624527752716769107743131258796508494 -# MD5 Fingerprint: e1:29:f9:62:7b:76:e2:96:6d:f3:d4:d7:0f:ae:1f:aa -# SHA1 Fingerprint: ea:b0:e2:52:1b:89:93:4c:11:68:f2:d8:9a:ac:22:4c:a3:8a:57:ae -# SHA256 Fingerprint: ff:e9:43:d7:93:42:4b:4f:7c:44:0c:1c:3d:64:8d:53:63:f3:4b:82:dc:87:aa:7a:9f:11:8f:c5:de:e1:01:f1 ------BEGIN CERTIFICATE----- -MIIFbDCCA1SgAwIBAgIUVBa/O345lXGN0aoApYYNK496BU4wDQYJKoZIhvcNAQEL -BQAwTjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwi -Q29tbVNjb3BlIFB1YmxpYyBUcnVzdCBSU0EgUm9vdC0wMjAeFw0yMTA0MjgxNzE2 -NDNaFw00NjA0MjgxNzE2NDJaME4xCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlDb21t -U2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3QgUlNBIFJvb3Qt -MDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDh+g77aAASyE3VrCLE -NQE7xVTlWXZjpX/rwcRqmL0yjReA61260WI9JSMZNRTpf4mnG2I81lDnNJUDMrG0 -kyI9p+Kx7eZ7Ti6Hmw0zdQreqjXnfuU2mKKuJZ6VszKWpCtYHu8//mI0SFHRtI1C -rWDaSWqVcN3SAOLMV2MCe5bdSZdbkk6V0/nLKR8YSvgBKtJjCW4k6YnS5cciTNxz -hkcAqg2Ijq6FfUrpuzNPDlJwnZXjfG2WWy09X6GDRl224yW4fKcZgBzqZUPckXk2 -LHR88mcGyYnJ27/aaL8j7dxrrSiDeS/sOKUNNwFnJ5rpM9kzXzehxfCrPfp4sOcs -n/Y+n2Dg70jpkEUeBVF4GiwSLFworA2iI540jwXmojPOEXcT1A6kHkIfhs1w/tku -FT0du7jyU1fbzMZ0KZwYszZ1OC4PVKH4kh+Jlk+71O6d6Ts2QrUKOyrUZHk2EOH5 -kQMreyBUzQ0ZGshBMjTRsJnhkB4BQDa1t/qp5Xd1pCKBXbCL5CcSD1SIxtuFdOa3 -wNemKfrb3vOTlycEVS8KbzfFPROvCgCpLIscgSjX74Yxqa7ybrjKaixUR9gqiC6v -wQcQeKwRoi9C8DfF8rhW3Q5iLc4tVn5V8qdE9isy9COoR+jUKgF4z2rDN6ieZdIs -5fq6M8EGRPbmz6UNp2YINIos8wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G -A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUR9DnsSL/nSz12Vdgs7GxcJXvYXowDQYJ -KoZIhvcNAQELBQADggIBAIZpsU0v6Z9PIpNojuQhmaPORVMbc0RTAIFhzTHjCLqB -KCh6krm2qMhDnscTJk3C2OVVnJJdUNjCK9v+5qiXz1I6JMNlZFxHMaNlNRPDk7n3 -+VGXu6TwYofF1gbTl4MgqX67tiHCpQ2EAOHyJxCDut0DgdXdaMNmEMjRdrSzbyme -APnCKfWxkxlSaRosTKCL4BWaMS/TiJVZbuXEs1DIFAhKm4sTg7GkcrI7djNB3Nyq -pgdvHSQSn8h2vS/ZjvQs7rfSOBAkNlEv41xdgSGn2rtO/+YHqP65DSdsu3BaVXoT -6fEqSWnHX4dXTEN5bTpl6TBcQe7rd6VzEojov32u5cSoHw2OHG1QAk8mGEPej1WF -sQs3BWDJVTkSBKEqz3EWnzZRSb9wO55nnPt7eck5HHisd5FUmrh1CoFSl+NmYWvt -PjgelmFV4ZFUjO2MJB+ByRCac5krFk5yAD9UG/iNuovnFNa2RU9g7Jauwy8CTl2d -lklyALKrdVwPaFsdZcJfMw8eD/A7hvWwTruc9+olBdytoptLFwG+Qt81IR2tq670 -v64fG9PiO/yzcnMcmyiQiRM9HcEARwmWmjgb3bHPDcK0RPOWlc4yOo80nOAXx17O -rg3bhzjlP1v9mxnhMUF6cKojawHhRUzNlM47ni3niAIi9G7oyOzWPPO5std3eqx7 ------END CERTIFICATE----- - -# Issuer: CN=Telekom Security TLS ECC Root 2020 O=Deutsche Telekom Security GmbH -# Subject: CN=Telekom Security TLS ECC Root 2020 O=Deutsche Telekom Security GmbH -# Label: "Telekom Security TLS ECC Root 2020" -# Serial: 72082518505882327255703894282316633856 -# MD5 Fingerprint: c1:ab:fe:6a:10:2c:03:8d:bc:1c:22:32:c0:85:a7:fd -# SHA1 Fingerprint: c0:f8:96:c5:a9:3b:01:06:21:07:da:18:42:48:bc:e9:9d:88:d5:ec -# SHA256 Fingerprint: 57:8a:f4:de:d0:85:3f:4e:59:98:db:4a:ea:f9:cb:ea:8d:94:5f:60:b6:20:a3:8d:1a:3c:13:b2:bc:7b:a8:e1 ------BEGIN CERTIFICATE----- -MIICQjCCAcmgAwIBAgIQNjqWjMlcsljN0AFdxeVXADAKBggqhkjOPQQDAzBjMQsw -CQYDVQQGEwJERTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0eSBH -bWJIMSswKQYDVQQDDCJUZWxla29tIFNlY3VyaXR5IFRMUyBFQ0MgUm9vdCAyMDIw -MB4XDTIwMDgyNTA3NDgyMFoXDTQ1MDgyNTIzNTk1OVowYzELMAkGA1UEBhMCREUx -JzAlBgNVBAoMHkRldXRzY2hlIFRlbGVrb20gU2VjdXJpdHkgR21iSDErMCkGA1UE -AwwiVGVsZWtvbSBTZWN1cml0eSBUTFMgRUNDIFJvb3QgMjAyMDB2MBAGByqGSM49 -AgEGBSuBBAAiA2IABM6//leov9Wq9xCazbzREaK9Z0LMkOsVGJDZos0MKiXrPk/O -tdKPD/M12kOLAoC+b1EkHQ9rK8qfwm9QMuU3ILYg/4gND21Ju9sGpIeQkpT0CdDP -f8iAC8GXs7s1J8nCG6NCMEAwHQYDVR0OBBYEFONyzG6VmUex5rNhTNHLq+O6zd6f -MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2cA -MGQCMHVSi7ekEE+uShCLsoRbQuHmKjYC2qBuGT8lv9pZMo7k+5Dck2TOrbRBR2Di -z6fLHgIwN0GMZt9Ba9aDAEH9L1r3ULRn0SyocddDypwnJJGDSA3PzfdUga/sf+Rn -27iQ7t0l ------END CERTIFICATE----- - -# Issuer: CN=Telekom Security TLS RSA Root 2023 O=Deutsche Telekom Security GmbH -# Subject: CN=Telekom Security TLS RSA Root 2023 O=Deutsche Telekom Security GmbH -# Label: "Telekom Security TLS RSA Root 2023" -# Serial: 44676229530606711399881795178081572759 -# MD5 Fingerprint: bf:5b:eb:54:40:cd:48:71:c4:20:8d:7d:de:0a:42:f2 -# SHA1 Fingerprint: 54:d3:ac:b3:bd:57:56:f6:85:9d:ce:e5:c3:21:e2:d4:ad:83:d0:93 -# SHA256 Fingerprint: ef:c6:5c:ad:bb:59:ad:b6:ef:e8:4d:a2:23:11:b3:56:24:b7:1b:3b:1e:a0:da:8b:66:55:17:4e:c8:97:86:46 ------BEGIN CERTIFICATE----- -MIIFszCCA5ugAwIBAgIQIZxULej27HF3+k7ow3BXlzANBgkqhkiG9w0BAQwFADBj -MQswCQYDVQQGEwJERTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0 -eSBHbWJIMSswKQYDVQQDDCJUZWxla29tIFNlY3VyaXR5IFRMUyBSU0EgUm9vdCAy -MDIzMB4XDTIzMDMyODEyMTY0NVoXDTQ4MDMyNzIzNTk1OVowYzELMAkGA1UEBhMC -REUxJzAlBgNVBAoMHkRldXRzY2hlIFRlbGVrb20gU2VjdXJpdHkgR21iSDErMCkG -A1UEAwwiVGVsZWtvbSBTZWN1cml0eSBUTFMgUlNBIFJvb3QgMjAyMzCCAiIwDQYJ -KoZIhvcNAQEBBQADggIPADCCAgoCggIBAO01oYGA88tKaVvC+1GDrib94W7zgRJ9 -cUD/h3VCKSHtgVIs3xLBGYSJwb3FKNXVS2xE1kzbB5ZKVXrKNoIENqil/Cf2SfHV -cp6R+SPWcHu79ZvB7JPPGeplfohwoHP89v+1VmLhc2o0mD6CuKyVU/QBoCcHcqMA -U6DksquDOFczJZSfvkgdmOGjup5czQRxUX11eKvzWarE4GC+j4NSuHUaQTXtvPM6 -Y+mpFEXX5lLRbtLevOP1Czvm4MS9Q2QTps70mDdsipWol8hHD/BeEIvnHRz+sTug -BTNoBUGCwQMrAcjnj02r6LX2zWtEtefdi+zqJbQAIldNsLGyMcEWzv/9FIS3R/qy -8XDe24tsNlikfLMR0cN3f1+2JeANxdKz+bi4d9s3cXFH42AYTyS2dTd4uaNir73J -co4vzLuu2+QVUhkHM/tqty1LkCiCc/4YizWN26cEar7qwU02OxY2kTLvtkCJkUPg -8qKrBC7m8kwOFjQgrIfBLX7JZkcXFBGk8/ehJImr2BrIoVyxo/eMbcgByU/J7MT8 -rFEz0ciD0cmfHdRHNCk+y7AO+oMLKFjlKdw/fKifybYKu6boRhYPluV75Gp6SG12 -mAWl3G0eQh5C2hrgUve1g8Aae3g1LDj1H/1Joy7SWWO/gLCMk3PLNaaZlSJhZQNg -+y+TS/qanIA7AgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtqeX -gj10hZv3PJ+TmpV5dVKMbUcwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS2 -p5eCPXSFm/c8n5OalXl1UoxtRzANBgkqhkiG9w0BAQwFAAOCAgEAqMxhpr51nhVQ -pGv7qHBFfLp+sVr8WyP6Cnf4mHGCDG3gXkaqk/QeoMPhk9tLrbKmXauw1GLLXrtm -9S3ul0A8Yute1hTWjOKWi0FpkzXmuZlrYrShF2Y0pmtjxrlO8iLpWA1WQdH6DErw -M807u20hOq6OcrXDSvvpfeWxm4bu4uB9tPcy/SKE8YXJN3nptT+/XOR0so8RYgDd -GGah2XsjX/GO1WfoVNpbOms2b/mBsTNHM3dA+VKq3dSDz4V4mZqTuXNnQkYRIer+ -CqkbGmVps4+uFrb2S1ayLfmlyOw7YqPta9BO1UAJpB+Y1zqlklkg5LB9zVtzaL1t -xKITDmcZuI1CfmwMmm6gJC3VRRvcxAIU/oVbZZfKTpBQCHpCNfnqwmbU+AGuHrS+ -w6jv/naaoqYfRvaE7fzbzsQCzndILIyy7MMAo+wsVRjBfhnu4S/yrYObnqsZ38aK -L4x35bcF7DvB7L6Gs4a8wPfc5+pbrrLMtTWGS9DiP7bY+A4A7l3j941Y/8+LN+lj -X273CXE2whJdV/LItM3z7gLfEdxquVeEHVlNjM7IDiPCtyaaEBRx/pOyiriA8A4Q -ntOoUAw3gi/q4Iqd4Sw5/7W0cwDk90imc6y/st53BIe0o82bNSQ3+pCTE4FCxpgm -dTdmQRCsu/WU48IxK63nI1bMNSWSs1A= ------END CERTIFICATE----- - -# Issuer: CN=FIRMAPROFESIONAL CA ROOT-A WEB O=Firmaprofesional SA -# Subject: CN=FIRMAPROFESIONAL CA ROOT-A WEB O=Firmaprofesional SA -# Label: "FIRMAPROFESIONAL CA ROOT-A WEB" -# Serial: 65916896770016886708751106294915943533 -# MD5 Fingerprint: 82:b2:ad:45:00:82:b0:66:63:f8:5f:c3:67:4e:ce:a3 -# SHA1 Fingerprint: a8:31:11:74:a6:14:15:0d:ca:77:dd:0e:e4:0c:5d:58:fc:a0:72:a5 -# SHA256 Fingerprint: be:f2:56:da:f2:6e:9c:69:bd:ec:16:02:35:97:98:f3:ca:f7:18:21:a0:3e:01:82:57:c5:3c:65:61:7f:3d:4a ------BEGIN CERTIFICATE----- -MIICejCCAgCgAwIBAgIQMZch7a+JQn81QYehZ1ZMbTAKBggqhkjOPQQDAzBuMQsw -CQYDVQQGEwJFUzEcMBoGA1UECgwTRmlybWFwcm9mZXNpb25hbCBTQTEYMBYGA1UE -YQwPVkFURVMtQTYyNjM0MDY4MScwJQYDVQQDDB5GSVJNQVBST0ZFU0lPTkFMIENB -IFJPT1QtQSBXRUIwHhcNMjIwNDA2MDkwMTM2WhcNNDcwMzMxMDkwMTM2WjBuMQsw -CQYDVQQGEwJFUzEcMBoGA1UECgwTRmlybWFwcm9mZXNpb25hbCBTQTEYMBYGA1UE -YQwPVkFURVMtQTYyNjM0MDY4MScwJQYDVQQDDB5GSVJNQVBST0ZFU0lPTkFMIENB -IFJPT1QtQSBXRUIwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARHU+osEaR3xyrq89Zf -e9MEkVz6iMYiuYMQYneEMy3pA4jU4DP37XcsSmDq5G+tbbT4TIqk5B/K6k84Si6C -cyvHZpsKjECcfIr28jlgst7L7Ljkb+qbXbdTkBgyVcUgt5SjYzBhMA8GA1UdEwEB -/wQFMAMBAf8wHwYDVR0jBBgwFoAUk+FDY1w8ndYn81LsF7Kpryz3dvgwHQYDVR0O -BBYEFJPhQ2NcPJ3WJ/NS7Beyqa8s93b4MA4GA1UdDwEB/wQEAwIBBjAKBggqhkjO -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----- - -# Issuer: CN=D-TRUST BR Root CA 2 2023 O=D-Trust GmbH -# Subject: CN=D-TRUST BR Root CA 2 2023 O=D-Trust GmbH -# Label: "D-TRUST BR Root CA 2 2023" -# Serial: 153168538924886464690566649552453098598 -# MD5 Fingerprint: e1:09:ed:d3:60:d4:56:1b:47:1f:b7:0c:5f:1b:5f:85 -# SHA1 Fingerprint: 2d:b0:70:ee:71:94:af:69:68:17:db:79:ce:58:9f:a0:6b:96:f7:87 -# SHA256 Fingerprint: 05:52:e6:f8:3f:df:65:e8:fa:96:70:e6:66:df:28:a4:e2:13:40:b5:10:cb:e5:25:66:f9:7c:4f:b9:4b:2b:d1 ------BEGIN CERTIFICATE----- -MIIFqTCCA5GgAwIBAgIQczswBEhb2U14LnNLyaHcZjANBgkqhkiG9w0BAQ0FADBI -MQswCQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlE -LVRSVVNUIEJSIFJvb3QgQ0EgMiAyMDIzMB4XDTIzMDUwOTA4NTYzMVoXDTM4MDUw -OTA4NTYzMFowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEi -MCAGA1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDIgMjAyMzCCAiIwDQYJKoZIhvcN -AQEBBQADggIPADCCAgoCggIBAK7/CVmRgApKaOYkP7in5Mg6CjoWzckjYaCTcfKr -i3OPoGdlYNJUa2NRb0kz4HIHE304zQaSBylSa053bATTlfrdTIzZXcFhfUvnKLNE -gXtRr90zsWh81k5M/itoucpmacTsXld/9w3HnDY25QdgrMBM6ghs7wZ8T1soegj8 -k12b9py0i4a6Ibn08OhZWiihNIQaJZG2tY/vsvmA+vk9PBFy2OMvhnbFeSzBqZCT -Rphny4NqoFAjpzv2gTng7fC5v2Xx2Mt6++9zA84A9H3X4F07ZrjcjrqDy4d2A/wl -2ecjbwb9Z/Pg/4S8R7+1FhhGaRTMBffb00msa8yr5LULQyReS2tNZ9/WtT5PeB+U -cSTq3nD88ZP+npNa5JRal1QMNXtfbO4AHyTsA7oC9Xb0n9Sa7YUsOCIvx9gvdhFP -/Wxc6PWOJ4d/GUohR5AdeY0cW/jPSoXk7bNbjb7EZChdQcRurDhaTyN0dKkSw/bS -uREVMweR2Ds3OmMwBtHFIjYoYiMQ4EbMl6zWK11kJNXuHA7e+whadSr2Y23OC0K+ -0bpwHJwh5Q8xaRfX/Aq03u2AnMuStIv13lmiWAmlY0cL4UEyNEHZmrHZqLAbWt4N -DfTisl01gLmB1IRpkQLLddCNxbU9CZEJjxShFHR5PtbJFR2kWVki3PaKRT08EtY+ -XTIvAgMBAAGjgY4wgYswDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUZ5Dw1t61 -GNVGKX5cq/ieCLxklRAwDgYDVR0PAQH/BAQDAgEGMEkGA1UdHwRCMEAwPqA8oDqG -OGh0dHA6Ly9jcmwuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3RfYnJfcm9vdF9jYV8y -XzIwMjMuY3JsMA0GCSqGSIb3DQEBDQUAA4ICAQA097N3U9swFrktpSHxQCF16+tI -FoE9c+CeJyrrd6kTpGoKWloUMz1oH4Guaf2Mn2VsNELZLdB/eBaxOqwjMa1ef67n -riv6uvw8l5VAk1/DLQOj7aRvU9f6QA4w9QAgLABMjDu0ox+2v5Eyq6+SmNMW5tTR -VFxDWy6u71cqqLRvpO8NVhTaIasgdp4D/Ca4nj8+AybmTNudX0KEPUUDAxxZiMrc -LmEkWqTqJwtzEr5SswrPMhfiHocaFpVIbVrg0M8JkiZmkdijYQ6qgYF/6FKC0ULn -4B0Y+qSFNueG4A3rvNTJ1jxD8V1Jbn6Bm2m1iWKPiFLY1/4nwSPFyysCu7Ff/vtD -hQNGvl3GyiEm/9cCnnRK3PgTFbGBVzbLZVzRHTF36SXDw7IyN9XxmAnkbWOACKsG -koHU6XCPpz+y7YaMgmo1yEJagtFSGkUPFaUA8JR7ZSdXOUPPfH/mvTWze/EZTN46 -ls/pdu4D58JDUjxqgejBWoC9EV2Ta/vH5mQ/u2kc6d0li690yVRAysuTEwrt+2aS -Ecr1wPrYg1UDfNPFIkZ1cGt5SAYqgpq/5usWDiJFAbzdNpQ0qTUmiteXue4Icr80 -knCDgKs4qllo3UCkGJCy89UDyibK79XH4I9TjvAA46jtn/mtd+ArY0+ew+43u3gJ -hJ65bvspmZDogNOfJA== ------END CERTIFICATE----- - -# Issuer: CN=TrustAsia TLS ECC Root CA O=TrustAsia Technologies, Inc. -# Subject: CN=TrustAsia TLS ECC Root CA O=TrustAsia Technologies, Inc. -# Label: "TrustAsia TLS ECC Root CA" -# Serial: 310892014698942880364840003424242768478804666567 -# MD5 Fingerprint: 09:48:04:77:d2:fc:65:93:71:66:b1:11:95:4f:06:8c -# SHA1 Fingerprint: b5:ec:39:f3:a1:66:37:ae:c3:05:94:57:e2:be:11:be:b7:a1:7f:36 -# SHA256 Fingerprint: c0:07:6b:9e:f0:53:1f:b1:a6:56:d6:7c:4e:be:97:cd:5d:ba:a4:1e:f4:45:98:ac:c2:48:98:78:c9:2d:87:11 ------BEGIN CERTIFICATE----- -MIICMTCCAbegAwIBAgIUNnThTXxlE8msg1UloD5Sfi9QaMcwCgYIKoZIzj0EAwMw -WDELMAkGA1UEBhMCQ04xJTAjBgNVBAoTHFRydXN0QXNpYSBUZWNobm9sb2dpZXMs -IEluYy4xIjAgBgNVBAMTGVRydXN0QXNpYSBUTFMgRUNDIFJvb3QgQ0EwHhcNMjQw -NTE1MDU0MTU2WhcNNDQwNTE1MDU0MTU1WjBYMQswCQYDVQQGEwJDTjElMCMGA1UE -ChMcVHJ1c3RBc2lhIFRlY2hub2xvZ2llcywgSW5jLjEiMCAGA1UEAxMZVHJ1c3RB -c2lhIFRMUyBFQ0MgUm9vdCBDQTB2MBAGByqGSM49AgEGBSuBBAAiA2IABLh/pVs/ -AT598IhtrimY4ZtcU5nb9wj/1WrgjstEpvDBjL1P1M7UiFPoXlfXTr4sP/MSpwDp -guMqWzJ8S5sUKZ74LYO1644xST0mYekdcouJtgq7nDM1D9rs3qlKH8kzsaNCMEAw -DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQULIVTu7FDzTLqnqOH/qKYqKaT6RAw -DgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2gAMGUCMFRH18MtYYZI9HlaVQ01 -L18N9mdsd0AaRuf4aFtOJx24mH1/k78ITcTaRTChD15KeAIxAKORh/IRM4PDwYqR -OkwrULG9IpRdNYlzg8WbGf60oenUoWa2AaU2+dhoYSi3dOGiMQ== ------END CERTIFICATE----- - -# Issuer: CN=TrustAsia TLS RSA Root CA O=TrustAsia Technologies, Inc. -# Subject: CN=TrustAsia TLS RSA Root CA O=TrustAsia Technologies, Inc. -# Label: "TrustAsia TLS RSA Root CA" -# Serial: 160405846464868906657516898462547310235378010780 -# MD5 Fingerprint: 3b:9e:c3:86:0f:34:3c:6b:c5:46:c4:8e:1d:e7:19:12 -# SHA1 Fingerprint: a5:46:50:c5:62:ea:95:9a:1a:a7:04:6f:17:58:c7:29:53:3d:03:fa -# SHA256 Fingerprint: 06:c0:8d:7d:af:d8:76:97:1e:b1:12:4f:e6:7f:84:7e:c0:c7:a1:58:d3:ea:53:cb:e9:40:e2:ea:97:91:f4:c3 ------BEGIN CERTIFICATE----- -MIIFgDCCA2igAwIBAgIUHBjYz+VTPyI1RlNUJDxsR9FcSpwwDQYJKoZIhvcNAQEM -BQAwWDELMAkGA1UEBhMCQ04xJTAjBgNVBAoTHFRydXN0QXNpYSBUZWNobm9sb2dp -ZXMsIEluYy4xIjAgBgNVBAMTGVRydXN0QXNpYSBUTFMgUlNBIFJvb3QgQ0EwHhcN -MjQwNTE1MDU0MTU3WhcNNDQwNTE1MDU0MTU2WjBYMQswCQYDVQQGEwJDTjElMCMG -A1UEChMcVHJ1c3RBc2lhIFRlY2hub2xvZ2llcywgSW5jLjEiMCAGA1UEAxMZVHJ1 -c3RBc2lhIFRMUyBSU0EgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC -AgoCggIBAMMWuBtqpERz5dZO9LnPWwvB0ZqB9WOwj0PBuwhaGnrhB3YmH49pVr7+ -NmDQDIPNlOrnxS1cLwUWAp4KqC/lYCZUlviYQB2srp10Zy9U+5RjmOMmSoPGlbYJ -Q1DNDX3eRA5gEk9bNb2/mThtfWza4mhzH/kxpRkQcwUqwzIZheo0qt1CHjCNP561 -HmHVb70AcnKtEj+qpklz8oYVlQwQX1Fkzv93uMltrOXVmPGZLmzjyUT5tUMnCE32 -ft5EebuyjBza00tsLtbDeLdM1aTk2tyKjg7/D8OmYCYozza/+lcK7Fs/6TAWe8Tb -xNRkoDD75f0dcZLdKY9BWN4ArTr9PXwaqLEX8E40eFgl1oUh63kd0Nyrz2I8sMeX -i9bQn9P+PN7F4/w6g3CEIR0JwqH8uyghZVNgepBtljhb//HXeltt08lwSUq6HTrQ -UNoyIBnkiz/r1RYmNzz7dZ6wB3C4FGB33PYPXFIKvF1tjVEK2sUYyJtt3LCDs3+j -TnhMmCWr8n4uIF6CFabW2I+s5c0yhsj55NqJ4js+k8UTav/H9xj8Z7XvGCxUq0DT -bE3txci3OE9kxJRMT6DNrqXGJyV1J23G2pyOsAWZ1SgRxSHUuPzHlqtKZFlhaxP8 -S8ySpg+kUb8OWJDZgoM5pl+z+m6Ss80zDoWo8SnTq1mt1tve1CuBAgMBAAGjQjBA -MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFLgHkXlcBvRG/XtZylomkadFK/hT -MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQwFAAOCAgEAIZtqBSBdGBanEqT3 -Rz/NyjuujsCCztxIJXgXbODgcMTWltnZ9r96nBO7U5WS/8+S4PPFJzVXqDuiGev4 -iqME3mmL5Dw8veWv0BIb5Ylrc5tvJQJLkIKvQMKtuppgJFqBTQUYo+IzeXoLH5Pt -7DlK9RME7I10nYEKqG/odv6LTytpEoYKNDbdgptvT+Bz3Ul/KD7JO6NXBNiT2Twp -2xIQaOHEibgGIOcberyxk2GaGUARtWqFVwHxtlotJnMnlvm5P1vQiJ3koP26TpUJ -g3933FEFlJ0gcXax7PqJtZwuhfG5WyRasQmr2soaB82G39tp27RIGAAtvKLEiUUj -pQ7hRGU+isFqMB3iYPg6qocJQrmBktwliJiJ8Xw18WLK7nn4GS/+X/jbh87qqA8M -pugLoDzga5SYnH+tBuYc6kIQX+ImFTw3OffXvO645e8D7r0i+yiGNFjEWn9hongP -XvPKnbwbPKfILfanIhHKA9jnZwqKDss1jjQ52MjqjZ9k4DewbNfFj8GQYSbbJIwe -SsCI3zWQzj8C9GRh3sfIB5XeMhg6j6JCQCTl1jNdfK7vsU1P1FeQNWrcrgSXSYk0 -ly4wBOeY99sLAZDBHwo/+ML+TvrbmnNzFrwFuHnYWa8G5z9nODmxfKuU4CkUpijy -323imttUQ/hHWKNddBWcwauwxzQ= ------END CERTIFICATE----- - -# Issuer: CN=D-TRUST EV Root CA 2 2023 O=D-Trust GmbH -# Subject: CN=D-TRUST EV Root CA 2 2023 O=D-Trust GmbH -# Label: "D-TRUST EV Root CA 2 2023" -# Serial: 139766439402180512324132425437959641711 -# MD5 Fingerprint: 96:b4:78:09:f0:09:cb:77:eb:bb:1b:4d:6f:36:bc:b6 -# SHA1 Fingerprint: a5:5b:d8:47:6c:8f:19:f7:4c:f4:6d:6b:b6:c2:79:82:22:df:54:8b -# SHA256 Fingerprint: 8e:82:21:b2:e7:d4:00:78:36:a1:67:2f:0d:cc:29:9c:33:bc:07:d3:16:f1:32:fa:1a:20:6d:58:71:50:f1:ce ------BEGIN CERTIFICATE----- -MIIFqTCCA5GgAwIBAgIQaSYJfoBLTKCnjHhiU19abzANBgkqhkiG9w0BAQ0FADBI -MQswCQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlE -LVRSVVNUIEVWIFJvb3QgQ0EgMiAyMDIzMB4XDTIzMDUwOTA5MTAzM1oXDTM4MDUw -OTA5MTAzMlowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEi -MCAGA1UEAxMZRC1UUlVTVCBFViBSb290IENBIDIgMjAyMzCCAiIwDQYJKoZIhvcN -AQEBBQADggIPADCCAgoCggIBANiOo4mAC7JXUtypU0w3uX9jFxPvp1sjW2l1sJkK -F8GLxNuo4MwxusLyzV3pt/gdr2rElYfXR8mV2IIEUD2BCP/kPbOx1sWy/YgJ25yE -7CUXFId/MHibaljJtnMoPDT3mfd/06b4HEV8rSyMlD/YZxBTfiLNTiVR8CUkNRFe -EMbsh2aJgWi6zCudR3Mfvc2RpHJqnKIbGKBv7FD0fUDCqDDPvXPIEysQEx6Lmqg6 -lHPTGGkKSv/BAQP/eX+1SH977ugpbzZMlWGG2Pmic4ruri+W7mjNPU0oQvlFKzIb -RlUWaqZLKfm7lVa/Rh3sHZMdwGWyH6FDrlaeoLGPaxK3YG14C8qKXO0elg6DpkiV -jTujIcSuWMYAsoS0I6SWhjW42J7YrDRJmGOVxcttSEfi8i4YHtAxq9107PncjLgc -jmgjutDzUNzPZY9zOjLHfP7KgiJPvo5iR2blzYfi6NUPGJ/lBHJLRjwQ8kTCZFZx -TnXonMkmdMV9WdEKWw9t/p51HBjGGjp82A0EzM23RWV6sY+4roRIPrN6TagD4uJ+ -ARZZaBhDM7DS3LAaQzXupdqpRlyuhoFBAUp0JuyfBr/CBTdkdXgpaP3F9ev+R/nk -hbDhezGdpn9yo7nELC7MmVcOIQxFAZRl62UJxmMiCzNJkkg8/M3OsD6Onov4/knF -NXJHAgMBAAGjgY4wgYswDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUqvyREBuH -kV8Wub9PS5FeAByxMoAwDgYDVR0PAQH/BAQDAgEGMEkGA1UdHwRCMEAwPqA8oDqG -OGh0dHA6Ly9jcmwuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3RfZXZfcm9vdF9jYV8y -XzIwMjMuY3JsMA0GCSqGSIb3DQEBDQUAA4ICAQCTy6UfmRHsmg1fLBWTxj++EI14 -QvBukEdHjqOSMo1wj/Zbjb6JzkcBahsgIIlbyIIQbODnmaprxiqgYzWRaoUlrRc4 -pZt+UPJ26oUFKidBK7GB0aL2QHWpDsvxVUjY7NHss+jOFKE17MJeNRqrphYBBo7q -3C+jisosketSjl8MmxfPy3MHGcRqwnNU73xDUmPBEcrCRbH0O1P1aa4846XerOhU -t7KR/aypH/KH5BfGSah82ApB9PI+53c0BFLd6IHyTS9URZ0V4U/M5d40VxDJI3IX -cI1QcB9WbMy5/zpaT2N6w25lBx2Eof+pDGOJbbJAiDnXH3dotfyc1dZnaVuodNv8 -ifYbMvekJKZ2t0dT741Jj6m2g1qllpBFYfXeA08mD6iL8AOWsKwV0HFaanuU5nCT -2vFp4LJiTZ6P/4mdm13NRemUAiKN4DV/6PEEeXFsVIP4M7kFMhtYVRFP0OUnR3Hs -7dpn1mKmS00PaaLJvOwiS5THaJQXfuKOKD62xur1NGyfN4gHONuGcfrNlUhDbqNP -gofXNJhuS5N5YHVpD/Aa1VP6IQzCP+k/HxiMkl14p3ZnGbuy6n/pcAlWVqOwDAst -Nl7F6cTVg8uGF5csbBNvh1qvSaYd2804BC5f4ko1Di1L+KIkBI3Y4WNeApI02phh -XBxvWHZks/wCuPWdCg== ------END CERTIFICATE----- - -# Issuer: CN=SwissSign RSA TLS Root CA 2022 - 1 O=SwissSign AG -# Subject: CN=SwissSign RSA TLS Root CA 2022 - 1 O=SwissSign AG -# Label: "SwissSign RSA TLS Root CA 2022 - 1" -# Serial: 388078645722908516278762308316089881486363258315 -# MD5 Fingerprint: 16:2e:e4:19:76:81:85:ba:8e:91:58:f1:15:ef:72:39 -# SHA1 Fingerprint: 81:34:0a:be:4c:cd:ce:cc:e7:7d:cc:8a:d4:57:e2:45:a0:77:5d:ce -# SHA256 Fingerprint: 19:31:44:f4:31:e0:fd:db:74:07:17:d4:de:92:6a:57:11:33:88:4b:43:60:d3:0e:27:29:13:cb:e6:60:ce:41 ------BEGIN CERTIFICATE----- -MIIFkzCCA3ugAwIBAgIUQ/oMX04bgBhE79G0TzUfRPSA7cswDQYJKoZIhvcNAQEL -BQAwUTELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzErMCkGA1UE -AxMiU3dpc3NTaWduIFJTQSBUTFMgUm9vdCBDQSAyMDIyIC0gMTAeFw0yMjA2MDgx -MTA4MjJaFw00NzA2MDgxMTA4MjJaMFExCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxT -d2lzc1NpZ24gQUcxKzApBgNVBAMTIlN3aXNzU2lnbiBSU0EgVExTIFJvb3QgQ0Eg -MjAyMiAtIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDLKmjiC8NX -vDVjvHClO/OMPE5Xlm7DTjak9gLKHqquuN6orx122ro10JFwB9+zBvKK8i5VUXu7 -LCTLf5ImgKO0lPaCoaTo+nUdWfMHamFk4saMla+ju45vVs9xzF6BYQ1t8qsCLqSX -5XH8irCRIFucdFJtrhUnWXjyCcplDn/L9Ovn3KlMd/YrFgSVrpxxpT8q2kFC5zyE -EPThPYxr4iuRR1VPuFa+Rd4iUU1OKNlfGUEGjw5NBuBwQCMBauTLE5tzrE0USJIt -/m2n+IdreXXhvhCxqohAWVTXz8TQm0SzOGlkjIHRI36qOTw7D59Ke4LKa2/KIj4x -0LDQKhySio/YGZxH5D4MucLNvkEM+KRHBdvBFzA4OmnczcNpI/2aDwLOEGrOyvi5 -KaM2iYauC8BPY7kGWUleDsFpswrzd34unYyzJ5jSmY0lpx+Gs6ZUcDj8fV3oT4MM -0ZPlEuRU2j7yrTrePjxF8CgPBrnh25d7mUWe3f6VWQQvdT/TromZhqwUtKiE+shd -OxtYk8EXlFXIC+OCeYSf8wCENO7cMdWP8vpPlkwGqnj73mSiI80fPsWMvDdUDrta -clXvyFu1cvh43zcgTFeRc5JzrBh3Q4IgaezprClG5QtO+DdziZaKHG29777YtvTK -wP1H8K4LWCDFyB02rpeNUIMmJCn3nTsPBQIDAQABo2MwYTAPBgNVHRMBAf8EBTAD -AQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBRvjmKLk0Ow4UD2p8P98Q+4 -DxU4pTAdBgNVHQ4EFgQUb45ii5NDsOFA9qfD/fEPuA8VOKUwDQYJKoZIhvcNAQEL -BQADggIBAKwsKUF9+lz1GpUYvyypiqkkVHX1uECry6gkUSsYP2OprphWKwVDIqO3 -10aewCoSPY6WlkDfDDOLazeROpW7OSltwAJsipQLBwJNGD77+3v1dj2b9l4wBlgz -Hqp41eZUBDqyggmNzhYzWUUo8aWjlw5DI/0LIICQ/+Mmz7hkkeUFjxOgdg3XNwwQ -iJb0Pr6VvfHDffCjw3lHC1ySFWPtUnWK50Zpy1FVCypM9fJkT6lc/2cyjlUtMoIc -gC9qkfjLvH4YoiaoLqNTKIftV+Vlek4ASltOU8liNr3CjlvrzG4ngRhZi0Rjn9UM -ZfQpZX+RLOV/fuiJz48gy20HQhFRJjKKLjpHE7iNvUcNCfAWpO2Whi4Z2L6MOuhF -LhG6rlrnub+xzI/goP+4s9GFe3lmozm1O2bYQL7Pt2eLSMkZJVX8vY3PXtpOpvJp -zv1/THfQwUY1mFwjmwJFQ5Ra3bxHrSL+ul4vkSkphnsh3m5kt8sNjzdbowhq6/Td -Ao9QAwKxuDdollDruF/UKIqlIgyKhPBZLtU30WHlQnNYKoH3dtvi4k0NX/a3vgW0 -rk4N3hY9A4GzJl5LuEsAz/+MF7psYC0nhzck5npgL7XTgwSqT0N1osGDsieYK7EO -gLrAhV5Cud+xYJHT6xh+cHiudoO+cVrQkOPKwRYlZ0rwtnu64ZzZ ------END CERTIFICATE----- - -# Issuer: CN=OISTE Server Root ECC G1 O=OISTE Foundation -# Subject: CN=OISTE Server Root ECC G1 O=OISTE Foundation -# Label: "OISTE Server Root ECC G1" -# Serial: 47819833811561661340092227008453318557 -# MD5 Fingerprint: 42:a7:d2:35:ae:02:92:db:19:76:08:de:2f:05:b4:d4 -# SHA1 Fingerprint: 3b:f6:8b:09:ae:2a:92:7b:ba:e3:8d:3f:11:95:d9:e6:44:0c:45:e2 -# SHA256 Fingerprint: ee:c9:97:c0:c3:0f:21:6f:7e:3b:8b:30:7d:2b:ae:42:41:2d:75:3f:c8:21:9d:af:d1:52:0b:25:72:85:0f:49 ------BEGIN CERTIFICATE----- -MIICNTCCAbqgAwIBAgIQI/nD1jWvjyhLH/BU6n6XnTAKBggqhkjOPQQDAzBLMQsw -CQYDVQQGEwJDSDEZMBcGA1UECgwQT0lTVEUgRm91bmRhdGlvbjEhMB8GA1UEAwwY -T0lTVEUgU2VydmVyIFJvb3QgRUNDIEcxMB4XDTIzMDUzMTE0NDIyOFoXDTQ4MDUy -NDE0NDIyN1owSzELMAkGA1UEBhMCQ0gxGTAXBgNVBAoMEE9JU1RFIEZvdW5kYXRp -b24xITAfBgNVBAMMGE9JU1RFIFNlcnZlciBSb290IEVDQyBHMTB2MBAGByqGSM49 -AgEGBSuBBAAiA2IABBcv+hK8rBjzCvRE1nZCnrPoH7d5qVi2+GXROiFPqOujvqQy -cvO2Ackr/XeFblPdreqqLiWStukhEaivtUwL85Zgmjvn6hp4LrQ95SjeHIC6XG4N -2xml4z+cKrhAS93mT6NjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBQ3 -TYhlz/w9itWj8UnATgwQb0K0nDAdBgNVHQ4EFgQUN02IZc/8PYrVo/FJwE4MEG9C -tJwwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2kAMGYCMQCpKjAd0MKfkFFR -QD6VVCHNFmb3U2wIFjnQEnx/Yxvf4zgAOdktUyBFCxxgZzFDJe0CMQCSia7pXGKD -YmH5LVerVrkR3SW+ak5KGoJr3M/TvEqzPNcum9v4KGm8ay3sMaE641c= ------END CERTIFICATE----- - -# Issuer: CN=OISTE Server Root RSA G1 O=OISTE Foundation -# Subject: CN=OISTE Server Root RSA G1 O=OISTE Foundation -# Label: " OISTE Server Root RSA G1" -# Serial: 113845518112613905024960613408179309848 -# MD5 Fingerprint: 23:a7:9e:d4:70:b8:b9:14:57:41:8a:7e:44:59:e2:68 -# SHA1 Fingerprint: f7:00:34:25:94:88:68:31:e4:34:87:3f:70:fe:86:b3:86:9f:f0:6e -# SHA256 Fingerprint: 9a:e3:62:32:a5:18:9f:fd:db:35:3d:fd:26:52:0c:01:53:95:d2:27:77:da:c5:9d:b5:7b:98:c0:89:a6:51:e6 ------BEGIN CERTIFICATE----- -MIIFgzCCA2ugAwIBAgIQVaXZZ5Qoxu0M+ifdWwFNGDANBgkqhkiG9w0BAQwFADBL -MQswCQYDVQQGEwJDSDEZMBcGA1UECgwQT0lTVEUgRm91bmRhdGlvbjEhMB8GA1UE -AwwYT0lTVEUgU2VydmVyIFJvb3QgUlNBIEcxMB4XDTIzMDUzMTE0MzcxNloXDTQ4 -MDUyNDE0MzcxNVowSzELMAkGA1UEBhMCQ0gxGTAXBgNVBAoMEE9JU1RFIEZvdW5k -YXRpb24xITAfBgNVBAMMGE9JU1RFIFNlcnZlciBSb290IFJTQSBHMTCCAiIwDQYJ -KoZIhvcNAQEBBQADggIPADCCAgoCggIBAKqu9KuCz/vlNwvn1ZatkOhLKdxVYOPM -vLO8LZK55KN68YG0nnJyQ98/qwsmtO57Gmn7KNByXEptaZnwYx4M0rH/1ow00O7b -rEi56rAUjtgHqSSY3ekJvqgiG1k50SeH3BzN+Puz6+mTeO0Pzjd8JnduodgsIUzk -ik/HEzxux9UTl7Ko2yRpg1bTacuCErudG/L4NPKYKyqOBGf244ehHa1uzjZ0Dl4z -O8vbUZeUapU8zhhabkvG/AePLhq5SvdkNCncpo1Q4Y2LS+VIG24ugBA/5J8bZT8R -tOpXaZ+0AOuFJJkk9SGdl6r7NH8CaxWQrbueWhl/pIzY+m0o/DjH40ytas7ZTpOS -jswMZ78LS5bOZmdTaMsXEY5Z96ycG7mOaES3GK/m5Q9l3JUJsJMStR8+lKXHiHUh -sd4JJCpM4rzsTGdHwimIuQq6+cF0zowYJmXa92/GjHtoXAvuY8BeS/FOzJ8vD+Ho -mnqT8eDI278n5mUpezbgMxVz8p1rhAhoKzYHKyfMeNhqhw5HdPSqoBNdZH702xSu -+zrkL8Fl47l6QGzwBrd7KJvX4V84c5Ss2XCTLdyEr0YconosP4EmQufU2MVshGYR -i3drVByjtdgQ8K4p92cIiBdcuJd5z+orKu5YM+Vt6SmqZQENghPsJQtdLEByFSnT -kCz3GkPVavBpAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU -8snBDw1jALvsRQ5KH7WxszbNDo0wHQYDVR0OBBYEFPLJwQ8NYwC77EUOSh+1sbM2 -zQ6NMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQwFAAOCAgEANGd5sjrG5T33 -I3K5Ce+SrScfoE4KsvXaFwyihdJ+klH9FWXXXGtkFu6KRcoMQzZENdl//nk6HOjG -5D1rd9QhEOP28yBOqb6J8xycqd+8MDoX0TJD0KqKchxRKEzdNsjkLWd9kYccnbz8 -qyiWXmFcuCIzGEgWUOrKL+mlSdx/PKQZvDatkuK59EvV6wit53j+F8Bdh3foZ3dP -AGav9LEDOr4SfEE15fSmG0eLy3n31r8Xbk5l8PjaV8GUgeV6Vg27Rn9vkf195hfk -gSe7BYhW3SCl95gtkRlpMV+bMPKZrXJAlszYd2abtNUOshD+FKrDgHGdPY3ofRRs -YWSGRqbXVMW215AWRqWFyp464+YTFrYVI8ypKVL9AMb2kI5Wj4kI3Zaq5tNqqYY1 -9tVFeEJKRvwDyF7YZvZFZSS0vod7VSCd9521Kvy5YhnLbDuv0204bKt7ph6N/Ome -/msVuduCmsuY33OhkKCgxeDoAaijFJzIwZqsFVAzje18KotzlUBDJvyBpCpfOZC3 -J8tRd/iWkx7P8nd9H0aTolkelUTFLXVksNb54Dxp6gS1HAviRkRNQzuXSXERvSS2 -wq1yVAb+axj5d9spLFKebXd7Yv0PTY6YMjAwcRLWJTXjn/hvnLXrahut6hDTlhZy -BiElxky8j3C7DOReIoMt0r7+hVu05L0= ------END CERTIFICATE----- diff --git a/venv1/Lib/site-packages/pip/_vendor/certifi/core.py b/venv1/Lib/site-packages/pip/_vendor/certifi/core.py index 2f2f7e08..c3e54660 100644 --- a/venv1/Lib/site-packages/pip/_vendor/certifi/core.py +++ b/venv1/Lib/site-packages/pip/_vendor/certifi/core.py @@ -5,10 +5,6 @@ This module returns the installation location of cacert.pem or its contents. """ import sys -import atexit - -def exit_cacert_ctx() -> None: - _CACERT_CTX.__exit__(None, None, None) # type: ignore[union-attr] if sys.version_info >= (3, 11): @@ -39,14 +35,13 @@ def where() -> str: # we will also store that at the global level as well. _CACERT_CTX = as_file(files("pip._vendor.certifi").joinpath("cacert.pem")) _CACERT_PATH = str(_CACERT_CTX.__enter__()) - atexit.register(exit_cacert_ctx) return _CACERT_PATH def contents() -> str: return files("pip._vendor.certifi").joinpath("cacert.pem").read_text(encoding="ascii") -else: +elif sys.version_info >= (3, 7): from importlib.resources import path as get_path, read_text @@ -75,9 +70,39 @@ def where() -> str: # we will also store that at the global level as well. _CACERT_CTX = get_path("pip._vendor.certifi", "cacert.pem") _CACERT_PATH = str(_CACERT_CTX.__enter__()) - atexit.register(exit_cacert_ctx) return _CACERT_PATH def contents() -> str: return read_text("pip._vendor.certifi", "cacert.pem", encoding="ascii") + +else: + import os + import types + from typing import Union + + Package = Union[types.ModuleType, str] + Resource = Union[str, "os.PathLike"] + + # This fallback will work for Python versions prior to 3.7 that lack the + # importlib.resources module but relies on the existing `where` function + # so won't address issues with environments like PyOxidizer that don't set + # __file__ on modules. + def read_text( + package: Package, + resource: Resource, + encoding: str = 'utf-8', + errors: str = 'strict' + ) -> str: + with open(where(), encoding=encoding) as data: + return data.read() + + # If we don't have importlib.resources, then we will just do the old logic + # of assuming we're on the filesystem and munge the path directly. + def where() -> str: + f = os.path.dirname(__file__) + + return os.path.join(f, "cacert.pem") + + def contents() -> str: + return read_text("pip._vendor.certifi", "cacert.pem", encoding="ascii") diff --git a/venv1/Lib/site-packages/pip/_vendor/certifi/py.typed b/venv1/Lib/site-packages/pip/_vendor/certifi/py.typed deleted file mode 100644 index e69de29b..00000000 diff --git a/venv1/Lib/site-packages/pip/_vendor/distlib/__init__.py b/venv1/Lib/site-packages/pip/_vendor/distlib/__init__.py index 4e82943e..962173c8 100644 --- a/venv1/Lib/site-packages/pip/_vendor/distlib/__init__.py +++ b/venv1/Lib/site-packages/pip/_vendor/distlib/__init__.py @@ -1,33 +1,23 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2012-2024 Vinay Sajip. +# Copyright (C) 2012-2022 Vinay Sajip. # Licensed to the Python Software Foundation under a contributor agreement. # See LICENSE.txt and CONTRIBUTORS.txt. # import logging -__version__ = '0.4.0' - +__version__ = '0.3.6' class DistlibException(Exception): pass - try: from logging import NullHandler -except ImportError: # pragma: no cover - +except ImportError: # pragma: no cover class NullHandler(logging.Handler): - - def handle(self, record): - pass - - def emit(self, record): - pass - - def createLock(self): - self.lock = None - + def handle(self, record): pass + def emit(self, record): pass + def createLock(self): self.lock = None logger = logging.getLogger(__name__) logger.addHandler(NullHandler()) diff --git a/venv1/Lib/site-packages/pip/_vendor/distlib/compat.py b/venv1/Lib/site-packages/pip/_vendor/distlib/compat.py index ca561dd2..1fe3d225 100644 --- a/venv1/Lib/site-packages/pip/_vendor/distlib/compat.py +++ b/venv1/Lib/site-packages/pip/_vendor/distlib/compat.py @@ -8,7 +8,6 @@ import os import re -import shutil import sys try: @@ -34,8 +33,9 @@ def quote(s): import urllib2 from urllib2 import (Request, urlopen, URLError, HTTPError, - HTTPBasicAuthHandler, HTTPPasswordMgr, HTTPHandler, - HTTPRedirectHandler, build_opener) + HTTPBasicAuthHandler, HTTPPasswordMgr, + HTTPHandler, HTTPRedirectHandler, + build_opener) if ssl: from urllib2 import HTTPSHandler import httplib @@ -50,15 +50,15 @@ def quote(s): # Leaving this around for now, in case it needs resurrecting in some way # _userprog = None # def splituser(host): - # """splituser('user[:passwd]@host[:port]') --> 'user[:passwd]', 'host[:port]'.""" - # global _userprog - # if _userprog is None: - # import re - # _userprog = re.compile('^(.*)@(.*)$') + # """splituser('user[:passwd]@host[:port]') --> 'user[:passwd]', 'host[:port]'.""" + # global _userprog + # if _userprog is None: + # import re + # _userprog = re.compile('^(.*)@(.*)$') - # match = _userprog.match(host) - # if match: return match.group(1, 2) - # return None, host + # match = _userprog.match(host) + # if match: return match.group(1, 2) + # return None, host else: # pragma: no cover from io import StringIO @@ -67,12 +67,14 @@ def quote(s): from io import TextIOWrapper as file_type import builtins import configparser - from urllib.parse import (urlparse, urlunparse, urljoin, quote, unquote, - urlsplit, urlunsplit, splittype) + import shutil + from urllib.parse import (urlparse, urlunparse, urljoin, quote, + unquote, urlsplit, urlunsplit, splittype) from urllib.request import (urlopen, urlretrieve, Request, url2pathname, - pathname2url, HTTPBasicAuthHandler, - HTTPPasswordMgr, HTTPHandler, - HTTPRedirectHandler, build_opener) + pathname2url, + HTTPBasicAuthHandler, HTTPPasswordMgr, + HTTPHandler, HTTPRedirectHandler, + build_opener) if ssl: from urllib.request import HTTPSHandler from urllib.error import HTTPError, URLError, ContentTooShortError @@ -86,13 +88,14 @@ def quote(s): from itertools import filterfalse filter = filter + try: from ssl import match_hostname, CertificateError -except ImportError: # pragma: no cover - +except ImportError: # pragma: no cover class CertificateError(ValueError): pass + def _dnsname_match(dn, hostname, max_wildcards=1): """Matching according to RFC 6125, section 6.4.3 @@ -142,6 +145,7 @@ def _dnsname_match(dn, hostname, max_wildcards=1): pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE) return pat.match(hostname) + def match_hostname(cert, hostname): """Verify that *cert* (in decoded format as returned by SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125 @@ -174,26 +178,24 @@ def match_hostname(cert, hostname): dnsnames.append(value) if len(dnsnames) > 1: raise CertificateError("hostname %r " - "doesn't match either of %s" % - (hostname, ', '.join(map(repr, dnsnames)))) + "doesn't match either of %s" + % (hostname, ', '.join(map(repr, dnsnames)))) elif len(dnsnames) == 1: raise CertificateError("hostname %r " - "doesn't match %r" % - (hostname, dnsnames[0])) + "doesn't match %r" + % (hostname, dnsnames[0])) else: raise CertificateError("no appropriate commonName or " - "subjectAltName fields were found") + "subjectAltName fields were found") try: from types import SimpleNamespace as Container except ImportError: # pragma: no cover - class Container(object): """ A generic container for when multiple values need to be returned """ - def __init__(self, **kwargs): self.__dict__.update(kwargs) @@ -212,12 +214,12 @@ def which(cmd, mode=os.F_OK | os.X_OK, path=None): path. """ - # Check that a given file can be accessed with the correct mode. # 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 @@ -235,7 +237,7 @@ def _access_check(fn, mode): if sys.platform == "win32": # The current directory takes precedence on Windows. - if os.curdir not in path: + if not os.curdir in path: path.insert(0, os.curdir) # PATHEXT is necessary to check on Windows. @@ -256,7 +258,7 @@ def _access_check(fn, mode): seen = set() for dir in path: normdir = os.path.normcase(dir) - if normdir not in seen: + if not normdir in seen: seen.add(normdir) for thefile in files: name = os.path.join(dir, thefile) @@ -275,7 +277,6 @@ def _access_check(fn, mode): from zipfile import ZipExtFile as BaseZipExtFile class ZipExtFile(BaseZipExtFile): - def __init__(self, base): self.__dict__.update(base.__dict__) @@ -287,7 +288,6 @@ def __exit__(self, *exc_info): # return None, so if an exception occurred, it will propagate class ZipFile(BaseZipFile): - def __enter__(self): return self @@ -299,11 +299,9 @@ def open(self, *args, **kwargs): base = BaseZipFile.open(self, *args, **kwargs) return ZipExtFile(base) - try: from platform import python_implementation -except ImportError: # pragma: no cover - +except ImportError: # pragma: no cover def python_implementation(): """Return a string identifying the Python implementation.""" if 'PyPy' in sys.version: @@ -314,12 +312,12 @@ def python_implementation(): return 'IronPython' return 'CPython' - +import shutil import sysconfig try: callable = callable -except NameError: # pragma: no cover +except NameError: # pragma: no cover from collections.abc import Callable def callable(obj): @@ -360,11 +358,11 @@ def fsdecode(filename): raise TypeError("expect bytes or str, not %s" % type(filename).__name__) - try: from tokenize import detect_encoding -except ImportError: # pragma: no cover +except ImportError: # pragma: no cover from codecs import BOM_UTF8, lookup + import re cookie_re = re.compile(r"coding[:=]\s*([-\w.]+)") @@ -403,7 +401,6 @@ def detect_encoding(readline): bom_found = False encoding = None default = 'utf-8' - def read_or_stop(): try: return readline() @@ -433,8 +430,8 @@ def find_cookie(line): if filename is None: msg = "unknown encoding: " + encoding else: - msg = "unknown encoding for {!r}: {}".format( - filename, encoding) + msg = "unknown encoding for {!r}: {}".format(filename, + encoding) raise SyntaxError(msg) if bom_found: @@ -443,8 +440,7 @@ def find_cookie(line): if filename is None: msg = 'encoding problem: utf-8' else: - msg = 'encoding problem for {!r}: utf-8'.format( - filename) + msg = 'encoding problem for {!r}: utf-8'.format(filename) raise SyntaxError(msg) encoding += '-sig' return encoding @@ -471,7 +467,6 @@ def find_cookie(line): return default, [first, second] - # For converting & <-> & etc. try: from html import escape @@ -484,13 +479,12 @@ def find_cookie(line): try: from collections import ChainMap -except ImportError: # pragma: no cover +except ImportError: # pragma: no cover from collections import MutableMapping try: from reprlib import recursive_repr as _recursive_repr except ImportError: - def _recursive_repr(fillvalue='...'): ''' Decorator to make a repr function return fillvalue for a recursive @@ -515,15 +509,13 @@ def wrapper(self): wrapper.__module__ = getattr(user_function, '__module__') wrapper.__doc__ = getattr(user_function, '__doc__') wrapper.__name__ = getattr(user_function, '__name__') - wrapper.__annotations__ = getattr(user_function, - '__annotations__', {}) + wrapper.__annotations__ = getattr(user_function, '__annotations__', {}) return wrapper return decorating_function class ChainMap(MutableMapping): - ''' - A ChainMap groups multiple dicts (or other mappings) together + ''' A ChainMap groups multiple dicts (or other mappings) together to create a single, updateable view. The underlying mappings are stored in a list. That list is public and can @@ -532,6 +524,7 @@ class ChainMap(MutableMapping): Lookups search the underlying mappings successively until a key is found. In contrast, writes, updates, and deletions only operate on the first mapping. + ''' def __init__(self, *maps): @@ -539,7 +532,7 @@ def __init__(self, *maps): If no mappings are provided, a single empty dictionary is used. ''' - self.maps = list(maps) or [{}] # always at least one map + self.maps = list(maps) or [{}] # always at least one map def __missing__(self, key): raise KeyError(key) @@ -547,19 +540,16 @@ def __missing__(self, key): def __getitem__(self, key): for mapping in self.maps: try: - return mapping[ - key] # can't use 'key in mapping' with defaultdict + return mapping[key] # can't use 'key in mapping' with defaultdict except KeyError: pass - return self.__missing__( - key) # support subclasses that define __missing__ + return self.__missing__(key) # support subclasses that define __missing__ def get(self, key, default=None): return self[key] if key in self else default def __len__(self): - return len(set().union( - *self.maps)) # reuses stored hash values if possible + return len(set().union(*self.maps)) # reuses stored hash values if possible def __iter__(self): return iter(set().union(*self.maps)) @@ -586,12 +576,12 @@ def copy(self): __copy__ = copy - def new_child(self): # like Django's Context.push() + def new_child(self): # like Django's Context.push() 'New ChainMap with a new dict followed by all previous maps.' return self.__class__({}, *self.maps) @property - def parents(self): # like Django's Context.pop() + def parents(self): # like Django's Context.pop() 'New ChainMap from maps[1:].' return self.__class__(*self.maps[1:]) @@ -602,8 +592,7 @@ def __delitem__(self, key): try: del self.maps[0][key] except KeyError: - raise KeyError( - 'Key not found in the first mapping: {!r}'.format(key)) + raise KeyError('Key not found in the first mapping: {!r}'.format(key)) def popitem(self): 'Remove and return an item pair from maps[0]. Raise KeyError is maps[0] is empty.' @@ -617,18 +606,15 @@ def pop(self, key, *args): try: return self.maps[0].pop(key, *args) except KeyError: - raise KeyError( - 'Key not found in the first mapping: {!r}'.format(key)) + raise KeyError('Key not found in the first mapping: {!r}'.format(key)) def clear(self): 'Clear maps[0], leaving maps[1:] intact.' self.maps[0].clear() - try: from importlib.util import cache_from_source # Python >= 3.4 except ImportError: # pragma: no cover - def cache_from_source(path, debug_override=None): assert path.endswith('.py') if debug_override is None: @@ -639,13 +625,12 @@ def cache_from_source(path, debug_override=None): suffix = 'o' return path + suffix - try: from collections import OrderedDict -except ImportError: # pragma: no cover - # {{{ http://code.activestate.com/recipes/576693/ (r9) - # Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pypy. - # Passes Python2.7's test suite and incorporates all the latest updates. +except ImportError: # pragma: no cover +## {{{ http://code.activestate.com/recipes/576693/ (r9) +# Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pypy. +# Passes Python2.7's test suite and incorporates all the latest updates. try: from thread import get_ident as _get_ident except ImportError: @@ -656,9 +641,9 @@ def cache_from_source(path, debug_override=None): except ImportError: pass + class OrderedDict(dict): 'Dictionary that remembers insertion order' - # An inherited dict maps keys to values. # The inherited dict provides __getitem__, __len__, __contains__, and get. # The remaining methods are order-aware. @@ -676,12 +661,11 @@ def __init__(self, *args, **kwds): ''' if len(args) > 1: - raise TypeError('expected at most 1 arguments, got %d' % - len(args)) + raise TypeError('expected at most 1 arguments, got %d' % len(args)) try: self.__root except AttributeError: - self.__root = root = [] # sentinel node + self.__root = root = [] # sentinel node root[:] = [root, root, None] self.__map = {} self.__update(*args, **kwds) @@ -795,7 +779,7 @@ def update(*args, **kwds): ''' if len(args) > 2: raise TypeError('update() takes at most 2 positional ' - 'arguments (%d given)' % (len(args), )) + 'arguments (%d given)' % (len(args),)) elif not args: raise TypeError('update() takes at least 1 argument (0 given)') self = args[0] @@ -841,15 +825,14 @@ def setdefault(self, key, default=None): def __repr__(self, _repr_running=None): 'od.__repr__() <==> repr(od)' - if not _repr_running: - _repr_running = {} + if not _repr_running: _repr_running = {} call_key = id(self), _get_ident() if call_key in _repr_running: return '...' _repr_running[call_key] = 1 try: if not self: - return '%s()' % (self.__class__.__name__, ) + return '%s()' % (self.__class__.__name__,) return '%s(%r)' % (self.__class__.__name__, self.items()) finally: del _repr_running[call_key] @@ -861,8 +844,8 @@ def __reduce__(self): for k in vars(OrderedDict()): inst_dict.pop(k, None) if inst_dict: - return (self.__class__, (items, ), inst_dict) - return self.__class__, (items, ) + return (self.__class__, (items,), inst_dict) + return self.__class__, (items,) def copy(self): 'od.copy() -> a shallow copy of od' @@ -885,8 +868,7 @@ def __eq__(self, other): ''' if isinstance(other, OrderedDict): - return len(self) == len( - other) and self.items() == other.items() + return len(self)==len(other) and self.items() == other.items() return dict.__eq__(self, other) def __ne__(self, other): @@ -906,18 +888,19 @@ def viewitems(self): "od.viewitems() -> a set-like object providing a view on od's items" return ItemsView(self) - try: from logging.config import BaseConfigurator, valid_ident -except ImportError: # pragma: no cover +except ImportError: # pragma: no cover IDENTIFIER = re.compile('^[a-z_][a-z0-9_]*$', re.I) + def valid_ident(s): m = IDENTIFIER.match(s) if not m: raise ValueError('Not a valid Python identifier: %r' % s) return True + # The ConvertingXXX classes are wrappers around standard Python containers, # and they serve to convert any suitable values in the container. The # conversion converts base dicts, lists and tuples to their wrapped @@ -933,7 +916,7 @@ class ConvertingDict(dict): def __getitem__(self, key): value = dict.__getitem__(self, key) result = self.configurator.convert(value) - # If the converted value is different, save for next time + #If the converted value is different, save for next time if value is not result: self[key] = result if type(result) in (ConvertingDict, ConvertingList, @@ -945,7 +928,7 @@ def __getitem__(self, key): def get(self, key, default=None): value = dict.get(self, key, default) result = self.configurator.convert(value) - # If the converted value is different, save for next time + #If the converted value is different, save for next time if value is not result: self[key] = result if type(result) in (ConvertingDict, ConvertingList, @@ -966,11 +949,10 @@ def pop(self, key, default=None): class ConvertingList(list): """A converting list wrapper.""" - def __getitem__(self, key): value = list.__getitem__(self, key) result = self.configurator.convert(value) - # If the converted value is different, save for next time + #If the converted value is different, save for next time if value is not result: self[key] = result if type(result) in (ConvertingDict, ConvertingList, @@ -990,7 +972,6 @@ def pop(self, idx=-1): class ConvertingTuple(tuple): """A converting tuple wrapper.""" - def __getitem__(self, key): value = tuple.__getitem__(self, key) result = self.configurator.convert(value) @@ -1014,8 +995,8 @@ class BaseConfigurator(object): DIGIT_PATTERN = re.compile(r'^\d+$') value_converters = { - 'ext': 'ext_convert', - 'cfg': 'cfg_convert', + 'ext' : 'ext_convert', + 'cfg' : 'cfg_convert', } # We might want to use a different one, e.g. importlib @@ -1061,6 +1042,7 @@ def cfg_convert(self, value): else: rest = rest[m.end():] d = self.config[m.groups()[0]] + #print d, rest while rest: m = self.DOT_PATTERN.match(rest) if m: @@ -1073,9 +1055,7 @@ def cfg_convert(self, value): d = d[idx] else: try: - n = int( - idx - ) # try as number first (most likely) + n = int(idx) # try as number first (most likely) d = d[n] except TypeError: d = d[idx] @@ -1084,7 +1064,7 @@ def cfg_convert(self, value): else: raise ValueError('Unable to convert ' '%r at %r' % (value, rest)) - # rest should be empty + #rest should be empty return d def convert(self, value): @@ -1093,15 +1073,14 @@ def convert(self, value): replaced by their converting alternatives. Strings are checked to see if they have a conversion format and are converted if they do. """ - if not isinstance(value, ConvertingDict) and isinstance( - value, dict): + if not isinstance(value, ConvertingDict) and isinstance(value, dict): value = ConvertingDict(value) value.configurator = self - elif not isinstance(value, ConvertingList) and isinstance( - value, list): + elif not isinstance(value, ConvertingList) and isinstance(value, list): value = ConvertingList(value) value.configurator = self - elif not isinstance(value, ConvertingTuple) and isinstance(value, tuple): + elif not isinstance(value, ConvertingTuple) and\ + isinstance(value, tuple): value = ConvertingTuple(value) value.configurator = self elif isinstance(value, string_types): diff --git a/venv1/Lib/site-packages/pip/_vendor/distlib/scripts.py b/venv1/Lib/site-packages/pip/_vendor/distlib/scripts.py index 195dc3f8..d2706242 100644 --- a/venv1/Lib/site-packages/pip/_vendor/distlib/scripts.py +++ b/venv1/Lib/site-packages/pip/_vendor/distlib/scripts.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2013-2023 Vinay Sajip. +# Copyright (C) 2013-2015 Vinay Sajip. # Licensed to the Python Software Foundation under a contributor agreement. # See LICENSE.txt and CONTRIBUTORS.txt. # @@ -15,7 +15,8 @@ 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__) @@ -42,31 +43,12 @@ SCRIPT_TEMPLATE = r'''# -*- coding: utf-8 -*- import re import sys +from %(module)s import %(import_name)s if __name__ == '__main__': - from %(module)s import %(import_name)s sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) sys.exit(%(func)s()) ''' -# Pre-fetch the contents of all executable wrapper stubs. -# This is to address https://github.com/pypa/pip/issues/12666. -# When updating pip, we rename the old pip in place before installing the -# new version. If we try to fetch a wrapper *after* that rename, the finder -# machinery will be confused as the package is no longer available at the -# location where it was imported from. So we load everything into memory in -# advance. - -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") - } - def enquote_executable(executable): if ' ' in executable: @@ -83,11 +65,9 @@ def enquote_executable(executable): executable = '"%s"' % executable return executable - # Keep the old name around (for now), as there is at least one project using it! _enquote_executable = enquote_executable - class ScriptMaker(object): """ A class to copy or create scripts from source scripts or callable @@ -97,18 +77,21 @@ 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): @@ -119,7 +102,6 @@ def _get_alternate_executable(self, executable, options): return executable if sys.platform.startswith('java'): # pragma: no cover - def _is_shell(self, executable): """ Determine if the specified executable is a script @@ -157,12 +139,6 @@ 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 @@ -170,35 +146,37 @@ 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"' '''\n" + result += b"' '''" return result def _get_shebang(self, encoding, post_interp=b'', options=None): enquote = True if self.executable: executable = self.executable - enquote = False # assume this will be taken care of + enquote = False # assume this will be taken care of 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': + executable = os.path.join( + sysconfig.get_config_var('BINDIR'), + 'python%s%s' % (sysconfig.get_config_var('VERSION'), + sysconfig.get_config_var('EXE'))) + if not os.path.isfile(executable): # 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'))) - 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' % (sysconfig.get_config_var('EXE'))) if options: executable = self._get_alternate_executable(executable, options) @@ -222,8 +200,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 @@ -234,7 +212,8 @@ 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. @@ -242,13 +221,15 @@ def _get_shebang(self, encoding, post_interp=b'', options=None): try: shebang.decode(encoding) except UnicodeDecodeError: # pragma: no cover - raise ValueError('The shebang (%r) is not decodable ' - 'from the script encoding (%r)' % (shebang, encoding)) + raise ValueError( + 'The shebang (%r) is not decodable ' + '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) + return self.script_template % dict(module=entry.prefix, + import_name=entry.suffix.split('.')[0], + func=entry.suffix) manifest = _DEFAULT_MANIFEST @@ -258,6 +239,9 @@ 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 @@ -291,7 +275,7 @@ def _write_script(self, names, shebang, script_bytes, filenames, ext): 'use .deleteme logic') dfname = '%s.deleteme' % outname if os.path.exists(dfname): - os.remove(dfname) # Not allowed to fail here + os.remove(dfname) # Not allowed to fail here os.rename(outname, dfname) # nor here self._fileop.write_binary_file(outname, script_bytes) logger.debug('Able to replace executable using ' @@ -299,7 +283,7 @@ def _write_script(self, names, shebang, script_bytes, filenames, ext): try: os.remove(dfname) except Exception: - pass # still in use - ignore error + pass # still in use - ignore error else: if self._is_nt and not outname.endswith('.' + ext): # pragma: no cover outname = '%s.%s' % (outname, ext) @@ -320,7 +304,8 @@ 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): @@ -375,7 +360,8 @@ 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) @@ -402,17 +388,21 @@ def dry_run(self, value): # Launchers are from https://bitbucket.org/vinay.sajip/simple_launcher/ def _get_launcher(self, kind): - if struct.calcsize('P') == 8: # 64-bit + if struct.calcsize('P') == 8: # 64-bit bits = '64' else: bits = '32' platform_suffix = '-arm' if get_platform() == 'win-arm64' else '' 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)) + # Issue 31: don't hardcode an absolute package name, but + # determine it relative to the current package + distlib_package = __name__.rsplit('.', 1)[0] + resource = finder(distlib_package).find(name) + if not resource: + msg = ('Unable to find resource %s in package %s' % (name, + distlib_package)) raise ValueError(msg) - return WRAPPERS[name] + return resource.bytes # Public API follows diff --git a/venv1/Lib/site-packages/pip/_vendor/distlib/util.py b/venv1/Lib/site-packages/pip/_vendor/distlib/util.py index 0d5bd7a8..dd01849d 100644 --- a/venv1/Lib/site-packages/pip/_vendor/distlib/util.py +++ b/venv1/Lib/site-packages/pip/_vendor/distlib/util.py @@ -1,5 +1,5 @@ # -# Copyright (C) 2012-2023 The Python Software Foundation. +# Copyright (C) 2012-2021 The Python Software Foundation. # See LICENSE.txt and CONTRIBUTORS.txt. # import codecs @@ -31,9 +31,11 @@ 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, + splittype, HTTPHandler, BaseConfigurator, valid_ident, + Container, configparser, URLError, ZipFile, fsdecode, + unquote, urlparse) logger = logging.getLogger(__name__) @@ -60,7 +62,6 @@ def parse_marker(marker_string): interpreted as a literal string, and a string not contained in quotes is a variable (such as os_name). """ - def marker_var(remaining): # either identifier, or literal string m = IDENTIFIER.match(remaining) @@ -94,7 +95,7 @@ def marker_var(remaining): raise SyntaxError('unterminated string: %s' % s) parts.append(q) result = ''.join(parts) - remaining = remaining[1:].lstrip() # skip past closing quote + remaining = remaining[1:].lstrip() # skip past closing quote return result, remaining def marker_expr(remaining): @@ -262,7 +263,8 @@ def get_versions(ver_remaining): 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) + return Container(name=distname, extras=extras, constraints=versions, + marker=mark_expr, url=uri, requirement=rs) def get_resources_dests(resources_root, rules): @@ -302,15 +304,15 @@ def in_venv(): def get_executable(): - # The __PYVENV_LAUNCHER__ dance is apparently no longer needed, as - # changes to the stub launcher mean that sys.executable always points - # to the stub on OS X - # if sys.platform == 'darwin' and ('__PYVENV_LAUNCHER__' - # in os.environ): - # result = os.environ['__PYVENV_LAUNCHER__'] - # else: - # result = sys.executable - # return result +# The __PYVENV_LAUNCHER__ dance is apparently no longer needed, as +# changes to the stub launcher mean that sys.executable always points +# to the stub on OS X +# if sys.platform == 'darwin' and ('__PYVENV_LAUNCHER__' +# in os.environ): +# result = os.environ['__PYVENV_LAUNCHER__'] +# else: +# result = sys.executable +# return result # Avoid normcasing: see issue #143 # result = os.path.normcase(sys.executable) result = sys.executable @@ -344,7 +346,6 @@ def extract_by_key(d, keys): result[key] = d[key] return result - def read_exports(stream): if sys.version_info[0] >= 3: # needs to be a text stream @@ -387,7 +388,7 @@ def read_stream(cp, stream): s = '%s = %s' % (name, value) entry = get_export_entry(s) assert entry is not None - # entry.dist = self + #entry.dist = self entries[name] = entry return result @@ -419,7 +420,6 @@ def tempdir(): finally: shutil.rmtree(td) - @contextlib.contextmanager def chdir(d): cwd = os.getcwd() @@ -441,21 +441,19 @@ def socket_timeout(seconds=15): class cached_property(object): - def __init__(self, func): self.func = func - # for attr in ('__name__', '__module__', '__doc__'): - # setattr(self, attr, getattr(func, attr, None)) + #for attr in ('__name__', '__module__', '__doc__'): + # setattr(self, attr, getattr(func, attr, None)) def __get__(self, obj, cls=None): if obj is None: return self value = self.func(obj) object.__setattr__(obj, self.func.__name__, value) - # obj.__dict__[self.func.__name__] = value = self.func(obj) + #obj.__dict__[self.func.__name__] = value = self.func(obj) return value - def convert_path(pathname): """Return 'pathname' as a name that will work on the native filesystem. @@ -484,7 +482,6 @@ def convert_path(pathname): class FileOperator(object): - def __init__(self, dry_run=False): self.dry_run = dry_run self.ensured = set() @@ -512,7 +509,8 @@ 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 @@ -600,10 +598,8 @@ def byte_compile(self, path, optimize=False, force=False, prefix=None, hashed_in diagpath = path[len(prefix):] compile_kwargs = {} 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 + compile_kwargs['invalidation_mode'] = py_compile.PycInvalidationMode.CHECKED_HASH + py_compile.compile(path, dpath, diagpath, True, **compile_kwargs) # raise error self.record_as_written(dpath) return dpath @@ -665,10 +661,9 @@ def rollback(self): assert flist == ['__pycache__'] sd = os.path.join(d, flist[0]) os.rmdir(sd) - os.rmdir(d) # should fail if non-empty + os.rmdir(d) # should fail if non-empty self._init_record() - def resolve(module_name, dotted_path): if module_name in sys.modules: mod = sys.modules[module_name] @@ -685,7 +680,6 @@ def resolve(module_name, dotted_path): class ExportEntry(object): - def __init__(self, name, prefix, suffix, flags): self.name = name self.prefix = prefix @@ -697,26 +691,27 @@ 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 + 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__ -ENTRY_RE = re.compile( - r'''(?P([^\[]\S*)) +ENTRY_RE = re.compile(r'''(?P(\w|[-.+])+) \s*=\s*(?P(\w+)([:\.]\w+)*) \s*(\[\s*(?P[\w-]+(=\w+)?(,\s*\w+(=\w+)?)*)\s*\])? ''', re.VERBOSE) - def get_export_entry(specification): m = ENTRY_RE.search(specification) if not m: @@ -789,7 +784,7 @@ def get_cache_base(suffix=None): return os.path.join(result, suffix) -def path_to_cache_dir(path, use_abspath=True): +def path_to_cache_dir(path): """ Convert an absolute path to a directory name for use in a cache. @@ -799,7 +794,7 @@ def path_to_cache_dir(path, use_abspath=True): #. Any occurrence of ``os.sep`` is replaced with ``'--'``. #. ``'.cache'`` is appended. """ - d, p = os.path.splitdrive(os.path.abspath(path) if use_abspath else path) + d, p = os.path.splitdrive(os.path.abspath(path)) if d: d = d.replace(':', '---') p = p.replace(os.sep, '--') @@ -832,7 +827,6 @@ def get_process_umask(): os.umask(result) return result - def is_string_sequence(seq): result = True i = None @@ -843,7 +837,6 @@ def is_string_sequence(seq): assert i is not None return result - 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?)') @@ -873,12 +866,10 @@ def split_filename(filename, project_name=None): result = m.group(1), m.group(3), pyver return result - # Allow spaces in name because of legacy dists like "Twisted Core" NAME_VERSION_RE = re.compile(r'(?P[\w .-]+)\s*' r'\(\s*(?P[^\s)]+)\)$') - def parse_name_and_version(p): """ A utility method used to get name and version from a string. @@ -894,7 +885,6 @@ def parse_name_and_version(p): d = m.groupdict() return d['name'].strip().lower(), d['ver'] - def get_extras(requested, available): result = set() requested = set(requested or []) @@ -916,13 +906,10 @@ def get_extras(requested, available): logger.warning('undeclared extra: %s' % r) result.add(r) return result - - # # Extended metadata functionality # - def _get_external_data(url): result = {} try: @@ -936,24 +923,21 @@ def _get_external_data(url): logger.debug('Unexpected response for JSON request: %s', ct) else: reader = codecs.getreader('utf-8')(resp) - # data = reader.read().decode('utf-8') - # result = json.loads(data) + #data = reader.read().decode('utf-8') + #result = json.loads(data) result = json.load(reader) except Exception as e: logger.exception('Failed to get external data for %s: %s', url, e) return result - _external_data_base_url = 'https://www.red-dove.com/pypi/projects/' - def get_project_data(name): url = '%s/%s/project.json' % (name[0].upper(), name) url = urljoin(_external_data_base_url, url) result = _get_external_data(url) return result - def get_package_data(name, version): url = '%s/%s/package-%s.json' % (name[0].upper(), name, version) url = urljoin(_external_data_base_url, url) @@ -981,11 +965,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, use_abspath=True): + def prefix_to_dir(self, prefix): """ Converts a resource prefix to a directory name in the cache. """ - return path_to_cache_dir(prefix, use_abspath=use_abspath) + return path_to_cache_dir(prefix) def clear(self): """ @@ -1008,7 +992,6 @@ class EventMixin(object): """ A very simple publish/subscribe system. """ - def __init__(self): self._subscribers = {} @@ -1070,19 +1053,18 @@ 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 - # # Simple sequencing # class Sequencer(object): - def __init__(self): self._preds = {} self._succs = {} - self._nodes = set() # nodes with no preds/succs + self._nodes = set() # nodes with no preds/succs def add_node(self, node): self._nodes.add(node) @@ -1122,7 +1104,8 @@ 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): @@ -1151,7 +1134,7 @@ def get_steps(self, final): @property def strong_connections(self): - # http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm + #http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm index_counter = [0] stack = [] lowlinks = {} @@ -1176,11 +1159,11 @@ def strongconnect(node): if successor not in lowlinks: # Successor has not yet been visited strongconnect(successor) - lowlinks[node] = min(lowlinks[node], lowlinks[successor]) + lowlinks[node] = min(lowlinks[node],lowlinks[successor]) elif successor in stack: # the successor is in the stack and hence in the current # strongly connected component (SCC) - lowlinks[node] = min(lowlinks[node], index[successor]) + lowlinks[node] = min(lowlinks[node],index[successor]) # If `node` is a root node, pop the stack and generate an SCC if lowlinks[node] == index[node]: @@ -1189,8 +1172,7 @@ def strongconnect(node): while True: successor = stack.pop() connected_component.append(successor) - if successor == node: - break + if successor == node: break component = tuple(connected_component) # storing the result result.append(component) @@ -1213,13 +1195,12 @@ def dot(self): result.append('}') return '\n'.join(result) - # # 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): @@ -1268,20 +1249,6 @@ def check_path(path): for tarinfo in archive.getmembers(): if not isinstance(tarinfo.name, text_type): tarinfo.name = tarinfo.name.decode('utf-8') - - # Limit extraction of dangerous items, if this Python - # allows it easily. If not, just trust the input. - # See: https://docs.python.org/3/library/tarfile.html#extraction-filters - def extraction_filter(member, path): - """Run tarfile.tar_filter, but raise the expected ValueError""" - # This is only called if the current Python has tarfile filters - try: - return tarfile.tar_filter(member, path) - except tarfile.FilterError as exc: - raise ValueError(str(exc)) - - archive.extraction_filter = extraction_filter - archive.extractall(dest_dir) finally: @@ -1302,12 +1269,11 @@ def zip_dir(directory): zf.write(full, dest) return result - # # Simple progress bar # -UNITS = ('', 'K', 'M', 'G', 'T', 'P') +UNITS = ('', 'K', 'M', 'G','T','P') class Progress(object): @@ -1362,8 +1328,8 @@ def percentage(self): def format_duration(self, duration): if (duration <= 0) and self.max is None or self.cur == self.min: result = '??:??:??' - # elif duration < 1: - # result = '--:--:--' + #elif duration < 1: + # result = '--:--:--' else: result = time.strftime('%H:%M:%S', time.gmtime(duration)) return result @@ -1373,7 +1339,7 @@ def ETA(self): if self.done: prefix = 'Done' t = self.elapsed - # import pdb; pdb.set_trace() + #import pdb; pdb.set_trace() else: prefix = 'ETA ' if self.max is None: @@ -1381,7 +1347,7 @@ def ETA(self): elif self.elapsed == 0 or (self.cur == self.min): t = 0 else: - # import pdb; pdb.set_trace() + #import pdb; pdb.set_trace() t = float(self.max - self.min) t /= self.cur - self.min t = (t - 1) * self.elapsed @@ -1399,7 +1365,6 @@ def speed(self): result /= 1000.0 return '%d %sB/s' % (result, unit) - # # Glob functionality # @@ -1447,17 +1412,18 @@ def _iglob(path_glob): for fn in _iglob(os.path.join(path, radical)): yield fn - 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 - # + +# +# HTTPSConnection which verifies certificates/matches domains +# class HTTPSConnection(httplib.HTTPSConnection): - ca_certs = None # set this to the path to the certs file (.pem) - check_domain = True # only used if ca_certs is not None + ca_certs = None # set this to the path to the certs file (.pem) + check_domain = True # only used if ca_certs is not None # noinspection PyPropertyAccess def connect(self): @@ -1469,7 +1435,7 @@ def connect(self): context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) if hasattr(ssl, 'OP_NO_SSLv2'): context.options |= ssl.OP_NO_SSLv2 - if getattr(self, 'cert_file', None): + if self.cert_file: context.load_cert_chain(self.cert_file, self.key_file) kwargs = {} if self.ca_certs: @@ -1489,7 +1455,6 @@ def connect(self): raise class HTTPSHandler(BaseHTTPSHandler): - def __init__(self, ca_certs, check_domain=True): BaseHTTPSHandler.__init__(self) self.ca_certs = ca_certs @@ -1531,17 +1496,14 @@ def https_open(self, req): # handler for HTTP itself. # class HTTPSOnlyHandler(HTTPSHandler, HTTPHandler): - def http_open(self, req): raise URLError('Unexpected HTTP request on what should be a secure ' 'connection: %s' % req) - # # XML-RPC with timeouts # class Transport(xmlrpclib.Transport): - def __init__(self, timeout, use_datetime=0): self.timeout = timeout xmlrpclib.Transport.__init__(self, use_datetime) @@ -1553,11 +1515,8 @@ def make_connection(self, host): self._connection = host, httplib.HTTPConnection(h) return self._connection[1] - if ssl: - class SafeTransport(xmlrpclib.SafeTransport): - def __init__(self, timeout, use_datetime=0): self.timeout = timeout xmlrpclib.SafeTransport.__init__(self, use_datetime) @@ -1569,12 +1528,12 @@ 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] class ServerProxy(xmlrpclib.ServerProxy): - def __init__(self, uri, **kwargs): self.timeout = timeout = kwargs.pop('timeout', None) # The above classes only come into play if a timeout @@ -1591,13 +1550,11 @@ def __init__(self, uri, **kwargs): self.transport = t xmlrpclib.ServerProxy.__init__(self, uri, **kwargs) - # # CSV functionality. This is provided because on 2.x, the csv module can't # handle Unicode. However, we need to deal with Unicode in e.g. RECORD files. # - def _csv_open(fn, mode, **kwargs): if sys.version_info[0] < 3: mode += 'b' @@ -1611,9 +1568,9 @@ def _csv_open(fn, mode, **kwargs): class CSVBase(object): defaults = { - 'delimiter': str(','), # The strs are used because we need native - 'quotechar': str('"'), # str in the csv API (2.x won't take - 'lineterminator': str('\n') # Unicode) + 'delimiter': str(','), # The strs are used because we need native + 'quotechar': str('"'), # str in the csv API (2.x won't take + 'lineterminator': str('\n') # Unicode) } def __enter__(self): @@ -1624,7 +1581,6 @@ def __exit__(self, *exc_info): class CSVReader(CSVBase): - def __init__(self, **kwargs): if 'stream' in kwargs: stream = kwargs['stream'] @@ -1649,9 +1605,7 @@ def next(self): __next__ = next - class CSVWriter(CSVBase): - def __init__(self, fn, **kwargs): self.stream = _csv_open(fn, 'w') self.writer = csv.writer(self.stream, **self.defaults) @@ -1666,12 +1620,10 @@ def writerow(self, row): row = r self.writer.writerow(row) - # # Configurator functionality # - class Configurator(BaseConfigurator): value_converters = dict(BaseConfigurator.value_converters) @@ -1682,7 +1634,6 @@ def __init__(self, config, base=None): self.base = base or os.getcwd() def configure_custom(self, config): - def convert(o): if isinstance(o, (list, tuple)): result = type(o)([convert(i) for i in o]) @@ -1732,7 +1683,6 @@ class SubprocessMixin(object): """ Mixin for running subprocesses and capturing their output """ - def __init__(self, verbose=False, progress=None): self.verbose = verbose self.progress = progress @@ -1759,7 +1709,8 @@ 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')) @@ -1779,17 +1730,15 @@ def normalize_name(name): # https://www.python.org/dev/peps/pep-0503/#normalized-names return re.sub('[-_.]+', '-', name).lower() - # def _get_pypirc_command(): -# """ -# Get the distutils command for interacting with PyPI configurations. -# :return: the command. -# """ -# from distutils.core import Distribution -# from distutils.config import PyPIRCCommand -# d = Distribution() -# return PyPIRCCommand(d) - + # """ + # Get the distutils command for interacting with PyPI configurations. + # :return: the command. + # """ + # from distutils.core import Distribution + # from distutils.config import PyPIRCCommand + # d = Distribution() + # return PyPIRCCommand(d) class PyPIRCFile(object): @@ -1814,7 +1763,9 @@ 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: @@ -1825,7 +1776,8 @@ 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) @@ -1835,9 +1787,11 @@ 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 @@ -1867,24 +1821,20 @@ def update(self, username, password): with open(fn, 'w') as f: config.write(f) - def _load_pypirc(index): """ Read the PyPI access configuration as supported by distutils. """ return PyPIRCFile(url=index.url).read() - def _store_pypirc(index): PyPIRCFile().update(index.username, index.password) - # # get_platform()/get_host_platform() copied from Python 3.10.a0 source, with some minor # tweaks # - def get_host_platform(): """Return a string that identifies the current platform. This is used mainly to distinguish platform-specific build directories and platform-specific built @@ -1936,16 +1886,16 @@ def get_host_platform(): # At least on Linux/Intel, 'machine' is the processor -- # i386, etc. # XXX what about Alpha, SPARC, etc? - return "%s-%s" % (osname, machine) + return "%s-%s" % (osname, machine) elif osname[:5] == 'sunos': - if release[0] >= '5': # SunOS 5 == Solaris 2 + if release[0] >= '5': # SunOS 5 == Solaris 2 osname = 'solaris' release = '%d.%s' % (int(release[0]) - 3, release[2:]) # We can't use 'platform.architecture()[0]' because a # bootstrap problem. We use a dict to get an error # if some suspicious happens. - bitness = {2147483647: '32bit', 9223372036854775807: '64bit'} + bitness = {2147483647:'32bit', 9223372036854775807:'64bit'} machine += '.%s' % bitness[sys.maxsize] # fall through to standard osname-release-machine representation elif osname[:3] == 'aix': @@ -1953,25 +1903,23 @@ def get_host_platform(): return aix_platform() elif osname[:6] == 'cygwin': osname = 'cygwin' - rel_re = re.compile(r'[\d.]+', re.ASCII) + rel_re = re.compile (r'[\d.]+', re.ASCII) m = rel_re.match(release) if m: release = m.group() elif osname[:6] == 'darwin': - import _osx_support - try: - from distutils import sysconfig - except ImportError: - import sysconfig - osname, release, machine = _osx_support.get_platform_osx(sysconfig.get_config_vars(), osname, release, machine) + import _osx_support, distutils.sysconfig + osname, release, machine = _osx_support.get_platform_osx( + distutils.sysconfig.get_config_vars(), + osname, release, machine) return '%s-%s-%s' % (osname, release, machine) _TARGET_TO_PLAT = { - 'x86': 'win32', - 'x64': 'win-amd64', - 'arm': 'win-arm32', + 'x86' : 'win32', + 'x64' : 'win-amd64', + 'arm' : 'win-arm32', } diff --git a/venv1/Lib/site-packages/pip/_vendor/distro/distro.py b/venv1/Lib/site-packages/pip/_vendor/distro/distro.py index 78ccdfa4..89e18680 100644 --- a/venv1/Lib/site-packages/pip/_vendor/distro/distro.py +++ b/venv1/Lib/site-packages/pip/_vendor/distro/distro.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright 2015-2021 Nir Cohen +# Copyright 2015,2016,2017 Nir Cohen # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -55,7 +55,7 @@ # Python 3.7 TypedDict = dict -__version__ = "1.9.0" +__version__ = "1.8.0" class VersionDict(TypedDict): @@ -125,7 +125,6 @@ class InfoDict(TypedDict): # Base file names to be looked up for if _UNIXCONFDIR is not readable. _DISTRO_RELEASE_BASENAMES = [ "SuSE-release", - "altlinux-release", "arch-release", "base-release", "centos-release", @@ -152,8 +151,6 @@ class InfoDict(TypedDict): "system-release", "plesk-release", "iredmail-release", - "board-release", - "ec2_version", ) @@ -246,7 +243,6 @@ def id() -> str: "rocky" Rocky Linux "aix" AIX "guix" Guix System - "altlinux" ALT Linux ============== ========================================= If you have a need to get distros for reliable IDs added into this set, @@ -995,10 +991,10 @@ def info(self, pretty: bool = False, best: bool = False) -> InfoDict: For details, see :func:`distro.info`. """ - return InfoDict( + return dict( id=self.id(), version=self.version(pretty, best), - version_parts=VersionDict( + version_parts=dict( major=self.major_version(best), minor=self.minor_version(best), build_number=self.build_number(best), diff --git a/venv1/Lib/site-packages/pip/_vendor/distro/py.typed b/venv1/Lib/site-packages/pip/_vendor/distro/py.typed deleted file mode 100644 index e69de29b..00000000 diff --git a/venv1/Lib/site-packages/pip/_vendor/idna/__init__.py b/venv1/Lib/site-packages/pip/_vendor/idna/__init__.py index cfdc030a..a40eeafc 100644 --- a/venv1/Lib/site-packages/pip/_vendor/idna/__init__.py +++ b/venv1/Lib/site-packages/pip/_vendor/idna/__init__.py @@ -1,3 +1,4 @@ +from .package_data import __version__ from .core import ( IDNABidiError, IDNAError, @@ -19,10 +20,8 @@ valid_string_length, ) from .intranges import intranges_contain -from .package_data import __version__ __all__ = [ - "__version__", "IDNABidiError", "IDNAError", "InvalidCodepoint", diff --git a/venv1/Lib/site-packages/pip/_vendor/idna/codec.py b/venv1/Lib/site-packages/pip/_vendor/idna/codec.py index 913abfd6..1ca9ba62 100644 --- a/venv1/Lib/site-packages/pip/_vendor/idna/codec.py +++ b/venv1/Lib/site-packages/pip/_vendor/idna/codec.py @@ -1,51 +1,49 @@ +from .core import encode, decode, alabel, ulabel, IDNAError import codecs import re -from typing import Any, Optional, Tuple - -from .core import IDNAError, alabel, decode, encode, ulabel - -_unicode_dots_re = re.compile("[\u002e\u3002\uff0e\uff61]") +from typing import Tuple, Optional +_unicode_dots_re = re.compile('[\u002e\u3002\uff0e\uff61]') class Codec(codecs.Codec): - def encode(self, data: str, errors: str = "strict") -> Tuple[bytes, int]: - if errors != "strict": - raise IDNAError('Unsupported error handling "{}"'.format(errors)) + + def encode(self, data: str, errors: str = 'strict') -> Tuple[bytes, int]: + if errors != 'strict': + raise IDNAError('Unsupported error handling \"{}\"'.format(errors)) if not data: return b"", 0 return encode(data), len(data) - def decode(self, data: bytes, errors: str = "strict") -> Tuple[str, int]: - if errors != "strict": - raise IDNAError('Unsupported error handling "{}"'.format(errors)) + def decode(self, data: bytes, errors: str = 'strict') -> Tuple[str, int]: + if errors != 'strict': + raise IDNAError('Unsupported error handling \"{}\"'.format(errors)) if not data: - return "", 0 + return '', 0 return decode(data), len(data) - class IncrementalEncoder(codecs.BufferedIncrementalEncoder): - def _buffer_encode(self, data: str, errors: str, final: bool) -> Tuple[bytes, int]: - if errors != "strict": - raise IDNAError('Unsupported error handling "{}"'.format(errors)) + def _buffer_encode(self, data: str, errors: str, final: bool) -> Tuple[str, int]: # type: ignore + if errors != 'strict': + raise IDNAError('Unsupported error handling \"{}\"'.format(errors)) if not data: - return b"", 0 + return "", 0 labels = _unicode_dots_re.split(data) - trailing_dot = b"" + trailing_dot = '' if labels: if not labels[-1]: - trailing_dot = b"." + trailing_dot = '.' del labels[-1] elif not final: # Keep potentially unfinished label until the next call del labels[-1] if labels: - trailing_dot = b"." + trailing_dot = '.' result = [] size = 0 @@ -56,33 +54,29 @@ def _buffer_encode(self, data: str, errors: str, final: bool) -> Tuple[bytes, in size += len(label) # Join with U+002E - result_bytes = b".".join(result) + trailing_dot + result_str = '.'.join(result) + trailing_dot # type: ignore size += len(trailing_dot) - return result_bytes, size - + return result_str, size class IncrementalDecoder(codecs.BufferedIncrementalDecoder): - def _buffer_decode(self, data: Any, errors: str, final: bool) -> Tuple[str, int]: - if errors != "strict": - raise IDNAError('Unsupported error handling "{}"'.format(errors)) + def _buffer_decode(self, data: str, errors: str, final: bool) -> Tuple[str, int]: # type: ignore + if errors != 'strict': + raise IDNAError('Unsupported error handling \"{}\"'.format(errors)) if not data: - return ("", 0) - - if not isinstance(data, str): - data = str(data, "ascii") + return ('', 0) labels = _unicode_dots_re.split(data) - trailing_dot = "" + trailing_dot = '' if labels: if not labels[-1]: - trailing_dot = "." + trailing_dot = '.' del labels[-1] elif not final: # Keep potentially unfinished label until the next call del labels[-1] if labels: - trailing_dot = "." + trailing_dot = '.' result = [] size = 0 @@ -92,7 +86,7 @@ def _buffer_decode(self, data: Any, errors: str, final: bool) -> Tuple[str, int] size += 1 size += len(label) - result_str = ".".join(result) + trailing_dot + result_str = '.'.join(result) + trailing_dot size += len(trailing_dot) return (result_str, size) @@ -105,18 +99,14 @@ class StreamReader(Codec, codecs.StreamReader): pass -def search_function(name: str) -> Optional[codecs.CodecInfo]: - if name != "idna2008": - return None +def getregentry() -> codecs.CodecInfo: + # Compatibility as a search_function for codecs.register() return codecs.CodecInfo( - name=name, - encode=Codec().encode, - decode=Codec().decode, + name='idna', + encode=Codec().encode, # type: ignore + decode=Codec().decode, # type: ignore incrementalencoder=IncrementalEncoder, incrementaldecoder=IncrementalDecoder, streamwriter=StreamWriter, streamreader=StreamReader, ) - - -codecs.register(search_function) diff --git a/venv1/Lib/site-packages/pip/_vendor/idna/compat.py b/venv1/Lib/site-packages/pip/_vendor/idna/compat.py index 1df9f2a7..786e6bda 100644 --- a/venv1/Lib/site-packages/pip/_vendor/idna/compat.py +++ b/venv1/Lib/site-packages/pip/_vendor/idna/compat.py @@ -1,15 +1,13 @@ +from .core import * +from .codec import * from typing import Any, Union -from .core import decode, encode - - def ToASCII(label: str) -> bytes: return encode(label) - def ToUnicode(label: Union[bytes, bytearray]) -> str: return decode(label) - def nameprep(s: Any) -> None: - raise NotImplementedError("IDNA 2008 does not utilise nameprep protocol") + raise NotImplementedError('IDNA 2008 does not utilise nameprep protocol') + diff --git a/venv1/Lib/site-packages/pip/_vendor/idna/core.py b/venv1/Lib/site-packages/pip/_vendor/idna/core.py index 9115f123..4f300371 100644 --- a/venv1/Lib/site-packages/pip/_vendor/idna/core.py +++ b/venv1/Lib/site-packages/pip/_vendor/idna/core.py @@ -1,37 +1,31 @@ +from . import idnadata import bisect -import re import unicodedata -from typing import Optional, Union - -from . import idnadata +import re +from typing import Union, Optional from .intranges import intranges_contain _virama_combining_class = 9 -_alabel_prefix = b"xn--" -_unicode_dots_re = re.compile("[\u002e\u3002\uff0e\uff61]") - +_alabel_prefix = b'xn--' +_unicode_dots_re = re.compile('[\u002e\u3002\uff0e\uff61]') class IDNAError(UnicodeError): - """Base exception for all IDNA-encoding related problems""" - + """ Base exception for all IDNA-encoding related problems """ pass class IDNABidiError(IDNAError): - """Exception when bidirectional requirements are not satisfied""" - + """ Exception when bidirectional requirements are not satisfied """ pass class InvalidCodepoint(IDNAError): - """Exception when a disallowed or unallocated codepoint is used""" - + """ Exception when a disallowed or unallocated codepoint is used """ pass class InvalidCodepointContext(IDNAError): - """Exception when the codepoint is not valid in the context it is used""" - + """ Exception when the codepoint is not valid in the context it is used """ pass @@ -39,20 +33,17 @@ def _combining_class(cp: int) -> int: v = unicodedata.combining(chr(cp)) if v == 0: if not unicodedata.name(chr(cp)): - raise ValueError("Unknown character in unicodedata") + raise ValueError('Unknown character in unicodedata') return v - def _is_script(cp: str, script: str) -> bool: return intranges_contain(ord(cp), idnadata.scripts[script]) - def _punycode(s: str) -> bytes: - return s.encode("punycode") - + return s.encode('punycode') def _unot(s: int) -> str: - return "U+{:04X}".format(s) + return 'U+{:04X}'.format(s) def valid_label_length(label: Union[bytes, str]) -> bool: @@ -70,170 +61,158 @@ def valid_string_length(label: Union[bytes, str], trailing_dot: bool) -> bool: def check_bidi(label: str, check_ltr: bool = False) -> bool: # Bidi rules should only be applied if string contains RTL characters bidi_label = False - for idx, cp in enumerate(label, 1): + for (idx, cp) in enumerate(label, 1): direction = unicodedata.bidirectional(cp) - if direction == "": + if direction == '': # String likely comes from a newer version of Unicode - raise IDNABidiError("Unknown directionality in label {} at position {}".format(repr(label), idx)) - if direction in ["R", "AL", "AN"]: + raise IDNABidiError('Unknown directionality in label {} at position {}'.format(repr(label), idx)) + if direction in ['R', 'AL', 'AN']: bidi_label = True if not bidi_label and not check_ltr: return True # Bidi rule 1 direction = unicodedata.bidirectional(label[0]) - if direction in ["R", "AL"]: + if direction in ['R', 'AL']: rtl = True - elif direction == "L": + elif direction == 'L': rtl = False else: - raise IDNABidiError("First codepoint in label {} must be directionality L, R or AL".format(repr(label))) + raise IDNABidiError('First codepoint in label {} must be directionality L, R or AL'.format(repr(label))) valid_ending = False - number_type: Optional[str] = None - for idx, cp in enumerate(label, 1): + number_type = None # type: Optional[str] + for (idx, cp) in enumerate(label, 1): direction = unicodedata.bidirectional(cp) if rtl: # Bidi rule 2 - if direction not in [ - "R", - "AL", - "AN", - "EN", - "ES", - "CS", - "ET", - "ON", - "BN", - "NSM", - ]: - raise IDNABidiError("Invalid direction for codepoint at position {} in a right-to-left label".format(idx)) + if not direction in ['R', 'AL', 'AN', 'EN', 'ES', 'CS', 'ET', 'ON', 'BN', 'NSM']: + raise IDNABidiError('Invalid direction for codepoint at position {} in a right-to-left label'.format(idx)) # Bidi rule 3 - if direction in ["R", "AL", "EN", "AN"]: + if direction in ['R', 'AL', 'EN', 'AN']: valid_ending = True - elif direction != "NSM": + elif direction != 'NSM': valid_ending = False # Bidi rule 4 - if direction in ["AN", "EN"]: + if direction in ['AN', 'EN']: if not number_type: number_type = direction else: if number_type != direction: - raise IDNABidiError("Can not mix numeral types in a right-to-left label") + raise IDNABidiError('Can not mix numeral types in a right-to-left label') else: # Bidi rule 5 - if direction not in ["L", "EN", "ES", "CS", "ET", "ON", "BN", "NSM"]: - raise IDNABidiError("Invalid direction for codepoint at position {} in a left-to-right label".format(idx)) + if not direction in ['L', 'EN', 'ES', 'CS', 'ET', 'ON', 'BN', 'NSM']: + raise IDNABidiError('Invalid direction for codepoint at position {} in a left-to-right label'.format(idx)) # Bidi rule 6 - if direction in ["L", "EN"]: + if direction in ['L', 'EN']: valid_ending = True - elif direction != "NSM": + elif direction != 'NSM': valid_ending = False if not valid_ending: - raise IDNABidiError("Label ends with illegal codepoint directionality") + raise IDNABidiError('Label ends with illegal codepoint directionality') return True def check_initial_combiner(label: str) -> bool: - if unicodedata.category(label[0])[0] == "M": - raise IDNAError("Label begins with an illegal combining character") + if unicodedata.category(label[0])[0] == 'M': + raise IDNAError('Label begins with an illegal combining character') return True def check_hyphen_ok(label: str) -> bool: - if label[2:4] == "--": - raise IDNAError("Label has disallowed hyphens in 3rd and 4th position") - if label[0] == "-" or label[-1] == "-": - raise IDNAError("Label must not start or end with a hyphen") + if label[2:4] == '--': + raise IDNAError('Label has disallowed hyphens in 3rd and 4th position') + if label[0] == '-' or label[-1] == '-': + raise IDNAError('Label must not start or end with a hyphen') return True def check_nfc(label: str) -> None: - if unicodedata.normalize("NFC", label) != label: - raise IDNAError("Label must be in Normalization Form C") + if unicodedata.normalize('NFC', label) != label: + raise IDNAError('Label must be in Normalization Form C') def valid_contextj(label: str, pos: int) -> bool: cp_value = ord(label[pos]) - if cp_value == 0x200C: + if cp_value == 0x200c: + if pos > 0: if _combining_class(ord(label[pos - 1])) == _virama_combining_class: return True ok = False - for i in range(pos - 1, -1, -1): + for i in range(pos-1, -1, -1): joining_type = idnadata.joining_types.get(ord(label[i])) - if joining_type == ord("T"): + if joining_type == ord('T'): continue - elif joining_type in [ord("L"), ord("D")]: + if joining_type in [ord('L'), ord('D')]: ok = True break - else: - break if not ok: return False ok = False - for i in range(pos + 1, len(label)): + for i in range(pos+1, len(label)): joining_type = idnadata.joining_types.get(ord(label[i])) - if joining_type == ord("T"): + if joining_type == ord('T'): continue - elif joining_type in [ord("R"), ord("D")]: + if joining_type in [ord('R'), ord('D')]: ok = True break - else: - break return ok - if cp_value == 0x200D: + if cp_value == 0x200d: + if pos > 0: if _combining_class(ord(label[pos - 1])) == _virama_combining_class: return True return False else: + return False def valid_contexto(label: str, pos: int, exception: bool = False) -> bool: cp_value = ord(label[pos]) - if cp_value == 0x00B7: - if 0 < pos < len(label) - 1: - if ord(label[pos - 1]) == 0x006C and ord(label[pos + 1]) == 0x006C: + if cp_value == 0x00b7: + if 0 < pos < len(label)-1: + if ord(label[pos - 1]) == 0x006c and ord(label[pos + 1]) == 0x006c: return True return False elif cp_value == 0x0375: - if pos < len(label) - 1 and len(label) > 1: - return _is_script(label[pos + 1], "Greek") + if pos < len(label)-1 and len(label) > 1: + return _is_script(label[pos + 1], 'Greek') return False - elif cp_value == 0x05F3 or cp_value == 0x05F4: + elif cp_value == 0x05f3 or cp_value == 0x05f4: if pos > 0: - return _is_script(label[pos - 1], "Hebrew") + return _is_script(label[pos - 1], 'Hebrew') return False - elif cp_value == 0x30FB: + elif cp_value == 0x30fb: for cp in label: - if cp == "\u30fb": + if cp == '\u30fb': continue - if _is_script(cp, "Hiragana") or _is_script(cp, "Katakana") or _is_script(cp, "Han"): + if _is_script(cp, 'Hiragana') or _is_script(cp, 'Katakana') or _is_script(cp, 'Han'): return True return False elif 0x660 <= cp_value <= 0x669: for cp in label: - if 0x6F0 <= ord(cp) <= 0x06F9: + if 0x6f0 <= ord(cp) <= 0x06f9: return False return True - elif 0x6F0 <= cp_value <= 0x6F9: + elif 0x6f0 <= cp_value <= 0x6f9: for cp in label: if 0x660 <= ord(cp) <= 0x0669: return False @@ -244,58 +223,55 @@ def valid_contexto(label: str, pos: int, exception: bool = False) -> bool: def check_label(label: Union[str, bytes, bytearray]) -> None: if isinstance(label, (bytes, bytearray)): - label = label.decode("utf-8") + label = label.decode('utf-8') if len(label) == 0: - raise IDNAError("Empty Label") + raise IDNAError('Empty Label') check_nfc(label) check_hyphen_ok(label) check_initial_combiner(label) - for pos, cp in enumerate(label): + for (pos, cp) in enumerate(label): cp_value = ord(cp) - if intranges_contain(cp_value, idnadata.codepoint_classes["PVALID"]): + if intranges_contain(cp_value, idnadata.codepoint_classes['PVALID']): continue - elif intranges_contain(cp_value, idnadata.codepoint_classes["CONTEXTJ"]): + elif intranges_contain(cp_value, idnadata.codepoint_classes['CONTEXTJ']): try: if not valid_contextj(label, pos): - raise InvalidCodepointContext( - "Joiner {} not allowed at position {} in {}".format(_unot(cp_value), pos + 1, repr(label)) - ) + raise InvalidCodepointContext('Joiner {} not allowed at position {} in {}'.format( + _unot(cp_value), pos+1, repr(label))) except ValueError: - raise IDNAError( - "Unknown codepoint adjacent to joiner {} at position {} in {}".format( - _unot(cp_value), pos + 1, repr(label) - ) - ) - elif intranges_contain(cp_value, idnadata.codepoint_classes["CONTEXTO"]): + raise IDNAError('Unknown codepoint adjacent to joiner {} at position {} in {}'.format( + _unot(cp_value), pos+1, repr(label))) + elif intranges_contain(cp_value, idnadata.codepoint_classes['CONTEXTO']): if not valid_contexto(label, pos): - raise InvalidCodepointContext( - "Codepoint {} not allowed at position {} in {}".format(_unot(cp_value), pos + 1, repr(label)) - ) + raise InvalidCodepointContext('Codepoint {} not allowed at position {} in {}'.format(_unot(cp_value), pos+1, repr(label))) else: - raise InvalidCodepoint( - "Codepoint {} at position {} of {} not allowed".format(_unot(cp_value), pos + 1, repr(label)) - ) + raise InvalidCodepoint('Codepoint {} at position {} of {} not allowed'.format(_unot(cp_value), pos+1, repr(label))) check_bidi(label) def alabel(label: str) -> bytes: try: - label_bytes = label.encode("ascii") + label_bytes = label.encode('ascii') ulabel(label_bytes) if not valid_label_length(label_bytes): - raise IDNAError("Label too long") + raise IDNAError('Label too long') return label_bytes except UnicodeEncodeError: pass + if not label: + raise IDNAError('No Input') + + label = str(label) check_label(label) - label_bytes = _alabel_prefix + _punycode(label) + label_bytes = _punycode(label) + label_bytes = _alabel_prefix + label_bytes if not valid_label_length(label_bytes): - raise IDNAError("Label too long") + raise IDNAError('Label too long') return label_bytes @@ -303,7 +279,7 @@ def alabel(label: str) -> bytes: def ulabel(label: Union[str, bytes, bytearray]) -> str: if not isinstance(label, (bytes, bytearray)): try: - label_bytes = label.encode("ascii") + label_bytes = label.encode('ascii') except UnicodeEncodeError: check_label(label) return label @@ -312,19 +288,19 @@ def ulabel(label: Union[str, bytes, bytearray]) -> str: label_bytes = label_bytes.lower() if label_bytes.startswith(_alabel_prefix): - label_bytes = label_bytes[len(_alabel_prefix) :] + label_bytes = label_bytes[len(_alabel_prefix):] if not label_bytes: - raise IDNAError("Malformed A-label, no Punycode eligible content found") - if label_bytes.decode("ascii")[-1] == "-": - raise IDNAError("A-label must not end with a hyphen") + raise IDNAError('Malformed A-label, no Punycode eligible content found') + if label_bytes.decode('ascii')[-1] == '-': + raise IDNAError('A-label must not end with a hyphen') else: check_label(label_bytes) - return label_bytes.decode("ascii") + return label_bytes.decode('ascii') try: - label = label_bytes.decode("punycode") + label = label_bytes.decode('punycode') except UnicodeError: - raise IDNAError("Invalid A-label") + raise IDNAError('Invalid A-label') check_label(label) return label @@ -332,60 +308,52 @@ def ulabel(label: Union[str, bytes, bytearray]) -> str: def uts46_remap(domain: str, std3_rules: bool = True, transitional: bool = False) -> str: """Re-map the characters in the string according to UTS46 processing.""" from .uts46data import uts46data - - output = "" + output = '' for pos, char in enumerate(domain): code_point = ord(char) try: - uts46row = uts46data[code_point if code_point < 256 else bisect.bisect_left(uts46data, (code_point, "Z")) - 1] + uts46row = uts46data[code_point if code_point < 256 else + bisect.bisect_left(uts46data, (code_point, 'Z')) - 1] status = uts46row[1] - replacement: Optional[str] = None + replacement = None # type: Optional[str] if len(uts46row) == 3: - replacement = uts46row[2] - if ( - status == "V" - or (status == "D" and not transitional) - or (status == "3" and not std3_rules and replacement is None) - ): + replacement = uts46row[2] # type: ignore + if (status == 'V' or + (status == 'D' and not transitional) or + (status == '3' and not std3_rules and replacement is None)): output += char - elif replacement is not None and ( - status == "M" or (status == "3" and not std3_rules) or (status == "D" and transitional) - ): + elif replacement is not None and (status == 'M' or + (status == '3' and not std3_rules) or + (status == 'D' and transitional)): output += replacement - elif status != "I": + elif status != 'I': raise IndexError() except IndexError: raise InvalidCodepoint( - "Codepoint {} not allowed at position {} in {}".format(_unot(code_point), pos + 1, repr(domain)) - ) + 'Codepoint {} not allowed at position {} in {}'.format( + _unot(code_point), pos + 1, repr(domain))) - return unicodedata.normalize("NFC", output) + return unicodedata.normalize('NFC', output) -def encode( - s: Union[str, bytes, bytearray], - strict: bool = False, - uts46: bool = False, - std3_rules: bool = False, - transitional: bool = False, -) -> bytes: - if not isinstance(s, str): +def encode(s: Union[str, bytes, bytearray], strict: bool = False, uts46: bool = False, std3_rules: bool = False, transitional: bool = False) -> bytes: + if isinstance(s, (bytes, bytearray)): try: - s = str(s, "ascii") + s = s.decode('ascii') except UnicodeDecodeError: - raise IDNAError("should pass a unicode string to the function rather than a byte string.") + raise IDNAError('should pass a unicode string to the function rather than a byte string.') if uts46: s = uts46_remap(s, std3_rules, transitional) trailing_dot = False result = [] if strict: - labels = s.split(".") + labels = s.split('.') else: labels = _unicode_dots_re.split(s) - if not labels or labels == [""]: - raise IDNAError("Empty domain") - if labels[-1] == "": + if not labels or labels == ['']: + raise IDNAError('Empty domain') + if labels[-1] == '': del labels[-1] trailing_dot = True for label in labels: @@ -393,26 +361,21 @@ def encode( if s: result.append(s) else: - raise IDNAError("Empty label") + raise IDNAError('Empty label') if trailing_dot: - result.append(b"") - s = b".".join(result) + result.append(b'') + s = b'.'.join(result) if not valid_string_length(s, trailing_dot): - raise IDNAError("Domain too long") + raise IDNAError('Domain too long') return s -def decode( - s: Union[str, bytes, bytearray], - strict: bool = False, - uts46: bool = False, - std3_rules: bool = False, -) -> str: +def decode(s: Union[str, bytes, bytearray], strict: bool = False, uts46: bool = False, std3_rules: bool = False) -> str: try: - if not isinstance(s, str): - s = str(s, "ascii") + if isinstance(s, (bytes, bytearray)): + s = s.decode('ascii') except UnicodeDecodeError: - raise IDNAError("Invalid ASCII in A-label") + raise IDNAError('Invalid ASCII in A-label') if uts46: s = uts46_remap(s, std3_rules, False) trailing_dot = False @@ -420,9 +383,9 @@ def decode( if not strict: labels = _unicode_dots_re.split(s) else: - labels = s.split(".") - if not labels or labels == [""]: - raise IDNAError("Empty domain") + labels = s.split('.') + if not labels or labels == ['']: + raise IDNAError('Empty domain') if not labels[-1]: del labels[-1] trailing_dot = True @@ -431,7 +394,7 @@ def decode( if s: result.append(s) else: - raise IDNAError("Empty label") + raise IDNAError('Empty label') if trailing_dot: - result.append("") - return ".".join(result) + result.append('') + return '.'.join(result) diff --git a/venv1/Lib/site-packages/pip/_vendor/idna/idnadata.py b/venv1/Lib/site-packages/pip/_vendor/idna/idnadata.py index 4be60046..67db4625 100644 --- a/venv1/Lib/site-packages/pip/_vendor/idna/idnadata.py +++ b/venv1/Lib/site-packages/pip/_vendor/idna/idnadata.py @@ -1,290 +1,115 @@ # This file is automatically generated by tools/idna-data -__version__ = "15.1.0" +__version__ = '15.0.0' scripts = { - "Greek": ( + 'Greek': ( 0x37000000374, 0x37500000378, - 0x37A0000037E, - 0x37F00000380, + 0x37a0000037e, + 0x37f00000380, 0x38400000385, 0x38600000387, - 0x3880000038B, - 0x38C0000038D, - 0x38E000003A2, - 0x3A3000003E2, - 0x3F000000400, - 0x1D2600001D2B, - 0x1D5D00001D62, - 0x1D6600001D6B, - 0x1DBF00001DC0, - 0x1F0000001F16, - 0x1F1800001F1E, - 0x1F2000001F46, - 0x1F4800001F4E, - 0x1F5000001F58, - 0x1F5900001F5A, - 0x1F5B00001F5C, - 0x1F5D00001F5E, - 0x1F5F00001F7E, - 0x1F8000001FB5, - 0x1FB600001FC5, - 0x1FC600001FD4, - 0x1FD600001FDC, - 0x1FDD00001FF0, - 0x1FF200001FF5, - 0x1FF600001FFF, + 0x3880000038b, + 0x38c0000038d, + 0x38e000003a2, + 0x3a3000003e2, + 0x3f000000400, + 0x1d2600001d2b, + 0x1d5d00001d62, + 0x1d6600001d6b, + 0x1dbf00001dc0, + 0x1f0000001f16, + 0x1f1800001f1e, + 0x1f2000001f46, + 0x1f4800001f4e, + 0x1f5000001f58, + 0x1f5900001f5a, + 0x1f5b00001f5c, + 0x1f5d00001f5e, + 0x1f5f00001f7e, + 0x1f8000001fb5, + 0x1fb600001fc5, + 0x1fc600001fd4, + 0x1fd600001fdc, + 0x1fdd00001ff0, + 0x1ff200001ff5, + 0x1ff600001fff, 0x212600002127, - 0xAB650000AB66, - 0x101400001018F, - 0x101A0000101A1, - 0x1D2000001D246, + 0xab650000ab66, + 0x101400001018f, + 0x101a0000101a1, + 0x1d2000001d246, ), - "Han": ( - 0x2E8000002E9A, - 0x2E9B00002EF4, - 0x2F0000002FD6, + 'Han': ( + 0x2e8000002e9a, + 0x2e9b00002ef4, + 0x2f0000002fd6, 0x300500003006, 0x300700003008, - 0x30210000302A, - 0x30380000303C, - 0x340000004DC0, - 0x4E000000A000, - 0xF9000000FA6E, - 0xFA700000FADA, - 0x16FE200016FE4, - 0x16FF000016FF2, - 0x200000002A6E0, - 0x2A7000002B73A, - 0x2B7400002B81E, - 0x2B8200002CEA2, - 0x2CEB00002EBE1, - 0x2EBF00002EE5E, - 0x2F8000002FA1E, - 0x300000003134B, - 0x31350000323B0, + 0x30210000302a, + 0x30380000303c, + 0x340000004dc0, + 0x4e000000a000, + 0xf9000000fa6e, + 0xfa700000fada, + 0x16fe200016fe4, + 0x16ff000016ff2, + 0x200000002a6e0, + 0x2a7000002b73a, + 0x2b7400002b81e, + 0x2b8200002cea2, + 0x2ceb00002ebe1, + 0x2f8000002fa1e, + 0x300000003134b, + 0x31350000323b0, ), - "Hebrew": ( - 0x591000005C8, - 0x5D0000005EB, - 0x5EF000005F5, - 0xFB1D0000FB37, - 0xFB380000FB3D, - 0xFB3E0000FB3F, - 0xFB400000FB42, - 0xFB430000FB45, - 0xFB460000FB50, + 'Hebrew': ( + 0x591000005c8, + 0x5d0000005eb, + 0x5ef000005f5, + 0xfb1d0000fb37, + 0xfb380000fb3d, + 0xfb3e0000fb3f, + 0xfb400000fb42, + 0xfb430000fb45, + 0xfb460000fb50, ), - "Hiragana": ( + 'Hiragana': ( 0x304100003097, - 0x309D000030A0, - 0x1B0010001B120, - 0x1B1320001B133, - 0x1B1500001B153, - 0x1F2000001F201, + 0x309d000030a0, + 0x1b0010001b120, + 0x1b1320001b133, + 0x1b1500001b153, + 0x1f2000001f201, ), - "Katakana": ( - 0x30A1000030FB, - 0x30FD00003100, - 0x31F000003200, - 0x32D0000032FF, + 'Katakana': ( + 0x30a1000030fb, + 0x30fd00003100, + 0x31f000003200, + 0x32d0000032ff, 0x330000003358, - 0xFF660000FF70, - 0xFF710000FF9E, - 0x1AFF00001AFF4, - 0x1AFF50001AFFC, - 0x1AFFD0001AFFF, - 0x1B0000001B001, - 0x1B1200001B123, - 0x1B1550001B156, - 0x1B1640001B168, + 0xff660000ff70, + 0xff710000ff9e, + 0x1aff00001aff4, + 0x1aff50001affc, + 0x1affd0001afff, + 0x1b0000001b001, + 0x1b1200001b123, + 0x1b1550001b156, + 0x1b1640001b168, ), } joining_types = { - 0xAD: 84, - 0x300: 84, - 0x301: 84, - 0x302: 84, - 0x303: 84, - 0x304: 84, - 0x305: 84, - 0x306: 84, - 0x307: 84, - 0x308: 84, - 0x309: 84, - 0x30A: 84, - 0x30B: 84, - 0x30C: 84, - 0x30D: 84, - 0x30E: 84, - 0x30F: 84, - 0x310: 84, - 0x311: 84, - 0x312: 84, - 0x313: 84, - 0x314: 84, - 0x315: 84, - 0x316: 84, - 0x317: 84, - 0x318: 84, - 0x319: 84, - 0x31A: 84, - 0x31B: 84, - 0x31C: 84, - 0x31D: 84, - 0x31E: 84, - 0x31F: 84, - 0x320: 84, - 0x321: 84, - 0x322: 84, - 0x323: 84, - 0x324: 84, - 0x325: 84, - 0x326: 84, - 0x327: 84, - 0x328: 84, - 0x329: 84, - 0x32A: 84, - 0x32B: 84, - 0x32C: 84, - 0x32D: 84, - 0x32E: 84, - 0x32F: 84, - 0x330: 84, - 0x331: 84, - 0x332: 84, - 0x333: 84, - 0x334: 84, - 0x335: 84, - 0x336: 84, - 0x337: 84, - 0x338: 84, - 0x339: 84, - 0x33A: 84, - 0x33B: 84, - 0x33C: 84, - 0x33D: 84, - 0x33E: 84, - 0x33F: 84, - 0x340: 84, - 0x341: 84, - 0x342: 84, - 0x343: 84, - 0x344: 84, - 0x345: 84, - 0x346: 84, - 0x347: 84, - 0x348: 84, - 0x349: 84, - 0x34A: 84, - 0x34B: 84, - 0x34C: 84, - 0x34D: 84, - 0x34E: 84, - 0x34F: 84, - 0x350: 84, - 0x351: 84, - 0x352: 84, - 0x353: 84, - 0x354: 84, - 0x355: 84, - 0x356: 84, - 0x357: 84, - 0x358: 84, - 0x359: 84, - 0x35A: 84, - 0x35B: 84, - 0x35C: 84, - 0x35D: 84, - 0x35E: 84, - 0x35F: 84, - 0x360: 84, - 0x361: 84, - 0x362: 84, - 0x363: 84, - 0x364: 84, - 0x365: 84, - 0x366: 84, - 0x367: 84, - 0x368: 84, - 0x369: 84, - 0x36A: 84, - 0x36B: 84, - 0x36C: 84, - 0x36D: 84, - 0x36E: 84, - 0x36F: 84, - 0x483: 84, - 0x484: 84, - 0x485: 84, - 0x486: 84, - 0x487: 84, - 0x488: 84, - 0x489: 84, - 0x591: 84, - 0x592: 84, - 0x593: 84, - 0x594: 84, - 0x595: 84, - 0x596: 84, - 0x597: 84, - 0x598: 84, - 0x599: 84, - 0x59A: 84, - 0x59B: 84, - 0x59C: 84, - 0x59D: 84, - 0x59E: 84, - 0x59F: 84, - 0x5A0: 84, - 0x5A1: 84, - 0x5A2: 84, - 0x5A3: 84, - 0x5A4: 84, - 0x5A5: 84, - 0x5A6: 84, - 0x5A7: 84, - 0x5A8: 84, - 0x5A9: 84, - 0x5AA: 84, - 0x5AB: 84, - 0x5AC: 84, - 0x5AD: 84, - 0x5AE: 84, - 0x5AF: 84, - 0x5B0: 84, - 0x5B1: 84, - 0x5B2: 84, - 0x5B3: 84, - 0x5B4: 84, - 0x5B5: 84, - 0x5B6: 84, - 0x5B7: 84, - 0x5B8: 84, - 0x5B9: 84, - 0x5BA: 84, - 0x5BB: 84, - 0x5BC: 84, - 0x5BD: 84, - 0x5BF: 84, - 0x5C1: 84, - 0x5C2: 84, - 0x5C4: 84, - 0x5C5: 84, - 0x5C7: 84, - 0x610: 84, - 0x611: 84, - 0x612: 84, - 0x613: 84, - 0x614: 84, - 0x615: 84, - 0x616: 84, - 0x617: 84, - 0x618: 84, - 0x619: 84, - 0x61A: 84, - 0x61C: 84, + 0x600: 85, + 0x601: 85, + 0x602: 85, + 0x603: 85, + 0x604: 85, + 0x605: 85, + 0x608: 85, + 0x60b: 85, 0x620: 68, + 0x621: 85, 0x622: 82, 0x623: 82, 0x624: 82, @@ -293,12 +118,12 @@ 0x627: 82, 0x628: 68, 0x629: 82, - 0x62A: 68, - 0x62B: 68, - 0x62C: 68, - 0x62D: 68, - 0x62E: 68, - 0x62F: 82, + 0x62a: 68, + 0x62b: 68, + 0x62c: 68, + 0x62d: 68, + 0x62e: 68, + 0x62f: 82, 0x630: 82, 0x631: 82, 0x632: 82, @@ -309,12 +134,12 @@ 0x637: 68, 0x638: 68, 0x639: 68, - 0x63A: 68, - 0x63B: 68, - 0x63C: 68, - 0x63D: 68, - 0x63E: 68, - 0x63F: 68, + 0x63a: 68, + 0x63b: 68, + 0x63c: 68, + 0x63d: 68, + 0x63e: 68, + 0x63f: 68, 0x640: 67, 0x641: 68, 0x642: 68, @@ -325,45 +150,24 @@ 0x647: 68, 0x648: 82, 0x649: 68, - 0x64A: 68, - 0x64B: 84, - 0x64C: 84, - 0x64D: 84, - 0x64E: 84, - 0x64F: 84, - 0x650: 84, - 0x651: 84, - 0x652: 84, - 0x653: 84, - 0x654: 84, - 0x655: 84, - 0x656: 84, - 0x657: 84, - 0x658: 84, - 0x659: 84, - 0x65A: 84, - 0x65B: 84, - 0x65C: 84, - 0x65D: 84, - 0x65E: 84, - 0x65F: 84, - 0x66E: 68, - 0x66F: 68, - 0x670: 84, + 0x64a: 68, + 0x66e: 68, + 0x66f: 68, 0x671: 82, 0x672: 82, 0x673: 82, + 0x674: 85, 0x675: 82, 0x676: 82, 0x677: 82, 0x678: 68, 0x679: 68, - 0x67A: 68, - 0x67B: 68, - 0x67C: 68, - 0x67D: 68, - 0x67E: 68, - 0x67F: 68, + 0x67a: 68, + 0x67b: 68, + 0x67c: 68, + 0x67d: 68, + 0x67e: 68, + 0x67f: 68, 0x680: 68, 0x681: 68, 0x682: 68, @@ -374,12 +178,12 @@ 0x687: 68, 0x688: 82, 0x689: 82, - 0x68A: 82, - 0x68B: 82, - 0x68C: 82, - 0x68D: 82, - 0x68E: 82, - 0x68F: 82, + 0x68a: 82, + 0x68b: 82, + 0x68c: 82, + 0x68d: 82, + 0x68e: 82, + 0x68f: 82, 0x690: 82, 0x691: 82, 0x692: 82, @@ -390,93 +194,74 @@ 0x697: 82, 0x698: 82, 0x699: 82, - 0x69A: 68, - 0x69B: 68, - 0x69C: 68, - 0x69D: 68, - 0x69E: 68, - 0x69F: 68, - 0x6A0: 68, - 0x6A1: 68, - 0x6A2: 68, - 0x6A3: 68, - 0x6A4: 68, - 0x6A5: 68, - 0x6A6: 68, - 0x6A7: 68, - 0x6A8: 68, - 0x6A9: 68, - 0x6AA: 68, - 0x6AB: 68, - 0x6AC: 68, - 0x6AD: 68, - 0x6AE: 68, - 0x6AF: 68, - 0x6B0: 68, - 0x6B1: 68, - 0x6B2: 68, - 0x6B3: 68, - 0x6B4: 68, - 0x6B5: 68, - 0x6B6: 68, - 0x6B7: 68, - 0x6B8: 68, - 0x6B9: 68, - 0x6BA: 68, - 0x6BB: 68, - 0x6BC: 68, - 0x6BD: 68, - 0x6BE: 68, - 0x6BF: 68, - 0x6C0: 82, - 0x6C1: 68, - 0x6C2: 68, - 0x6C3: 82, - 0x6C4: 82, - 0x6C5: 82, - 0x6C6: 82, - 0x6C7: 82, - 0x6C8: 82, - 0x6C9: 82, - 0x6CA: 82, - 0x6CB: 82, - 0x6CC: 68, - 0x6CD: 82, - 0x6CE: 68, - 0x6CF: 82, - 0x6D0: 68, - 0x6D1: 68, - 0x6D2: 82, - 0x6D3: 82, - 0x6D5: 82, - 0x6D6: 84, - 0x6D7: 84, - 0x6D8: 84, - 0x6D9: 84, - 0x6DA: 84, - 0x6DB: 84, - 0x6DC: 84, - 0x6DF: 84, - 0x6E0: 84, - 0x6E1: 84, - 0x6E2: 84, - 0x6E3: 84, - 0x6E4: 84, - 0x6E7: 84, - 0x6E8: 84, - 0x6EA: 84, - 0x6EB: 84, - 0x6EC: 84, - 0x6ED: 84, - 0x6EE: 82, - 0x6EF: 82, - 0x6FA: 68, - 0x6FB: 68, - 0x6FC: 68, - 0x6FF: 68, - 0x70F: 84, + 0x69a: 68, + 0x69b: 68, + 0x69c: 68, + 0x69d: 68, + 0x69e: 68, + 0x69f: 68, + 0x6a0: 68, + 0x6a1: 68, + 0x6a2: 68, + 0x6a3: 68, + 0x6a4: 68, + 0x6a5: 68, + 0x6a6: 68, + 0x6a7: 68, + 0x6a8: 68, + 0x6a9: 68, + 0x6aa: 68, + 0x6ab: 68, + 0x6ac: 68, + 0x6ad: 68, + 0x6ae: 68, + 0x6af: 68, + 0x6b0: 68, + 0x6b1: 68, + 0x6b2: 68, + 0x6b3: 68, + 0x6b4: 68, + 0x6b5: 68, + 0x6b6: 68, + 0x6b7: 68, + 0x6b8: 68, + 0x6b9: 68, + 0x6ba: 68, + 0x6bb: 68, + 0x6bc: 68, + 0x6bd: 68, + 0x6be: 68, + 0x6bf: 68, + 0x6c0: 82, + 0x6c1: 68, + 0x6c2: 68, + 0x6c3: 82, + 0x6c4: 82, + 0x6c5: 82, + 0x6c6: 82, + 0x6c7: 82, + 0x6c8: 82, + 0x6c9: 82, + 0x6ca: 82, + 0x6cb: 82, + 0x6cc: 68, + 0x6cd: 82, + 0x6ce: 68, + 0x6cf: 82, + 0x6d0: 68, + 0x6d1: 68, + 0x6d2: 82, + 0x6d3: 82, + 0x6d5: 82, + 0x6dd: 85, + 0x6ee: 82, + 0x6ef: 82, + 0x6fa: 68, + 0x6fb: 68, + 0x6fc: 68, + 0x6ff: 68, + 0x70f: 84, 0x710: 82, - 0x711: 84, 0x712: 68, 0x713: 68, 0x714: 68, @@ -485,12 +270,12 @@ 0x717: 82, 0x718: 82, 0x719: 82, - 0x71A: 68, - 0x71B: 68, - 0x71C: 68, - 0x71D: 68, - 0x71E: 82, - 0x71F: 68, + 0x71a: 68, + 0x71b: 68, + 0x71c: 68, + 0x71d: 68, + 0x71e: 82, + 0x71f: 68, 0x720: 68, 0x721: 68, 0x722: 68, @@ -501,42 +286,15 @@ 0x727: 68, 0x728: 82, 0x729: 68, - 0x72A: 82, - 0x72B: 68, - 0x72C: 82, - 0x72D: 68, - 0x72E: 68, - 0x72F: 82, - 0x730: 84, - 0x731: 84, - 0x732: 84, - 0x733: 84, - 0x734: 84, - 0x735: 84, - 0x736: 84, - 0x737: 84, - 0x738: 84, - 0x739: 84, - 0x73A: 84, - 0x73B: 84, - 0x73C: 84, - 0x73D: 84, - 0x73E: 84, - 0x73F: 84, - 0x740: 84, - 0x741: 84, - 0x742: 84, - 0x743: 84, - 0x744: 84, - 0x745: 84, - 0x746: 84, - 0x747: 84, - 0x748: 84, - 0x749: 84, - 0x74A: 84, - 0x74D: 82, - 0x74E: 68, - 0x74F: 68, + 0x72a: 82, + 0x72b: 68, + 0x72c: 82, + 0x72d: 68, + 0x72e: 68, + 0x72f: 82, + 0x74d: 82, + 0x74e: 68, + 0x74f: 68, 0x750: 68, 0x751: 68, 0x752: 68, @@ -547,12 +305,12 @@ 0x757: 68, 0x758: 68, 0x759: 82, - 0x75A: 82, - 0x75B: 82, - 0x75C: 68, - 0x75D: 68, - 0x75E: 68, - 0x75F: 68, + 0x75a: 82, + 0x75b: 82, + 0x75c: 68, + 0x75d: 68, + 0x75e: 68, + 0x75f: 68, 0x760: 68, 0x761: 68, 0x762: 68, @@ -563,12 +321,12 @@ 0x767: 68, 0x768: 68, 0x769: 68, - 0x76A: 68, - 0x76B: 82, - 0x76C: 82, - 0x76D: 68, - 0x76E: 68, - 0x76F: 68, + 0x76a: 68, + 0x76b: 82, + 0x76c: 82, + 0x76d: 68, + 0x76e: 68, + 0x76f: 68, 0x770: 68, 0x771: 82, 0x772: 68, @@ -579,88 +337,46 @@ 0x777: 68, 0x778: 82, 0x779: 82, - 0x77A: 68, - 0x77B: 68, - 0x77C: 68, - 0x77D: 68, - 0x77E: 68, - 0x77F: 68, - 0x7A6: 84, - 0x7A7: 84, - 0x7A8: 84, - 0x7A9: 84, - 0x7AA: 84, - 0x7AB: 84, - 0x7AC: 84, - 0x7AD: 84, - 0x7AE: 84, - 0x7AF: 84, - 0x7B0: 84, - 0x7CA: 68, - 0x7CB: 68, - 0x7CC: 68, - 0x7CD: 68, - 0x7CE: 68, - 0x7CF: 68, - 0x7D0: 68, - 0x7D1: 68, - 0x7D2: 68, - 0x7D3: 68, - 0x7D4: 68, - 0x7D5: 68, - 0x7D6: 68, - 0x7D7: 68, - 0x7D8: 68, - 0x7D9: 68, - 0x7DA: 68, - 0x7DB: 68, - 0x7DC: 68, - 0x7DD: 68, - 0x7DE: 68, - 0x7DF: 68, - 0x7E0: 68, - 0x7E1: 68, - 0x7E2: 68, - 0x7E3: 68, - 0x7E4: 68, - 0x7E5: 68, - 0x7E6: 68, - 0x7E7: 68, - 0x7E8: 68, - 0x7E9: 68, - 0x7EA: 68, - 0x7EB: 84, - 0x7EC: 84, - 0x7ED: 84, - 0x7EE: 84, - 0x7EF: 84, - 0x7F0: 84, - 0x7F1: 84, - 0x7F2: 84, - 0x7F3: 84, - 0x7FA: 67, - 0x7FD: 84, - 0x816: 84, - 0x817: 84, - 0x818: 84, - 0x819: 84, - 0x81B: 84, - 0x81C: 84, - 0x81D: 84, - 0x81E: 84, - 0x81F: 84, - 0x820: 84, - 0x821: 84, - 0x822: 84, - 0x823: 84, - 0x825: 84, - 0x826: 84, - 0x827: 84, - 0x829: 84, - 0x82A: 84, - 0x82B: 84, - 0x82C: 84, - 0x82D: 84, + 0x77a: 68, + 0x77b: 68, + 0x77c: 68, + 0x77d: 68, + 0x77e: 68, + 0x77f: 68, + 0x7ca: 68, + 0x7cb: 68, + 0x7cc: 68, + 0x7cd: 68, + 0x7ce: 68, + 0x7cf: 68, + 0x7d0: 68, + 0x7d1: 68, + 0x7d2: 68, + 0x7d3: 68, + 0x7d4: 68, + 0x7d5: 68, + 0x7d6: 68, + 0x7d7: 68, + 0x7d8: 68, + 0x7d9: 68, + 0x7da: 68, + 0x7db: 68, + 0x7dc: 68, + 0x7dd: 68, + 0x7de: 68, + 0x7df: 68, + 0x7e0: 68, + 0x7e1: 68, + 0x7e2: 68, + 0x7e3: 68, + 0x7e4: 68, + 0x7e5: 68, + 0x7e6: 68, + 0x7e7: 68, + 0x7e8: 68, + 0x7e9: 68, + 0x7ea: 68, + 0x7fa: 67, 0x840: 82, 0x841: 68, 0x842: 68, @@ -671,12 +387,12 @@ 0x847: 82, 0x848: 68, 0x849: 82, - 0x84A: 68, - 0x84B: 68, - 0x84C: 68, - 0x84D: 68, - 0x84E: 68, - 0x84F: 68, + 0x84a: 68, + 0x84b: 68, + 0x84c: 68, + 0x84d: 68, + 0x84e: 68, + 0x84f: 68, 0x850: 68, 0x851: 68, 0x852: 68, @@ -686,18 +402,17 @@ 0x856: 82, 0x857: 82, 0x858: 82, - 0x859: 84, - 0x85A: 84, - 0x85B: 84, 0x860: 68, + 0x861: 85, 0x862: 68, 0x863: 68, 0x864: 68, 0x865: 68, + 0x866: 85, 0x867: 82, 0x868: 68, 0x869: 82, - 0x86A: 82, + 0x86a: 82, 0x870: 82, 0x871: 82, 0x872: 82, @@ -708,12 +423,12 @@ 0x877: 82, 0x878: 82, 0x879: 82, - 0x87A: 82, - 0x87B: 82, - 0x87C: 82, - 0x87D: 82, - 0x87E: 82, - 0x87F: 82, + 0x87a: 82, + 0x87b: 82, + 0x87c: 82, + 0x87d: 82, + 0x87e: 82, + 0x87f: 82, 0x880: 82, 0x881: 82, 0x882: 82, @@ -721,411 +436,62 @@ 0x884: 67, 0x885: 67, 0x886: 68, + 0x887: 85, + 0x888: 85, 0x889: 68, - 0x88A: 68, - 0x88B: 68, - 0x88C: 68, - 0x88D: 68, - 0x88E: 82, - 0x898: 84, - 0x899: 84, - 0x89A: 84, - 0x89B: 84, - 0x89C: 84, - 0x89D: 84, - 0x89E: 84, - 0x89F: 84, - 0x8A0: 68, - 0x8A1: 68, - 0x8A2: 68, - 0x8A3: 68, - 0x8A4: 68, - 0x8A5: 68, - 0x8A6: 68, - 0x8A7: 68, - 0x8A8: 68, - 0x8A9: 68, - 0x8AA: 82, - 0x8AB: 82, - 0x8AC: 82, - 0x8AE: 82, - 0x8AF: 68, - 0x8B0: 68, - 0x8B1: 82, - 0x8B2: 82, - 0x8B3: 68, - 0x8B4: 68, - 0x8B5: 68, - 0x8B6: 68, - 0x8B7: 68, - 0x8B8: 68, - 0x8B9: 82, - 0x8BA: 68, - 0x8BB: 68, - 0x8BC: 68, - 0x8BD: 68, - 0x8BE: 68, - 0x8BF: 68, - 0x8C0: 68, - 0x8C1: 68, - 0x8C2: 68, - 0x8C3: 68, - 0x8C4: 68, - 0x8C5: 68, - 0x8C6: 68, - 0x8C7: 68, - 0x8C8: 68, - 0x8CA: 84, - 0x8CB: 84, - 0x8CC: 84, - 0x8CD: 84, - 0x8CE: 84, - 0x8CF: 84, - 0x8D0: 84, - 0x8D1: 84, - 0x8D2: 84, - 0x8D3: 84, - 0x8D4: 84, - 0x8D5: 84, - 0x8D6: 84, - 0x8D7: 84, - 0x8D8: 84, - 0x8D9: 84, - 0x8DA: 84, - 0x8DB: 84, - 0x8DC: 84, - 0x8DD: 84, - 0x8DE: 84, - 0x8DF: 84, - 0x8E0: 84, - 0x8E1: 84, - 0x8E3: 84, - 0x8E4: 84, - 0x8E5: 84, - 0x8E6: 84, - 0x8E7: 84, - 0x8E8: 84, - 0x8E9: 84, - 0x8EA: 84, - 0x8EB: 84, - 0x8EC: 84, - 0x8ED: 84, - 0x8EE: 84, - 0x8EF: 84, - 0x8F0: 84, - 0x8F1: 84, - 0x8F2: 84, - 0x8F3: 84, - 0x8F4: 84, - 0x8F5: 84, - 0x8F6: 84, - 0x8F7: 84, - 0x8F8: 84, - 0x8F9: 84, - 0x8FA: 84, - 0x8FB: 84, - 0x8FC: 84, - 0x8FD: 84, - 0x8FE: 84, - 0x8FF: 84, - 0x900: 84, - 0x901: 84, - 0x902: 84, - 0x93A: 84, - 0x93C: 84, - 0x941: 84, - 0x942: 84, - 0x943: 84, - 0x944: 84, - 0x945: 84, - 0x946: 84, - 0x947: 84, - 0x948: 84, - 0x94D: 84, - 0x951: 84, - 0x952: 84, - 0x953: 84, - 0x954: 84, - 0x955: 84, - 0x956: 84, - 0x957: 84, - 0x962: 84, - 0x963: 84, - 0x981: 84, - 0x9BC: 84, - 0x9C1: 84, - 0x9C2: 84, - 0x9C3: 84, - 0x9C4: 84, - 0x9CD: 84, - 0x9E2: 84, - 0x9E3: 84, - 0x9FE: 84, - 0xA01: 84, - 0xA02: 84, - 0xA3C: 84, - 0xA41: 84, - 0xA42: 84, - 0xA47: 84, - 0xA48: 84, - 0xA4B: 84, - 0xA4C: 84, - 0xA4D: 84, - 0xA51: 84, - 0xA70: 84, - 0xA71: 84, - 0xA75: 84, - 0xA81: 84, - 0xA82: 84, - 0xABC: 84, - 0xAC1: 84, - 0xAC2: 84, - 0xAC3: 84, - 0xAC4: 84, - 0xAC5: 84, - 0xAC7: 84, - 0xAC8: 84, - 0xACD: 84, - 0xAE2: 84, - 0xAE3: 84, - 0xAFA: 84, - 0xAFB: 84, - 0xAFC: 84, - 0xAFD: 84, - 0xAFE: 84, - 0xAFF: 84, - 0xB01: 84, - 0xB3C: 84, - 0xB3F: 84, - 0xB41: 84, - 0xB42: 84, - 0xB43: 84, - 0xB44: 84, - 0xB4D: 84, - 0xB55: 84, - 0xB56: 84, - 0xB62: 84, - 0xB63: 84, - 0xB82: 84, - 0xBC0: 84, - 0xBCD: 84, - 0xC00: 84, - 0xC04: 84, - 0xC3C: 84, - 0xC3E: 84, - 0xC3F: 84, - 0xC40: 84, - 0xC46: 84, - 0xC47: 84, - 0xC48: 84, - 0xC4A: 84, - 0xC4B: 84, - 0xC4C: 84, - 0xC4D: 84, - 0xC55: 84, - 0xC56: 84, - 0xC62: 84, - 0xC63: 84, - 0xC81: 84, - 0xCBC: 84, - 0xCBF: 84, - 0xCC6: 84, - 0xCCC: 84, - 0xCCD: 84, - 0xCE2: 84, - 0xCE3: 84, - 0xD00: 84, - 0xD01: 84, - 0xD3B: 84, - 0xD3C: 84, - 0xD41: 84, - 0xD42: 84, - 0xD43: 84, - 0xD44: 84, - 0xD4D: 84, - 0xD62: 84, - 0xD63: 84, - 0xD81: 84, - 0xDCA: 84, - 0xDD2: 84, - 0xDD3: 84, - 0xDD4: 84, - 0xDD6: 84, - 0xE31: 84, - 0xE34: 84, - 0xE35: 84, - 0xE36: 84, - 0xE37: 84, - 0xE38: 84, - 0xE39: 84, - 0xE3A: 84, - 0xE47: 84, - 0xE48: 84, - 0xE49: 84, - 0xE4A: 84, - 0xE4B: 84, - 0xE4C: 84, - 0xE4D: 84, - 0xE4E: 84, - 0xEB1: 84, - 0xEB4: 84, - 0xEB5: 84, - 0xEB6: 84, - 0xEB7: 84, - 0xEB8: 84, - 0xEB9: 84, - 0xEBA: 84, - 0xEBB: 84, - 0xEBC: 84, - 0xEC8: 84, - 0xEC9: 84, - 0xECA: 84, - 0xECB: 84, - 0xECC: 84, - 0xECD: 84, - 0xECE: 84, - 0xF18: 84, - 0xF19: 84, - 0xF35: 84, - 0xF37: 84, - 0xF39: 84, - 0xF71: 84, - 0xF72: 84, - 0xF73: 84, - 0xF74: 84, - 0xF75: 84, - 0xF76: 84, - 0xF77: 84, - 0xF78: 84, - 0xF79: 84, - 0xF7A: 84, - 0xF7B: 84, - 0xF7C: 84, - 0xF7D: 84, - 0xF7E: 84, - 0xF80: 84, - 0xF81: 84, - 0xF82: 84, - 0xF83: 84, - 0xF84: 84, - 0xF86: 84, - 0xF87: 84, - 0xF8D: 84, - 0xF8E: 84, - 0xF8F: 84, - 0xF90: 84, - 0xF91: 84, - 0xF92: 84, - 0xF93: 84, - 0xF94: 84, - 0xF95: 84, - 0xF96: 84, - 0xF97: 84, - 0xF99: 84, - 0xF9A: 84, - 0xF9B: 84, - 0xF9C: 84, - 0xF9D: 84, - 0xF9E: 84, - 0xF9F: 84, - 0xFA0: 84, - 0xFA1: 84, - 0xFA2: 84, - 0xFA3: 84, - 0xFA4: 84, - 0xFA5: 84, - 0xFA6: 84, - 0xFA7: 84, - 0xFA8: 84, - 0xFA9: 84, - 0xFAA: 84, - 0xFAB: 84, - 0xFAC: 84, - 0xFAD: 84, - 0xFAE: 84, - 0xFAF: 84, - 0xFB0: 84, - 0xFB1: 84, - 0xFB2: 84, - 0xFB3: 84, - 0xFB4: 84, - 0xFB5: 84, - 0xFB6: 84, - 0xFB7: 84, - 0xFB8: 84, - 0xFB9: 84, - 0xFBA: 84, - 0xFBB: 84, - 0xFBC: 84, - 0xFC6: 84, - 0x102D: 84, - 0x102E: 84, - 0x102F: 84, - 0x1030: 84, - 0x1032: 84, - 0x1033: 84, - 0x1034: 84, - 0x1035: 84, - 0x1036: 84, - 0x1037: 84, - 0x1039: 84, - 0x103A: 84, - 0x103D: 84, - 0x103E: 84, - 0x1058: 84, - 0x1059: 84, - 0x105E: 84, - 0x105F: 84, - 0x1060: 84, - 0x1071: 84, - 0x1072: 84, - 0x1073: 84, - 0x1074: 84, - 0x1082: 84, - 0x1085: 84, - 0x1086: 84, - 0x108D: 84, - 0x109D: 84, - 0x135D: 84, - 0x135E: 84, - 0x135F: 84, - 0x1712: 84, - 0x1713: 84, - 0x1714: 84, - 0x1732: 84, - 0x1733: 84, - 0x1752: 84, - 0x1753: 84, - 0x1772: 84, - 0x1773: 84, - 0x17B4: 84, - 0x17B5: 84, - 0x17B7: 84, - 0x17B8: 84, - 0x17B9: 84, - 0x17BA: 84, - 0x17BB: 84, - 0x17BC: 84, - 0x17BD: 84, - 0x17C6: 84, - 0x17C9: 84, - 0x17CA: 84, - 0x17CB: 84, - 0x17CC: 84, - 0x17CD: 84, - 0x17CE: 84, - 0x17CF: 84, - 0x17D0: 84, - 0x17D1: 84, - 0x17D2: 84, - 0x17D3: 84, - 0x17DD: 84, + 0x88a: 68, + 0x88b: 68, + 0x88c: 68, + 0x88d: 68, + 0x88e: 82, + 0x890: 85, + 0x891: 85, + 0x8a0: 68, + 0x8a1: 68, + 0x8a2: 68, + 0x8a3: 68, + 0x8a4: 68, + 0x8a5: 68, + 0x8a6: 68, + 0x8a7: 68, + 0x8a8: 68, + 0x8a9: 68, + 0x8aa: 82, + 0x8ab: 82, + 0x8ac: 82, + 0x8ad: 85, + 0x8ae: 82, + 0x8af: 68, + 0x8b0: 68, + 0x8b1: 82, + 0x8b2: 82, + 0x8b3: 68, + 0x8b4: 68, + 0x8b5: 68, + 0x8b6: 68, + 0x8b7: 68, + 0x8b8: 68, + 0x8b9: 82, + 0x8ba: 68, + 0x8bb: 68, + 0x8bc: 68, + 0x8bd: 68, + 0x8be: 68, + 0x8bf: 68, + 0x8c0: 68, + 0x8c1: 68, + 0x8c2: 68, + 0x8c3: 68, + 0x8c4: 68, + 0x8c5: 68, + 0x8c6: 68, + 0x8c7: 68, + 0x8c8: 68, + 0x8e2: 85, + 0x1806: 85, 0x1807: 68, - 0x180A: 67, - 0x180B: 84, - 0x180C: 84, - 0x180D: 84, - 0x180F: 84, + 0x180a: 67, + 0x180e: 85, 0x1820: 68, 0x1821: 68, 0x1822: 68, @@ -1136,12 +502,12 @@ 0x1827: 68, 0x1828: 68, 0x1829: 68, - 0x182A: 68, - 0x182B: 68, - 0x182C: 68, - 0x182D: 68, - 0x182E: 68, - 0x182F: 68, + 0x182a: 68, + 0x182b: 68, + 0x182c: 68, + 0x182d: 68, + 0x182e: 68, + 0x182f: 68, 0x1830: 68, 0x1831: 68, 0x1832: 68, @@ -1152,12 +518,12 @@ 0x1837: 68, 0x1838: 68, 0x1839: 68, - 0x183A: 68, - 0x183B: 68, - 0x183C: 68, - 0x183D: 68, - 0x183E: 68, - 0x183F: 68, + 0x183a: 68, + 0x183b: 68, + 0x183c: 68, + 0x183d: 68, + 0x183e: 68, + 0x183f: 68, 0x1840: 68, 0x1841: 68, 0x1842: 68, @@ -1168,12 +534,12 @@ 0x1847: 68, 0x1848: 68, 0x1849: 68, - 0x184A: 68, - 0x184B: 68, - 0x184C: 68, - 0x184D: 68, - 0x184E: 68, - 0x184F: 68, + 0x184a: 68, + 0x184b: 68, + 0x184c: 68, + 0x184d: 68, + 0x184e: 68, + 0x184f: 68, 0x1850: 68, 0x1851: 68, 0x1852: 68, @@ -1184,12 +550,12 @@ 0x1857: 68, 0x1858: 68, 0x1859: 68, - 0x185A: 68, - 0x185B: 68, - 0x185C: 68, - 0x185D: 68, - 0x185E: 68, - 0x185F: 68, + 0x185a: 68, + 0x185b: 68, + 0x185c: 68, + 0x185d: 68, + 0x185e: 68, + 0x185f: 68, 0x1860: 68, 0x1861: 68, 0x1862: 68, @@ -1200,12 +566,12 @@ 0x1867: 68, 0x1868: 68, 0x1869: 68, - 0x186A: 68, - 0x186B: 68, - 0x186C: 68, - 0x186D: 68, - 0x186E: 68, - 0x186F: 68, + 0x186a: 68, + 0x186b: 68, + 0x186c: 68, + 0x186d: 68, + 0x186e: 68, + 0x186f: 68, 0x1870: 68, 0x1871: 68, 0x1872: 68, @@ -1215,17 +581,22 @@ 0x1876: 68, 0x1877: 68, 0x1878: 68, + 0x1880: 85, + 0x1881: 85, + 0x1882: 85, + 0x1883: 85, + 0x1884: 85, 0x1885: 84, 0x1886: 84, 0x1887: 68, 0x1888: 68, 0x1889: 68, - 0x188A: 68, - 0x188B: 68, - 0x188C: 68, - 0x188D: 68, - 0x188E: 68, - 0x188F: 68, + 0x188a: 68, + 0x188b: 68, + 0x188c: 68, + 0x188d: 68, + 0x188e: 68, + 0x188f: 68, 0x1890: 68, 0x1891: 68, 0x1892: 68, @@ -1236,3008 +607,1545 @@ 0x1897: 68, 0x1898: 68, 0x1899: 68, - 0x189A: 68, - 0x189B: 68, - 0x189C: 68, - 0x189D: 68, - 0x189E: 68, - 0x189F: 68, - 0x18A0: 68, - 0x18A1: 68, - 0x18A2: 68, - 0x18A3: 68, - 0x18A4: 68, - 0x18A5: 68, - 0x18A6: 68, - 0x18A7: 68, - 0x18A8: 68, - 0x18A9: 84, - 0x18AA: 68, - 0x1920: 84, - 0x1921: 84, - 0x1922: 84, - 0x1927: 84, - 0x1928: 84, - 0x1932: 84, - 0x1939: 84, - 0x193A: 84, - 0x193B: 84, - 0x1A17: 84, - 0x1A18: 84, - 0x1A1B: 84, - 0x1A56: 84, - 0x1A58: 84, - 0x1A59: 84, - 0x1A5A: 84, - 0x1A5B: 84, - 0x1A5C: 84, - 0x1A5D: 84, - 0x1A5E: 84, - 0x1A60: 84, - 0x1A62: 84, - 0x1A65: 84, - 0x1A66: 84, - 0x1A67: 84, - 0x1A68: 84, - 0x1A69: 84, - 0x1A6A: 84, - 0x1A6B: 84, - 0x1A6C: 84, - 0x1A73: 84, - 0x1A74: 84, - 0x1A75: 84, - 0x1A76: 84, - 0x1A77: 84, - 0x1A78: 84, - 0x1A79: 84, - 0x1A7A: 84, - 0x1A7B: 84, - 0x1A7C: 84, - 0x1A7F: 84, - 0x1AB0: 84, - 0x1AB1: 84, - 0x1AB2: 84, - 0x1AB3: 84, - 0x1AB4: 84, - 0x1AB5: 84, - 0x1AB6: 84, - 0x1AB7: 84, - 0x1AB8: 84, - 0x1AB9: 84, - 0x1ABA: 84, - 0x1ABB: 84, - 0x1ABC: 84, - 0x1ABD: 84, - 0x1ABE: 84, - 0x1ABF: 84, - 0x1AC0: 84, - 0x1AC1: 84, - 0x1AC2: 84, - 0x1AC3: 84, - 0x1AC4: 84, - 0x1AC5: 84, - 0x1AC6: 84, - 0x1AC7: 84, - 0x1AC8: 84, - 0x1AC9: 84, - 0x1ACA: 84, - 0x1ACB: 84, - 0x1ACC: 84, - 0x1ACD: 84, - 0x1ACE: 84, - 0x1B00: 84, - 0x1B01: 84, - 0x1B02: 84, - 0x1B03: 84, - 0x1B34: 84, - 0x1B36: 84, - 0x1B37: 84, - 0x1B38: 84, - 0x1B39: 84, - 0x1B3A: 84, - 0x1B3C: 84, - 0x1B42: 84, - 0x1B6B: 84, - 0x1B6C: 84, - 0x1B6D: 84, - 0x1B6E: 84, - 0x1B6F: 84, - 0x1B70: 84, - 0x1B71: 84, - 0x1B72: 84, - 0x1B73: 84, - 0x1B80: 84, - 0x1B81: 84, - 0x1BA2: 84, - 0x1BA3: 84, - 0x1BA4: 84, - 0x1BA5: 84, - 0x1BA8: 84, - 0x1BA9: 84, - 0x1BAB: 84, - 0x1BAC: 84, - 0x1BAD: 84, - 0x1BE6: 84, - 0x1BE8: 84, - 0x1BE9: 84, - 0x1BED: 84, - 0x1BEF: 84, - 0x1BF0: 84, - 0x1BF1: 84, - 0x1C2C: 84, - 0x1C2D: 84, - 0x1C2E: 84, - 0x1C2F: 84, - 0x1C30: 84, - 0x1C31: 84, - 0x1C32: 84, - 0x1C33: 84, - 0x1C36: 84, - 0x1C37: 84, - 0x1CD0: 84, - 0x1CD1: 84, - 0x1CD2: 84, - 0x1CD4: 84, - 0x1CD5: 84, - 0x1CD6: 84, - 0x1CD7: 84, - 0x1CD8: 84, - 0x1CD9: 84, - 0x1CDA: 84, - 0x1CDB: 84, - 0x1CDC: 84, - 0x1CDD: 84, - 0x1CDE: 84, - 0x1CDF: 84, - 0x1CE0: 84, - 0x1CE2: 84, - 0x1CE3: 84, - 0x1CE4: 84, - 0x1CE5: 84, - 0x1CE6: 84, - 0x1CE7: 84, - 0x1CE8: 84, - 0x1CED: 84, - 0x1CF4: 84, - 0x1CF8: 84, - 0x1CF9: 84, - 0x1DC0: 84, - 0x1DC1: 84, - 0x1DC2: 84, - 0x1DC3: 84, - 0x1DC4: 84, - 0x1DC5: 84, - 0x1DC6: 84, - 0x1DC7: 84, - 0x1DC8: 84, - 0x1DC9: 84, - 0x1DCA: 84, - 0x1DCB: 84, - 0x1DCC: 84, - 0x1DCD: 84, - 0x1DCE: 84, - 0x1DCF: 84, - 0x1DD0: 84, - 0x1DD1: 84, - 0x1DD2: 84, - 0x1DD3: 84, - 0x1DD4: 84, - 0x1DD5: 84, - 0x1DD6: 84, - 0x1DD7: 84, - 0x1DD8: 84, - 0x1DD9: 84, - 0x1DDA: 84, - 0x1DDB: 84, - 0x1DDC: 84, - 0x1DDD: 84, - 0x1DDE: 84, - 0x1DDF: 84, - 0x1DE0: 84, - 0x1DE1: 84, - 0x1DE2: 84, - 0x1DE3: 84, - 0x1DE4: 84, - 0x1DE5: 84, - 0x1DE6: 84, - 0x1DE7: 84, - 0x1DE8: 84, - 0x1DE9: 84, - 0x1DEA: 84, - 0x1DEB: 84, - 0x1DEC: 84, - 0x1DED: 84, - 0x1DEE: 84, - 0x1DEF: 84, - 0x1DF0: 84, - 0x1DF1: 84, - 0x1DF2: 84, - 0x1DF3: 84, - 0x1DF4: 84, - 0x1DF5: 84, - 0x1DF6: 84, - 0x1DF7: 84, - 0x1DF8: 84, - 0x1DF9: 84, - 0x1DFA: 84, - 0x1DFB: 84, - 0x1DFC: 84, - 0x1DFD: 84, - 0x1DFE: 84, - 0x1DFF: 84, - 0x200B: 84, - 0x200D: 67, - 0x200E: 84, - 0x200F: 84, - 0x202A: 84, - 0x202B: 84, - 0x202C: 84, - 0x202D: 84, - 0x202E: 84, - 0x2060: 84, - 0x2061: 84, - 0x2062: 84, - 0x2063: 84, - 0x2064: 84, - 0x206A: 84, - 0x206B: 84, - 0x206C: 84, - 0x206D: 84, - 0x206E: 84, - 0x206F: 84, - 0x20D0: 84, - 0x20D1: 84, - 0x20D2: 84, - 0x20D3: 84, - 0x20D4: 84, - 0x20D5: 84, - 0x20D6: 84, - 0x20D7: 84, - 0x20D8: 84, - 0x20D9: 84, - 0x20DA: 84, - 0x20DB: 84, - 0x20DC: 84, - 0x20DD: 84, - 0x20DE: 84, - 0x20DF: 84, - 0x20E0: 84, - 0x20E1: 84, - 0x20E2: 84, - 0x20E3: 84, - 0x20E4: 84, - 0x20E5: 84, - 0x20E6: 84, - 0x20E7: 84, - 0x20E8: 84, - 0x20E9: 84, - 0x20EA: 84, - 0x20EB: 84, - 0x20EC: 84, - 0x20ED: 84, - 0x20EE: 84, - 0x20EF: 84, - 0x20F0: 84, - 0x2CEF: 84, - 0x2CF0: 84, - 0x2CF1: 84, - 0x2D7F: 84, - 0x2DE0: 84, - 0x2DE1: 84, - 0x2DE2: 84, - 0x2DE3: 84, - 0x2DE4: 84, - 0x2DE5: 84, - 0x2DE6: 84, - 0x2DE7: 84, - 0x2DE8: 84, - 0x2DE9: 84, - 0x2DEA: 84, - 0x2DEB: 84, - 0x2DEC: 84, - 0x2DED: 84, - 0x2DEE: 84, - 0x2DEF: 84, - 0x2DF0: 84, - 0x2DF1: 84, - 0x2DF2: 84, - 0x2DF3: 84, - 0x2DF4: 84, - 0x2DF5: 84, - 0x2DF6: 84, - 0x2DF7: 84, - 0x2DF8: 84, - 0x2DF9: 84, - 0x2DFA: 84, - 0x2DFB: 84, - 0x2DFC: 84, - 0x2DFD: 84, - 0x2DFE: 84, - 0x2DFF: 84, - 0x302A: 84, - 0x302B: 84, - 0x302C: 84, - 0x302D: 84, - 0x3099: 84, - 0x309A: 84, - 0xA66F: 84, - 0xA670: 84, - 0xA671: 84, - 0xA672: 84, - 0xA674: 84, - 0xA675: 84, - 0xA676: 84, - 0xA677: 84, - 0xA678: 84, - 0xA679: 84, - 0xA67A: 84, - 0xA67B: 84, - 0xA67C: 84, - 0xA67D: 84, - 0xA69E: 84, - 0xA69F: 84, - 0xA6F0: 84, - 0xA6F1: 84, - 0xA802: 84, - 0xA806: 84, - 0xA80B: 84, - 0xA825: 84, - 0xA826: 84, - 0xA82C: 84, - 0xA840: 68, - 0xA841: 68, - 0xA842: 68, - 0xA843: 68, - 0xA844: 68, - 0xA845: 68, - 0xA846: 68, - 0xA847: 68, - 0xA848: 68, - 0xA849: 68, - 0xA84A: 68, - 0xA84B: 68, - 0xA84C: 68, - 0xA84D: 68, - 0xA84E: 68, - 0xA84F: 68, - 0xA850: 68, - 0xA851: 68, - 0xA852: 68, - 0xA853: 68, - 0xA854: 68, - 0xA855: 68, - 0xA856: 68, - 0xA857: 68, - 0xA858: 68, - 0xA859: 68, - 0xA85A: 68, - 0xA85B: 68, - 0xA85C: 68, - 0xA85D: 68, - 0xA85E: 68, - 0xA85F: 68, - 0xA860: 68, - 0xA861: 68, - 0xA862: 68, - 0xA863: 68, - 0xA864: 68, - 0xA865: 68, - 0xA866: 68, - 0xA867: 68, - 0xA868: 68, - 0xA869: 68, - 0xA86A: 68, - 0xA86B: 68, - 0xA86C: 68, - 0xA86D: 68, - 0xA86E: 68, - 0xA86F: 68, - 0xA870: 68, - 0xA871: 68, - 0xA872: 76, - 0xA8C4: 84, - 0xA8C5: 84, - 0xA8E0: 84, - 0xA8E1: 84, - 0xA8E2: 84, - 0xA8E3: 84, - 0xA8E4: 84, - 0xA8E5: 84, - 0xA8E6: 84, - 0xA8E7: 84, - 0xA8E8: 84, - 0xA8E9: 84, - 0xA8EA: 84, - 0xA8EB: 84, - 0xA8EC: 84, - 0xA8ED: 84, - 0xA8EE: 84, - 0xA8EF: 84, - 0xA8F0: 84, - 0xA8F1: 84, - 0xA8FF: 84, - 0xA926: 84, - 0xA927: 84, - 0xA928: 84, - 0xA929: 84, - 0xA92A: 84, - 0xA92B: 84, - 0xA92C: 84, - 0xA92D: 84, - 0xA947: 84, - 0xA948: 84, - 0xA949: 84, - 0xA94A: 84, - 0xA94B: 84, - 0xA94C: 84, - 0xA94D: 84, - 0xA94E: 84, - 0xA94F: 84, - 0xA950: 84, - 0xA951: 84, - 0xA980: 84, - 0xA981: 84, - 0xA982: 84, - 0xA9B3: 84, - 0xA9B6: 84, - 0xA9B7: 84, - 0xA9B8: 84, - 0xA9B9: 84, - 0xA9BC: 84, - 0xA9BD: 84, - 0xA9E5: 84, - 0xAA29: 84, - 0xAA2A: 84, - 0xAA2B: 84, - 0xAA2C: 84, - 0xAA2D: 84, - 0xAA2E: 84, - 0xAA31: 84, - 0xAA32: 84, - 0xAA35: 84, - 0xAA36: 84, - 0xAA43: 84, - 0xAA4C: 84, - 0xAA7C: 84, - 0xAAB0: 84, - 0xAAB2: 84, - 0xAAB3: 84, - 0xAAB4: 84, - 0xAAB7: 84, - 0xAAB8: 84, - 0xAABE: 84, - 0xAABF: 84, - 0xAAC1: 84, - 0xAAEC: 84, - 0xAAED: 84, - 0xAAF6: 84, - 0xABE5: 84, - 0xABE8: 84, - 0xABED: 84, - 0xFB1E: 84, - 0xFE00: 84, - 0xFE01: 84, - 0xFE02: 84, - 0xFE03: 84, - 0xFE04: 84, - 0xFE05: 84, - 0xFE06: 84, - 0xFE07: 84, - 0xFE08: 84, - 0xFE09: 84, - 0xFE0A: 84, - 0xFE0B: 84, - 0xFE0C: 84, - 0xFE0D: 84, - 0xFE0E: 84, - 0xFE0F: 84, - 0xFE20: 84, - 0xFE21: 84, - 0xFE22: 84, - 0xFE23: 84, - 0xFE24: 84, - 0xFE25: 84, - 0xFE26: 84, - 0xFE27: 84, - 0xFE28: 84, - 0xFE29: 84, - 0xFE2A: 84, - 0xFE2B: 84, - 0xFE2C: 84, - 0xFE2D: 84, - 0xFE2E: 84, - 0xFE2F: 84, - 0xFEFF: 84, - 0xFFF9: 84, - 0xFFFA: 84, - 0xFFFB: 84, - 0x101FD: 84, - 0x102E0: 84, - 0x10376: 84, - 0x10377: 84, - 0x10378: 84, - 0x10379: 84, - 0x1037A: 84, - 0x10A01: 84, - 0x10A02: 84, - 0x10A03: 84, - 0x10A05: 84, - 0x10A06: 84, - 0x10A0C: 84, - 0x10A0D: 84, - 0x10A0E: 84, - 0x10A0F: 84, - 0x10A38: 84, - 0x10A39: 84, - 0x10A3A: 84, - 0x10A3F: 84, - 0x10AC0: 68, - 0x10AC1: 68, - 0x10AC2: 68, - 0x10AC3: 68, - 0x10AC4: 68, - 0x10AC5: 82, - 0x10AC7: 82, - 0x10AC9: 82, - 0x10ACA: 82, - 0x10ACD: 76, - 0x10ACE: 82, - 0x10ACF: 82, - 0x10AD0: 82, - 0x10AD1: 82, - 0x10AD2: 82, - 0x10AD3: 68, - 0x10AD4: 68, - 0x10AD5: 68, - 0x10AD6: 68, - 0x10AD7: 76, - 0x10AD8: 68, - 0x10AD9: 68, - 0x10ADA: 68, - 0x10ADB: 68, - 0x10ADC: 68, - 0x10ADD: 82, - 0x10ADE: 68, - 0x10ADF: 68, - 0x10AE0: 68, - 0x10AE1: 82, - 0x10AE4: 82, - 0x10AE5: 84, - 0x10AE6: 84, - 0x10AEB: 68, - 0x10AEC: 68, - 0x10AED: 68, - 0x10AEE: 68, - 0x10AEF: 82, - 0x10B80: 68, - 0x10B81: 82, - 0x10B82: 68, - 0x10B83: 82, - 0x10B84: 82, - 0x10B85: 82, - 0x10B86: 68, - 0x10B87: 68, - 0x10B88: 68, - 0x10B89: 82, - 0x10B8A: 68, - 0x10B8B: 68, - 0x10B8C: 82, - 0x10B8D: 68, - 0x10B8E: 82, - 0x10B8F: 82, - 0x10B90: 68, - 0x10B91: 82, - 0x10BA9: 82, - 0x10BAA: 82, - 0x10BAB: 82, - 0x10BAC: 82, - 0x10BAD: 68, - 0x10BAE: 68, - 0x10D00: 76, - 0x10D01: 68, - 0x10D02: 68, - 0x10D03: 68, - 0x10D04: 68, - 0x10D05: 68, - 0x10D06: 68, - 0x10D07: 68, - 0x10D08: 68, - 0x10D09: 68, - 0x10D0A: 68, - 0x10D0B: 68, - 0x10D0C: 68, - 0x10D0D: 68, - 0x10D0E: 68, - 0x10D0F: 68, - 0x10D10: 68, - 0x10D11: 68, - 0x10D12: 68, - 0x10D13: 68, - 0x10D14: 68, - 0x10D15: 68, - 0x10D16: 68, - 0x10D17: 68, - 0x10D18: 68, - 0x10D19: 68, - 0x10D1A: 68, - 0x10D1B: 68, - 0x10D1C: 68, - 0x10D1D: 68, - 0x10D1E: 68, - 0x10D1F: 68, - 0x10D20: 68, - 0x10D21: 68, - 0x10D22: 82, - 0x10D23: 68, - 0x10D24: 84, - 0x10D25: 84, - 0x10D26: 84, - 0x10D27: 84, - 0x10EAB: 84, - 0x10EAC: 84, - 0x10EFD: 84, - 0x10EFE: 84, - 0x10EFF: 84, - 0x10F30: 68, - 0x10F31: 68, - 0x10F32: 68, - 0x10F33: 82, - 0x10F34: 68, - 0x10F35: 68, - 0x10F36: 68, - 0x10F37: 68, - 0x10F38: 68, - 0x10F39: 68, - 0x10F3A: 68, - 0x10F3B: 68, - 0x10F3C: 68, - 0x10F3D: 68, - 0x10F3E: 68, - 0x10F3F: 68, - 0x10F40: 68, - 0x10F41: 68, - 0x10F42: 68, - 0x10F43: 68, - 0x10F44: 68, - 0x10F46: 84, - 0x10F47: 84, - 0x10F48: 84, - 0x10F49: 84, - 0x10F4A: 84, - 0x10F4B: 84, - 0x10F4C: 84, - 0x10F4D: 84, - 0x10F4E: 84, - 0x10F4F: 84, - 0x10F50: 84, - 0x10F51: 68, - 0x10F52: 68, - 0x10F53: 68, - 0x10F54: 82, - 0x10F70: 68, - 0x10F71: 68, - 0x10F72: 68, - 0x10F73: 68, - 0x10F74: 82, - 0x10F75: 82, - 0x10F76: 68, - 0x10F77: 68, - 0x10F78: 68, - 0x10F79: 68, - 0x10F7A: 68, - 0x10F7B: 68, - 0x10F7C: 68, - 0x10F7D: 68, - 0x10F7E: 68, - 0x10F7F: 68, - 0x10F80: 68, - 0x10F81: 68, - 0x10F82: 84, - 0x10F83: 84, - 0x10F84: 84, - 0x10F85: 84, - 0x10FB0: 68, - 0x10FB2: 68, - 0x10FB3: 68, - 0x10FB4: 82, - 0x10FB5: 82, - 0x10FB6: 82, - 0x10FB8: 68, - 0x10FB9: 82, - 0x10FBA: 82, - 0x10FBB: 68, - 0x10FBC: 68, - 0x10FBD: 82, - 0x10FBE: 68, - 0x10FBF: 68, - 0x10FC1: 68, - 0x10FC2: 82, - 0x10FC3: 82, - 0x10FC4: 68, - 0x10FC9: 82, - 0x10FCA: 68, - 0x10FCB: 76, - 0x11001: 84, - 0x11038: 84, - 0x11039: 84, - 0x1103A: 84, - 0x1103B: 84, - 0x1103C: 84, - 0x1103D: 84, - 0x1103E: 84, - 0x1103F: 84, - 0x11040: 84, - 0x11041: 84, - 0x11042: 84, - 0x11043: 84, - 0x11044: 84, - 0x11045: 84, - 0x11046: 84, - 0x11070: 84, - 0x11073: 84, - 0x11074: 84, - 0x1107F: 84, - 0x11080: 84, - 0x11081: 84, - 0x110B3: 84, - 0x110B4: 84, - 0x110B5: 84, - 0x110B6: 84, - 0x110B9: 84, - 0x110BA: 84, - 0x110C2: 84, - 0x11100: 84, - 0x11101: 84, - 0x11102: 84, - 0x11127: 84, - 0x11128: 84, - 0x11129: 84, - 0x1112A: 84, - 0x1112B: 84, - 0x1112D: 84, - 0x1112E: 84, - 0x1112F: 84, - 0x11130: 84, - 0x11131: 84, - 0x11132: 84, - 0x11133: 84, - 0x11134: 84, - 0x11173: 84, - 0x11180: 84, - 0x11181: 84, - 0x111B6: 84, - 0x111B7: 84, - 0x111B8: 84, - 0x111B9: 84, - 0x111BA: 84, - 0x111BB: 84, - 0x111BC: 84, - 0x111BD: 84, - 0x111BE: 84, - 0x111C9: 84, - 0x111CA: 84, - 0x111CB: 84, - 0x111CC: 84, - 0x111CF: 84, - 0x1122F: 84, - 0x11230: 84, - 0x11231: 84, - 0x11234: 84, - 0x11236: 84, - 0x11237: 84, - 0x1123E: 84, - 0x11241: 84, - 0x112DF: 84, - 0x112E3: 84, - 0x112E4: 84, - 0x112E5: 84, - 0x112E6: 84, - 0x112E7: 84, - 0x112E8: 84, - 0x112E9: 84, - 0x112EA: 84, - 0x11300: 84, - 0x11301: 84, - 0x1133B: 84, - 0x1133C: 84, - 0x11340: 84, - 0x11366: 84, - 0x11367: 84, - 0x11368: 84, - 0x11369: 84, - 0x1136A: 84, - 0x1136B: 84, - 0x1136C: 84, - 0x11370: 84, - 0x11371: 84, - 0x11372: 84, - 0x11373: 84, - 0x11374: 84, - 0x11438: 84, - 0x11439: 84, - 0x1143A: 84, - 0x1143B: 84, - 0x1143C: 84, - 0x1143D: 84, - 0x1143E: 84, - 0x1143F: 84, - 0x11442: 84, - 0x11443: 84, - 0x11444: 84, - 0x11446: 84, - 0x1145E: 84, - 0x114B3: 84, - 0x114B4: 84, - 0x114B5: 84, - 0x114B6: 84, - 0x114B7: 84, - 0x114B8: 84, - 0x114BA: 84, - 0x114BF: 84, - 0x114C0: 84, - 0x114C2: 84, - 0x114C3: 84, - 0x115B2: 84, - 0x115B3: 84, - 0x115B4: 84, - 0x115B5: 84, - 0x115BC: 84, - 0x115BD: 84, - 0x115BF: 84, - 0x115C0: 84, - 0x115DC: 84, - 0x115DD: 84, - 0x11633: 84, - 0x11634: 84, - 0x11635: 84, - 0x11636: 84, - 0x11637: 84, - 0x11638: 84, - 0x11639: 84, - 0x1163A: 84, - 0x1163D: 84, - 0x1163F: 84, - 0x11640: 84, - 0x116AB: 84, - 0x116AD: 84, - 0x116B0: 84, - 0x116B1: 84, - 0x116B2: 84, - 0x116B3: 84, - 0x116B4: 84, - 0x116B5: 84, - 0x116B7: 84, - 0x1171D: 84, - 0x1171E: 84, - 0x1171F: 84, - 0x11722: 84, - 0x11723: 84, - 0x11724: 84, - 0x11725: 84, - 0x11727: 84, - 0x11728: 84, - 0x11729: 84, - 0x1172A: 84, - 0x1172B: 84, - 0x1182F: 84, - 0x11830: 84, - 0x11831: 84, - 0x11832: 84, - 0x11833: 84, - 0x11834: 84, - 0x11835: 84, - 0x11836: 84, - 0x11837: 84, - 0x11839: 84, - 0x1183A: 84, - 0x1193B: 84, - 0x1193C: 84, - 0x1193E: 84, - 0x11943: 84, - 0x119D4: 84, - 0x119D5: 84, - 0x119D6: 84, - 0x119D7: 84, - 0x119DA: 84, - 0x119DB: 84, - 0x119E0: 84, - 0x11A01: 84, - 0x11A02: 84, - 0x11A03: 84, - 0x11A04: 84, - 0x11A05: 84, - 0x11A06: 84, - 0x11A07: 84, - 0x11A08: 84, - 0x11A09: 84, - 0x11A0A: 84, - 0x11A33: 84, - 0x11A34: 84, - 0x11A35: 84, - 0x11A36: 84, - 0x11A37: 84, - 0x11A38: 84, - 0x11A3B: 84, - 0x11A3C: 84, - 0x11A3D: 84, - 0x11A3E: 84, - 0x11A47: 84, - 0x11A51: 84, - 0x11A52: 84, - 0x11A53: 84, - 0x11A54: 84, - 0x11A55: 84, - 0x11A56: 84, - 0x11A59: 84, - 0x11A5A: 84, - 0x11A5B: 84, - 0x11A8A: 84, - 0x11A8B: 84, - 0x11A8C: 84, - 0x11A8D: 84, - 0x11A8E: 84, - 0x11A8F: 84, - 0x11A90: 84, - 0x11A91: 84, - 0x11A92: 84, - 0x11A93: 84, - 0x11A94: 84, - 0x11A95: 84, - 0x11A96: 84, - 0x11A98: 84, - 0x11A99: 84, - 0x11C30: 84, - 0x11C31: 84, - 0x11C32: 84, - 0x11C33: 84, - 0x11C34: 84, - 0x11C35: 84, - 0x11C36: 84, - 0x11C38: 84, - 0x11C39: 84, - 0x11C3A: 84, - 0x11C3B: 84, - 0x11C3C: 84, - 0x11C3D: 84, - 0x11C3F: 84, - 0x11C92: 84, - 0x11C93: 84, - 0x11C94: 84, - 0x11C95: 84, - 0x11C96: 84, - 0x11C97: 84, - 0x11C98: 84, - 0x11C99: 84, - 0x11C9A: 84, - 0x11C9B: 84, - 0x11C9C: 84, - 0x11C9D: 84, - 0x11C9E: 84, - 0x11C9F: 84, - 0x11CA0: 84, - 0x11CA1: 84, - 0x11CA2: 84, - 0x11CA3: 84, - 0x11CA4: 84, - 0x11CA5: 84, - 0x11CA6: 84, - 0x11CA7: 84, - 0x11CAA: 84, - 0x11CAB: 84, - 0x11CAC: 84, - 0x11CAD: 84, - 0x11CAE: 84, - 0x11CAF: 84, - 0x11CB0: 84, - 0x11CB2: 84, - 0x11CB3: 84, - 0x11CB5: 84, - 0x11CB6: 84, - 0x11D31: 84, - 0x11D32: 84, - 0x11D33: 84, - 0x11D34: 84, - 0x11D35: 84, - 0x11D36: 84, - 0x11D3A: 84, - 0x11D3C: 84, - 0x11D3D: 84, - 0x11D3F: 84, - 0x11D40: 84, - 0x11D41: 84, - 0x11D42: 84, - 0x11D43: 84, - 0x11D44: 84, - 0x11D45: 84, - 0x11D47: 84, - 0x11D90: 84, - 0x11D91: 84, - 0x11D95: 84, - 0x11D97: 84, - 0x11EF3: 84, - 0x11EF4: 84, - 0x11F00: 84, - 0x11F01: 84, - 0x11F36: 84, - 0x11F37: 84, - 0x11F38: 84, - 0x11F39: 84, - 0x11F3A: 84, - 0x11F40: 84, - 0x11F42: 84, - 0x13430: 84, - 0x13431: 84, - 0x13432: 84, - 0x13433: 84, - 0x13434: 84, - 0x13435: 84, - 0x13436: 84, - 0x13437: 84, - 0x13438: 84, - 0x13439: 84, - 0x1343A: 84, - 0x1343B: 84, - 0x1343C: 84, - 0x1343D: 84, - 0x1343E: 84, - 0x1343F: 84, - 0x13440: 84, - 0x13447: 84, - 0x13448: 84, - 0x13449: 84, - 0x1344A: 84, - 0x1344B: 84, - 0x1344C: 84, - 0x1344D: 84, - 0x1344E: 84, - 0x1344F: 84, - 0x13450: 84, - 0x13451: 84, - 0x13452: 84, - 0x13453: 84, - 0x13454: 84, - 0x13455: 84, - 0x16AF0: 84, - 0x16AF1: 84, - 0x16AF2: 84, - 0x16AF3: 84, - 0x16AF4: 84, - 0x16B30: 84, - 0x16B31: 84, - 0x16B32: 84, - 0x16B33: 84, - 0x16B34: 84, - 0x16B35: 84, - 0x16B36: 84, - 0x16F4F: 84, - 0x16F8F: 84, - 0x16F90: 84, - 0x16F91: 84, - 0x16F92: 84, - 0x16FE4: 84, - 0x1BC9D: 84, - 0x1BC9E: 84, - 0x1BCA0: 84, - 0x1BCA1: 84, - 0x1BCA2: 84, - 0x1BCA3: 84, - 0x1CF00: 84, - 0x1CF01: 84, - 0x1CF02: 84, - 0x1CF03: 84, - 0x1CF04: 84, - 0x1CF05: 84, - 0x1CF06: 84, - 0x1CF07: 84, - 0x1CF08: 84, - 0x1CF09: 84, - 0x1CF0A: 84, - 0x1CF0B: 84, - 0x1CF0C: 84, - 0x1CF0D: 84, - 0x1CF0E: 84, - 0x1CF0F: 84, - 0x1CF10: 84, - 0x1CF11: 84, - 0x1CF12: 84, - 0x1CF13: 84, - 0x1CF14: 84, - 0x1CF15: 84, - 0x1CF16: 84, - 0x1CF17: 84, - 0x1CF18: 84, - 0x1CF19: 84, - 0x1CF1A: 84, - 0x1CF1B: 84, - 0x1CF1C: 84, - 0x1CF1D: 84, - 0x1CF1E: 84, - 0x1CF1F: 84, - 0x1CF20: 84, - 0x1CF21: 84, - 0x1CF22: 84, - 0x1CF23: 84, - 0x1CF24: 84, - 0x1CF25: 84, - 0x1CF26: 84, - 0x1CF27: 84, - 0x1CF28: 84, - 0x1CF29: 84, - 0x1CF2A: 84, - 0x1CF2B: 84, - 0x1CF2C: 84, - 0x1CF2D: 84, - 0x1CF30: 84, - 0x1CF31: 84, - 0x1CF32: 84, - 0x1CF33: 84, - 0x1CF34: 84, - 0x1CF35: 84, - 0x1CF36: 84, - 0x1CF37: 84, - 0x1CF38: 84, - 0x1CF39: 84, - 0x1CF3A: 84, - 0x1CF3B: 84, - 0x1CF3C: 84, - 0x1CF3D: 84, - 0x1CF3E: 84, - 0x1CF3F: 84, - 0x1CF40: 84, - 0x1CF41: 84, - 0x1CF42: 84, - 0x1CF43: 84, - 0x1CF44: 84, - 0x1CF45: 84, - 0x1CF46: 84, - 0x1D167: 84, - 0x1D168: 84, - 0x1D169: 84, - 0x1D173: 84, - 0x1D174: 84, - 0x1D175: 84, - 0x1D176: 84, - 0x1D177: 84, - 0x1D178: 84, - 0x1D179: 84, - 0x1D17A: 84, - 0x1D17B: 84, - 0x1D17C: 84, - 0x1D17D: 84, - 0x1D17E: 84, - 0x1D17F: 84, - 0x1D180: 84, - 0x1D181: 84, - 0x1D182: 84, - 0x1D185: 84, - 0x1D186: 84, - 0x1D187: 84, - 0x1D188: 84, - 0x1D189: 84, - 0x1D18A: 84, - 0x1D18B: 84, - 0x1D1AA: 84, - 0x1D1AB: 84, - 0x1D1AC: 84, - 0x1D1AD: 84, - 0x1D242: 84, - 0x1D243: 84, - 0x1D244: 84, - 0x1DA00: 84, - 0x1DA01: 84, - 0x1DA02: 84, - 0x1DA03: 84, - 0x1DA04: 84, - 0x1DA05: 84, - 0x1DA06: 84, - 0x1DA07: 84, - 0x1DA08: 84, - 0x1DA09: 84, - 0x1DA0A: 84, - 0x1DA0B: 84, - 0x1DA0C: 84, - 0x1DA0D: 84, - 0x1DA0E: 84, - 0x1DA0F: 84, - 0x1DA10: 84, - 0x1DA11: 84, - 0x1DA12: 84, - 0x1DA13: 84, - 0x1DA14: 84, - 0x1DA15: 84, - 0x1DA16: 84, - 0x1DA17: 84, - 0x1DA18: 84, - 0x1DA19: 84, - 0x1DA1A: 84, - 0x1DA1B: 84, - 0x1DA1C: 84, - 0x1DA1D: 84, - 0x1DA1E: 84, - 0x1DA1F: 84, - 0x1DA20: 84, - 0x1DA21: 84, - 0x1DA22: 84, - 0x1DA23: 84, - 0x1DA24: 84, - 0x1DA25: 84, - 0x1DA26: 84, - 0x1DA27: 84, - 0x1DA28: 84, - 0x1DA29: 84, - 0x1DA2A: 84, - 0x1DA2B: 84, - 0x1DA2C: 84, - 0x1DA2D: 84, - 0x1DA2E: 84, - 0x1DA2F: 84, - 0x1DA30: 84, - 0x1DA31: 84, - 0x1DA32: 84, - 0x1DA33: 84, - 0x1DA34: 84, - 0x1DA35: 84, - 0x1DA36: 84, - 0x1DA3B: 84, - 0x1DA3C: 84, - 0x1DA3D: 84, - 0x1DA3E: 84, - 0x1DA3F: 84, - 0x1DA40: 84, - 0x1DA41: 84, - 0x1DA42: 84, - 0x1DA43: 84, - 0x1DA44: 84, - 0x1DA45: 84, - 0x1DA46: 84, - 0x1DA47: 84, - 0x1DA48: 84, - 0x1DA49: 84, - 0x1DA4A: 84, - 0x1DA4B: 84, - 0x1DA4C: 84, - 0x1DA4D: 84, - 0x1DA4E: 84, - 0x1DA4F: 84, - 0x1DA50: 84, - 0x1DA51: 84, - 0x1DA52: 84, - 0x1DA53: 84, - 0x1DA54: 84, - 0x1DA55: 84, - 0x1DA56: 84, - 0x1DA57: 84, - 0x1DA58: 84, - 0x1DA59: 84, - 0x1DA5A: 84, - 0x1DA5B: 84, - 0x1DA5C: 84, - 0x1DA5D: 84, - 0x1DA5E: 84, - 0x1DA5F: 84, - 0x1DA60: 84, - 0x1DA61: 84, - 0x1DA62: 84, - 0x1DA63: 84, - 0x1DA64: 84, - 0x1DA65: 84, - 0x1DA66: 84, - 0x1DA67: 84, - 0x1DA68: 84, - 0x1DA69: 84, - 0x1DA6A: 84, - 0x1DA6B: 84, - 0x1DA6C: 84, - 0x1DA75: 84, - 0x1DA84: 84, - 0x1DA9B: 84, - 0x1DA9C: 84, - 0x1DA9D: 84, - 0x1DA9E: 84, - 0x1DA9F: 84, - 0x1DAA1: 84, - 0x1DAA2: 84, - 0x1DAA3: 84, - 0x1DAA4: 84, - 0x1DAA5: 84, - 0x1DAA6: 84, - 0x1DAA7: 84, - 0x1DAA8: 84, - 0x1DAA9: 84, - 0x1DAAA: 84, - 0x1DAAB: 84, - 0x1DAAC: 84, - 0x1DAAD: 84, - 0x1DAAE: 84, - 0x1DAAF: 84, - 0x1E000: 84, - 0x1E001: 84, - 0x1E002: 84, - 0x1E003: 84, - 0x1E004: 84, - 0x1E005: 84, - 0x1E006: 84, - 0x1E008: 84, - 0x1E009: 84, - 0x1E00A: 84, - 0x1E00B: 84, - 0x1E00C: 84, - 0x1E00D: 84, - 0x1E00E: 84, - 0x1E00F: 84, - 0x1E010: 84, - 0x1E011: 84, - 0x1E012: 84, - 0x1E013: 84, - 0x1E014: 84, - 0x1E015: 84, - 0x1E016: 84, - 0x1E017: 84, - 0x1E018: 84, - 0x1E01B: 84, - 0x1E01C: 84, - 0x1E01D: 84, - 0x1E01E: 84, - 0x1E01F: 84, - 0x1E020: 84, - 0x1E021: 84, - 0x1E023: 84, - 0x1E024: 84, - 0x1E026: 84, - 0x1E027: 84, - 0x1E028: 84, - 0x1E029: 84, - 0x1E02A: 84, - 0x1E08F: 84, - 0x1E130: 84, - 0x1E131: 84, - 0x1E132: 84, - 0x1E133: 84, - 0x1E134: 84, - 0x1E135: 84, - 0x1E136: 84, - 0x1E2AE: 84, - 0x1E2EC: 84, - 0x1E2ED: 84, - 0x1E2EE: 84, - 0x1E2EF: 84, - 0x1E4EC: 84, - 0x1E4ED: 84, - 0x1E4EE: 84, - 0x1E4EF: 84, - 0x1E8D0: 84, - 0x1E8D1: 84, - 0x1E8D2: 84, - 0x1E8D3: 84, - 0x1E8D4: 84, - 0x1E8D5: 84, - 0x1E8D6: 84, - 0x1E900: 68, - 0x1E901: 68, - 0x1E902: 68, - 0x1E903: 68, - 0x1E904: 68, - 0x1E905: 68, - 0x1E906: 68, - 0x1E907: 68, - 0x1E908: 68, - 0x1E909: 68, - 0x1E90A: 68, - 0x1E90B: 68, - 0x1E90C: 68, - 0x1E90D: 68, - 0x1E90E: 68, - 0x1E90F: 68, - 0x1E910: 68, - 0x1E911: 68, - 0x1E912: 68, - 0x1E913: 68, - 0x1E914: 68, - 0x1E915: 68, - 0x1E916: 68, - 0x1E917: 68, - 0x1E918: 68, - 0x1E919: 68, - 0x1E91A: 68, - 0x1E91B: 68, - 0x1E91C: 68, - 0x1E91D: 68, - 0x1E91E: 68, - 0x1E91F: 68, - 0x1E920: 68, - 0x1E921: 68, - 0x1E922: 68, - 0x1E923: 68, - 0x1E924: 68, - 0x1E925: 68, - 0x1E926: 68, - 0x1E927: 68, - 0x1E928: 68, - 0x1E929: 68, - 0x1E92A: 68, - 0x1E92B: 68, - 0x1E92C: 68, - 0x1E92D: 68, - 0x1E92E: 68, - 0x1E92F: 68, - 0x1E930: 68, - 0x1E931: 68, - 0x1E932: 68, - 0x1E933: 68, - 0x1E934: 68, - 0x1E935: 68, - 0x1E936: 68, - 0x1E937: 68, - 0x1E938: 68, - 0x1E939: 68, - 0x1E93A: 68, - 0x1E93B: 68, - 0x1E93C: 68, - 0x1E93D: 68, - 0x1E93E: 68, - 0x1E93F: 68, - 0x1E940: 68, - 0x1E941: 68, - 0x1E942: 68, - 0x1E943: 68, - 0x1E944: 84, - 0x1E945: 84, - 0x1E946: 84, - 0x1E947: 84, - 0x1E948: 84, - 0x1E949: 84, - 0x1E94A: 84, - 0x1E94B: 84, - 0xE0001: 84, - 0xE0020: 84, - 0xE0021: 84, - 0xE0022: 84, - 0xE0023: 84, - 0xE0024: 84, - 0xE0025: 84, - 0xE0026: 84, - 0xE0027: 84, - 0xE0028: 84, - 0xE0029: 84, - 0xE002A: 84, - 0xE002B: 84, - 0xE002C: 84, - 0xE002D: 84, - 0xE002E: 84, - 0xE002F: 84, - 0xE0030: 84, - 0xE0031: 84, - 0xE0032: 84, - 0xE0033: 84, - 0xE0034: 84, - 0xE0035: 84, - 0xE0036: 84, - 0xE0037: 84, - 0xE0038: 84, - 0xE0039: 84, - 0xE003A: 84, - 0xE003B: 84, - 0xE003C: 84, - 0xE003D: 84, - 0xE003E: 84, - 0xE003F: 84, - 0xE0040: 84, - 0xE0041: 84, - 0xE0042: 84, - 0xE0043: 84, - 0xE0044: 84, - 0xE0045: 84, - 0xE0046: 84, - 0xE0047: 84, - 0xE0048: 84, - 0xE0049: 84, - 0xE004A: 84, - 0xE004B: 84, - 0xE004C: 84, - 0xE004D: 84, - 0xE004E: 84, - 0xE004F: 84, - 0xE0050: 84, - 0xE0051: 84, - 0xE0052: 84, - 0xE0053: 84, - 0xE0054: 84, - 0xE0055: 84, - 0xE0056: 84, - 0xE0057: 84, - 0xE0058: 84, - 0xE0059: 84, - 0xE005A: 84, - 0xE005B: 84, - 0xE005C: 84, - 0xE005D: 84, - 0xE005E: 84, - 0xE005F: 84, - 0xE0060: 84, - 0xE0061: 84, - 0xE0062: 84, - 0xE0063: 84, - 0xE0064: 84, - 0xE0065: 84, - 0xE0066: 84, - 0xE0067: 84, - 0xE0068: 84, - 0xE0069: 84, - 0xE006A: 84, - 0xE006B: 84, - 0xE006C: 84, - 0xE006D: 84, - 0xE006E: 84, - 0xE006F: 84, - 0xE0070: 84, - 0xE0071: 84, - 0xE0072: 84, - 0xE0073: 84, - 0xE0074: 84, - 0xE0075: 84, - 0xE0076: 84, - 0xE0077: 84, - 0xE0078: 84, - 0xE0079: 84, - 0xE007A: 84, - 0xE007B: 84, - 0xE007C: 84, - 0xE007D: 84, - 0xE007E: 84, - 0xE007F: 84, - 0xE0100: 84, - 0xE0101: 84, - 0xE0102: 84, - 0xE0103: 84, - 0xE0104: 84, - 0xE0105: 84, - 0xE0106: 84, - 0xE0107: 84, - 0xE0108: 84, - 0xE0109: 84, - 0xE010A: 84, - 0xE010B: 84, - 0xE010C: 84, - 0xE010D: 84, - 0xE010E: 84, - 0xE010F: 84, - 0xE0110: 84, - 0xE0111: 84, - 0xE0112: 84, - 0xE0113: 84, - 0xE0114: 84, - 0xE0115: 84, - 0xE0116: 84, - 0xE0117: 84, - 0xE0118: 84, - 0xE0119: 84, - 0xE011A: 84, - 0xE011B: 84, - 0xE011C: 84, - 0xE011D: 84, - 0xE011E: 84, - 0xE011F: 84, - 0xE0120: 84, - 0xE0121: 84, - 0xE0122: 84, - 0xE0123: 84, - 0xE0124: 84, - 0xE0125: 84, - 0xE0126: 84, - 0xE0127: 84, - 0xE0128: 84, - 0xE0129: 84, - 0xE012A: 84, - 0xE012B: 84, - 0xE012C: 84, - 0xE012D: 84, - 0xE012E: 84, - 0xE012F: 84, - 0xE0130: 84, - 0xE0131: 84, - 0xE0132: 84, - 0xE0133: 84, - 0xE0134: 84, - 0xE0135: 84, - 0xE0136: 84, - 0xE0137: 84, - 0xE0138: 84, - 0xE0139: 84, - 0xE013A: 84, - 0xE013B: 84, - 0xE013C: 84, - 0xE013D: 84, - 0xE013E: 84, - 0xE013F: 84, - 0xE0140: 84, - 0xE0141: 84, - 0xE0142: 84, - 0xE0143: 84, - 0xE0144: 84, - 0xE0145: 84, - 0xE0146: 84, - 0xE0147: 84, - 0xE0148: 84, - 0xE0149: 84, - 0xE014A: 84, - 0xE014B: 84, - 0xE014C: 84, - 0xE014D: 84, - 0xE014E: 84, - 0xE014F: 84, - 0xE0150: 84, - 0xE0151: 84, - 0xE0152: 84, - 0xE0153: 84, - 0xE0154: 84, - 0xE0155: 84, - 0xE0156: 84, - 0xE0157: 84, - 0xE0158: 84, - 0xE0159: 84, - 0xE015A: 84, - 0xE015B: 84, - 0xE015C: 84, - 0xE015D: 84, - 0xE015E: 84, - 0xE015F: 84, - 0xE0160: 84, - 0xE0161: 84, - 0xE0162: 84, - 0xE0163: 84, - 0xE0164: 84, - 0xE0165: 84, - 0xE0166: 84, - 0xE0167: 84, - 0xE0168: 84, - 0xE0169: 84, - 0xE016A: 84, - 0xE016B: 84, - 0xE016C: 84, - 0xE016D: 84, - 0xE016E: 84, - 0xE016F: 84, - 0xE0170: 84, - 0xE0171: 84, - 0xE0172: 84, - 0xE0173: 84, - 0xE0174: 84, - 0xE0175: 84, - 0xE0176: 84, - 0xE0177: 84, - 0xE0178: 84, - 0xE0179: 84, - 0xE017A: 84, - 0xE017B: 84, - 0xE017C: 84, - 0xE017D: 84, - 0xE017E: 84, - 0xE017F: 84, - 0xE0180: 84, - 0xE0181: 84, - 0xE0182: 84, - 0xE0183: 84, - 0xE0184: 84, - 0xE0185: 84, - 0xE0186: 84, - 0xE0187: 84, - 0xE0188: 84, - 0xE0189: 84, - 0xE018A: 84, - 0xE018B: 84, - 0xE018C: 84, - 0xE018D: 84, - 0xE018E: 84, - 0xE018F: 84, - 0xE0190: 84, - 0xE0191: 84, - 0xE0192: 84, - 0xE0193: 84, - 0xE0194: 84, - 0xE0195: 84, - 0xE0196: 84, - 0xE0197: 84, - 0xE0198: 84, - 0xE0199: 84, - 0xE019A: 84, - 0xE019B: 84, - 0xE019C: 84, - 0xE019D: 84, - 0xE019E: 84, - 0xE019F: 84, - 0xE01A0: 84, - 0xE01A1: 84, - 0xE01A2: 84, - 0xE01A3: 84, - 0xE01A4: 84, - 0xE01A5: 84, - 0xE01A6: 84, - 0xE01A7: 84, - 0xE01A8: 84, - 0xE01A9: 84, - 0xE01AA: 84, - 0xE01AB: 84, - 0xE01AC: 84, - 0xE01AD: 84, - 0xE01AE: 84, - 0xE01AF: 84, - 0xE01B0: 84, - 0xE01B1: 84, - 0xE01B2: 84, - 0xE01B3: 84, - 0xE01B4: 84, - 0xE01B5: 84, - 0xE01B6: 84, - 0xE01B7: 84, - 0xE01B8: 84, - 0xE01B9: 84, - 0xE01BA: 84, - 0xE01BB: 84, - 0xE01BC: 84, - 0xE01BD: 84, - 0xE01BE: 84, - 0xE01BF: 84, - 0xE01C0: 84, - 0xE01C1: 84, - 0xE01C2: 84, - 0xE01C3: 84, - 0xE01C4: 84, - 0xE01C5: 84, - 0xE01C6: 84, - 0xE01C7: 84, - 0xE01C8: 84, - 0xE01C9: 84, - 0xE01CA: 84, - 0xE01CB: 84, - 0xE01CC: 84, - 0xE01CD: 84, - 0xE01CE: 84, - 0xE01CF: 84, - 0xE01D0: 84, - 0xE01D1: 84, - 0xE01D2: 84, - 0xE01D3: 84, - 0xE01D4: 84, - 0xE01D5: 84, - 0xE01D6: 84, - 0xE01D7: 84, - 0xE01D8: 84, - 0xE01D9: 84, - 0xE01DA: 84, - 0xE01DB: 84, - 0xE01DC: 84, - 0xE01DD: 84, - 0xE01DE: 84, - 0xE01DF: 84, - 0xE01E0: 84, - 0xE01E1: 84, - 0xE01E2: 84, - 0xE01E3: 84, - 0xE01E4: 84, - 0xE01E5: 84, - 0xE01E6: 84, - 0xE01E7: 84, - 0xE01E8: 84, - 0xE01E9: 84, - 0xE01EA: 84, - 0xE01EB: 84, - 0xE01EC: 84, - 0xE01ED: 84, - 0xE01EE: 84, - 0xE01EF: 84, + 0x189a: 68, + 0x189b: 68, + 0x189c: 68, + 0x189d: 68, + 0x189e: 68, + 0x189f: 68, + 0x18a0: 68, + 0x18a1: 68, + 0x18a2: 68, + 0x18a3: 68, + 0x18a4: 68, + 0x18a5: 68, + 0x18a6: 68, + 0x18a7: 68, + 0x18a8: 68, + 0x18aa: 68, + 0x200c: 85, + 0x200d: 67, + 0x202f: 85, + 0x2066: 85, + 0x2067: 85, + 0x2068: 85, + 0x2069: 85, + 0xa840: 68, + 0xa841: 68, + 0xa842: 68, + 0xa843: 68, + 0xa844: 68, + 0xa845: 68, + 0xa846: 68, + 0xa847: 68, + 0xa848: 68, + 0xa849: 68, + 0xa84a: 68, + 0xa84b: 68, + 0xa84c: 68, + 0xa84d: 68, + 0xa84e: 68, + 0xa84f: 68, + 0xa850: 68, + 0xa851: 68, + 0xa852: 68, + 0xa853: 68, + 0xa854: 68, + 0xa855: 68, + 0xa856: 68, + 0xa857: 68, + 0xa858: 68, + 0xa859: 68, + 0xa85a: 68, + 0xa85b: 68, + 0xa85c: 68, + 0xa85d: 68, + 0xa85e: 68, + 0xa85f: 68, + 0xa860: 68, + 0xa861: 68, + 0xa862: 68, + 0xa863: 68, + 0xa864: 68, + 0xa865: 68, + 0xa866: 68, + 0xa867: 68, + 0xa868: 68, + 0xa869: 68, + 0xa86a: 68, + 0xa86b: 68, + 0xa86c: 68, + 0xa86d: 68, + 0xa86e: 68, + 0xa86f: 68, + 0xa870: 68, + 0xa871: 68, + 0xa872: 76, + 0xa873: 85, + 0x10ac0: 68, + 0x10ac1: 68, + 0x10ac2: 68, + 0x10ac3: 68, + 0x10ac4: 68, + 0x10ac5: 82, + 0x10ac6: 85, + 0x10ac7: 82, + 0x10ac8: 85, + 0x10ac9: 82, + 0x10aca: 82, + 0x10acb: 85, + 0x10acc: 85, + 0x10acd: 76, + 0x10ace: 82, + 0x10acf: 82, + 0x10ad0: 82, + 0x10ad1: 82, + 0x10ad2: 82, + 0x10ad3: 68, + 0x10ad4: 68, + 0x10ad5: 68, + 0x10ad6: 68, + 0x10ad7: 76, + 0x10ad8: 68, + 0x10ad9: 68, + 0x10ada: 68, + 0x10adb: 68, + 0x10adc: 68, + 0x10add: 82, + 0x10ade: 68, + 0x10adf: 68, + 0x10ae0: 68, + 0x10ae1: 82, + 0x10ae2: 85, + 0x10ae3: 85, + 0x10ae4: 82, + 0x10aeb: 68, + 0x10aec: 68, + 0x10aed: 68, + 0x10aee: 68, + 0x10aef: 82, + 0x10b80: 68, + 0x10b81: 82, + 0x10b82: 68, + 0x10b83: 82, + 0x10b84: 82, + 0x10b85: 82, + 0x10b86: 68, + 0x10b87: 68, + 0x10b88: 68, + 0x10b89: 82, + 0x10b8a: 68, + 0x10b8b: 68, + 0x10b8c: 82, + 0x10b8d: 68, + 0x10b8e: 82, + 0x10b8f: 82, + 0x10b90: 68, + 0x10b91: 82, + 0x10ba9: 82, + 0x10baa: 82, + 0x10bab: 82, + 0x10bac: 82, + 0x10bad: 68, + 0x10bae: 68, + 0x10baf: 85, + 0x10d00: 76, + 0x10d01: 68, + 0x10d02: 68, + 0x10d03: 68, + 0x10d04: 68, + 0x10d05: 68, + 0x10d06: 68, + 0x10d07: 68, + 0x10d08: 68, + 0x10d09: 68, + 0x10d0a: 68, + 0x10d0b: 68, + 0x10d0c: 68, + 0x10d0d: 68, + 0x10d0e: 68, + 0x10d0f: 68, + 0x10d10: 68, + 0x10d11: 68, + 0x10d12: 68, + 0x10d13: 68, + 0x10d14: 68, + 0x10d15: 68, + 0x10d16: 68, + 0x10d17: 68, + 0x10d18: 68, + 0x10d19: 68, + 0x10d1a: 68, + 0x10d1b: 68, + 0x10d1c: 68, + 0x10d1d: 68, + 0x10d1e: 68, + 0x10d1f: 68, + 0x10d20: 68, + 0x10d21: 68, + 0x10d22: 82, + 0x10d23: 68, + 0x10f30: 68, + 0x10f31: 68, + 0x10f32: 68, + 0x10f33: 82, + 0x10f34: 68, + 0x10f35: 68, + 0x10f36: 68, + 0x10f37: 68, + 0x10f38: 68, + 0x10f39: 68, + 0x10f3a: 68, + 0x10f3b: 68, + 0x10f3c: 68, + 0x10f3d: 68, + 0x10f3e: 68, + 0x10f3f: 68, + 0x10f40: 68, + 0x10f41: 68, + 0x10f42: 68, + 0x10f43: 68, + 0x10f44: 68, + 0x10f45: 85, + 0x10f51: 68, + 0x10f52: 68, + 0x10f53: 68, + 0x10f54: 82, + 0x10f70: 68, + 0x10f71: 68, + 0x10f72: 68, + 0x10f73: 68, + 0x10f74: 82, + 0x10f75: 82, + 0x10f76: 68, + 0x10f77: 68, + 0x10f78: 68, + 0x10f79: 68, + 0x10f7a: 68, + 0x10f7b: 68, + 0x10f7c: 68, + 0x10f7d: 68, + 0x10f7e: 68, + 0x10f7f: 68, + 0x10f80: 68, + 0x10f81: 68, + 0x10fb0: 68, + 0x10fb1: 85, + 0x10fb2: 68, + 0x10fb3: 68, + 0x10fb4: 82, + 0x10fb5: 82, + 0x10fb6: 82, + 0x10fb7: 85, + 0x10fb8: 68, + 0x10fb9: 82, + 0x10fba: 82, + 0x10fbb: 68, + 0x10fbc: 68, + 0x10fbd: 82, + 0x10fbe: 68, + 0x10fbf: 68, + 0x10fc0: 85, + 0x10fc1: 68, + 0x10fc2: 82, + 0x10fc3: 82, + 0x10fc4: 68, + 0x10fc5: 85, + 0x10fc6: 85, + 0x10fc7: 85, + 0x10fc8: 85, + 0x10fc9: 82, + 0x10fca: 68, + 0x10fcb: 76, + 0x110bd: 85, + 0x110cd: 85, + 0x1e900: 68, + 0x1e901: 68, + 0x1e902: 68, + 0x1e903: 68, + 0x1e904: 68, + 0x1e905: 68, + 0x1e906: 68, + 0x1e907: 68, + 0x1e908: 68, + 0x1e909: 68, + 0x1e90a: 68, + 0x1e90b: 68, + 0x1e90c: 68, + 0x1e90d: 68, + 0x1e90e: 68, + 0x1e90f: 68, + 0x1e910: 68, + 0x1e911: 68, + 0x1e912: 68, + 0x1e913: 68, + 0x1e914: 68, + 0x1e915: 68, + 0x1e916: 68, + 0x1e917: 68, + 0x1e918: 68, + 0x1e919: 68, + 0x1e91a: 68, + 0x1e91b: 68, + 0x1e91c: 68, + 0x1e91d: 68, + 0x1e91e: 68, + 0x1e91f: 68, + 0x1e920: 68, + 0x1e921: 68, + 0x1e922: 68, + 0x1e923: 68, + 0x1e924: 68, + 0x1e925: 68, + 0x1e926: 68, + 0x1e927: 68, + 0x1e928: 68, + 0x1e929: 68, + 0x1e92a: 68, + 0x1e92b: 68, + 0x1e92c: 68, + 0x1e92d: 68, + 0x1e92e: 68, + 0x1e92f: 68, + 0x1e930: 68, + 0x1e931: 68, + 0x1e932: 68, + 0x1e933: 68, + 0x1e934: 68, + 0x1e935: 68, + 0x1e936: 68, + 0x1e937: 68, + 0x1e938: 68, + 0x1e939: 68, + 0x1e93a: 68, + 0x1e93b: 68, + 0x1e93c: 68, + 0x1e93d: 68, + 0x1e93e: 68, + 0x1e93f: 68, + 0x1e940: 68, + 0x1e941: 68, + 0x1e942: 68, + 0x1e943: 68, + 0x1e94b: 84, } codepoint_classes = { - "PVALID": ( - 0x2D0000002E, - 0x300000003A, - 0x610000007B, - 0xDF000000F7, - 0xF800000100, + 'PVALID': ( + 0x2d0000002e, + 0x300000003a, + 0x610000007b, + 0xdf000000f7, + 0xf800000100, 0x10100000102, 0x10300000104, 0x10500000106, 0x10700000108, - 0x1090000010A, - 0x10B0000010C, - 0x10D0000010E, - 0x10F00000110, + 0x1090000010a, + 0x10b0000010c, + 0x10d0000010e, + 0x10f00000110, 0x11100000112, 0x11300000114, 0x11500000116, 0x11700000118, - 0x1190000011A, - 0x11B0000011C, - 0x11D0000011E, - 0x11F00000120, + 0x1190000011a, + 0x11b0000011c, + 0x11d0000011e, + 0x11f00000120, 0x12100000122, 0x12300000124, 0x12500000126, 0x12700000128, - 0x1290000012A, - 0x12B0000012C, - 0x12D0000012E, - 0x12F00000130, + 0x1290000012a, + 0x12b0000012c, + 0x12d0000012e, + 0x12f00000130, 0x13100000132, 0x13500000136, 0x13700000139, - 0x13A0000013B, - 0x13C0000013D, - 0x13E0000013F, + 0x13a0000013b, + 0x13c0000013d, + 0x13e0000013f, 0x14200000143, 0x14400000145, 0x14600000147, 0x14800000149, - 0x14B0000014C, - 0x14D0000014E, - 0x14F00000150, + 0x14b0000014c, + 0x14d0000014e, + 0x14f00000150, 0x15100000152, 0x15300000154, 0x15500000156, 0x15700000158, - 0x1590000015A, - 0x15B0000015C, - 0x15D0000015E, - 0x15F00000160, + 0x1590000015a, + 0x15b0000015c, + 0x15d0000015e, + 0x15f00000160, 0x16100000162, 0x16300000164, 0x16500000166, 0x16700000168, - 0x1690000016A, - 0x16B0000016C, - 0x16D0000016E, - 0x16F00000170, + 0x1690000016a, + 0x16b0000016c, + 0x16d0000016e, + 0x16f00000170, 0x17100000172, 0x17300000174, 0x17500000176, 0x17700000178, - 0x17A0000017B, - 0x17C0000017D, - 0x17E0000017F, + 0x17a0000017b, + 0x17c0000017d, + 0x17e0000017f, 0x18000000181, 0x18300000184, 0x18500000186, 0x18800000189, - 0x18C0000018E, + 0x18c0000018e, 0x19200000193, 0x19500000196, - 0x1990000019C, - 0x19E0000019F, - 0x1A1000001A2, - 0x1A3000001A4, - 0x1A5000001A6, - 0x1A8000001A9, - 0x1AA000001AC, - 0x1AD000001AE, - 0x1B0000001B1, - 0x1B4000001B5, - 0x1B6000001B7, - 0x1B9000001BC, - 0x1BD000001C4, - 0x1CE000001CF, - 0x1D0000001D1, - 0x1D2000001D3, - 0x1D4000001D5, - 0x1D6000001D7, - 0x1D8000001D9, - 0x1DA000001DB, - 0x1DC000001DE, - 0x1DF000001E0, - 0x1E1000001E2, - 0x1E3000001E4, - 0x1E5000001E6, - 0x1E7000001E8, - 0x1E9000001EA, - 0x1EB000001EC, - 0x1ED000001EE, - 0x1EF000001F1, - 0x1F5000001F6, - 0x1F9000001FA, - 0x1FB000001FC, - 0x1FD000001FE, - 0x1FF00000200, + 0x1990000019c, + 0x19e0000019f, + 0x1a1000001a2, + 0x1a3000001a4, + 0x1a5000001a6, + 0x1a8000001a9, + 0x1aa000001ac, + 0x1ad000001ae, + 0x1b0000001b1, + 0x1b4000001b5, + 0x1b6000001b7, + 0x1b9000001bc, + 0x1bd000001c4, + 0x1ce000001cf, + 0x1d0000001d1, + 0x1d2000001d3, + 0x1d4000001d5, + 0x1d6000001d7, + 0x1d8000001d9, + 0x1da000001db, + 0x1dc000001de, + 0x1df000001e0, + 0x1e1000001e2, + 0x1e3000001e4, + 0x1e5000001e6, + 0x1e7000001e8, + 0x1e9000001ea, + 0x1eb000001ec, + 0x1ed000001ee, + 0x1ef000001f1, + 0x1f5000001f6, + 0x1f9000001fa, + 0x1fb000001fc, + 0x1fd000001fe, + 0x1ff00000200, 0x20100000202, 0x20300000204, 0x20500000206, 0x20700000208, - 0x2090000020A, - 0x20B0000020C, - 0x20D0000020E, - 0x20F00000210, + 0x2090000020a, + 0x20b0000020c, + 0x20d0000020e, + 0x20f00000210, 0x21100000212, 0x21300000214, 0x21500000216, 0x21700000218, - 0x2190000021A, - 0x21B0000021C, - 0x21D0000021E, - 0x21F00000220, + 0x2190000021a, + 0x21b0000021c, + 0x21d0000021e, + 0x21f00000220, 0x22100000222, 0x22300000224, 0x22500000226, 0x22700000228, - 0x2290000022A, - 0x22B0000022C, - 0x22D0000022E, - 0x22F00000230, + 0x2290000022a, + 0x22b0000022c, + 0x22d0000022e, + 0x22f00000230, 0x23100000232, - 0x2330000023A, - 0x23C0000023D, - 0x23F00000241, + 0x2330000023a, + 0x23c0000023d, + 0x23f00000241, 0x24200000243, 0x24700000248, - 0x2490000024A, - 0x24B0000024C, - 0x24D0000024E, - 0x24F000002B0, - 0x2B9000002C2, - 0x2C6000002D2, - 0x2EC000002ED, - 0x2EE000002EF, + 0x2490000024a, + 0x24b0000024c, + 0x24d0000024e, + 0x24f000002b0, + 0x2b9000002c2, + 0x2c6000002d2, + 0x2ec000002ed, + 0x2ee000002ef, 0x30000000340, 0x34200000343, - 0x3460000034F, + 0x3460000034f, 0x35000000370, 0x37100000372, 0x37300000374, 0x37700000378, - 0x37B0000037E, + 0x37b0000037e, 0x39000000391, - 0x3AC000003CF, - 0x3D7000003D8, - 0x3D9000003DA, - 0x3DB000003DC, - 0x3DD000003DE, - 0x3DF000003E0, - 0x3E1000003E2, - 0x3E3000003E4, - 0x3E5000003E6, - 0x3E7000003E8, - 0x3E9000003EA, - 0x3EB000003EC, - 0x3ED000003EE, - 0x3EF000003F0, - 0x3F3000003F4, - 0x3F8000003F9, - 0x3FB000003FD, + 0x3ac000003cf, + 0x3d7000003d8, + 0x3d9000003da, + 0x3db000003dc, + 0x3dd000003de, + 0x3df000003e0, + 0x3e1000003e2, + 0x3e3000003e4, + 0x3e5000003e6, + 0x3e7000003e8, + 0x3e9000003ea, + 0x3eb000003ec, + 0x3ed000003ee, + 0x3ef000003f0, + 0x3f3000003f4, + 0x3f8000003f9, + 0x3fb000003fd, 0x43000000460, 0x46100000462, 0x46300000464, 0x46500000466, 0x46700000468, - 0x4690000046A, - 0x46B0000046C, - 0x46D0000046E, - 0x46F00000470, + 0x4690000046a, + 0x46b0000046c, + 0x46d0000046e, + 0x46f00000470, 0x47100000472, 0x47300000474, 0x47500000476, 0x47700000478, - 0x4790000047A, - 0x47B0000047C, - 0x47D0000047E, - 0x47F00000480, + 0x4790000047a, + 0x47b0000047c, + 0x47d0000047e, + 0x47f00000480, 0x48100000482, 0x48300000488, - 0x48B0000048C, - 0x48D0000048E, - 0x48F00000490, + 0x48b0000048c, + 0x48d0000048e, + 0x48f00000490, 0x49100000492, 0x49300000494, 0x49500000496, 0x49700000498, - 0x4990000049A, - 0x49B0000049C, - 0x49D0000049E, - 0x49F000004A0, - 0x4A1000004A2, - 0x4A3000004A4, - 0x4A5000004A6, - 0x4A7000004A8, - 0x4A9000004AA, - 0x4AB000004AC, - 0x4AD000004AE, - 0x4AF000004B0, - 0x4B1000004B2, - 0x4B3000004B4, - 0x4B5000004B6, - 0x4B7000004B8, - 0x4B9000004BA, - 0x4BB000004BC, - 0x4BD000004BE, - 0x4BF000004C0, - 0x4C2000004C3, - 0x4C4000004C5, - 0x4C6000004C7, - 0x4C8000004C9, - 0x4CA000004CB, - 0x4CC000004CD, - 0x4CE000004D0, - 0x4D1000004D2, - 0x4D3000004D4, - 0x4D5000004D6, - 0x4D7000004D8, - 0x4D9000004DA, - 0x4DB000004DC, - 0x4DD000004DE, - 0x4DF000004E0, - 0x4E1000004E2, - 0x4E3000004E4, - 0x4E5000004E6, - 0x4E7000004E8, - 0x4E9000004EA, - 0x4EB000004EC, - 0x4ED000004EE, - 0x4EF000004F0, - 0x4F1000004F2, - 0x4F3000004F4, - 0x4F5000004F6, - 0x4F7000004F8, - 0x4F9000004FA, - 0x4FB000004FC, - 0x4FD000004FE, - 0x4FF00000500, + 0x4990000049a, + 0x49b0000049c, + 0x49d0000049e, + 0x49f000004a0, + 0x4a1000004a2, + 0x4a3000004a4, + 0x4a5000004a6, + 0x4a7000004a8, + 0x4a9000004aa, + 0x4ab000004ac, + 0x4ad000004ae, + 0x4af000004b0, + 0x4b1000004b2, + 0x4b3000004b4, + 0x4b5000004b6, + 0x4b7000004b8, + 0x4b9000004ba, + 0x4bb000004bc, + 0x4bd000004be, + 0x4bf000004c0, + 0x4c2000004c3, + 0x4c4000004c5, + 0x4c6000004c7, + 0x4c8000004c9, + 0x4ca000004cb, + 0x4cc000004cd, + 0x4ce000004d0, + 0x4d1000004d2, + 0x4d3000004d4, + 0x4d5000004d6, + 0x4d7000004d8, + 0x4d9000004da, + 0x4db000004dc, + 0x4dd000004de, + 0x4df000004e0, + 0x4e1000004e2, + 0x4e3000004e4, + 0x4e5000004e6, + 0x4e7000004e8, + 0x4e9000004ea, + 0x4eb000004ec, + 0x4ed000004ee, + 0x4ef000004f0, + 0x4f1000004f2, + 0x4f3000004f4, + 0x4f5000004f6, + 0x4f7000004f8, + 0x4f9000004fa, + 0x4fb000004fc, + 0x4fd000004fe, + 0x4ff00000500, 0x50100000502, 0x50300000504, 0x50500000506, 0x50700000508, - 0x5090000050A, - 0x50B0000050C, - 0x50D0000050E, - 0x50F00000510, + 0x5090000050a, + 0x50b0000050c, + 0x50d0000050e, + 0x50f00000510, 0x51100000512, 0x51300000514, 0x51500000516, 0x51700000518, - 0x5190000051A, - 0x51B0000051C, - 0x51D0000051E, - 0x51F00000520, + 0x5190000051a, + 0x51b0000051c, + 0x51d0000051e, + 0x51f00000520, 0x52100000522, 0x52300000524, 0x52500000526, 0x52700000528, - 0x5290000052A, - 0x52B0000052C, - 0x52D0000052E, - 0x52F00000530, - 0x5590000055A, + 0x5290000052a, + 0x52b0000052c, + 0x52d0000052e, + 0x52f00000530, + 0x5590000055a, 0x56000000587, 0x58800000589, - 0x591000005BE, - 0x5BF000005C0, - 0x5C1000005C3, - 0x5C4000005C6, - 0x5C7000005C8, - 0x5D0000005EB, - 0x5EF000005F3, - 0x6100000061B, + 0x591000005be, + 0x5bf000005c0, + 0x5c1000005c3, + 0x5c4000005c6, + 0x5c7000005c8, + 0x5d0000005eb, + 0x5ef000005f3, + 0x6100000061b, 0x62000000640, 0x64100000660, - 0x66E00000675, - 0x679000006D4, - 0x6D5000006DD, - 0x6DF000006E9, - 0x6EA000006F0, - 0x6FA00000700, - 0x7100000074B, - 0x74D000007B2, - 0x7C0000007F6, - 0x7FD000007FE, - 0x8000000082E, - 0x8400000085C, - 0x8600000086B, + 0x66e00000675, + 0x679000006d4, + 0x6d5000006dd, + 0x6df000006e9, + 0x6ea000006f0, + 0x6fa00000700, + 0x7100000074b, + 0x74d000007b2, + 0x7c0000007f6, + 0x7fd000007fe, + 0x8000000082e, + 0x8400000085c, + 0x8600000086b, 0x87000000888, - 0x8890000088F, - 0x898000008E2, - 0x8E300000958, + 0x8890000088f, + 0x898000008e2, + 0x8e300000958, 0x96000000964, 0x96600000970, 0x97100000984, - 0x9850000098D, - 0x98F00000991, - 0x993000009A9, - 0x9AA000009B1, - 0x9B2000009B3, - 0x9B6000009BA, - 0x9BC000009C5, - 0x9C7000009C9, - 0x9CB000009CF, - 0x9D7000009D8, - 0x9E0000009E4, - 0x9E6000009F2, - 0x9FC000009FD, - 0x9FE000009FF, - 0xA0100000A04, - 0xA0500000A0B, - 0xA0F00000A11, - 0xA1300000A29, - 0xA2A00000A31, - 0xA3200000A33, - 0xA3500000A36, - 0xA3800000A3A, - 0xA3C00000A3D, - 0xA3E00000A43, - 0xA4700000A49, - 0xA4B00000A4E, - 0xA5100000A52, - 0xA5C00000A5D, - 0xA6600000A76, - 0xA8100000A84, - 0xA8500000A8E, - 0xA8F00000A92, - 0xA9300000AA9, - 0xAAA00000AB1, - 0xAB200000AB4, - 0xAB500000ABA, - 0xABC00000AC6, - 0xAC700000ACA, - 0xACB00000ACE, - 0xAD000000AD1, - 0xAE000000AE4, - 0xAE600000AF0, - 0xAF900000B00, - 0xB0100000B04, - 0xB0500000B0D, - 0xB0F00000B11, - 0xB1300000B29, - 0xB2A00000B31, - 0xB3200000B34, - 0xB3500000B3A, - 0xB3C00000B45, - 0xB4700000B49, - 0xB4B00000B4E, - 0xB5500000B58, - 0xB5F00000B64, - 0xB6600000B70, - 0xB7100000B72, - 0xB8200000B84, - 0xB8500000B8B, - 0xB8E00000B91, - 0xB9200000B96, - 0xB9900000B9B, - 0xB9C00000B9D, - 0xB9E00000BA0, - 0xBA300000BA5, - 0xBA800000BAB, - 0xBAE00000BBA, - 0xBBE00000BC3, - 0xBC600000BC9, - 0xBCA00000BCE, - 0xBD000000BD1, - 0xBD700000BD8, - 0xBE600000BF0, - 0xC0000000C0D, - 0xC0E00000C11, - 0xC1200000C29, - 0xC2A00000C3A, - 0xC3C00000C45, - 0xC4600000C49, - 0xC4A00000C4E, - 0xC5500000C57, - 0xC5800000C5B, - 0xC5D00000C5E, - 0xC6000000C64, - 0xC6600000C70, - 0xC8000000C84, - 0xC8500000C8D, - 0xC8E00000C91, - 0xC9200000CA9, - 0xCAA00000CB4, - 0xCB500000CBA, - 0xCBC00000CC5, - 0xCC600000CC9, - 0xCCA00000CCE, - 0xCD500000CD7, - 0xCDD00000CDF, - 0xCE000000CE4, - 0xCE600000CF0, - 0xCF100000CF4, - 0xD0000000D0D, - 0xD0E00000D11, - 0xD1200000D45, - 0xD4600000D49, - 0xD4A00000D4F, - 0xD5400000D58, - 0xD5F00000D64, - 0xD6600000D70, - 0xD7A00000D80, - 0xD8100000D84, - 0xD8500000D97, - 0xD9A00000DB2, - 0xDB300000DBC, - 0xDBD00000DBE, - 0xDC000000DC7, - 0xDCA00000DCB, - 0xDCF00000DD5, - 0xDD600000DD7, - 0xDD800000DE0, - 0xDE600000DF0, - 0xDF200000DF4, - 0xE0100000E33, - 0xE3400000E3B, - 0xE4000000E4F, - 0xE5000000E5A, - 0xE8100000E83, - 0xE8400000E85, - 0xE8600000E8B, - 0xE8C00000EA4, - 0xEA500000EA6, - 0xEA700000EB3, - 0xEB400000EBE, - 0xEC000000EC5, - 0xEC600000EC7, - 0xEC800000ECF, - 0xED000000EDA, - 0xEDE00000EE0, - 0xF0000000F01, - 0xF0B00000F0C, - 0xF1800000F1A, - 0xF2000000F2A, - 0xF3500000F36, - 0xF3700000F38, - 0xF3900000F3A, - 0xF3E00000F43, - 0xF4400000F48, - 0xF4900000F4D, - 0xF4E00000F52, - 0xF5300000F57, - 0xF5800000F5C, - 0xF5D00000F69, - 0xF6A00000F6D, - 0xF7100000F73, - 0xF7400000F75, - 0xF7A00000F81, - 0xF8200000F85, - 0xF8600000F93, - 0xF9400000F98, - 0xF9900000F9D, - 0xF9E00000FA2, - 0xFA300000FA7, - 0xFA800000FAC, - 0xFAD00000FB9, - 0xFBA00000FBD, - 0xFC600000FC7, - 0x10000000104A, - 0x10500000109E, - 0x10D0000010FB, - 0x10FD00001100, + 0x9850000098d, + 0x98f00000991, + 0x993000009a9, + 0x9aa000009b1, + 0x9b2000009b3, + 0x9b6000009ba, + 0x9bc000009c5, + 0x9c7000009c9, + 0x9cb000009cf, + 0x9d7000009d8, + 0x9e0000009e4, + 0x9e6000009f2, + 0x9fc000009fd, + 0x9fe000009ff, + 0xa0100000a04, + 0xa0500000a0b, + 0xa0f00000a11, + 0xa1300000a29, + 0xa2a00000a31, + 0xa3200000a33, + 0xa3500000a36, + 0xa3800000a3a, + 0xa3c00000a3d, + 0xa3e00000a43, + 0xa4700000a49, + 0xa4b00000a4e, + 0xa5100000a52, + 0xa5c00000a5d, + 0xa6600000a76, + 0xa8100000a84, + 0xa8500000a8e, + 0xa8f00000a92, + 0xa9300000aa9, + 0xaaa00000ab1, + 0xab200000ab4, + 0xab500000aba, + 0xabc00000ac6, + 0xac700000aca, + 0xacb00000ace, + 0xad000000ad1, + 0xae000000ae4, + 0xae600000af0, + 0xaf900000b00, + 0xb0100000b04, + 0xb0500000b0d, + 0xb0f00000b11, + 0xb1300000b29, + 0xb2a00000b31, + 0xb3200000b34, + 0xb3500000b3a, + 0xb3c00000b45, + 0xb4700000b49, + 0xb4b00000b4e, + 0xb5500000b58, + 0xb5f00000b64, + 0xb6600000b70, + 0xb7100000b72, + 0xb8200000b84, + 0xb8500000b8b, + 0xb8e00000b91, + 0xb9200000b96, + 0xb9900000b9b, + 0xb9c00000b9d, + 0xb9e00000ba0, + 0xba300000ba5, + 0xba800000bab, + 0xbae00000bba, + 0xbbe00000bc3, + 0xbc600000bc9, + 0xbca00000bce, + 0xbd000000bd1, + 0xbd700000bd8, + 0xbe600000bf0, + 0xc0000000c0d, + 0xc0e00000c11, + 0xc1200000c29, + 0xc2a00000c3a, + 0xc3c00000c45, + 0xc4600000c49, + 0xc4a00000c4e, + 0xc5500000c57, + 0xc5800000c5b, + 0xc5d00000c5e, + 0xc6000000c64, + 0xc6600000c70, + 0xc8000000c84, + 0xc8500000c8d, + 0xc8e00000c91, + 0xc9200000ca9, + 0xcaa00000cb4, + 0xcb500000cba, + 0xcbc00000cc5, + 0xcc600000cc9, + 0xcca00000cce, + 0xcd500000cd7, + 0xcdd00000cdf, + 0xce000000ce4, + 0xce600000cf0, + 0xcf100000cf4, + 0xd0000000d0d, + 0xd0e00000d11, + 0xd1200000d45, + 0xd4600000d49, + 0xd4a00000d4f, + 0xd5400000d58, + 0xd5f00000d64, + 0xd6600000d70, + 0xd7a00000d80, + 0xd8100000d84, + 0xd8500000d97, + 0xd9a00000db2, + 0xdb300000dbc, + 0xdbd00000dbe, + 0xdc000000dc7, + 0xdca00000dcb, + 0xdcf00000dd5, + 0xdd600000dd7, + 0xdd800000de0, + 0xde600000df0, + 0xdf200000df4, + 0xe0100000e33, + 0xe3400000e3b, + 0xe4000000e4f, + 0xe5000000e5a, + 0xe8100000e83, + 0xe8400000e85, + 0xe8600000e8b, + 0xe8c00000ea4, + 0xea500000ea6, + 0xea700000eb3, + 0xeb400000ebe, + 0xec000000ec5, + 0xec600000ec7, + 0xec800000ecf, + 0xed000000eda, + 0xede00000ee0, + 0xf0000000f01, + 0xf0b00000f0c, + 0xf1800000f1a, + 0xf2000000f2a, + 0xf3500000f36, + 0xf3700000f38, + 0xf3900000f3a, + 0xf3e00000f43, + 0xf4400000f48, + 0xf4900000f4d, + 0xf4e00000f52, + 0xf5300000f57, + 0xf5800000f5c, + 0xf5d00000f69, + 0xf6a00000f6d, + 0xf7100000f73, + 0xf7400000f75, + 0xf7a00000f81, + 0xf8200000f85, + 0xf8600000f93, + 0xf9400000f98, + 0xf9900000f9d, + 0xf9e00000fa2, + 0xfa300000fa7, + 0xfa800000fac, + 0xfad00000fb9, + 0xfba00000fbd, + 0xfc600000fc7, + 0x10000000104a, + 0x10500000109e, + 0x10d0000010fb, + 0x10fd00001100, 0x120000001249, - 0x124A0000124E, + 0x124a0000124e, 0x125000001257, 0x125800001259, - 0x125A0000125E, + 0x125a0000125e, 0x126000001289, - 0x128A0000128E, - 0x1290000012B1, - 0x12B2000012B6, - 0x12B8000012BF, - 0x12C0000012C1, - 0x12C2000012C6, - 0x12C8000012D7, - 0x12D800001311, + 0x128a0000128e, + 0x1290000012b1, + 0x12b2000012b6, + 0x12b8000012bf, + 0x12c0000012c1, + 0x12c2000012c6, + 0x12c8000012d7, + 0x12d800001311, 0x131200001316, - 0x13180000135B, - 0x135D00001360, + 0x13180000135b, + 0x135d00001360, 0x138000001390, - 0x13A0000013F6, - 0x14010000166D, - 0x166F00001680, - 0x16810000169B, - 0x16A0000016EB, - 0x16F1000016F9, + 0x13a0000013f6, + 0x14010000166d, + 0x166f00001680, + 0x16810000169b, + 0x16a0000016eb, + 0x16f1000016f9, 0x170000001716, - 0x171F00001735, + 0x171f00001735, 0x174000001754, - 0x17600000176D, - 0x176E00001771, + 0x17600000176d, + 0x176e00001771, 0x177200001774, - 0x1780000017B4, - 0x17B6000017D4, - 0x17D7000017D8, - 0x17DC000017DE, - 0x17E0000017EA, - 0x18100000181A, + 0x1780000017b4, + 0x17b6000017d4, + 0x17d7000017d8, + 0x17dc000017de, + 0x17e0000017ea, + 0x18100000181a, 0x182000001879, - 0x1880000018AB, - 0x18B0000018F6, - 0x19000000191F, - 0x19200000192C, - 0x19300000193C, - 0x19460000196E, + 0x1880000018ab, + 0x18b0000018f6, + 0x19000000191f, + 0x19200000192c, + 0x19300000193c, + 0x19460000196e, 0x197000001975, - 0x1980000019AC, - 0x19B0000019CA, - 0x19D0000019DA, - 0x1A0000001A1C, - 0x1A2000001A5F, - 0x1A6000001A7D, - 0x1A7F00001A8A, - 0x1A9000001A9A, - 0x1AA700001AA8, - 0x1AB000001ABE, - 0x1ABF00001ACF, - 0x1B0000001B4D, - 0x1B5000001B5A, - 0x1B6B00001B74, - 0x1B8000001BF4, - 0x1C0000001C38, - 0x1C4000001C4A, - 0x1C4D00001C7E, - 0x1CD000001CD3, - 0x1CD400001CFB, - 0x1D0000001D2C, - 0x1D2F00001D30, - 0x1D3B00001D3C, - 0x1D4E00001D4F, - 0x1D6B00001D78, - 0x1D7900001D9B, - 0x1DC000001E00, - 0x1E0100001E02, - 0x1E0300001E04, - 0x1E0500001E06, - 0x1E0700001E08, - 0x1E0900001E0A, - 0x1E0B00001E0C, - 0x1E0D00001E0E, - 0x1E0F00001E10, - 0x1E1100001E12, - 0x1E1300001E14, - 0x1E1500001E16, - 0x1E1700001E18, - 0x1E1900001E1A, - 0x1E1B00001E1C, - 0x1E1D00001E1E, - 0x1E1F00001E20, - 0x1E2100001E22, - 0x1E2300001E24, - 0x1E2500001E26, - 0x1E2700001E28, - 0x1E2900001E2A, - 0x1E2B00001E2C, - 0x1E2D00001E2E, - 0x1E2F00001E30, - 0x1E3100001E32, - 0x1E3300001E34, - 0x1E3500001E36, - 0x1E3700001E38, - 0x1E3900001E3A, - 0x1E3B00001E3C, - 0x1E3D00001E3E, - 0x1E3F00001E40, - 0x1E4100001E42, - 0x1E4300001E44, - 0x1E4500001E46, - 0x1E4700001E48, - 0x1E4900001E4A, - 0x1E4B00001E4C, - 0x1E4D00001E4E, - 0x1E4F00001E50, - 0x1E5100001E52, - 0x1E5300001E54, - 0x1E5500001E56, - 0x1E5700001E58, - 0x1E5900001E5A, - 0x1E5B00001E5C, - 0x1E5D00001E5E, - 0x1E5F00001E60, - 0x1E6100001E62, - 0x1E6300001E64, - 0x1E6500001E66, - 0x1E6700001E68, - 0x1E6900001E6A, - 0x1E6B00001E6C, - 0x1E6D00001E6E, - 0x1E6F00001E70, - 0x1E7100001E72, - 0x1E7300001E74, - 0x1E7500001E76, - 0x1E7700001E78, - 0x1E7900001E7A, - 0x1E7B00001E7C, - 0x1E7D00001E7E, - 0x1E7F00001E80, - 0x1E8100001E82, - 0x1E8300001E84, - 0x1E8500001E86, - 0x1E8700001E88, - 0x1E8900001E8A, - 0x1E8B00001E8C, - 0x1E8D00001E8E, - 0x1E8F00001E90, - 0x1E9100001E92, - 0x1E9300001E94, - 0x1E9500001E9A, - 0x1E9C00001E9E, - 0x1E9F00001EA0, - 0x1EA100001EA2, - 0x1EA300001EA4, - 0x1EA500001EA6, - 0x1EA700001EA8, - 0x1EA900001EAA, - 0x1EAB00001EAC, - 0x1EAD00001EAE, - 0x1EAF00001EB0, - 0x1EB100001EB2, - 0x1EB300001EB4, - 0x1EB500001EB6, - 0x1EB700001EB8, - 0x1EB900001EBA, - 0x1EBB00001EBC, - 0x1EBD00001EBE, - 0x1EBF00001EC0, - 0x1EC100001EC2, - 0x1EC300001EC4, - 0x1EC500001EC6, - 0x1EC700001EC8, - 0x1EC900001ECA, - 0x1ECB00001ECC, - 0x1ECD00001ECE, - 0x1ECF00001ED0, - 0x1ED100001ED2, - 0x1ED300001ED4, - 0x1ED500001ED6, - 0x1ED700001ED8, - 0x1ED900001EDA, - 0x1EDB00001EDC, - 0x1EDD00001EDE, - 0x1EDF00001EE0, - 0x1EE100001EE2, - 0x1EE300001EE4, - 0x1EE500001EE6, - 0x1EE700001EE8, - 0x1EE900001EEA, - 0x1EEB00001EEC, - 0x1EED00001EEE, - 0x1EEF00001EF0, - 0x1EF100001EF2, - 0x1EF300001EF4, - 0x1EF500001EF6, - 0x1EF700001EF8, - 0x1EF900001EFA, - 0x1EFB00001EFC, - 0x1EFD00001EFE, - 0x1EFF00001F08, - 0x1F1000001F16, - 0x1F2000001F28, - 0x1F3000001F38, - 0x1F4000001F46, - 0x1F5000001F58, - 0x1F6000001F68, - 0x1F7000001F71, - 0x1F7200001F73, - 0x1F7400001F75, - 0x1F7600001F77, - 0x1F7800001F79, - 0x1F7A00001F7B, - 0x1F7C00001F7D, - 0x1FB000001FB2, - 0x1FB600001FB7, - 0x1FC600001FC7, - 0x1FD000001FD3, - 0x1FD600001FD8, - 0x1FE000001FE3, - 0x1FE400001FE8, - 0x1FF600001FF7, - 0x214E0000214F, + 0x1980000019ac, + 0x19b0000019ca, + 0x19d0000019da, + 0x1a0000001a1c, + 0x1a2000001a5f, + 0x1a6000001a7d, + 0x1a7f00001a8a, + 0x1a9000001a9a, + 0x1aa700001aa8, + 0x1ab000001abe, + 0x1abf00001acf, + 0x1b0000001b4d, + 0x1b5000001b5a, + 0x1b6b00001b74, + 0x1b8000001bf4, + 0x1c0000001c38, + 0x1c4000001c4a, + 0x1c4d00001c7e, + 0x1cd000001cd3, + 0x1cd400001cfb, + 0x1d0000001d2c, + 0x1d2f00001d30, + 0x1d3b00001d3c, + 0x1d4e00001d4f, + 0x1d6b00001d78, + 0x1d7900001d9b, + 0x1dc000001e00, + 0x1e0100001e02, + 0x1e0300001e04, + 0x1e0500001e06, + 0x1e0700001e08, + 0x1e0900001e0a, + 0x1e0b00001e0c, + 0x1e0d00001e0e, + 0x1e0f00001e10, + 0x1e1100001e12, + 0x1e1300001e14, + 0x1e1500001e16, + 0x1e1700001e18, + 0x1e1900001e1a, + 0x1e1b00001e1c, + 0x1e1d00001e1e, + 0x1e1f00001e20, + 0x1e2100001e22, + 0x1e2300001e24, + 0x1e2500001e26, + 0x1e2700001e28, + 0x1e2900001e2a, + 0x1e2b00001e2c, + 0x1e2d00001e2e, + 0x1e2f00001e30, + 0x1e3100001e32, + 0x1e3300001e34, + 0x1e3500001e36, + 0x1e3700001e38, + 0x1e3900001e3a, + 0x1e3b00001e3c, + 0x1e3d00001e3e, + 0x1e3f00001e40, + 0x1e4100001e42, + 0x1e4300001e44, + 0x1e4500001e46, + 0x1e4700001e48, + 0x1e4900001e4a, + 0x1e4b00001e4c, + 0x1e4d00001e4e, + 0x1e4f00001e50, + 0x1e5100001e52, + 0x1e5300001e54, + 0x1e5500001e56, + 0x1e5700001e58, + 0x1e5900001e5a, + 0x1e5b00001e5c, + 0x1e5d00001e5e, + 0x1e5f00001e60, + 0x1e6100001e62, + 0x1e6300001e64, + 0x1e6500001e66, + 0x1e6700001e68, + 0x1e6900001e6a, + 0x1e6b00001e6c, + 0x1e6d00001e6e, + 0x1e6f00001e70, + 0x1e7100001e72, + 0x1e7300001e74, + 0x1e7500001e76, + 0x1e7700001e78, + 0x1e7900001e7a, + 0x1e7b00001e7c, + 0x1e7d00001e7e, + 0x1e7f00001e80, + 0x1e8100001e82, + 0x1e8300001e84, + 0x1e8500001e86, + 0x1e8700001e88, + 0x1e8900001e8a, + 0x1e8b00001e8c, + 0x1e8d00001e8e, + 0x1e8f00001e90, + 0x1e9100001e92, + 0x1e9300001e94, + 0x1e9500001e9a, + 0x1e9c00001e9e, + 0x1e9f00001ea0, + 0x1ea100001ea2, + 0x1ea300001ea4, + 0x1ea500001ea6, + 0x1ea700001ea8, + 0x1ea900001eaa, + 0x1eab00001eac, + 0x1ead00001eae, + 0x1eaf00001eb0, + 0x1eb100001eb2, + 0x1eb300001eb4, + 0x1eb500001eb6, + 0x1eb700001eb8, + 0x1eb900001eba, + 0x1ebb00001ebc, + 0x1ebd00001ebe, + 0x1ebf00001ec0, + 0x1ec100001ec2, + 0x1ec300001ec4, + 0x1ec500001ec6, + 0x1ec700001ec8, + 0x1ec900001eca, + 0x1ecb00001ecc, + 0x1ecd00001ece, + 0x1ecf00001ed0, + 0x1ed100001ed2, + 0x1ed300001ed4, + 0x1ed500001ed6, + 0x1ed700001ed8, + 0x1ed900001eda, + 0x1edb00001edc, + 0x1edd00001ede, + 0x1edf00001ee0, + 0x1ee100001ee2, + 0x1ee300001ee4, + 0x1ee500001ee6, + 0x1ee700001ee8, + 0x1ee900001eea, + 0x1eeb00001eec, + 0x1eed00001eee, + 0x1eef00001ef0, + 0x1ef100001ef2, + 0x1ef300001ef4, + 0x1ef500001ef6, + 0x1ef700001ef8, + 0x1ef900001efa, + 0x1efb00001efc, + 0x1efd00001efe, + 0x1eff00001f08, + 0x1f1000001f16, + 0x1f2000001f28, + 0x1f3000001f38, + 0x1f4000001f46, + 0x1f5000001f58, + 0x1f6000001f68, + 0x1f7000001f71, + 0x1f7200001f73, + 0x1f7400001f75, + 0x1f7600001f77, + 0x1f7800001f79, + 0x1f7a00001f7b, + 0x1f7c00001f7d, + 0x1fb000001fb2, + 0x1fb600001fb7, + 0x1fc600001fc7, + 0x1fd000001fd3, + 0x1fd600001fd8, + 0x1fe000001fe3, + 0x1fe400001fe8, + 0x1ff600001ff7, + 0x214e0000214f, 0x218400002185, - 0x2C3000002C60, - 0x2C6100002C62, - 0x2C6500002C67, - 0x2C6800002C69, - 0x2C6A00002C6B, - 0x2C6C00002C6D, - 0x2C7100002C72, - 0x2C7300002C75, - 0x2C7600002C7C, - 0x2C8100002C82, - 0x2C8300002C84, - 0x2C8500002C86, - 0x2C8700002C88, - 0x2C8900002C8A, - 0x2C8B00002C8C, - 0x2C8D00002C8E, - 0x2C8F00002C90, - 0x2C9100002C92, - 0x2C9300002C94, - 0x2C9500002C96, - 0x2C9700002C98, - 0x2C9900002C9A, - 0x2C9B00002C9C, - 0x2C9D00002C9E, - 0x2C9F00002CA0, - 0x2CA100002CA2, - 0x2CA300002CA4, - 0x2CA500002CA6, - 0x2CA700002CA8, - 0x2CA900002CAA, - 0x2CAB00002CAC, - 0x2CAD00002CAE, - 0x2CAF00002CB0, - 0x2CB100002CB2, - 0x2CB300002CB4, - 0x2CB500002CB6, - 0x2CB700002CB8, - 0x2CB900002CBA, - 0x2CBB00002CBC, - 0x2CBD00002CBE, - 0x2CBF00002CC0, - 0x2CC100002CC2, - 0x2CC300002CC4, - 0x2CC500002CC6, - 0x2CC700002CC8, - 0x2CC900002CCA, - 0x2CCB00002CCC, - 0x2CCD00002CCE, - 0x2CCF00002CD0, - 0x2CD100002CD2, - 0x2CD300002CD4, - 0x2CD500002CD6, - 0x2CD700002CD8, - 0x2CD900002CDA, - 0x2CDB00002CDC, - 0x2CDD00002CDE, - 0x2CDF00002CE0, - 0x2CE100002CE2, - 0x2CE300002CE5, - 0x2CEC00002CED, - 0x2CEE00002CF2, - 0x2CF300002CF4, - 0x2D0000002D26, - 0x2D2700002D28, - 0x2D2D00002D2E, - 0x2D3000002D68, - 0x2D7F00002D97, - 0x2DA000002DA7, - 0x2DA800002DAF, - 0x2DB000002DB7, - 0x2DB800002DBF, - 0x2DC000002DC7, - 0x2DC800002DCF, - 0x2DD000002DD7, - 0x2DD800002DDF, - 0x2DE000002E00, - 0x2E2F00002E30, + 0x2c3000002c60, + 0x2c6100002c62, + 0x2c6500002c67, + 0x2c6800002c69, + 0x2c6a00002c6b, + 0x2c6c00002c6d, + 0x2c7100002c72, + 0x2c7300002c75, + 0x2c7600002c7c, + 0x2c8100002c82, + 0x2c8300002c84, + 0x2c8500002c86, + 0x2c8700002c88, + 0x2c8900002c8a, + 0x2c8b00002c8c, + 0x2c8d00002c8e, + 0x2c8f00002c90, + 0x2c9100002c92, + 0x2c9300002c94, + 0x2c9500002c96, + 0x2c9700002c98, + 0x2c9900002c9a, + 0x2c9b00002c9c, + 0x2c9d00002c9e, + 0x2c9f00002ca0, + 0x2ca100002ca2, + 0x2ca300002ca4, + 0x2ca500002ca6, + 0x2ca700002ca8, + 0x2ca900002caa, + 0x2cab00002cac, + 0x2cad00002cae, + 0x2caf00002cb0, + 0x2cb100002cb2, + 0x2cb300002cb4, + 0x2cb500002cb6, + 0x2cb700002cb8, + 0x2cb900002cba, + 0x2cbb00002cbc, + 0x2cbd00002cbe, + 0x2cbf00002cc0, + 0x2cc100002cc2, + 0x2cc300002cc4, + 0x2cc500002cc6, + 0x2cc700002cc8, + 0x2cc900002cca, + 0x2ccb00002ccc, + 0x2ccd00002cce, + 0x2ccf00002cd0, + 0x2cd100002cd2, + 0x2cd300002cd4, + 0x2cd500002cd6, + 0x2cd700002cd8, + 0x2cd900002cda, + 0x2cdb00002cdc, + 0x2cdd00002cde, + 0x2cdf00002ce0, + 0x2ce100002ce2, + 0x2ce300002ce5, + 0x2cec00002ced, + 0x2cee00002cf2, + 0x2cf300002cf4, + 0x2d0000002d26, + 0x2d2700002d28, + 0x2d2d00002d2e, + 0x2d3000002d68, + 0x2d7f00002d97, + 0x2da000002da7, + 0x2da800002daf, + 0x2db000002db7, + 0x2db800002dbf, + 0x2dc000002dc7, + 0x2dc800002dcf, + 0x2dd000002dd7, + 0x2dd800002ddf, + 0x2de000002e00, + 0x2e2f00002e30, 0x300500003008, - 0x302A0000302E, - 0x303C0000303D, + 0x302a0000302e, + 0x303c0000303d, 0x304100003097, - 0x30990000309B, - 0x309D0000309F, - 0x30A1000030FB, - 0x30FC000030FF, + 0x30990000309b, + 0x309d0000309f, + 0x30a1000030fb, + 0x30fc000030ff, 0x310500003130, - 0x31A0000031C0, - 0x31F000003200, - 0x340000004DC0, - 0x4E000000A48D, - 0xA4D00000A4FE, - 0xA5000000A60D, - 0xA6100000A62C, - 0xA6410000A642, - 0xA6430000A644, - 0xA6450000A646, - 0xA6470000A648, - 0xA6490000A64A, - 0xA64B0000A64C, - 0xA64D0000A64E, - 0xA64F0000A650, - 0xA6510000A652, - 0xA6530000A654, - 0xA6550000A656, - 0xA6570000A658, - 0xA6590000A65A, - 0xA65B0000A65C, - 0xA65D0000A65E, - 0xA65F0000A660, - 0xA6610000A662, - 0xA6630000A664, - 0xA6650000A666, - 0xA6670000A668, - 0xA6690000A66A, - 0xA66B0000A66C, - 0xA66D0000A670, - 0xA6740000A67E, - 0xA67F0000A680, - 0xA6810000A682, - 0xA6830000A684, - 0xA6850000A686, - 0xA6870000A688, - 0xA6890000A68A, - 0xA68B0000A68C, - 0xA68D0000A68E, - 0xA68F0000A690, - 0xA6910000A692, - 0xA6930000A694, - 0xA6950000A696, - 0xA6970000A698, - 0xA6990000A69A, - 0xA69B0000A69C, - 0xA69E0000A6E6, - 0xA6F00000A6F2, - 0xA7170000A720, - 0xA7230000A724, - 0xA7250000A726, - 0xA7270000A728, - 0xA7290000A72A, - 0xA72B0000A72C, - 0xA72D0000A72E, - 0xA72F0000A732, - 0xA7330000A734, - 0xA7350000A736, - 0xA7370000A738, - 0xA7390000A73A, - 0xA73B0000A73C, - 0xA73D0000A73E, - 0xA73F0000A740, - 0xA7410000A742, - 0xA7430000A744, - 0xA7450000A746, - 0xA7470000A748, - 0xA7490000A74A, - 0xA74B0000A74C, - 0xA74D0000A74E, - 0xA74F0000A750, - 0xA7510000A752, - 0xA7530000A754, - 0xA7550000A756, - 0xA7570000A758, - 0xA7590000A75A, - 0xA75B0000A75C, - 0xA75D0000A75E, - 0xA75F0000A760, - 0xA7610000A762, - 0xA7630000A764, - 0xA7650000A766, - 0xA7670000A768, - 0xA7690000A76A, - 0xA76B0000A76C, - 0xA76D0000A76E, - 0xA76F0000A770, - 0xA7710000A779, - 0xA77A0000A77B, - 0xA77C0000A77D, - 0xA77F0000A780, - 0xA7810000A782, - 0xA7830000A784, - 0xA7850000A786, - 0xA7870000A789, - 0xA78C0000A78D, - 0xA78E0000A790, - 0xA7910000A792, - 0xA7930000A796, - 0xA7970000A798, - 0xA7990000A79A, - 0xA79B0000A79C, - 0xA79D0000A79E, - 0xA79F0000A7A0, - 0xA7A10000A7A2, - 0xA7A30000A7A4, - 0xA7A50000A7A6, - 0xA7A70000A7A8, - 0xA7A90000A7AA, - 0xA7AF0000A7B0, - 0xA7B50000A7B6, - 0xA7B70000A7B8, - 0xA7B90000A7BA, - 0xA7BB0000A7BC, - 0xA7BD0000A7BE, - 0xA7BF0000A7C0, - 0xA7C10000A7C2, - 0xA7C30000A7C4, - 0xA7C80000A7C9, - 0xA7CA0000A7CB, - 0xA7D10000A7D2, - 0xA7D30000A7D4, - 0xA7D50000A7D6, - 0xA7D70000A7D8, - 0xA7D90000A7DA, - 0xA7F60000A7F8, - 0xA7FA0000A828, - 0xA82C0000A82D, - 0xA8400000A874, - 0xA8800000A8C6, - 0xA8D00000A8DA, - 0xA8E00000A8F8, - 0xA8FB0000A8FC, - 0xA8FD0000A92E, - 0xA9300000A954, - 0xA9800000A9C1, - 0xA9CF0000A9DA, - 0xA9E00000A9FF, - 0xAA000000AA37, - 0xAA400000AA4E, - 0xAA500000AA5A, - 0xAA600000AA77, - 0xAA7A0000AAC3, - 0xAADB0000AADE, - 0xAAE00000AAF0, - 0xAAF20000AAF7, - 0xAB010000AB07, - 0xAB090000AB0F, - 0xAB110000AB17, - 0xAB200000AB27, - 0xAB280000AB2F, - 0xAB300000AB5B, - 0xAB600000AB69, - 0xABC00000ABEB, - 0xABEC0000ABEE, - 0xABF00000ABFA, - 0xAC000000D7A4, - 0xFA0E0000FA10, - 0xFA110000FA12, - 0xFA130000FA15, - 0xFA1F0000FA20, - 0xFA210000FA22, - 0xFA230000FA25, - 0xFA270000FA2A, - 0xFB1E0000FB1F, - 0xFE200000FE30, - 0xFE730000FE74, - 0x100000001000C, - 0x1000D00010027, - 0x100280001003B, - 0x1003C0001003E, - 0x1003F0001004E, - 0x100500001005E, - 0x10080000100FB, - 0x101FD000101FE, - 0x102800001029D, - 0x102A0000102D1, - 0x102E0000102E1, + 0x31a0000031c0, + 0x31f000003200, + 0x340000004dc0, + 0x4e000000a48d, + 0xa4d00000a4fe, + 0xa5000000a60d, + 0xa6100000a62c, + 0xa6410000a642, + 0xa6430000a644, + 0xa6450000a646, + 0xa6470000a648, + 0xa6490000a64a, + 0xa64b0000a64c, + 0xa64d0000a64e, + 0xa64f0000a650, + 0xa6510000a652, + 0xa6530000a654, + 0xa6550000a656, + 0xa6570000a658, + 0xa6590000a65a, + 0xa65b0000a65c, + 0xa65d0000a65e, + 0xa65f0000a660, + 0xa6610000a662, + 0xa6630000a664, + 0xa6650000a666, + 0xa6670000a668, + 0xa6690000a66a, + 0xa66b0000a66c, + 0xa66d0000a670, + 0xa6740000a67e, + 0xa67f0000a680, + 0xa6810000a682, + 0xa6830000a684, + 0xa6850000a686, + 0xa6870000a688, + 0xa6890000a68a, + 0xa68b0000a68c, + 0xa68d0000a68e, + 0xa68f0000a690, + 0xa6910000a692, + 0xa6930000a694, + 0xa6950000a696, + 0xa6970000a698, + 0xa6990000a69a, + 0xa69b0000a69c, + 0xa69e0000a6e6, + 0xa6f00000a6f2, + 0xa7170000a720, + 0xa7230000a724, + 0xa7250000a726, + 0xa7270000a728, + 0xa7290000a72a, + 0xa72b0000a72c, + 0xa72d0000a72e, + 0xa72f0000a732, + 0xa7330000a734, + 0xa7350000a736, + 0xa7370000a738, + 0xa7390000a73a, + 0xa73b0000a73c, + 0xa73d0000a73e, + 0xa73f0000a740, + 0xa7410000a742, + 0xa7430000a744, + 0xa7450000a746, + 0xa7470000a748, + 0xa7490000a74a, + 0xa74b0000a74c, + 0xa74d0000a74e, + 0xa74f0000a750, + 0xa7510000a752, + 0xa7530000a754, + 0xa7550000a756, + 0xa7570000a758, + 0xa7590000a75a, + 0xa75b0000a75c, + 0xa75d0000a75e, + 0xa75f0000a760, + 0xa7610000a762, + 0xa7630000a764, + 0xa7650000a766, + 0xa7670000a768, + 0xa7690000a76a, + 0xa76b0000a76c, + 0xa76d0000a76e, + 0xa76f0000a770, + 0xa7710000a779, + 0xa77a0000a77b, + 0xa77c0000a77d, + 0xa77f0000a780, + 0xa7810000a782, + 0xa7830000a784, + 0xa7850000a786, + 0xa7870000a789, + 0xa78c0000a78d, + 0xa78e0000a790, + 0xa7910000a792, + 0xa7930000a796, + 0xa7970000a798, + 0xa7990000a79a, + 0xa79b0000a79c, + 0xa79d0000a79e, + 0xa79f0000a7a0, + 0xa7a10000a7a2, + 0xa7a30000a7a4, + 0xa7a50000a7a6, + 0xa7a70000a7a8, + 0xa7a90000a7aa, + 0xa7af0000a7b0, + 0xa7b50000a7b6, + 0xa7b70000a7b8, + 0xa7b90000a7ba, + 0xa7bb0000a7bc, + 0xa7bd0000a7be, + 0xa7bf0000a7c0, + 0xa7c10000a7c2, + 0xa7c30000a7c4, + 0xa7c80000a7c9, + 0xa7ca0000a7cb, + 0xa7d10000a7d2, + 0xa7d30000a7d4, + 0xa7d50000a7d6, + 0xa7d70000a7d8, + 0xa7d90000a7da, + 0xa7f20000a7f5, + 0xa7f60000a7f8, + 0xa7fa0000a828, + 0xa82c0000a82d, + 0xa8400000a874, + 0xa8800000a8c6, + 0xa8d00000a8da, + 0xa8e00000a8f8, + 0xa8fb0000a8fc, + 0xa8fd0000a92e, + 0xa9300000a954, + 0xa9800000a9c1, + 0xa9cf0000a9da, + 0xa9e00000a9ff, + 0xaa000000aa37, + 0xaa400000aa4e, + 0xaa500000aa5a, + 0xaa600000aa77, + 0xaa7a0000aac3, + 0xaadb0000aade, + 0xaae00000aaf0, + 0xaaf20000aaf7, + 0xab010000ab07, + 0xab090000ab0f, + 0xab110000ab17, + 0xab200000ab27, + 0xab280000ab2f, + 0xab300000ab5b, + 0xab600000ab69, + 0xabc00000abeb, + 0xabec0000abee, + 0xabf00000abfa, + 0xac000000d7a4, + 0xfa0e0000fa10, + 0xfa110000fa12, + 0xfa130000fa15, + 0xfa1f0000fa20, + 0xfa210000fa22, + 0xfa230000fa25, + 0xfa270000fa2a, + 0xfb1e0000fb1f, + 0xfe200000fe30, + 0xfe730000fe74, + 0x100000001000c, + 0x1000d00010027, + 0x100280001003b, + 0x1003c0001003e, + 0x1003f0001004e, + 0x100500001005e, + 0x10080000100fb, + 0x101fd000101fe, + 0x102800001029d, + 0x102a0000102d1, + 0x102e0000102e1, 0x1030000010320, - 0x1032D00010341, - 0x103420001034A, - 0x103500001037B, - 0x103800001039E, - 0x103A0000103C4, - 0x103C8000103D0, - 0x104280001049E, - 0x104A0000104AA, - 0x104D8000104FC, + 0x1032d00010341, + 0x103420001034a, + 0x103500001037b, + 0x103800001039e, + 0x103a0000103c4, + 0x103c8000103d0, + 0x104280001049e, + 0x104a0000104aa, + 0x104d8000104fc, 0x1050000010528, 0x1053000010564, - 0x10597000105A2, - 0x105A3000105B2, - 0x105B3000105BA, - 0x105BB000105BD, + 0x10597000105a2, + 0x105a3000105b2, + 0x105b3000105ba, + 0x105bb000105bd, 0x1060000010737, 0x1074000010756, 0x1076000010768, - 0x1078000010781, + 0x1078000010786, + 0x10787000107b1, + 0x107b2000107bb, 0x1080000010806, 0x1080800010809, - 0x1080A00010836, + 0x1080a00010836, 0x1083700010839, - 0x1083C0001083D, - 0x1083F00010856, + 0x1083c0001083d, + 0x1083f00010856, 0x1086000010877, - 0x108800001089F, - 0x108E0000108F3, - 0x108F4000108F6, + 0x108800001089f, + 0x108e0000108f3, + 0x108f4000108f6, 0x1090000010916, - 0x109200001093A, - 0x10980000109B8, - 0x109BE000109C0, - 0x10A0000010A04, - 0x10A0500010A07, - 0x10A0C00010A14, - 0x10A1500010A18, - 0x10A1900010A36, - 0x10A3800010A3B, - 0x10A3F00010A40, - 0x10A6000010A7D, - 0x10A8000010A9D, - 0x10AC000010AC8, - 0x10AC900010AE7, - 0x10B0000010B36, - 0x10B4000010B56, - 0x10B6000010B73, - 0x10B8000010B92, - 0x10C0000010C49, - 0x10CC000010CF3, - 0x10D0000010D28, - 0x10D3000010D3A, - 0x10E8000010EAA, - 0x10EAB00010EAD, - 0x10EB000010EB2, - 0x10EFD00010F1D, - 0x10F2700010F28, - 0x10F3000010F51, - 0x10F7000010F86, - 0x10FB000010FC5, - 0x10FE000010FF7, + 0x109200001093a, + 0x10980000109b8, + 0x109be000109c0, + 0x10a0000010a04, + 0x10a0500010a07, + 0x10a0c00010a14, + 0x10a1500010a18, + 0x10a1900010a36, + 0x10a3800010a3b, + 0x10a3f00010a40, + 0x10a6000010a7d, + 0x10a8000010a9d, + 0x10ac000010ac8, + 0x10ac900010ae7, + 0x10b0000010b36, + 0x10b4000010b56, + 0x10b6000010b73, + 0x10b8000010b92, + 0x10c0000010c49, + 0x10cc000010cf3, + 0x10d0000010d28, + 0x10d3000010d3a, + 0x10e8000010eaa, + 0x10eab00010ead, + 0x10eb000010eb2, + 0x10efd00010f1d, + 0x10f2700010f28, + 0x10f3000010f51, + 0x10f7000010f86, + 0x10fb000010fc5, + 0x10fe000010ff7, 0x1100000011047, 0x1106600011076, - 0x1107F000110BB, - 0x110C2000110C3, - 0x110D0000110E9, - 0x110F0000110FA, + 0x1107f000110bb, + 0x110c2000110c3, + 0x110d0000110e9, + 0x110f0000110fa, 0x1110000011135, 0x1113600011140, 0x1114400011148, 0x1115000011174, 0x1117600011177, - 0x11180000111C5, - 0x111C9000111CD, - 0x111CE000111DB, - 0x111DC000111DD, + 0x11180000111c5, + 0x111c9000111cd, + 0x111ce000111db, + 0x111dc000111dd, 0x1120000011212, 0x1121300011238, - 0x1123E00011242, + 0x1123e00011242, 0x1128000011287, 0x1128800011289, - 0x1128A0001128E, - 0x1128F0001129E, - 0x1129F000112A9, - 0x112B0000112EB, - 0x112F0000112FA, + 0x1128a0001128e, + 0x1128f0001129e, + 0x1129f000112a9, + 0x112b0000112eb, + 0x112f0000112fa, 0x1130000011304, - 0x113050001130D, - 0x1130F00011311, + 0x113050001130d, + 0x1130f00011311, 0x1131300011329, - 0x1132A00011331, + 0x1132a00011331, 0x1133200011334, - 0x113350001133A, - 0x1133B00011345, + 0x113350001133a, + 0x1133b00011345, 0x1134700011349, - 0x1134B0001134E, + 0x1134b0001134e, 0x1135000011351, 0x1135700011358, - 0x1135D00011364, - 0x113660001136D, + 0x1135d00011364, + 0x113660001136d, 0x1137000011375, - 0x114000001144B, - 0x114500001145A, - 0x1145E00011462, - 0x11480000114C6, - 0x114C7000114C8, - 0x114D0000114DA, - 0x11580000115B6, - 0x115B8000115C1, - 0x115D8000115DE, + 0x114000001144b, + 0x114500001145a, + 0x1145e00011462, + 0x11480000114c6, + 0x114c7000114c8, + 0x114d0000114da, + 0x11580000115b6, + 0x115b8000115c1, + 0x115d8000115de, 0x1160000011641, 0x1164400011645, - 0x116500001165A, - 0x11680000116B9, - 0x116C0000116CA, - 0x117000001171B, - 0x1171D0001172C, - 0x117300001173A, + 0x116500001165a, + 0x11680000116b9, + 0x116c0000116ca, + 0x117000001171b, + 0x1171d0001172c, + 0x117300001173a, 0x1174000011747, - 0x118000001183B, - 0x118C0000118EA, - 0x118FF00011907, - 0x119090001190A, - 0x1190C00011914, + 0x118000001183b, + 0x118c0000118ea, + 0x118ff00011907, + 0x119090001190a, + 0x1190c00011914, 0x1191500011917, 0x1191800011936, 0x1193700011939, - 0x1193B00011944, - 0x119500001195A, - 0x119A0000119A8, - 0x119AA000119D8, - 0x119DA000119E2, - 0x119E3000119E5, - 0x11A0000011A3F, - 0x11A4700011A48, - 0x11A5000011A9A, - 0x11A9D00011A9E, - 0x11AB000011AF9, - 0x11C0000011C09, - 0x11C0A00011C37, - 0x11C3800011C41, - 0x11C5000011C5A, - 0x11C7200011C90, - 0x11C9200011CA8, - 0x11CA900011CB7, - 0x11D0000011D07, - 0x11D0800011D0A, - 0x11D0B00011D37, - 0x11D3A00011D3B, - 0x11D3C00011D3E, - 0x11D3F00011D48, - 0x11D5000011D5A, - 0x11D6000011D66, - 0x11D6700011D69, - 0x11D6A00011D8F, - 0x11D9000011D92, - 0x11D9300011D99, - 0x11DA000011DAA, - 0x11EE000011EF7, - 0x11F0000011F11, - 0x11F1200011F3B, - 0x11F3E00011F43, - 0x11F5000011F5A, - 0x11FB000011FB1, - 0x120000001239A, + 0x1193b00011944, + 0x119500001195a, + 0x119a0000119a8, + 0x119aa000119d8, + 0x119da000119e2, + 0x119e3000119e5, + 0x11a0000011a3f, + 0x11a4700011a48, + 0x11a5000011a9a, + 0x11a9d00011a9e, + 0x11ab000011af9, + 0x11c0000011c09, + 0x11c0a00011c37, + 0x11c3800011c41, + 0x11c5000011c5a, + 0x11c7200011c90, + 0x11c9200011ca8, + 0x11ca900011cb7, + 0x11d0000011d07, + 0x11d0800011d0a, + 0x11d0b00011d37, + 0x11d3a00011d3b, + 0x11d3c00011d3e, + 0x11d3f00011d48, + 0x11d5000011d5a, + 0x11d6000011d66, + 0x11d6700011d69, + 0x11d6a00011d8f, + 0x11d9000011d92, + 0x11d9300011d99, + 0x11da000011daa, + 0x11ee000011ef7, + 0x11f0000011f11, + 0x11f1200011f3b, + 0x11f3e00011f43, + 0x11f5000011f5a, + 0x11fb000011fb1, + 0x120000001239a, 0x1248000012544, - 0x12F9000012FF1, + 0x12f9000012ff1, 0x1300000013430, 0x1344000013456, 0x1440000014647, - 0x1680000016A39, - 0x16A4000016A5F, - 0x16A6000016A6A, - 0x16A7000016ABF, - 0x16AC000016ACA, - 0x16AD000016AEE, - 0x16AF000016AF5, - 0x16B0000016B37, - 0x16B4000016B44, - 0x16B5000016B5A, - 0x16B6300016B78, - 0x16B7D00016B90, - 0x16E6000016E80, - 0x16F0000016F4B, - 0x16F4F00016F88, - 0x16F8F00016FA0, - 0x16FE000016FE2, - 0x16FE300016FE5, - 0x16FF000016FF2, - 0x17000000187F8, - 0x1880000018CD6, - 0x18D0000018D09, - 0x1AFF00001AFF4, - 0x1AFF50001AFFC, - 0x1AFFD0001AFFF, - 0x1B0000001B123, - 0x1B1320001B133, - 0x1B1500001B153, - 0x1B1550001B156, - 0x1B1640001B168, - 0x1B1700001B2FC, - 0x1BC000001BC6B, - 0x1BC700001BC7D, - 0x1BC800001BC89, - 0x1BC900001BC9A, - 0x1BC9D0001BC9F, - 0x1CF000001CF2E, - 0x1CF300001CF47, - 0x1DA000001DA37, - 0x1DA3B0001DA6D, - 0x1DA750001DA76, - 0x1DA840001DA85, - 0x1DA9B0001DAA0, - 0x1DAA10001DAB0, - 0x1DF000001DF1F, - 0x1DF250001DF2B, - 0x1E0000001E007, - 0x1E0080001E019, - 0x1E01B0001E022, - 0x1E0230001E025, - 0x1E0260001E02B, - 0x1E08F0001E090, - 0x1E1000001E12D, - 0x1E1300001E13E, - 0x1E1400001E14A, - 0x1E14E0001E14F, - 0x1E2900001E2AF, - 0x1E2C00001E2FA, - 0x1E4D00001E4FA, - 0x1E7E00001E7E7, - 0x1E7E80001E7EC, - 0x1E7ED0001E7EF, - 0x1E7F00001E7FF, - 0x1E8000001E8C5, - 0x1E8D00001E8D7, - 0x1E9220001E94C, - 0x1E9500001E95A, - 0x200000002A6E0, - 0x2A7000002B73A, - 0x2B7400002B81E, - 0x2B8200002CEA2, - 0x2CEB00002EBE1, - 0x2EBF00002EE5E, - 0x300000003134B, - 0x31350000323B0, + 0x1680000016a39, + 0x16a4000016a5f, + 0x16a6000016a6a, + 0x16a7000016abf, + 0x16ac000016aca, + 0x16ad000016aee, + 0x16af000016af5, + 0x16b0000016b37, + 0x16b4000016b44, + 0x16b5000016b5a, + 0x16b6300016b78, + 0x16b7d00016b90, + 0x16e6000016e80, + 0x16f0000016f4b, + 0x16f4f00016f88, + 0x16f8f00016fa0, + 0x16fe000016fe2, + 0x16fe300016fe5, + 0x16ff000016ff2, + 0x17000000187f8, + 0x1880000018cd6, + 0x18d0000018d09, + 0x1aff00001aff4, + 0x1aff50001affc, + 0x1affd0001afff, + 0x1b0000001b123, + 0x1b1320001b133, + 0x1b1500001b153, + 0x1b1550001b156, + 0x1b1640001b168, + 0x1b1700001b2fc, + 0x1bc000001bc6b, + 0x1bc700001bc7d, + 0x1bc800001bc89, + 0x1bc900001bc9a, + 0x1bc9d0001bc9f, + 0x1cf000001cf2e, + 0x1cf300001cf47, + 0x1da000001da37, + 0x1da3b0001da6d, + 0x1da750001da76, + 0x1da840001da85, + 0x1da9b0001daa0, + 0x1daa10001dab0, + 0x1df000001df1f, + 0x1df250001df2b, + 0x1e0000001e007, + 0x1e0080001e019, + 0x1e01b0001e022, + 0x1e0230001e025, + 0x1e0260001e02b, + 0x1e0300001e06e, + 0x1e08f0001e090, + 0x1e1000001e12d, + 0x1e1300001e13e, + 0x1e1400001e14a, + 0x1e14e0001e14f, + 0x1e2900001e2af, + 0x1e2c00001e2fa, + 0x1e4d00001e4fa, + 0x1e7e00001e7e7, + 0x1e7e80001e7ec, + 0x1e7ed0001e7ef, + 0x1e7f00001e7ff, + 0x1e8000001e8c5, + 0x1e8d00001e8d7, + 0x1e9220001e94c, + 0x1e9500001e95a, + 0x200000002a6e0, + 0x2a7000002b73a, + 0x2b7400002b81e, + 0x2b8200002cea2, + 0x2ceb00002ebe1, + 0x300000003134b, + 0x31350000323b0, ), - "CONTEXTJ": (0x200C0000200E,), - "CONTEXTO": ( - 0xB7000000B8, + 'CONTEXTJ': ( + 0x200c0000200e, + ), + 'CONTEXTO': ( + 0xb7000000b8, 0x37500000376, - 0x5F3000005F5, - 0x6600000066A, - 0x6F0000006FA, - 0x30FB000030FC, + 0x5f3000005f5, + 0x6600000066a, + 0x6f0000006fa, + 0x30fb000030fc, ), } diff --git a/venv1/Lib/site-packages/pip/_vendor/idna/intranges.py b/venv1/Lib/site-packages/pip/_vendor/idna/intranges.py index 7bfaa8d8..6a43b047 100644 --- a/venv1/Lib/site-packages/pip/_vendor/idna/intranges.py +++ b/venv1/Lib/site-packages/pip/_vendor/idna/intranges.py @@ -8,7 +8,6 @@ import bisect from typing import List, Tuple - def intranges_from_list(list_: List[int]) -> Tuple[int, ...]: """Represent a list of integers as a sequence of ranges: ((start_0, end_0), (start_1, end_1), ...), such that the original @@ -21,20 +20,18 @@ def intranges_from_list(list_: List[int]) -> Tuple[int, ...]: ranges = [] last_write = -1 for i in range(len(sorted_list)): - if i + 1 < len(sorted_list): - if sorted_list[i] == sorted_list[i + 1] - 1: + if i+1 < len(sorted_list): + if sorted_list[i] == sorted_list[i+1]-1: continue - current_range = sorted_list[last_write + 1 : i + 1] + current_range = sorted_list[last_write+1:i+1] ranges.append(_encode_range(current_range[0], current_range[-1] + 1)) last_write = i return tuple(ranges) - def _encode_range(start: int, end: int) -> int: return (start << 32) | end - def _decode_range(r: int) -> Tuple[int, int]: return (r >> 32), (r & ((1 << 32) - 1)) @@ -46,7 +43,7 @@ def intranges_contain(int_: int, ranges: Tuple[int, ...]) -> bool: # we could be immediately ahead of a tuple (start, end) # with start < int_ <= end if pos > 0: - left, right = _decode_range(ranges[pos - 1]) + left, right = _decode_range(ranges[pos-1]) if left <= int_ < right: return True # or we could be immediately behind a tuple (int_, end) diff --git a/venv1/Lib/site-packages/pip/_vendor/idna/package_data.py b/venv1/Lib/site-packages/pip/_vendor/idna/package_data.py index 514ff7e2..8501893b 100644 --- a/venv1/Lib/site-packages/pip/_vendor/idna/package_data.py +++ b/venv1/Lib/site-packages/pip/_vendor/idna/package_data.py @@ -1 +1,2 @@ -__version__ = "3.10" +__version__ = '3.4' + diff --git a/venv1/Lib/site-packages/pip/_vendor/idna/py.typed b/venv1/Lib/site-packages/pip/_vendor/idna/py.typed deleted file mode 100644 index e69de29b..00000000 diff --git a/venv1/Lib/site-packages/pip/_vendor/idna/uts46data.py b/venv1/Lib/site-packages/pip/_vendor/idna/uts46data.py index eb894327..186796c1 100644 --- a/venv1/Lib/site-packages/pip/_vendor/idna/uts46data.py +++ b/venv1/Lib/site-packages/pip/_vendor/idna/uts46data.py @@ -3,8598 +3,8517 @@ from typing import List, Tuple, Union -"""IDNA Mapping Table from UTS46.""" - -__version__ = "15.1.0" +"""IDNA Mapping Table from UTS46.""" +__version__ = '15.0.0' def _seg_0() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x0, "3"), - (0x1, "3"), - (0x2, "3"), - (0x3, "3"), - (0x4, "3"), - (0x5, "3"), - (0x6, "3"), - (0x7, "3"), - (0x8, "3"), - (0x9, "3"), - (0xA, "3"), - (0xB, "3"), - (0xC, "3"), - (0xD, "3"), - (0xE, "3"), - (0xF, "3"), - (0x10, "3"), - (0x11, "3"), - (0x12, "3"), - (0x13, "3"), - (0x14, "3"), - (0x15, "3"), - (0x16, "3"), - (0x17, "3"), - (0x18, "3"), - (0x19, "3"), - (0x1A, "3"), - (0x1B, "3"), - (0x1C, "3"), - (0x1D, "3"), - (0x1E, "3"), - (0x1F, "3"), - (0x20, "3"), - (0x21, "3"), - (0x22, "3"), - (0x23, "3"), - (0x24, "3"), - (0x25, "3"), - (0x26, "3"), - (0x27, "3"), - (0x28, "3"), - (0x29, "3"), - (0x2A, "3"), - (0x2B, "3"), - (0x2C, "3"), - (0x2D, "V"), - (0x2E, "V"), - (0x2F, "3"), - (0x30, "V"), - (0x31, "V"), - (0x32, "V"), - (0x33, "V"), - (0x34, "V"), - (0x35, "V"), - (0x36, "V"), - (0x37, "V"), - (0x38, "V"), - (0x39, "V"), - (0x3A, "3"), - (0x3B, "3"), - (0x3C, "3"), - (0x3D, "3"), - (0x3E, "3"), - (0x3F, "3"), - (0x40, "3"), - (0x41, "M", "a"), - (0x42, "M", "b"), - (0x43, "M", "c"), - (0x44, "M", "d"), - (0x45, "M", "e"), - (0x46, "M", "f"), - (0x47, "M", "g"), - (0x48, "M", "h"), - (0x49, "M", "i"), - (0x4A, "M", "j"), - (0x4B, "M", "k"), - (0x4C, "M", "l"), - (0x4D, "M", "m"), - (0x4E, "M", "n"), - (0x4F, "M", "o"), - (0x50, "M", "p"), - (0x51, "M", "q"), - (0x52, "M", "r"), - (0x53, "M", "s"), - (0x54, "M", "t"), - (0x55, "M", "u"), - (0x56, "M", "v"), - (0x57, "M", "w"), - (0x58, "M", "x"), - (0x59, "M", "y"), - (0x5A, "M", "z"), - (0x5B, "3"), - (0x5C, "3"), - (0x5D, "3"), - (0x5E, "3"), - (0x5F, "3"), - (0x60, "3"), - (0x61, "V"), - (0x62, "V"), - (0x63, "V"), + (0x0, '3'), + (0x1, '3'), + (0x2, '3'), + (0x3, '3'), + (0x4, '3'), + (0x5, '3'), + (0x6, '3'), + (0x7, '3'), + (0x8, '3'), + (0x9, '3'), + (0xA, '3'), + (0xB, '3'), + (0xC, '3'), + (0xD, '3'), + (0xE, '3'), + (0xF, '3'), + (0x10, '3'), + (0x11, '3'), + (0x12, '3'), + (0x13, '3'), + (0x14, '3'), + (0x15, '3'), + (0x16, '3'), + (0x17, '3'), + (0x18, '3'), + (0x19, '3'), + (0x1A, '3'), + (0x1B, '3'), + (0x1C, '3'), + (0x1D, '3'), + (0x1E, '3'), + (0x1F, '3'), + (0x20, '3'), + (0x21, '3'), + (0x22, '3'), + (0x23, '3'), + (0x24, '3'), + (0x25, '3'), + (0x26, '3'), + (0x27, '3'), + (0x28, '3'), + (0x29, '3'), + (0x2A, '3'), + (0x2B, '3'), + (0x2C, '3'), + (0x2D, 'V'), + (0x2E, 'V'), + (0x2F, '3'), + (0x30, 'V'), + (0x31, 'V'), + (0x32, 'V'), + (0x33, 'V'), + (0x34, 'V'), + (0x35, 'V'), + (0x36, 'V'), + (0x37, 'V'), + (0x38, 'V'), + (0x39, 'V'), + (0x3A, '3'), + (0x3B, '3'), + (0x3C, '3'), + (0x3D, '3'), + (0x3E, '3'), + (0x3F, '3'), + (0x40, '3'), + (0x41, 'M', 'a'), + (0x42, 'M', 'b'), + (0x43, 'M', 'c'), + (0x44, 'M', 'd'), + (0x45, 'M', 'e'), + (0x46, 'M', 'f'), + (0x47, 'M', 'g'), + (0x48, 'M', 'h'), + (0x49, 'M', 'i'), + (0x4A, 'M', 'j'), + (0x4B, 'M', 'k'), + (0x4C, 'M', 'l'), + (0x4D, 'M', 'm'), + (0x4E, 'M', 'n'), + (0x4F, 'M', 'o'), + (0x50, 'M', 'p'), + (0x51, 'M', 'q'), + (0x52, 'M', 'r'), + (0x53, 'M', 's'), + (0x54, 'M', 't'), + (0x55, 'M', 'u'), + (0x56, 'M', 'v'), + (0x57, 'M', 'w'), + (0x58, 'M', 'x'), + (0x59, 'M', 'y'), + (0x5A, 'M', 'z'), + (0x5B, '3'), + (0x5C, '3'), + (0x5D, '3'), + (0x5E, '3'), + (0x5F, '3'), + (0x60, '3'), + (0x61, 'V'), + (0x62, 'V'), + (0x63, 'V'), ] - def _seg_1() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x64, "V"), - (0x65, "V"), - (0x66, "V"), - (0x67, "V"), - (0x68, "V"), - (0x69, "V"), - (0x6A, "V"), - (0x6B, "V"), - (0x6C, "V"), - (0x6D, "V"), - (0x6E, "V"), - (0x6F, "V"), - (0x70, "V"), - (0x71, "V"), - (0x72, "V"), - (0x73, "V"), - (0x74, "V"), - (0x75, "V"), - (0x76, "V"), - (0x77, "V"), - (0x78, "V"), - (0x79, "V"), - (0x7A, "V"), - (0x7B, "3"), - (0x7C, "3"), - (0x7D, "3"), - (0x7E, "3"), - (0x7F, "3"), - (0x80, "X"), - (0x81, "X"), - (0x82, "X"), - (0x83, "X"), - (0x84, "X"), - (0x85, "X"), - (0x86, "X"), - (0x87, "X"), - (0x88, "X"), - (0x89, "X"), - (0x8A, "X"), - (0x8B, "X"), - (0x8C, "X"), - (0x8D, "X"), - (0x8E, "X"), - (0x8F, "X"), - (0x90, "X"), - (0x91, "X"), - (0x92, "X"), - (0x93, "X"), - (0x94, "X"), - (0x95, "X"), - (0x96, "X"), - (0x97, "X"), - (0x98, "X"), - (0x99, "X"), - (0x9A, "X"), - (0x9B, "X"), - (0x9C, "X"), - (0x9D, "X"), - (0x9E, "X"), - (0x9F, "X"), - (0xA0, "3", " "), - (0xA1, "V"), - (0xA2, "V"), - (0xA3, "V"), - (0xA4, "V"), - (0xA5, "V"), - (0xA6, "V"), - (0xA7, "V"), - (0xA8, "3", " ̈"), - (0xA9, "V"), - (0xAA, "M", "a"), - (0xAB, "V"), - (0xAC, "V"), - (0xAD, "I"), - (0xAE, "V"), - (0xAF, "3", " ̄"), - (0xB0, "V"), - (0xB1, "V"), - (0xB2, "M", "2"), - (0xB3, "M", "3"), - (0xB4, "3", " ́"), - (0xB5, "M", "μ"), - (0xB6, "V"), - (0xB7, "V"), - (0xB8, "3", " ̧"), - (0xB9, "M", "1"), - (0xBA, "M", "o"), - (0xBB, "V"), - (0xBC, "M", "1⁄4"), - (0xBD, "M", "1⁄2"), - (0xBE, "M", "3⁄4"), - (0xBF, "V"), - (0xC0, "M", "à"), - (0xC1, "M", "á"), - (0xC2, "M", "â"), - (0xC3, "M", "ã"), - (0xC4, "M", "ä"), - (0xC5, "M", "å"), - (0xC6, "M", "æ"), - (0xC7, "M", "ç"), + (0x64, 'V'), + (0x65, 'V'), + (0x66, 'V'), + (0x67, 'V'), + (0x68, 'V'), + (0x69, 'V'), + (0x6A, 'V'), + (0x6B, 'V'), + (0x6C, 'V'), + (0x6D, 'V'), + (0x6E, 'V'), + (0x6F, 'V'), + (0x70, 'V'), + (0x71, 'V'), + (0x72, 'V'), + (0x73, 'V'), + (0x74, 'V'), + (0x75, 'V'), + (0x76, 'V'), + (0x77, 'V'), + (0x78, 'V'), + (0x79, 'V'), + (0x7A, 'V'), + (0x7B, '3'), + (0x7C, '3'), + (0x7D, '3'), + (0x7E, '3'), + (0x7F, '3'), + (0x80, 'X'), + (0x81, 'X'), + (0x82, 'X'), + (0x83, 'X'), + (0x84, 'X'), + (0x85, 'X'), + (0x86, 'X'), + (0x87, 'X'), + (0x88, 'X'), + (0x89, 'X'), + (0x8A, 'X'), + (0x8B, 'X'), + (0x8C, 'X'), + (0x8D, 'X'), + (0x8E, 'X'), + (0x8F, 'X'), + (0x90, 'X'), + (0x91, 'X'), + (0x92, 'X'), + (0x93, 'X'), + (0x94, 'X'), + (0x95, 'X'), + (0x96, 'X'), + (0x97, 'X'), + (0x98, 'X'), + (0x99, 'X'), + (0x9A, 'X'), + (0x9B, 'X'), + (0x9C, 'X'), + (0x9D, 'X'), + (0x9E, 'X'), + (0x9F, 'X'), + (0xA0, '3', ' '), + (0xA1, 'V'), + (0xA2, 'V'), + (0xA3, 'V'), + (0xA4, 'V'), + (0xA5, 'V'), + (0xA6, 'V'), + (0xA7, 'V'), + (0xA8, '3', ' ̈'), + (0xA9, 'V'), + (0xAA, 'M', 'a'), + (0xAB, 'V'), + (0xAC, 'V'), + (0xAD, 'I'), + (0xAE, 'V'), + (0xAF, '3', ' ̄'), + (0xB0, 'V'), + (0xB1, 'V'), + (0xB2, 'M', '2'), + (0xB3, 'M', '3'), + (0xB4, '3', ' ́'), + (0xB5, 'M', 'μ'), + (0xB6, 'V'), + (0xB7, 'V'), + (0xB8, '3', ' ̧'), + (0xB9, 'M', '1'), + (0xBA, 'M', 'o'), + (0xBB, 'V'), + (0xBC, 'M', '1⁄4'), + (0xBD, 'M', '1⁄2'), + (0xBE, 'M', '3⁄4'), + (0xBF, 'V'), + (0xC0, 'M', 'à'), + (0xC1, 'M', 'á'), + (0xC2, 'M', 'â'), + (0xC3, 'M', 'ã'), + (0xC4, 'M', 'ä'), + (0xC5, 'M', 'å'), + (0xC6, 'M', 'æ'), + (0xC7, 'M', 'ç'), ] - def _seg_2() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0xC8, "M", "è"), - (0xC9, "M", "é"), - (0xCA, "M", "ê"), - (0xCB, "M", "ë"), - (0xCC, "M", "ì"), - (0xCD, "M", "í"), - (0xCE, "M", "î"), - (0xCF, "M", "ï"), - (0xD0, "M", "ð"), - (0xD1, "M", "ñ"), - (0xD2, "M", "ò"), - (0xD3, "M", "ó"), - (0xD4, "M", "ô"), - (0xD5, "M", "õ"), - (0xD6, "M", "ö"), - (0xD7, "V"), - (0xD8, "M", "ø"), - (0xD9, "M", "ù"), - (0xDA, "M", "ú"), - (0xDB, "M", "û"), - (0xDC, "M", "ü"), - (0xDD, "M", "ý"), - (0xDE, "M", "þ"), - (0xDF, "D", "ss"), - (0xE0, "V"), - (0xE1, "V"), - (0xE2, "V"), - (0xE3, "V"), - (0xE4, "V"), - (0xE5, "V"), - (0xE6, "V"), - (0xE7, "V"), - (0xE8, "V"), - (0xE9, "V"), - (0xEA, "V"), - (0xEB, "V"), - (0xEC, "V"), - (0xED, "V"), - (0xEE, "V"), - (0xEF, "V"), - (0xF0, "V"), - (0xF1, "V"), - (0xF2, "V"), - (0xF3, "V"), - (0xF4, "V"), - (0xF5, "V"), - (0xF6, "V"), - (0xF7, "V"), - (0xF8, "V"), - (0xF9, "V"), - (0xFA, "V"), - (0xFB, "V"), - (0xFC, "V"), - (0xFD, "V"), - (0xFE, "V"), - (0xFF, "V"), - (0x100, "M", "ā"), - (0x101, "V"), - (0x102, "M", "ă"), - (0x103, "V"), - (0x104, "M", "ą"), - (0x105, "V"), - (0x106, "M", "ć"), - (0x107, "V"), - (0x108, "M", "ĉ"), - (0x109, "V"), - (0x10A, "M", "ċ"), - (0x10B, "V"), - (0x10C, "M", "č"), - (0x10D, "V"), - (0x10E, "M", "ď"), - (0x10F, "V"), - (0x110, "M", "đ"), - (0x111, "V"), - (0x112, "M", "ē"), - (0x113, "V"), - (0x114, "M", "ĕ"), - (0x115, "V"), - (0x116, "M", "ė"), - (0x117, "V"), - (0x118, "M", "ę"), - (0x119, "V"), - (0x11A, "M", "ě"), - (0x11B, "V"), - (0x11C, "M", "ĝ"), - (0x11D, "V"), - (0x11E, "M", "ğ"), - (0x11F, "V"), - (0x120, "M", "ġ"), - (0x121, "V"), - (0x122, "M", "ģ"), - (0x123, "V"), - (0x124, "M", "ĥ"), - (0x125, "V"), - (0x126, "M", "ħ"), - (0x127, "V"), - (0x128, "M", "ĩ"), - (0x129, "V"), - (0x12A, "M", "ī"), - (0x12B, "V"), + (0xC8, 'M', 'è'), + (0xC9, 'M', 'é'), + (0xCA, 'M', 'ê'), + (0xCB, 'M', 'ë'), + (0xCC, 'M', 'ì'), + (0xCD, 'M', 'í'), + (0xCE, 'M', 'î'), + (0xCF, 'M', 'ï'), + (0xD0, 'M', 'ð'), + (0xD1, 'M', 'ñ'), + (0xD2, 'M', 'ò'), + (0xD3, 'M', 'ó'), + (0xD4, 'M', 'ô'), + (0xD5, 'M', 'õ'), + (0xD6, 'M', 'ö'), + (0xD7, 'V'), + (0xD8, 'M', 'ø'), + (0xD9, 'M', 'ù'), + (0xDA, 'M', 'ú'), + (0xDB, 'M', 'û'), + (0xDC, 'M', 'ü'), + (0xDD, 'M', 'ý'), + (0xDE, 'M', 'þ'), + (0xDF, 'D', 'ss'), + (0xE0, 'V'), + (0xE1, 'V'), + (0xE2, 'V'), + (0xE3, 'V'), + (0xE4, 'V'), + (0xE5, 'V'), + (0xE6, 'V'), + (0xE7, 'V'), + (0xE8, 'V'), + (0xE9, 'V'), + (0xEA, 'V'), + (0xEB, 'V'), + (0xEC, 'V'), + (0xED, 'V'), + (0xEE, 'V'), + (0xEF, 'V'), + (0xF0, 'V'), + (0xF1, 'V'), + (0xF2, 'V'), + (0xF3, 'V'), + (0xF4, 'V'), + (0xF5, 'V'), + (0xF6, 'V'), + (0xF7, 'V'), + (0xF8, 'V'), + (0xF9, 'V'), + (0xFA, 'V'), + (0xFB, 'V'), + (0xFC, 'V'), + (0xFD, 'V'), + (0xFE, 'V'), + (0xFF, 'V'), + (0x100, 'M', 'ā'), + (0x101, 'V'), + (0x102, 'M', 'ă'), + (0x103, 'V'), + (0x104, 'M', 'ą'), + (0x105, 'V'), + (0x106, 'M', 'ć'), + (0x107, 'V'), + (0x108, 'M', 'ĉ'), + (0x109, 'V'), + (0x10A, 'M', 'ċ'), + (0x10B, 'V'), + (0x10C, 'M', 'č'), + (0x10D, 'V'), + (0x10E, 'M', 'ď'), + (0x10F, 'V'), + (0x110, 'M', 'đ'), + (0x111, 'V'), + (0x112, 'M', 'ē'), + (0x113, 'V'), + (0x114, 'M', 'ĕ'), + (0x115, 'V'), + (0x116, 'M', 'ė'), + (0x117, 'V'), + (0x118, 'M', 'ę'), + (0x119, 'V'), + (0x11A, 'M', 'ě'), + (0x11B, 'V'), + (0x11C, 'M', 'ĝ'), + (0x11D, 'V'), + (0x11E, 'M', 'ğ'), + (0x11F, 'V'), + (0x120, 'M', 'ġ'), + (0x121, 'V'), + (0x122, 'M', 'ģ'), + (0x123, 'V'), + (0x124, 'M', 'ĥ'), + (0x125, 'V'), + (0x126, 'M', 'ħ'), + (0x127, 'V'), + (0x128, 'M', 'ĩ'), + (0x129, 'V'), + (0x12A, 'M', 'ī'), + (0x12B, 'V'), ] - def _seg_3() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x12C, "M", "ĭ"), - (0x12D, "V"), - (0x12E, "M", "į"), - (0x12F, "V"), - (0x130, "M", "i̇"), - (0x131, "V"), - (0x132, "M", "ij"), - (0x134, "M", "ĵ"), - (0x135, "V"), - (0x136, "M", "ķ"), - (0x137, "V"), - (0x139, "M", "ĺ"), - (0x13A, "V"), - (0x13B, "M", "ļ"), - (0x13C, "V"), - (0x13D, "M", "ľ"), - (0x13E, "V"), - (0x13F, "M", "l·"), - (0x141, "M", "ł"), - (0x142, "V"), - (0x143, "M", "ń"), - (0x144, "V"), - (0x145, "M", "ņ"), - (0x146, "V"), - (0x147, "M", "ň"), - (0x148, "V"), - (0x149, "M", "ʼn"), - (0x14A, "M", "ŋ"), - (0x14B, "V"), - (0x14C, "M", "ō"), - (0x14D, "V"), - (0x14E, "M", "ŏ"), - (0x14F, "V"), - (0x150, "M", "ő"), - (0x151, "V"), - (0x152, "M", "œ"), - (0x153, "V"), - (0x154, "M", "ŕ"), - (0x155, "V"), - (0x156, "M", "ŗ"), - (0x157, "V"), - (0x158, "M", "ř"), - (0x159, "V"), - (0x15A, "M", "ś"), - (0x15B, "V"), - (0x15C, "M", "ŝ"), - (0x15D, "V"), - (0x15E, "M", "ş"), - (0x15F, "V"), - (0x160, "M", "š"), - (0x161, "V"), - (0x162, "M", "ţ"), - (0x163, "V"), - (0x164, "M", "ť"), - (0x165, "V"), - (0x166, "M", "ŧ"), - (0x167, "V"), - (0x168, "M", "ũ"), - (0x169, "V"), - (0x16A, "M", "ū"), - (0x16B, "V"), - (0x16C, "M", "ŭ"), - (0x16D, "V"), - (0x16E, "M", "ů"), - (0x16F, "V"), - (0x170, "M", "ű"), - (0x171, "V"), - (0x172, "M", "ų"), - (0x173, "V"), - (0x174, "M", "ŵ"), - (0x175, "V"), - (0x176, "M", "ŷ"), - (0x177, "V"), - (0x178, "M", "ÿ"), - (0x179, "M", "ź"), - (0x17A, "V"), - (0x17B, "M", "ż"), - (0x17C, "V"), - (0x17D, "M", "ž"), - (0x17E, "V"), - (0x17F, "M", "s"), - (0x180, "V"), - (0x181, "M", "ɓ"), - (0x182, "M", "ƃ"), - (0x183, "V"), - (0x184, "M", "ƅ"), - (0x185, "V"), - (0x186, "M", "ɔ"), - (0x187, "M", "ƈ"), - (0x188, "V"), - (0x189, "M", "ɖ"), - (0x18A, "M", "ɗ"), - (0x18B, "M", "ƌ"), - (0x18C, "V"), - (0x18E, "M", "ǝ"), - (0x18F, "M", "ə"), - (0x190, "M", "ɛ"), - (0x191, "M", "ƒ"), - (0x192, "V"), - (0x193, "M", "ɠ"), + (0x12C, 'M', 'ĭ'), + (0x12D, 'V'), + (0x12E, 'M', 'į'), + (0x12F, 'V'), + (0x130, 'M', 'i̇'), + (0x131, 'V'), + (0x132, 'M', 'ij'), + (0x134, 'M', 'ĵ'), + (0x135, 'V'), + (0x136, 'M', 'ķ'), + (0x137, 'V'), + (0x139, 'M', 'ĺ'), + (0x13A, 'V'), + (0x13B, 'M', 'ļ'), + (0x13C, 'V'), + (0x13D, 'M', 'ľ'), + (0x13E, 'V'), + (0x13F, 'M', 'l·'), + (0x141, 'M', 'ł'), + (0x142, 'V'), + (0x143, 'M', 'ń'), + (0x144, 'V'), + (0x145, 'M', 'ņ'), + (0x146, 'V'), + (0x147, 'M', 'ň'), + (0x148, 'V'), + (0x149, 'M', 'ʼn'), + (0x14A, 'M', 'ŋ'), + (0x14B, 'V'), + (0x14C, 'M', 'ō'), + (0x14D, 'V'), + (0x14E, 'M', 'ŏ'), + (0x14F, 'V'), + (0x150, 'M', 'ő'), + (0x151, 'V'), + (0x152, 'M', 'œ'), + (0x153, 'V'), + (0x154, 'M', 'ŕ'), + (0x155, 'V'), + (0x156, 'M', 'ŗ'), + (0x157, 'V'), + (0x158, 'M', 'ř'), + (0x159, 'V'), + (0x15A, 'M', 'ś'), + (0x15B, 'V'), + (0x15C, 'M', 'ŝ'), + (0x15D, 'V'), + (0x15E, 'M', 'ş'), + (0x15F, 'V'), + (0x160, 'M', 'š'), + (0x161, 'V'), + (0x162, 'M', 'ţ'), + (0x163, 'V'), + (0x164, 'M', 'ť'), + (0x165, 'V'), + (0x166, 'M', 'ŧ'), + (0x167, 'V'), + (0x168, 'M', 'ũ'), + (0x169, 'V'), + (0x16A, 'M', 'ū'), + (0x16B, 'V'), + (0x16C, 'M', 'ŭ'), + (0x16D, 'V'), + (0x16E, 'M', 'ů'), + (0x16F, 'V'), + (0x170, 'M', 'ű'), + (0x171, 'V'), + (0x172, 'M', 'ų'), + (0x173, 'V'), + (0x174, 'M', 'ŵ'), + (0x175, 'V'), + (0x176, 'M', 'ŷ'), + (0x177, 'V'), + (0x178, 'M', 'ÿ'), + (0x179, 'M', 'ź'), + (0x17A, 'V'), + (0x17B, 'M', 'ż'), + (0x17C, 'V'), + (0x17D, 'M', 'ž'), + (0x17E, 'V'), + (0x17F, 'M', 's'), + (0x180, 'V'), + (0x181, 'M', 'ɓ'), + (0x182, 'M', 'ƃ'), + (0x183, 'V'), + (0x184, 'M', 'ƅ'), + (0x185, 'V'), + (0x186, 'M', 'ɔ'), + (0x187, 'M', 'ƈ'), + (0x188, 'V'), + (0x189, 'M', 'ɖ'), + (0x18A, 'M', 'ɗ'), + (0x18B, 'M', 'ƌ'), + (0x18C, 'V'), + (0x18E, 'M', 'ǝ'), + (0x18F, 'M', 'ə'), + (0x190, 'M', 'ɛ'), + (0x191, 'M', 'ƒ'), + (0x192, 'V'), + (0x193, 'M', 'ɠ'), ] - def _seg_4() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x194, "M", "ɣ"), - (0x195, "V"), - (0x196, "M", "ɩ"), - (0x197, "M", "ɨ"), - (0x198, "M", "ƙ"), - (0x199, "V"), - (0x19C, "M", "ɯ"), - (0x19D, "M", "ɲ"), - (0x19E, "V"), - (0x19F, "M", "ɵ"), - (0x1A0, "M", "ơ"), - (0x1A1, "V"), - (0x1A2, "M", "ƣ"), - (0x1A3, "V"), - (0x1A4, "M", "ƥ"), - (0x1A5, "V"), - (0x1A6, "M", "ʀ"), - (0x1A7, "M", "ƨ"), - (0x1A8, "V"), - (0x1A9, "M", "ʃ"), - (0x1AA, "V"), - (0x1AC, "M", "ƭ"), - (0x1AD, "V"), - (0x1AE, "M", "ʈ"), - (0x1AF, "M", "ư"), - (0x1B0, "V"), - (0x1B1, "M", "ʊ"), - (0x1B2, "M", "ʋ"), - (0x1B3, "M", "ƴ"), - (0x1B4, "V"), - (0x1B5, "M", "ƶ"), - (0x1B6, "V"), - (0x1B7, "M", "ʒ"), - (0x1B8, "M", "ƹ"), - (0x1B9, "V"), - (0x1BC, "M", "ƽ"), - (0x1BD, "V"), - (0x1C4, "M", "dž"), - (0x1C7, "M", "lj"), - (0x1CA, "M", "nj"), - (0x1CD, "M", "ǎ"), - (0x1CE, "V"), - (0x1CF, "M", "ǐ"), - (0x1D0, "V"), - (0x1D1, "M", "ǒ"), - (0x1D2, "V"), - (0x1D3, "M", "ǔ"), - (0x1D4, "V"), - (0x1D5, "M", "ǖ"), - (0x1D6, "V"), - (0x1D7, "M", "ǘ"), - (0x1D8, "V"), - (0x1D9, "M", "ǚ"), - (0x1DA, "V"), - (0x1DB, "M", "ǜ"), - (0x1DC, "V"), - (0x1DE, "M", "ǟ"), - (0x1DF, "V"), - (0x1E0, "M", "ǡ"), - (0x1E1, "V"), - (0x1E2, "M", "ǣ"), - (0x1E3, "V"), - (0x1E4, "M", "ǥ"), - (0x1E5, "V"), - (0x1E6, "M", "ǧ"), - (0x1E7, "V"), - (0x1E8, "M", "ǩ"), - (0x1E9, "V"), - (0x1EA, "M", "ǫ"), - (0x1EB, "V"), - (0x1EC, "M", "ǭ"), - (0x1ED, "V"), - (0x1EE, "M", "ǯ"), - (0x1EF, "V"), - (0x1F1, "M", "dz"), - (0x1F4, "M", "ǵ"), - (0x1F5, "V"), - (0x1F6, "M", "ƕ"), - (0x1F7, "M", "ƿ"), - (0x1F8, "M", "ǹ"), - (0x1F9, "V"), - (0x1FA, "M", "ǻ"), - (0x1FB, "V"), - (0x1FC, "M", "ǽ"), - (0x1FD, "V"), - (0x1FE, "M", "ǿ"), - (0x1FF, "V"), - (0x200, "M", "ȁ"), - (0x201, "V"), - (0x202, "M", "ȃ"), - (0x203, "V"), - (0x204, "M", "ȅ"), - (0x205, "V"), - (0x206, "M", "ȇ"), - (0x207, "V"), - (0x208, "M", "ȉ"), - (0x209, "V"), - (0x20A, "M", "ȋ"), - (0x20B, "V"), - (0x20C, "M", "ȍ"), + (0x194, 'M', 'ɣ'), + (0x195, 'V'), + (0x196, 'M', 'ɩ'), + (0x197, 'M', 'ɨ'), + (0x198, 'M', 'ƙ'), + (0x199, 'V'), + (0x19C, 'M', 'ɯ'), + (0x19D, 'M', 'ɲ'), + (0x19E, 'V'), + (0x19F, 'M', 'ɵ'), + (0x1A0, 'M', 'ơ'), + (0x1A1, 'V'), + (0x1A2, 'M', 'ƣ'), + (0x1A3, 'V'), + (0x1A4, 'M', 'ƥ'), + (0x1A5, 'V'), + (0x1A6, 'M', 'ʀ'), + (0x1A7, 'M', 'ƨ'), + (0x1A8, 'V'), + (0x1A9, 'M', 'ʃ'), + (0x1AA, 'V'), + (0x1AC, 'M', 'ƭ'), + (0x1AD, 'V'), + (0x1AE, 'M', 'ʈ'), + (0x1AF, 'M', 'ư'), + (0x1B0, 'V'), + (0x1B1, 'M', 'ʊ'), + (0x1B2, 'M', 'ʋ'), + (0x1B3, 'M', 'ƴ'), + (0x1B4, 'V'), + (0x1B5, 'M', 'ƶ'), + (0x1B6, 'V'), + (0x1B7, 'M', 'ʒ'), + (0x1B8, 'M', 'ƹ'), + (0x1B9, 'V'), + (0x1BC, 'M', 'ƽ'), + (0x1BD, 'V'), + (0x1C4, 'M', 'dž'), + (0x1C7, 'M', 'lj'), + (0x1CA, 'M', 'nj'), + (0x1CD, 'M', 'ǎ'), + (0x1CE, 'V'), + (0x1CF, 'M', 'ǐ'), + (0x1D0, 'V'), + (0x1D1, 'M', 'ǒ'), + (0x1D2, 'V'), + (0x1D3, 'M', 'ǔ'), + (0x1D4, 'V'), + (0x1D5, 'M', 'ǖ'), + (0x1D6, 'V'), + (0x1D7, 'M', 'ǘ'), + (0x1D8, 'V'), + (0x1D9, 'M', 'ǚ'), + (0x1DA, 'V'), + (0x1DB, 'M', 'ǜ'), + (0x1DC, 'V'), + (0x1DE, 'M', 'ǟ'), + (0x1DF, 'V'), + (0x1E0, 'M', 'ǡ'), + (0x1E1, 'V'), + (0x1E2, 'M', 'ǣ'), + (0x1E3, 'V'), + (0x1E4, 'M', 'ǥ'), + (0x1E5, 'V'), + (0x1E6, 'M', 'ǧ'), + (0x1E7, 'V'), + (0x1E8, 'M', 'ǩ'), + (0x1E9, 'V'), + (0x1EA, 'M', 'ǫ'), + (0x1EB, 'V'), + (0x1EC, 'M', 'ǭ'), + (0x1ED, 'V'), + (0x1EE, 'M', 'ǯ'), + (0x1EF, 'V'), + (0x1F1, 'M', 'dz'), + (0x1F4, 'M', 'ǵ'), + (0x1F5, 'V'), + (0x1F6, 'M', 'ƕ'), + (0x1F7, 'M', 'ƿ'), + (0x1F8, 'M', 'ǹ'), + (0x1F9, 'V'), + (0x1FA, 'M', 'ǻ'), + (0x1FB, 'V'), + (0x1FC, 'M', 'ǽ'), + (0x1FD, 'V'), + (0x1FE, 'M', 'ǿ'), + (0x1FF, 'V'), + (0x200, 'M', 'ȁ'), + (0x201, 'V'), + (0x202, 'M', 'ȃ'), + (0x203, 'V'), + (0x204, 'M', 'ȅ'), + (0x205, 'V'), + (0x206, 'M', 'ȇ'), + (0x207, 'V'), + (0x208, 'M', 'ȉ'), + (0x209, 'V'), + (0x20A, 'M', 'ȋ'), + (0x20B, 'V'), + (0x20C, 'M', 'ȍ'), ] - def _seg_5() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x20D, "V"), - (0x20E, "M", "ȏ"), - (0x20F, "V"), - (0x210, "M", "ȑ"), - (0x211, "V"), - (0x212, "M", "ȓ"), - (0x213, "V"), - (0x214, "M", "ȕ"), - (0x215, "V"), - (0x216, "M", "ȗ"), - (0x217, "V"), - (0x218, "M", "ș"), - (0x219, "V"), - (0x21A, "M", "ț"), - (0x21B, "V"), - (0x21C, "M", "ȝ"), - (0x21D, "V"), - (0x21E, "M", "ȟ"), - (0x21F, "V"), - (0x220, "M", "ƞ"), - (0x221, "V"), - (0x222, "M", "ȣ"), - (0x223, "V"), - (0x224, "M", "ȥ"), - (0x225, "V"), - (0x226, "M", "ȧ"), - (0x227, "V"), - (0x228, "M", "ȩ"), - (0x229, "V"), - (0x22A, "M", "ȫ"), - (0x22B, "V"), - (0x22C, "M", "ȭ"), - (0x22D, "V"), - (0x22E, "M", "ȯ"), - (0x22F, "V"), - (0x230, "M", "ȱ"), - (0x231, "V"), - (0x232, "M", "ȳ"), - (0x233, "V"), - (0x23A, "M", "ⱥ"), - (0x23B, "M", "ȼ"), - (0x23C, "V"), - (0x23D, "M", "ƚ"), - (0x23E, "M", "ⱦ"), - (0x23F, "V"), - (0x241, "M", "ɂ"), - (0x242, "V"), - (0x243, "M", "ƀ"), - (0x244, "M", "ʉ"), - (0x245, "M", "ʌ"), - (0x246, "M", "ɇ"), - (0x247, "V"), - (0x248, "M", "ɉ"), - (0x249, "V"), - (0x24A, "M", "ɋ"), - (0x24B, "V"), - (0x24C, "M", "ɍ"), - (0x24D, "V"), - (0x24E, "M", "ɏ"), - (0x24F, "V"), - (0x2B0, "M", "h"), - (0x2B1, "M", "ɦ"), - (0x2B2, "M", "j"), - (0x2B3, "M", "r"), - (0x2B4, "M", "ɹ"), - (0x2B5, "M", "ɻ"), - (0x2B6, "M", "ʁ"), - (0x2B7, "M", "w"), - (0x2B8, "M", "y"), - (0x2B9, "V"), - (0x2D8, "3", " ̆"), - (0x2D9, "3", " ̇"), - (0x2DA, "3", " ̊"), - (0x2DB, "3", " ̨"), - (0x2DC, "3", " ̃"), - (0x2DD, "3", " ̋"), - (0x2DE, "V"), - (0x2E0, "M", "ɣ"), - (0x2E1, "M", "l"), - (0x2E2, "M", "s"), - (0x2E3, "M", "x"), - (0x2E4, "M", "ʕ"), - (0x2E5, "V"), - (0x340, "M", "̀"), - (0x341, "M", "́"), - (0x342, "V"), - (0x343, "M", "̓"), - (0x344, "M", "̈́"), - (0x345, "M", "ι"), - (0x346, "V"), - (0x34F, "I"), - (0x350, "V"), - (0x370, "M", "ͱ"), - (0x371, "V"), - (0x372, "M", "ͳ"), - (0x373, "V"), - (0x374, "M", "ʹ"), - (0x375, "V"), - (0x376, "M", "ͷ"), - (0x377, "V"), + (0x20D, 'V'), + (0x20E, 'M', 'ȏ'), + (0x20F, 'V'), + (0x210, 'M', 'ȑ'), + (0x211, 'V'), + (0x212, 'M', 'ȓ'), + (0x213, 'V'), + (0x214, 'M', 'ȕ'), + (0x215, 'V'), + (0x216, 'M', 'ȗ'), + (0x217, 'V'), + (0x218, 'M', 'ș'), + (0x219, 'V'), + (0x21A, 'M', 'ț'), + (0x21B, 'V'), + (0x21C, 'M', 'ȝ'), + (0x21D, 'V'), + (0x21E, 'M', 'ȟ'), + (0x21F, 'V'), + (0x220, 'M', 'ƞ'), + (0x221, 'V'), + (0x222, 'M', 'ȣ'), + (0x223, 'V'), + (0x224, 'M', 'ȥ'), + (0x225, 'V'), + (0x226, 'M', 'ȧ'), + (0x227, 'V'), + (0x228, 'M', 'ȩ'), + (0x229, 'V'), + (0x22A, 'M', 'ȫ'), + (0x22B, 'V'), + (0x22C, 'M', 'ȭ'), + (0x22D, 'V'), + (0x22E, 'M', 'ȯ'), + (0x22F, 'V'), + (0x230, 'M', 'ȱ'), + (0x231, 'V'), + (0x232, 'M', 'ȳ'), + (0x233, 'V'), + (0x23A, 'M', 'ⱥ'), + (0x23B, 'M', 'ȼ'), + (0x23C, 'V'), + (0x23D, 'M', 'ƚ'), + (0x23E, 'M', 'ⱦ'), + (0x23F, 'V'), + (0x241, 'M', 'ɂ'), + (0x242, 'V'), + (0x243, 'M', 'ƀ'), + (0x244, 'M', 'ʉ'), + (0x245, 'M', 'ʌ'), + (0x246, 'M', 'ɇ'), + (0x247, 'V'), + (0x248, 'M', 'ɉ'), + (0x249, 'V'), + (0x24A, 'M', 'ɋ'), + (0x24B, 'V'), + (0x24C, 'M', 'ɍ'), + (0x24D, 'V'), + (0x24E, 'M', 'ɏ'), + (0x24F, 'V'), + (0x2B0, 'M', 'h'), + (0x2B1, 'M', 'ɦ'), + (0x2B2, 'M', 'j'), + (0x2B3, 'M', 'r'), + (0x2B4, 'M', 'ɹ'), + (0x2B5, 'M', 'ɻ'), + (0x2B6, 'M', 'ʁ'), + (0x2B7, 'M', 'w'), + (0x2B8, 'M', 'y'), + (0x2B9, 'V'), + (0x2D8, '3', ' ̆'), + (0x2D9, '3', ' ̇'), + (0x2DA, '3', ' ̊'), + (0x2DB, '3', ' ̨'), + (0x2DC, '3', ' ̃'), + (0x2DD, '3', ' ̋'), + (0x2DE, 'V'), + (0x2E0, 'M', 'ɣ'), + (0x2E1, 'M', 'l'), + (0x2E2, 'M', 's'), + (0x2E3, 'M', 'x'), + (0x2E4, 'M', 'ʕ'), + (0x2E5, 'V'), + (0x340, 'M', '̀'), + (0x341, 'M', '́'), + (0x342, 'V'), + (0x343, 'M', '̓'), + (0x344, 'M', '̈́'), + (0x345, 'M', 'ι'), + (0x346, 'V'), + (0x34F, 'I'), + (0x350, 'V'), + (0x370, 'M', 'ͱ'), + (0x371, 'V'), + (0x372, 'M', 'ͳ'), + (0x373, 'V'), + (0x374, 'M', 'ʹ'), + (0x375, 'V'), + (0x376, 'M', 'ͷ'), + (0x377, 'V'), ] - def _seg_6() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x378, "X"), - (0x37A, "3", " ι"), - (0x37B, "V"), - (0x37E, "3", ";"), - (0x37F, "M", "ϳ"), - (0x380, "X"), - (0x384, "3", " ́"), - (0x385, "3", " ̈́"), - (0x386, "M", "ά"), - (0x387, "M", "·"), - (0x388, "M", "έ"), - (0x389, "M", "ή"), - (0x38A, "M", "ί"), - (0x38B, "X"), - (0x38C, "M", "ό"), - (0x38D, "X"), - (0x38E, "M", "ύ"), - (0x38F, "M", "ώ"), - (0x390, "V"), - (0x391, "M", "α"), - (0x392, "M", "β"), - (0x393, "M", "γ"), - (0x394, "M", "δ"), - (0x395, "M", "ε"), - (0x396, "M", "ζ"), - (0x397, "M", "η"), - (0x398, "M", "θ"), - (0x399, "M", "ι"), - (0x39A, "M", "κ"), - (0x39B, "M", "λ"), - (0x39C, "M", "μ"), - (0x39D, "M", "ν"), - (0x39E, "M", "ξ"), - (0x39F, "M", "ο"), - (0x3A0, "M", "π"), - (0x3A1, "M", "ρ"), - (0x3A2, "X"), - (0x3A3, "M", "σ"), - (0x3A4, "M", "τ"), - (0x3A5, "M", "υ"), - (0x3A6, "M", "φ"), - (0x3A7, "M", "χ"), - (0x3A8, "M", "ψ"), - (0x3A9, "M", "ω"), - (0x3AA, "M", "ϊ"), - (0x3AB, "M", "ϋ"), - (0x3AC, "V"), - (0x3C2, "D", "σ"), - (0x3C3, "V"), - (0x3CF, "M", "ϗ"), - (0x3D0, "M", "β"), - (0x3D1, "M", "θ"), - (0x3D2, "M", "υ"), - (0x3D3, "M", "ύ"), - (0x3D4, "M", "ϋ"), - (0x3D5, "M", "φ"), - (0x3D6, "M", "π"), - (0x3D7, "V"), - (0x3D8, "M", "ϙ"), - (0x3D9, "V"), - (0x3DA, "M", "ϛ"), - (0x3DB, "V"), - (0x3DC, "M", "ϝ"), - (0x3DD, "V"), - (0x3DE, "M", "ϟ"), - (0x3DF, "V"), - (0x3E0, "M", "ϡ"), - (0x3E1, "V"), - (0x3E2, "M", "ϣ"), - (0x3E3, "V"), - (0x3E4, "M", "ϥ"), - (0x3E5, "V"), - (0x3E6, "M", "ϧ"), - (0x3E7, "V"), - (0x3E8, "M", "ϩ"), - (0x3E9, "V"), - (0x3EA, "M", "ϫ"), - (0x3EB, "V"), - (0x3EC, "M", "ϭ"), - (0x3ED, "V"), - (0x3EE, "M", "ϯ"), - (0x3EF, "V"), - (0x3F0, "M", "κ"), - (0x3F1, "M", "ρ"), - (0x3F2, "M", "σ"), - (0x3F3, "V"), - (0x3F4, "M", "θ"), - (0x3F5, "M", "ε"), - (0x3F6, "V"), - (0x3F7, "M", "ϸ"), - (0x3F8, "V"), - (0x3F9, "M", "σ"), - (0x3FA, "M", "ϻ"), - (0x3FB, "V"), - (0x3FD, "M", "ͻ"), - (0x3FE, "M", "ͼ"), - (0x3FF, "M", "ͽ"), - (0x400, "M", "ѐ"), - (0x401, "M", "ё"), - (0x402, "M", "ђ"), + (0x378, 'X'), + (0x37A, '3', ' ι'), + (0x37B, 'V'), + (0x37E, '3', ';'), + (0x37F, 'M', 'ϳ'), + (0x380, 'X'), + (0x384, '3', ' ́'), + (0x385, '3', ' ̈́'), + (0x386, 'M', 'ά'), + (0x387, 'M', '·'), + (0x388, 'M', 'έ'), + (0x389, 'M', 'ή'), + (0x38A, 'M', 'ί'), + (0x38B, 'X'), + (0x38C, 'M', 'ό'), + (0x38D, 'X'), + (0x38E, 'M', 'ύ'), + (0x38F, 'M', 'ώ'), + (0x390, 'V'), + (0x391, 'M', 'α'), + (0x392, 'M', 'β'), + (0x393, 'M', 'γ'), + (0x394, 'M', 'δ'), + (0x395, 'M', 'ε'), + (0x396, 'M', 'ζ'), + (0x397, 'M', 'η'), + (0x398, 'M', 'θ'), + (0x399, 'M', 'ι'), + (0x39A, 'M', 'κ'), + (0x39B, 'M', 'λ'), + (0x39C, 'M', 'μ'), + (0x39D, 'M', 'ν'), + (0x39E, 'M', 'ξ'), + (0x39F, 'M', 'ο'), + (0x3A0, 'M', 'π'), + (0x3A1, 'M', 'ρ'), + (0x3A2, 'X'), + (0x3A3, 'M', 'σ'), + (0x3A4, 'M', 'τ'), + (0x3A5, 'M', 'υ'), + (0x3A6, 'M', 'φ'), + (0x3A7, 'M', 'χ'), + (0x3A8, 'M', 'ψ'), + (0x3A9, 'M', 'ω'), + (0x3AA, 'M', 'ϊ'), + (0x3AB, 'M', 'ϋ'), + (0x3AC, 'V'), + (0x3C2, 'D', 'σ'), + (0x3C3, 'V'), + (0x3CF, 'M', 'ϗ'), + (0x3D0, 'M', 'β'), + (0x3D1, 'M', 'θ'), + (0x3D2, 'M', 'υ'), + (0x3D3, 'M', 'ύ'), + (0x3D4, 'M', 'ϋ'), + (0x3D5, 'M', 'φ'), + (0x3D6, 'M', 'π'), + (0x3D7, 'V'), + (0x3D8, 'M', 'ϙ'), + (0x3D9, 'V'), + (0x3DA, 'M', 'ϛ'), + (0x3DB, 'V'), + (0x3DC, 'M', 'ϝ'), + (0x3DD, 'V'), + (0x3DE, 'M', 'ϟ'), + (0x3DF, 'V'), + (0x3E0, 'M', 'ϡ'), + (0x3E1, 'V'), + (0x3E2, 'M', 'ϣ'), + (0x3E3, 'V'), + (0x3E4, 'M', 'ϥ'), + (0x3E5, 'V'), + (0x3E6, 'M', 'ϧ'), + (0x3E7, 'V'), + (0x3E8, 'M', 'ϩ'), + (0x3E9, 'V'), + (0x3EA, 'M', 'ϫ'), + (0x3EB, 'V'), + (0x3EC, 'M', 'ϭ'), + (0x3ED, 'V'), + (0x3EE, 'M', 'ϯ'), + (0x3EF, 'V'), + (0x3F0, 'M', 'κ'), + (0x3F1, 'M', 'ρ'), + (0x3F2, 'M', 'σ'), + (0x3F3, 'V'), + (0x3F4, 'M', 'θ'), + (0x3F5, 'M', 'ε'), + (0x3F6, 'V'), + (0x3F7, 'M', 'ϸ'), + (0x3F8, 'V'), + (0x3F9, 'M', 'σ'), + (0x3FA, 'M', 'ϻ'), + (0x3FB, 'V'), + (0x3FD, 'M', 'ͻ'), + (0x3FE, 'M', 'ͼ'), + (0x3FF, 'M', 'ͽ'), + (0x400, 'M', 'ѐ'), + (0x401, 'M', 'ё'), + (0x402, 'M', 'ђ'), ] - def _seg_7() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x403, "M", "ѓ"), - (0x404, "M", "є"), - (0x405, "M", "ѕ"), - (0x406, "M", "і"), - (0x407, "M", "ї"), - (0x408, "M", "ј"), - (0x409, "M", "љ"), - (0x40A, "M", "њ"), - (0x40B, "M", "ћ"), - (0x40C, "M", "ќ"), - (0x40D, "M", "ѝ"), - (0x40E, "M", "ў"), - (0x40F, "M", "џ"), - (0x410, "M", "а"), - (0x411, "M", "б"), - (0x412, "M", "в"), - (0x413, "M", "г"), - (0x414, "M", "д"), - (0x415, "M", "е"), - (0x416, "M", "ж"), - (0x417, "M", "з"), - (0x418, "M", "и"), - (0x419, "M", "й"), - (0x41A, "M", "к"), - (0x41B, "M", "л"), - (0x41C, "M", "м"), - (0x41D, "M", "н"), - (0x41E, "M", "о"), - (0x41F, "M", "п"), - (0x420, "M", "р"), - (0x421, "M", "с"), - (0x422, "M", "т"), - (0x423, "M", "у"), - (0x424, "M", "ф"), - (0x425, "M", "х"), - (0x426, "M", "ц"), - (0x427, "M", "ч"), - (0x428, "M", "ш"), - (0x429, "M", "щ"), - (0x42A, "M", "ъ"), - (0x42B, "M", "ы"), - (0x42C, "M", "ь"), - (0x42D, "M", "э"), - (0x42E, "M", "ю"), - (0x42F, "M", "я"), - (0x430, "V"), - (0x460, "M", "ѡ"), - (0x461, "V"), - (0x462, "M", "ѣ"), - (0x463, "V"), - (0x464, "M", "ѥ"), - (0x465, "V"), - (0x466, "M", "ѧ"), - (0x467, "V"), - (0x468, "M", "ѩ"), - (0x469, "V"), - (0x46A, "M", "ѫ"), - (0x46B, "V"), - (0x46C, "M", "ѭ"), - (0x46D, "V"), - (0x46E, "M", "ѯ"), - (0x46F, "V"), - (0x470, "M", "ѱ"), - (0x471, "V"), - (0x472, "M", "ѳ"), - (0x473, "V"), - (0x474, "M", "ѵ"), - (0x475, "V"), - (0x476, "M", "ѷ"), - (0x477, "V"), - (0x478, "M", "ѹ"), - (0x479, "V"), - (0x47A, "M", "ѻ"), - (0x47B, "V"), - (0x47C, "M", "ѽ"), - (0x47D, "V"), - (0x47E, "M", "ѿ"), - (0x47F, "V"), - (0x480, "M", "ҁ"), - (0x481, "V"), - (0x48A, "M", "ҋ"), - (0x48B, "V"), - (0x48C, "M", "ҍ"), - (0x48D, "V"), - (0x48E, "M", "ҏ"), - (0x48F, "V"), - (0x490, "M", "ґ"), - (0x491, "V"), - (0x492, "M", "ғ"), - (0x493, "V"), - (0x494, "M", "ҕ"), - (0x495, "V"), - (0x496, "M", "җ"), - (0x497, "V"), - (0x498, "M", "ҙ"), - (0x499, "V"), - (0x49A, "M", "қ"), - (0x49B, "V"), - (0x49C, "M", "ҝ"), - (0x49D, "V"), + (0x403, 'M', 'ѓ'), + (0x404, 'M', 'є'), + (0x405, 'M', 'ѕ'), + (0x406, 'M', 'і'), + (0x407, 'M', 'ї'), + (0x408, 'M', 'ј'), + (0x409, 'M', 'љ'), + (0x40A, 'M', 'њ'), + (0x40B, 'M', 'ћ'), + (0x40C, 'M', 'ќ'), + (0x40D, 'M', 'ѝ'), + (0x40E, 'M', 'ў'), + (0x40F, 'M', 'џ'), + (0x410, 'M', 'а'), + (0x411, 'M', 'б'), + (0x412, 'M', 'в'), + (0x413, 'M', 'г'), + (0x414, 'M', 'д'), + (0x415, 'M', 'е'), + (0x416, 'M', 'ж'), + (0x417, 'M', 'з'), + (0x418, 'M', 'и'), + (0x419, 'M', 'й'), + (0x41A, 'M', 'к'), + (0x41B, 'M', 'л'), + (0x41C, 'M', 'м'), + (0x41D, 'M', 'н'), + (0x41E, 'M', 'о'), + (0x41F, 'M', 'п'), + (0x420, 'M', 'р'), + (0x421, 'M', 'с'), + (0x422, 'M', 'т'), + (0x423, 'M', 'у'), + (0x424, 'M', 'ф'), + (0x425, 'M', 'х'), + (0x426, 'M', 'ц'), + (0x427, 'M', 'ч'), + (0x428, 'M', 'ш'), + (0x429, 'M', 'щ'), + (0x42A, 'M', 'ъ'), + (0x42B, 'M', 'ы'), + (0x42C, 'M', 'ь'), + (0x42D, 'M', 'э'), + (0x42E, 'M', 'ю'), + (0x42F, 'M', 'я'), + (0x430, 'V'), + (0x460, 'M', 'ѡ'), + (0x461, 'V'), + (0x462, 'M', 'ѣ'), + (0x463, 'V'), + (0x464, 'M', 'ѥ'), + (0x465, 'V'), + (0x466, 'M', 'ѧ'), + (0x467, 'V'), + (0x468, 'M', 'ѩ'), + (0x469, 'V'), + (0x46A, 'M', 'ѫ'), + (0x46B, 'V'), + (0x46C, 'M', 'ѭ'), + (0x46D, 'V'), + (0x46E, 'M', 'ѯ'), + (0x46F, 'V'), + (0x470, 'M', 'ѱ'), + (0x471, 'V'), + (0x472, 'M', 'ѳ'), + (0x473, 'V'), + (0x474, 'M', 'ѵ'), + (0x475, 'V'), + (0x476, 'M', 'ѷ'), + (0x477, 'V'), + (0x478, 'M', 'ѹ'), + (0x479, 'V'), + (0x47A, 'M', 'ѻ'), + (0x47B, 'V'), + (0x47C, 'M', 'ѽ'), + (0x47D, 'V'), + (0x47E, 'M', 'ѿ'), + (0x47F, 'V'), + (0x480, 'M', 'ҁ'), + (0x481, 'V'), + (0x48A, 'M', 'ҋ'), + (0x48B, 'V'), + (0x48C, 'M', 'ҍ'), + (0x48D, 'V'), + (0x48E, 'M', 'ҏ'), + (0x48F, 'V'), + (0x490, 'M', 'ґ'), + (0x491, 'V'), + (0x492, 'M', 'ғ'), + (0x493, 'V'), + (0x494, 'M', 'ҕ'), + (0x495, 'V'), + (0x496, 'M', 'җ'), + (0x497, 'V'), + (0x498, 'M', 'ҙ'), + (0x499, 'V'), + (0x49A, 'M', 'қ'), + (0x49B, 'V'), + (0x49C, 'M', 'ҝ'), + (0x49D, 'V'), ] - def _seg_8() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x49E, "M", "ҟ"), - (0x49F, "V"), - (0x4A0, "M", "ҡ"), - (0x4A1, "V"), - (0x4A2, "M", "ң"), - (0x4A3, "V"), - (0x4A4, "M", "ҥ"), - (0x4A5, "V"), - (0x4A6, "M", "ҧ"), - (0x4A7, "V"), - (0x4A8, "M", "ҩ"), - (0x4A9, "V"), - (0x4AA, "M", "ҫ"), - (0x4AB, "V"), - (0x4AC, "M", "ҭ"), - (0x4AD, "V"), - (0x4AE, "M", "ү"), - (0x4AF, "V"), - (0x4B0, "M", "ұ"), - (0x4B1, "V"), - (0x4B2, "M", "ҳ"), - (0x4B3, "V"), - (0x4B4, "M", "ҵ"), - (0x4B5, "V"), - (0x4B6, "M", "ҷ"), - (0x4B7, "V"), - (0x4B8, "M", "ҹ"), - (0x4B9, "V"), - (0x4BA, "M", "һ"), - (0x4BB, "V"), - (0x4BC, "M", "ҽ"), - (0x4BD, "V"), - (0x4BE, "M", "ҿ"), - (0x4BF, "V"), - (0x4C0, "X"), - (0x4C1, "M", "ӂ"), - (0x4C2, "V"), - (0x4C3, "M", "ӄ"), - (0x4C4, "V"), - (0x4C5, "M", "ӆ"), - (0x4C6, "V"), - (0x4C7, "M", "ӈ"), - (0x4C8, "V"), - (0x4C9, "M", "ӊ"), - (0x4CA, "V"), - (0x4CB, "M", "ӌ"), - (0x4CC, "V"), - (0x4CD, "M", "ӎ"), - (0x4CE, "V"), - (0x4D0, "M", "ӑ"), - (0x4D1, "V"), - (0x4D2, "M", "ӓ"), - (0x4D3, "V"), - (0x4D4, "M", "ӕ"), - (0x4D5, "V"), - (0x4D6, "M", "ӗ"), - (0x4D7, "V"), - (0x4D8, "M", "ә"), - (0x4D9, "V"), - (0x4DA, "M", "ӛ"), - (0x4DB, "V"), - (0x4DC, "M", "ӝ"), - (0x4DD, "V"), - (0x4DE, "M", "ӟ"), - (0x4DF, "V"), - (0x4E0, "M", "ӡ"), - (0x4E1, "V"), - (0x4E2, "M", "ӣ"), - (0x4E3, "V"), - (0x4E4, "M", "ӥ"), - (0x4E5, "V"), - (0x4E6, "M", "ӧ"), - (0x4E7, "V"), - (0x4E8, "M", "ө"), - (0x4E9, "V"), - (0x4EA, "M", "ӫ"), - (0x4EB, "V"), - (0x4EC, "M", "ӭ"), - (0x4ED, "V"), - (0x4EE, "M", "ӯ"), - (0x4EF, "V"), - (0x4F0, "M", "ӱ"), - (0x4F1, "V"), - (0x4F2, "M", "ӳ"), - (0x4F3, "V"), - (0x4F4, "M", "ӵ"), - (0x4F5, "V"), - (0x4F6, "M", "ӷ"), - (0x4F7, "V"), - (0x4F8, "M", "ӹ"), - (0x4F9, "V"), - (0x4FA, "M", "ӻ"), - (0x4FB, "V"), - (0x4FC, "M", "ӽ"), - (0x4FD, "V"), - (0x4FE, "M", "ӿ"), - (0x4FF, "V"), - (0x500, "M", "ԁ"), - (0x501, "V"), - (0x502, "M", "ԃ"), + (0x49E, 'M', 'ҟ'), + (0x49F, 'V'), + (0x4A0, 'M', 'ҡ'), + (0x4A1, 'V'), + (0x4A2, 'M', 'ң'), + (0x4A3, 'V'), + (0x4A4, 'M', 'ҥ'), + (0x4A5, 'V'), + (0x4A6, 'M', 'ҧ'), + (0x4A7, 'V'), + (0x4A8, 'M', 'ҩ'), + (0x4A9, 'V'), + (0x4AA, 'M', 'ҫ'), + (0x4AB, 'V'), + (0x4AC, 'M', 'ҭ'), + (0x4AD, 'V'), + (0x4AE, 'M', 'ү'), + (0x4AF, 'V'), + (0x4B0, 'M', 'ұ'), + (0x4B1, 'V'), + (0x4B2, 'M', 'ҳ'), + (0x4B3, 'V'), + (0x4B4, 'M', 'ҵ'), + (0x4B5, 'V'), + (0x4B6, 'M', 'ҷ'), + (0x4B7, 'V'), + (0x4B8, 'M', 'ҹ'), + (0x4B9, 'V'), + (0x4BA, 'M', 'һ'), + (0x4BB, 'V'), + (0x4BC, 'M', 'ҽ'), + (0x4BD, 'V'), + (0x4BE, 'M', 'ҿ'), + (0x4BF, 'V'), + (0x4C0, 'X'), + (0x4C1, 'M', 'ӂ'), + (0x4C2, 'V'), + (0x4C3, 'M', 'ӄ'), + (0x4C4, 'V'), + (0x4C5, 'M', 'ӆ'), + (0x4C6, 'V'), + (0x4C7, 'M', 'ӈ'), + (0x4C8, 'V'), + (0x4C9, 'M', 'ӊ'), + (0x4CA, 'V'), + (0x4CB, 'M', 'ӌ'), + (0x4CC, 'V'), + (0x4CD, 'M', 'ӎ'), + (0x4CE, 'V'), + (0x4D0, 'M', 'ӑ'), + (0x4D1, 'V'), + (0x4D2, 'M', 'ӓ'), + (0x4D3, 'V'), + (0x4D4, 'M', 'ӕ'), + (0x4D5, 'V'), + (0x4D6, 'M', 'ӗ'), + (0x4D7, 'V'), + (0x4D8, 'M', 'ә'), + (0x4D9, 'V'), + (0x4DA, 'M', 'ӛ'), + (0x4DB, 'V'), + (0x4DC, 'M', 'ӝ'), + (0x4DD, 'V'), + (0x4DE, 'M', 'ӟ'), + (0x4DF, 'V'), + (0x4E0, 'M', 'ӡ'), + (0x4E1, 'V'), + (0x4E2, 'M', 'ӣ'), + (0x4E3, 'V'), + (0x4E4, 'M', 'ӥ'), + (0x4E5, 'V'), + (0x4E6, 'M', 'ӧ'), + (0x4E7, 'V'), + (0x4E8, 'M', 'ө'), + (0x4E9, 'V'), + (0x4EA, 'M', 'ӫ'), + (0x4EB, 'V'), + (0x4EC, 'M', 'ӭ'), + (0x4ED, 'V'), + (0x4EE, 'M', 'ӯ'), + (0x4EF, 'V'), + (0x4F0, 'M', 'ӱ'), + (0x4F1, 'V'), + (0x4F2, 'M', 'ӳ'), + (0x4F3, 'V'), + (0x4F4, 'M', 'ӵ'), + (0x4F5, 'V'), + (0x4F6, 'M', 'ӷ'), + (0x4F7, 'V'), + (0x4F8, 'M', 'ӹ'), + (0x4F9, 'V'), + (0x4FA, 'M', 'ӻ'), + (0x4FB, 'V'), + (0x4FC, 'M', 'ӽ'), + (0x4FD, 'V'), + (0x4FE, 'M', 'ӿ'), + (0x4FF, 'V'), + (0x500, 'M', 'ԁ'), + (0x501, 'V'), + (0x502, 'M', 'ԃ'), ] - def _seg_9() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x503, "V"), - (0x504, "M", "ԅ"), - (0x505, "V"), - (0x506, "M", "ԇ"), - (0x507, "V"), - (0x508, "M", "ԉ"), - (0x509, "V"), - (0x50A, "M", "ԋ"), - (0x50B, "V"), - (0x50C, "M", "ԍ"), - (0x50D, "V"), - (0x50E, "M", "ԏ"), - (0x50F, "V"), - (0x510, "M", "ԑ"), - (0x511, "V"), - (0x512, "M", "ԓ"), - (0x513, "V"), - (0x514, "M", "ԕ"), - (0x515, "V"), - (0x516, "M", "ԗ"), - (0x517, "V"), - (0x518, "M", "ԙ"), - (0x519, "V"), - (0x51A, "M", "ԛ"), - (0x51B, "V"), - (0x51C, "M", "ԝ"), - (0x51D, "V"), - (0x51E, "M", "ԟ"), - (0x51F, "V"), - (0x520, "M", "ԡ"), - (0x521, "V"), - (0x522, "M", "ԣ"), - (0x523, "V"), - (0x524, "M", "ԥ"), - (0x525, "V"), - (0x526, "M", "ԧ"), - (0x527, "V"), - (0x528, "M", "ԩ"), - (0x529, "V"), - (0x52A, "M", "ԫ"), - (0x52B, "V"), - (0x52C, "M", "ԭ"), - (0x52D, "V"), - (0x52E, "M", "ԯ"), - (0x52F, "V"), - (0x530, "X"), - (0x531, "M", "ա"), - (0x532, "M", "բ"), - (0x533, "M", "գ"), - (0x534, "M", "դ"), - (0x535, "M", "ե"), - (0x536, "M", "զ"), - (0x537, "M", "է"), - (0x538, "M", "ը"), - (0x539, "M", "թ"), - (0x53A, "M", "ժ"), - (0x53B, "M", "ի"), - (0x53C, "M", "լ"), - (0x53D, "M", "խ"), - (0x53E, "M", "ծ"), - (0x53F, "M", "կ"), - (0x540, "M", "հ"), - (0x541, "M", "ձ"), - (0x542, "M", "ղ"), - (0x543, "M", "ճ"), - (0x544, "M", "մ"), - (0x545, "M", "յ"), - (0x546, "M", "ն"), - (0x547, "M", "շ"), - (0x548, "M", "ո"), - (0x549, "M", "չ"), - (0x54A, "M", "պ"), - (0x54B, "M", "ջ"), - (0x54C, "M", "ռ"), - (0x54D, "M", "ս"), - (0x54E, "M", "վ"), - (0x54F, "M", "տ"), - (0x550, "M", "ր"), - (0x551, "M", "ց"), - (0x552, "M", "ւ"), - (0x553, "M", "փ"), - (0x554, "M", "ք"), - (0x555, "M", "օ"), - (0x556, "M", "ֆ"), - (0x557, "X"), - (0x559, "V"), - (0x587, "M", "եւ"), - (0x588, "V"), - (0x58B, "X"), - (0x58D, "V"), - (0x590, "X"), - (0x591, "V"), - (0x5C8, "X"), - (0x5D0, "V"), - (0x5EB, "X"), - (0x5EF, "V"), - (0x5F5, "X"), - (0x606, "V"), - (0x61C, "X"), - (0x61D, "V"), + (0x503, 'V'), + (0x504, 'M', 'ԅ'), + (0x505, 'V'), + (0x506, 'M', 'ԇ'), + (0x507, 'V'), + (0x508, 'M', 'ԉ'), + (0x509, 'V'), + (0x50A, 'M', 'ԋ'), + (0x50B, 'V'), + (0x50C, 'M', 'ԍ'), + (0x50D, 'V'), + (0x50E, 'M', 'ԏ'), + (0x50F, 'V'), + (0x510, 'M', 'ԑ'), + (0x511, 'V'), + (0x512, 'M', 'ԓ'), + (0x513, 'V'), + (0x514, 'M', 'ԕ'), + (0x515, 'V'), + (0x516, 'M', 'ԗ'), + (0x517, 'V'), + (0x518, 'M', 'ԙ'), + (0x519, 'V'), + (0x51A, 'M', 'ԛ'), + (0x51B, 'V'), + (0x51C, 'M', 'ԝ'), + (0x51D, 'V'), + (0x51E, 'M', 'ԟ'), + (0x51F, 'V'), + (0x520, 'M', 'ԡ'), + (0x521, 'V'), + (0x522, 'M', 'ԣ'), + (0x523, 'V'), + (0x524, 'M', 'ԥ'), + (0x525, 'V'), + (0x526, 'M', 'ԧ'), + (0x527, 'V'), + (0x528, 'M', 'ԩ'), + (0x529, 'V'), + (0x52A, 'M', 'ԫ'), + (0x52B, 'V'), + (0x52C, 'M', 'ԭ'), + (0x52D, 'V'), + (0x52E, 'M', 'ԯ'), + (0x52F, 'V'), + (0x530, 'X'), + (0x531, 'M', 'ա'), + (0x532, 'M', 'բ'), + (0x533, 'M', 'գ'), + (0x534, 'M', 'դ'), + (0x535, 'M', 'ե'), + (0x536, 'M', 'զ'), + (0x537, 'M', 'է'), + (0x538, 'M', 'ը'), + (0x539, 'M', 'թ'), + (0x53A, 'M', 'ժ'), + (0x53B, 'M', 'ի'), + (0x53C, 'M', 'լ'), + (0x53D, 'M', 'խ'), + (0x53E, 'M', 'ծ'), + (0x53F, 'M', 'կ'), + (0x540, 'M', 'հ'), + (0x541, 'M', 'ձ'), + (0x542, 'M', 'ղ'), + (0x543, 'M', 'ճ'), + (0x544, 'M', 'մ'), + (0x545, 'M', 'յ'), + (0x546, 'M', 'ն'), + (0x547, 'M', 'շ'), + (0x548, 'M', 'ո'), + (0x549, 'M', 'չ'), + (0x54A, 'M', 'պ'), + (0x54B, 'M', 'ջ'), + (0x54C, 'M', 'ռ'), + (0x54D, 'M', 'ս'), + (0x54E, 'M', 'վ'), + (0x54F, 'M', 'տ'), + (0x550, 'M', 'ր'), + (0x551, 'M', 'ց'), + (0x552, 'M', 'ւ'), + (0x553, 'M', 'փ'), + (0x554, 'M', 'ք'), + (0x555, 'M', 'օ'), + (0x556, 'M', 'ֆ'), + (0x557, 'X'), + (0x559, 'V'), + (0x587, 'M', 'եւ'), + (0x588, 'V'), + (0x58B, 'X'), + (0x58D, 'V'), + (0x590, 'X'), + (0x591, 'V'), + (0x5C8, 'X'), + (0x5D0, 'V'), + (0x5EB, 'X'), + (0x5EF, 'V'), + (0x5F5, 'X'), + (0x606, 'V'), + (0x61C, 'X'), + (0x61D, 'V'), ] - def _seg_10() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x675, "M", "اٴ"), - (0x676, "M", "وٴ"), - (0x677, "M", "ۇٴ"), - (0x678, "M", "يٴ"), - (0x679, "V"), - (0x6DD, "X"), - (0x6DE, "V"), - (0x70E, "X"), - (0x710, "V"), - (0x74B, "X"), - (0x74D, "V"), - (0x7B2, "X"), - (0x7C0, "V"), - (0x7FB, "X"), - (0x7FD, "V"), - (0x82E, "X"), - (0x830, "V"), - (0x83F, "X"), - (0x840, "V"), - (0x85C, "X"), - (0x85E, "V"), - (0x85F, "X"), - (0x860, "V"), - (0x86B, "X"), - (0x870, "V"), - (0x88F, "X"), - (0x898, "V"), - (0x8E2, "X"), - (0x8E3, "V"), - (0x958, "M", "क़"), - (0x959, "M", "ख़"), - (0x95A, "M", "ग़"), - (0x95B, "M", "ज़"), - (0x95C, "M", "ड़"), - (0x95D, "M", "ढ़"), - (0x95E, "M", "फ़"), - (0x95F, "M", "य़"), - (0x960, "V"), - (0x984, "X"), - (0x985, "V"), - (0x98D, "X"), - (0x98F, "V"), - (0x991, "X"), - (0x993, "V"), - (0x9A9, "X"), - (0x9AA, "V"), - (0x9B1, "X"), - (0x9B2, "V"), - (0x9B3, "X"), - (0x9B6, "V"), - (0x9BA, "X"), - (0x9BC, "V"), - (0x9C5, "X"), - (0x9C7, "V"), - (0x9C9, "X"), - (0x9CB, "V"), - (0x9CF, "X"), - (0x9D7, "V"), - (0x9D8, "X"), - (0x9DC, "M", "ড়"), - (0x9DD, "M", "ঢ়"), - (0x9DE, "X"), - (0x9DF, "M", "য়"), - (0x9E0, "V"), - (0x9E4, "X"), - (0x9E6, "V"), - (0x9FF, "X"), - (0xA01, "V"), - (0xA04, "X"), - (0xA05, "V"), - (0xA0B, "X"), - (0xA0F, "V"), - (0xA11, "X"), - (0xA13, "V"), - (0xA29, "X"), - (0xA2A, "V"), - (0xA31, "X"), - (0xA32, "V"), - (0xA33, "M", "ਲ਼"), - (0xA34, "X"), - (0xA35, "V"), - (0xA36, "M", "ਸ਼"), - (0xA37, "X"), - (0xA38, "V"), - (0xA3A, "X"), - (0xA3C, "V"), - (0xA3D, "X"), - (0xA3E, "V"), - (0xA43, "X"), - (0xA47, "V"), - (0xA49, "X"), - (0xA4B, "V"), - (0xA4E, "X"), - (0xA51, "V"), - (0xA52, "X"), - (0xA59, "M", "ਖ਼"), - (0xA5A, "M", "ਗ਼"), - (0xA5B, "M", "ਜ਼"), - (0xA5C, "V"), - (0xA5D, "X"), + (0x675, 'M', 'اٴ'), + (0x676, 'M', 'وٴ'), + (0x677, 'M', 'ۇٴ'), + (0x678, 'M', 'يٴ'), + (0x679, 'V'), + (0x6DD, 'X'), + (0x6DE, 'V'), + (0x70E, 'X'), + (0x710, 'V'), + (0x74B, 'X'), + (0x74D, 'V'), + (0x7B2, 'X'), + (0x7C0, 'V'), + (0x7FB, 'X'), + (0x7FD, 'V'), + (0x82E, 'X'), + (0x830, 'V'), + (0x83F, 'X'), + (0x840, 'V'), + (0x85C, 'X'), + (0x85E, 'V'), + (0x85F, 'X'), + (0x860, 'V'), + (0x86B, 'X'), + (0x870, 'V'), + (0x88F, 'X'), + (0x898, 'V'), + (0x8E2, 'X'), + (0x8E3, 'V'), + (0x958, 'M', 'क़'), + (0x959, 'M', 'ख़'), + (0x95A, 'M', 'ग़'), + (0x95B, 'M', 'ज़'), + (0x95C, 'M', 'ड़'), + (0x95D, 'M', 'ढ़'), + (0x95E, 'M', 'फ़'), + (0x95F, 'M', 'य़'), + (0x960, 'V'), + (0x984, 'X'), + (0x985, 'V'), + (0x98D, 'X'), + (0x98F, 'V'), + (0x991, 'X'), + (0x993, 'V'), + (0x9A9, 'X'), + (0x9AA, 'V'), + (0x9B1, 'X'), + (0x9B2, 'V'), + (0x9B3, 'X'), + (0x9B6, 'V'), + (0x9BA, 'X'), + (0x9BC, 'V'), + (0x9C5, 'X'), + (0x9C7, 'V'), + (0x9C9, 'X'), + (0x9CB, 'V'), + (0x9CF, 'X'), + (0x9D7, 'V'), + (0x9D8, 'X'), + (0x9DC, 'M', 'ড়'), + (0x9DD, 'M', 'ঢ়'), + (0x9DE, 'X'), + (0x9DF, 'M', 'য়'), + (0x9E0, 'V'), + (0x9E4, 'X'), + (0x9E6, 'V'), + (0x9FF, 'X'), + (0xA01, 'V'), + (0xA04, 'X'), + (0xA05, 'V'), + (0xA0B, 'X'), + (0xA0F, 'V'), + (0xA11, 'X'), + (0xA13, 'V'), + (0xA29, 'X'), + (0xA2A, 'V'), + (0xA31, 'X'), + (0xA32, 'V'), + (0xA33, 'M', 'ਲ਼'), + (0xA34, 'X'), + (0xA35, 'V'), + (0xA36, 'M', 'ਸ਼'), + (0xA37, 'X'), + (0xA38, 'V'), + (0xA3A, 'X'), + (0xA3C, 'V'), + (0xA3D, 'X'), + (0xA3E, 'V'), + (0xA43, 'X'), + (0xA47, 'V'), + (0xA49, 'X'), + (0xA4B, 'V'), + (0xA4E, 'X'), + (0xA51, 'V'), + (0xA52, 'X'), + (0xA59, 'M', 'ਖ਼'), + (0xA5A, 'M', 'ਗ਼'), + (0xA5B, 'M', 'ਜ਼'), + (0xA5C, 'V'), + (0xA5D, 'X'), ] - def _seg_11() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0xA5E, "M", "ਫ਼"), - (0xA5F, "X"), - (0xA66, "V"), - (0xA77, "X"), - (0xA81, "V"), - (0xA84, "X"), - (0xA85, "V"), - (0xA8E, "X"), - (0xA8F, "V"), - (0xA92, "X"), - (0xA93, "V"), - (0xAA9, "X"), - (0xAAA, "V"), - (0xAB1, "X"), - (0xAB2, "V"), - (0xAB4, "X"), - (0xAB5, "V"), - (0xABA, "X"), - (0xABC, "V"), - (0xAC6, "X"), - (0xAC7, "V"), - (0xACA, "X"), - (0xACB, "V"), - (0xACE, "X"), - (0xAD0, "V"), - (0xAD1, "X"), - (0xAE0, "V"), - (0xAE4, "X"), - (0xAE6, "V"), - (0xAF2, "X"), - (0xAF9, "V"), - (0xB00, "X"), - (0xB01, "V"), - (0xB04, "X"), - (0xB05, "V"), - (0xB0D, "X"), - (0xB0F, "V"), - (0xB11, "X"), - (0xB13, "V"), - (0xB29, "X"), - (0xB2A, "V"), - (0xB31, "X"), - (0xB32, "V"), - (0xB34, "X"), - (0xB35, "V"), - (0xB3A, "X"), - (0xB3C, "V"), - (0xB45, "X"), - (0xB47, "V"), - (0xB49, "X"), - (0xB4B, "V"), - (0xB4E, "X"), - (0xB55, "V"), - (0xB58, "X"), - (0xB5C, "M", "ଡ଼"), - (0xB5D, "M", "ଢ଼"), - (0xB5E, "X"), - (0xB5F, "V"), - (0xB64, "X"), - (0xB66, "V"), - (0xB78, "X"), - (0xB82, "V"), - (0xB84, "X"), - (0xB85, "V"), - (0xB8B, "X"), - (0xB8E, "V"), - (0xB91, "X"), - (0xB92, "V"), - (0xB96, "X"), - (0xB99, "V"), - (0xB9B, "X"), - (0xB9C, "V"), - (0xB9D, "X"), - (0xB9E, "V"), - (0xBA0, "X"), - (0xBA3, "V"), - (0xBA5, "X"), - (0xBA8, "V"), - (0xBAB, "X"), - (0xBAE, "V"), - (0xBBA, "X"), - (0xBBE, "V"), - (0xBC3, "X"), - (0xBC6, "V"), - (0xBC9, "X"), - (0xBCA, "V"), - (0xBCE, "X"), - (0xBD0, "V"), - (0xBD1, "X"), - (0xBD7, "V"), - (0xBD8, "X"), - (0xBE6, "V"), - (0xBFB, "X"), - (0xC00, "V"), - (0xC0D, "X"), - (0xC0E, "V"), - (0xC11, "X"), - (0xC12, "V"), - (0xC29, "X"), - (0xC2A, "V"), + (0xA5E, 'M', 'ਫ਼'), + (0xA5F, 'X'), + (0xA66, 'V'), + (0xA77, 'X'), + (0xA81, 'V'), + (0xA84, 'X'), + (0xA85, 'V'), + (0xA8E, 'X'), + (0xA8F, 'V'), + (0xA92, 'X'), + (0xA93, 'V'), + (0xAA9, 'X'), + (0xAAA, 'V'), + (0xAB1, 'X'), + (0xAB2, 'V'), + (0xAB4, 'X'), + (0xAB5, 'V'), + (0xABA, 'X'), + (0xABC, 'V'), + (0xAC6, 'X'), + (0xAC7, 'V'), + (0xACA, 'X'), + (0xACB, 'V'), + (0xACE, 'X'), + (0xAD0, 'V'), + (0xAD1, 'X'), + (0xAE0, 'V'), + (0xAE4, 'X'), + (0xAE6, 'V'), + (0xAF2, 'X'), + (0xAF9, 'V'), + (0xB00, 'X'), + (0xB01, 'V'), + (0xB04, 'X'), + (0xB05, 'V'), + (0xB0D, 'X'), + (0xB0F, 'V'), + (0xB11, 'X'), + (0xB13, 'V'), + (0xB29, 'X'), + (0xB2A, 'V'), + (0xB31, 'X'), + (0xB32, 'V'), + (0xB34, 'X'), + (0xB35, 'V'), + (0xB3A, 'X'), + (0xB3C, 'V'), + (0xB45, 'X'), + (0xB47, 'V'), + (0xB49, 'X'), + (0xB4B, 'V'), + (0xB4E, 'X'), + (0xB55, 'V'), + (0xB58, 'X'), + (0xB5C, 'M', 'ଡ଼'), + (0xB5D, 'M', 'ଢ଼'), + (0xB5E, 'X'), + (0xB5F, 'V'), + (0xB64, 'X'), + (0xB66, 'V'), + (0xB78, 'X'), + (0xB82, 'V'), + (0xB84, 'X'), + (0xB85, 'V'), + (0xB8B, 'X'), + (0xB8E, 'V'), + (0xB91, 'X'), + (0xB92, 'V'), + (0xB96, 'X'), + (0xB99, 'V'), + (0xB9B, 'X'), + (0xB9C, 'V'), + (0xB9D, 'X'), + (0xB9E, 'V'), + (0xBA0, 'X'), + (0xBA3, 'V'), + (0xBA5, 'X'), + (0xBA8, 'V'), + (0xBAB, 'X'), + (0xBAE, 'V'), + (0xBBA, 'X'), + (0xBBE, 'V'), + (0xBC3, 'X'), + (0xBC6, 'V'), + (0xBC9, 'X'), + (0xBCA, 'V'), + (0xBCE, 'X'), + (0xBD0, 'V'), + (0xBD1, 'X'), + (0xBD7, 'V'), + (0xBD8, 'X'), + (0xBE6, 'V'), + (0xBFB, 'X'), + (0xC00, 'V'), + (0xC0D, 'X'), + (0xC0E, 'V'), + (0xC11, 'X'), + (0xC12, 'V'), + (0xC29, 'X'), + (0xC2A, 'V'), ] - def _seg_12() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0xC3A, "X"), - (0xC3C, "V"), - (0xC45, "X"), - (0xC46, "V"), - (0xC49, "X"), - (0xC4A, "V"), - (0xC4E, "X"), - (0xC55, "V"), - (0xC57, "X"), - (0xC58, "V"), - (0xC5B, "X"), - (0xC5D, "V"), - (0xC5E, "X"), - (0xC60, "V"), - (0xC64, "X"), - (0xC66, "V"), - (0xC70, "X"), - (0xC77, "V"), - (0xC8D, "X"), - (0xC8E, "V"), - (0xC91, "X"), - (0xC92, "V"), - (0xCA9, "X"), - (0xCAA, "V"), - (0xCB4, "X"), - (0xCB5, "V"), - (0xCBA, "X"), - (0xCBC, "V"), - (0xCC5, "X"), - (0xCC6, "V"), - (0xCC9, "X"), - (0xCCA, "V"), - (0xCCE, "X"), - (0xCD5, "V"), - (0xCD7, "X"), - (0xCDD, "V"), - (0xCDF, "X"), - (0xCE0, "V"), - (0xCE4, "X"), - (0xCE6, "V"), - (0xCF0, "X"), - (0xCF1, "V"), - (0xCF4, "X"), - (0xD00, "V"), - (0xD0D, "X"), - (0xD0E, "V"), - (0xD11, "X"), - (0xD12, "V"), - (0xD45, "X"), - (0xD46, "V"), - (0xD49, "X"), - (0xD4A, "V"), - (0xD50, "X"), - (0xD54, "V"), - (0xD64, "X"), - (0xD66, "V"), - (0xD80, "X"), - (0xD81, "V"), - (0xD84, "X"), - (0xD85, "V"), - (0xD97, "X"), - (0xD9A, "V"), - (0xDB2, "X"), - (0xDB3, "V"), - (0xDBC, "X"), - (0xDBD, "V"), - (0xDBE, "X"), - (0xDC0, "V"), - (0xDC7, "X"), - (0xDCA, "V"), - (0xDCB, "X"), - (0xDCF, "V"), - (0xDD5, "X"), - (0xDD6, "V"), - (0xDD7, "X"), - (0xDD8, "V"), - (0xDE0, "X"), - (0xDE6, "V"), - (0xDF0, "X"), - (0xDF2, "V"), - (0xDF5, "X"), - (0xE01, "V"), - (0xE33, "M", "ํา"), - (0xE34, "V"), - (0xE3B, "X"), - (0xE3F, "V"), - (0xE5C, "X"), - (0xE81, "V"), - (0xE83, "X"), - (0xE84, "V"), - (0xE85, "X"), - (0xE86, "V"), - (0xE8B, "X"), - (0xE8C, "V"), - (0xEA4, "X"), - (0xEA5, "V"), - (0xEA6, "X"), - (0xEA7, "V"), - (0xEB3, "M", "ໍາ"), - (0xEB4, "V"), + (0xC3A, 'X'), + (0xC3C, 'V'), + (0xC45, 'X'), + (0xC46, 'V'), + (0xC49, 'X'), + (0xC4A, 'V'), + (0xC4E, 'X'), + (0xC55, 'V'), + (0xC57, 'X'), + (0xC58, 'V'), + (0xC5B, 'X'), + (0xC5D, 'V'), + (0xC5E, 'X'), + (0xC60, 'V'), + (0xC64, 'X'), + (0xC66, 'V'), + (0xC70, 'X'), + (0xC77, 'V'), + (0xC8D, 'X'), + (0xC8E, 'V'), + (0xC91, 'X'), + (0xC92, 'V'), + (0xCA9, 'X'), + (0xCAA, 'V'), + (0xCB4, 'X'), + (0xCB5, 'V'), + (0xCBA, 'X'), + (0xCBC, 'V'), + (0xCC5, 'X'), + (0xCC6, 'V'), + (0xCC9, 'X'), + (0xCCA, 'V'), + (0xCCE, 'X'), + (0xCD5, 'V'), + (0xCD7, 'X'), + (0xCDD, 'V'), + (0xCDF, 'X'), + (0xCE0, 'V'), + (0xCE4, 'X'), + (0xCE6, 'V'), + (0xCF0, 'X'), + (0xCF1, 'V'), + (0xCF4, 'X'), + (0xD00, 'V'), + (0xD0D, 'X'), + (0xD0E, 'V'), + (0xD11, 'X'), + (0xD12, 'V'), + (0xD45, 'X'), + (0xD46, 'V'), + (0xD49, 'X'), + (0xD4A, 'V'), + (0xD50, 'X'), + (0xD54, 'V'), + (0xD64, 'X'), + (0xD66, 'V'), + (0xD80, 'X'), + (0xD81, 'V'), + (0xD84, 'X'), + (0xD85, 'V'), + (0xD97, 'X'), + (0xD9A, 'V'), + (0xDB2, 'X'), + (0xDB3, 'V'), + (0xDBC, 'X'), + (0xDBD, 'V'), + (0xDBE, 'X'), + (0xDC0, 'V'), + (0xDC7, 'X'), + (0xDCA, 'V'), + (0xDCB, 'X'), + (0xDCF, 'V'), + (0xDD5, 'X'), + (0xDD6, 'V'), + (0xDD7, 'X'), + (0xDD8, 'V'), + (0xDE0, 'X'), + (0xDE6, 'V'), + (0xDF0, 'X'), + (0xDF2, 'V'), + (0xDF5, 'X'), + (0xE01, 'V'), + (0xE33, 'M', 'ํา'), + (0xE34, 'V'), + (0xE3B, 'X'), + (0xE3F, 'V'), + (0xE5C, 'X'), + (0xE81, 'V'), + (0xE83, 'X'), + (0xE84, 'V'), + (0xE85, 'X'), + (0xE86, 'V'), + (0xE8B, 'X'), + (0xE8C, 'V'), + (0xEA4, 'X'), + (0xEA5, 'V'), + (0xEA6, 'X'), + (0xEA7, 'V'), + (0xEB3, 'M', 'ໍາ'), + (0xEB4, 'V'), ] - def _seg_13() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0xEBE, "X"), - (0xEC0, "V"), - (0xEC5, "X"), - (0xEC6, "V"), - (0xEC7, "X"), - (0xEC8, "V"), - (0xECF, "X"), - (0xED0, "V"), - (0xEDA, "X"), - (0xEDC, "M", "ຫນ"), - (0xEDD, "M", "ຫມ"), - (0xEDE, "V"), - (0xEE0, "X"), - (0xF00, "V"), - (0xF0C, "M", "་"), - (0xF0D, "V"), - (0xF43, "M", "གྷ"), - (0xF44, "V"), - (0xF48, "X"), - (0xF49, "V"), - (0xF4D, "M", "ཌྷ"), - (0xF4E, "V"), - (0xF52, "M", "དྷ"), - (0xF53, "V"), - (0xF57, "M", "བྷ"), - (0xF58, "V"), - (0xF5C, "M", "ཛྷ"), - (0xF5D, "V"), - (0xF69, "M", "ཀྵ"), - (0xF6A, "V"), - (0xF6D, "X"), - (0xF71, "V"), - (0xF73, "M", "ཱི"), - (0xF74, "V"), - (0xF75, "M", "ཱུ"), - (0xF76, "M", "ྲྀ"), - (0xF77, "M", "ྲཱྀ"), - (0xF78, "M", "ླྀ"), - (0xF79, "M", "ླཱྀ"), - (0xF7A, "V"), - (0xF81, "M", "ཱྀ"), - (0xF82, "V"), - (0xF93, "M", "ྒྷ"), - (0xF94, "V"), - (0xF98, "X"), - (0xF99, "V"), - (0xF9D, "M", "ྜྷ"), - (0xF9E, "V"), - (0xFA2, "M", "ྡྷ"), - (0xFA3, "V"), - (0xFA7, "M", "ྦྷ"), - (0xFA8, "V"), - (0xFAC, "M", "ྫྷ"), - (0xFAD, "V"), - (0xFB9, "M", "ྐྵ"), - (0xFBA, "V"), - (0xFBD, "X"), - (0xFBE, "V"), - (0xFCD, "X"), - (0xFCE, "V"), - (0xFDB, "X"), - (0x1000, "V"), - (0x10A0, "X"), - (0x10C7, "M", "ⴧ"), - (0x10C8, "X"), - (0x10CD, "M", "ⴭ"), - (0x10CE, "X"), - (0x10D0, "V"), - (0x10FC, "M", "ნ"), - (0x10FD, "V"), - (0x115F, "X"), - (0x1161, "V"), - (0x1249, "X"), - (0x124A, "V"), - (0x124E, "X"), - (0x1250, "V"), - (0x1257, "X"), - (0x1258, "V"), - (0x1259, "X"), - (0x125A, "V"), - (0x125E, "X"), - (0x1260, "V"), - (0x1289, "X"), - (0x128A, "V"), - (0x128E, "X"), - (0x1290, "V"), - (0x12B1, "X"), - (0x12B2, "V"), - (0x12B6, "X"), - (0x12B8, "V"), - (0x12BF, "X"), - (0x12C0, "V"), - (0x12C1, "X"), - (0x12C2, "V"), - (0x12C6, "X"), - (0x12C8, "V"), - (0x12D7, "X"), - (0x12D8, "V"), - (0x1311, "X"), - (0x1312, "V"), + (0xEBE, 'X'), + (0xEC0, 'V'), + (0xEC5, 'X'), + (0xEC6, 'V'), + (0xEC7, 'X'), + (0xEC8, 'V'), + (0xECF, 'X'), + (0xED0, 'V'), + (0xEDA, 'X'), + (0xEDC, 'M', 'ຫນ'), + (0xEDD, 'M', 'ຫມ'), + (0xEDE, 'V'), + (0xEE0, 'X'), + (0xF00, 'V'), + (0xF0C, 'M', '་'), + (0xF0D, 'V'), + (0xF43, 'M', 'གྷ'), + (0xF44, 'V'), + (0xF48, 'X'), + (0xF49, 'V'), + (0xF4D, 'M', 'ཌྷ'), + (0xF4E, 'V'), + (0xF52, 'M', 'དྷ'), + (0xF53, 'V'), + (0xF57, 'M', 'བྷ'), + (0xF58, 'V'), + (0xF5C, 'M', 'ཛྷ'), + (0xF5D, 'V'), + (0xF69, 'M', 'ཀྵ'), + (0xF6A, 'V'), + (0xF6D, 'X'), + (0xF71, 'V'), + (0xF73, 'M', 'ཱི'), + (0xF74, 'V'), + (0xF75, 'M', 'ཱུ'), + (0xF76, 'M', 'ྲྀ'), + (0xF77, 'M', 'ྲཱྀ'), + (0xF78, 'M', 'ླྀ'), + (0xF79, 'M', 'ླཱྀ'), + (0xF7A, 'V'), + (0xF81, 'M', 'ཱྀ'), + (0xF82, 'V'), + (0xF93, 'M', 'ྒྷ'), + (0xF94, 'V'), + (0xF98, 'X'), + (0xF99, 'V'), + (0xF9D, 'M', 'ྜྷ'), + (0xF9E, 'V'), + (0xFA2, 'M', 'ྡྷ'), + (0xFA3, 'V'), + (0xFA7, 'M', 'ྦྷ'), + (0xFA8, 'V'), + (0xFAC, 'M', 'ྫྷ'), + (0xFAD, 'V'), + (0xFB9, 'M', 'ྐྵ'), + (0xFBA, 'V'), + (0xFBD, 'X'), + (0xFBE, 'V'), + (0xFCD, 'X'), + (0xFCE, 'V'), + (0xFDB, 'X'), + (0x1000, 'V'), + (0x10A0, 'X'), + (0x10C7, 'M', 'ⴧ'), + (0x10C8, 'X'), + (0x10CD, 'M', 'ⴭ'), + (0x10CE, 'X'), + (0x10D0, 'V'), + (0x10FC, 'M', 'ნ'), + (0x10FD, 'V'), + (0x115F, 'X'), + (0x1161, 'V'), + (0x1249, 'X'), + (0x124A, 'V'), + (0x124E, 'X'), + (0x1250, 'V'), + (0x1257, 'X'), + (0x1258, 'V'), + (0x1259, 'X'), + (0x125A, 'V'), + (0x125E, 'X'), + (0x1260, 'V'), + (0x1289, 'X'), + (0x128A, 'V'), + (0x128E, 'X'), + (0x1290, 'V'), + (0x12B1, 'X'), + (0x12B2, 'V'), + (0x12B6, 'X'), + (0x12B8, 'V'), + (0x12BF, 'X'), + (0x12C0, 'V'), + (0x12C1, 'X'), + (0x12C2, 'V'), + (0x12C6, 'X'), + (0x12C8, 'V'), + (0x12D7, 'X'), + (0x12D8, 'V'), + (0x1311, 'X'), + (0x1312, 'V'), ] - def _seg_14() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x1316, "X"), - (0x1318, "V"), - (0x135B, "X"), - (0x135D, "V"), - (0x137D, "X"), - (0x1380, "V"), - (0x139A, "X"), - (0x13A0, "V"), - (0x13F6, "X"), - (0x13F8, "M", "Ᏸ"), - (0x13F9, "M", "Ᏹ"), - (0x13FA, "M", "Ᏺ"), - (0x13FB, "M", "Ᏻ"), - (0x13FC, "M", "Ᏼ"), - (0x13FD, "M", "Ᏽ"), - (0x13FE, "X"), - (0x1400, "V"), - (0x1680, "X"), - (0x1681, "V"), - (0x169D, "X"), - (0x16A0, "V"), - (0x16F9, "X"), - (0x1700, "V"), - (0x1716, "X"), - (0x171F, "V"), - (0x1737, "X"), - (0x1740, "V"), - (0x1754, "X"), - (0x1760, "V"), - (0x176D, "X"), - (0x176E, "V"), - (0x1771, "X"), - (0x1772, "V"), - (0x1774, "X"), - (0x1780, "V"), - (0x17B4, "X"), - (0x17B6, "V"), - (0x17DE, "X"), - (0x17E0, "V"), - (0x17EA, "X"), - (0x17F0, "V"), - (0x17FA, "X"), - (0x1800, "V"), - (0x1806, "X"), - (0x1807, "V"), - (0x180B, "I"), - (0x180E, "X"), - (0x180F, "I"), - (0x1810, "V"), - (0x181A, "X"), - (0x1820, "V"), - (0x1879, "X"), - (0x1880, "V"), - (0x18AB, "X"), - (0x18B0, "V"), - (0x18F6, "X"), - (0x1900, "V"), - (0x191F, "X"), - (0x1920, "V"), - (0x192C, "X"), - (0x1930, "V"), - (0x193C, "X"), - (0x1940, "V"), - (0x1941, "X"), - (0x1944, "V"), - (0x196E, "X"), - (0x1970, "V"), - (0x1975, "X"), - (0x1980, "V"), - (0x19AC, "X"), - (0x19B0, "V"), - (0x19CA, "X"), - (0x19D0, "V"), - (0x19DB, "X"), - (0x19DE, "V"), - (0x1A1C, "X"), - (0x1A1E, "V"), - (0x1A5F, "X"), - (0x1A60, "V"), - (0x1A7D, "X"), - (0x1A7F, "V"), - (0x1A8A, "X"), - (0x1A90, "V"), - (0x1A9A, "X"), - (0x1AA0, "V"), - (0x1AAE, "X"), - (0x1AB0, "V"), - (0x1ACF, "X"), - (0x1B00, "V"), - (0x1B4D, "X"), - (0x1B50, "V"), - (0x1B7F, "X"), - (0x1B80, "V"), - (0x1BF4, "X"), - (0x1BFC, "V"), - (0x1C38, "X"), - (0x1C3B, "V"), - (0x1C4A, "X"), - (0x1C4D, "V"), - (0x1C80, "M", "в"), + (0x1316, 'X'), + (0x1318, 'V'), + (0x135B, 'X'), + (0x135D, 'V'), + (0x137D, 'X'), + (0x1380, 'V'), + (0x139A, 'X'), + (0x13A0, 'V'), + (0x13F6, 'X'), + (0x13F8, 'M', 'Ᏸ'), + (0x13F9, 'M', 'Ᏹ'), + (0x13FA, 'M', 'Ᏺ'), + (0x13FB, 'M', 'Ᏻ'), + (0x13FC, 'M', 'Ᏼ'), + (0x13FD, 'M', 'Ᏽ'), + (0x13FE, 'X'), + (0x1400, 'V'), + (0x1680, 'X'), + (0x1681, 'V'), + (0x169D, 'X'), + (0x16A0, 'V'), + (0x16F9, 'X'), + (0x1700, 'V'), + (0x1716, 'X'), + (0x171F, 'V'), + (0x1737, 'X'), + (0x1740, 'V'), + (0x1754, 'X'), + (0x1760, 'V'), + (0x176D, 'X'), + (0x176E, 'V'), + (0x1771, 'X'), + (0x1772, 'V'), + (0x1774, 'X'), + (0x1780, 'V'), + (0x17B4, 'X'), + (0x17B6, 'V'), + (0x17DE, 'X'), + (0x17E0, 'V'), + (0x17EA, 'X'), + (0x17F0, 'V'), + (0x17FA, 'X'), + (0x1800, 'V'), + (0x1806, 'X'), + (0x1807, 'V'), + (0x180B, 'I'), + (0x180E, 'X'), + (0x180F, 'I'), + (0x1810, 'V'), + (0x181A, 'X'), + (0x1820, 'V'), + (0x1879, 'X'), + (0x1880, 'V'), + (0x18AB, 'X'), + (0x18B0, 'V'), + (0x18F6, 'X'), + (0x1900, 'V'), + (0x191F, 'X'), + (0x1920, 'V'), + (0x192C, 'X'), + (0x1930, 'V'), + (0x193C, 'X'), + (0x1940, 'V'), + (0x1941, 'X'), + (0x1944, 'V'), + (0x196E, 'X'), + (0x1970, 'V'), + (0x1975, 'X'), + (0x1980, 'V'), + (0x19AC, 'X'), + (0x19B0, 'V'), + (0x19CA, 'X'), + (0x19D0, 'V'), + (0x19DB, 'X'), + (0x19DE, 'V'), + (0x1A1C, 'X'), + (0x1A1E, 'V'), + (0x1A5F, 'X'), + (0x1A60, 'V'), + (0x1A7D, 'X'), + (0x1A7F, 'V'), + (0x1A8A, 'X'), + (0x1A90, 'V'), + (0x1A9A, 'X'), + (0x1AA0, 'V'), + (0x1AAE, 'X'), + (0x1AB0, 'V'), + (0x1ACF, 'X'), + (0x1B00, 'V'), + (0x1B4D, 'X'), + (0x1B50, 'V'), + (0x1B7F, 'X'), + (0x1B80, 'V'), + (0x1BF4, 'X'), + (0x1BFC, 'V'), + (0x1C38, 'X'), + (0x1C3B, 'V'), + (0x1C4A, 'X'), + (0x1C4D, 'V'), + (0x1C80, 'M', 'в'), ] - def _seg_15() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x1C81, "M", "д"), - (0x1C82, "M", "о"), - (0x1C83, "M", "с"), - (0x1C84, "M", "т"), - (0x1C86, "M", "ъ"), - (0x1C87, "M", "ѣ"), - (0x1C88, "M", "ꙋ"), - (0x1C89, "X"), - (0x1C90, "M", "ა"), - (0x1C91, "M", "ბ"), - (0x1C92, "M", "გ"), - (0x1C93, "M", "დ"), - (0x1C94, "M", "ე"), - (0x1C95, "M", "ვ"), - (0x1C96, "M", "ზ"), - (0x1C97, "M", "თ"), - (0x1C98, "M", "ი"), - (0x1C99, "M", "კ"), - (0x1C9A, "M", "ლ"), - (0x1C9B, "M", "მ"), - (0x1C9C, "M", "ნ"), - (0x1C9D, "M", "ო"), - (0x1C9E, "M", "პ"), - (0x1C9F, "M", "ჟ"), - (0x1CA0, "M", "რ"), - (0x1CA1, "M", "ს"), - (0x1CA2, "M", "ტ"), - (0x1CA3, "M", "უ"), - (0x1CA4, "M", "ფ"), - (0x1CA5, "M", "ქ"), - (0x1CA6, "M", "ღ"), - (0x1CA7, "M", "ყ"), - (0x1CA8, "M", "შ"), - (0x1CA9, "M", "ჩ"), - (0x1CAA, "M", "ც"), - (0x1CAB, "M", "ძ"), - (0x1CAC, "M", "წ"), - (0x1CAD, "M", "ჭ"), - (0x1CAE, "M", "ხ"), - (0x1CAF, "M", "ჯ"), - (0x1CB0, "M", "ჰ"), - (0x1CB1, "M", "ჱ"), - (0x1CB2, "M", "ჲ"), - (0x1CB3, "M", "ჳ"), - (0x1CB4, "M", "ჴ"), - (0x1CB5, "M", "ჵ"), - (0x1CB6, "M", "ჶ"), - (0x1CB7, "M", "ჷ"), - (0x1CB8, "M", "ჸ"), - (0x1CB9, "M", "ჹ"), - (0x1CBA, "M", "ჺ"), - (0x1CBB, "X"), - (0x1CBD, "M", "ჽ"), - (0x1CBE, "M", "ჾ"), - (0x1CBF, "M", "ჿ"), - (0x1CC0, "V"), - (0x1CC8, "X"), - (0x1CD0, "V"), - (0x1CFB, "X"), - (0x1D00, "V"), - (0x1D2C, "M", "a"), - (0x1D2D, "M", "æ"), - (0x1D2E, "M", "b"), - (0x1D2F, "V"), - (0x1D30, "M", "d"), - (0x1D31, "M", "e"), - (0x1D32, "M", "ǝ"), - (0x1D33, "M", "g"), - (0x1D34, "M", "h"), - (0x1D35, "M", "i"), - (0x1D36, "M", "j"), - (0x1D37, "M", "k"), - (0x1D38, "M", "l"), - (0x1D39, "M", "m"), - (0x1D3A, "M", "n"), - (0x1D3B, "V"), - (0x1D3C, "M", "o"), - (0x1D3D, "M", "ȣ"), - (0x1D3E, "M", "p"), - (0x1D3F, "M", "r"), - (0x1D40, "M", "t"), - (0x1D41, "M", "u"), - (0x1D42, "M", "w"), - (0x1D43, "M", "a"), - (0x1D44, "M", "ɐ"), - (0x1D45, "M", "ɑ"), - (0x1D46, "M", "ᴂ"), - (0x1D47, "M", "b"), - (0x1D48, "M", "d"), - (0x1D49, "M", "e"), - (0x1D4A, "M", "ə"), - (0x1D4B, "M", "ɛ"), - (0x1D4C, "M", "ɜ"), - (0x1D4D, "M", "g"), - (0x1D4E, "V"), - (0x1D4F, "M", "k"), - (0x1D50, "M", "m"), - (0x1D51, "M", "ŋ"), - (0x1D52, "M", "o"), - (0x1D53, "M", "ɔ"), + (0x1C81, 'M', 'д'), + (0x1C82, 'M', 'о'), + (0x1C83, 'M', 'с'), + (0x1C84, 'M', 'т'), + (0x1C86, 'M', 'ъ'), + (0x1C87, 'M', 'ѣ'), + (0x1C88, 'M', 'ꙋ'), + (0x1C89, 'X'), + (0x1C90, 'M', 'ა'), + (0x1C91, 'M', 'ბ'), + (0x1C92, 'M', 'გ'), + (0x1C93, 'M', 'დ'), + (0x1C94, 'M', 'ე'), + (0x1C95, 'M', 'ვ'), + (0x1C96, 'M', 'ზ'), + (0x1C97, 'M', 'თ'), + (0x1C98, 'M', 'ი'), + (0x1C99, 'M', 'კ'), + (0x1C9A, 'M', 'ლ'), + (0x1C9B, 'M', 'მ'), + (0x1C9C, 'M', 'ნ'), + (0x1C9D, 'M', 'ო'), + (0x1C9E, 'M', 'პ'), + (0x1C9F, 'M', 'ჟ'), + (0x1CA0, 'M', 'რ'), + (0x1CA1, 'M', 'ს'), + (0x1CA2, 'M', 'ტ'), + (0x1CA3, 'M', 'უ'), + (0x1CA4, 'M', 'ფ'), + (0x1CA5, 'M', 'ქ'), + (0x1CA6, 'M', 'ღ'), + (0x1CA7, 'M', 'ყ'), + (0x1CA8, 'M', 'შ'), + (0x1CA9, 'M', 'ჩ'), + (0x1CAA, 'M', 'ც'), + (0x1CAB, 'M', 'ძ'), + (0x1CAC, 'M', 'წ'), + (0x1CAD, 'M', 'ჭ'), + (0x1CAE, 'M', 'ხ'), + (0x1CAF, 'M', 'ჯ'), + (0x1CB0, 'M', 'ჰ'), + (0x1CB1, 'M', 'ჱ'), + (0x1CB2, 'M', 'ჲ'), + (0x1CB3, 'M', 'ჳ'), + (0x1CB4, 'M', 'ჴ'), + (0x1CB5, 'M', 'ჵ'), + (0x1CB6, 'M', 'ჶ'), + (0x1CB7, 'M', 'ჷ'), + (0x1CB8, 'M', 'ჸ'), + (0x1CB9, 'M', 'ჹ'), + (0x1CBA, 'M', 'ჺ'), + (0x1CBB, 'X'), + (0x1CBD, 'M', 'ჽ'), + (0x1CBE, 'M', 'ჾ'), + (0x1CBF, 'M', 'ჿ'), + (0x1CC0, 'V'), + (0x1CC8, 'X'), + (0x1CD0, 'V'), + (0x1CFB, 'X'), + (0x1D00, 'V'), + (0x1D2C, 'M', 'a'), + (0x1D2D, 'M', 'æ'), + (0x1D2E, 'M', 'b'), + (0x1D2F, 'V'), + (0x1D30, 'M', 'd'), + (0x1D31, 'M', 'e'), + (0x1D32, 'M', 'ǝ'), + (0x1D33, 'M', 'g'), + (0x1D34, 'M', 'h'), + (0x1D35, 'M', 'i'), + (0x1D36, 'M', 'j'), + (0x1D37, 'M', 'k'), + (0x1D38, 'M', 'l'), + (0x1D39, 'M', 'm'), + (0x1D3A, 'M', 'n'), + (0x1D3B, 'V'), + (0x1D3C, 'M', 'o'), + (0x1D3D, 'M', 'ȣ'), + (0x1D3E, 'M', 'p'), + (0x1D3F, 'M', 'r'), + (0x1D40, 'M', 't'), + (0x1D41, 'M', 'u'), + (0x1D42, 'M', 'w'), + (0x1D43, 'M', 'a'), + (0x1D44, 'M', 'ɐ'), + (0x1D45, 'M', 'ɑ'), + (0x1D46, 'M', 'ᴂ'), + (0x1D47, 'M', 'b'), + (0x1D48, 'M', 'd'), + (0x1D49, 'M', 'e'), + (0x1D4A, 'M', 'ə'), + (0x1D4B, 'M', 'ɛ'), + (0x1D4C, 'M', 'ɜ'), + (0x1D4D, 'M', 'g'), + (0x1D4E, 'V'), + (0x1D4F, 'M', 'k'), + (0x1D50, 'M', 'm'), + (0x1D51, 'M', 'ŋ'), + (0x1D52, 'M', 'o'), + (0x1D53, 'M', 'ɔ'), ] - def _seg_16() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x1D54, "M", "ᴖ"), - (0x1D55, "M", "ᴗ"), - (0x1D56, "M", "p"), - (0x1D57, "M", "t"), - (0x1D58, "M", "u"), - (0x1D59, "M", "ᴝ"), - (0x1D5A, "M", "ɯ"), - (0x1D5B, "M", "v"), - (0x1D5C, "M", "ᴥ"), - (0x1D5D, "M", "β"), - (0x1D5E, "M", "γ"), - (0x1D5F, "M", "δ"), - (0x1D60, "M", "φ"), - (0x1D61, "M", "χ"), - (0x1D62, "M", "i"), - (0x1D63, "M", "r"), - (0x1D64, "M", "u"), - (0x1D65, "M", "v"), - (0x1D66, "M", "β"), - (0x1D67, "M", "γ"), - (0x1D68, "M", "ρ"), - (0x1D69, "M", "φ"), - (0x1D6A, "M", "χ"), - (0x1D6B, "V"), - (0x1D78, "M", "н"), - (0x1D79, "V"), - (0x1D9B, "M", "ɒ"), - (0x1D9C, "M", "c"), - (0x1D9D, "M", "ɕ"), - (0x1D9E, "M", "ð"), - (0x1D9F, "M", "ɜ"), - (0x1DA0, "M", "f"), - (0x1DA1, "M", "ɟ"), - (0x1DA2, "M", "ɡ"), - (0x1DA3, "M", "ɥ"), - (0x1DA4, "M", "ɨ"), - (0x1DA5, "M", "ɩ"), - (0x1DA6, "M", "ɪ"), - (0x1DA7, "M", "ᵻ"), - (0x1DA8, "M", "ʝ"), - (0x1DA9, "M", "ɭ"), - (0x1DAA, "M", "ᶅ"), - (0x1DAB, "M", "ʟ"), - (0x1DAC, "M", "ɱ"), - (0x1DAD, "M", "ɰ"), - (0x1DAE, "M", "ɲ"), - (0x1DAF, "M", "ɳ"), - (0x1DB0, "M", "ɴ"), - (0x1DB1, "M", "ɵ"), - (0x1DB2, "M", "ɸ"), - (0x1DB3, "M", "ʂ"), - (0x1DB4, "M", "ʃ"), - (0x1DB5, "M", "ƫ"), - (0x1DB6, "M", "ʉ"), - (0x1DB7, "M", "ʊ"), - (0x1DB8, "M", "ᴜ"), - (0x1DB9, "M", "ʋ"), - (0x1DBA, "M", "ʌ"), - (0x1DBB, "M", "z"), - (0x1DBC, "M", "ʐ"), - (0x1DBD, "M", "ʑ"), - (0x1DBE, "M", "ʒ"), - (0x1DBF, "M", "θ"), - (0x1DC0, "V"), - (0x1E00, "M", "ḁ"), - (0x1E01, "V"), - (0x1E02, "M", "ḃ"), - (0x1E03, "V"), - (0x1E04, "M", "ḅ"), - (0x1E05, "V"), - (0x1E06, "M", "ḇ"), - (0x1E07, "V"), - (0x1E08, "M", "ḉ"), - (0x1E09, "V"), - (0x1E0A, "M", "ḋ"), - (0x1E0B, "V"), - (0x1E0C, "M", "ḍ"), - (0x1E0D, "V"), - (0x1E0E, "M", "ḏ"), - (0x1E0F, "V"), - (0x1E10, "M", "ḑ"), - (0x1E11, "V"), - (0x1E12, "M", "ḓ"), - (0x1E13, "V"), - (0x1E14, "M", "ḕ"), - (0x1E15, "V"), - (0x1E16, "M", "ḗ"), - (0x1E17, "V"), - (0x1E18, "M", "ḙ"), - (0x1E19, "V"), - (0x1E1A, "M", "ḛ"), - (0x1E1B, "V"), - (0x1E1C, "M", "ḝ"), - (0x1E1D, "V"), - (0x1E1E, "M", "ḟ"), - (0x1E1F, "V"), - (0x1E20, "M", "ḡ"), - (0x1E21, "V"), - (0x1E22, "M", "ḣ"), - (0x1E23, "V"), + (0x1D54, 'M', 'ᴖ'), + (0x1D55, 'M', 'ᴗ'), + (0x1D56, 'M', 'p'), + (0x1D57, 'M', 't'), + (0x1D58, 'M', 'u'), + (0x1D59, 'M', 'ᴝ'), + (0x1D5A, 'M', 'ɯ'), + (0x1D5B, 'M', 'v'), + (0x1D5C, 'M', 'ᴥ'), + (0x1D5D, 'M', 'β'), + (0x1D5E, 'M', 'γ'), + (0x1D5F, 'M', 'δ'), + (0x1D60, 'M', 'φ'), + (0x1D61, 'M', 'χ'), + (0x1D62, 'M', 'i'), + (0x1D63, 'M', 'r'), + (0x1D64, 'M', 'u'), + (0x1D65, 'M', 'v'), + (0x1D66, 'M', 'β'), + (0x1D67, 'M', 'γ'), + (0x1D68, 'M', 'ρ'), + (0x1D69, 'M', 'φ'), + (0x1D6A, 'M', 'χ'), + (0x1D6B, 'V'), + (0x1D78, 'M', 'н'), + (0x1D79, 'V'), + (0x1D9B, 'M', 'ɒ'), + (0x1D9C, 'M', 'c'), + (0x1D9D, 'M', 'ɕ'), + (0x1D9E, 'M', 'ð'), + (0x1D9F, 'M', 'ɜ'), + (0x1DA0, 'M', 'f'), + (0x1DA1, 'M', 'ɟ'), + (0x1DA2, 'M', 'ɡ'), + (0x1DA3, 'M', 'ɥ'), + (0x1DA4, 'M', 'ɨ'), + (0x1DA5, 'M', 'ɩ'), + (0x1DA6, 'M', 'ɪ'), + (0x1DA7, 'M', 'ᵻ'), + (0x1DA8, 'M', 'ʝ'), + (0x1DA9, 'M', 'ɭ'), + (0x1DAA, 'M', 'ᶅ'), + (0x1DAB, 'M', 'ʟ'), + (0x1DAC, 'M', 'ɱ'), + (0x1DAD, 'M', 'ɰ'), + (0x1DAE, 'M', 'ɲ'), + (0x1DAF, 'M', 'ɳ'), + (0x1DB0, 'M', 'ɴ'), + (0x1DB1, 'M', 'ɵ'), + (0x1DB2, 'M', 'ɸ'), + (0x1DB3, 'M', 'ʂ'), + (0x1DB4, 'M', 'ʃ'), + (0x1DB5, 'M', 'ƫ'), + (0x1DB6, 'M', 'ʉ'), + (0x1DB7, 'M', 'ʊ'), + (0x1DB8, 'M', 'ᴜ'), + (0x1DB9, 'M', 'ʋ'), + (0x1DBA, 'M', 'ʌ'), + (0x1DBB, 'M', 'z'), + (0x1DBC, 'M', 'ʐ'), + (0x1DBD, 'M', 'ʑ'), + (0x1DBE, 'M', 'ʒ'), + (0x1DBF, 'M', 'θ'), + (0x1DC0, 'V'), + (0x1E00, 'M', 'ḁ'), + (0x1E01, 'V'), + (0x1E02, 'M', 'ḃ'), + (0x1E03, 'V'), + (0x1E04, 'M', 'ḅ'), + (0x1E05, 'V'), + (0x1E06, 'M', 'ḇ'), + (0x1E07, 'V'), + (0x1E08, 'M', 'ḉ'), + (0x1E09, 'V'), + (0x1E0A, 'M', 'ḋ'), + (0x1E0B, 'V'), + (0x1E0C, 'M', 'ḍ'), + (0x1E0D, 'V'), + (0x1E0E, 'M', 'ḏ'), + (0x1E0F, 'V'), + (0x1E10, 'M', 'ḑ'), + (0x1E11, 'V'), + (0x1E12, 'M', 'ḓ'), + (0x1E13, 'V'), + (0x1E14, 'M', 'ḕ'), + (0x1E15, 'V'), + (0x1E16, 'M', 'ḗ'), + (0x1E17, 'V'), + (0x1E18, 'M', 'ḙ'), + (0x1E19, 'V'), + (0x1E1A, 'M', 'ḛ'), + (0x1E1B, 'V'), + (0x1E1C, 'M', 'ḝ'), + (0x1E1D, 'V'), + (0x1E1E, 'M', 'ḟ'), + (0x1E1F, 'V'), + (0x1E20, 'M', 'ḡ'), + (0x1E21, 'V'), + (0x1E22, 'M', 'ḣ'), + (0x1E23, 'V'), ] - def _seg_17() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x1E24, "M", "ḥ"), - (0x1E25, "V"), - (0x1E26, "M", "ḧ"), - (0x1E27, "V"), - (0x1E28, "M", "ḩ"), - (0x1E29, "V"), - (0x1E2A, "M", "ḫ"), - (0x1E2B, "V"), - (0x1E2C, "M", "ḭ"), - (0x1E2D, "V"), - (0x1E2E, "M", "ḯ"), - (0x1E2F, "V"), - (0x1E30, "M", "ḱ"), - (0x1E31, "V"), - (0x1E32, "M", "ḳ"), - (0x1E33, "V"), - (0x1E34, "M", "ḵ"), - (0x1E35, "V"), - (0x1E36, "M", "ḷ"), - (0x1E37, "V"), - (0x1E38, "M", "ḹ"), - (0x1E39, "V"), - (0x1E3A, "M", "ḻ"), - (0x1E3B, "V"), - (0x1E3C, "M", "ḽ"), - (0x1E3D, "V"), - (0x1E3E, "M", "ḿ"), - (0x1E3F, "V"), - (0x1E40, "M", "ṁ"), - (0x1E41, "V"), - (0x1E42, "M", "ṃ"), - (0x1E43, "V"), - (0x1E44, "M", "ṅ"), - (0x1E45, "V"), - (0x1E46, "M", "ṇ"), - (0x1E47, "V"), - (0x1E48, "M", "ṉ"), - (0x1E49, "V"), - (0x1E4A, "M", "ṋ"), - (0x1E4B, "V"), - (0x1E4C, "M", "ṍ"), - (0x1E4D, "V"), - (0x1E4E, "M", "ṏ"), - (0x1E4F, "V"), - (0x1E50, "M", "ṑ"), - (0x1E51, "V"), - (0x1E52, "M", "ṓ"), - (0x1E53, "V"), - (0x1E54, "M", "ṕ"), - (0x1E55, "V"), - (0x1E56, "M", "ṗ"), - (0x1E57, "V"), - (0x1E58, "M", "ṙ"), - (0x1E59, "V"), - (0x1E5A, "M", "ṛ"), - (0x1E5B, "V"), - (0x1E5C, "M", "ṝ"), - (0x1E5D, "V"), - (0x1E5E, "M", "ṟ"), - (0x1E5F, "V"), - (0x1E60, "M", "ṡ"), - (0x1E61, "V"), - (0x1E62, "M", "ṣ"), - (0x1E63, "V"), - (0x1E64, "M", "ṥ"), - (0x1E65, "V"), - (0x1E66, "M", "ṧ"), - (0x1E67, "V"), - (0x1E68, "M", "ṩ"), - (0x1E69, "V"), - (0x1E6A, "M", "ṫ"), - (0x1E6B, "V"), - (0x1E6C, "M", "ṭ"), - (0x1E6D, "V"), - (0x1E6E, "M", "ṯ"), - (0x1E6F, "V"), - (0x1E70, "M", "ṱ"), - (0x1E71, "V"), - (0x1E72, "M", "ṳ"), - (0x1E73, "V"), - (0x1E74, "M", "ṵ"), - (0x1E75, "V"), - (0x1E76, "M", "ṷ"), - (0x1E77, "V"), - (0x1E78, "M", "ṹ"), - (0x1E79, "V"), - (0x1E7A, "M", "ṻ"), - (0x1E7B, "V"), - (0x1E7C, "M", "ṽ"), - (0x1E7D, "V"), - (0x1E7E, "M", "ṿ"), - (0x1E7F, "V"), - (0x1E80, "M", "ẁ"), - (0x1E81, "V"), - (0x1E82, "M", "ẃ"), - (0x1E83, "V"), - (0x1E84, "M", "ẅ"), - (0x1E85, "V"), - (0x1E86, "M", "ẇ"), - (0x1E87, "V"), + (0x1E24, 'M', 'ḥ'), + (0x1E25, 'V'), + (0x1E26, 'M', 'ḧ'), + (0x1E27, 'V'), + (0x1E28, 'M', 'ḩ'), + (0x1E29, 'V'), + (0x1E2A, 'M', 'ḫ'), + (0x1E2B, 'V'), + (0x1E2C, 'M', 'ḭ'), + (0x1E2D, 'V'), + (0x1E2E, 'M', 'ḯ'), + (0x1E2F, 'V'), + (0x1E30, 'M', 'ḱ'), + (0x1E31, 'V'), + (0x1E32, 'M', 'ḳ'), + (0x1E33, 'V'), + (0x1E34, 'M', 'ḵ'), + (0x1E35, 'V'), + (0x1E36, 'M', 'ḷ'), + (0x1E37, 'V'), + (0x1E38, 'M', 'ḹ'), + (0x1E39, 'V'), + (0x1E3A, 'M', 'ḻ'), + (0x1E3B, 'V'), + (0x1E3C, 'M', 'ḽ'), + (0x1E3D, 'V'), + (0x1E3E, 'M', 'ḿ'), + (0x1E3F, 'V'), + (0x1E40, 'M', 'ṁ'), + (0x1E41, 'V'), + (0x1E42, 'M', 'ṃ'), + (0x1E43, 'V'), + (0x1E44, 'M', 'ṅ'), + (0x1E45, 'V'), + (0x1E46, 'M', 'ṇ'), + (0x1E47, 'V'), + (0x1E48, 'M', 'ṉ'), + (0x1E49, 'V'), + (0x1E4A, 'M', 'ṋ'), + (0x1E4B, 'V'), + (0x1E4C, 'M', 'ṍ'), + (0x1E4D, 'V'), + (0x1E4E, 'M', 'ṏ'), + (0x1E4F, 'V'), + (0x1E50, 'M', 'ṑ'), + (0x1E51, 'V'), + (0x1E52, 'M', 'ṓ'), + (0x1E53, 'V'), + (0x1E54, 'M', 'ṕ'), + (0x1E55, 'V'), + (0x1E56, 'M', 'ṗ'), + (0x1E57, 'V'), + (0x1E58, 'M', 'ṙ'), + (0x1E59, 'V'), + (0x1E5A, 'M', 'ṛ'), + (0x1E5B, 'V'), + (0x1E5C, 'M', 'ṝ'), + (0x1E5D, 'V'), + (0x1E5E, 'M', 'ṟ'), + (0x1E5F, 'V'), + (0x1E60, 'M', 'ṡ'), + (0x1E61, 'V'), + (0x1E62, 'M', 'ṣ'), + (0x1E63, 'V'), + (0x1E64, 'M', 'ṥ'), + (0x1E65, 'V'), + (0x1E66, 'M', 'ṧ'), + (0x1E67, 'V'), + (0x1E68, 'M', 'ṩ'), + (0x1E69, 'V'), + (0x1E6A, 'M', 'ṫ'), + (0x1E6B, 'V'), + (0x1E6C, 'M', 'ṭ'), + (0x1E6D, 'V'), + (0x1E6E, 'M', 'ṯ'), + (0x1E6F, 'V'), + (0x1E70, 'M', 'ṱ'), + (0x1E71, 'V'), + (0x1E72, 'M', 'ṳ'), + (0x1E73, 'V'), + (0x1E74, 'M', 'ṵ'), + (0x1E75, 'V'), + (0x1E76, 'M', 'ṷ'), + (0x1E77, 'V'), + (0x1E78, 'M', 'ṹ'), + (0x1E79, 'V'), + (0x1E7A, 'M', 'ṻ'), + (0x1E7B, 'V'), + (0x1E7C, 'M', 'ṽ'), + (0x1E7D, 'V'), + (0x1E7E, 'M', 'ṿ'), + (0x1E7F, 'V'), + (0x1E80, 'M', 'ẁ'), + (0x1E81, 'V'), + (0x1E82, 'M', 'ẃ'), + (0x1E83, 'V'), + (0x1E84, 'M', 'ẅ'), + (0x1E85, 'V'), + (0x1E86, 'M', 'ẇ'), + (0x1E87, 'V'), ] - def _seg_18() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x1E88, "M", "ẉ"), - (0x1E89, "V"), - (0x1E8A, "M", "ẋ"), - (0x1E8B, "V"), - (0x1E8C, "M", "ẍ"), - (0x1E8D, "V"), - (0x1E8E, "M", "ẏ"), - (0x1E8F, "V"), - (0x1E90, "M", "ẑ"), - (0x1E91, "V"), - (0x1E92, "M", "ẓ"), - (0x1E93, "V"), - (0x1E94, "M", "ẕ"), - (0x1E95, "V"), - (0x1E9A, "M", "aʾ"), - (0x1E9B, "M", "ṡ"), - (0x1E9C, "V"), - (0x1E9E, "M", "ß"), - (0x1E9F, "V"), - (0x1EA0, "M", "ạ"), - (0x1EA1, "V"), - (0x1EA2, "M", "ả"), - (0x1EA3, "V"), - (0x1EA4, "M", "ấ"), - (0x1EA5, "V"), - (0x1EA6, "M", "ầ"), - (0x1EA7, "V"), - (0x1EA8, "M", "ẩ"), - (0x1EA9, "V"), - (0x1EAA, "M", "ẫ"), - (0x1EAB, "V"), - (0x1EAC, "M", "ậ"), - (0x1EAD, "V"), - (0x1EAE, "M", "ắ"), - (0x1EAF, "V"), - (0x1EB0, "M", "ằ"), - (0x1EB1, "V"), - (0x1EB2, "M", "ẳ"), - (0x1EB3, "V"), - (0x1EB4, "M", "ẵ"), - (0x1EB5, "V"), - (0x1EB6, "M", "ặ"), - (0x1EB7, "V"), - (0x1EB8, "M", "ẹ"), - (0x1EB9, "V"), - (0x1EBA, "M", "ẻ"), - (0x1EBB, "V"), - (0x1EBC, "M", "ẽ"), - (0x1EBD, "V"), - (0x1EBE, "M", "ế"), - (0x1EBF, "V"), - (0x1EC0, "M", "ề"), - (0x1EC1, "V"), - (0x1EC2, "M", "ể"), - (0x1EC3, "V"), - (0x1EC4, "M", "ễ"), - (0x1EC5, "V"), - (0x1EC6, "M", "ệ"), - (0x1EC7, "V"), - (0x1EC8, "M", "ỉ"), - (0x1EC9, "V"), - (0x1ECA, "M", "ị"), - (0x1ECB, "V"), - (0x1ECC, "M", "ọ"), - (0x1ECD, "V"), - (0x1ECE, "M", "ỏ"), - (0x1ECF, "V"), - (0x1ED0, "M", "ố"), - (0x1ED1, "V"), - (0x1ED2, "M", "ồ"), - (0x1ED3, "V"), - (0x1ED4, "M", "ổ"), - (0x1ED5, "V"), - (0x1ED6, "M", "ỗ"), - (0x1ED7, "V"), - (0x1ED8, "M", "ộ"), - (0x1ED9, "V"), - (0x1EDA, "M", "ớ"), - (0x1EDB, "V"), - (0x1EDC, "M", "ờ"), - (0x1EDD, "V"), - (0x1EDE, "M", "ở"), - (0x1EDF, "V"), - (0x1EE0, "M", "ỡ"), - (0x1EE1, "V"), - (0x1EE2, "M", "ợ"), - (0x1EE3, "V"), - (0x1EE4, "M", "ụ"), - (0x1EE5, "V"), - (0x1EE6, "M", "ủ"), - (0x1EE7, "V"), - (0x1EE8, "M", "ứ"), - (0x1EE9, "V"), - (0x1EEA, "M", "ừ"), - (0x1EEB, "V"), - (0x1EEC, "M", "ử"), - (0x1EED, "V"), - (0x1EEE, "M", "ữ"), - (0x1EEF, "V"), - (0x1EF0, "M", "ự"), + (0x1E88, 'M', 'ẉ'), + (0x1E89, 'V'), + (0x1E8A, 'M', 'ẋ'), + (0x1E8B, 'V'), + (0x1E8C, 'M', 'ẍ'), + (0x1E8D, 'V'), + (0x1E8E, 'M', 'ẏ'), + (0x1E8F, 'V'), + (0x1E90, 'M', 'ẑ'), + (0x1E91, 'V'), + (0x1E92, 'M', 'ẓ'), + (0x1E93, 'V'), + (0x1E94, 'M', 'ẕ'), + (0x1E95, 'V'), + (0x1E9A, 'M', 'aʾ'), + (0x1E9B, 'M', 'ṡ'), + (0x1E9C, 'V'), + (0x1E9E, 'M', 'ss'), + (0x1E9F, 'V'), + (0x1EA0, 'M', 'ạ'), + (0x1EA1, 'V'), + (0x1EA2, 'M', 'ả'), + (0x1EA3, 'V'), + (0x1EA4, 'M', 'ấ'), + (0x1EA5, 'V'), + (0x1EA6, 'M', 'ầ'), + (0x1EA7, 'V'), + (0x1EA8, 'M', 'ẩ'), + (0x1EA9, 'V'), + (0x1EAA, 'M', 'ẫ'), + (0x1EAB, 'V'), + (0x1EAC, 'M', 'ậ'), + (0x1EAD, 'V'), + (0x1EAE, 'M', 'ắ'), + (0x1EAF, 'V'), + (0x1EB0, 'M', 'ằ'), + (0x1EB1, 'V'), + (0x1EB2, 'M', 'ẳ'), + (0x1EB3, 'V'), + (0x1EB4, 'M', 'ẵ'), + (0x1EB5, 'V'), + (0x1EB6, 'M', 'ặ'), + (0x1EB7, 'V'), + (0x1EB8, 'M', 'ẹ'), + (0x1EB9, 'V'), + (0x1EBA, 'M', 'ẻ'), + (0x1EBB, 'V'), + (0x1EBC, 'M', 'ẽ'), + (0x1EBD, 'V'), + (0x1EBE, 'M', 'ế'), + (0x1EBF, 'V'), + (0x1EC0, 'M', 'ề'), + (0x1EC1, 'V'), + (0x1EC2, 'M', 'ể'), + (0x1EC3, 'V'), + (0x1EC4, 'M', 'ễ'), + (0x1EC5, 'V'), + (0x1EC6, 'M', 'ệ'), + (0x1EC7, 'V'), + (0x1EC8, 'M', 'ỉ'), + (0x1EC9, 'V'), + (0x1ECA, 'M', 'ị'), + (0x1ECB, 'V'), + (0x1ECC, 'M', 'ọ'), + (0x1ECD, 'V'), + (0x1ECE, 'M', 'ỏ'), + (0x1ECF, 'V'), + (0x1ED0, 'M', 'ố'), + (0x1ED1, 'V'), + (0x1ED2, 'M', 'ồ'), + (0x1ED3, 'V'), + (0x1ED4, 'M', 'ổ'), + (0x1ED5, 'V'), + (0x1ED6, 'M', 'ỗ'), + (0x1ED7, 'V'), + (0x1ED8, 'M', 'ộ'), + (0x1ED9, 'V'), + (0x1EDA, 'M', 'ớ'), + (0x1EDB, 'V'), + (0x1EDC, 'M', 'ờ'), + (0x1EDD, 'V'), + (0x1EDE, 'M', 'ở'), + (0x1EDF, 'V'), + (0x1EE0, 'M', 'ỡ'), + (0x1EE1, 'V'), + (0x1EE2, 'M', 'ợ'), + (0x1EE3, 'V'), + (0x1EE4, 'M', 'ụ'), + (0x1EE5, 'V'), + (0x1EE6, 'M', 'ủ'), + (0x1EE7, 'V'), + (0x1EE8, 'M', 'ứ'), + (0x1EE9, 'V'), + (0x1EEA, 'M', 'ừ'), + (0x1EEB, 'V'), + (0x1EEC, 'M', 'ử'), + (0x1EED, 'V'), + (0x1EEE, 'M', 'ữ'), + (0x1EEF, 'V'), + (0x1EF0, 'M', 'ự'), ] - def _seg_19() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x1EF1, "V"), - (0x1EF2, "M", "ỳ"), - (0x1EF3, "V"), - (0x1EF4, "M", "ỵ"), - (0x1EF5, "V"), - (0x1EF6, "M", "ỷ"), - (0x1EF7, "V"), - (0x1EF8, "M", "ỹ"), - (0x1EF9, "V"), - (0x1EFA, "M", "ỻ"), - (0x1EFB, "V"), - (0x1EFC, "M", "ỽ"), - (0x1EFD, "V"), - (0x1EFE, "M", "ỿ"), - (0x1EFF, "V"), - (0x1F08, "M", "ἀ"), - (0x1F09, "M", "ἁ"), - (0x1F0A, "M", "ἂ"), - (0x1F0B, "M", "ἃ"), - (0x1F0C, "M", "ἄ"), - (0x1F0D, "M", "ἅ"), - (0x1F0E, "M", "ἆ"), - (0x1F0F, "M", "ἇ"), - (0x1F10, "V"), - (0x1F16, "X"), - (0x1F18, "M", "ἐ"), - (0x1F19, "M", "ἑ"), - (0x1F1A, "M", "ἒ"), - (0x1F1B, "M", "ἓ"), - (0x1F1C, "M", "ἔ"), - (0x1F1D, "M", "ἕ"), - (0x1F1E, "X"), - (0x1F20, "V"), - (0x1F28, "M", "ἠ"), - (0x1F29, "M", "ἡ"), - (0x1F2A, "M", "ἢ"), - (0x1F2B, "M", "ἣ"), - (0x1F2C, "M", "ἤ"), - (0x1F2D, "M", "ἥ"), - (0x1F2E, "M", "ἦ"), - (0x1F2F, "M", "ἧ"), - (0x1F30, "V"), - (0x1F38, "M", "ἰ"), - (0x1F39, "M", "ἱ"), - (0x1F3A, "M", "ἲ"), - (0x1F3B, "M", "ἳ"), - (0x1F3C, "M", "ἴ"), - (0x1F3D, "M", "ἵ"), - (0x1F3E, "M", "ἶ"), - (0x1F3F, "M", "ἷ"), - (0x1F40, "V"), - (0x1F46, "X"), - (0x1F48, "M", "ὀ"), - (0x1F49, "M", "ὁ"), - (0x1F4A, "M", "ὂ"), - (0x1F4B, "M", "ὃ"), - (0x1F4C, "M", "ὄ"), - (0x1F4D, "M", "ὅ"), - (0x1F4E, "X"), - (0x1F50, "V"), - (0x1F58, "X"), - (0x1F59, "M", "ὑ"), - (0x1F5A, "X"), - (0x1F5B, "M", "ὓ"), - (0x1F5C, "X"), - (0x1F5D, "M", "ὕ"), - (0x1F5E, "X"), - (0x1F5F, "M", "ὗ"), - (0x1F60, "V"), - (0x1F68, "M", "ὠ"), - (0x1F69, "M", "ὡ"), - (0x1F6A, "M", "ὢ"), - (0x1F6B, "M", "ὣ"), - (0x1F6C, "M", "ὤ"), - (0x1F6D, "M", "ὥ"), - (0x1F6E, "M", "ὦ"), - (0x1F6F, "M", "ὧ"), - (0x1F70, "V"), - (0x1F71, "M", "ά"), - (0x1F72, "V"), - (0x1F73, "M", "έ"), - (0x1F74, "V"), - (0x1F75, "M", "ή"), - (0x1F76, "V"), - (0x1F77, "M", "ί"), - (0x1F78, "V"), - (0x1F79, "M", "ό"), - (0x1F7A, "V"), - (0x1F7B, "M", "ύ"), - (0x1F7C, "V"), - (0x1F7D, "M", "ώ"), - (0x1F7E, "X"), - (0x1F80, "M", "ἀι"), - (0x1F81, "M", "ἁι"), - (0x1F82, "M", "ἂι"), - (0x1F83, "M", "ἃι"), - (0x1F84, "M", "ἄι"), - (0x1F85, "M", "ἅι"), - (0x1F86, "M", "ἆι"), - (0x1F87, "M", "ἇι"), + (0x1EF1, 'V'), + (0x1EF2, 'M', 'ỳ'), + (0x1EF3, 'V'), + (0x1EF4, 'M', 'ỵ'), + (0x1EF5, 'V'), + (0x1EF6, 'M', 'ỷ'), + (0x1EF7, 'V'), + (0x1EF8, 'M', 'ỹ'), + (0x1EF9, 'V'), + (0x1EFA, 'M', 'ỻ'), + (0x1EFB, 'V'), + (0x1EFC, 'M', 'ỽ'), + (0x1EFD, 'V'), + (0x1EFE, 'M', 'ỿ'), + (0x1EFF, 'V'), + (0x1F08, 'M', 'ἀ'), + (0x1F09, 'M', 'ἁ'), + (0x1F0A, 'M', 'ἂ'), + (0x1F0B, 'M', 'ἃ'), + (0x1F0C, 'M', 'ἄ'), + (0x1F0D, 'M', 'ἅ'), + (0x1F0E, 'M', 'ἆ'), + (0x1F0F, 'M', 'ἇ'), + (0x1F10, 'V'), + (0x1F16, 'X'), + (0x1F18, 'M', 'ἐ'), + (0x1F19, 'M', 'ἑ'), + (0x1F1A, 'M', 'ἒ'), + (0x1F1B, 'M', 'ἓ'), + (0x1F1C, 'M', 'ἔ'), + (0x1F1D, 'M', 'ἕ'), + (0x1F1E, 'X'), + (0x1F20, 'V'), + (0x1F28, 'M', 'ἠ'), + (0x1F29, 'M', 'ἡ'), + (0x1F2A, 'M', 'ἢ'), + (0x1F2B, 'M', 'ἣ'), + (0x1F2C, 'M', 'ἤ'), + (0x1F2D, 'M', 'ἥ'), + (0x1F2E, 'M', 'ἦ'), + (0x1F2F, 'M', 'ἧ'), + (0x1F30, 'V'), + (0x1F38, 'M', 'ἰ'), + (0x1F39, 'M', 'ἱ'), + (0x1F3A, 'M', 'ἲ'), + (0x1F3B, 'M', 'ἳ'), + (0x1F3C, 'M', 'ἴ'), + (0x1F3D, 'M', 'ἵ'), + (0x1F3E, 'M', 'ἶ'), + (0x1F3F, 'M', 'ἷ'), + (0x1F40, 'V'), + (0x1F46, 'X'), + (0x1F48, 'M', 'ὀ'), + (0x1F49, 'M', 'ὁ'), + (0x1F4A, 'M', 'ὂ'), + (0x1F4B, 'M', 'ὃ'), + (0x1F4C, 'M', 'ὄ'), + (0x1F4D, 'M', 'ὅ'), + (0x1F4E, 'X'), + (0x1F50, 'V'), + (0x1F58, 'X'), + (0x1F59, 'M', 'ὑ'), + (0x1F5A, 'X'), + (0x1F5B, 'M', 'ὓ'), + (0x1F5C, 'X'), + (0x1F5D, 'M', 'ὕ'), + (0x1F5E, 'X'), + (0x1F5F, 'M', 'ὗ'), + (0x1F60, 'V'), + (0x1F68, 'M', 'ὠ'), + (0x1F69, 'M', 'ὡ'), + (0x1F6A, 'M', 'ὢ'), + (0x1F6B, 'M', 'ὣ'), + (0x1F6C, 'M', 'ὤ'), + (0x1F6D, 'M', 'ὥ'), + (0x1F6E, 'M', 'ὦ'), + (0x1F6F, 'M', 'ὧ'), + (0x1F70, 'V'), + (0x1F71, 'M', 'ά'), + (0x1F72, 'V'), + (0x1F73, 'M', 'έ'), + (0x1F74, 'V'), + (0x1F75, 'M', 'ή'), + (0x1F76, 'V'), + (0x1F77, 'M', 'ί'), + (0x1F78, 'V'), + (0x1F79, 'M', 'ό'), + (0x1F7A, 'V'), + (0x1F7B, 'M', 'ύ'), + (0x1F7C, 'V'), + (0x1F7D, 'M', 'ώ'), + (0x1F7E, 'X'), + (0x1F80, 'M', 'ἀι'), + (0x1F81, 'M', 'ἁι'), + (0x1F82, 'M', 'ἂι'), + (0x1F83, 'M', 'ἃι'), + (0x1F84, 'M', 'ἄι'), + (0x1F85, 'M', 'ἅι'), + (0x1F86, 'M', 'ἆι'), + (0x1F87, 'M', 'ἇι'), ] - def _seg_20() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x1F88, "M", "ἀι"), - (0x1F89, "M", "ἁι"), - (0x1F8A, "M", "ἂι"), - (0x1F8B, "M", "ἃι"), - (0x1F8C, "M", "ἄι"), - (0x1F8D, "M", "ἅι"), - (0x1F8E, "M", "ἆι"), - (0x1F8F, "M", "ἇι"), - (0x1F90, "M", "ἠι"), - (0x1F91, "M", "ἡι"), - (0x1F92, "M", "ἢι"), - (0x1F93, "M", "ἣι"), - (0x1F94, "M", "ἤι"), - (0x1F95, "M", "ἥι"), - (0x1F96, "M", "ἦι"), - (0x1F97, "M", "ἧι"), - (0x1F98, "M", "ἠι"), - (0x1F99, "M", "ἡι"), - (0x1F9A, "M", "ἢι"), - (0x1F9B, "M", "ἣι"), - (0x1F9C, "M", "ἤι"), - (0x1F9D, "M", "ἥι"), - (0x1F9E, "M", "ἦι"), - (0x1F9F, "M", "ἧι"), - (0x1FA0, "M", "ὠι"), - (0x1FA1, "M", "ὡι"), - (0x1FA2, "M", "ὢι"), - (0x1FA3, "M", "ὣι"), - (0x1FA4, "M", "ὤι"), - (0x1FA5, "M", "ὥι"), - (0x1FA6, "M", "ὦι"), - (0x1FA7, "M", "ὧι"), - (0x1FA8, "M", "ὠι"), - (0x1FA9, "M", "ὡι"), - (0x1FAA, "M", "ὢι"), - (0x1FAB, "M", "ὣι"), - (0x1FAC, "M", "ὤι"), - (0x1FAD, "M", "ὥι"), - (0x1FAE, "M", "ὦι"), - (0x1FAF, "M", "ὧι"), - (0x1FB0, "V"), - (0x1FB2, "M", "ὰι"), - (0x1FB3, "M", "αι"), - (0x1FB4, "M", "άι"), - (0x1FB5, "X"), - (0x1FB6, "V"), - (0x1FB7, "M", "ᾶι"), - (0x1FB8, "M", "ᾰ"), - (0x1FB9, "M", "ᾱ"), - (0x1FBA, "M", "ὰ"), - (0x1FBB, "M", "ά"), - (0x1FBC, "M", "αι"), - (0x1FBD, "3", " ̓"), - (0x1FBE, "M", "ι"), - (0x1FBF, "3", " ̓"), - (0x1FC0, "3", " ͂"), - (0x1FC1, "3", " ̈͂"), - (0x1FC2, "M", "ὴι"), - (0x1FC3, "M", "ηι"), - (0x1FC4, "M", "ήι"), - (0x1FC5, "X"), - (0x1FC6, "V"), - (0x1FC7, "M", "ῆι"), - (0x1FC8, "M", "ὲ"), - (0x1FC9, "M", "έ"), - (0x1FCA, "M", "ὴ"), - (0x1FCB, "M", "ή"), - (0x1FCC, "M", "ηι"), - (0x1FCD, "3", " ̓̀"), - (0x1FCE, "3", " ̓́"), - (0x1FCF, "3", " ̓͂"), - (0x1FD0, "V"), - (0x1FD3, "M", "ΐ"), - (0x1FD4, "X"), - (0x1FD6, "V"), - (0x1FD8, "M", "ῐ"), - (0x1FD9, "M", "ῑ"), - (0x1FDA, "M", "ὶ"), - (0x1FDB, "M", "ί"), - (0x1FDC, "X"), - (0x1FDD, "3", " ̔̀"), - (0x1FDE, "3", " ̔́"), - (0x1FDF, "3", " ̔͂"), - (0x1FE0, "V"), - (0x1FE3, "M", "ΰ"), - (0x1FE4, "V"), - (0x1FE8, "M", "ῠ"), - (0x1FE9, "M", "ῡ"), - (0x1FEA, "M", "ὺ"), - (0x1FEB, "M", "ύ"), - (0x1FEC, "M", "ῥ"), - (0x1FED, "3", " ̈̀"), - (0x1FEE, "3", " ̈́"), - (0x1FEF, "3", "`"), - (0x1FF0, "X"), - (0x1FF2, "M", "ὼι"), - (0x1FF3, "M", "ωι"), - (0x1FF4, "M", "ώι"), - (0x1FF5, "X"), - (0x1FF6, "V"), + (0x1F88, 'M', 'ἀι'), + (0x1F89, 'M', 'ἁι'), + (0x1F8A, 'M', 'ἂι'), + (0x1F8B, 'M', 'ἃι'), + (0x1F8C, 'M', 'ἄι'), + (0x1F8D, 'M', 'ἅι'), + (0x1F8E, 'M', 'ἆι'), + (0x1F8F, 'M', 'ἇι'), + (0x1F90, 'M', 'ἠι'), + (0x1F91, 'M', 'ἡι'), + (0x1F92, 'M', 'ἢι'), + (0x1F93, 'M', 'ἣι'), + (0x1F94, 'M', 'ἤι'), + (0x1F95, 'M', 'ἥι'), + (0x1F96, 'M', 'ἦι'), + (0x1F97, 'M', 'ἧι'), + (0x1F98, 'M', 'ἠι'), + (0x1F99, 'M', 'ἡι'), + (0x1F9A, 'M', 'ἢι'), + (0x1F9B, 'M', 'ἣι'), + (0x1F9C, 'M', 'ἤι'), + (0x1F9D, 'M', 'ἥι'), + (0x1F9E, 'M', 'ἦι'), + (0x1F9F, 'M', 'ἧι'), + (0x1FA0, 'M', 'ὠι'), + (0x1FA1, 'M', 'ὡι'), + (0x1FA2, 'M', 'ὢι'), + (0x1FA3, 'M', 'ὣι'), + (0x1FA4, 'M', 'ὤι'), + (0x1FA5, 'M', 'ὥι'), + (0x1FA6, 'M', 'ὦι'), + (0x1FA7, 'M', 'ὧι'), + (0x1FA8, 'M', 'ὠι'), + (0x1FA9, 'M', 'ὡι'), + (0x1FAA, 'M', 'ὢι'), + (0x1FAB, 'M', 'ὣι'), + (0x1FAC, 'M', 'ὤι'), + (0x1FAD, 'M', 'ὥι'), + (0x1FAE, 'M', 'ὦι'), + (0x1FAF, 'M', 'ὧι'), + (0x1FB0, 'V'), + (0x1FB2, 'M', 'ὰι'), + (0x1FB3, 'M', 'αι'), + (0x1FB4, 'M', 'άι'), + (0x1FB5, 'X'), + (0x1FB6, 'V'), + (0x1FB7, 'M', 'ᾶι'), + (0x1FB8, 'M', 'ᾰ'), + (0x1FB9, 'M', 'ᾱ'), + (0x1FBA, 'M', 'ὰ'), + (0x1FBB, 'M', 'ά'), + (0x1FBC, 'M', 'αι'), + (0x1FBD, '3', ' ̓'), + (0x1FBE, 'M', 'ι'), + (0x1FBF, '3', ' ̓'), + (0x1FC0, '3', ' ͂'), + (0x1FC1, '3', ' ̈͂'), + (0x1FC2, 'M', 'ὴι'), + (0x1FC3, 'M', 'ηι'), + (0x1FC4, 'M', 'ήι'), + (0x1FC5, 'X'), + (0x1FC6, 'V'), + (0x1FC7, 'M', 'ῆι'), + (0x1FC8, 'M', 'ὲ'), + (0x1FC9, 'M', 'έ'), + (0x1FCA, 'M', 'ὴ'), + (0x1FCB, 'M', 'ή'), + (0x1FCC, 'M', 'ηι'), + (0x1FCD, '3', ' ̓̀'), + (0x1FCE, '3', ' ̓́'), + (0x1FCF, '3', ' ̓͂'), + (0x1FD0, 'V'), + (0x1FD3, 'M', 'ΐ'), + (0x1FD4, 'X'), + (0x1FD6, 'V'), + (0x1FD8, 'M', 'ῐ'), + (0x1FD9, 'M', 'ῑ'), + (0x1FDA, 'M', 'ὶ'), + (0x1FDB, 'M', 'ί'), + (0x1FDC, 'X'), + (0x1FDD, '3', ' ̔̀'), + (0x1FDE, '3', ' ̔́'), + (0x1FDF, '3', ' ̔͂'), + (0x1FE0, 'V'), + (0x1FE3, 'M', 'ΰ'), + (0x1FE4, 'V'), + (0x1FE8, 'M', 'ῠ'), + (0x1FE9, 'M', 'ῡ'), + (0x1FEA, 'M', 'ὺ'), + (0x1FEB, 'M', 'ύ'), + (0x1FEC, 'M', 'ῥ'), + (0x1FED, '3', ' ̈̀'), + (0x1FEE, '3', ' ̈́'), + (0x1FEF, '3', '`'), + (0x1FF0, 'X'), + (0x1FF2, 'M', 'ὼι'), + (0x1FF3, 'M', 'ωι'), + (0x1FF4, 'M', 'ώι'), + (0x1FF5, 'X'), + (0x1FF6, 'V'), ] - def _seg_21() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x1FF7, "M", "ῶι"), - (0x1FF8, "M", "ὸ"), - (0x1FF9, "M", "ό"), - (0x1FFA, "M", "ὼ"), - (0x1FFB, "M", "ώ"), - (0x1FFC, "M", "ωι"), - (0x1FFD, "3", " ́"), - (0x1FFE, "3", " ̔"), - (0x1FFF, "X"), - (0x2000, "3", " "), - (0x200B, "I"), - (0x200C, "D", ""), - (0x200E, "X"), - (0x2010, "V"), - (0x2011, "M", "‐"), - (0x2012, "V"), - (0x2017, "3", " ̳"), - (0x2018, "V"), - (0x2024, "X"), - (0x2027, "V"), - (0x2028, "X"), - (0x202F, "3", " "), - (0x2030, "V"), - (0x2033, "M", "′′"), - (0x2034, "M", "′′′"), - (0x2035, "V"), - (0x2036, "M", "‵‵"), - (0x2037, "M", "‵‵‵"), - (0x2038, "V"), - (0x203C, "3", "!!"), - (0x203D, "V"), - (0x203E, "3", " ̅"), - (0x203F, "V"), - (0x2047, "3", "??"), - (0x2048, "3", "?!"), - (0x2049, "3", "!?"), - (0x204A, "V"), - (0x2057, "M", "′′′′"), - (0x2058, "V"), - (0x205F, "3", " "), - (0x2060, "I"), - (0x2061, "X"), - (0x2064, "I"), - (0x2065, "X"), - (0x2070, "M", "0"), - (0x2071, "M", "i"), - (0x2072, "X"), - (0x2074, "M", "4"), - (0x2075, "M", "5"), - (0x2076, "M", "6"), - (0x2077, "M", "7"), - (0x2078, "M", "8"), - (0x2079, "M", "9"), - (0x207A, "3", "+"), - (0x207B, "M", "−"), - (0x207C, "3", "="), - (0x207D, "3", "("), - (0x207E, "3", ")"), - (0x207F, "M", "n"), - (0x2080, "M", "0"), - (0x2081, "M", "1"), - (0x2082, "M", "2"), - (0x2083, "M", "3"), - (0x2084, "M", "4"), - (0x2085, "M", "5"), - (0x2086, "M", "6"), - (0x2087, "M", "7"), - (0x2088, "M", "8"), - (0x2089, "M", "9"), - (0x208A, "3", "+"), - (0x208B, "M", "−"), - (0x208C, "3", "="), - (0x208D, "3", "("), - (0x208E, "3", ")"), - (0x208F, "X"), - (0x2090, "M", "a"), - (0x2091, "M", "e"), - (0x2092, "M", "o"), - (0x2093, "M", "x"), - (0x2094, "M", "ə"), - (0x2095, "M", "h"), - (0x2096, "M", "k"), - (0x2097, "M", "l"), - (0x2098, "M", "m"), - (0x2099, "M", "n"), - (0x209A, "M", "p"), - (0x209B, "M", "s"), - (0x209C, "M", "t"), - (0x209D, "X"), - (0x20A0, "V"), - (0x20A8, "M", "rs"), - (0x20A9, "V"), - (0x20C1, "X"), - (0x20D0, "V"), - (0x20F1, "X"), - (0x2100, "3", "a/c"), - (0x2101, "3", "a/s"), - (0x2102, "M", "c"), - (0x2103, "M", "°c"), - (0x2104, "V"), + (0x1FF7, 'M', 'ῶι'), + (0x1FF8, 'M', 'ὸ'), + (0x1FF9, 'M', 'ό'), + (0x1FFA, 'M', 'ὼ'), + (0x1FFB, 'M', 'ώ'), + (0x1FFC, 'M', 'ωι'), + (0x1FFD, '3', ' ́'), + (0x1FFE, '3', ' ̔'), + (0x1FFF, 'X'), + (0x2000, '3', ' '), + (0x200B, 'I'), + (0x200C, 'D', ''), + (0x200E, 'X'), + (0x2010, 'V'), + (0x2011, 'M', '‐'), + (0x2012, 'V'), + (0x2017, '3', ' ̳'), + (0x2018, 'V'), + (0x2024, 'X'), + (0x2027, 'V'), + (0x2028, 'X'), + (0x202F, '3', ' '), + (0x2030, 'V'), + (0x2033, 'M', '′′'), + (0x2034, 'M', '′′′'), + (0x2035, 'V'), + (0x2036, 'M', '‵‵'), + (0x2037, 'M', '‵‵‵'), + (0x2038, 'V'), + (0x203C, '3', '!!'), + (0x203D, 'V'), + (0x203E, '3', ' ̅'), + (0x203F, 'V'), + (0x2047, '3', '??'), + (0x2048, '3', '?!'), + (0x2049, '3', '!?'), + (0x204A, 'V'), + (0x2057, 'M', '′′′′'), + (0x2058, 'V'), + (0x205F, '3', ' '), + (0x2060, 'I'), + (0x2061, 'X'), + (0x2064, 'I'), + (0x2065, 'X'), + (0x2070, 'M', '0'), + (0x2071, 'M', 'i'), + (0x2072, 'X'), + (0x2074, 'M', '4'), + (0x2075, 'M', '5'), + (0x2076, 'M', '6'), + (0x2077, 'M', '7'), + (0x2078, 'M', '8'), + (0x2079, 'M', '9'), + (0x207A, '3', '+'), + (0x207B, 'M', '−'), + (0x207C, '3', '='), + (0x207D, '3', '('), + (0x207E, '3', ')'), + (0x207F, 'M', 'n'), + (0x2080, 'M', '0'), + (0x2081, 'M', '1'), + (0x2082, 'M', '2'), + (0x2083, 'M', '3'), + (0x2084, 'M', '4'), + (0x2085, 'M', '5'), + (0x2086, 'M', '6'), + (0x2087, 'M', '7'), + (0x2088, 'M', '8'), + (0x2089, 'M', '9'), + (0x208A, '3', '+'), + (0x208B, 'M', '−'), + (0x208C, '3', '='), + (0x208D, '3', '('), + (0x208E, '3', ')'), + (0x208F, 'X'), + (0x2090, 'M', 'a'), + (0x2091, 'M', 'e'), + (0x2092, 'M', 'o'), + (0x2093, 'M', 'x'), + (0x2094, 'M', 'ə'), + (0x2095, 'M', 'h'), + (0x2096, 'M', 'k'), + (0x2097, 'M', 'l'), + (0x2098, 'M', 'm'), + (0x2099, 'M', 'n'), + (0x209A, 'M', 'p'), + (0x209B, 'M', 's'), + (0x209C, 'M', 't'), + (0x209D, 'X'), + (0x20A0, 'V'), + (0x20A8, 'M', 'rs'), + (0x20A9, 'V'), + (0x20C1, 'X'), + (0x20D0, 'V'), + (0x20F1, 'X'), + (0x2100, '3', 'a/c'), + (0x2101, '3', 'a/s'), + (0x2102, 'M', 'c'), + (0x2103, 'M', '°c'), + (0x2104, 'V'), ] - def _seg_22() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x2105, "3", "c/o"), - (0x2106, "3", "c/u"), - (0x2107, "M", "ɛ"), - (0x2108, "V"), - (0x2109, "M", "°f"), - (0x210A, "M", "g"), - (0x210B, "M", "h"), - (0x210F, "M", "ħ"), - (0x2110, "M", "i"), - (0x2112, "M", "l"), - (0x2114, "V"), - (0x2115, "M", "n"), - (0x2116, "M", "no"), - (0x2117, "V"), - (0x2119, "M", "p"), - (0x211A, "M", "q"), - (0x211B, "M", "r"), - (0x211E, "V"), - (0x2120, "M", "sm"), - (0x2121, "M", "tel"), - (0x2122, "M", "tm"), - (0x2123, "V"), - (0x2124, "M", "z"), - (0x2125, "V"), - (0x2126, "M", "ω"), - (0x2127, "V"), - (0x2128, "M", "z"), - (0x2129, "V"), - (0x212A, "M", "k"), - (0x212B, "M", "å"), - (0x212C, "M", "b"), - (0x212D, "M", "c"), - (0x212E, "V"), - (0x212F, "M", "e"), - (0x2131, "M", "f"), - (0x2132, "X"), - (0x2133, "M", "m"), - (0x2134, "M", "o"), - (0x2135, "M", "א"), - (0x2136, "M", "ב"), - (0x2137, "M", "ג"), - (0x2138, "M", "ד"), - (0x2139, "M", "i"), - (0x213A, "V"), - (0x213B, "M", "fax"), - (0x213C, "M", "π"), - (0x213D, "M", "γ"), - (0x213F, "M", "π"), - (0x2140, "M", "∑"), - (0x2141, "V"), - (0x2145, "M", "d"), - (0x2147, "M", "e"), - (0x2148, "M", "i"), - (0x2149, "M", "j"), - (0x214A, "V"), - (0x2150, "M", "1⁄7"), - (0x2151, "M", "1⁄9"), - (0x2152, "M", "1⁄10"), - (0x2153, "M", "1⁄3"), - (0x2154, "M", "2⁄3"), - (0x2155, "M", "1⁄5"), - (0x2156, "M", "2⁄5"), - (0x2157, "M", "3⁄5"), - (0x2158, "M", "4⁄5"), - (0x2159, "M", "1⁄6"), - (0x215A, "M", "5⁄6"), - (0x215B, "M", "1⁄8"), - (0x215C, "M", "3⁄8"), - (0x215D, "M", "5⁄8"), - (0x215E, "M", "7⁄8"), - (0x215F, "M", "1⁄"), - (0x2160, "M", "i"), - (0x2161, "M", "ii"), - (0x2162, "M", "iii"), - (0x2163, "M", "iv"), - (0x2164, "M", "v"), - (0x2165, "M", "vi"), - (0x2166, "M", "vii"), - (0x2167, "M", "viii"), - (0x2168, "M", "ix"), - (0x2169, "M", "x"), - (0x216A, "M", "xi"), - (0x216B, "M", "xii"), - (0x216C, "M", "l"), - (0x216D, "M", "c"), - (0x216E, "M", "d"), - (0x216F, "M", "m"), - (0x2170, "M", "i"), - (0x2171, "M", "ii"), - (0x2172, "M", "iii"), - (0x2173, "M", "iv"), - (0x2174, "M", "v"), - (0x2175, "M", "vi"), - (0x2176, "M", "vii"), - (0x2177, "M", "viii"), - (0x2178, "M", "ix"), - (0x2179, "M", "x"), - (0x217A, "M", "xi"), - (0x217B, "M", "xii"), - (0x217C, "M", "l"), + (0x2105, '3', 'c/o'), + (0x2106, '3', 'c/u'), + (0x2107, 'M', 'ɛ'), + (0x2108, 'V'), + (0x2109, 'M', '°f'), + (0x210A, 'M', 'g'), + (0x210B, 'M', 'h'), + (0x210F, 'M', 'ħ'), + (0x2110, 'M', 'i'), + (0x2112, 'M', 'l'), + (0x2114, 'V'), + (0x2115, 'M', 'n'), + (0x2116, 'M', 'no'), + (0x2117, 'V'), + (0x2119, 'M', 'p'), + (0x211A, 'M', 'q'), + (0x211B, 'M', 'r'), + (0x211E, 'V'), + (0x2120, 'M', 'sm'), + (0x2121, 'M', 'tel'), + (0x2122, 'M', 'tm'), + (0x2123, 'V'), + (0x2124, 'M', 'z'), + (0x2125, 'V'), + (0x2126, 'M', 'ω'), + (0x2127, 'V'), + (0x2128, 'M', 'z'), + (0x2129, 'V'), + (0x212A, 'M', 'k'), + (0x212B, 'M', 'å'), + (0x212C, 'M', 'b'), + (0x212D, 'M', 'c'), + (0x212E, 'V'), + (0x212F, 'M', 'e'), + (0x2131, 'M', 'f'), + (0x2132, 'X'), + (0x2133, 'M', 'm'), + (0x2134, 'M', 'o'), + (0x2135, 'M', 'א'), + (0x2136, 'M', 'ב'), + (0x2137, 'M', 'ג'), + (0x2138, 'M', 'ד'), + (0x2139, 'M', 'i'), + (0x213A, 'V'), + (0x213B, 'M', 'fax'), + (0x213C, 'M', 'π'), + (0x213D, 'M', 'γ'), + (0x213F, 'M', 'π'), + (0x2140, 'M', '∑'), + (0x2141, 'V'), + (0x2145, 'M', 'd'), + (0x2147, 'M', 'e'), + (0x2148, 'M', 'i'), + (0x2149, 'M', 'j'), + (0x214A, 'V'), + (0x2150, 'M', '1⁄7'), + (0x2151, 'M', '1⁄9'), + (0x2152, 'M', '1⁄10'), + (0x2153, 'M', '1⁄3'), + (0x2154, 'M', '2⁄3'), + (0x2155, 'M', '1⁄5'), + (0x2156, 'M', '2⁄5'), + (0x2157, 'M', '3⁄5'), + (0x2158, 'M', '4⁄5'), + (0x2159, 'M', '1⁄6'), + (0x215A, 'M', '5⁄6'), + (0x215B, 'M', '1⁄8'), + (0x215C, 'M', '3⁄8'), + (0x215D, 'M', '5⁄8'), + (0x215E, 'M', '7⁄8'), + (0x215F, 'M', '1⁄'), + (0x2160, 'M', 'i'), + (0x2161, 'M', 'ii'), + (0x2162, 'M', 'iii'), + (0x2163, 'M', 'iv'), + (0x2164, 'M', 'v'), + (0x2165, 'M', 'vi'), + (0x2166, 'M', 'vii'), + (0x2167, 'M', 'viii'), + (0x2168, 'M', 'ix'), + (0x2169, 'M', 'x'), + (0x216A, 'M', 'xi'), + (0x216B, 'M', 'xii'), + (0x216C, 'M', 'l'), + (0x216D, 'M', 'c'), + (0x216E, 'M', 'd'), + (0x216F, 'M', 'm'), + (0x2170, 'M', 'i'), + (0x2171, 'M', 'ii'), + (0x2172, 'M', 'iii'), + (0x2173, 'M', 'iv'), + (0x2174, 'M', 'v'), + (0x2175, 'M', 'vi'), + (0x2176, 'M', 'vii'), + (0x2177, 'M', 'viii'), + (0x2178, 'M', 'ix'), + (0x2179, 'M', 'x'), + (0x217A, 'M', 'xi'), + (0x217B, 'M', 'xii'), + (0x217C, 'M', 'l'), ] - def _seg_23() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x217D, "M", "c"), - (0x217E, "M", "d"), - (0x217F, "M", "m"), - (0x2180, "V"), - (0x2183, "X"), - (0x2184, "V"), - (0x2189, "M", "0⁄3"), - (0x218A, "V"), - (0x218C, "X"), - (0x2190, "V"), - (0x222C, "M", "∫∫"), - (0x222D, "M", "∫∫∫"), - (0x222E, "V"), - (0x222F, "M", "∮∮"), - (0x2230, "M", "∮∮∮"), - (0x2231, "V"), - (0x2329, "M", "〈"), - (0x232A, "M", "〉"), - (0x232B, "V"), - (0x2427, "X"), - (0x2440, "V"), - (0x244B, "X"), - (0x2460, "M", "1"), - (0x2461, "M", "2"), - (0x2462, "M", "3"), - (0x2463, "M", "4"), - (0x2464, "M", "5"), - (0x2465, "M", "6"), - (0x2466, "M", "7"), - (0x2467, "M", "8"), - (0x2468, "M", "9"), - (0x2469, "M", "10"), - (0x246A, "M", "11"), - (0x246B, "M", "12"), - (0x246C, "M", "13"), - (0x246D, "M", "14"), - (0x246E, "M", "15"), - (0x246F, "M", "16"), - (0x2470, "M", "17"), - (0x2471, "M", "18"), - (0x2472, "M", "19"), - (0x2473, "M", "20"), - (0x2474, "3", "(1)"), - (0x2475, "3", "(2)"), - (0x2476, "3", "(3)"), - (0x2477, "3", "(4)"), - (0x2478, "3", "(5)"), - (0x2479, "3", "(6)"), - (0x247A, "3", "(7)"), - (0x247B, "3", "(8)"), - (0x247C, "3", "(9)"), - (0x247D, "3", "(10)"), - (0x247E, "3", "(11)"), - (0x247F, "3", "(12)"), - (0x2480, "3", "(13)"), - (0x2481, "3", "(14)"), - (0x2482, "3", "(15)"), - (0x2483, "3", "(16)"), - (0x2484, "3", "(17)"), - (0x2485, "3", "(18)"), - (0x2486, "3", "(19)"), - (0x2487, "3", "(20)"), - (0x2488, "X"), - (0x249C, "3", "(a)"), - (0x249D, "3", "(b)"), - (0x249E, "3", "(c)"), - (0x249F, "3", "(d)"), - (0x24A0, "3", "(e)"), - (0x24A1, "3", "(f)"), - (0x24A2, "3", "(g)"), - (0x24A3, "3", "(h)"), - (0x24A4, "3", "(i)"), - (0x24A5, "3", "(j)"), - (0x24A6, "3", "(k)"), - (0x24A7, "3", "(l)"), - (0x24A8, "3", "(m)"), - (0x24A9, "3", "(n)"), - (0x24AA, "3", "(o)"), - (0x24AB, "3", "(p)"), - (0x24AC, "3", "(q)"), - (0x24AD, "3", "(r)"), - (0x24AE, "3", "(s)"), - (0x24AF, "3", "(t)"), - (0x24B0, "3", "(u)"), - (0x24B1, "3", "(v)"), - (0x24B2, "3", "(w)"), - (0x24B3, "3", "(x)"), - (0x24B4, "3", "(y)"), - (0x24B5, "3", "(z)"), - (0x24B6, "M", "a"), - (0x24B7, "M", "b"), - (0x24B8, "M", "c"), - (0x24B9, "M", "d"), - (0x24BA, "M", "e"), - (0x24BB, "M", "f"), - (0x24BC, "M", "g"), - (0x24BD, "M", "h"), - (0x24BE, "M", "i"), - (0x24BF, "M", "j"), - (0x24C0, "M", "k"), + (0x217D, 'M', 'c'), + (0x217E, 'M', 'd'), + (0x217F, 'M', 'm'), + (0x2180, 'V'), + (0x2183, 'X'), + (0x2184, 'V'), + (0x2189, 'M', '0⁄3'), + (0x218A, 'V'), + (0x218C, 'X'), + (0x2190, 'V'), + (0x222C, 'M', '∫∫'), + (0x222D, 'M', '∫∫∫'), + (0x222E, 'V'), + (0x222F, 'M', '∮∮'), + (0x2230, 'M', '∮∮∮'), + (0x2231, 'V'), + (0x2260, '3'), + (0x2261, 'V'), + (0x226E, '3'), + (0x2270, 'V'), + (0x2329, 'M', '〈'), + (0x232A, 'M', '〉'), + (0x232B, 'V'), + (0x2427, 'X'), + (0x2440, 'V'), + (0x244B, 'X'), + (0x2460, 'M', '1'), + (0x2461, 'M', '2'), + (0x2462, 'M', '3'), + (0x2463, 'M', '4'), + (0x2464, 'M', '5'), + (0x2465, 'M', '6'), + (0x2466, 'M', '7'), + (0x2467, 'M', '8'), + (0x2468, 'M', '9'), + (0x2469, 'M', '10'), + (0x246A, 'M', '11'), + (0x246B, 'M', '12'), + (0x246C, 'M', '13'), + (0x246D, 'M', '14'), + (0x246E, 'M', '15'), + (0x246F, 'M', '16'), + (0x2470, 'M', '17'), + (0x2471, 'M', '18'), + (0x2472, 'M', '19'), + (0x2473, 'M', '20'), + (0x2474, '3', '(1)'), + (0x2475, '3', '(2)'), + (0x2476, '3', '(3)'), + (0x2477, '3', '(4)'), + (0x2478, '3', '(5)'), + (0x2479, '3', '(6)'), + (0x247A, '3', '(7)'), + (0x247B, '3', '(8)'), + (0x247C, '3', '(9)'), + (0x247D, '3', '(10)'), + (0x247E, '3', '(11)'), + (0x247F, '3', '(12)'), + (0x2480, '3', '(13)'), + (0x2481, '3', '(14)'), + (0x2482, '3', '(15)'), + (0x2483, '3', '(16)'), + (0x2484, '3', '(17)'), + (0x2485, '3', '(18)'), + (0x2486, '3', '(19)'), + (0x2487, '3', '(20)'), + (0x2488, 'X'), + (0x249C, '3', '(a)'), + (0x249D, '3', '(b)'), + (0x249E, '3', '(c)'), + (0x249F, '3', '(d)'), + (0x24A0, '3', '(e)'), + (0x24A1, '3', '(f)'), + (0x24A2, '3', '(g)'), + (0x24A3, '3', '(h)'), + (0x24A4, '3', '(i)'), + (0x24A5, '3', '(j)'), + (0x24A6, '3', '(k)'), + (0x24A7, '3', '(l)'), + (0x24A8, '3', '(m)'), + (0x24A9, '3', '(n)'), + (0x24AA, '3', '(o)'), + (0x24AB, '3', '(p)'), + (0x24AC, '3', '(q)'), + (0x24AD, '3', '(r)'), + (0x24AE, '3', '(s)'), + (0x24AF, '3', '(t)'), + (0x24B0, '3', '(u)'), + (0x24B1, '3', '(v)'), + (0x24B2, '3', '(w)'), + (0x24B3, '3', '(x)'), + (0x24B4, '3', '(y)'), + (0x24B5, '3', '(z)'), + (0x24B6, 'M', 'a'), + (0x24B7, 'M', 'b'), + (0x24B8, 'M', 'c'), + (0x24B9, 'M', 'd'), + (0x24BA, 'M', 'e'), + (0x24BB, 'M', 'f'), + (0x24BC, 'M', 'g'), ] - def _seg_24() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x24C1, "M", "l"), - (0x24C2, "M", "m"), - (0x24C3, "M", "n"), - (0x24C4, "M", "o"), - (0x24C5, "M", "p"), - (0x24C6, "M", "q"), - (0x24C7, "M", "r"), - (0x24C8, "M", "s"), - (0x24C9, "M", "t"), - (0x24CA, "M", "u"), - (0x24CB, "M", "v"), - (0x24CC, "M", "w"), - (0x24CD, "M", "x"), - (0x24CE, "M", "y"), - (0x24CF, "M", "z"), - (0x24D0, "M", "a"), - (0x24D1, "M", "b"), - (0x24D2, "M", "c"), - (0x24D3, "M", "d"), - (0x24D4, "M", "e"), - (0x24D5, "M", "f"), - (0x24D6, "M", "g"), - (0x24D7, "M", "h"), - (0x24D8, "M", "i"), - (0x24D9, "M", "j"), - (0x24DA, "M", "k"), - (0x24DB, "M", "l"), - (0x24DC, "M", "m"), - (0x24DD, "M", "n"), - (0x24DE, "M", "o"), - (0x24DF, "M", "p"), - (0x24E0, "M", "q"), - (0x24E1, "M", "r"), - (0x24E2, "M", "s"), - (0x24E3, "M", "t"), - (0x24E4, "M", "u"), - (0x24E5, "M", "v"), - (0x24E6, "M", "w"), - (0x24E7, "M", "x"), - (0x24E8, "M", "y"), - (0x24E9, "M", "z"), - (0x24EA, "M", "0"), - (0x24EB, "V"), - (0x2A0C, "M", "∫∫∫∫"), - (0x2A0D, "V"), - (0x2A74, "3", "::="), - (0x2A75, "3", "=="), - (0x2A76, "3", "==="), - (0x2A77, "V"), - (0x2ADC, "M", "⫝̸"), - (0x2ADD, "V"), - (0x2B74, "X"), - (0x2B76, "V"), - (0x2B96, "X"), - (0x2B97, "V"), - (0x2C00, "M", "ⰰ"), - (0x2C01, "M", "ⰱ"), - (0x2C02, "M", "ⰲ"), - (0x2C03, "M", "ⰳ"), - (0x2C04, "M", "ⰴ"), - (0x2C05, "M", "ⰵ"), - (0x2C06, "M", "ⰶ"), - (0x2C07, "M", "ⰷ"), - (0x2C08, "M", "ⰸ"), - (0x2C09, "M", "ⰹ"), - (0x2C0A, "M", "ⰺ"), - (0x2C0B, "M", "ⰻ"), - (0x2C0C, "M", "ⰼ"), - (0x2C0D, "M", "ⰽ"), - (0x2C0E, "M", "ⰾ"), - (0x2C0F, "M", "ⰿ"), - (0x2C10, "M", "ⱀ"), - (0x2C11, "M", "ⱁ"), - (0x2C12, "M", "ⱂ"), - (0x2C13, "M", "ⱃ"), - (0x2C14, "M", "ⱄ"), - (0x2C15, "M", "ⱅ"), - (0x2C16, "M", "ⱆ"), - (0x2C17, "M", "ⱇ"), - (0x2C18, "M", "ⱈ"), - (0x2C19, "M", "ⱉ"), - (0x2C1A, "M", "ⱊ"), - (0x2C1B, "M", "ⱋ"), - (0x2C1C, "M", "ⱌ"), - (0x2C1D, "M", "ⱍ"), - (0x2C1E, "M", "ⱎ"), - (0x2C1F, "M", "ⱏ"), - (0x2C20, "M", "ⱐ"), - (0x2C21, "M", "ⱑ"), - (0x2C22, "M", "ⱒ"), - (0x2C23, "M", "ⱓ"), - (0x2C24, "M", "ⱔ"), - (0x2C25, "M", "ⱕ"), - (0x2C26, "M", "ⱖ"), - (0x2C27, "M", "ⱗ"), - (0x2C28, "M", "ⱘ"), - (0x2C29, "M", "ⱙ"), - (0x2C2A, "M", "ⱚ"), - (0x2C2B, "M", "ⱛ"), - (0x2C2C, "M", "ⱜ"), + (0x24BD, 'M', 'h'), + (0x24BE, 'M', 'i'), + (0x24BF, 'M', 'j'), + (0x24C0, 'M', 'k'), + (0x24C1, 'M', 'l'), + (0x24C2, 'M', 'm'), + (0x24C3, 'M', 'n'), + (0x24C4, 'M', 'o'), + (0x24C5, 'M', 'p'), + (0x24C6, 'M', 'q'), + (0x24C7, 'M', 'r'), + (0x24C8, 'M', 's'), + (0x24C9, 'M', 't'), + (0x24CA, 'M', 'u'), + (0x24CB, 'M', 'v'), + (0x24CC, 'M', 'w'), + (0x24CD, 'M', 'x'), + (0x24CE, 'M', 'y'), + (0x24CF, 'M', 'z'), + (0x24D0, 'M', 'a'), + (0x24D1, 'M', 'b'), + (0x24D2, 'M', 'c'), + (0x24D3, 'M', 'd'), + (0x24D4, 'M', 'e'), + (0x24D5, 'M', 'f'), + (0x24D6, 'M', 'g'), + (0x24D7, 'M', 'h'), + (0x24D8, 'M', 'i'), + (0x24D9, 'M', 'j'), + (0x24DA, 'M', 'k'), + (0x24DB, 'M', 'l'), + (0x24DC, 'M', 'm'), + (0x24DD, 'M', 'n'), + (0x24DE, 'M', 'o'), + (0x24DF, 'M', 'p'), + (0x24E0, 'M', 'q'), + (0x24E1, 'M', 'r'), + (0x24E2, 'M', 's'), + (0x24E3, 'M', 't'), + (0x24E4, 'M', 'u'), + (0x24E5, 'M', 'v'), + (0x24E6, 'M', 'w'), + (0x24E7, 'M', 'x'), + (0x24E8, 'M', 'y'), + (0x24E9, 'M', 'z'), + (0x24EA, 'M', '0'), + (0x24EB, 'V'), + (0x2A0C, 'M', '∫∫∫∫'), + (0x2A0D, 'V'), + (0x2A74, '3', '::='), + (0x2A75, '3', '=='), + (0x2A76, '3', '==='), + (0x2A77, 'V'), + (0x2ADC, 'M', '⫝̸'), + (0x2ADD, 'V'), + (0x2B74, 'X'), + (0x2B76, 'V'), + (0x2B96, 'X'), + (0x2B97, 'V'), + (0x2C00, 'M', 'ⰰ'), + (0x2C01, 'M', 'ⰱ'), + (0x2C02, 'M', 'ⰲ'), + (0x2C03, 'M', 'ⰳ'), + (0x2C04, 'M', 'ⰴ'), + (0x2C05, 'M', 'ⰵ'), + (0x2C06, 'M', 'ⰶ'), + (0x2C07, 'M', 'ⰷ'), + (0x2C08, 'M', 'ⰸ'), + (0x2C09, 'M', 'ⰹ'), + (0x2C0A, 'M', 'ⰺ'), + (0x2C0B, 'M', 'ⰻ'), + (0x2C0C, 'M', 'ⰼ'), + (0x2C0D, 'M', 'ⰽ'), + (0x2C0E, 'M', 'ⰾ'), + (0x2C0F, 'M', 'ⰿ'), + (0x2C10, 'M', 'ⱀ'), + (0x2C11, 'M', 'ⱁ'), + (0x2C12, 'M', 'ⱂ'), + (0x2C13, 'M', 'ⱃ'), + (0x2C14, 'M', 'ⱄ'), + (0x2C15, 'M', 'ⱅ'), + (0x2C16, 'M', 'ⱆ'), + (0x2C17, 'M', 'ⱇ'), + (0x2C18, 'M', 'ⱈ'), + (0x2C19, 'M', 'ⱉ'), + (0x2C1A, 'M', 'ⱊ'), + (0x2C1B, 'M', 'ⱋ'), + (0x2C1C, 'M', 'ⱌ'), + (0x2C1D, 'M', 'ⱍ'), + (0x2C1E, 'M', 'ⱎ'), + (0x2C1F, 'M', 'ⱏ'), + (0x2C20, 'M', 'ⱐ'), + (0x2C21, 'M', 'ⱑ'), + (0x2C22, 'M', 'ⱒ'), + (0x2C23, 'M', 'ⱓ'), + (0x2C24, 'M', 'ⱔ'), + (0x2C25, 'M', 'ⱕ'), + (0x2C26, 'M', 'ⱖ'), + (0x2C27, 'M', 'ⱗ'), + (0x2C28, 'M', 'ⱘ'), ] - def _seg_25() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x2C2D, "M", "ⱝ"), - (0x2C2E, "M", "ⱞ"), - (0x2C2F, "M", "ⱟ"), - (0x2C30, "V"), - (0x2C60, "M", "ⱡ"), - (0x2C61, "V"), - (0x2C62, "M", "ɫ"), - (0x2C63, "M", "ᵽ"), - (0x2C64, "M", "ɽ"), - (0x2C65, "V"), - (0x2C67, "M", "ⱨ"), - (0x2C68, "V"), - (0x2C69, "M", "ⱪ"), - (0x2C6A, "V"), - (0x2C6B, "M", "ⱬ"), - (0x2C6C, "V"), - (0x2C6D, "M", "ɑ"), - (0x2C6E, "M", "ɱ"), - (0x2C6F, "M", "ɐ"), - (0x2C70, "M", "ɒ"), - (0x2C71, "V"), - (0x2C72, "M", "ⱳ"), - (0x2C73, "V"), - (0x2C75, "M", "ⱶ"), - (0x2C76, "V"), - (0x2C7C, "M", "j"), - (0x2C7D, "M", "v"), - (0x2C7E, "M", "ȿ"), - (0x2C7F, "M", "ɀ"), - (0x2C80, "M", "ⲁ"), - (0x2C81, "V"), - (0x2C82, "M", "ⲃ"), - (0x2C83, "V"), - (0x2C84, "M", "ⲅ"), - (0x2C85, "V"), - (0x2C86, "M", "ⲇ"), - (0x2C87, "V"), - (0x2C88, "M", "ⲉ"), - (0x2C89, "V"), - (0x2C8A, "M", "ⲋ"), - (0x2C8B, "V"), - (0x2C8C, "M", "ⲍ"), - (0x2C8D, "V"), - (0x2C8E, "M", "ⲏ"), - (0x2C8F, "V"), - (0x2C90, "M", "ⲑ"), - (0x2C91, "V"), - (0x2C92, "M", "ⲓ"), - (0x2C93, "V"), - (0x2C94, "M", "ⲕ"), - (0x2C95, "V"), - (0x2C96, "M", "ⲗ"), - (0x2C97, "V"), - (0x2C98, "M", "ⲙ"), - (0x2C99, "V"), - (0x2C9A, "M", "ⲛ"), - (0x2C9B, "V"), - (0x2C9C, "M", "ⲝ"), - (0x2C9D, "V"), - (0x2C9E, "M", "ⲟ"), - (0x2C9F, "V"), - (0x2CA0, "M", "ⲡ"), - (0x2CA1, "V"), - (0x2CA2, "M", "ⲣ"), - (0x2CA3, "V"), - (0x2CA4, "M", "ⲥ"), - (0x2CA5, "V"), - (0x2CA6, "M", "ⲧ"), - (0x2CA7, "V"), - (0x2CA8, "M", "ⲩ"), - (0x2CA9, "V"), - (0x2CAA, "M", "ⲫ"), - (0x2CAB, "V"), - (0x2CAC, "M", "ⲭ"), - (0x2CAD, "V"), - (0x2CAE, "M", "ⲯ"), - (0x2CAF, "V"), - (0x2CB0, "M", "ⲱ"), - (0x2CB1, "V"), - (0x2CB2, "M", "ⲳ"), - (0x2CB3, "V"), - (0x2CB4, "M", "ⲵ"), - (0x2CB5, "V"), - (0x2CB6, "M", "ⲷ"), - (0x2CB7, "V"), - (0x2CB8, "M", "ⲹ"), - (0x2CB9, "V"), - (0x2CBA, "M", "ⲻ"), - (0x2CBB, "V"), - (0x2CBC, "M", "ⲽ"), - (0x2CBD, "V"), - (0x2CBE, "M", "ⲿ"), - (0x2CBF, "V"), - (0x2CC0, "M", "ⳁ"), - (0x2CC1, "V"), - (0x2CC2, "M", "ⳃ"), - (0x2CC3, "V"), - (0x2CC4, "M", "ⳅ"), - (0x2CC5, "V"), - (0x2CC6, "M", "ⳇ"), + (0x2C29, 'M', 'ⱙ'), + (0x2C2A, 'M', 'ⱚ'), + (0x2C2B, 'M', 'ⱛ'), + (0x2C2C, 'M', 'ⱜ'), + (0x2C2D, 'M', 'ⱝ'), + (0x2C2E, 'M', 'ⱞ'), + (0x2C2F, 'M', 'ⱟ'), + (0x2C30, 'V'), + (0x2C60, 'M', 'ⱡ'), + (0x2C61, 'V'), + (0x2C62, 'M', 'ɫ'), + (0x2C63, 'M', 'ᵽ'), + (0x2C64, 'M', 'ɽ'), + (0x2C65, 'V'), + (0x2C67, 'M', 'ⱨ'), + (0x2C68, 'V'), + (0x2C69, 'M', 'ⱪ'), + (0x2C6A, 'V'), + (0x2C6B, 'M', 'ⱬ'), + (0x2C6C, 'V'), + (0x2C6D, 'M', 'ɑ'), + (0x2C6E, 'M', 'ɱ'), + (0x2C6F, 'M', 'ɐ'), + (0x2C70, 'M', 'ɒ'), + (0x2C71, 'V'), + (0x2C72, 'M', 'ⱳ'), + (0x2C73, 'V'), + (0x2C75, 'M', 'ⱶ'), + (0x2C76, 'V'), + (0x2C7C, 'M', 'j'), + (0x2C7D, 'M', 'v'), + (0x2C7E, 'M', 'ȿ'), + (0x2C7F, 'M', 'ɀ'), + (0x2C80, 'M', 'ⲁ'), + (0x2C81, 'V'), + (0x2C82, 'M', 'ⲃ'), + (0x2C83, 'V'), + (0x2C84, 'M', 'ⲅ'), + (0x2C85, 'V'), + (0x2C86, 'M', 'ⲇ'), + (0x2C87, 'V'), + (0x2C88, 'M', 'ⲉ'), + (0x2C89, 'V'), + (0x2C8A, 'M', 'ⲋ'), + (0x2C8B, 'V'), + (0x2C8C, 'M', 'ⲍ'), + (0x2C8D, 'V'), + (0x2C8E, 'M', 'ⲏ'), + (0x2C8F, 'V'), + (0x2C90, 'M', 'ⲑ'), + (0x2C91, 'V'), + (0x2C92, 'M', 'ⲓ'), + (0x2C93, 'V'), + (0x2C94, 'M', 'ⲕ'), + (0x2C95, 'V'), + (0x2C96, 'M', 'ⲗ'), + (0x2C97, 'V'), + (0x2C98, 'M', 'ⲙ'), + (0x2C99, 'V'), + (0x2C9A, 'M', 'ⲛ'), + (0x2C9B, 'V'), + (0x2C9C, 'M', 'ⲝ'), + (0x2C9D, 'V'), + (0x2C9E, 'M', 'ⲟ'), + (0x2C9F, 'V'), + (0x2CA0, 'M', 'ⲡ'), + (0x2CA1, 'V'), + (0x2CA2, 'M', 'ⲣ'), + (0x2CA3, 'V'), + (0x2CA4, 'M', 'ⲥ'), + (0x2CA5, 'V'), + (0x2CA6, 'M', 'ⲧ'), + (0x2CA7, 'V'), + (0x2CA8, 'M', 'ⲩ'), + (0x2CA9, 'V'), + (0x2CAA, 'M', 'ⲫ'), + (0x2CAB, 'V'), + (0x2CAC, 'M', 'ⲭ'), + (0x2CAD, 'V'), + (0x2CAE, 'M', 'ⲯ'), + (0x2CAF, 'V'), + (0x2CB0, 'M', 'ⲱ'), + (0x2CB1, 'V'), + (0x2CB2, 'M', 'ⲳ'), + (0x2CB3, 'V'), + (0x2CB4, 'M', 'ⲵ'), + (0x2CB5, 'V'), + (0x2CB6, 'M', 'ⲷ'), + (0x2CB7, 'V'), + (0x2CB8, 'M', 'ⲹ'), + (0x2CB9, 'V'), + (0x2CBA, 'M', 'ⲻ'), + (0x2CBB, 'V'), + (0x2CBC, 'M', 'ⲽ'), + (0x2CBD, 'V'), + (0x2CBE, 'M', 'ⲿ'), + (0x2CBF, 'V'), + (0x2CC0, 'M', 'ⳁ'), + (0x2CC1, 'V'), + (0x2CC2, 'M', 'ⳃ'), ] - def _seg_26() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x2CC7, "V"), - (0x2CC8, "M", "ⳉ"), - (0x2CC9, "V"), - (0x2CCA, "M", "ⳋ"), - (0x2CCB, "V"), - (0x2CCC, "M", "ⳍ"), - (0x2CCD, "V"), - (0x2CCE, "M", "ⳏ"), - (0x2CCF, "V"), - (0x2CD0, "M", "ⳑ"), - (0x2CD1, "V"), - (0x2CD2, "M", "ⳓ"), - (0x2CD3, "V"), - (0x2CD4, "M", "ⳕ"), - (0x2CD5, "V"), - (0x2CD6, "M", "ⳗ"), - (0x2CD7, "V"), - (0x2CD8, "M", "ⳙ"), - (0x2CD9, "V"), - (0x2CDA, "M", "ⳛ"), - (0x2CDB, "V"), - (0x2CDC, "M", "ⳝ"), - (0x2CDD, "V"), - (0x2CDE, "M", "ⳟ"), - (0x2CDF, "V"), - (0x2CE0, "M", "ⳡ"), - (0x2CE1, "V"), - (0x2CE2, "M", "ⳣ"), - (0x2CE3, "V"), - (0x2CEB, "M", "ⳬ"), - (0x2CEC, "V"), - (0x2CED, "M", "ⳮ"), - (0x2CEE, "V"), - (0x2CF2, "M", "ⳳ"), - (0x2CF3, "V"), - (0x2CF4, "X"), - (0x2CF9, "V"), - (0x2D26, "X"), - (0x2D27, "V"), - (0x2D28, "X"), - (0x2D2D, "V"), - (0x2D2E, "X"), - (0x2D30, "V"), - (0x2D68, "X"), - (0x2D6F, "M", "ⵡ"), - (0x2D70, "V"), - (0x2D71, "X"), - (0x2D7F, "V"), - (0x2D97, "X"), - (0x2DA0, "V"), - (0x2DA7, "X"), - (0x2DA8, "V"), - (0x2DAF, "X"), - (0x2DB0, "V"), - (0x2DB7, "X"), - (0x2DB8, "V"), - (0x2DBF, "X"), - (0x2DC0, "V"), - (0x2DC7, "X"), - (0x2DC8, "V"), - (0x2DCF, "X"), - (0x2DD0, "V"), - (0x2DD7, "X"), - (0x2DD8, "V"), - (0x2DDF, "X"), - (0x2DE0, "V"), - (0x2E5E, "X"), - (0x2E80, "V"), - (0x2E9A, "X"), - (0x2E9B, "V"), - (0x2E9F, "M", "母"), - (0x2EA0, "V"), - (0x2EF3, "M", "龟"), - (0x2EF4, "X"), - (0x2F00, "M", "一"), - (0x2F01, "M", "丨"), - (0x2F02, "M", "丶"), - (0x2F03, "M", "丿"), - (0x2F04, "M", "乙"), - (0x2F05, "M", "亅"), - (0x2F06, "M", "二"), - (0x2F07, "M", "亠"), - (0x2F08, "M", "人"), - (0x2F09, "M", "儿"), - (0x2F0A, "M", "入"), - (0x2F0B, "M", "八"), - (0x2F0C, "M", "冂"), - (0x2F0D, "M", "冖"), - (0x2F0E, "M", "冫"), - (0x2F0F, "M", "几"), - (0x2F10, "M", "凵"), - (0x2F11, "M", "刀"), - (0x2F12, "M", "力"), - (0x2F13, "M", "勹"), - (0x2F14, "M", "匕"), - (0x2F15, "M", "匚"), - (0x2F16, "M", "匸"), - (0x2F17, "M", "十"), - (0x2F18, "M", "卜"), - (0x2F19, "M", "卩"), + (0x2CC3, 'V'), + (0x2CC4, 'M', 'ⳅ'), + (0x2CC5, 'V'), + (0x2CC6, 'M', 'ⳇ'), + (0x2CC7, 'V'), + (0x2CC8, 'M', 'ⳉ'), + (0x2CC9, 'V'), + (0x2CCA, 'M', 'ⳋ'), + (0x2CCB, 'V'), + (0x2CCC, 'M', 'ⳍ'), + (0x2CCD, 'V'), + (0x2CCE, 'M', 'ⳏ'), + (0x2CCF, 'V'), + (0x2CD0, 'M', 'ⳑ'), + (0x2CD1, 'V'), + (0x2CD2, 'M', 'ⳓ'), + (0x2CD3, 'V'), + (0x2CD4, 'M', 'ⳕ'), + (0x2CD5, 'V'), + (0x2CD6, 'M', 'ⳗ'), + (0x2CD7, 'V'), + (0x2CD8, 'M', 'ⳙ'), + (0x2CD9, 'V'), + (0x2CDA, 'M', 'ⳛ'), + (0x2CDB, 'V'), + (0x2CDC, 'M', 'ⳝ'), + (0x2CDD, 'V'), + (0x2CDE, 'M', 'ⳟ'), + (0x2CDF, 'V'), + (0x2CE0, 'M', 'ⳡ'), + (0x2CE1, 'V'), + (0x2CE2, 'M', 'ⳣ'), + (0x2CE3, 'V'), + (0x2CEB, 'M', 'ⳬ'), + (0x2CEC, 'V'), + (0x2CED, 'M', 'ⳮ'), + (0x2CEE, 'V'), + (0x2CF2, 'M', 'ⳳ'), + (0x2CF3, 'V'), + (0x2CF4, 'X'), + (0x2CF9, 'V'), + (0x2D26, 'X'), + (0x2D27, 'V'), + (0x2D28, 'X'), + (0x2D2D, 'V'), + (0x2D2E, 'X'), + (0x2D30, 'V'), + (0x2D68, 'X'), + (0x2D6F, 'M', 'ⵡ'), + (0x2D70, 'V'), + (0x2D71, 'X'), + (0x2D7F, 'V'), + (0x2D97, 'X'), + (0x2DA0, 'V'), + (0x2DA7, 'X'), + (0x2DA8, 'V'), + (0x2DAF, 'X'), + (0x2DB0, 'V'), + (0x2DB7, 'X'), + (0x2DB8, 'V'), + (0x2DBF, 'X'), + (0x2DC0, 'V'), + (0x2DC7, 'X'), + (0x2DC8, 'V'), + (0x2DCF, 'X'), + (0x2DD0, 'V'), + (0x2DD7, 'X'), + (0x2DD8, 'V'), + (0x2DDF, 'X'), + (0x2DE0, 'V'), + (0x2E5E, 'X'), + (0x2E80, 'V'), + (0x2E9A, 'X'), + (0x2E9B, 'V'), + (0x2E9F, 'M', '母'), + (0x2EA0, 'V'), + (0x2EF3, 'M', '龟'), + (0x2EF4, 'X'), + (0x2F00, 'M', '一'), + (0x2F01, 'M', '丨'), + (0x2F02, 'M', '丶'), + (0x2F03, 'M', '丿'), + (0x2F04, 'M', '乙'), + (0x2F05, 'M', '亅'), + (0x2F06, 'M', '二'), + (0x2F07, 'M', '亠'), + (0x2F08, 'M', '人'), + (0x2F09, 'M', '儿'), + (0x2F0A, 'M', '入'), + (0x2F0B, 'M', '八'), + (0x2F0C, 'M', '冂'), + (0x2F0D, 'M', '冖'), + (0x2F0E, 'M', '冫'), + (0x2F0F, 'M', '几'), + (0x2F10, 'M', '凵'), + (0x2F11, 'M', '刀'), + (0x2F12, 'M', '力'), + (0x2F13, 'M', '勹'), + (0x2F14, 'M', '匕'), + (0x2F15, 'M', '匚'), ] - def _seg_27() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x2F1A, "M", "厂"), - (0x2F1B, "M", "厶"), - (0x2F1C, "M", "又"), - (0x2F1D, "M", "口"), - (0x2F1E, "M", "囗"), - (0x2F1F, "M", "土"), - (0x2F20, "M", "士"), - (0x2F21, "M", "夂"), - (0x2F22, "M", "夊"), - (0x2F23, "M", "夕"), - (0x2F24, "M", "大"), - (0x2F25, "M", "女"), - (0x2F26, "M", "子"), - (0x2F27, "M", "宀"), - (0x2F28, "M", "寸"), - (0x2F29, "M", "小"), - (0x2F2A, "M", "尢"), - (0x2F2B, "M", "尸"), - (0x2F2C, "M", "屮"), - (0x2F2D, "M", "山"), - (0x2F2E, "M", "巛"), - (0x2F2F, "M", "工"), - (0x2F30, "M", "己"), - (0x2F31, "M", "巾"), - (0x2F32, "M", "干"), - (0x2F33, "M", "幺"), - (0x2F34, "M", "广"), - (0x2F35, "M", "廴"), - (0x2F36, "M", "廾"), - (0x2F37, "M", "弋"), - (0x2F38, "M", "弓"), - (0x2F39, "M", "彐"), - (0x2F3A, "M", "彡"), - (0x2F3B, "M", "彳"), - (0x2F3C, "M", "心"), - (0x2F3D, "M", "戈"), - (0x2F3E, "M", "戶"), - (0x2F3F, "M", "手"), - (0x2F40, "M", "支"), - (0x2F41, "M", "攴"), - (0x2F42, "M", "文"), - (0x2F43, "M", "斗"), - (0x2F44, "M", "斤"), - (0x2F45, "M", "方"), - (0x2F46, "M", "无"), - (0x2F47, "M", "日"), - (0x2F48, "M", "曰"), - (0x2F49, "M", "月"), - (0x2F4A, "M", "木"), - (0x2F4B, "M", "欠"), - (0x2F4C, "M", "止"), - (0x2F4D, "M", "歹"), - (0x2F4E, "M", "殳"), - (0x2F4F, "M", "毋"), - (0x2F50, "M", "比"), - (0x2F51, "M", "毛"), - (0x2F52, "M", "氏"), - (0x2F53, "M", "气"), - (0x2F54, "M", "水"), - (0x2F55, "M", "火"), - (0x2F56, "M", "爪"), - (0x2F57, "M", "父"), - (0x2F58, "M", "爻"), - (0x2F59, "M", "爿"), - (0x2F5A, "M", "片"), - (0x2F5B, "M", "牙"), - (0x2F5C, "M", "牛"), - (0x2F5D, "M", "犬"), - (0x2F5E, "M", "玄"), - (0x2F5F, "M", "玉"), - (0x2F60, "M", "瓜"), - (0x2F61, "M", "瓦"), - (0x2F62, "M", "甘"), - (0x2F63, "M", "生"), - (0x2F64, "M", "用"), - (0x2F65, "M", "田"), - (0x2F66, "M", "疋"), - (0x2F67, "M", "疒"), - (0x2F68, "M", "癶"), - (0x2F69, "M", "白"), - (0x2F6A, "M", "皮"), - (0x2F6B, "M", "皿"), - (0x2F6C, "M", "目"), - (0x2F6D, "M", "矛"), - (0x2F6E, "M", "矢"), - (0x2F6F, "M", "石"), - (0x2F70, "M", "示"), - (0x2F71, "M", "禸"), - (0x2F72, "M", "禾"), - (0x2F73, "M", "穴"), - (0x2F74, "M", "立"), - (0x2F75, "M", "竹"), - (0x2F76, "M", "米"), - (0x2F77, "M", "糸"), - (0x2F78, "M", "缶"), - (0x2F79, "M", "网"), - (0x2F7A, "M", "羊"), - (0x2F7B, "M", "羽"), - (0x2F7C, "M", "老"), - (0x2F7D, "M", "而"), + (0x2F16, 'M', '匸'), + (0x2F17, 'M', '十'), + (0x2F18, 'M', '卜'), + (0x2F19, 'M', '卩'), + (0x2F1A, 'M', '厂'), + (0x2F1B, 'M', '厶'), + (0x2F1C, 'M', '又'), + (0x2F1D, 'M', '口'), + (0x2F1E, 'M', '囗'), + (0x2F1F, 'M', '土'), + (0x2F20, 'M', '士'), + (0x2F21, 'M', '夂'), + (0x2F22, 'M', '夊'), + (0x2F23, 'M', '夕'), + (0x2F24, 'M', '大'), + (0x2F25, 'M', '女'), + (0x2F26, 'M', '子'), + (0x2F27, 'M', '宀'), + (0x2F28, 'M', '寸'), + (0x2F29, 'M', '小'), + (0x2F2A, 'M', '尢'), + (0x2F2B, 'M', '尸'), + (0x2F2C, 'M', '屮'), + (0x2F2D, 'M', '山'), + (0x2F2E, 'M', '巛'), + (0x2F2F, 'M', '工'), + (0x2F30, 'M', '己'), + (0x2F31, 'M', '巾'), + (0x2F32, 'M', '干'), + (0x2F33, 'M', '幺'), + (0x2F34, 'M', '广'), + (0x2F35, 'M', '廴'), + (0x2F36, 'M', '廾'), + (0x2F37, 'M', '弋'), + (0x2F38, 'M', '弓'), + (0x2F39, 'M', '彐'), + (0x2F3A, 'M', '彡'), + (0x2F3B, 'M', '彳'), + (0x2F3C, 'M', '心'), + (0x2F3D, 'M', '戈'), + (0x2F3E, 'M', '戶'), + (0x2F3F, 'M', '手'), + (0x2F40, 'M', '支'), + (0x2F41, 'M', '攴'), + (0x2F42, 'M', '文'), + (0x2F43, 'M', '斗'), + (0x2F44, 'M', '斤'), + (0x2F45, 'M', '方'), + (0x2F46, 'M', '无'), + (0x2F47, 'M', '日'), + (0x2F48, 'M', '曰'), + (0x2F49, 'M', '月'), + (0x2F4A, 'M', '木'), + (0x2F4B, 'M', '欠'), + (0x2F4C, 'M', '止'), + (0x2F4D, 'M', '歹'), + (0x2F4E, 'M', '殳'), + (0x2F4F, 'M', '毋'), + (0x2F50, 'M', '比'), + (0x2F51, 'M', '毛'), + (0x2F52, 'M', '氏'), + (0x2F53, 'M', '气'), + (0x2F54, 'M', '水'), + (0x2F55, 'M', '火'), + (0x2F56, 'M', '爪'), + (0x2F57, 'M', '父'), + (0x2F58, 'M', '爻'), + (0x2F59, 'M', '爿'), + (0x2F5A, 'M', '片'), + (0x2F5B, 'M', '牙'), + (0x2F5C, 'M', '牛'), + (0x2F5D, 'M', '犬'), + (0x2F5E, 'M', '玄'), + (0x2F5F, 'M', '玉'), + (0x2F60, 'M', '瓜'), + (0x2F61, 'M', '瓦'), + (0x2F62, 'M', '甘'), + (0x2F63, 'M', '生'), + (0x2F64, 'M', '用'), + (0x2F65, 'M', '田'), + (0x2F66, 'M', '疋'), + (0x2F67, 'M', '疒'), + (0x2F68, 'M', '癶'), + (0x2F69, 'M', '白'), + (0x2F6A, 'M', '皮'), + (0x2F6B, 'M', '皿'), + (0x2F6C, 'M', '目'), + (0x2F6D, 'M', '矛'), + (0x2F6E, 'M', '矢'), + (0x2F6F, 'M', '石'), + (0x2F70, 'M', '示'), + (0x2F71, 'M', '禸'), + (0x2F72, 'M', '禾'), + (0x2F73, 'M', '穴'), + (0x2F74, 'M', '立'), + (0x2F75, 'M', '竹'), + (0x2F76, 'M', '米'), + (0x2F77, 'M', '糸'), + (0x2F78, 'M', '缶'), + (0x2F79, 'M', '网'), ] - def _seg_28() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x2F7E, "M", "耒"), - (0x2F7F, "M", "耳"), - (0x2F80, "M", "聿"), - (0x2F81, "M", "肉"), - (0x2F82, "M", "臣"), - (0x2F83, "M", "自"), - (0x2F84, "M", "至"), - (0x2F85, "M", "臼"), - (0x2F86, "M", "舌"), - (0x2F87, "M", "舛"), - (0x2F88, "M", "舟"), - (0x2F89, "M", "艮"), - (0x2F8A, "M", "色"), - (0x2F8B, "M", "艸"), - (0x2F8C, "M", "虍"), - (0x2F8D, "M", "虫"), - (0x2F8E, "M", "血"), - (0x2F8F, "M", "行"), - (0x2F90, "M", "衣"), - (0x2F91, "M", "襾"), - (0x2F92, "M", "見"), - (0x2F93, "M", "角"), - (0x2F94, "M", "言"), - (0x2F95, "M", "谷"), - (0x2F96, "M", "豆"), - (0x2F97, "M", "豕"), - (0x2F98, "M", "豸"), - (0x2F99, "M", "貝"), - (0x2F9A, "M", "赤"), - (0x2F9B, "M", "走"), - (0x2F9C, "M", "足"), - (0x2F9D, "M", "身"), - (0x2F9E, "M", "車"), - (0x2F9F, "M", "辛"), - (0x2FA0, "M", "辰"), - (0x2FA1, "M", "辵"), - (0x2FA2, "M", "邑"), - (0x2FA3, "M", "酉"), - (0x2FA4, "M", "釆"), - (0x2FA5, "M", "里"), - (0x2FA6, "M", "金"), - (0x2FA7, "M", "長"), - (0x2FA8, "M", "門"), - (0x2FA9, "M", "阜"), - (0x2FAA, "M", "隶"), - (0x2FAB, "M", "隹"), - (0x2FAC, "M", "雨"), - (0x2FAD, "M", "靑"), - (0x2FAE, "M", "非"), - (0x2FAF, "M", "面"), - (0x2FB0, "M", "革"), - (0x2FB1, "M", "韋"), - (0x2FB2, "M", "韭"), - (0x2FB3, "M", "音"), - (0x2FB4, "M", "頁"), - (0x2FB5, "M", "風"), - (0x2FB6, "M", "飛"), - (0x2FB7, "M", "食"), - (0x2FB8, "M", "首"), - (0x2FB9, "M", "香"), - (0x2FBA, "M", "馬"), - (0x2FBB, "M", "骨"), - (0x2FBC, "M", "高"), - (0x2FBD, "M", "髟"), - (0x2FBE, "M", "鬥"), - (0x2FBF, "M", "鬯"), - (0x2FC0, "M", "鬲"), - (0x2FC1, "M", "鬼"), - (0x2FC2, "M", "魚"), - (0x2FC3, "M", "鳥"), - (0x2FC4, "M", "鹵"), - (0x2FC5, "M", "鹿"), - (0x2FC6, "M", "麥"), - (0x2FC7, "M", "麻"), - (0x2FC8, "M", "黃"), - (0x2FC9, "M", "黍"), - (0x2FCA, "M", "黑"), - (0x2FCB, "M", "黹"), - (0x2FCC, "M", "黽"), - (0x2FCD, "M", "鼎"), - (0x2FCE, "M", "鼓"), - (0x2FCF, "M", "鼠"), - (0x2FD0, "M", "鼻"), - (0x2FD1, "M", "齊"), - (0x2FD2, "M", "齒"), - (0x2FD3, "M", "龍"), - (0x2FD4, "M", "龜"), - (0x2FD5, "M", "龠"), - (0x2FD6, "X"), - (0x3000, "3", " "), - (0x3001, "V"), - (0x3002, "M", "."), - (0x3003, "V"), - (0x3036, "M", "〒"), - (0x3037, "V"), - (0x3038, "M", "十"), - (0x3039, "M", "卄"), - (0x303A, "M", "卅"), - (0x303B, "V"), - (0x3040, "X"), + (0x2F7A, 'M', '羊'), + (0x2F7B, 'M', '羽'), + (0x2F7C, 'M', '老'), + (0x2F7D, 'M', '而'), + (0x2F7E, 'M', '耒'), + (0x2F7F, 'M', '耳'), + (0x2F80, 'M', '聿'), + (0x2F81, 'M', '肉'), + (0x2F82, 'M', '臣'), + (0x2F83, 'M', '自'), + (0x2F84, 'M', '至'), + (0x2F85, 'M', '臼'), + (0x2F86, 'M', '舌'), + (0x2F87, 'M', '舛'), + (0x2F88, 'M', '舟'), + (0x2F89, 'M', '艮'), + (0x2F8A, 'M', '色'), + (0x2F8B, 'M', '艸'), + (0x2F8C, 'M', '虍'), + (0x2F8D, 'M', '虫'), + (0x2F8E, 'M', '血'), + (0x2F8F, 'M', '行'), + (0x2F90, 'M', '衣'), + (0x2F91, 'M', '襾'), + (0x2F92, 'M', '見'), + (0x2F93, 'M', '角'), + (0x2F94, 'M', '言'), + (0x2F95, 'M', '谷'), + (0x2F96, 'M', '豆'), + (0x2F97, 'M', '豕'), + (0x2F98, 'M', '豸'), + (0x2F99, 'M', '貝'), + (0x2F9A, 'M', '赤'), + (0x2F9B, 'M', '走'), + (0x2F9C, 'M', '足'), + (0x2F9D, 'M', '身'), + (0x2F9E, 'M', '車'), + (0x2F9F, 'M', '辛'), + (0x2FA0, 'M', '辰'), + (0x2FA1, 'M', '辵'), + (0x2FA2, 'M', '邑'), + (0x2FA3, 'M', '酉'), + (0x2FA4, 'M', '釆'), + (0x2FA5, 'M', '里'), + (0x2FA6, 'M', '金'), + (0x2FA7, 'M', '長'), + (0x2FA8, 'M', '門'), + (0x2FA9, 'M', '阜'), + (0x2FAA, 'M', '隶'), + (0x2FAB, 'M', '隹'), + (0x2FAC, 'M', '雨'), + (0x2FAD, 'M', '靑'), + (0x2FAE, 'M', '非'), + (0x2FAF, 'M', '面'), + (0x2FB0, 'M', '革'), + (0x2FB1, 'M', '韋'), + (0x2FB2, 'M', '韭'), + (0x2FB3, 'M', '音'), + (0x2FB4, 'M', '頁'), + (0x2FB5, 'M', '風'), + (0x2FB6, 'M', '飛'), + (0x2FB7, 'M', '食'), + (0x2FB8, 'M', '首'), + (0x2FB9, 'M', '香'), + (0x2FBA, 'M', '馬'), + (0x2FBB, 'M', '骨'), + (0x2FBC, 'M', '高'), + (0x2FBD, 'M', '髟'), + (0x2FBE, 'M', '鬥'), + (0x2FBF, 'M', '鬯'), + (0x2FC0, 'M', '鬲'), + (0x2FC1, 'M', '鬼'), + (0x2FC2, 'M', '魚'), + (0x2FC3, 'M', '鳥'), + (0x2FC4, 'M', '鹵'), + (0x2FC5, 'M', '鹿'), + (0x2FC6, 'M', '麥'), + (0x2FC7, 'M', '麻'), + (0x2FC8, 'M', '黃'), + (0x2FC9, 'M', '黍'), + (0x2FCA, 'M', '黑'), + (0x2FCB, 'M', '黹'), + (0x2FCC, 'M', '黽'), + (0x2FCD, 'M', '鼎'), + (0x2FCE, 'M', '鼓'), + (0x2FCF, 'M', '鼠'), + (0x2FD0, 'M', '鼻'), + (0x2FD1, 'M', '齊'), + (0x2FD2, 'M', '齒'), + (0x2FD3, 'M', '龍'), + (0x2FD4, 'M', '龜'), + (0x2FD5, 'M', '龠'), + (0x2FD6, 'X'), + (0x3000, '3', ' '), + (0x3001, 'V'), + (0x3002, 'M', '.'), + (0x3003, 'V'), + (0x3036, 'M', '〒'), + (0x3037, 'V'), + (0x3038, 'M', '十'), ] - def _seg_29() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x3041, "V"), - (0x3097, "X"), - (0x3099, "V"), - (0x309B, "3", " ゙"), - (0x309C, "3", " ゚"), - (0x309D, "V"), - (0x309F, "M", "より"), - (0x30A0, "V"), - (0x30FF, "M", "コト"), - (0x3100, "X"), - (0x3105, "V"), - (0x3130, "X"), - (0x3131, "M", "ᄀ"), - (0x3132, "M", "ᄁ"), - (0x3133, "M", "ᆪ"), - (0x3134, "M", "ᄂ"), - (0x3135, "M", "ᆬ"), - (0x3136, "M", "ᆭ"), - (0x3137, "M", "ᄃ"), - (0x3138, "M", "ᄄ"), - (0x3139, "M", "ᄅ"), - (0x313A, "M", "ᆰ"), - (0x313B, "M", "ᆱ"), - (0x313C, "M", "ᆲ"), - (0x313D, "M", "ᆳ"), - (0x313E, "M", "ᆴ"), - (0x313F, "M", "ᆵ"), - (0x3140, "M", "ᄚ"), - (0x3141, "M", "ᄆ"), - (0x3142, "M", "ᄇ"), - (0x3143, "M", "ᄈ"), - (0x3144, "M", "ᄡ"), - (0x3145, "M", "ᄉ"), - (0x3146, "M", "ᄊ"), - (0x3147, "M", "ᄋ"), - (0x3148, "M", "ᄌ"), - (0x3149, "M", "ᄍ"), - (0x314A, "M", "ᄎ"), - (0x314B, "M", "ᄏ"), - (0x314C, "M", "ᄐ"), - (0x314D, "M", "ᄑ"), - (0x314E, "M", "ᄒ"), - (0x314F, "M", "ᅡ"), - (0x3150, "M", "ᅢ"), - (0x3151, "M", "ᅣ"), - (0x3152, "M", "ᅤ"), - (0x3153, "M", "ᅥ"), - (0x3154, "M", "ᅦ"), - (0x3155, "M", "ᅧ"), - (0x3156, "M", "ᅨ"), - (0x3157, "M", "ᅩ"), - (0x3158, "M", "ᅪ"), - (0x3159, "M", "ᅫ"), - (0x315A, "M", "ᅬ"), - (0x315B, "M", "ᅭ"), - (0x315C, "M", "ᅮ"), - (0x315D, "M", "ᅯ"), - (0x315E, "M", "ᅰ"), - (0x315F, "M", "ᅱ"), - (0x3160, "M", "ᅲ"), - (0x3161, "M", "ᅳ"), - (0x3162, "M", "ᅴ"), - (0x3163, "M", "ᅵ"), - (0x3164, "X"), - (0x3165, "M", "ᄔ"), - (0x3166, "M", "ᄕ"), - (0x3167, "M", "ᇇ"), - (0x3168, "M", "ᇈ"), - (0x3169, "M", "ᇌ"), - (0x316A, "M", "ᇎ"), - (0x316B, "M", "ᇓ"), - (0x316C, "M", "ᇗ"), - (0x316D, "M", "ᇙ"), - (0x316E, "M", "ᄜ"), - (0x316F, "M", "ᇝ"), - (0x3170, "M", "ᇟ"), - (0x3171, "M", "ᄝ"), - (0x3172, "M", "ᄞ"), - (0x3173, "M", "ᄠ"), - (0x3174, "M", "ᄢ"), - (0x3175, "M", "ᄣ"), - (0x3176, "M", "ᄧ"), - (0x3177, "M", "ᄩ"), - (0x3178, "M", "ᄫ"), - (0x3179, "M", "ᄬ"), - (0x317A, "M", "ᄭ"), - (0x317B, "M", "ᄮ"), - (0x317C, "M", "ᄯ"), - (0x317D, "M", "ᄲ"), - (0x317E, "M", "ᄶ"), - (0x317F, "M", "ᅀ"), - (0x3180, "M", "ᅇ"), - (0x3181, "M", "ᅌ"), - (0x3182, "M", "ᇱ"), - (0x3183, "M", "ᇲ"), - (0x3184, "M", "ᅗ"), - (0x3185, "M", "ᅘ"), - (0x3186, "M", "ᅙ"), - (0x3187, "M", "ᆄ"), - (0x3188, "M", "ᆅ"), + (0x3039, 'M', '卄'), + (0x303A, 'M', '卅'), + (0x303B, 'V'), + (0x3040, 'X'), + (0x3041, 'V'), + (0x3097, 'X'), + (0x3099, 'V'), + (0x309B, '3', ' ゙'), + (0x309C, '3', ' ゚'), + (0x309D, 'V'), + (0x309F, 'M', 'より'), + (0x30A0, 'V'), + (0x30FF, 'M', 'コト'), + (0x3100, 'X'), + (0x3105, 'V'), + (0x3130, 'X'), + (0x3131, 'M', 'ᄀ'), + (0x3132, 'M', 'ᄁ'), + (0x3133, 'M', 'ᆪ'), + (0x3134, 'M', 'ᄂ'), + (0x3135, 'M', 'ᆬ'), + (0x3136, 'M', 'ᆭ'), + (0x3137, 'M', 'ᄃ'), + (0x3138, 'M', 'ᄄ'), + (0x3139, 'M', 'ᄅ'), + (0x313A, 'M', 'ᆰ'), + (0x313B, 'M', 'ᆱ'), + (0x313C, 'M', 'ᆲ'), + (0x313D, 'M', 'ᆳ'), + (0x313E, 'M', 'ᆴ'), + (0x313F, 'M', 'ᆵ'), + (0x3140, 'M', 'ᄚ'), + (0x3141, 'M', 'ᄆ'), + (0x3142, 'M', 'ᄇ'), + (0x3143, 'M', 'ᄈ'), + (0x3144, 'M', 'ᄡ'), + (0x3145, 'M', 'ᄉ'), + (0x3146, 'M', 'ᄊ'), + (0x3147, 'M', 'ᄋ'), + (0x3148, 'M', 'ᄌ'), + (0x3149, 'M', 'ᄍ'), + (0x314A, 'M', 'ᄎ'), + (0x314B, 'M', 'ᄏ'), + (0x314C, 'M', 'ᄐ'), + (0x314D, 'M', 'ᄑ'), + (0x314E, 'M', 'ᄒ'), + (0x314F, 'M', 'ᅡ'), + (0x3150, 'M', 'ᅢ'), + (0x3151, 'M', 'ᅣ'), + (0x3152, 'M', 'ᅤ'), + (0x3153, 'M', 'ᅥ'), + (0x3154, 'M', 'ᅦ'), + (0x3155, 'M', 'ᅧ'), + (0x3156, 'M', 'ᅨ'), + (0x3157, 'M', 'ᅩ'), + (0x3158, 'M', 'ᅪ'), + (0x3159, 'M', 'ᅫ'), + (0x315A, 'M', 'ᅬ'), + (0x315B, 'M', 'ᅭ'), + (0x315C, 'M', 'ᅮ'), + (0x315D, 'M', 'ᅯ'), + (0x315E, 'M', 'ᅰ'), + (0x315F, 'M', 'ᅱ'), + (0x3160, 'M', 'ᅲ'), + (0x3161, 'M', 'ᅳ'), + (0x3162, 'M', 'ᅴ'), + (0x3163, 'M', 'ᅵ'), + (0x3164, 'X'), + (0x3165, 'M', 'ᄔ'), + (0x3166, 'M', 'ᄕ'), + (0x3167, 'M', 'ᇇ'), + (0x3168, 'M', 'ᇈ'), + (0x3169, 'M', 'ᇌ'), + (0x316A, 'M', 'ᇎ'), + (0x316B, 'M', 'ᇓ'), + (0x316C, 'M', 'ᇗ'), + (0x316D, 'M', 'ᇙ'), + (0x316E, 'M', 'ᄜ'), + (0x316F, 'M', 'ᇝ'), + (0x3170, 'M', 'ᇟ'), + (0x3171, 'M', 'ᄝ'), + (0x3172, 'M', 'ᄞ'), + (0x3173, 'M', 'ᄠ'), + (0x3174, 'M', 'ᄢ'), + (0x3175, 'M', 'ᄣ'), + (0x3176, 'M', 'ᄧ'), + (0x3177, 'M', 'ᄩ'), + (0x3178, 'M', 'ᄫ'), + (0x3179, 'M', 'ᄬ'), + (0x317A, 'M', 'ᄭ'), + (0x317B, 'M', 'ᄮ'), + (0x317C, 'M', 'ᄯ'), + (0x317D, 'M', 'ᄲ'), + (0x317E, 'M', 'ᄶ'), + (0x317F, 'M', 'ᅀ'), + (0x3180, 'M', 'ᅇ'), + (0x3181, 'M', 'ᅌ'), + (0x3182, 'M', 'ᇱ'), + (0x3183, 'M', 'ᇲ'), + (0x3184, 'M', 'ᅗ'), ] - def _seg_30() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x3189, "M", "ᆈ"), - (0x318A, "M", "ᆑ"), - (0x318B, "M", "ᆒ"), - (0x318C, "M", "ᆔ"), - (0x318D, "M", "ᆞ"), - (0x318E, "M", "ᆡ"), - (0x318F, "X"), - (0x3190, "V"), - (0x3192, "M", "一"), - (0x3193, "M", "二"), - (0x3194, "M", "三"), - (0x3195, "M", "四"), - (0x3196, "M", "上"), - (0x3197, "M", "中"), - (0x3198, "M", "下"), - (0x3199, "M", "甲"), - (0x319A, "M", "乙"), - (0x319B, "M", "丙"), - (0x319C, "M", "丁"), - (0x319D, "M", "天"), - (0x319E, "M", "地"), - (0x319F, "M", "人"), - (0x31A0, "V"), - (0x31E4, "X"), - (0x31F0, "V"), - (0x3200, "3", "(ᄀ)"), - (0x3201, "3", "(ᄂ)"), - (0x3202, "3", "(ᄃ)"), - (0x3203, "3", "(ᄅ)"), - (0x3204, "3", "(ᄆ)"), - (0x3205, "3", "(ᄇ)"), - (0x3206, "3", "(ᄉ)"), - (0x3207, "3", "(ᄋ)"), - (0x3208, "3", "(ᄌ)"), - (0x3209, "3", "(ᄎ)"), - (0x320A, "3", "(ᄏ)"), - (0x320B, "3", "(ᄐ)"), - (0x320C, "3", "(ᄑ)"), - (0x320D, "3", "(ᄒ)"), - (0x320E, "3", "(가)"), - (0x320F, "3", "(나)"), - (0x3210, "3", "(다)"), - (0x3211, "3", "(라)"), - (0x3212, "3", "(마)"), - (0x3213, "3", "(바)"), - (0x3214, "3", "(사)"), - (0x3215, "3", "(아)"), - (0x3216, "3", "(자)"), - (0x3217, "3", "(차)"), - (0x3218, "3", "(카)"), - (0x3219, "3", "(타)"), - (0x321A, "3", "(파)"), - (0x321B, "3", "(하)"), - (0x321C, "3", "(주)"), - (0x321D, "3", "(오전)"), - (0x321E, "3", "(오후)"), - (0x321F, "X"), - (0x3220, "3", "(一)"), - (0x3221, "3", "(二)"), - (0x3222, "3", "(三)"), - (0x3223, "3", "(四)"), - (0x3224, "3", "(五)"), - (0x3225, "3", "(六)"), - (0x3226, "3", "(七)"), - (0x3227, "3", "(八)"), - (0x3228, "3", "(九)"), - (0x3229, "3", "(十)"), - (0x322A, "3", "(月)"), - (0x322B, "3", "(火)"), - (0x322C, "3", "(水)"), - (0x322D, "3", "(木)"), - (0x322E, "3", "(金)"), - (0x322F, "3", "(土)"), - (0x3230, "3", "(日)"), - (0x3231, "3", "(株)"), - (0x3232, "3", "(有)"), - (0x3233, "3", "(社)"), - (0x3234, "3", "(名)"), - (0x3235, "3", "(特)"), - (0x3236, "3", "(財)"), - (0x3237, "3", "(祝)"), - (0x3238, "3", "(労)"), - (0x3239, "3", "(代)"), - (0x323A, "3", "(呼)"), - (0x323B, "3", "(学)"), - (0x323C, "3", "(監)"), - (0x323D, "3", "(企)"), - (0x323E, "3", "(資)"), - (0x323F, "3", "(協)"), - (0x3240, "3", "(祭)"), - (0x3241, "3", "(休)"), - (0x3242, "3", "(自)"), - (0x3243, "3", "(至)"), - (0x3244, "M", "問"), - (0x3245, "M", "幼"), - (0x3246, "M", "文"), - (0x3247, "M", "箏"), - (0x3248, "V"), - (0x3250, "M", "pte"), - (0x3251, "M", "21"), + (0x3185, 'M', 'ᅘ'), + (0x3186, 'M', 'ᅙ'), + (0x3187, 'M', 'ᆄ'), + (0x3188, 'M', 'ᆅ'), + (0x3189, 'M', 'ᆈ'), + (0x318A, 'M', 'ᆑ'), + (0x318B, 'M', 'ᆒ'), + (0x318C, 'M', 'ᆔ'), + (0x318D, 'M', 'ᆞ'), + (0x318E, 'M', 'ᆡ'), + (0x318F, 'X'), + (0x3190, 'V'), + (0x3192, 'M', '一'), + (0x3193, 'M', '二'), + (0x3194, 'M', '三'), + (0x3195, 'M', '四'), + (0x3196, 'M', '上'), + (0x3197, 'M', '中'), + (0x3198, 'M', '下'), + (0x3199, 'M', '甲'), + (0x319A, 'M', '乙'), + (0x319B, 'M', '丙'), + (0x319C, 'M', '丁'), + (0x319D, 'M', '天'), + (0x319E, 'M', '地'), + (0x319F, 'M', '人'), + (0x31A0, 'V'), + (0x31E4, 'X'), + (0x31F0, 'V'), + (0x3200, '3', '(ᄀ)'), + (0x3201, '3', '(ᄂ)'), + (0x3202, '3', '(ᄃ)'), + (0x3203, '3', '(ᄅ)'), + (0x3204, '3', '(ᄆ)'), + (0x3205, '3', '(ᄇ)'), + (0x3206, '3', '(ᄉ)'), + (0x3207, '3', '(ᄋ)'), + (0x3208, '3', '(ᄌ)'), + (0x3209, '3', '(ᄎ)'), + (0x320A, '3', '(ᄏ)'), + (0x320B, '3', '(ᄐ)'), + (0x320C, '3', '(ᄑ)'), + (0x320D, '3', '(ᄒ)'), + (0x320E, '3', '(가)'), + (0x320F, '3', '(나)'), + (0x3210, '3', '(다)'), + (0x3211, '3', '(라)'), + (0x3212, '3', '(마)'), + (0x3213, '3', '(바)'), + (0x3214, '3', '(사)'), + (0x3215, '3', '(아)'), + (0x3216, '3', '(자)'), + (0x3217, '3', '(차)'), + (0x3218, '3', '(카)'), + (0x3219, '3', '(타)'), + (0x321A, '3', '(파)'), + (0x321B, '3', '(하)'), + (0x321C, '3', '(주)'), + (0x321D, '3', '(오전)'), + (0x321E, '3', '(오후)'), + (0x321F, 'X'), + (0x3220, '3', '(一)'), + (0x3221, '3', '(二)'), + (0x3222, '3', '(三)'), + (0x3223, '3', '(四)'), + (0x3224, '3', '(五)'), + (0x3225, '3', '(六)'), + (0x3226, '3', '(七)'), + (0x3227, '3', '(八)'), + (0x3228, '3', '(九)'), + (0x3229, '3', '(十)'), + (0x322A, '3', '(月)'), + (0x322B, '3', '(火)'), + (0x322C, '3', '(水)'), + (0x322D, '3', '(木)'), + (0x322E, '3', '(金)'), + (0x322F, '3', '(土)'), + (0x3230, '3', '(日)'), + (0x3231, '3', '(株)'), + (0x3232, '3', '(有)'), + (0x3233, '3', '(社)'), + (0x3234, '3', '(名)'), + (0x3235, '3', '(特)'), + (0x3236, '3', '(財)'), + (0x3237, '3', '(祝)'), + (0x3238, '3', '(労)'), + (0x3239, '3', '(代)'), + (0x323A, '3', '(呼)'), + (0x323B, '3', '(学)'), + (0x323C, '3', '(監)'), + (0x323D, '3', '(企)'), + (0x323E, '3', '(資)'), + (0x323F, '3', '(協)'), + (0x3240, '3', '(祭)'), + (0x3241, '3', '(休)'), + (0x3242, '3', '(自)'), + (0x3243, '3', '(至)'), + (0x3244, 'M', '問'), + (0x3245, 'M', '幼'), + (0x3246, 'M', '文'), ] - def _seg_31() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x3252, "M", "22"), - (0x3253, "M", "23"), - (0x3254, "M", "24"), - (0x3255, "M", "25"), - (0x3256, "M", "26"), - (0x3257, "M", "27"), - (0x3258, "M", "28"), - (0x3259, "M", "29"), - (0x325A, "M", "30"), - (0x325B, "M", "31"), - (0x325C, "M", "32"), - (0x325D, "M", "33"), - (0x325E, "M", "34"), - (0x325F, "M", "35"), - (0x3260, "M", "ᄀ"), - (0x3261, "M", "ᄂ"), - (0x3262, "M", "ᄃ"), - (0x3263, "M", "ᄅ"), - (0x3264, "M", "ᄆ"), - (0x3265, "M", "ᄇ"), - (0x3266, "M", "ᄉ"), - (0x3267, "M", "ᄋ"), - (0x3268, "M", "ᄌ"), - (0x3269, "M", "ᄎ"), - (0x326A, "M", "ᄏ"), - (0x326B, "M", "ᄐ"), - (0x326C, "M", "ᄑ"), - (0x326D, "M", "ᄒ"), - (0x326E, "M", "가"), - (0x326F, "M", "나"), - (0x3270, "M", "다"), - (0x3271, "M", "라"), - (0x3272, "M", "마"), - (0x3273, "M", "바"), - (0x3274, "M", "사"), - (0x3275, "M", "아"), - (0x3276, "M", "자"), - (0x3277, "M", "차"), - (0x3278, "M", "카"), - (0x3279, "M", "타"), - (0x327A, "M", "파"), - (0x327B, "M", "하"), - (0x327C, "M", "참고"), - (0x327D, "M", "주의"), - (0x327E, "M", "우"), - (0x327F, "V"), - (0x3280, "M", "一"), - (0x3281, "M", "二"), - (0x3282, "M", "三"), - (0x3283, "M", "四"), - (0x3284, "M", "五"), - (0x3285, "M", "六"), - (0x3286, "M", "七"), - (0x3287, "M", "八"), - (0x3288, "M", "九"), - (0x3289, "M", "十"), - (0x328A, "M", "月"), - (0x328B, "M", "火"), - (0x328C, "M", "水"), - (0x328D, "M", "木"), - (0x328E, "M", "金"), - (0x328F, "M", "土"), - (0x3290, "M", "日"), - (0x3291, "M", "株"), - (0x3292, "M", "有"), - (0x3293, "M", "社"), - (0x3294, "M", "名"), - (0x3295, "M", "特"), - (0x3296, "M", "財"), - (0x3297, "M", "祝"), - (0x3298, "M", "労"), - (0x3299, "M", "秘"), - (0x329A, "M", "男"), - (0x329B, "M", "女"), - (0x329C, "M", "適"), - (0x329D, "M", "優"), - (0x329E, "M", "印"), - (0x329F, "M", "注"), - (0x32A0, "M", "項"), - (0x32A1, "M", "休"), - (0x32A2, "M", "写"), - (0x32A3, "M", "正"), - (0x32A4, "M", "上"), - (0x32A5, "M", "中"), - (0x32A6, "M", "下"), - (0x32A7, "M", "左"), - (0x32A8, "M", "右"), - (0x32A9, "M", "医"), - (0x32AA, "M", "宗"), - (0x32AB, "M", "学"), - (0x32AC, "M", "監"), - (0x32AD, "M", "企"), - (0x32AE, "M", "資"), - (0x32AF, "M", "協"), - (0x32B0, "M", "夜"), - (0x32B1, "M", "36"), - (0x32B2, "M", "37"), - (0x32B3, "M", "38"), - (0x32B4, "M", "39"), - (0x32B5, "M", "40"), + (0x3247, 'M', '箏'), + (0x3248, 'V'), + (0x3250, 'M', 'pte'), + (0x3251, 'M', '21'), + (0x3252, 'M', '22'), + (0x3253, 'M', '23'), + (0x3254, 'M', '24'), + (0x3255, 'M', '25'), + (0x3256, 'M', '26'), + (0x3257, 'M', '27'), + (0x3258, 'M', '28'), + (0x3259, 'M', '29'), + (0x325A, 'M', '30'), + (0x325B, 'M', '31'), + (0x325C, 'M', '32'), + (0x325D, 'M', '33'), + (0x325E, 'M', '34'), + (0x325F, 'M', '35'), + (0x3260, 'M', 'ᄀ'), + (0x3261, 'M', 'ᄂ'), + (0x3262, 'M', 'ᄃ'), + (0x3263, 'M', 'ᄅ'), + (0x3264, 'M', 'ᄆ'), + (0x3265, 'M', 'ᄇ'), + (0x3266, 'M', 'ᄉ'), + (0x3267, 'M', 'ᄋ'), + (0x3268, 'M', 'ᄌ'), + (0x3269, 'M', 'ᄎ'), + (0x326A, 'M', 'ᄏ'), + (0x326B, 'M', 'ᄐ'), + (0x326C, 'M', 'ᄑ'), + (0x326D, 'M', 'ᄒ'), + (0x326E, 'M', '가'), + (0x326F, 'M', '나'), + (0x3270, 'M', '다'), + (0x3271, 'M', '라'), + (0x3272, 'M', '마'), + (0x3273, 'M', '바'), + (0x3274, 'M', '사'), + (0x3275, 'M', '아'), + (0x3276, 'M', '자'), + (0x3277, 'M', '차'), + (0x3278, 'M', '카'), + (0x3279, 'M', '타'), + (0x327A, 'M', '파'), + (0x327B, 'M', '하'), + (0x327C, 'M', '참고'), + (0x327D, 'M', '주의'), + (0x327E, 'M', '우'), + (0x327F, 'V'), + (0x3280, 'M', '一'), + (0x3281, 'M', '二'), + (0x3282, 'M', '三'), + (0x3283, 'M', '四'), + (0x3284, 'M', '五'), + (0x3285, 'M', '六'), + (0x3286, 'M', '七'), + (0x3287, 'M', '八'), + (0x3288, 'M', '九'), + (0x3289, 'M', '十'), + (0x328A, 'M', '月'), + (0x328B, 'M', '火'), + (0x328C, 'M', '水'), + (0x328D, 'M', '木'), + (0x328E, 'M', '金'), + (0x328F, 'M', '土'), + (0x3290, 'M', '日'), + (0x3291, 'M', '株'), + (0x3292, 'M', '有'), + (0x3293, 'M', '社'), + (0x3294, 'M', '名'), + (0x3295, 'M', '特'), + (0x3296, 'M', '財'), + (0x3297, 'M', '祝'), + (0x3298, 'M', '労'), + (0x3299, 'M', '秘'), + (0x329A, 'M', '男'), + (0x329B, 'M', '女'), + (0x329C, 'M', '適'), + (0x329D, 'M', '優'), + (0x329E, 'M', '印'), + (0x329F, 'M', '注'), + (0x32A0, 'M', '項'), + (0x32A1, 'M', '休'), + (0x32A2, 'M', '写'), + (0x32A3, 'M', '正'), + (0x32A4, 'M', '上'), + (0x32A5, 'M', '中'), + (0x32A6, 'M', '下'), + (0x32A7, 'M', '左'), + (0x32A8, 'M', '右'), + (0x32A9, 'M', '医'), + (0x32AA, 'M', '宗'), + (0x32AB, 'M', '学'), + (0x32AC, 'M', '監'), + (0x32AD, 'M', '企'), + (0x32AE, 'M', '資'), + (0x32AF, 'M', '協'), + (0x32B0, 'M', '夜'), + (0x32B1, 'M', '36'), ] - def _seg_32() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x32B6, "M", "41"), - (0x32B7, "M", "42"), - (0x32B8, "M", "43"), - (0x32B9, "M", "44"), - (0x32BA, "M", "45"), - (0x32BB, "M", "46"), - (0x32BC, "M", "47"), - (0x32BD, "M", "48"), - (0x32BE, "M", "49"), - (0x32BF, "M", "50"), - (0x32C0, "M", "1月"), - (0x32C1, "M", "2月"), - (0x32C2, "M", "3月"), - (0x32C3, "M", "4月"), - (0x32C4, "M", "5月"), - (0x32C5, "M", "6月"), - (0x32C6, "M", "7月"), - (0x32C7, "M", "8月"), - (0x32C8, "M", "9月"), - (0x32C9, "M", "10月"), - (0x32CA, "M", "11月"), - (0x32CB, "M", "12月"), - (0x32CC, "M", "hg"), - (0x32CD, "M", "erg"), - (0x32CE, "M", "ev"), - (0x32CF, "M", "ltd"), - (0x32D0, "M", "ア"), - (0x32D1, "M", "イ"), - (0x32D2, "M", "ウ"), - (0x32D3, "M", "エ"), - (0x32D4, "M", "オ"), - (0x32D5, "M", "カ"), - (0x32D6, "M", "キ"), - (0x32D7, "M", "ク"), - (0x32D8, "M", "ケ"), - (0x32D9, "M", "コ"), - (0x32DA, "M", "サ"), - (0x32DB, "M", "シ"), - (0x32DC, "M", "ス"), - (0x32DD, "M", "セ"), - (0x32DE, "M", "ソ"), - (0x32DF, "M", "タ"), - (0x32E0, "M", "チ"), - (0x32E1, "M", "ツ"), - (0x32E2, "M", "テ"), - (0x32E3, "M", "ト"), - (0x32E4, "M", "ナ"), - (0x32E5, "M", "ニ"), - (0x32E6, "M", "ヌ"), - (0x32E7, "M", "ネ"), - (0x32E8, "M", "ノ"), - (0x32E9, "M", "ハ"), - (0x32EA, "M", "ヒ"), - (0x32EB, "M", "フ"), - (0x32EC, "M", "ヘ"), - (0x32ED, "M", "ホ"), - (0x32EE, "M", "マ"), - (0x32EF, "M", "ミ"), - (0x32F0, "M", "ム"), - (0x32F1, "M", "メ"), - (0x32F2, "M", "モ"), - (0x32F3, "M", "ヤ"), - (0x32F4, "M", "ユ"), - (0x32F5, "M", "ヨ"), - (0x32F6, "M", "ラ"), - (0x32F7, "M", "リ"), - (0x32F8, "M", "ル"), - (0x32F9, "M", "レ"), - (0x32FA, "M", "ロ"), - (0x32FB, "M", "ワ"), - (0x32FC, "M", "ヰ"), - (0x32FD, "M", "ヱ"), - (0x32FE, "M", "ヲ"), - (0x32FF, "M", "令和"), - (0x3300, "M", "アパート"), - (0x3301, "M", "アルファ"), - (0x3302, "M", "アンペア"), - (0x3303, "M", "アール"), - (0x3304, "M", "イニング"), - (0x3305, "M", "インチ"), - (0x3306, "M", "ウォン"), - (0x3307, "M", "エスクード"), - (0x3308, "M", "エーカー"), - (0x3309, "M", "オンス"), - (0x330A, "M", "オーム"), - (0x330B, "M", "カイリ"), - (0x330C, "M", "カラット"), - (0x330D, "M", "カロリー"), - (0x330E, "M", "ガロン"), - (0x330F, "M", "ガンマ"), - (0x3310, "M", "ギガ"), - (0x3311, "M", "ギニー"), - (0x3312, "M", "キュリー"), - (0x3313, "M", "ギルダー"), - (0x3314, "M", "キロ"), - (0x3315, "M", "キログラム"), - (0x3316, "M", "キロメートル"), - (0x3317, "M", "キロワット"), - (0x3318, "M", "グラム"), - (0x3319, "M", "グラムトン"), + (0x32B2, 'M', '37'), + (0x32B3, 'M', '38'), + (0x32B4, 'M', '39'), + (0x32B5, 'M', '40'), + (0x32B6, 'M', '41'), + (0x32B7, 'M', '42'), + (0x32B8, 'M', '43'), + (0x32B9, 'M', '44'), + (0x32BA, 'M', '45'), + (0x32BB, 'M', '46'), + (0x32BC, 'M', '47'), + (0x32BD, 'M', '48'), + (0x32BE, 'M', '49'), + (0x32BF, 'M', '50'), + (0x32C0, 'M', '1月'), + (0x32C1, 'M', '2月'), + (0x32C2, 'M', '3月'), + (0x32C3, 'M', '4月'), + (0x32C4, 'M', '5月'), + (0x32C5, 'M', '6月'), + (0x32C6, 'M', '7月'), + (0x32C7, 'M', '8月'), + (0x32C8, 'M', '9月'), + (0x32C9, 'M', '10月'), + (0x32CA, 'M', '11月'), + (0x32CB, 'M', '12月'), + (0x32CC, 'M', 'hg'), + (0x32CD, 'M', 'erg'), + (0x32CE, 'M', 'ev'), + (0x32CF, 'M', 'ltd'), + (0x32D0, 'M', 'ア'), + (0x32D1, 'M', 'イ'), + (0x32D2, 'M', 'ウ'), + (0x32D3, 'M', 'エ'), + (0x32D4, 'M', 'オ'), + (0x32D5, 'M', 'カ'), + (0x32D6, 'M', 'キ'), + (0x32D7, 'M', 'ク'), + (0x32D8, 'M', 'ケ'), + (0x32D9, 'M', 'コ'), + (0x32DA, 'M', 'サ'), + (0x32DB, 'M', 'シ'), + (0x32DC, 'M', 'ス'), + (0x32DD, 'M', 'セ'), + (0x32DE, 'M', 'ソ'), + (0x32DF, 'M', 'タ'), + (0x32E0, 'M', 'チ'), + (0x32E1, 'M', 'ツ'), + (0x32E2, 'M', 'テ'), + (0x32E3, 'M', 'ト'), + (0x32E4, 'M', 'ナ'), + (0x32E5, 'M', 'ニ'), + (0x32E6, 'M', 'ヌ'), + (0x32E7, 'M', 'ネ'), + (0x32E8, 'M', 'ノ'), + (0x32E9, 'M', 'ハ'), + (0x32EA, 'M', 'ヒ'), + (0x32EB, 'M', 'フ'), + (0x32EC, 'M', 'ヘ'), + (0x32ED, 'M', 'ホ'), + (0x32EE, 'M', 'マ'), + (0x32EF, 'M', 'ミ'), + (0x32F0, 'M', 'ム'), + (0x32F1, 'M', 'メ'), + (0x32F2, 'M', 'モ'), + (0x32F3, 'M', 'ヤ'), + (0x32F4, 'M', 'ユ'), + (0x32F5, 'M', 'ヨ'), + (0x32F6, 'M', 'ラ'), + (0x32F7, 'M', 'リ'), + (0x32F8, 'M', 'ル'), + (0x32F9, 'M', 'レ'), + (0x32FA, 'M', 'ロ'), + (0x32FB, 'M', 'ワ'), + (0x32FC, 'M', 'ヰ'), + (0x32FD, 'M', 'ヱ'), + (0x32FE, 'M', 'ヲ'), + (0x32FF, 'M', '令和'), + (0x3300, 'M', 'アパート'), + (0x3301, 'M', 'アルファ'), + (0x3302, 'M', 'アンペア'), + (0x3303, 'M', 'アール'), + (0x3304, 'M', 'イニング'), + (0x3305, 'M', 'インチ'), + (0x3306, 'M', 'ウォン'), + (0x3307, 'M', 'エスクード'), + (0x3308, 'M', 'エーカー'), + (0x3309, 'M', 'オンス'), + (0x330A, 'M', 'オーム'), + (0x330B, 'M', 'カイリ'), + (0x330C, 'M', 'カラット'), + (0x330D, 'M', 'カロリー'), + (0x330E, 'M', 'ガロン'), + (0x330F, 'M', 'ガンマ'), + (0x3310, 'M', 'ギガ'), + (0x3311, 'M', 'ギニー'), + (0x3312, 'M', 'キュリー'), + (0x3313, 'M', 'ギルダー'), + (0x3314, 'M', 'キロ'), + (0x3315, 'M', 'キログラム'), ] - def _seg_33() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x331A, "M", "クルゼイロ"), - (0x331B, "M", "クローネ"), - (0x331C, "M", "ケース"), - (0x331D, "M", "コルナ"), - (0x331E, "M", "コーポ"), - (0x331F, "M", "サイクル"), - (0x3320, "M", "サンチーム"), - (0x3321, "M", "シリング"), - (0x3322, "M", "センチ"), - (0x3323, "M", "セント"), - (0x3324, "M", "ダース"), - (0x3325, "M", "デシ"), - (0x3326, "M", "ドル"), - (0x3327, "M", "トン"), - (0x3328, "M", "ナノ"), - (0x3329, "M", "ノット"), - (0x332A, "M", "ハイツ"), - (0x332B, "M", "パーセント"), - (0x332C, "M", "パーツ"), - (0x332D, "M", "バーレル"), - (0x332E, "M", "ピアストル"), - (0x332F, "M", "ピクル"), - (0x3330, "M", "ピコ"), - (0x3331, "M", "ビル"), - (0x3332, "M", "ファラッド"), - (0x3333, "M", "フィート"), - (0x3334, "M", "ブッシェル"), - (0x3335, "M", "フラン"), - (0x3336, "M", "ヘクタール"), - (0x3337, "M", "ペソ"), - (0x3338, "M", "ペニヒ"), - (0x3339, "M", "ヘルツ"), - (0x333A, "M", "ペンス"), - (0x333B, "M", "ページ"), - (0x333C, "M", "ベータ"), - (0x333D, "M", "ポイント"), - (0x333E, "M", "ボルト"), - (0x333F, "M", "ホン"), - (0x3340, "M", "ポンド"), - (0x3341, "M", "ホール"), - (0x3342, "M", "ホーン"), - (0x3343, "M", "マイクロ"), - (0x3344, "M", "マイル"), - (0x3345, "M", "マッハ"), - (0x3346, "M", "マルク"), - (0x3347, "M", "マンション"), - (0x3348, "M", "ミクロン"), - (0x3349, "M", "ミリ"), - (0x334A, "M", "ミリバール"), - (0x334B, "M", "メガ"), - (0x334C, "M", "メガトン"), - (0x334D, "M", "メートル"), - (0x334E, "M", "ヤード"), - (0x334F, "M", "ヤール"), - (0x3350, "M", "ユアン"), - (0x3351, "M", "リットル"), - (0x3352, "M", "リラ"), - (0x3353, "M", "ルピー"), - (0x3354, "M", "ルーブル"), - (0x3355, "M", "レム"), - (0x3356, "M", "レントゲン"), - (0x3357, "M", "ワット"), - (0x3358, "M", "0点"), - (0x3359, "M", "1点"), - (0x335A, "M", "2点"), - (0x335B, "M", "3点"), - (0x335C, "M", "4点"), - (0x335D, "M", "5点"), - (0x335E, "M", "6点"), - (0x335F, "M", "7点"), - (0x3360, "M", "8点"), - (0x3361, "M", "9点"), - (0x3362, "M", "10点"), - (0x3363, "M", "11点"), - (0x3364, "M", "12点"), - (0x3365, "M", "13点"), - (0x3366, "M", "14点"), - (0x3367, "M", "15点"), - (0x3368, "M", "16点"), - (0x3369, "M", "17点"), - (0x336A, "M", "18点"), - (0x336B, "M", "19点"), - (0x336C, "M", "20点"), - (0x336D, "M", "21点"), - (0x336E, "M", "22点"), - (0x336F, "M", "23点"), - (0x3370, "M", "24点"), - (0x3371, "M", "hpa"), - (0x3372, "M", "da"), - (0x3373, "M", "au"), - (0x3374, "M", "bar"), - (0x3375, "M", "ov"), - (0x3376, "M", "pc"), - (0x3377, "M", "dm"), - (0x3378, "M", "dm2"), - (0x3379, "M", "dm3"), - (0x337A, "M", "iu"), - (0x337B, "M", "平成"), - (0x337C, "M", "昭和"), - (0x337D, "M", "大正"), + (0x3316, 'M', 'キロメートル'), + (0x3317, 'M', 'キロワット'), + (0x3318, 'M', 'グラム'), + (0x3319, 'M', 'グラムトン'), + (0x331A, 'M', 'クルゼイロ'), + (0x331B, 'M', 'クローネ'), + (0x331C, 'M', 'ケース'), + (0x331D, 'M', 'コルナ'), + (0x331E, 'M', 'コーポ'), + (0x331F, 'M', 'サイクル'), + (0x3320, 'M', 'サンチーム'), + (0x3321, 'M', 'シリング'), + (0x3322, 'M', 'センチ'), + (0x3323, 'M', 'セント'), + (0x3324, 'M', 'ダース'), + (0x3325, 'M', 'デシ'), + (0x3326, 'M', 'ドル'), + (0x3327, 'M', 'トン'), + (0x3328, 'M', 'ナノ'), + (0x3329, 'M', 'ノット'), + (0x332A, 'M', 'ハイツ'), + (0x332B, 'M', 'パーセント'), + (0x332C, 'M', 'パーツ'), + (0x332D, 'M', 'バーレル'), + (0x332E, 'M', 'ピアストル'), + (0x332F, 'M', 'ピクル'), + (0x3330, 'M', 'ピコ'), + (0x3331, 'M', 'ビル'), + (0x3332, 'M', 'ファラッド'), + (0x3333, 'M', 'フィート'), + (0x3334, 'M', 'ブッシェル'), + (0x3335, 'M', 'フラン'), + (0x3336, 'M', 'ヘクタール'), + (0x3337, 'M', 'ペソ'), + (0x3338, 'M', 'ペニヒ'), + (0x3339, 'M', 'ヘルツ'), + (0x333A, 'M', 'ペンス'), + (0x333B, 'M', 'ページ'), + (0x333C, 'M', 'ベータ'), + (0x333D, 'M', 'ポイント'), + (0x333E, 'M', 'ボルト'), + (0x333F, 'M', 'ホン'), + (0x3340, 'M', 'ポンド'), + (0x3341, 'M', 'ホール'), + (0x3342, 'M', 'ホーン'), + (0x3343, 'M', 'マイクロ'), + (0x3344, 'M', 'マイル'), + (0x3345, 'M', 'マッハ'), + (0x3346, 'M', 'マルク'), + (0x3347, 'M', 'マンション'), + (0x3348, 'M', 'ミクロン'), + (0x3349, 'M', 'ミリ'), + (0x334A, 'M', 'ミリバール'), + (0x334B, 'M', 'メガ'), + (0x334C, 'M', 'メガトン'), + (0x334D, 'M', 'メートル'), + (0x334E, 'M', 'ヤード'), + (0x334F, 'M', 'ヤール'), + (0x3350, 'M', 'ユアン'), + (0x3351, 'M', 'リットル'), + (0x3352, 'M', 'リラ'), + (0x3353, 'M', 'ルピー'), + (0x3354, 'M', 'ルーブル'), + (0x3355, 'M', 'レム'), + (0x3356, 'M', 'レントゲン'), + (0x3357, 'M', 'ワット'), + (0x3358, 'M', '0点'), + (0x3359, 'M', '1点'), + (0x335A, 'M', '2点'), + (0x335B, 'M', '3点'), + (0x335C, 'M', '4点'), + (0x335D, 'M', '5点'), + (0x335E, 'M', '6点'), + (0x335F, 'M', '7点'), + (0x3360, 'M', '8点'), + (0x3361, 'M', '9点'), + (0x3362, 'M', '10点'), + (0x3363, 'M', '11点'), + (0x3364, 'M', '12点'), + (0x3365, 'M', '13点'), + (0x3366, 'M', '14点'), + (0x3367, 'M', '15点'), + (0x3368, 'M', '16点'), + (0x3369, 'M', '17点'), + (0x336A, 'M', '18点'), + (0x336B, 'M', '19点'), + (0x336C, 'M', '20点'), + (0x336D, 'M', '21点'), + (0x336E, 'M', '22点'), + (0x336F, 'M', '23点'), + (0x3370, 'M', '24点'), + (0x3371, 'M', 'hpa'), + (0x3372, 'M', 'da'), + (0x3373, 'M', 'au'), + (0x3374, 'M', 'bar'), + (0x3375, 'M', 'ov'), + (0x3376, 'M', 'pc'), + (0x3377, 'M', 'dm'), + (0x3378, 'M', 'dm2'), + (0x3379, 'M', 'dm3'), ] - def _seg_34() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x337E, "M", "明治"), - (0x337F, "M", "株式会社"), - (0x3380, "M", "pa"), - (0x3381, "M", "na"), - (0x3382, "M", "μa"), - (0x3383, "M", "ma"), - (0x3384, "M", "ka"), - (0x3385, "M", "kb"), - (0x3386, "M", "mb"), - (0x3387, "M", "gb"), - (0x3388, "M", "cal"), - (0x3389, "M", "kcal"), - (0x338A, "M", "pf"), - (0x338B, "M", "nf"), - (0x338C, "M", "μf"), - (0x338D, "M", "μg"), - (0x338E, "M", "mg"), - (0x338F, "M", "kg"), - (0x3390, "M", "hz"), - (0x3391, "M", "khz"), - (0x3392, "M", "mhz"), - (0x3393, "M", "ghz"), - (0x3394, "M", "thz"), - (0x3395, "M", "μl"), - (0x3396, "M", "ml"), - (0x3397, "M", "dl"), - (0x3398, "M", "kl"), - (0x3399, "M", "fm"), - (0x339A, "M", "nm"), - (0x339B, "M", "μm"), - (0x339C, "M", "mm"), - (0x339D, "M", "cm"), - (0x339E, "M", "km"), - (0x339F, "M", "mm2"), - (0x33A0, "M", "cm2"), - (0x33A1, "M", "m2"), - (0x33A2, "M", "km2"), - (0x33A3, "M", "mm3"), - (0x33A4, "M", "cm3"), - (0x33A5, "M", "m3"), - (0x33A6, "M", "km3"), - (0x33A7, "M", "m∕s"), - (0x33A8, "M", "m∕s2"), - (0x33A9, "M", "pa"), - (0x33AA, "M", "kpa"), - (0x33AB, "M", "mpa"), - (0x33AC, "M", "gpa"), - (0x33AD, "M", "rad"), - (0x33AE, "M", "rad∕s"), - (0x33AF, "M", "rad∕s2"), - (0x33B0, "M", "ps"), - (0x33B1, "M", "ns"), - (0x33B2, "M", "μs"), - (0x33B3, "M", "ms"), - (0x33B4, "M", "pv"), - (0x33B5, "M", "nv"), - (0x33B6, "M", "μv"), - (0x33B7, "M", "mv"), - (0x33B8, "M", "kv"), - (0x33B9, "M", "mv"), - (0x33BA, "M", "pw"), - (0x33BB, "M", "nw"), - (0x33BC, "M", "μw"), - (0x33BD, "M", "mw"), - (0x33BE, "M", "kw"), - (0x33BF, "M", "mw"), - (0x33C0, "M", "kω"), - (0x33C1, "M", "mω"), - (0x33C2, "X"), - (0x33C3, "M", "bq"), - (0x33C4, "M", "cc"), - (0x33C5, "M", "cd"), - (0x33C6, "M", "c∕kg"), - (0x33C7, "X"), - (0x33C8, "M", "db"), - (0x33C9, "M", "gy"), - (0x33CA, "M", "ha"), - (0x33CB, "M", "hp"), - (0x33CC, "M", "in"), - (0x33CD, "M", "kk"), - (0x33CE, "M", "km"), - (0x33CF, "M", "kt"), - (0x33D0, "M", "lm"), - (0x33D1, "M", "ln"), - (0x33D2, "M", "log"), - (0x33D3, "M", "lx"), - (0x33D4, "M", "mb"), - (0x33D5, "M", "mil"), - (0x33D6, "M", "mol"), - (0x33D7, "M", "ph"), - (0x33D8, "X"), - (0x33D9, "M", "ppm"), - (0x33DA, "M", "pr"), - (0x33DB, "M", "sr"), - (0x33DC, "M", "sv"), - (0x33DD, "M", "wb"), - (0x33DE, "M", "v∕m"), - (0x33DF, "M", "a∕m"), - (0x33E0, "M", "1日"), - (0x33E1, "M", "2日"), + (0x337A, 'M', 'iu'), + (0x337B, 'M', '平成'), + (0x337C, 'M', '昭和'), + (0x337D, 'M', '大正'), + (0x337E, 'M', '明治'), + (0x337F, 'M', '株式会社'), + (0x3380, 'M', 'pa'), + (0x3381, 'M', 'na'), + (0x3382, 'M', 'μa'), + (0x3383, 'M', 'ma'), + (0x3384, 'M', 'ka'), + (0x3385, 'M', 'kb'), + (0x3386, 'M', 'mb'), + (0x3387, 'M', 'gb'), + (0x3388, 'M', 'cal'), + (0x3389, 'M', 'kcal'), + (0x338A, 'M', 'pf'), + (0x338B, 'M', 'nf'), + (0x338C, 'M', 'μf'), + (0x338D, 'M', 'μg'), + (0x338E, 'M', 'mg'), + (0x338F, 'M', 'kg'), + (0x3390, 'M', 'hz'), + (0x3391, 'M', 'khz'), + (0x3392, 'M', 'mhz'), + (0x3393, 'M', 'ghz'), + (0x3394, 'M', 'thz'), + (0x3395, 'M', 'μl'), + (0x3396, 'M', 'ml'), + (0x3397, 'M', 'dl'), + (0x3398, 'M', 'kl'), + (0x3399, 'M', 'fm'), + (0x339A, 'M', 'nm'), + (0x339B, 'M', 'μm'), + (0x339C, 'M', 'mm'), + (0x339D, 'M', 'cm'), + (0x339E, 'M', 'km'), + (0x339F, 'M', 'mm2'), + (0x33A0, 'M', 'cm2'), + (0x33A1, 'M', 'm2'), + (0x33A2, 'M', 'km2'), + (0x33A3, 'M', 'mm3'), + (0x33A4, 'M', 'cm3'), + (0x33A5, 'M', 'm3'), + (0x33A6, 'M', 'km3'), + (0x33A7, 'M', 'm∕s'), + (0x33A8, 'M', 'm∕s2'), + (0x33A9, 'M', 'pa'), + (0x33AA, 'M', 'kpa'), + (0x33AB, 'M', 'mpa'), + (0x33AC, 'M', 'gpa'), + (0x33AD, 'M', 'rad'), + (0x33AE, 'M', 'rad∕s'), + (0x33AF, 'M', 'rad∕s2'), + (0x33B0, 'M', 'ps'), + (0x33B1, 'M', 'ns'), + (0x33B2, 'M', 'μs'), + (0x33B3, 'M', 'ms'), + (0x33B4, 'M', 'pv'), + (0x33B5, 'M', 'nv'), + (0x33B6, 'M', 'μv'), + (0x33B7, 'M', 'mv'), + (0x33B8, 'M', 'kv'), + (0x33B9, 'M', 'mv'), + (0x33BA, 'M', 'pw'), + (0x33BB, 'M', 'nw'), + (0x33BC, 'M', 'μw'), + (0x33BD, 'M', 'mw'), + (0x33BE, 'M', 'kw'), + (0x33BF, 'M', 'mw'), + (0x33C0, 'M', 'kω'), + (0x33C1, 'M', 'mω'), + (0x33C2, 'X'), + (0x33C3, 'M', 'bq'), + (0x33C4, 'M', 'cc'), + (0x33C5, 'M', 'cd'), + (0x33C6, 'M', 'c∕kg'), + (0x33C7, 'X'), + (0x33C8, 'M', 'db'), + (0x33C9, 'M', 'gy'), + (0x33CA, 'M', 'ha'), + (0x33CB, 'M', 'hp'), + (0x33CC, 'M', 'in'), + (0x33CD, 'M', 'kk'), + (0x33CE, 'M', 'km'), + (0x33CF, 'M', 'kt'), + (0x33D0, 'M', 'lm'), + (0x33D1, 'M', 'ln'), + (0x33D2, 'M', 'log'), + (0x33D3, 'M', 'lx'), + (0x33D4, 'M', 'mb'), + (0x33D5, 'M', 'mil'), + (0x33D6, 'M', 'mol'), + (0x33D7, 'M', 'ph'), + (0x33D8, 'X'), + (0x33D9, 'M', 'ppm'), + (0x33DA, 'M', 'pr'), + (0x33DB, 'M', 'sr'), + (0x33DC, 'M', 'sv'), + (0x33DD, 'M', 'wb'), ] - def _seg_35() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x33E2, "M", "3日"), - (0x33E3, "M", "4日"), - (0x33E4, "M", "5日"), - (0x33E5, "M", "6日"), - (0x33E6, "M", "7日"), - (0x33E7, "M", "8日"), - (0x33E8, "M", "9日"), - (0x33E9, "M", "10日"), - (0x33EA, "M", "11日"), - (0x33EB, "M", "12日"), - (0x33EC, "M", "13日"), - (0x33ED, "M", "14日"), - (0x33EE, "M", "15日"), - (0x33EF, "M", "16日"), - (0x33F0, "M", "17日"), - (0x33F1, "M", "18日"), - (0x33F2, "M", "19日"), - (0x33F3, "M", "20日"), - (0x33F4, "M", "21日"), - (0x33F5, "M", "22日"), - (0x33F6, "M", "23日"), - (0x33F7, "M", "24日"), - (0x33F8, "M", "25日"), - (0x33F9, "M", "26日"), - (0x33FA, "M", "27日"), - (0x33FB, "M", "28日"), - (0x33FC, "M", "29日"), - (0x33FD, "M", "30日"), - (0x33FE, "M", "31日"), - (0x33FF, "M", "gal"), - (0x3400, "V"), - (0xA48D, "X"), - (0xA490, "V"), - (0xA4C7, "X"), - (0xA4D0, "V"), - (0xA62C, "X"), - (0xA640, "M", "ꙁ"), - (0xA641, "V"), - (0xA642, "M", "ꙃ"), - (0xA643, "V"), - (0xA644, "M", "ꙅ"), - (0xA645, "V"), - (0xA646, "M", "ꙇ"), - (0xA647, "V"), - (0xA648, "M", "ꙉ"), - (0xA649, "V"), - (0xA64A, "M", "ꙋ"), - (0xA64B, "V"), - (0xA64C, "M", "ꙍ"), - (0xA64D, "V"), - (0xA64E, "M", "ꙏ"), - (0xA64F, "V"), - (0xA650, "M", "ꙑ"), - (0xA651, "V"), - (0xA652, "M", "ꙓ"), - (0xA653, "V"), - (0xA654, "M", "ꙕ"), - (0xA655, "V"), - (0xA656, "M", "ꙗ"), - (0xA657, "V"), - (0xA658, "M", "ꙙ"), - (0xA659, "V"), - (0xA65A, "M", "ꙛ"), - (0xA65B, "V"), - (0xA65C, "M", "ꙝ"), - (0xA65D, "V"), - (0xA65E, "M", "ꙟ"), - (0xA65F, "V"), - (0xA660, "M", "ꙡ"), - (0xA661, "V"), - (0xA662, "M", "ꙣ"), - (0xA663, "V"), - (0xA664, "M", "ꙥ"), - (0xA665, "V"), - (0xA666, "M", "ꙧ"), - (0xA667, "V"), - (0xA668, "M", "ꙩ"), - (0xA669, "V"), - (0xA66A, "M", "ꙫ"), - (0xA66B, "V"), - (0xA66C, "M", "ꙭ"), - (0xA66D, "V"), - (0xA680, "M", "ꚁ"), - (0xA681, "V"), - (0xA682, "M", "ꚃ"), - (0xA683, "V"), - (0xA684, "M", "ꚅ"), - (0xA685, "V"), - (0xA686, "M", "ꚇ"), - (0xA687, "V"), - (0xA688, "M", "ꚉ"), - (0xA689, "V"), - (0xA68A, "M", "ꚋ"), - (0xA68B, "V"), - (0xA68C, "M", "ꚍ"), - (0xA68D, "V"), - (0xA68E, "M", "ꚏ"), - (0xA68F, "V"), - (0xA690, "M", "ꚑ"), - (0xA691, "V"), + (0x33DE, 'M', 'v∕m'), + (0x33DF, 'M', 'a∕m'), + (0x33E0, 'M', '1日'), + (0x33E1, 'M', '2日'), + (0x33E2, 'M', '3日'), + (0x33E3, 'M', '4日'), + (0x33E4, 'M', '5日'), + (0x33E5, 'M', '6日'), + (0x33E6, 'M', '7日'), + (0x33E7, 'M', '8日'), + (0x33E8, 'M', '9日'), + (0x33E9, 'M', '10日'), + (0x33EA, 'M', '11日'), + (0x33EB, 'M', '12日'), + (0x33EC, 'M', '13日'), + (0x33ED, 'M', '14日'), + (0x33EE, 'M', '15日'), + (0x33EF, 'M', '16日'), + (0x33F0, 'M', '17日'), + (0x33F1, 'M', '18日'), + (0x33F2, 'M', '19日'), + (0x33F3, 'M', '20日'), + (0x33F4, 'M', '21日'), + (0x33F5, 'M', '22日'), + (0x33F6, 'M', '23日'), + (0x33F7, 'M', '24日'), + (0x33F8, 'M', '25日'), + (0x33F9, 'M', '26日'), + (0x33FA, 'M', '27日'), + (0x33FB, 'M', '28日'), + (0x33FC, 'M', '29日'), + (0x33FD, 'M', '30日'), + (0x33FE, 'M', '31日'), + (0x33FF, 'M', 'gal'), + (0x3400, 'V'), + (0xA48D, 'X'), + (0xA490, 'V'), + (0xA4C7, 'X'), + (0xA4D0, 'V'), + (0xA62C, 'X'), + (0xA640, 'M', 'ꙁ'), + (0xA641, 'V'), + (0xA642, 'M', 'ꙃ'), + (0xA643, 'V'), + (0xA644, 'M', 'ꙅ'), + (0xA645, 'V'), + (0xA646, 'M', 'ꙇ'), + (0xA647, 'V'), + (0xA648, 'M', 'ꙉ'), + (0xA649, 'V'), + (0xA64A, 'M', 'ꙋ'), + (0xA64B, 'V'), + (0xA64C, 'M', 'ꙍ'), + (0xA64D, 'V'), + (0xA64E, 'M', 'ꙏ'), + (0xA64F, 'V'), + (0xA650, 'M', 'ꙑ'), + (0xA651, 'V'), + (0xA652, 'M', 'ꙓ'), + (0xA653, 'V'), + (0xA654, 'M', 'ꙕ'), + (0xA655, 'V'), + (0xA656, 'M', 'ꙗ'), + (0xA657, 'V'), + (0xA658, 'M', 'ꙙ'), + (0xA659, 'V'), + (0xA65A, 'M', 'ꙛ'), + (0xA65B, 'V'), + (0xA65C, 'M', 'ꙝ'), + (0xA65D, 'V'), + (0xA65E, 'M', 'ꙟ'), + (0xA65F, 'V'), + (0xA660, 'M', 'ꙡ'), + (0xA661, 'V'), + (0xA662, 'M', 'ꙣ'), + (0xA663, 'V'), + (0xA664, 'M', 'ꙥ'), + (0xA665, 'V'), + (0xA666, 'M', 'ꙧ'), + (0xA667, 'V'), + (0xA668, 'M', 'ꙩ'), + (0xA669, 'V'), + (0xA66A, 'M', 'ꙫ'), + (0xA66B, 'V'), + (0xA66C, 'M', 'ꙭ'), + (0xA66D, 'V'), + (0xA680, 'M', 'ꚁ'), + (0xA681, 'V'), + (0xA682, 'M', 'ꚃ'), + (0xA683, 'V'), + (0xA684, 'M', 'ꚅ'), + (0xA685, 'V'), + (0xA686, 'M', 'ꚇ'), + (0xA687, 'V'), + (0xA688, 'M', 'ꚉ'), + (0xA689, 'V'), + (0xA68A, 'M', 'ꚋ'), + (0xA68B, 'V'), + (0xA68C, 'M', 'ꚍ'), + (0xA68D, 'V'), ] - def _seg_36() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0xA692, "M", "ꚓ"), - (0xA693, "V"), - (0xA694, "M", "ꚕ"), - (0xA695, "V"), - (0xA696, "M", "ꚗ"), - (0xA697, "V"), - (0xA698, "M", "ꚙ"), - (0xA699, "V"), - (0xA69A, "M", "ꚛ"), - (0xA69B, "V"), - (0xA69C, "M", "ъ"), - (0xA69D, "M", "ь"), - (0xA69E, "V"), - (0xA6F8, "X"), - (0xA700, "V"), - (0xA722, "M", "ꜣ"), - (0xA723, "V"), - (0xA724, "M", "ꜥ"), - (0xA725, "V"), - (0xA726, "M", "ꜧ"), - (0xA727, "V"), - (0xA728, "M", "ꜩ"), - (0xA729, "V"), - (0xA72A, "M", "ꜫ"), - (0xA72B, "V"), - (0xA72C, "M", "ꜭ"), - (0xA72D, "V"), - (0xA72E, "M", "ꜯ"), - (0xA72F, "V"), - (0xA732, "M", "ꜳ"), - (0xA733, "V"), - (0xA734, "M", "ꜵ"), - (0xA735, "V"), - (0xA736, "M", "ꜷ"), - (0xA737, "V"), - (0xA738, "M", "ꜹ"), - (0xA739, "V"), - (0xA73A, "M", "ꜻ"), - (0xA73B, "V"), - (0xA73C, "M", "ꜽ"), - (0xA73D, "V"), - (0xA73E, "M", "ꜿ"), - (0xA73F, "V"), - (0xA740, "M", "ꝁ"), - (0xA741, "V"), - (0xA742, "M", "ꝃ"), - (0xA743, "V"), - (0xA744, "M", "ꝅ"), - (0xA745, "V"), - (0xA746, "M", "ꝇ"), - (0xA747, "V"), - (0xA748, "M", "ꝉ"), - (0xA749, "V"), - (0xA74A, "M", "ꝋ"), - (0xA74B, "V"), - (0xA74C, "M", "ꝍ"), - (0xA74D, "V"), - (0xA74E, "M", "ꝏ"), - (0xA74F, "V"), - (0xA750, "M", "ꝑ"), - (0xA751, "V"), - (0xA752, "M", "ꝓ"), - (0xA753, "V"), - (0xA754, "M", "ꝕ"), - (0xA755, "V"), - (0xA756, "M", "ꝗ"), - (0xA757, "V"), - (0xA758, "M", "ꝙ"), - (0xA759, "V"), - (0xA75A, "M", "ꝛ"), - (0xA75B, "V"), - (0xA75C, "M", "ꝝ"), - (0xA75D, "V"), - (0xA75E, "M", "ꝟ"), - (0xA75F, "V"), - (0xA760, "M", "ꝡ"), - (0xA761, "V"), - (0xA762, "M", "ꝣ"), - (0xA763, "V"), - (0xA764, "M", "ꝥ"), - (0xA765, "V"), - (0xA766, "M", "ꝧ"), - (0xA767, "V"), - (0xA768, "M", "ꝩ"), - (0xA769, "V"), - (0xA76A, "M", "ꝫ"), - (0xA76B, "V"), - (0xA76C, "M", "ꝭ"), - (0xA76D, "V"), - (0xA76E, "M", "ꝯ"), - (0xA76F, "V"), - (0xA770, "M", "ꝯ"), - (0xA771, "V"), - (0xA779, "M", "ꝺ"), - (0xA77A, "V"), - (0xA77B, "M", "ꝼ"), - (0xA77C, "V"), - (0xA77D, "M", "ᵹ"), - (0xA77E, "M", "ꝿ"), - (0xA77F, "V"), + (0xA68E, 'M', 'ꚏ'), + (0xA68F, 'V'), + (0xA690, 'M', 'ꚑ'), + (0xA691, 'V'), + (0xA692, 'M', 'ꚓ'), + (0xA693, 'V'), + (0xA694, 'M', 'ꚕ'), + (0xA695, 'V'), + (0xA696, 'M', 'ꚗ'), + (0xA697, 'V'), + (0xA698, 'M', 'ꚙ'), + (0xA699, 'V'), + (0xA69A, 'M', 'ꚛ'), + (0xA69B, 'V'), + (0xA69C, 'M', 'ъ'), + (0xA69D, 'M', 'ь'), + (0xA69E, 'V'), + (0xA6F8, 'X'), + (0xA700, 'V'), + (0xA722, 'M', 'ꜣ'), + (0xA723, 'V'), + (0xA724, 'M', 'ꜥ'), + (0xA725, 'V'), + (0xA726, 'M', 'ꜧ'), + (0xA727, 'V'), + (0xA728, 'M', 'ꜩ'), + (0xA729, 'V'), + (0xA72A, 'M', 'ꜫ'), + (0xA72B, 'V'), + (0xA72C, 'M', 'ꜭ'), + (0xA72D, 'V'), + (0xA72E, 'M', 'ꜯ'), + (0xA72F, 'V'), + (0xA732, 'M', 'ꜳ'), + (0xA733, 'V'), + (0xA734, 'M', 'ꜵ'), + (0xA735, 'V'), + (0xA736, 'M', 'ꜷ'), + (0xA737, 'V'), + (0xA738, 'M', 'ꜹ'), + (0xA739, 'V'), + (0xA73A, 'M', 'ꜻ'), + (0xA73B, 'V'), + (0xA73C, 'M', 'ꜽ'), + (0xA73D, 'V'), + (0xA73E, 'M', 'ꜿ'), + (0xA73F, 'V'), + (0xA740, 'M', 'ꝁ'), + (0xA741, 'V'), + (0xA742, 'M', 'ꝃ'), + (0xA743, 'V'), + (0xA744, 'M', 'ꝅ'), + (0xA745, 'V'), + (0xA746, 'M', 'ꝇ'), + (0xA747, 'V'), + (0xA748, 'M', 'ꝉ'), + (0xA749, 'V'), + (0xA74A, 'M', 'ꝋ'), + (0xA74B, 'V'), + (0xA74C, 'M', 'ꝍ'), + (0xA74D, 'V'), + (0xA74E, 'M', 'ꝏ'), + (0xA74F, 'V'), + (0xA750, 'M', 'ꝑ'), + (0xA751, 'V'), + (0xA752, 'M', 'ꝓ'), + (0xA753, 'V'), + (0xA754, 'M', 'ꝕ'), + (0xA755, 'V'), + (0xA756, 'M', 'ꝗ'), + (0xA757, 'V'), + (0xA758, 'M', 'ꝙ'), + (0xA759, 'V'), + (0xA75A, 'M', 'ꝛ'), + (0xA75B, 'V'), + (0xA75C, 'M', 'ꝝ'), + (0xA75D, 'V'), + (0xA75E, 'M', 'ꝟ'), + (0xA75F, 'V'), + (0xA760, 'M', 'ꝡ'), + (0xA761, 'V'), + (0xA762, 'M', 'ꝣ'), + (0xA763, 'V'), + (0xA764, 'M', 'ꝥ'), + (0xA765, 'V'), + (0xA766, 'M', 'ꝧ'), + (0xA767, 'V'), + (0xA768, 'M', 'ꝩ'), + (0xA769, 'V'), + (0xA76A, 'M', 'ꝫ'), + (0xA76B, 'V'), + (0xA76C, 'M', 'ꝭ'), + (0xA76D, 'V'), + (0xA76E, 'M', 'ꝯ'), + (0xA76F, 'V'), + (0xA770, 'M', 'ꝯ'), + (0xA771, 'V'), + (0xA779, 'M', 'ꝺ'), + (0xA77A, 'V'), + (0xA77B, 'M', 'ꝼ'), ] - def _seg_37() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0xA780, "M", "ꞁ"), - (0xA781, "V"), - (0xA782, "M", "ꞃ"), - (0xA783, "V"), - (0xA784, "M", "ꞅ"), - (0xA785, "V"), - (0xA786, "M", "ꞇ"), - (0xA787, "V"), - (0xA78B, "M", "ꞌ"), - (0xA78C, "V"), - (0xA78D, "M", "ɥ"), - (0xA78E, "V"), - (0xA790, "M", "ꞑ"), - (0xA791, "V"), - (0xA792, "M", "ꞓ"), - (0xA793, "V"), - (0xA796, "M", "ꞗ"), - (0xA797, "V"), - (0xA798, "M", "ꞙ"), - (0xA799, "V"), - (0xA79A, "M", "ꞛ"), - (0xA79B, "V"), - (0xA79C, "M", "ꞝ"), - (0xA79D, "V"), - (0xA79E, "M", "ꞟ"), - (0xA79F, "V"), - (0xA7A0, "M", "ꞡ"), - (0xA7A1, "V"), - (0xA7A2, "M", "ꞣ"), - (0xA7A3, "V"), - (0xA7A4, "M", "ꞥ"), - (0xA7A5, "V"), - (0xA7A6, "M", "ꞧ"), - (0xA7A7, "V"), - (0xA7A8, "M", "ꞩ"), - (0xA7A9, "V"), - (0xA7AA, "M", "ɦ"), - (0xA7AB, "M", "ɜ"), - (0xA7AC, "M", "ɡ"), - (0xA7AD, "M", "ɬ"), - (0xA7AE, "M", "ɪ"), - (0xA7AF, "V"), - (0xA7B0, "M", "ʞ"), - (0xA7B1, "M", "ʇ"), - (0xA7B2, "M", "ʝ"), - (0xA7B3, "M", "ꭓ"), - (0xA7B4, "M", "ꞵ"), - (0xA7B5, "V"), - (0xA7B6, "M", "ꞷ"), - (0xA7B7, "V"), - (0xA7B8, "M", "ꞹ"), - (0xA7B9, "V"), - (0xA7BA, "M", "ꞻ"), - (0xA7BB, "V"), - (0xA7BC, "M", "ꞽ"), - (0xA7BD, "V"), - (0xA7BE, "M", "ꞿ"), - (0xA7BF, "V"), - (0xA7C0, "M", "ꟁ"), - (0xA7C1, "V"), - (0xA7C2, "M", "ꟃ"), - (0xA7C3, "V"), - (0xA7C4, "M", "ꞔ"), - (0xA7C5, "M", "ʂ"), - (0xA7C6, "M", "ᶎ"), - (0xA7C7, "M", "ꟈ"), - (0xA7C8, "V"), - (0xA7C9, "M", "ꟊ"), - (0xA7CA, "V"), - (0xA7CB, "X"), - (0xA7D0, "M", "ꟑ"), - (0xA7D1, "V"), - (0xA7D2, "X"), - (0xA7D3, "V"), - (0xA7D4, "X"), - (0xA7D5, "V"), - (0xA7D6, "M", "ꟗ"), - (0xA7D7, "V"), - (0xA7D8, "M", "ꟙ"), - (0xA7D9, "V"), - (0xA7DA, "X"), - (0xA7F2, "M", "c"), - (0xA7F3, "M", "f"), - (0xA7F4, "M", "q"), - (0xA7F5, "M", "ꟶ"), - (0xA7F6, "V"), - (0xA7F8, "M", "ħ"), - (0xA7F9, "M", "œ"), - (0xA7FA, "V"), - (0xA82D, "X"), - (0xA830, "V"), - (0xA83A, "X"), - (0xA840, "V"), - (0xA878, "X"), - (0xA880, "V"), - (0xA8C6, "X"), - (0xA8CE, "V"), - (0xA8DA, "X"), - (0xA8E0, "V"), - (0xA954, "X"), + (0xA77C, 'V'), + (0xA77D, 'M', 'ᵹ'), + (0xA77E, 'M', 'ꝿ'), + (0xA77F, 'V'), + (0xA780, 'M', 'ꞁ'), + (0xA781, 'V'), + (0xA782, 'M', 'ꞃ'), + (0xA783, 'V'), + (0xA784, 'M', 'ꞅ'), + (0xA785, 'V'), + (0xA786, 'M', 'ꞇ'), + (0xA787, 'V'), + (0xA78B, 'M', 'ꞌ'), + (0xA78C, 'V'), + (0xA78D, 'M', 'ɥ'), + (0xA78E, 'V'), + (0xA790, 'M', 'ꞑ'), + (0xA791, 'V'), + (0xA792, 'M', 'ꞓ'), + (0xA793, 'V'), + (0xA796, 'M', 'ꞗ'), + (0xA797, 'V'), + (0xA798, 'M', 'ꞙ'), + (0xA799, 'V'), + (0xA79A, 'M', 'ꞛ'), + (0xA79B, 'V'), + (0xA79C, 'M', 'ꞝ'), + (0xA79D, 'V'), + (0xA79E, 'M', 'ꞟ'), + (0xA79F, 'V'), + (0xA7A0, 'M', 'ꞡ'), + (0xA7A1, 'V'), + (0xA7A2, 'M', 'ꞣ'), + (0xA7A3, 'V'), + (0xA7A4, 'M', 'ꞥ'), + (0xA7A5, 'V'), + (0xA7A6, 'M', 'ꞧ'), + (0xA7A7, 'V'), + (0xA7A8, 'M', 'ꞩ'), + (0xA7A9, 'V'), + (0xA7AA, 'M', 'ɦ'), + (0xA7AB, 'M', 'ɜ'), + (0xA7AC, 'M', 'ɡ'), + (0xA7AD, 'M', 'ɬ'), + (0xA7AE, 'M', 'ɪ'), + (0xA7AF, 'V'), + (0xA7B0, 'M', 'ʞ'), + (0xA7B1, 'M', 'ʇ'), + (0xA7B2, 'M', 'ʝ'), + (0xA7B3, 'M', 'ꭓ'), + (0xA7B4, 'M', 'ꞵ'), + (0xA7B5, 'V'), + (0xA7B6, 'M', 'ꞷ'), + (0xA7B7, 'V'), + (0xA7B8, 'M', 'ꞹ'), + (0xA7B9, 'V'), + (0xA7BA, 'M', 'ꞻ'), + (0xA7BB, 'V'), + (0xA7BC, 'M', 'ꞽ'), + (0xA7BD, 'V'), + (0xA7BE, 'M', 'ꞿ'), + (0xA7BF, 'V'), + (0xA7C0, 'M', 'ꟁ'), + (0xA7C1, 'V'), + (0xA7C2, 'M', 'ꟃ'), + (0xA7C3, 'V'), + (0xA7C4, 'M', 'ꞔ'), + (0xA7C5, 'M', 'ʂ'), + (0xA7C6, 'M', 'ᶎ'), + (0xA7C7, 'M', 'ꟈ'), + (0xA7C8, 'V'), + (0xA7C9, 'M', 'ꟊ'), + (0xA7CA, 'V'), + (0xA7CB, 'X'), + (0xA7D0, 'M', 'ꟑ'), + (0xA7D1, 'V'), + (0xA7D2, 'X'), + (0xA7D3, 'V'), + (0xA7D4, 'X'), + (0xA7D5, 'V'), + (0xA7D6, 'M', 'ꟗ'), + (0xA7D7, 'V'), + (0xA7D8, 'M', 'ꟙ'), + (0xA7D9, 'V'), + (0xA7DA, 'X'), + (0xA7F2, 'M', 'c'), + (0xA7F3, 'M', 'f'), + (0xA7F4, 'M', 'q'), + (0xA7F5, 'M', 'ꟶ'), + (0xA7F6, 'V'), + (0xA7F8, 'M', 'ħ'), + (0xA7F9, 'M', 'œ'), + (0xA7FA, 'V'), + (0xA82D, 'X'), + (0xA830, 'V'), + (0xA83A, 'X'), + (0xA840, 'V'), + (0xA878, 'X'), + (0xA880, 'V'), + (0xA8C6, 'X'), ] - def _seg_38() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0xA95F, "V"), - (0xA97D, "X"), - (0xA980, "V"), - (0xA9CE, "X"), - (0xA9CF, "V"), - (0xA9DA, "X"), - (0xA9DE, "V"), - (0xA9FF, "X"), - (0xAA00, "V"), - (0xAA37, "X"), - (0xAA40, "V"), - (0xAA4E, "X"), - (0xAA50, "V"), - (0xAA5A, "X"), - (0xAA5C, "V"), - (0xAAC3, "X"), - (0xAADB, "V"), - (0xAAF7, "X"), - (0xAB01, "V"), - (0xAB07, "X"), - (0xAB09, "V"), - (0xAB0F, "X"), - (0xAB11, "V"), - (0xAB17, "X"), - (0xAB20, "V"), - (0xAB27, "X"), - (0xAB28, "V"), - (0xAB2F, "X"), - (0xAB30, "V"), - (0xAB5C, "M", "ꜧ"), - (0xAB5D, "M", "ꬷ"), - (0xAB5E, "M", "ɫ"), - (0xAB5F, "M", "ꭒ"), - (0xAB60, "V"), - (0xAB69, "M", "ʍ"), - (0xAB6A, "V"), - (0xAB6C, "X"), - (0xAB70, "M", "Ꭰ"), - (0xAB71, "M", "Ꭱ"), - (0xAB72, "M", "Ꭲ"), - (0xAB73, "M", "Ꭳ"), - (0xAB74, "M", "Ꭴ"), - (0xAB75, "M", "Ꭵ"), - (0xAB76, "M", "Ꭶ"), - (0xAB77, "M", "Ꭷ"), - (0xAB78, "M", "Ꭸ"), - (0xAB79, "M", "Ꭹ"), - (0xAB7A, "M", "Ꭺ"), - (0xAB7B, "M", "Ꭻ"), - (0xAB7C, "M", "Ꭼ"), - (0xAB7D, "M", "Ꭽ"), - (0xAB7E, "M", "Ꭾ"), - (0xAB7F, "M", "Ꭿ"), - (0xAB80, "M", "Ꮀ"), - (0xAB81, "M", "Ꮁ"), - (0xAB82, "M", "Ꮂ"), - (0xAB83, "M", "Ꮃ"), - (0xAB84, "M", "Ꮄ"), - (0xAB85, "M", "Ꮅ"), - (0xAB86, "M", "Ꮆ"), - (0xAB87, "M", "Ꮇ"), - (0xAB88, "M", "Ꮈ"), - (0xAB89, "M", "Ꮉ"), - (0xAB8A, "M", "Ꮊ"), - (0xAB8B, "M", "Ꮋ"), - (0xAB8C, "M", "Ꮌ"), - (0xAB8D, "M", "Ꮍ"), - (0xAB8E, "M", "Ꮎ"), - (0xAB8F, "M", "Ꮏ"), - (0xAB90, "M", "Ꮐ"), - (0xAB91, "M", "Ꮑ"), - (0xAB92, "M", "Ꮒ"), - (0xAB93, "M", "Ꮓ"), - (0xAB94, "M", "Ꮔ"), - (0xAB95, "M", "Ꮕ"), - (0xAB96, "M", "Ꮖ"), - (0xAB97, "M", "Ꮗ"), - (0xAB98, "M", "Ꮘ"), - (0xAB99, "M", "Ꮙ"), - (0xAB9A, "M", "Ꮚ"), - (0xAB9B, "M", "Ꮛ"), - (0xAB9C, "M", "Ꮜ"), - (0xAB9D, "M", "Ꮝ"), - (0xAB9E, "M", "Ꮞ"), - (0xAB9F, "M", "Ꮟ"), - (0xABA0, "M", "Ꮠ"), - (0xABA1, "M", "Ꮡ"), - (0xABA2, "M", "Ꮢ"), - (0xABA3, "M", "Ꮣ"), - (0xABA4, "M", "Ꮤ"), - (0xABA5, "M", "Ꮥ"), - (0xABA6, "M", "Ꮦ"), - (0xABA7, "M", "Ꮧ"), - (0xABA8, "M", "Ꮨ"), - (0xABA9, "M", "Ꮩ"), - (0xABAA, "M", "Ꮪ"), - (0xABAB, "M", "Ꮫ"), - (0xABAC, "M", "Ꮬ"), - (0xABAD, "M", "Ꮭ"), - (0xABAE, "M", "Ꮮ"), + (0xA8CE, 'V'), + (0xA8DA, 'X'), + (0xA8E0, 'V'), + (0xA954, 'X'), + (0xA95F, 'V'), + (0xA97D, 'X'), + (0xA980, 'V'), + (0xA9CE, 'X'), + (0xA9CF, 'V'), + (0xA9DA, 'X'), + (0xA9DE, 'V'), + (0xA9FF, 'X'), + (0xAA00, 'V'), + (0xAA37, 'X'), + (0xAA40, 'V'), + (0xAA4E, 'X'), + (0xAA50, 'V'), + (0xAA5A, 'X'), + (0xAA5C, 'V'), + (0xAAC3, 'X'), + (0xAADB, 'V'), + (0xAAF7, 'X'), + (0xAB01, 'V'), + (0xAB07, 'X'), + (0xAB09, 'V'), + (0xAB0F, 'X'), + (0xAB11, 'V'), + (0xAB17, 'X'), + (0xAB20, 'V'), + (0xAB27, 'X'), + (0xAB28, 'V'), + (0xAB2F, 'X'), + (0xAB30, 'V'), + (0xAB5C, 'M', 'ꜧ'), + (0xAB5D, 'M', 'ꬷ'), + (0xAB5E, 'M', 'ɫ'), + (0xAB5F, 'M', 'ꭒ'), + (0xAB60, 'V'), + (0xAB69, 'M', 'ʍ'), + (0xAB6A, 'V'), + (0xAB6C, 'X'), + (0xAB70, 'M', 'Ꭰ'), + (0xAB71, 'M', 'Ꭱ'), + (0xAB72, 'M', 'Ꭲ'), + (0xAB73, 'M', 'Ꭳ'), + (0xAB74, 'M', 'Ꭴ'), + (0xAB75, 'M', 'Ꭵ'), + (0xAB76, 'M', 'Ꭶ'), + (0xAB77, 'M', 'Ꭷ'), + (0xAB78, 'M', 'Ꭸ'), + (0xAB79, 'M', 'Ꭹ'), + (0xAB7A, 'M', 'Ꭺ'), + (0xAB7B, 'M', 'Ꭻ'), + (0xAB7C, 'M', 'Ꭼ'), + (0xAB7D, 'M', 'Ꭽ'), + (0xAB7E, 'M', 'Ꭾ'), + (0xAB7F, 'M', 'Ꭿ'), + (0xAB80, 'M', 'Ꮀ'), + (0xAB81, 'M', 'Ꮁ'), + (0xAB82, 'M', 'Ꮂ'), + (0xAB83, 'M', 'Ꮃ'), + (0xAB84, 'M', 'Ꮄ'), + (0xAB85, 'M', 'Ꮅ'), + (0xAB86, 'M', 'Ꮆ'), + (0xAB87, 'M', 'Ꮇ'), + (0xAB88, 'M', 'Ꮈ'), + (0xAB89, 'M', 'Ꮉ'), + (0xAB8A, 'M', 'Ꮊ'), + (0xAB8B, 'M', 'Ꮋ'), + (0xAB8C, 'M', 'Ꮌ'), + (0xAB8D, 'M', 'Ꮍ'), + (0xAB8E, 'M', 'Ꮎ'), + (0xAB8F, 'M', 'Ꮏ'), + (0xAB90, 'M', 'Ꮐ'), + (0xAB91, 'M', 'Ꮑ'), + (0xAB92, 'M', 'Ꮒ'), + (0xAB93, 'M', 'Ꮓ'), + (0xAB94, 'M', 'Ꮔ'), + (0xAB95, 'M', 'Ꮕ'), + (0xAB96, 'M', 'Ꮖ'), + (0xAB97, 'M', 'Ꮗ'), + (0xAB98, 'M', 'Ꮘ'), + (0xAB99, 'M', 'Ꮙ'), + (0xAB9A, 'M', 'Ꮚ'), + (0xAB9B, 'M', 'Ꮛ'), + (0xAB9C, 'M', 'Ꮜ'), + (0xAB9D, 'M', 'Ꮝ'), + (0xAB9E, 'M', 'Ꮞ'), + (0xAB9F, 'M', 'Ꮟ'), + (0xABA0, 'M', 'Ꮠ'), + (0xABA1, 'M', 'Ꮡ'), + (0xABA2, 'M', 'Ꮢ'), + (0xABA3, 'M', 'Ꮣ'), + (0xABA4, 'M', 'Ꮤ'), + (0xABA5, 'M', 'Ꮥ'), + (0xABA6, 'M', 'Ꮦ'), + (0xABA7, 'M', 'Ꮧ'), + (0xABA8, 'M', 'Ꮨ'), + (0xABA9, 'M', 'Ꮩ'), + (0xABAA, 'M', 'Ꮪ'), ] - def _seg_39() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0xABAF, "M", "Ꮯ"), - (0xABB0, "M", "Ꮰ"), - (0xABB1, "M", "Ꮱ"), - (0xABB2, "M", "Ꮲ"), - (0xABB3, "M", "Ꮳ"), - (0xABB4, "M", "Ꮴ"), - (0xABB5, "M", "Ꮵ"), - (0xABB6, "M", "Ꮶ"), - (0xABB7, "M", "Ꮷ"), - (0xABB8, "M", "Ꮸ"), - (0xABB9, "M", "Ꮹ"), - (0xABBA, "M", "Ꮺ"), - (0xABBB, "M", "Ꮻ"), - (0xABBC, "M", "Ꮼ"), - (0xABBD, "M", "Ꮽ"), - (0xABBE, "M", "Ꮾ"), - (0xABBF, "M", "Ꮿ"), - (0xABC0, "V"), - (0xABEE, "X"), - (0xABF0, "V"), - (0xABFA, "X"), - (0xAC00, "V"), - (0xD7A4, "X"), - (0xD7B0, "V"), - (0xD7C7, "X"), - (0xD7CB, "V"), - (0xD7FC, "X"), - (0xF900, "M", "豈"), - (0xF901, "M", "更"), - (0xF902, "M", "車"), - (0xF903, "M", "賈"), - (0xF904, "M", "滑"), - (0xF905, "M", "串"), - (0xF906, "M", "句"), - (0xF907, "M", "龜"), - (0xF909, "M", "契"), - (0xF90A, "M", "金"), - (0xF90B, "M", "喇"), - (0xF90C, "M", "奈"), - (0xF90D, "M", "懶"), - (0xF90E, "M", "癩"), - (0xF90F, "M", "羅"), - (0xF910, "M", "蘿"), - (0xF911, "M", "螺"), - (0xF912, "M", "裸"), - (0xF913, "M", "邏"), - (0xF914, "M", "樂"), - (0xF915, "M", "洛"), - (0xF916, "M", "烙"), - (0xF917, "M", "珞"), - (0xF918, "M", "落"), - (0xF919, "M", "酪"), - (0xF91A, "M", "駱"), - (0xF91B, "M", "亂"), - (0xF91C, "M", "卵"), - (0xF91D, "M", "欄"), - (0xF91E, "M", "爛"), - (0xF91F, "M", "蘭"), - (0xF920, "M", "鸞"), - (0xF921, "M", "嵐"), - (0xF922, "M", "濫"), - (0xF923, "M", "藍"), - (0xF924, "M", "襤"), - (0xF925, "M", "拉"), - (0xF926, "M", "臘"), - (0xF927, "M", "蠟"), - (0xF928, "M", "廊"), - (0xF929, "M", "朗"), - (0xF92A, "M", "浪"), - (0xF92B, "M", "狼"), - (0xF92C, "M", "郎"), - (0xF92D, "M", "來"), - (0xF92E, "M", "冷"), - (0xF92F, "M", "勞"), - (0xF930, "M", "擄"), - (0xF931, "M", "櫓"), - (0xF932, "M", "爐"), - (0xF933, "M", "盧"), - (0xF934, "M", "老"), - (0xF935, "M", "蘆"), - (0xF936, "M", "虜"), - (0xF937, "M", "路"), - (0xF938, "M", "露"), - (0xF939, "M", "魯"), - (0xF93A, "M", "鷺"), - (0xF93B, "M", "碌"), - (0xF93C, "M", "祿"), - (0xF93D, "M", "綠"), - (0xF93E, "M", "菉"), - (0xF93F, "M", "錄"), - (0xF940, "M", "鹿"), - (0xF941, "M", "論"), - (0xF942, "M", "壟"), - (0xF943, "M", "弄"), - (0xF944, "M", "籠"), - (0xF945, "M", "聾"), - (0xF946, "M", "牢"), - (0xF947, "M", "磊"), - (0xF948, "M", "賂"), - (0xF949, "M", "雷"), + (0xABAB, 'M', 'Ꮫ'), + (0xABAC, 'M', 'Ꮬ'), + (0xABAD, 'M', 'Ꮭ'), + (0xABAE, 'M', 'Ꮮ'), + (0xABAF, 'M', 'Ꮯ'), + (0xABB0, 'M', 'Ꮰ'), + (0xABB1, 'M', 'Ꮱ'), + (0xABB2, 'M', 'Ꮲ'), + (0xABB3, 'M', 'Ꮳ'), + (0xABB4, 'M', 'Ꮴ'), + (0xABB5, 'M', 'Ꮵ'), + (0xABB6, 'M', 'Ꮶ'), + (0xABB7, 'M', 'Ꮷ'), + (0xABB8, 'M', 'Ꮸ'), + (0xABB9, 'M', 'Ꮹ'), + (0xABBA, 'M', 'Ꮺ'), + (0xABBB, 'M', 'Ꮻ'), + (0xABBC, 'M', 'Ꮼ'), + (0xABBD, 'M', 'Ꮽ'), + (0xABBE, 'M', 'Ꮾ'), + (0xABBF, 'M', 'Ꮿ'), + (0xABC0, 'V'), + (0xABEE, 'X'), + (0xABF0, 'V'), + (0xABFA, 'X'), + (0xAC00, 'V'), + (0xD7A4, 'X'), + (0xD7B0, 'V'), + (0xD7C7, 'X'), + (0xD7CB, 'V'), + (0xD7FC, 'X'), + (0xF900, 'M', '豈'), + (0xF901, 'M', '更'), + (0xF902, 'M', '車'), + (0xF903, 'M', '賈'), + (0xF904, 'M', '滑'), + (0xF905, 'M', '串'), + (0xF906, 'M', '句'), + (0xF907, 'M', '龜'), + (0xF909, 'M', '契'), + (0xF90A, 'M', '金'), + (0xF90B, 'M', '喇'), + (0xF90C, 'M', '奈'), + (0xF90D, 'M', '懶'), + (0xF90E, 'M', '癩'), + (0xF90F, 'M', '羅'), + (0xF910, 'M', '蘿'), + (0xF911, 'M', '螺'), + (0xF912, 'M', '裸'), + (0xF913, 'M', '邏'), + (0xF914, 'M', '樂'), + (0xF915, 'M', '洛'), + (0xF916, 'M', '烙'), + (0xF917, 'M', '珞'), + (0xF918, 'M', '落'), + (0xF919, 'M', '酪'), + (0xF91A, 'M', '駱'), + (0xF91B, 'M', '亂'), + (0xF91C, 'M', '卵'), + (0xF91D, 'M', '欄'), + (0xF91E, 'M', '爛'), + (0xF91F, 'M', '蘭'), + (0xF920, 'M', '鸞'), + (0xF921, 'M', '嵐'), + (0xF922, 'M', '濫'), + (0xF923, 'M', '藍'), + (0xF924, 'M', '襤'), + (0xF925, 'M', '拉'), + (0xF926, 'M', '臘'), + (0xF927, 'M', '蠟'), + (0xF928, 'M', '廊'), + (0xF929, 'M', '朗'), + (0xF92A, 'M', '浪'), + (0xF92B, 'M', '狼'), + (0xF92C, 'M', '郎'), + (0xF92D, 'M', '來'), + (0xF92E, 'M', '冷'), + (0xF92F, 'M', '勞'), + (0xF930, 'M', '擄'), + (0xF931, 'M', '櫓'), + (0xF932, 'M', '爐'), + (0xF933, 'M', '盧'), + (0xF934, 'M', '老'), + (0xF935, 'M', '蘆'), + (0xF936, 'M', '虜'), + (0xF937, 'M', '路'), + (0xF938, 'M', '露'), + (0xF939, 'M', '魯'), + (0xF93A, 'M', '鷺'), + (0xF93B, 'M', '碌'), + (0xF93C, 'M', '祿'), + (0xF93D, 'M', '綠'), + (0xF93E, 'M', '菉'), + (0xF93F, 'M', '錄'), + (0xF940, 'M', '鹿'), + (0xF941, 'M', '論'), + (0xF942, 'M', '壟'), + (0xF943, 'M', '弄'), + (0xF944, 'M', '籠'), + (0xF945, 'M', '聾'), ] - def _seg_40() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0xF94A, "M", "壘"), - (0xF94B, "M", "屢"), - (0xF94C, "M", "樓"), - (0xF94D, "M", "淚"), - (0xF94E, "M", "漏"), - (0xF94F, "M", "累"), - (0xF950, "M", "縷"), - (0xF951, "M", "陋"), - (0xF952, "M", "勒"), - (0xF953, "M", "肋"), - (0xF954, "M", "凜"), - (0xF955, "M", "凌"), - (0xF956, "M", "稜"), - (0xF957, "M", "綾"), - (0xF958, "M", "菱"), - (0xF959, "M", "陵"), - (0xF95A, "M", "讀"), - (0xF95B, "M", "拏"), - (0xF95C, "M", "樂"), - (0xF95D, "M", "諾"), - (0xF95E, "M", "丹"), - (0xF95F, "M", "寧"), - (0xF960, "M", "怒"), - (0xF961, "M", "率"), - (0xF962, "M", "異"), - (0xF963, "M", "北"), - (0xF964, "M", "磻"), - (0xF965, "M", "便"), - (0xF966, "M", "復"), - (0xF967, "M", "不"), - (0xF968, "M", "泌"), - (0xF969, "M", "數"), - (0xF96A, "M", "索"), - (0xF96B, "M", "參"), - (0xF96C, "M", "塞"), - (0xF96D, "M", "省"), - (0xF96E, "M", "葉"), - (0xF96F, "M", "說"), - (0xF970, "M", "殺"), - (0xF971, "M", "辰"), - (0xF972, "M", "沈"), - (0xF973, "M", "拾"), - (0xF974, "M", "若"), - (0xF975, "M", "掠"), - (0xF976, "M", "略"), - (0xF977, "M", "亮"), - (0xF978, "M", "兩"), - (0xF979, "M", "凉"), - (0xF97A, "M", "梁"), - (0xF97B, "M", "糧"), - (0xF97C, "M", "良"), - (0xF97D, "M", "諒"), - (0xF97E, "M", "量"), - (0xF97F, "M", "勵"), - (0xF980, "M", "呂"), - (0xF981, "M", "女"), - (0xF982, "M", "廬"), - (0xF983, "M", "旅"), - (0xF984, "M", "濾"), - (0xF985, "M", "礪"), - (0xF986, "M", "閭"), - (0xF987, "M", "驪"), - (0xF988, "M", "麗"), - (0xF989, "M", "黎"), - (0xF98A, "M", "力"), - (0xF98B, "M", "曆"), - (0xF98C, "M", "歷"), - (0xF98D, "M", "轢"), - (0xF98E, "M", "年"), - (0xF98F, "M", "憐"), - (0xF990, "M", "戀"), - (0xF991, "M", "撚"), - (0xF992, "M", "漣"), - (0xF993, "M", "煉"), - (0xF994, "M", "璉"), - (0xF995, "M", "秊"), - (0xF996, "M", "練"), - (0xF997, "M", "聯"), - (0xF998, "M", "輦"), - (0xF999, "M", "蓮"), - (0xF99A, "M", "連"), - (0xF99B, "M", "鍊"), - (0xF99C, "M", "列"), - (0xF99D, "M", "劣"), - (0xF99E, "M", "咽"), - (0xF99F, "M", "烈"), - (0xF9A0, "M", "裂"), - (0xF9A1, "M", "說"), - (0xF9A2, "M", "廉"), - (0xF9A3, "M", "念"), - (0xF9A4, "M", "捻"), - (0xF9A5, "M", "殮"), - (0xF9A6, "M", "簾"), - (0xF9A7, "M", "獵"), - (0xF9A8, "M", "令"), - (0xF9A9, "M", "囹"), - (0xF9AA, "M", "寧"), - (0xF9AB, "M", "嶺"), - (0xF9AC, "M", "怜"), - (0xF9AD, "M", "玲"), + (0xF946, 'M', '牢'), + (0xF947, 'M', '磊'), + (0xF948, 'M', '賂'), + (0xF949, 'M', '雷'), + (0xF94A, 'M', '壘'), + (0xF94B, 'M', '屢'), + (0xF94C, 'M', '樓'), + (0xF94D, 'M', '淚'), + (0xF94E, 'M', '漏'), + (0xF94F, 'M', '累'), + (0xF950, 'M', '縷'), + (0xF951, 'M', '陋'), + (0xF952, 'M', '勒'), + (0xF953, 'M', '肋'), + (0xF954, 'M', '凜'), + (0xF955, 'M', '凌'), + (0xF956, 'M', '稜'), + (0xF957, 'M', '綾'), + (0xF958, 'M', '菱'), + (0xF959, 'M', '陵'), + (0xF95A, 'M', '讀'), + (0xF95B, 'M', '拏'), + (0xF95C, 'M', '樂'), + (0xF95D, 'M', '諾'), + (0xF95E, 'M', '丹'), + (0xF95F, 'M', '寧'), + (0xF960, 'M', '怒'), + (0xF961, 'M', '率'), + (0xF962, 'M', '異'), + (0xF963, 'M', '北'), + (0xF964, 'M', '磻'), + (0xF965, 'M', '便'), + (0xF966, 'M', '復'), + (0xF967, 'M', '不'), + (0xF968, 'M', '泌'), + (0xF969, 'M', '數'), + (0xF96A, 'M', '索'), + (0xF96B, 'M', '參'), + (0xF96C, 'M', '塞'), + (0xF96D, 'M', '省'), + (0xF96E, 'M', '葉'), + (0xF96F, 'M', '說'), + (0xF970, 'M', '殺'), + (0xF971, 'M', '辰'), + (0xF972, 'M', '沈'), + (0xF973, 'M', '拾'), + (0xF974, 'M', '若'), + (0xF975, 'M', '掠'), + (0xF976, 'M', '略'), + (0xF977, 'M', '亮'), + (0xF978, 'M', '兩'), + (0xF979, 'M', '凉'), + (0xF97A, 'M', '梁'), + (0xF97B, 'M', '糧'), + (0xF97C, 'M', '良'), + (0xF97D, 'M', '諒'), + (0xF97E, 'M', '量'), + (0xF97F, 'M', '勵'), + (0xF980, 'M', '呂'), + (0xF981, 'M', '女'), + (0xF982, 'M', '廬'), + (0xF983, 'M', '旅'), + (0xF984, 'M', '濾'), + (0xF985, 'M', '礪'), + (0xF986, 'M', '閭'), + (0xF987, 'M', '驪'), + (0xF988, 'M', '麗'), + (0xF989, 'M', '黎'), + (0xF98A, 'M', '力'), + (0xF98B, 'M', '曆'), + (0xF98C, 'M', '歷'), + (0xF98D, 'M', '轢'), + (0xF98E, 'M', '年'), + (0xF98F, 'M', '憐'), + (0xF990, 'M', '戀'), + (0xF991, 'M', '撚'), + (0xF992, 'M', '漣'), + (0xF993, 'M', '煉'), + (0xF994, 'M', '璉'), + (0xF995, 'M', '秊'), + (0xF996, 'M', '練'), + (0xF997, 'M', '聯'), + (0xF998, 'M', '輦'), + (0xF999, 'M', '蓮'), + (0xF99A, 'M', '連'), + (0xF99B, 'M', '鍊'), + (0xF99C, 'M', '列'), + (0xF99D, 'M', '劣'), + (0xF99E, 'M', '咽'), + (0xF99F, 'M', '烈'), + (0xF9A0, 'M', '裂'), + (0xF9A1, 'M', '說'), + (0xF9A2, 'M', '廉'), + (0xF9A3, 'M', '念'), + (0xF9A4, 'M', '捻'), + (0xF9A5, 'M', '殮'), + (0xF9A6, 'M', '簾'), + (0xF9A7, 'M', '獵'), + (0xF9A8, 'M', '令'), + (0xF9A9, 'M', '囹'), ] - def _seg_41() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0xF9AE, "M", "瑩"), - (0xF9AF, "M", "羚"), - (0xF9B0, "M", "聆"), - (0xF9B1, "M", "鈴"), - (0xF9B2, "M", "零"), - (0xF9B3, "M", "靈"), - (0xF9B4, "M", "領"), - (0xF9B5, "M", "例"), - (0xF9B6, "M", "禮"), - (0xF9B7, "M", "醴"), - (0xF9B8, "M", "隸"), - (0xF9B9, "M", "惡"), - (0xF9BA, "M", "了"), - (0xF9BB, "M", "僚"), - (0xF9BC, "M", "寮"), - (0xF9BD, "M", "尿"), - (0xF9BE, "M", "料"), - (0xF9BF, "M", "樂"), - (0xF9C0, "M", "燎"), - (0xF9C1, "M", "療"), - (0xF9C2, "M", "蓼"), - (0xF9C3, "M", "遼"), - (0xF9C4, "M", "龍"), - (0xF9C5, "M", "暈"), - (0xF9C6, "M", "阮"), - (0xF9C7, "M", "劉"), - (0xF9C8, "M", "杻"), - (0xF9C9, "M", "柳"), - (0xF9CA, "M", "流"), - (0xF9CB, "M", "溜"), - (0xF9CC, "M", "琉"), - (0xF9CD, "M", "留"), - (0xF9CE, "M", "硫"), - (0xF9CF, "M", "紐"), - (0xF9D0, "M", "類"), - (0xF9D1, "M", "六"), - (0xF9D2, "M", "戮"), - (0xF9D3, "M", "陸"), - (0xF9D4, "M", "倫"), - (0xF9D5, "M", "崙"), - (0xF9D6, "M", "淪"), - (0xF9D7, "M", "輪"), - (0xF9D8, "M", "律"), - (0xF9D9, "M", "慄"), - (0xF9DA, "M", "栗"), - (0xF9DB, "M", "率"), - (0xF9DC, "M", "隆"), - (0xF9DD, "M", "利"), - (0xF9DE, "M", "吏"), - (0xF9DF, "M", "履"), - (0xF9E0, "M", "易"), - (0xF9E1, "M", "李"), - (0xF9E2, "M", "梨"), - (0xF9E3, "M", "泥"), - (0xF9E4, "M", "理"), - (0xF9E5, "M", "痢"), - (0xF9E6, "M", "罹"), - (0xF9E7, "M", "裏"), - (0xF9E8, "M", "裡"), - (0xF9E9, "M", "里"), - (0xF9EA, "M", "離"), - (0xF9EB, "M", "匿"), - (0xF9EC, "M", "溺"), - (0xF9ED, "M", "吝"), - (0xF9EE, "M", "燐"), - (0xF9EF, "M", "璘"), - (0xF9F0, "M", "藺"), - (0xF9F1, "M", "隣"), - (0xF9F2, "M", "鱗"), - (0xF9F3, "M", "麟"), - (0xF9F4, "M", "林"), - (0xF9F5, "M", "淋"), - (0xF9F6, "M", "臨"), - (0xF9F7, "M", "立"), - (0xF9F8, "M", "笠"), - (0xF9F9, "M", "粒"), - (0xF9FA, "M", "狀"), - (0xF9FB, "M", "炙"), - (0xF9FC, "M", "識"), - (0xF9FD, "M", "什"), - (0xF9FE, "M", "茶"), - (0xF9FF, "M", "刺"), - (0xFA00, "M", "切"), - (0xFA01, "M", "度"), - (0xFA02, "M", "拓"), - (0xFA03, "M", "糖"), - (0xFA04, "M", "宅"), - (0xFA05, "M", "洞"), - (0xFA06, "M", "暴"), - (0xFA07, "M", "輻"), - (0xFA08, "M", "行"), - (0xFA09, "M", "降"), - (0xFA0A, "M", "見"), - (0xFA0B, "M", "廓"), - (0xFA0C, "M", "兀"), - (0xFA0D, "M", "嗀"), - (0xFA0E, "V"), - (0xFA10, "M", "塚"), - (0xFA11, "V"), - (0xFA12, "M", "晴"), + (0xF9AA, 'M', '寧'), + (0xF9AB, 'M', '嶺'), + (0xF9AC, 'M', '怜'), + (0xF9AD, 'M', '玲'), + (0xF9AE, 'M', '瑩'), + (0xF9AF, 'M', '羚'), + (0xF9B0, 'M', '聆'), + (0xF9B1, 'M', '鈴'), + (0xF9B2, 'M', '零'), + (0xF9B3, 'M', '靈'), + (0xF9B4, 'M', '領'), + (0xF9B5, 'M', '例'), + (0xF9B6, 'M', '禮'), + (0xF9B7, 'M', '醴'), + (0xF9B8, 'M', '隸'), + (0xF9B9, 'M', '惡'), + (0xF9BA, 'M', '了'), + (0xF9BB, 'M', '僚'), + (0xF9BC, 'M', '寮'), + (0xF9BD, 'M', '尿'), + (0xF9BE, 'M', '料'), + (0xF9BF, 'M', '樂'), + (0xF9C0, 'M', '燎'), + (0xF9C1, 'M', '療'), + (0xF9C2, 'M', '蓼'), + (0xF9C3, 'M', '遼'), + (0xF9C4, 'M', '龍'), + (0xF9C5, 'M', '暈'), + (0xF9C6, 'M', '阮'), + (0xF9C7, 'M', '劉'), + (0xF9C8, 'M', '杻'), + (0xF9C9, 'M', '柳'), + (0xF9CA, 'M', '流'), + (0xF9CB, 'M', '溜'), + (0xF9CC, 'M', '琉'), + (0xF9CD, 'M', '留'), + (0xF9CE, 'M', '硫'), + (0xF9CF, 'M', '紐'), + (0xF9D0, 'M', '類'), + (0xF9D1, 'M', '六'), + (0xF9D2, 'M', '戮'), + (0xF9D3, 'M', '陸'), + (0xF9D4, 'M', '倫'), + (0xF9D5, 'M', '崙'), + (0xF9D6, 'M', '淪'), + (0xF9D7, 'M', '輪'), + (0xF9D8, 'M', '律'), + (0xF9D9, 'M', '慄'), + (0xF9DA, 'M', '栗'), + (0xF9DB, 'M', '率'), + (0xF9DC, 'M', '隆'), + (0xF9DD, 'M', '利'), + (0xF9DE, 'M', '吏'), + (0xF9DF, 'M', '履'), + (0xF9E0, 'M', '易'), + (0xF9E1, 'M', '李'), + (0xF9E2, 'M', '梨'), + (0xF9E3, 'M', '泥'), + (0xF9E4, 'M', '理'), + (0xF9E5, 'M', '痢'), + (0xF9E6, 'M', '罹'), + (0xF9E7, 'M', '裏'), + (0xF9E8, 'M', '裡'), + (0xF9E9, 'M', '里'), + (0xF9EA, 'M', '離'), + (0xF9EB, 'M', '匿'), + (0xF9EC, 'M', '溺'), + (0xF9ED, 'M', '吝'), + (0xF9EE, 'M', '燐'), + (0xF9EF, 'M', '璘'), + (0xF9F0, 'M', '藺'), + (0xF9F1, 'M', '隣'), + (0xF9F2, 'M', '鱗'), + (0xF9F3, 'M', '麟'), + (0xF9F4, 'M', '林'), + (0xF9F5, 'M', '淋'), + (0xF9F6, 'M', '臨'), + (0xF9F7, 'M', '立'), + (0xF9F8, 'M', '笠'), + (0xF9F9, 'M', '粒'), + (0xF9FA, 'M', '狀'), + (0xF9FB, 'M', '炙'), + (0xF9FC, 'M', '識'), + (0xF9FD, 'M', '什'), + (0xF9FE, 'M', '茶'), + (0xF9FF, 'M', '刺'), + (0xFA00, 'M', '切'), + (0xFA01, 'M', '度'), + (0xFA02, 'M', '拓'), + (0xFA03, 'M', '糖'), + (0xFA04, 'M', '宅'), + (0xFA05, 'M', '洞'), + (0xFA06, 'M', '暴'), + (0xFA07, 'M', '輻'), + (0xFA08, 'M', '行'), + (0xFA09, 'M', '降'), + (0xFA0A, 'M', '見'), + (0xFA0B, 'M', '廓'), + (0xFA0C, 'M', '兀'), + (0xFA0D, 'M', '嗀'), ] - def _seg_42() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0xFA13, "V"), - (0xFA15, "M", "凞"), - (0xFA16, "M", "猪"), - (0xFA17, "M", "益"), - (0xFA18, "M", "礼"), - (0xFA19, "M", "神"), - (0xFA1A, "M", "祥"), - (0xFA1B, "M", "福"), - (0xFA1C, "M", "靖"), - (0xFA1D, "M", "精"), - (0xFA1E, "M", "羽"), - (0xFA1F, "V"), - (0xFA20, "M", "蘒"), - (0xFA21, "V"), - (0xFA22, "M", "諸"), - (0xFA23, "V"), - (0xFA25, "M", "逸"), - (0xFA26, "M", "都"), - (0xFA27, "V"), - (0xFA2A, "M", "飯"), - (0xFA2B, "M", "飼"), - (0xFA2C, "M", "館"), - (0xFA2D, "M", "鶴"), - (0xFA2E, "M", "郞"), - (0xFA2F, "M", "隷"), - (0xFA30, "M", "侮"), - (0xFA31, "M", "僧"), - (0xFA32, "M", "免"), - (0xFA33, "M", "勉"), - (0xFA34, "M", "勤"), - (0xFA35, "M", "卑"), - (0xFA36, "M", "喝"), - (0xFA37, "M", "嘆"), - (0xFA38, "M", "器"), - (0xFA39, "M", "塀"), - (0xFA3A, "M", "墨"), - (0xFA3B, "M", "層"), - (0xFA3C, "M", "屮"), - (0xFA3D, "M", "悔"), - (0xFA3E, "M", "慨"), - (0xFA3F, "M", "憎"), - (0xFA40, "M", "懲"), - (0xFA41, "M", "敏"), - (0xFA42, "M", "既"), - (0xFA43, "M", "暑"), - (0xFA44, "M", "梅"), - (0xFA45, "M", "海"), - (0xFA46, "M", "渚"), - (0xFA47, "M", "漢"), - (0xFA48, "M", "煮"), - (0xFA49, "M", "爫"), - (0xFA4A, "M", "琢"), - (0xFA4B, "M", "碑"), - (0xFA4C, "M", "社"), - (0xFA4D, "M", "祉"), - (0xFA4E, "M", "祈"), - (0xFA4F, "M", "祐"), - (0xFA50, "M", "祖"), - (0xFA51, "M", "祝"), - (0xFA52, "M", "禍"), - (0xFA53, "M", "禎"), - (0xFA54, "M", "穀"), - (0xFA55, "M", "突"), - (0xFA56, "M", "節"), - (0xFA57, "M", "練"), - (0xFA58, "M", "縉"), - (0xFA59, "M", "繁"), - (0xFA5A, "M", "署"), - (0xFA5B, "M", "者"), - (0xFA5C, "M", "臭"), - (0xFA5D, "M", "艹"), - (0xFA5F, "M", "著"), - (0xFA60, "M", "褐"), - (0xFA61, "M", "視"), - (0xFA62, "M", "謁"), - (0xFA63, "M", "謹"), - (0xFA64, "M", "賓"), - (0xFA65, "M", "贈"), - (0xFA66, "M", "辶"), - (0xFA67, "M", "逸"), - (0xFA68, "M", "難"), - (0xFA69, "M", "響"), - (0xFA6A, "M", "頻"), - (0xFA6B, "M", "恵"), - (0xFA6C, "M", "𤋮"), - (0xFA6D, "M", "舘"), - (0xFA6E, "X"), - (0xFA70, "M", "並"), - (0xFA71, "M", "况"), - (0xFA72, "M", "全"), - (0xFA73, "M", "侀"), - (0xFA74, "M", "充"), - (0xFA75, "M", "冀"), - (0xFA76, "M", "勇"), - (0xFA77, "M", "勺"), - (0xFA78, "M", "喝"), - (0xFA79, "M", "啕"), - (0xFA7A, "M", "喙"), - (0xFA7B, "M", "嗢"), - (0xFA7C, "M", "塚"), + (0xFA0E, 'V'), + (0xFA10, 'M', '塚'), + (0xFA11, 'V'), + (0xFA12, 'M', '晴'), + (0xFA13, 'V'), + (0xFA15, 'M', '凞'), + (0xFA16, 'M', '猪'), + (0xFA17, 'M', '益'), + (0xFA18, 'M', '礼'), + (0xFA19, 'M', '神'), + (0xFA1A, 'M', '祥'), + (0xFA1B, 'M', '福'), + (0xFA1C, 'M', '靖'), + (0xFA1D, 'M', '精'), + (0xFA1E, 'M', '羽'), + (0xFA1F, 'V'), + (0xFA20, 'M', '蘒'), + (0xFA21, 'V'), + (0xFA22, 'M', '諸'), + (0xFA23, 'V'), + (0xFA25, 'M', '逸'), + (0xFA26, 'M', '都'), + (0xFA27, 'V'), + (0xFA2A, 'M', '飯'), + (0xFA2B, 'M', '飼'), + (0xFA2C, 'M', '館'), + (0xFA2D, 'M', '鶴'), + (0xFA2E, 'M', '郞'), + (0xFA2F, 'M', '隷'), + (0xFA30, 'M', '侮'), + (0xFA31, 'M', '僧'), + (0xFA32, 'M', '免'), + (0xFA33, 'M', '勉'), + (0xFA34, 'M', '勤'), + (0xFA35, 'M', '卑'), + (0xFA36, 'M', '喝'), + (0xFA37, 'M', '嘆'), + (0xFA38, 'M', '器'), + (0xFA39, 'M', '塀'), + (0xFA3A, 'M', '墨'), + (0xFA3B, 'M', '層'), + (0xFA3C, 'M', '屮'), + (0xFA3D, 'M', '悔'), + (0xFA3E, 'M', '慨'), + (0xFA3F, 'M', '憎'), + (0xFA40, 'M', '懲'), + (0xFA41, 'M', '敏'), + (0xFA42, 'M', '既'), + (0xFA43, 'M', '暑'), + (0xFA44, 'M', '梅'), + (0xFA45, 'M', '海'), + (0xFA46, 'M', '渚'), + (0xFA47, 'M', '漢'), + (0xFA48, 'M', '煮'), + (0xFA49, 'M', '爫'), + (0xFA4A, 'M', '琢'), + (0xFA4B, 'M', '碑'), + (0xFA4C, 'M', '社'), + (0xFA4D, 'M', '祉'), + (0xFA4E, 'M', '祈'), + (0xFA4F, 'M', '祐'), + (0xFA50, 'M', '祖'), + (0xFA51, 'M', '祝'), + (0xFA52, 'M', '禍'), + (0xFA53, 'M', '禎'), + (0xFA54, 'M', '穀'), + (0xFA55, 'M', '突'), + (0xFA56, 'M', '節'), + (0xFA57, 'M', '練'), + (0xFA58, 'M', '縉'), + (0xFA59, 'M', '繁'), + (0xFA5A, 'M', '署'), + (0xFA5B, 'M', '者'), + (0xFA5C, 'M', '臭'), + (0xFA5D, 'M', '艹'), + (0xFA5F, 'M', '著'), + (0xFA60, 'M', '褐'), + (0xFA61, 'M', '視'), + (0xFA62, 'M', '謁'), + (0xFA63, 'M', '謹'), + (0xFA64, 'M', '賓'), + (0xFA65, 'M', '贈'), + (0xFA66, 'M', '辶'), + (0xFA67, 'M', '逸'), + (0xFA68, 'M', '難'), + (0xFA69, 'M', '響'), + (0xFA6A, 'M', '頻'), + (0xFA6B, 'M', '恵'), + (0xFA6C, 'M', '𤋮'), + (0xFA6D, 'M', '舘'), + (0xFA6E, 'X'), + (0xFA70, 'M', '並'), + (0xFA71, 'M', '况'), + (0xFA72, 'M', '全'), + (0xFA73, 'M', '侀'), + (0xFA74, 'M', '充'), + (0xFA75, 'M', '冀'), + (0xFA76, 'M', '勇'), + (0xFA77, 'M', '勺'), + (0xFA78, 'M', '喝'), ] - def _seg_43() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0xFA7D, "M", "墳"), - (0xFA7E, "M", "奄"), - (0xFA7F, "M", "奔"), - (0xFA80, "M", "婢"), - (0xFA81, "M", "嬨"), - (0xFA82, "M", "廒"), - (0xFA83, "M", "廙"), - (0xFA84, "M", "彩"), - (0xFA85, "M", "徭"), - (0xFA86, "M", "惘"), - (0xFA87, "M", "慎"), - (0xFA88, "M", "愈"), - (0xFA89, "M", "憎"), - (0xFA8A, "M", "慠"), - (0xFA8B, "M", "懲"), - (0xFA8C, "M", "戴"), - (0xFA8D, "M", "揄"), - (0xFA8E, "M", "搜"), - (0xFA8F, "M", "摒"), - (0xFA90, "M", "敖"), - (0xFA91, "M", "晴"), - (0xFA92, "M", "朗"), - (0xFA93, "M", "望"), - (0xFA94, "M", "杖"), - (0xFA95, "M", "歹"), - (0xFA96, "M", "殺"), - (0xFA97, "M", "流"), - (0xFA98, "M", "滛"), - (0xFA99, "M", "滋"), - (0xFA9A, "M", "漢"), - (0xFA9B, "M", "瀞"), - (0xFA9C, "M", "煮"), - (0xFA9D, "M", "瞧"), - (0xFA9E, "M", "爵"), - (0xFA9F, "M", "犯"), - (0xFAA0, "M", "猪"), - (0xFAA1, "M", "瑱"), - (0xFAA2, "M", "甆"), - (0xFAA3, "M", "画"), - (0xFAA4, "M", "瘝"), - (0xFAA5, "M", "瘟"), - (0xFAA6, "M", "益"), - (0xFAA7, "M", "盛"), - (0xFAA8, "M", "直"), - (0xFAA9, "M", "睊"), - (0xFAAA, "M", "着"), - (0xFAAB, "M", "磌"), - (0xFAAC, "M", "窱"), - (0xFAAD, "M", "節"), - (0xFAAE, "M", "类"), - (0xFAAF, "M", "絛"), - (0xFAB0, "M", "練"), - (0xFAB1, "M", "缾"), - (0xFAB2, "M", "者"), - (0xFAB3, "M", "荒"), - (0xFAB4, "M", "華"), - (0xFAB5, "M", "蝹"), - (0xFAB6, "M", "襁"), - (0xFAB7, "M", "覆"), - (0xFAB8, "M", "視"), - (0xFAB9, "M", "調"), - (0xFABA, "M", "諸"), - (0xFABB, "M", "請"), - (0xFABC, "M", "謁"), - (0xFABD, "M", "諾"), - (0xFABE, "M", "諭"), - (0xFABF, "M", "謹"), - (0xFAC0, "M", "變"), - (0xFAC1, "M", "贈"), - (0xFAC2, "M", "輸"), - (0xFAC3, "M", "遲"), - (0xFAC4, "M", "醙"), - (0xFAC5, "M", "鉶"), - (0xFAC6, "M", "陼"), - (0xFAC7, "M", "難"), - (0xFAC8, "M", "靖"), - (0xFAC9, "M", "韛"), - (0xFACA, "M", "響"), - (0xFACB, "M", "頋"), - (0xFACC, "M", "頻"), - (0xFACD, "M", "鬒"), - (0xFACE, "M", "龜"), - (0xFACF, "M", "𢡊"), - (0xFAD0, "M", "𢡄"), - (0xFAD1, "M", "𣏕"), - (0xFAD2, "M", "㮝"), - (0xFAD3, "M", "䀘"), - (0xFAD4, "M", "䀹"), - (0xFAD5, "M", "𥉉"), - (0xFAD6, "M", "𥳐"), - (0xFAD7, "M", "𧻓"), - (0xFAD8, "M", "齃"), - (0xFAD9, "M", "龎"), - (0xFADA, "X"), - (0xFB00, "M", "ff"), - (0xFB01, "M", "fi"), - (0xFB02, "M", "fl"), - (0xFB03, "M", "ffi"), - (0xFB04, "M", "ffl"), - (0xFB05, "M", "st"), + (0xFA79, 'M', '啕'), + (0xFA7A, 'M', '喙'), + (0xFA7B, 'M', '嗢'), + (0xFA7C, 'M', '塚'), + (0xFA7D, 'M', '墳'), + (0xFA7E, 'M', '奄'), + (0xFA7F, 'M', '奔'), + (0xFA80, 'M', '婢'), + (0xFA81, 'M', '嬨'), + (0xFA82, 'M', '廒'), + (0xFA83, 'M', '廙'), + (0xFA84, 'M', '彩'), + (0xFA85, 'M', '徭'), + (0xFA86, 'M', '惘'), + (0xFA87, 'M', '慎'), + (0xFA88, 'M', '愈'), + (0xFA89, 'M', '憎'), + (0xFA8A, 'M', '慠'), + (0xFA8B, 'M', '懲'), + (0xFA8C, 'M', '戴'), + (0xFA8D, 'M', '揄'), + (0xFA8E, 'M', '搜'), + (0xFA8F, 'M', '摒'), + (0xFA90, 'M', '敖'), + (0xFA91, 'M', '晴'), + (0xFA92, 'M', '朗'), + (0xFA93, 'M', '望'), + (0xFA94, 'M', '杖'), + (0xFA95, 'M', '歹'), + (0xFA96, 'M', '殺'), + (0xFA97, 'M', '流'), + (0xFA98, 'M', '滛'), + (0xFA99, 'M', '滋'), + (0xFA9A, 'M', '漢'), + (0xFA9B, 'M', '瀞'), + (0xFA9C, 'M', '煮'), + (0xFA9D, 'M', '瞧'), + (0xFA9E, 'M', '爵'), + (0xFA9F, 'M', '犯'), + (0xFAA0, 'M', '猪'), + (0xFAA1, 'M', '瑱'), + (0xFAA2, 'M', '甆'), + (0xFAA3, 'M', '画'), + (0xFAA4, 'M', '瘝'), + (0xFAA5, 'M', '瘟'), + (0xFAA6, 'M', '益'), + (0xFAA7, 'M', '盛'), + (0xFAA8, 'M', '直'), + (0xFAA9, 'M', '睊'), + (0xFAAA, 'M', '着'), + (0xFAAB, 'M', '磌'), + (0xFAAC, 'M', '窱'), + (0xFAAD, 'M', '節'), + (0xFAAE, 'M', '类'), + (0xFAAF, 'M', '絛'), + (0xFAB0, 'M', '練'), + (0xFAB1, 'M', '缾'), + (0xFAB2, 'M', '者'), + (0xFAB3, 'M', '荒'), + (0xFAB4, 'M', '華'), + (0xFAB5, 'M', '蝹'), + (0xFAB6, 'M', '襁'), + (0xFAB7, 'M', '覆'), + (0xFAB8, 'M', '視'), + (0xFAB9, 'M', '調'), + (0xFABA, 'M', '諸'), + (0xFABB, 'M', '請'), + (0xFABC, 'M', '謁'), + (0xFABD, 'M', '諾'), + (0xFABE, 'M', '諭'), + (0xFABF, 'M', '謹'), + (0xFAC0, 'M', '變'), + (0xFAC1, 'M', '贈'), + (0xFAC2, 'M', '輸'), + (0xFAC3, 'M', '遲'), + (0xFAC4, 'M', '醙'), + (0xFAC5, 'M', '鉶'), + (0xFAC6, 'M', '陼'), + (0xFAC7, 'M', '難'), + (0xFAC8, 'M', '靖'), + (0xFAC9, 'M', '韛'), + (0xFACA, 'M', '響'), + (0xFACB, 'M', '頋'), + (0xFACC, 'M', '頻'), + (0xFACD, 'M', '鬒'), + (0xFACE, 'M', '龜'), + (0xFACF, 'M', '𢡊'), + (0xFAD0, 'M', '𢡄'), + (0xFAD1, 'M', '𣏕'), + (0xFAD2, 'M', '㮝'), + (0xFAD3, 'M', '䀘'), + (0xFAD4, 'M', '䀹'), + (0xFAD5, 'M', '𥉉'), + (0xFAD6, 'M', '𥳐'), + (0xFAD7, 'M', '𧻓'), + (0xFAD8, 'M', '齃'), + (0xFAD9, 'M', '龎'), + (0xFADA, 'X'), + (0xFB00, 'M', 'ff'), + (0xFB01, 'M', 'fi'), ] - def _seg_44() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0xFB07, "X"), - (0xFB13, "M", "մն"), - (0xFB14, "M", "մե"), - (0xFB15, "M", "մի"), - (0xFB16, "M", "վն"), - (0xFB17, "M", "մխ"), - (0xFB18, "X"), - (0xFB1D, "M", "יִ"), - (0xFB1E, "V"), - (0xFB1F, "M", "ײַ"), - (0xFB20, "M", "ע"), - (0xFB21, "M", "א"), - (0xFB22, "M", "ד"), - (0xFB23, "M", "ה"), - (0xFB24, "M", "כ"), - (0xFB25, "M", "ל"), - (0xFB26, "M", "ם"), - (0xFB27, "M", "ר"), - (0xFB28, "M", "ת"), - (0xFB29, "3", "+"), - (0xFB2A, "M", "שׁ"), - (0xFB2B, "M", "שׂ"), - (0xFB2C, "M", "שּׁ"), - (0xFB2D, "M", "שּׂ"), - (0xFB2E, "M", "אַ"), - (0xFB2F, "M", "אָ"), - (0xFB30, "M", "אּ"), - (0xFB31, "M", "בּ"), - (0xFB32, "M", "גּ"), - (0xFB33, "M", "דּ"), - (0xFB34, "M", "הּ"), - (0xFB35, "M", "וּ"), - (0xFB36, "M", "זּ"), - (0xFB37, "X"), - (0xFB38, "M", "טּ"), - (0xFB39, "M", "יּ"), - (0xFB3A, "M", "ךּ"), - (0xFB3B, "M", "כּ"), - (0xFB3C, "M", "לּ"), - (0xFB3D, "X"), - (0xFB3E, "M", "מּ"), - (0xFB3F, "X"), - (0xFB40, "M", "נּ"), - (0xFB41, "M", "סּ"), - (0xFB42, "X"), - (0xFB43, "M", "ףּ"), - (0xFB44, "M", "פּ"), - (0xFB45, "X"), - (0xFB46, "M", "צּ"), - (0xFB47, "M", "קּ"), - (0xFB48, "M", "רּ"), - (0xFB49, "M", "שּ"), - (0xFB4A, "M", "תּ"), - (0xFB4B, "M", "וֹ"), - (0xFB4C, "M", "בֿ"), - (0xFB4D, "M", "כֿ"), - (0xFB4E, "M", "פֿ"), - (0xFB4F, "M", "אל"), - (0xFB50, "M", "ٱ"), - (0xFB52, "M", "ٻ"), - (0xFB56, "M", "پ"), - (0xFB5A, "M", "ڀ"), - (0xFB5E, "M", "ٺ"), - (0xFB62, "M", "ٿ"), - (0xFB66, "M", "ٹ"), - (0xFB6A, "M", "ڤ"), - (0xFB6E, "M", "ڦ"), - (0xFB72, "M", "ڄ"), - (0xFB76, "M", "ڃ"), - (0xFB7A, "M", "چ"), - (0xFB7E, "M", "ڇ"), - (0xFB82, "M", "ڍ"), - (0xFB84, "M", "ڌ"), - (0xFB86, "M", "ڎ"), - (0xFB88, "M", "ڈ"), - (0xFB8A, "M", "ژ"), - (0xFB8C, "M", "ڑ"), - (0xFB8E, "M", "ک"), - (0xFB92, "M", "گ"), - (0xFB96, "M", "ڳ"), - (0xFB9A, "M", "ڱ"), - (0xFB9E, "M", "ں"), - (0xFBA0, "M", "ڻ"), - (0xFBA4, "M", "ۀ"), - (0xFBA6, "M", "ہ"), - (0xFBAA, "M", "ھ"), - (0xFBAE, "M", "ے"), - (0xFBB0, "M", "ۓ"), - (0xFBB2, "V"), - (0xFBC3, "X"), - (0xFBD3, "M", "ڭ"), - (0xFBD7, "M", "ۇ"), - (0xFBD9, "M", "ۆ"), - (0xFBDB, "M", "ۈ"), - (0xFBDD, "M", "ۇٴ"), - (0xFBDE, "M", "ۋ"), - (0xFBE0, "M", "ۅ"), - (0xFBE2, "M", "ۉ"), - (0xFBE4, "M", "ې"), - (0xFBE8, "M", "ى"), + (0xFB02, 'M', 'fl'), + (0xFB03, 'M', 'ffi'), + (0xFB04, 'M', 'ffl'), + (0xFB05, 'M', 'st'), + (0xFB07, 'X'), + (0xFB13, 'M', 'մն'), + (0xFB14, 'M', 'մե'), + (0xFB15, 'M', 'մի'), + (0xFB16, 'M', 'վն'), + (0xFB17, 'M', 'մխ'), + (0xFB18, 'X'), + (0xFB1D, 'M', 'יִ'), + (0xFB1E, 'V'), + (0xFB1F, 'M', 'ײַ'), + (0xFB20, 'M', 'ע'), + (0xFB21, 'M', 'א'), + (0xFB22, 'M', 'ד'), + (0xFB23, 'M', 'ה'), + (0xFB24, 'M', 'כ'), + (0xFB25, 'M', 'ל'), + (0xFB26, 'M', 'ם'), + (0xFB27, 'M', 'ר'), + (0xFB28, 'M', 'ת'), + (0xFB29, '3', '+'), + (0xFB2A, 'M', 'שׁ'), + (0xFB2B, 'M', 'שׂ'), + (0xFB2C, 'M', 'שּׁ'), + (0xFB2D, 'M', 'שּׂ'), + (0xFB2E, 'M', 'אַ'), + (0xFB2F, 'M', 'אָ'), + (0xFB30, 'M', 'אּ'), + (0xFB31, 'M', 'בּ'), + (0xFB32, 'M', 'גּ'), + (0xFB33, 'M', 'דּ'), + (0xFB34, 'M', 'הּ'), + (0xFB35, 'M', 'וּ'), + (0xFB36, 'M', 'זּ'), + (0xFB37, 'X'), + (0xFB38, 'M', 'טּ'), + (0xFB39, 'M', 'יּ'), + (0xFB3A, 'M', 'ךּ'), + (0xFB3B, 'M', 'כּ'), + (0xFB3C, 'M', 'לּ'), + (0xFB3D, 'X'), + (0xFB3E, 'M', 'מּ'), + (0xFB3F, 'X'), + (0xFB40, 'M', 'נּ'), + (0xFB41, 'M', 'סּ'), + (0xFB42, 'X'), + (0xFB43, 'M', 'ףּ'), + (0xFB44, 'M', 'פּ'), + (0xFB45, 'X'), + (0xFB46, 'M', 'צּ'), + (0xFB47, 'M', 'קּ'), + (0xFB48, 'M', 'רּ'), + (0xFB49, 'M', 'שּ'), + (0xFB4A, 'M', 'תּ'), + (0xFB4B, 'M', 'וֹ'), + (0xFB4C, 'M', 'בֿ'), + (0xFB4D, 'M', 'כֿ'), + (0xFB4E, 'M', 'פֿ'), + (0xFB4F, 'M', 'אל'), + (0xFB50, 'M', 'ٱ'), + (0xFB52, 'M', 'ٻ'), + (0xFB56, 'M', 'پ'), + (0xFB5A, 'M', 'ڀ'), + (0xFB5E, 'M', 'ٺ'), + (0xFB62, 'M', 'ٿ'), + (0xFB66, 'M', 'ٹ'), + (0xFB6A, 'M', 'ڤ'), + (0xFB6E, 'M', 'ڦ'), + (0xFB72, 'M', 'ڄ'), + (0xFB76, 'M', 'ڃ'), + (0xFB7A, 'M', 'چ'), + (0xFB7E, 'M', 'ڇ'), + (0xFB82, 'M', 'ڍ'), + (0xFB84, 'M', 'ڌ'), + (0xFB86, 'M', 'ڎ'), + (0xFB88, 'M', 'ڈ'), + (0xFB8A, 'M', 'ژ'), + (0xFB8C, 'M', 'ڑ'), + (0xFB8E, 'M', 'ک'), + (0xFB92, 'M', 'گ'), + (0xFB96, 'M', 'ڳ'), + (0xFB9A, 'M', 'ڱ'), + (0xFB9E, 'M', 'ں'), + (0xFBA0, 'M', 'ڻ'), + (0xFBA4, 'M', 'ۀ'), + (0xFBA6, 'M', 'ہ'), + (0xFBAA, 'M', 'ھ'), + (0xFBAE, 'M', 'ے'), + (0xFBB0, 'M', 'ۓ'), + (0xFBB2, 'V'), + (0xFBC3, 'X'), + (0xFBD3, 'M', 'ڭ'), + (0xFBD7, 'M', 'ۇ'), + (0xFBD9, 'M', 'ۆ'), + (0xFBDB, 'M', 'ۈ'), + (0xFBDD, 'M', 'ۇٴ'), + (0xFBDE, 'M', 'ۋ'), ] - def _seg_45() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0xFBEA, "M", "ئا"), - (0xFBEC, "M", "ئە"), - (0xFBEE, "M", "ئو"), - (0xFBF0, "M", "ئۇ"), - (0xFBF2, "M", "ئۆ"), - (0xFBF4, "M", "ئۈ"), - (0xFBF6, "M", "ئې"), - (0xFBF9, "M", "ئى"), - (0xFBFC, "M", "ی"), - (0xFC00, "M", "ئج"), - (0xFC01, "M", "ئح"), - (0xFC02, "M", "ئم"), - (0xFC03, "M", "ئى"), - (0xFC04, "M", "ئي"), - (0xFC05, "M", "بج"), - (0xFC06, "M", "بح"), - (0xFC07, "M", "بخ"), - (0xFC08, "M", "بم"), - (0xFC09, "M", "بى"), - (0xFC0A, "M", "بي"), - (0xFC0B, "M", "تج"), - (0xFC0C, "M", "تح"), - (0xFC0D, "M", "تخ"), - (0xFC0E, "M", "تم"), - (0xFC0F, "M", "تى"), - (0xFC10, "M", "تي"), - (0xFC11, "M", "ثج"), - (0xFC12, "M", "ثم"), - (0xFC13, "M", "ثى"), - (0xFC14, "M", "ثي"), - (0xFC15, "M", "جح"), - (0xFC16, "M", "جم"), - (0xFC17, "M", "حج"), - (0xFC18, "M", "حم"), - (0xFC19, "M", "خج"), - (0xFC1A, "M", "خح"), - (0xFC1B, "M", "خم"), - (0xFC1C, "M", "سج"), - (0xFC1D, "M", "سح"), - (0xFC1E, "M", "سخ"), - (0xFC1F, "M", "سم"), - (0xFC20, "M", "صح"), - (0xFC21, "M", "صم"), - (0xFC22, "M", "ضج"), - (0xFC23, "M", "ضح"), - (0xFC24, "M", "ضخ"), - (0xFC25, "M", "ضم"), - (0xFC26, "M", "طح"), - (0xFC27, "M", "طم"), - (0xFC28, "M", "ظم"), - (0xFC29, "M", "عج"), - (0xFC2A, "M", "عم"), - (0xFC2B, "M", "غج"), - (0xFC2C, "M", "غم"), - (0xFC2D, "M", "فج"), - (0xFC2E, "M", "فح"), - (0xFC2F, "M", "فخ"), - (0xFC30, "M", "فم"), - (0xFC31, "M", "فى"), - (0xFC32, "M", "في"), - (0xFC33, "M", "قح"), - (0xFC34, "M", "قم"), - (0xFC35, "M", "قى"), - (0xFC36, "M", "قي"), - (0xFC37, "M", "كا"), - (0xFC38, "M", "كج"), - (0xFC39, "M", "كح"), - (0xFC3A, "M", "كخ"), - (0xFC3B, "M", "كل"), - (0xFC3C, "M", "كم"), - (0xFC3D, "M", "كى"), - (0xFC3E, "M", "كي"), - (0xFC3F, "M", "لج"), - (0xFC40, "M", "لح"), - (0xFC41, "M", "لخ"), - (0xFC42, "M", "لم"), - (0xFC43, "M", "لى"), - (0xFC44, "M", "لي"), - (0xFC45, "M", "مج"), - (0xFC46, "M", "مح"), - (0xFC47, "M", "مخ"), - (0xFC48, "M", "مم"), - (0xFC49, "M", "مى"), - (0xFC4A, "M", "مي"), - (0xFC4B, "M", "نج"), - (0xFC4C, "M", "نح"), - (0xFC4D, "M", "نخ"), - (0xFC4E, "M", "نم"), - (0xFC4F, "M", "نى"), - (0xFC50, "M", "ني"), - (0xFC51, "M", "هج"), - (0xFC52, "M", "هم"), - (0xFC53, "M", "هى"), - (0xFC54, "M", "هي"), - (0xFC55, "M", "يج"), - (0xFC56, "M", "يح"), - (0xFC57, "M", "يخ"), - (0xFC58, "M", "يم"), - (0xFC59, "M", "يى"), - (0xFC5A, "M", "يي"), + (0xFBE0, 'M', 'ۅ'), + (0xFBE2, 'M', 'ۉ'), + (0xFBE4, 'M', 'ې'), + (0xFBE8, 'M', 'ى'), + (0xFBEA, 'M', 'ئا'), + (0xFBEC, 'M', 'ئە'), + (0xFBEE, 'M', 'ئو'), + (0xFBF0, 'M', 'ئۇ'), + (0xFBF2, 'M', 'ئۆ'), + (0xFBF4, 'M', 'ئۈ'), + (0xFBF6, 'M', 'ئې'), + (0xFBF9, 'M', 'ئى'), + (0xFBFC, 'M', 'ی'), + (0xFC00, 'M', 'ئج'), + (0xFC01, 'M', 'ئح'), + (0xFC02, 'M', 'ئم'), + (0xFC03, 'M', 'ئى'), + (0xFC04, 'M', 'ئي'), + (0xFC05, 'M', 'بج'), + (0xFC06, 'M', 'بح'), + (0xFC07, 'M', 'بخ'), + (0xFC08, 'M', 'بم'), + (0xFC09, 'M', 'بى'), + (0xFC0A, 'M', 'بي'), + (0xFC0B, 'M', 'تج'), + (0xFC0C, 'M', 'تح'), + (0xFC0D, 'M', 'تخ'), + (0xFC0E, 'M', 'تم'), + (0xFC0F, 'M', 'تى'), + (0xFC10, 'M', 'تي'), + (0xFC11, 'M', 'ثج'), + (0xFC12, 'M', 'ثم'), + (0xFC13, 'M', 'ثى'), + (0xFC14, 'M', 'ثي'), + (0xFC15, 'M', 'جح'), + (0xFC16, 'M', 'جم'), + (0xFC17, 'M', 'حج'), + (0xFC18, 'M', 'حم'), + (0xFC19, 'M', 'خج'), + (0xFC1A, 'M', 'خح'), + (0xFC1B, 'M', 'خم'), + (0xFC1C, 'M', 'سج'), + (0xFC1D, 'M', 'سح'), + (0xFC1E, 'M', 'سخ'), + (0xFC1F, 'M', 'سم'), + (0xFC20, 'M', 'صح'), + (0xFC21, 'M', 'صم'), + (0xFC22, 'M', 'ضج'), + (0xFC23, 'M', 'ضح'), + (0xFC24, 'M', 'ضخ'), + (0xFC25, 'M', 'ضم'), + (0xFC26, 'M', 'طح'), + (0xFC27, 'M', 'طم'), + (0xFC28, 'M', 'ظم'), + (0xFC29, 'M', 'عج'), + (0xFC2A, 'M', 'عم'), + (0xFC2B, 'M', 'غج'), + (0xFC2C, 'M', 'غم'), + (0xFC2D, 'M', 'فج'), + (0xFC2E, 'M', 'فح'), + (0xFC2F, 'M', 'فخ'), + (0xFC30, 'M', 'فم'), + (0xFC31, 'M', 'فى'), + (0xFC32, 'M', 'في'), + (0xFC33, 'M', 'قح'), + (0xFC34, 'M', 'قم'), + (0xFC35, 'M', 'قى'), + (0xFC36, 'M', 'قي'), + (0xFC37, 'M', 'كا'), + (0xFC38, 'M', 'كج'), + (0xFC39, 'M', 'كح'), + (0xFC3A, 'M', 'كخ'), + (0xFC3B, 'M', 'كل'), + (0xFC3C, 'M', 'كم'), + (0xFC3D, 'M', 'كى'), + (0xFC3E, 'M', 'كي'), + (0xFC3F, 'M', 'لج'), + (0xFC40, 'M', 'لح'), + (0xFC41, 'M', 'لخ'), + (0xFC42, 'M', 'لم'), + (0xFC43, 'M', 'لى'), + (0xFC44, 'M', 'لي'), + (0xFC45, 'M', 'مج'), + (0xFC46, 'M', 'مح'), + (0xFC47, 'M', 'مخ'), + (0xFC48, 'M', 'مم'), + (0xFC49, 'M', 'مى'), + (0xFC4A, 'M', 'مي'), + (0xFC4B, 'M', 'نج'), + (0xFC4C, 'M', 'نح'), + (0xFC4D, 'M', 'نخ'), + (0xFC4E, 'M', 'نم'), + (0xFC4F, 'M', 'نى'), + (0xFC50, 'M', 'ني'), + (0xFC51, 'M', 'هج'), + (0xFC52, 'M', 'هم'), + (0xFC53, 'M', 'هى'), + (0xFC54, 'M', 'هي'), + (0xFC55, 'M', 'يج'), + (0xFC56, 'M', 'يح'), ] - def _seg_46() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0xFC5B, "M", "ذٰ"), - (0xFC5C, "M", "رٰ"), - (0xFC5D, "M", "ىٰ"), - (0xFC5E, "3", " ٌّ"), - (0xFC5F, "3", " ٍّ"), - (0xFC60, "3", " َّ"), - (0xFC61, "3", " ُّ"), - (0xFC62, "3", " ِّ"), - (0xFC63, "3", " ّٰ"), - (0xFC64, "M", "ئر"), - (0xFC65, "M", "ئز"), - (0xFC66, "M", "ئم"), - (0xFC67, "M", "ئن"), - (0xFC68, "M", "ئى"), - (0xFC69, "M", "ئي"), - (0xFC6A, "M", "بر"), - (0xFC6B, "M", "بز"), - (0xFC6C, "M", "بم"), - (0xFC6D, "M", "بن"), - (0xFC6E, "M", "بى"), - (0xFC6F, "M", "بي"), - (0xFC70, "M", "تر"), - (0xFC71, "M", "تز"), - (0xFC72, "M", "تم"), - (0xFC73, "M", "تن"), - (0xFC74, "M", "تى"), - (0xFC75, "M", "تي"), - (0xFC76, "M", "ثر"), - (0xFC77, "M", "ثز"), - (0xFC78, "M", "ثم"), - (0xFC79, "M", "ثن"), - (0xFC7A, "M", "ثى"), - (0xFC7B, "M", "ثي"), - (0xFC7C, "M", "فى"), - (0xFC7D, "M", "في"), - (0xFC7E, "M", "قى"), - (0xFC7F, "M", "قي"), - (0xFC80, "M", "كا"), - (0xFC81, "M", "كل"), - (0xFC82, "M", "كم"), - (0xFC83, "M", "كى"), - (0xFC84, "M", "كي"), - (0xFC85, "M", "لم"), - (0xFC86, "M", "لى"), - (0xFC87, "M", "لي"), - (0xFC88, "M", "ما"), - (0xFC89, "M", "مم"), - (0xFC8A, "M", "نر"), - (0xFC8B, "M", "نز"), - (0xFC8C, "M", "نم"), - (0xFC8D, "M", "نن"), - (0xFC8E, "M", "نى"), - (0xFC8F, "M", "ني"), - (0xFC90, "M", "ىٰ"), - (0xFC91, "M", "ير"), - (0xFC92, "M", "يز"), - (0xFC93, "M", "يم"), - (0xFC94, "M", "ين"), - (0xFC95, "M", "يى"), - (0xFC96, "M", "يي"), - (0xFC97, "M", "ئج"), - (0xFC98, "M", "ئح"), - (0xFC99, "M", "ئخ"), - (0xFC9A, "M", "ئم"), - (0xFC9B, "M", "ئه"), - (0xFC9C, "M", "بج"), - (0xFC9D, "M", "بح"), - (0xFC9E, "M", "بخ"), - (0xFC9F, "M", "بم"), - (0xFCA0, "M", "به"), - (0xFCA1, "M", "تج"), - (0xFCA2, "M", "تح"), - (0xFCA3, "M", "تخ"), - (0xFCA4, "M", "تم"), - (0xFCA5, "M", "ته"), - (0xFCA6, "M", "ثم"), - (0xFCA7, "M", "جح"), - (0xFCA8, "M", "جم"), - (0xFCA9, "M", "حج"), - (0xFCAA, "M", "حم"), - (0xFCAB, "M", "خج"), - (0xFCAC, "M", "خم"), - (0xFCAD, "M", "سج"), - (0xFCAE, "M", "سح"), - (0xFCAF, "M", "سخ"), - (0xFCB0, "M", "سم"), - (0xFCB1, "M", "صح"), - (0xFCB2, "M", "صخ"), - (0xFCB3, "M", "صم"), - (0xFCB4, "M", "ضج"), - (0xFCB5, "M", "ضح"), - (0xFCB6, "M", "ضخ"), - (0xFCB7, "M", "ضم"), - (0xFCB8, "M", "طح"), - (0xFCB9, "M", "ظم"), - (0xFCBA, "M", "عج"), - (0xFCBB, "M", "عم"), - (0xFCBC, "M", "غج"), - (0xFCBD, "M", "غم"), - (0xFCBE, "M", "فج"), + (0xFC57, 'M', 'يخ'), + (0xFC58, 'M', 'يم'), + (0xFC59, 'M', 'يى'), + (0xFC5A, 'M', 'يي'), + (0xFC5B, 'M', 'ذٰ'), + (0xFC5C, 'M', 'رٰ'), + (0xFC5D, 'M', 'ىٰ'), + (0xFC5E, '3', ' ٌّ'), + (0xFC5F, '3', ' ٍّ'), + (0xFC60, '3', ' َّ'), + (0xFC61, '3', ' ُّ'), + (0xFC62, '3', ' ِّ'), + (0xFC63, '3', ' ّٰ'), + (0xFC64, 'M', 'ئر'), + (0xFC65, 'M', 'ئز'), + (0xFC66, 'M', 'ئم'), + (0xFC67, 'M', 'ئن'), + (0xFC68, 'M', 'ئى'), + (0xFC69, 'M', 'ئي'), + (0xFC6A, 'M', 'بر'), + (0xFC6B, 'M', 'بز'), + (0xFC6C, 'M', 'بم'), + (0xFC6D, 'M', 'بن'), + (0xFC6E, 'M', 'بى'), + (0xFC6F, 'M', 'بي'), + (0xFC70, 'M', 'تر'), + (0xFC71, 'M', 'تز'), + (0xFC72, 'M', 'تم'), + (0xFC73, 'M', 'تن'), + (0xFC74, 'M', 'تى'), + (0xFC75, 'M', 'تي'), + (0xFC76, 'M', 'ثر'), + (0xFC77, 'M', 'ثز'), + (0xFC78, 'M', 'ثم'), + (0xFC79, 'M', 'ثن'), + (0xFC7A, 'M', 'ثى'), + (0xFC7B, 'M', 'ثي'), + (0xFC7C, 'M', 'فى'), + (0xFC7D, 'M', 'في'), + (0xFC7E, 'M', 'قى'), + (0xFC7F, 'M', 'قي'), + (0xFC80, 'M', 'كا'), + (0xFC81, 'M', 'كل'), + (0xFC82, 'M', 'كم'), + (0xFC83, 'M', 'كى'), + (0xFC84, 'M', 'كي'), + (0xFC85, 'M', 'لم'), + (0xFC86, 'M', 'لى'), + (0xFC87, 'M', 'لي'), + (0xFC88, 'M', 'ما'), + (0xFC89, 'M', 'مم'), + (0xFC8A, 'M', 'نر'), + (0xFC8B, 'M', 'نز'), + (0xFC8C, 'M', 'نم'), + (0xFC8D, 'M', 'نن'), + (0xFC8E, 'M', 'نى'), + (0xFC8F, 'M', 'ني'), + (0xFC90, 'M', 'ىٰ'), + (0xFC91, 'M', 'ير'), + (0xFC92, 'M', 'يز'), + (0xFC93, 'M', 'يم'), + (0xFC94, 'M', 'ين'), + (0xFC95, 'M', 'يى'), + (0xFC96, 'M', 'يي'), + (0xFC97, 'M', 'ئج'), + (0xFC98, 'M', 'ئح'), + (0xFC99, 'M', 'ئخ'), + (0xFC9A, 'M', 'ئم'), + (0xFC9B, 'M', 'ئه'), + (0xFC9C, 'M', 'بج'), + (0xFC9D, 'M', 'بح'), + (0xFC9E, 'M', 'بخ'), + (0xFC9F, 'M', 'بم'), + (0xFCA0, 'M', 'به'), + (0xFCA1, 'M', 'تج'), + (0xFCA2, 'M', 'تح'), + (0xFCA3, 'M', 'تخ'), + (0xFCA4, 'M', 'تم'), + (0xFCA5, 'M', 'ته'), + (0xFCA6, 'M', 'ثم'), + (0xFCA7, 'M', 'جح'), + (0xFCA8, 'M', 'جم'), + (0xFCA9, 'M', 'حج'), + (0xFCAA, 'M', 'حم'), + (0xFCAB, 'M', 'خج'), + (0xFCAC, 'M', 'خم'), + (0xFCAD, 'M', 'سج'), + (0xFCAE, 'M', 'سح'), + (0xFCAF, 'M', 'سخ'), + (0xFCB0, 'M', 'سم'), + (0xFCB1, 'M', 'صح'), + (0xFCB2, 'M', 'صخ'), + (0xFCB3, 'M', 'صم'), + (0xFCB4, 'M', 'ضج'), + (0xFCB5, 'M', 'ضح'), + (0xFCB6, 'M', 'ضخ'), + (0xFCB7, 'M', 'ضم'), + (0xFCB8, 'M', 'طح'), + (0xFCB9, 'M', 'ظم'), + (0xFCBA, 'M', 'عج'), ] - def _seg_47() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0xFCBF, "M", "فح"), - (0xFCC0, "M", "فخ"), - (0xFCC1, "M", "فم"), - (0xFCC2, "M", "قح"), - (0xFCC3, "M", "قم"), - (0xFCC4, "M", "كج"), - (0xFCC5, "M", "كح"), - (0xFCC6, "M", "كخ"), - (0xFCC7, "M", "كل"), - (0xFCC8, "M", "كم"), - (0xFCC9, "M", "لج"), - (0xFCCA, "M", "لح"), - (0xFCCB, "M", "لخ"), - (0xFCCC, "M", "لم"), - (0xFCCD, "M", "له"), - (0xFCCE, "M", "مج"), - (0xFCCF, "M", "مح"), - (0xFCD0, "M", "مخ"), - (0xFCD1, "M", "مم"), - (0xFCD2, "M", "نج"), - (0xFCD3, "M", "نح"), - (0xFCD4, "M", "نخ"), - (0xFCD5, "M", "نم"), - (0xFCD6, "M", "نه"), - (0xFCD7, "M", "هج"), - (0xFCD8, "M", "هم"), - (0xFCD9, "M", "هٰ"), - (0xFCDA, "M", "يج"), - (0xFCDB, "M", "يح"), - (0xFCDC, "M", "يخ"), - (0xFCDD, "M", "يم"), - (0xFCDE, "M", "يه"), - (0xFCDF, "M", "ئم"), - (0xFCE0, "M", "ئه"), - (0xFCE1, "M", "بم"), - (0xFCE2, "M", "به"), - (0xFCE3, "M", "تم"), - (0xFCE4, "M", "ته"), - (0xFCE5, "M", "ثم"), - (0xFCE6, "M", "ثه"), - (0xFCE7, "M", "سم"), - (0xFCE8, "M", "سه"), - (0xFCE9, "M", "شم"), - (0xFCEA, "M", "شه"), - (0xFCEB, "M", "كل"), - (0xFCEC, "M", "كم"), - (0xFCED, "M", "لم"), - (0xFCEE, "M", "نم"), - (0xFCEF, "M", "نه"), - (0xFCF0, "M", "يم"), - (0xFCF1, "M", "يه"), - (0xFCF2, "M", "ـَّ"), - (0xFCF3, "M", "ـُّ"), - (0xFCF4, "M", "ـِّ"), - (0xFCF5, "M", "طى"), - (0xFCF6, "M", "طي"), - (0xFCF7, "M", "عى"), - (0xFCF8, "M", "عي"), - (0xFCF9, "M", "غى"), - (0xFCFA, "M", "غي"), - (0xFCFB, "M", "سى"), - (0xFCFC, "M", "سي"), - (0xFCFD, "M", "شى"), - (0xFCFE, "M", "شي"), - (0xFCFF, "M", "حى"), - (0xFD00, "M", "حي"), - (0xFD01, "M", "جى"), - (0xFD02, "M", "جي"), - (0xFD03, "M", "خى"), - (0xFD04, "M", "خي"), - (0xFD05, "M", "صى"), - (0xFD06, "M", "صي"), - (0xFD07, "M", "ضى"), - (0xFD08, "M", "ضي"), - (0xFD09, "M", "شج"), - (0xFD0A, "M", "شح"), - (0xFD0B, "M", "شخ"), - (0xFD0C, "M", "شم"), - (0xFD0D, "M", "شر"), - (0xFD0E, "M", "سر"), - (0xFD0F, "M", "صر"), - (0xFD10, "M", "ضر"), - (0xFD11, "M", "طى"), - (0xFD12, "M", "طي"), - (0xFD13, "M", "عى"), - (0xFD14, "M", "عي"), - (0xFD15, "M", "غى"), - (0xFD16, "M", "غي"), - (0xFD17, "M", "سى"), - (0xFD18, "M", "سي"), - (0xFD19, "M", "شى"), - (0xFD1A, "M", "شي"), - (0xFD1B, "M", "حى"), - (0xFD1C, "M", "حي"), - (0xFD1D, "M", "جى"), - (0xFD1E, "M", "جي"), - (0xFD1F, "M", "خى"), - (0xFD20, "M", "خي"), - (0xFD21, "M", "صى"), - (0xFD22, "M", "صي"), + (0xFCBB, 'M', 'عم'), + (0xFCBC, 'M', 'غج'), + (0xFCBD, 'M', 'غم'), + (0xFCBE, 'M', 'فج'), + (0xFCBF, 'M', 'فح'), + (0xFCC0, 'M', 'فخ'), + (0xFCC1, 'M', 'فم'), + (0xFCC2, 'M', 'قح'), + (0xFCC3, 'M', 'قم'), + (0xFCC4, 'M', 'كج'), + (0xFCC5, 'M', 'كح'), + (0xFCC6, 'M', 'كخ'), + (0xFCC7, 'M', 'كل'), + (0xFCC8, 'M', 'كم'), + (0xFCC9, 'M', 'لج'), + (0xFCCA, 'M', 'لح'), + (0xFCCB, 'M', 'لخ'), + (0xFCCC, 'M', 'لم'), + (0xFCCD, 'M', 'له'), + (0xFCCE, 'M', 'مج'), + (0xFCCF, 'M', 'مح'), + (0xFCD0, 'M', 'مخ'), + (0xFCD1, 'M', 'مم'), + (0xFCD2, 'M', 'نج'), + (0xFCD3, 'M', 'نح'), + (0xFCD4, 'M', 'نخ'), + (0xFCD5, 'M', 'نم'), + (0xFCD6, 'M', 'نه'), + (0xFCD7, 'M', 'هج'), + (0xFCD8, 'M', 'هم'), + (0xFCD9, 'M', 'هٰ'), + (0xFCDA, 'M', 'يج'), + (0xFCDB, 'M', 'يح'), + (0xFCDC, 'M', 'يخ'), + (0xFCDD, 'M', 'يم'), + (0xFCDE, 'M', 'يه'), + (0xFCDF, 'M', 'ئم'), + (0xFCE0, 'M', 'ئه'), + (0xFCE1, 'M', 'بم'), + (0xFCE2, 'M', 'به'), + (0xFCE3, 'M', 'تم'), + (0xFCE4, 'M', 'ته'), + (0xFCE5, 'M', 'ثم'), + (0xFCE6, 'M', 'ثه'), + (0xFCE7, 'M', 'سم'), + (0xFCE8, 'M', 'سه'), + (0xFCE9, 'M', 'شم'), + (0xFCEA, 'M', 'شه'), + (0xFCEB, 'M', 'كل'), + (0xFCEC, 'M', 'كم'), + (0xFCED, 'M', 'لم'), + (0xFCEE, 'M', 'نم'), + (0xFCEF, 'M', 'نه'), + (0xFCF0, 'M', 'يم'), + (0xFCF1, 'M', 'يه'), + (0xFCF2, 'M', 'ـَّ'), + (0xFCF3, 'M', 'ـُّ'), + (0xFCF4, 'M', 'ـِّ'), + (0xFCF5, 'M', 'طى'), + (0xFCF6, 'M', 'طي'), + (0xFCF7, 'M', 'عى'), + (0xFCF8, 'M', 'عي'), + (0xFCF9, 'M', 'غى'), + (0xFCFA, 'M', 'غي'), + (0xFCFB, 'M', 'سى'), + (0xFCFC, 'M', 'سي'), + (0xFCFD, 'M', 'شى'), + (0xFCFE, 'M', 'شي'), + (0xFCFF, 'M', 'حى'), + (0xFD00, 'M', 'حي'), + (0xFD01, 'M', 'جى'), + (0xFD02, 'M', 'جي'), + (0xFD03, 'M', 'خى'), + (0xFD04, 'M', 'خي'), + (0xFD05, 'M', 'صى'), + (0xFD06, 'M', 'صي'), + (0xFD07, 'M', 'ضى'), + (0xFD08, 'M', 'ضي'), + (0xFD09, 'M', 'شج'), + (0xFD0A, 'M', 'شح'), + (0xFD0B, 'M', 'شخ'), + (0xFD0C, 'M', 'شم'), + (0xFD0D, 'M', 'شر'), + (0xFD0E, 'M', 'سر'), + (0xFD0F, 'M', 'صر'), + (0xFD10, 'M', 'ضر'), + (0xFD11, 'M', 'طى'), + (0xFD12, 'M', 'طي'), + (0xFD13, 'M', 'عى'), + (0xFD14, 'M', 'عي'), + (0xFD15, 'M', 'غى'), + (0xFD16, 'M', 'غي'), + (0xFD17, 'M', 'سى'), + (0xFD18, 'M', 'سي'), + (0xFD19, 'M', 'شى'), + (0xFD1A, 'M', 'شي'), + (0xFD1B, 'M', 'حى'), + (0xFD1C, 'M', 'حي'), + (0xFD1D, 'M', 'جى'), + (0xFD1E, 'M', 'جي'), ] - def _seg_48() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0xFD23, "M", "ضى"), - (0xFD24, "M", "ضي"), - (0xFD25, "M", "شج"), - (0xFD26, "M", "شح"), - (0xFD27, "M", "شخ"), - (0xFD28, "M", "شم"), - (0xFD29, "M", "شر"), - (0xFD2A, "M", "سر"), - (0xFD2B, "M", "صر"), - (0xFD2C, "M", "ضر"), - (0xFD2D, "M", "شج"), - (0xFD2E, "M", "شح"), - (0xFD2F, "M", "شخ"), - (0xFD30, "M", "شم"), - (0xFD31, "M", "سه"), - (0xFD32, "M", "شه"), - (0xFD33, "M", "طم"), - (0xFD34, "M", "سج"), - (0xFD35, "M", "سح"), - (0xFD36, "M", "سخ"), - (0xFD37, "M", "شج"), - (0xFD38, "M", "شح"), - (0xFD39, "M", "شخ"), - (0xFD3A, "M", "طم"), - (0xFD3B, "M", "ظم"), - (0xFD3C, "M", "اً"), - (0xFD3E, "V"), - (0xFD50, "M", "تجم"), - (0xFD51, "M", "تحج"), - (0xFD53, "M", "تحم"), - (0xFD54, "M", "تخم"), - (0xFD55, "M", "تمج"), - (0xFD56, "M", "تمح"), - (0xFD57, "M", "تمخ"), - (0xFD58, "M", "جمح"), - (0xFD5A, "M", "حمي"), - (0xFD5B, "M", "حمى"), - (0xFD5C, "M", "سحج"), - (0xFD5D, "M", "سجح"), - (0xFD5E, "M", "سجى"), - (0xFD5F, "M", "سمح"), - (0xFD61, "M", "سمج"), - (0xFD62, "M", "سمم"), - (0xFD64, "M", "صحح"), - (0xFD66, "M", "صمم"), - (0xFD67, "M", "شحم"), - (0xFD69, "M", "شجي"), - (0xFD6A, "M", "شمخ"), - (0xFD6C, "M", "شمم"), - (0xFD6E, "M", "ضحى"), - (0xFD6F, "M", "ضخم"), - (0xFD71, "M", "طمح"), - (0xFD73, "M", "طمم"), - (0xFD74, "M", "طمي"), - (0xFD75, "M", "عجم"), - (0xFD76, "M", "عمم"), - (0xFD78, "M", "عمى"), - (0xFD79, "M", "غمم"), - (0xFD7A, "M", "غمي"), - (0xFD7B, "M", "غمى"), - (0xFD7C, "M", "فخم"), - (0xFD7E, "M", "قمح"), - (0xFD7F, "M", "قمم"), - (0xFD80, "M", "لحم"), - (0xFD81, "M", "لحي"), - (0xFD82, "M", "لحى"), - (0xFD83, "M", "لجج"), - (0xFD85, "M", "لخم"), - (0xFD87, "M", "لمح"), - (0xFD89, "M", "محج"), - (0xFD8A, "M", "محم"), - (0xFD8B, "M", "محي"), - (0xFD8C, "M", "مجح"), - (0xFD8D, "M", "مجم"), - (0xFD8E, "M", "مخج"), - (0xFD8F, "M", "مخم"), - (0xFD90, "X"), - (0xFD92, "M", "مجخ"), - (0xFD93, "M", "همج"), - (0xFD94, "M", "همم"), - (0xFD95, "M", "نحم"), - (0xFD96, "M", "نحى"), - (0xFD97, "M", "نجم"), - (0xFD99, "M", "نجى"), - (0xFD9A, "M", "نمي"), - (0xFD9B, "M", "نمى"), - (0xFD9C, "M", "يمم"), - (0xFD9E, "M", "بخي"), - (0xFD9F, "M", "تجي"), - (0xFDA0, "M", "تجى"), - (0xFDA1, "M", "تخي"), - (0xFDA2, "M", "تخى"), - (0xFDA3, "M", "تمي"), - (0xFDA4, "M", "تمى"), - (0xFDA5, "M", "جمي"), - (0xFDA6, "M", "جحى"), - (0xFDA7, "M", "جمى"), - (0xFDA8, "M", "سخى"), - (0xFDA9, "M", "صحي"), - (0xFDAA, "M", "شحي"), + (0xFD1F, 'M', 'خى'), + (0xFD20, 'M', 'خي'), + (0xFD21, 'M', 'صى'), + (0xFD22, 'M', 'صي'), + (0xFD23, 'M', 'ضى'), + (0xFD24, 'M', 'ضي'), + (0xFD25, 'M', 'شج'), + (0xFD26, 'M', 'شح'), + (0xFD27, 'M', 'شخ'), + (0xFD28, 'M', 'شم'), + (0xFD29, 'M', 'شر'), + (0xFD2A, 'M', 'سر'), + (0xFD2B, 'M', 'صر'), + (0xFD2C, 'M', 'ضر'), + (0xFD2D, 'M', 'شج'), + (0xFD2E, 'M', 'شح'), + (0xFD2F, 'M', 'شخ'), + (0xFD30, 'M', 'شم'), + (0xFD31, 'M', 'سه'), + (0xFD32, 'M', 'شه'), + (0xFD33, 'M', 'طم'), + (0xFD34, 'M', 'سج'), + (0xFD35, 'M', 'سح'), + (0xFD36, 'M', 'سخ'), + (0xFD37, 'M', 'شج'), + (0xFD38, 'M', 'شح'), + (0xFD39, 'M', 'شخ'), + (0xFD3A, 'M', 'طم'), + (0xFD3B, 'M', 'ظم'), + (0xFD3C, 'M', 'اً'), + (0xFD3E, 'V'), + (0xFD50, 'M', 'تجم'), + (0xFD51, 'M', 'تحج'), + (0xFD53, 'M', 'تحم'), + (0xFD54, 'M', 'تخم'), + (0xFD55, 'M', 'تمج'), + (0xFD56, 'M', 'تمح'), + (0xFD57, 'M', 'تمخ'), + (0xFD58, 'M', 'جمح'), + (0xFD5A, 'M', 'حمي'), + (0xFD5B, 'M', 'حمى'), + (0xFD5C, 'M', 'سحج'), + (0xFD5D, 'M', 'سجح'), + (0xFD5E, 'M', 'سجى'), + (0xFD5F, 'M', 'سمح'), + (0xFD61, 'M', 'سمج'), + (0xFD62, 'M', 'سمم'), + (0xFD64, 'M', 'صحح'), + (0xFD66, 'M', 'صمم'), + (0xFD67, 'M', 'شحم'), + (0xFD69, 'M', 'شجي'), + (0xFD6A, 'M', 'شمخ'), + (0xFD6C, 'M', 'شمم'), + (0xFD6E, 'M', 'ضحى'), + (0xFD6F, 'M', 'ضخم'), + (0xFD71, 'M', 'طمح'), + (0xFD73, 'M', 'طمم'), + (0xFD74, 'M', 'طمي'), + (0xFD75, 'M', 'عجم'), + (0xFD76, 'M', 'عمم'), + (0xFD78, 'M', 'عمى'), + (0xFD79, 'M', 'غمم'), + (0xFD7A, 'M', 'غمي'), + (0xFD7B, 'M', 'غمى'), + (0xFD7C, 'M', 'فخم'), + (0xFD7E, 'M', 'قمح'), + (0xFD7F, 'M', 'قمم'), + (0xFD80, 'M', 'لحم'), + (0xFD81, 'M', 'لحي'), + (0xFD82, 'M', 'لحى'), + (0xFD83, 'M', 'لجج'), + (0xFD85, 'M', 'لخم'), + (0xFD87, 'M', 'لمح'), + (0xFD89, 'M', 'محج'), + (0xFD8A, 'M', 'محم'), + (0xFD8B, 'M', 'محي'), + (0xFD8C, 'M', 'مجح'), + (0xFD8D, 'M', 'مجم'), + (0xFD8E, 'M', 'مخج'), + (0xFD8F, 'M', 'مخم'), + (0xFD90, 'X'), + (0xFD92, 'M', 'مجخ'), + (0xFD93, 'M', 'همج'), + (0xFD94, 'M', 'همم'), + (0xFD95, 'M', 'نحم'), + (0xFD96, 'M', 'نحى'), + (0xFD97, 'M', 'نجم'), + (0xFD99, 'M', 'نجى'), + (0xFD9A, 'M', 'نمي'), + (0xFD9B, 'M', 'نمى'), + (0xFD9C, 'M', 'يمم'), + (0xFD9E, 'M', 'بخي'), + (0xFD9F, 'M', 'تجي'), + (0xFDA0, 'M', 'تجى'), + (0xFDA1, 'M', 'تخي'), + (0xFDA2, 'M', 'تخى'), + (0xFDA3, 'M', 'تمي'), + (0xFDA4, 'M', 'تمى'), + (0xFDA5, 'M', 'جمي'), + (0xFDA6, 'M', 'جحى'), ] - def _seg_49() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0xFDAB, "M", "ضحي"), - (0xFDAC, "M", "لجي"), - (0xFDAD, "M", "لمي"), - (0xFDAE, "M", "يحي"), - (0xFDAF, "M", "يجي"), - (0xFDB0, "M", "يمي"), - (0xFDB1, "M", "ممي"), - (0xFDB2, "M", "قمي"), - (0xFDB3, "M", "نحي"), - (0xFDB4, "M", "قمح"), - (0xFDB5, "M", "لحم"), - (0xFDB6, "M", "عمي"), - (0xFDB7, "M", "كمي"), - (0xFDB8, "M", "نجح"), - (0xFDB9, "M", "مخي"), - (0xFDBA, "M", "لجم"), - (0xFDBB, "M", "كمم"), - (0xFDBC, "M", "لجم"), - (0xFDBD, "M", "نجح"), - (0xFDBE, "M", "جحي"), - (0xFDBF, "M", "حجي"), - (0xFDC0, "M", "مجي"), - (0xFDC1, "M", "فمي"), - (0xFDC2, "M", "بحي"), - (0xFDC3, "M", "كمم"), - (0xFDC4, "M", "عجم"), - (0xFDC5, "M", "صمم"), - (0xFDC6, "M", "سخي"), - (0xFDC7, "M", "نجي"), - (0xFDC8, "X"), - (0xFDCF, "V"), - (0xFDD0, "X"), - (0xFDF0, "M", "صلے"), - (0xFDF1, "M", "قلے"), - (0xFDF2, "M", "الله"), - (0xFDF3, "M", "اكبر"), - (0xFDF4, "M", "محمد"), - (0xFDF5, "M", "صلعم"), - (0xFDF6, "M", "رسول"), - (0xFDF7, "M", "عليه"), - (0xFDF8, "M", "وسلم"), - (0xFDF9, "M", "صلى"), - (0xFDFA, "3", "صلى الله عليه وسلم"), - (0xFDFB, "3", "جل جلاله"), - (0xFDFC, "M", "ریال"), - (0xFDFD, "V"), - (0xFE00, "I"), - (0xFE10, "3", ","), - (0xFE11, "M", "、"), - (0xFE12, "X"), - (0xFE13, "3", ":"), - (0xFE14, "3", ";"), - (0xFE15, "3", "!"), - (0xFE16, "3", "?"), - (0xFE17, "M", "〖"), - (0xFE18, "M", "〗"), - (0xFE19, "X"), - (0xFE20, "V"), - (0xFE30, "X"), - (0xFE31, "M", "—"), - (0xFE32, "M", "–"), - (0xFE33, "3", "_"), - (0xFE35, "3", "("), - (0xFE36, "3", ")"), - (0xFE37, "3", "{"), - (0xFE38, "3", "}"), - (0xFE39, "M", "〔"), - (0xFE3A, "M", "〕"), - (0xFE3B, "M", "【"), - (0xFE3C, "M", "】"), - (0xFE3D, "M", "《"), - (0xFE3E, "M", "》"), - (0xFE3F, "M", "〈"), - (0xFE40, "M", "〉"), - (0xFE41, "M", "「"), - (0xFE42, "M", "」"), - (0xFE43, "M", "『"), - (0xFE44, "M", "』"), - (0xFE45, "V"), - (0xFE47, "3", "["), - (0xFE48, "3", "]"), - (0xFE49, "3", " ̅"), - (0xFE4D, "3", "_"), - (0xFE50, "3", ","), - (0xFE51, "M", "、"), - (0xFE52, "X"), - (0xFE54, "3", ";"), - (0xFE55, "3", ":"), - (0xFE56, "3", "?"), - (0xFE57, "3", "!"), - (0xFE58, "M", "—"), - (0xFE59, "3", "("), - (0xFE5A, "3", ")"), - (0xFE5B, "3", "{"), - (0xFE5C, "3", "}"), - (0xFE5D, "M", "〔"), - (0xFE5E, "M", "〕"), - (0xFE5F, "3", "#"), - (0xFE60, "3", "&"), - (0xFE61, "3", "*"), + (0xFDA7, 'M', 'جمى'), + (0xFDA8, 'M', 'سخى'), + (0xFDA9, 'M', 'صحي'), + (0xFDAA, 'M', 'شحي'), + (0xFDAB, 'M', 'ضحي'), + (0xFDAC, 'M', 'لجي'), + (0xFDAD, 'M', 'لمي'), + (0xFDAE, 'M', 'يحي'), + (0xFDAF, 'M', 'يجي'), + (0xFDB0, 'M', 'يمي'), + (0xFDB1, 'M', 'ممي'), + (0xFDB2, 'M', 'قمي'), + (0xFDB3, 'M', 'نحي'), + (0xFDB4, 'M', 'قمح'), + (0xFDB5, 'M', 'لحم'), + (0xFDB6, 'M', 'عمي'), + (0xFDB7, 'M', 'كمي'), + (0xFDB8, 'M', 'نجح'), + (0xFDB9, 'M', 'مخي'), + (0xFDBA, 'M', 'لجم'), + (0xFDBB, 'M', 'كمم'), + (0xFDBC, 'M', 'لجم'), + (0xFDBD, 'M', 'نجح'), + (0xFDBE, 'M', 'جحي'), + (0xFDBF, 'M', 'حجي'), + (0xFDC0, 'M', 'مجي'), + (0xFDC1, 'M', 'فمي'), + (0xFDC2, 'M', 'بحي'), + (0xFDC3, 'M', 'كمم'), + (0xFDC4, 'M', 'عجم'), + (0xFDC5, 'M', 'صمم'), + (0xFDC6, 'M', 'سخي'), + (0xFDC7, 'M', 'نجي'), + (0xFDC8, 'X'), + (0xFDCF, 'V'), + (0xFDD0, 'X'), + (0xFDF0, 'M', 'صلے'), + (0xFDF1, 'M', 'قلے'), + (0xFDF2, 'M', 'الله'), + (0xFDF3, 'M', 'اكبر'), + (0xFDF4, 'M', 'محمد'), + (0xFDF5, 'M', 'صلعم'), + (0xFDF6, 'M', 'رسول'), + (0xFDF7, 'M', 'عليه'), + (0xFDF8, 'M', 'وسلم'), + (0xFDF9, 'M', 'صلى'), + (0xFDFA, '3', 'صلى الله عليه وسلم'), + (0xFDFB, '3', 'جل جلاله'), + (0xFDFC, 'M', 'ریال'), + (0xFDFD, 'V'), + (0xFE00, 'I'), + (0xFE10, '3', ','), + (0xFE11, 'M', '、'), + (0xFE12, 'X'), + (0xFE13, '3', ':'), + (0xFE14, '3', ';'), + (0xFE15, '3', '!'), + (0xFE16, '3', '?'), + (0xFE17, 'M', '〖'), + (0xFE18, 'M', '〗'), + (0xFE19, 'X'), + (0xFE20, 'V'), + (0xFE30, 'X'), + (0xFE31, 'M', '—'), + (0xFE32, 'M', '–'), + (0xFE33, '3', '_'), + (0xFE35, '3', '('), + (0xFE36, '3', ')'), + (0xFE37, '3', '{'), + (0xFE38, '3', '}'), + (0xFE39, 'M', '〔'), + (0xFE3A, 'M', '〕'), + (0xFE3B, 'M', '【'), + (0xFE3C, 'M', '】'), + (0xFE3D, 'M', '《'), + (0xFE3E, 'M', '》'), + (0xFE3F, 'M', '〈'), + (0xFE40, 'M', '〉'), + (0xFE41, 'M', '「'), + (0xFE42, 'M', '」'), + (0xFE43, 'M', '『'), + (0xFE44, 'M', '』'), + (0xFE45, 'V'), + (0xFE47, '3', '['), + (0xFE48, '3', ']'), + (0xFE49, '3', ' ̅'), + (0xFE4D, '3', '_'), + (0xFE50, '3', ','), + (0xFE51, 'M', '、'), + (0xFE52, 'X'), + (0xFE54, '3', ';'), + (0xFE55, '3', ':'), + (0xFE56, '3', '?'), + (0xFE57, '3', '!'), + (0xFE58, 'M', '—'), + (0xFE59, '3', '('), + (0xFE5A, '3', ')'), + (0xFE5B, '3', '{'), + (0xFE5C, '3', '}'), + (0xFE5D, 'M', '〔'), ] - def _seg_50() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0xFE62, "3", "+"), - (0xFE63, "M", "-"), - (0xFE64, "3", "<"), - (0xFE65, "3", ">"), - (0xFE66, "3", "="), - (0xFE67, "X"), - (0xFE68, "3", "\\"), - (0xFE69, "3", "$"), - (0xFE6A, "3", "%"), - (0xFE6B, "3", "@"), - (0xFE6C, "X"), - (0xFE70, "3", " ً"), - (0xFE71, "M", "ـً"), - (0xFE72, "3", " ٌ"), - (0xFE73, "V"), - (0xFE74, "3", " ٍ"), - (0xFE75, "X"), - (0xFE76, "3", " َ"), - (0xFE77, "M", "ـَ"), - (0xFE78, "3", " ُ"), - (0xFE79, "M", "ـُ"), - (0xFE7A, "3", " ِ"), - (0xFE7B, "M", "ـِ"), - (0xFE7C, "3", " ّ"), - (0xFE7D, "M", "ـّ"), - (0xFE7E, "3", " ْ"), - (0xFE7F, "M", "ـْ"), - (0xFE80, "M", "ء"), - (0xFE81, "M", "آ"), - (0xFE83, "M", "أ"), - (0xFE85, "M", "ؤ"), - (0xFE87, "M", "إ"), - (0xFE89, "M", "ئ"), - (0xFE8D, "M", "ا"), - (0xFE8F, "M", "ب"), - (0xFE93, "M", "ة"), - (0xFE95, "M", "ت"), - (0xFE99, "M", "ث"), - (0xFE9D, "M", "ج"), - (0xFEA1, "M", "ح"), - (0xFEA5, "M", "خ"), - (0xFEA9, "M", "د"), - (0xFEAB, "M", "ذ"), - (0xFEAD, "M", "ر"), - (0xFEAF, "M", "ز"), - (0xFEB1, "M", "س"), - (0xFEB5, "M", "ش"), - (0xFEB9, "M", "ص"), - (0xFEBD, "M", "ض"), - (0xFEC1, "M", "ط"), - (0xFEC5, "M", "ظ"), - (0xFEC9, "M", "ع"), - (0xFECD, "M", "غ"), - (0xFED1, "M", "ف"), - (0xFED5, "M", "ق"), - (0xFED9, "M", "ك"), - (0xFEDD, "M", "ل"), - (0xFEE1, "M", "م"), - (0xFEE5, "M", "ن"), - (0xFEE9, "M", "ه"), - (0xFEED, "M", "و"), - (0xFEEF, "M", "ى"), - (0xFEF1, "M", "ي"), - (0xFEF5, "M", "لآ"), - (0xFEF7, "M", "لأ"), - (0xFEF9, "M", "لإ"), - (0xFEFB, "M", "لا"), - (0xFEFD, "X"), - (0xFEFF, "I"), - (0xFF00, "X"), - (0xFF01, "3", "!"), - (0xFF02, "3", '"'), - (0xFF03, "3", "#"), - (0xFF04, "3", "$"), - (0xFF05, "3", "%"), - (0xFF06, "3", "&"), - (0xFF07, "3", "'"), - (0xFF08, "3", "("), - (0xFF09, "3", ")"), - (0xFF0A, "3", "*"), - (0xFF0B, "3", "+"), - (0xFF0C, "3", ","), - (0xFF0D, "M", "-"), - (0xFF0E, "M", "."), - (0xFF0F, "3", "/"), - (0xFF10, "M", "0"), - (0xFF11, "M", "1"), - (0xFF12, "M", "2"), - (0xFF13, "M", "3"), - (0xFF14, "M", "4"), - (0xFF15, "M", "5"), - (0xFF16, "M", "6"), - (0xFF17, "M", "7"), - (0xFF18, "M", "8"), - (0xFF19, "M", "9"), - (0xFF1A, "3", ":"), - (0xFF1B, "3", ";"), - (0xFF1C, "3", "<"), - (0xFF1D, "3", "="), - (0xFF1E, "3", ">"), + (0xFE5E, 'M', '〕'), + (0xFE5F, '3', '#'), + (0xFE60, '3', '&'), + (0xFE61, '3', '*'), + (0xFE62, '3', '+'), + (0xFE63, 'M', '-'), + (0xFE64, '3', '<'), + (0xFE65, '3', '>'), + (0xFE66, '3', '='), + (0xFE67, 'X'), + (0xFE68, '3', '\\'), + (0xFE69, '3', '$'), + (0xFE6A, '3', '%'), + (0xFE6B, '3', '@'), + (0xFE6C, 'X'), + (0xFE70, '3', ' ً'), + (0xFE71, 'M', 'ـً'), + (0xFE72, '3', ' ٌ'), + (0xFE73, 'V'), + (0xFE74, '3', ' ٍ'), + (0xFE75, 'X'), + (0xFE76, '3', ' َ'), + (0xFE77, 'M', 'ـَ'), + (0xFE78, '3', ' ُ'), + (0xFE79, 'M', 'ـُ'), + (0xFE7A, '3', ' ِ'), + (0xFE7B, 'M', 'ـِ'), + (0xFE7C, '3', ' ّ'), + (0xFE7D, 'M', 'ـّ'), + (0xFE7E, '3', ' ْ'), + (0xFE7F, 'M', 'ـْ'), + (0xFE80, 'M', 'ء'), + (0xFE81, 'M', 'آ'), + (0xFE83, 'M', 'أ'), + (0xFE85, 'M', 'ؤ'), + (0xFE87, 'M', 'إ'), + (0xFE89, 'M', 'ئ'), + (0xFE8D, 'M', 'ا'), + (0xFE8F, 'M', 'ب'), + (0xFE93, 'M', 'ة'), + (0xFE95, 'M', 'ت'), + (0xFE99, 'M', 'ث'), + (0xFE9D, 'M', 'ج'), + (0xFEA1, 'M', 'ح'), + (0xFEA5, 'M', 'خ'), + (0xFEA9, 'M', 'د'), + (0xFEAB, 'M', 'ذ'), + (0xFEAD, 'M', 'ر'), + (0xFEAF, 'M', 'ز'), + (0xFEB1, 'M', 'س'), + (0xFEB5, 'M', 'ش'), + (0xFEB9, 'M', 'ص'), + (0xFEBD, 'M', 'ض'), + (0xFEC1, 'M', 'ط'), + (0xFEC5, 'M', 'ظ'), + (0xFEC9, 'M', 'ع'), + (0xFECD, 'M', 'غ'), + (0xFED1, 'M', 'ف'), + (0xFED5, 'M', 'ق'), + (0xFED9, 'M', 'ك'), + (0xFEDD, 'M', 'ل'), + (0xFEE1, 'M', 'م'), + (0xFEE5, 'M', 'ن'), + (0xFEE9, 'M', 'ه'), + (0xFEED, 'M', 'و'), + (0xFEEF, 'M', 'ى'), + (0xFEF1, 'M', 'ي'), + (0xFEF5, 'M', 'لآ'), + (0xFEF7, 'M', 'لأ'), + (0xFEF9, 'M', 'لإ'), + (0xFEFB, 'M', 'لا'), + (0xFEFD, 'X'), + (0xFEFF, 'I'), + (0xFF00, 'X'), + (0xFF01, '3', '!'), + (0xFF02, '3', '"'), + (0xFF03, '3', '#'), + (0xFF04, '3', '$'), + (0xFF05, '3', '%'), + (0xFF06, '3', '&'), + (0xFF07, '3', '\''), + (0xFF08, '3', '('), + (0xFF09, '3', ')'), + (0xFF0A, '3', '*'), + (0xFF0B, '3', '+'), + (0xFF0C, '3', ','), + (0xFF0D, 'M', '-'), + (0xFF0E, 'M', '.'), + (0xFF0F, '3', '/'), + (0xFF10, 'M', '0'), + (0xFF11, 'M', '1'), + (0xFF12, 'M', '2'), + (0xFF13, 'M', '3'), + (0xFF14, 'M', '4'), + (0xFF15, 'M', '5'), + (0xFF16, 'M', '6'), + (0xFF17, 'M', '7'), + (0xFF18, 'M', '8'), + (0xFF19, 'M', '9'), + (0xFF1A, '3', ':'), ] - def _seg_51() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0xFF1F, "3", "?"), - (0xFF20, "3", "@"), - (0xFF21, "M", "a"), - (0xFF22, "M", "b"), - (0xFF23, "M", "c"), - (0xFF24, "M", "d"), - (0xFF25, "M", "e"), - (0xFF26, "M", "f"), - (0xFF27, "M", "g"), - (0xFF28, "M", "h"), - (0xFF29, "M", "i"), - (0xFF2A, "M", "j"), - (0xFF2B, "M", "k"), - (0xFF2C, "M", "l"), - (0xFF2D, "M", "m"), - (0xFF2E, "M", "n"), - (0xFF2F, "M", "o"), - (0xFF30, "M", "p"), - (0xFF31, "M", "q"), - (0xFF32, "M", "r"), - (0xFF33, "M", "s"), - (0xFF34, "M", "t"), - (0xFF35, "M", "u"), - (0xFF36, "M", "v"), - (0xFF37, "M", "w"), - (0xFF38, "M", "x"), - (0xFF39, "M", "y"), - (0xFF3A, "M", "z"), - (0xFF3B, "3", "["), - (0xFF3C, "3", "\\"), - (0xFF3D, "3", "]"), - (0xFF3E, "3", "^"), - (0xFF3F, "3", "_"), - (0xFF40, "3", "`"), - (0xFF41, "M", "a"), - (0xFF42, "M", "b"), - (0xFF43, "M", "c"), - (0xFF44, "M", "d"), - (0xFF45, "M", "e"), - (0xFF46, "M", "f"), - (0xFF47, "M", "g"), - (0xFF48, "M", "h"), - (0xFF49, "M", "i"), - (0xFF4A, "M", "j"), - (0xFF4B, "M", "k"), - (0xFF4C, "M", "l"), - (0xFF4D, "M", "m"), - (0xFF4E, "M", "n"), - (0xFF4F, "M", "o"), - (0xFF50, "M", "p"), - (0xFF51, "M", "q"), - (0xFF52, "M", "r"), - (0xFF53, "M", "s"), - (0xFF54, "M", "t"), - (0xFF55, "M", "u"), - (0xFF56, "M", "v"), - (0xFF57, "M", "w"), - (0xFF58, "M", "x"), - (0xFF59, "M", "y"), - (0xFF5A, "M", "z"), - (0xFF5B, "3", "{"), - (0xFF5C, "3", "|"), - (0xFF5D, "3", "}"), - (0xFF5E, "3", "~"), - (0xFF5F, "M", "⦅"), - (0xFF60, "M", "⦆"), - (0xFF61, "M", "."), - (0xFF62, "M", "「"), - (0xFF63, "M", "」"), - (0xFF64, "M", "、"), - (0xFF65, "M", "・"), - (0xFF66, "M", "ヲ"), - (0xFF67, "M", "ァ"), - (0xFF68, "M", "ィ"), - (0xFF69, "M", "ゥ"), - (0xFF6A, "M", "ェ"), - (0xFF6B, "M", "ォ"), - (0xFF6C, "M", "ャ"), - (0xFF6D, "M", "ュ"), - (0xFF6E, "M", "ョ"), - (0xFF6F, "M", "ッ"), - (0xFF70, "M", "ー"), - (0xFF71, "M", "ア"), - (0xFF72, "M", "イ"), - (0xFF73, "M", "ウ"), - (0xFF74, "M", "エ"), - (0xFF75, "M", "オ"), - (0xFF76, "M", "カ"), - (0xFF77, "M", "キ"), - (0xFF78, "M", "ク"), - (0xFF79, "M", "ケ"), - (0xFF7A, "M", "コ"), - (0xFF7B, "M", "サ"), - (0xFF7C, "M", "シ"), - (0xFF7D, "M", "ス"), - (0xFF7E, "M", "セ"), - (0xFF7F, "M", "ソ"), - (0xFF80, "M", "タ"), - (0xFF81, "M", "チ"), - (0xFF82, "M", "ツ"), + (0xFF1B, '3', ';'), + (0xFF1C, '3', '<'), + (0xFF1D, '3', '='), + (0xFF1E, '3', '>'), + (0xFF1F, '3', '?'), + (0xFF20, '3', '@'), + (0xFF21, 'M', 'a'), + (0xFF22, 'M', 'b'), + (0xFF23, 'M', 'c'), + (0xFF24, 'M', 'd'), + (0xFF25, 'M', 'e'), + (0xFF26, 'M', 'f'), + (0xFF27, 'M', 'g'), + (0xFF28, 'M', 'h'), + (0xFF29, 'M', 'i'), + (0xFF2A, 'M', 'j'), + (0xFF2B, 'M', 'k'), + (0xFF2C, 'M', 'l'), + (0xFF2D, 'M', 'm'), + (0xFF2E, 'M', 'n'), + (0xFF2F, 'M', 'o'), + (0xFF30, 'M', 'p'), + (0xFF31, 'M', 'q'), + (0xFF32, 'M', 'r'), + (0xFF33, 'M', 's'), + (0xFF34, 'M', 't'), + (0xFF35, 'M', 'u'), + (0xFF36, 'M', 'v'), + (0xFF37, 'M', 'w'), + (0xFF38, 'M', 'x'), + (0xFF39, 'M', 'y'), + (0xFF3A, 'M', 'z'), + (0xFF3B, '3', '['), + (0xFF3C, '3', '\\'), + (0xFF3D, '3', ']'), + (0xFF3E, '3', '^'), + (0xFF3F, '3', '_'), + (0xFF40, '3', '`'), + (0xFF41, 'M', 'a'), + (0xFF42, 'M', 'b'), + (0xFF43, 'M', 'c'), + (0xFF44, 'M', 'd'), + (0xFF45, 'M', 'e'), + (0xFF46, 'M', 'f'), + (0xFF47, 'M', 'g'), + (0xFF48, 'M', 'h'), + (0xFF49, 'M', 'i'), + (0xFF4A, 'M', 'j'), + (0xFF4B, 'M', 'k'), + (0xFF4C, 'M', 'l'), + (0xFF4D, 'M', 'm'), + (0xFF4E, 'M', 'n'), + (0xFF4F, 'M', 'o'), + (0xFF50, 'M', 'p'), + (0xFF51, 'M', 'q'), + (0xFF52, 'M', 'r'), + (0xFF53, 'M', 's'), + (0xFF54, 'M', 't'), + (0xFF55, 'M', 'u'), + (0xFF56, 'M', 'v'), + (0xFF57, 'M', 'w'), + (0xFF58, 'M', 'x'), + (0xFF59, 'M', 'y'), + (0xFF5A, 'M', 'z'), + (0xFF5B, '3', '{'), + (0xFF5C, '3', '|'), + (0xFF5D, '3', '}'), + (0xFF5E, '3', '~'), + (0xFF5F, 'M', '⦅'), + (0xFF60, 'M', '⦆'), + (0xFF61, 'M', '.'), + (0xFF62, 'M', '「'), + (0xFF63, 'M', '」'), + (0xFF64, 'M', '、'), + (0xFF65, 'M', '・'), + (0xFF66, 'M', 'ヲ'), + (0xFF67, 'M', 'ァ'), + (0xFF68, 'M', 'ィ'), + (0xFF69, 'M', 'ゥ'), + (0xFF6A, 'M', 'ェ'), + (0xFF6B, 'M', 'ォ'), + (0xFF6C, 'M', 'ャ'), + (0xFF6D, 'M', 'ュ'), + (0xFF6E, 'M', 'ョ'), + (0xFF6F, 'M', 'ッ'), + (0xFF70, 'M', 'ー'), + (0xFF71, 'M', 'ア'), + (0xFF72, 'M', 'イ'), + (0xFF73, 'M', 'ウ'), + (0xFF74, 'M', 'エ'), + (0xFF75, 'M', 'オ'), + (0xFF76, 'M', 'カ'), + (0xFF77, 'M', 'キ'), + (0xFF78, 'M', 'ク'), + (0xFF79, 'M', 'ケ'), + (0xFF7A, 'M', 'コ'), + (0xFF7B, 'M', 'サ'), + (0xFF7C, 'M', 'シ'), + (0xFF7D, 'M', 'ス'), + (0xFF7E, 'M', 'セ'), ] - def _seg_52() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0xFF83, "M", "テ"), - (0xFF84, "M", "ト"), - (0xFF85, "M", "ナ"), - (0xFF86, "M", "ニ"), - (0xFF87, "M", "ヌ"), - (0xFF88, "M", "ネ"), - (0xFF89, "M", "ノ"), - (0xFF8A, "M", "ハ"), - (0xFF8B, "M", "ヒ"), - (0xFF8C, "M", "フ"), - (0xFF8D, "M", "ヘ"), - (0xFF8E, "M", "ホ"), - (0xFF8F, "M", "マ"), - (0xFF90, "M", "ミ"), - (0xFF91, "M", "ム"), - (0xFF92, "M", "メ"), - (0xFF93, "M", "モ"), - (0xFF94, "M", "ヤ"), - (0xFF95, "M", "ユ"), - (0xFF96, "M", "ヨ"), - (0xFF97, "M", "ラ"), - (0xFF98, "M", "リ"), - (0xFF99, "M", "ル"), - (0xFF9A, "M", "レ"), - (0xFF9B, "M", "ロ"), - (0xFF9C, "M", "ワ"), - (0xFF9D, "M", "ン"), - (0xFF9E, "M", "゙"), - (0xFF9F, "M", "゚"), - (0xFFA0, "X"), - (0xFFA1, "M", "ᄀ"), - (0xFFA2, "M", "ᄁ"), - (0xFFA3, "M", "ᆪ"), - (0xFFA4, "M", "ᄂ"), - (0xFFA5, "M", "ᆬ"), - (0xFFA6, "M", "ᆭ"), - (0xFFA7, "M", "ᄃ"), - (0xFFA8, "M", "ᄄ"), - (0xFFA9, "M", "ᄅ"), - (0xFFAA, "M", "ᆰ"), - (0xFFAB, "M", "ᆱ"), - (0xFFAC, "M", "ᆲ"), - (0xFFAD, "M", "ᆳ"), - (0xFFAE, "M", "ᆴ"), - (0xFFAF, "M", "ᆵ"), - (0xFFB0, "M", "ᄚ"), - (0xFFB1, "M", "ᄆ"), - (0xFFB2, "M", "ᄇ"), - (0xFFB3, "M", "ᄈ"), - (0xFFB4, "M", "ᄡ"), - (0xFFB5, "M", "ᄉ"), - (0xFFB6, "M", "ᄊ"), - (0xFFB7, "M", "ᄋ"), - (0xFFB8, "M", "ᄌ"), - (0xFFB9, "M", "ᄍ"), - (0xFFBA, "M", "ᄎ"), - (0xFFBB, "M", "ᄏ"), - (0xFFBC, "M", "ᄐ"), - (0xFFBD, "M", "ᄑ"), - (0xFFBE, "M", "ᄒ"), - (0xFFBF, "X"), - (0xFFC2, "M", "ᅡ"), - (0xFFC3, "M", "ᅢ"), - (0xFFC4, "M", "ᅣ"), - (0xFFC5, "M", "ᅤ"), - (0xFFC6, "M", "ᅥ"), - (0xFFC7, "M", "ᅦ"), - (0xFFC8, "X"), - (0xFFCA, "M", "ᅧ"), - (0xFFCB, "M", "ᅨ"), - (0xFFCC, "M", "ᅩ"), - (0xFFCD, "M", "ᅪ"), - (0xFFCE, "M", "ᅫ"), - (0xFFCF, "M", "ᅬ"), - (0xFFD0, "X"), - (0xFFD2, "M", "ᅭ"), - (0xFFD3, "M", "ᅮ"), - (0xFFD4, "M", "ᅯ"), - (0xFFD5, "M", "ᅰ"), - (0xFFD6, "M", "ᅱ"), - (0xFFD7, "M", "ᅲ"), - (0xFFD8, "X"), - (0xFFDA, "M", "ᅳ"), - (0xFFDB, "M", "ᅴ"), - (0xFFDC, "M", "ᅵ"), - (0xFFDD, "X"), - (0xFFE0, "M", "¢"), - (0xFFE1, "M", "£"), - (0xFFE2, "M", "¬"), - (0xFFE3, "3", " ̄"), - (0xFFE4, "M", "¦"), - (0xFFE5, "M", "¥"), - (0xFFE6, "M", "₩"), - (0xFFE7, "X"), - (0xFFE8, "M", "│"), - (0xFFE9, "M", "←"), - (0xFFEA, "M", "↑"), - (0xFFEB, "M", "→"), - (0xFFEC, "M", "↓"), - (0xFFED, "M", "■"), + (0xFF7F, 'M', 'ソ'), + (0xFF80, 'M', 'タ'), + (0xFF81, 'M', 'チ'), + (0xFF82, 'M', 'ツ'), + (0xFF83, 'M', 'テ'), + (0xFF84, 'M', 'ト'), + (0xFF85, 'M', 'ナ'), + (0xFF86, 'M', 'ニ'), + (0xFF87, 'M', 'ヌ'), + (0xFF88, 'M', 'ネ'), + (0xFF89, 'M', 'ノ'), + (0xFF8A, 'M', 'ハ'), + (0xFF8B, 'M', 'ヒ'), + (0xFF8C, 'M', 'フ'), + (0xFF8D, 'M', 'ヘ'), + (0xFF8E, 'M', 'ホ'), + (0xFF8F, 'M', 'マ'), + (0xFF90, 'M', 'ミ'), + (0xFF91, 'M', 'ム'), + (0xFF92, 'M', 'メ'), + (0xFF93, 'M', 'モ'), + (0xFF94, 'M', 'ヤ'), + (0xFF95, 'M', 'ユ'), + (0xFF96, 'M', 'ヨ'), + (0xFF97, 'M', 'ラ'), + (0xFF98, 'M', 'リ'), + (0xFF99, 'M', 'ル'), + (0xFF9A, 'M', 'レ'), + (0xFF9B, 'M', 'ロ'), + (0xFF9C, 'M', 'ワ'), + (0xFF9D, 'M', 'ン'), + (0xFF9E, 'M', '゙'), + (0xFF9F, 'M', '゚'), + (0xFFA0, 'X'), + (0xFFA1, 'M', 'ᄀ'), + (0xFFA2, 'M', 'ᄁ'), + (0xFFA3, 'M', 'ᆪ'), + (0xFFA4, 'M', 'ᄂ'), + (0xFFA5, 'M', 'ᆬ'), + (0xFFA6, 'M', 'ᆭ'), + (0xFFA7, 'M', 'ᄃ'), + (0xFFA8, 'M', 'ᄄ'), + (0xFFA9, 'M', 'ᄅ'), + (0xFFAA, 'M', 'ᆰ'), + (0xFFAB, 'M', 'ᆱ'), + (0xFFAC, 'M', 'ᆲ'), + (0xFFAD, 'M', 'ᆳ'), + (0xFFAE, 'M', 'ᆴ'), + (0xFFAF, 'M', 'ᆵ'), + (0xFFB0, 'M', 'ᄚ'), + (0xFFB1, 'M', 'ᄆ'), + (0xFFB2, 'M', 'ᄇ'), + (0xFFB3, 'M', 'ᄈ'), + (0xFFB4, 'M', 'ᄡ'), + (0xFFB5, 'M', 'ᄉ'), + (0xFFB6, 'M', 'ᄊ'), + (0xFFB7, 'M', 'ᄋ'), + (0xFFB8, 'M', 'ᄌ'), + (0xFFB9, 'M', 'ᄍ'), + (0xFFBA, 'M', 'ᄎ'), + (0xFFBB, 'M', 'ᄏ'), + (0xFFBC, 'M', 'ᄐ'), + (0xFFBD, 'M', 'ᄑ'), + (0xFFBE, 'M', 'ᄒ'), + (0xFFBF, 'X'), + (0xFFC2, 'M', 'ᅡ'), + (0xFFC3, 'M', 'ᅢ'), + (0xFFC4, 'M', 'ᅣ'), + (0xFFC5, 'M', 'ᅤ'), + (0xFFC6, 'M', 'ᅥ'), + (0xFFC7, 'M', 'ᅦ'), + (0xFFC8, 'X'), + (0xFFCA, 'M', 'ᅧ'), + (0xFFCB, 'M', 'ᅨ'), + (0xFFCC, 'M', 'ᅩ'), + (0xFFCD, 'M', 'ᅪ'), + (0xFFCE, 'M', 'ᅫ'), + (0xFFCF, 'M', 'ᅬ'), + (0xFFD0, 'X'), + (0xFFD2, 'M', 'ᅭ'), + (0xFFD3, 'M', 'ᅮ'), + (0xFFD4, 'M', 'ᅯ'), + (0xFFD5, 'M', 'ᅰ'), + (0xFFD6, 'M', 'ᅱ'), + (0xFFD7, 'M', 'ᅲ'), + (0xFFD8, 'X'), + (0xFFDA, 'M', 'ᅳ'), + (0xFFDB, 'M', 'ᅴ'), + (0xFFDC, 'M', 'ᅵ'), + (0xFFDD, 'X'), + (0xFFE0, 'M', '¢'), + (0xFFE1, 'M', '£'), + (0xFFE2, 'M', '¬'), + (0xFFE3, '3', ' ̄'), + (0xFFE4, 'M', '¦'), + (0xFFE5, 'M', '¥'), + (0xFFE6, 'M', '₩'), + (0xFFE7, 'X'), + (0xFFE8, 'M', '│'), + (0xFFE9, 'M', '←'), ] - def _seg_53() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0xFFEE, "M", "○"), - (0xFFEF, "X"), - (0x10000, "V"), - (0x1000C, "X"), - (0x1000D, "V"), - (0x10027, "X"), - (0x10028, "V"), - (0x1003B, "X"), - (0x1003C, "V"), - (0x1003E, "X"), - (0x1003F, "V"), - (0x1004E, "X"), - (0x10050, "V"), - (0x1005E, "X"), - (0x10080, "V"), - (0x100FB, "X"), - (0x10100, "V"), - (0x10103, "X"), - (0x10107, "V"), - (0x10134, "X"), - (0x10137, "V"), - (0x1018F, "X"), - (0x10190, "V"), - (0x1019D, "X"), - (0x101A0, "V"), - (0x101A1, "X"), - (0x101D0, "V"), - (0x101FE, "X"), - (0x10280, "V"), - (0x1029D, "X"), - (0x102A0, "V"), - (0x102D1, "X"), - (0x102E0, "V"), - (0x102FC, "X"), - (0x10300, "V"), - (0x10324, "X"), - (0x1032D, "V"), - (0x1034B, "X"), - (0x10350, "V"), - (0x1037B, "X"), - (0x10380, "V"), - (0x1039E, "X"), - (0x1039F, "V"), - (0x103C4, "X"), - (0x103C8, "V"), - (0x103D6, "X"), - (0x10400, "M", "𐐨"), - (0x10401, "M", "𐐩"), - (0x10402, "M", "𐐪"), - (0x10403, "M", "𐐫"), - (0x10404, "M", "𐐬"), - (0x10405, "M", "𐐭"), - (0x10406, "M", "𐐮"), - (0x10407, "M", "𐐯"), - (0x10408, "M", "𐐰"), - (0x10409, "M", "𐐱"), - (0x1040A, "M", "𐐲"), - (0x1040B, "M", "𐐳"), - (0x1040C, "M", "𐐴"), - (0x1040D, "M", "𐐵"), - (0x1040E, "M", "𐐶"), - (0x1040F, "M", "𐐷"), - (0x10410, "M", "𐐸"), - (0x10411, "M", "𐐹"), - (0x10412, "M", "𐐺"), - (0x10413, "M", "𐐻"), - (0x10414, "M", "𐐼"), - (0x10415, "M", "𐐽"), - (0x10416, "M", "𐐾"), - (0x10417, "M", "𐐿"), - (0x10418, "M", "𐑀"), - (0x10419, "M", "𐑁"), - (0x1041A, "M", "𐑂"), - (0x1041B, "M", "𐑃"), - (0x1041C, "M", "𐑄"), - (0x1041D, "M", "𐑅"), - (0x1041E, "M", "𐑆"), - (0x1041F, "M", "𐑇"), - (0x10420, "M", "𐑈"), - (0x10421, "M", "𐑉"), - (0x10422, "M", "𐑊"), - (0x10423, "M", "𐑋"), - (0x10424, "M", "𐑌"), - (0x10425, "M", "𐑍"), - (0x10426, "M", "𐑎"), - (0x10427, "M", "𐑏"), - (0x10428, "V"), - (0x1049E, "X"), - (0x104A0, "V"), - (0x104AA, "X"), - (0x104B0, "M", "𐓘"), - (0x104B1, "M", "𐓙"), - (0x104B2, "M", "𐓚"), - (0x104B3, "M", "𐓛"), - (0x104B4, "M", "𐓜"), - (0x104B5, "M", "𐓝"), - (0x104B6, "M", "𐓞"), - (0x104B7, "M", "𐓟"), - (0x104B8, "M", "𐓠"), - (0x104B9, "M", "𐓡"), + (0xFFEA, 'M', '↑'), + (0xFFEB, 'M', '→'), + (0xFFEC, 'M', '↓'), + (0xFFED, 'M', '■'), + (0xFFEE, 'M', '○'), + (0xFFEF, 'X'), + (0x10000, 'V'), + (0x1000C, 'X'), + (0x1000D, 'V'), + (0x10027, 'X'), + (0x10028, 'V'), + (0x1003B, 'X'), + (0x1003C, 'V'), + (0x1003E, 'X'), + (0x1003F, 'V'), + (0x1004E, 'X'), + (0x10050, 'V'), + (0x1005E, 'X'), + (0x10080, 'V'), + (0x100FB, 'X'), + (0x10100, 'V'), + (0x10103, 'X'), + (0x10107, 'V'), + (0x10134, 'X'), + (0x10137, 'V'), + (0x1018F, 'X'), + (0x10190, 'V'), + (0x1019D, 'X'), + (0x101A0, 'V'), + (0x101A1, 'X'), + (0x101D0, 'V'), + (0x101FE, 'X'), + (0x10280, 'V'), + (0x1029D, 'X'), + (0x102A0, 'V'), + (0x102D1, 'X'), + (0x102E0, 'V'), + (0x102FC, 'X'), + (0x10300, 'V'), + (0x10324, 'X'), + (0x1032D, 'V'), + (0x1034B, 'X'), + (0x10350, 'V'), + (0x1037B, 'X'), + (0x10380, 'V'), + (0x1039E, 'X'), + (0x1039F, 'V'), + (0x103C4, 'X'), + (0x103C8, 'V'), + (0x103D6, 'X'), + (0x10400, 'M', '𐐨'), + (0x10401, 'M', '𐐩'), + (0x10402, 'M', '𐐪'), + (0x10403, 'M', '𐐫'), + (0x10404, 'M', '𐐬'), + (0x10405, 'M', '𐐭'), + (0x10406, 'M', '𐐮'), + (0x10407, 'M', '𐐯'), + (0x10408, 'M', '𐐰'), + (0x10409, 'M', '𐐱'), + (0x1040A, 'M', '𐐲'), + (0x1040B, 'M', '𐐳'), + (0x1040C, 'M', '𐐴'), + (0x1040D, 'M', '𐐵'), + (0x1040E, 'M', '𐐶'), + (0x1040F, 'M', '𐐷'), + (0x10410, 'M', '𐐸'), + (0x10411, 'M', '𐐹'), + (0x10412, 'M', '𐐺'), + (0x10413, 'M', '𐐻'), + (0x10414, 'M', '𐐼'), + (0x10415, 'M', '𐐽'), + (0x10416, 'M', '𐐾'), + (0x10417, 'M', '𐐿'), + (0x10418, 'M', '𐑀'), + (0x10419, 'M', '𐑁'), + (0x1041A, 'M', '𐑂'), + (0x1041B, 'M', '𐑃'), + (0x1041C, 'M', '𐑄'), + (0x1041D, 'M', '𐑅'), + (0x1041E, 'M', '𐑆'), + (0x1041F, 'M', '𐑇'), + (0x10420, 'M', '𐑈'), + (0x10421, 'M', '𐑉'), + (0x10422, 'M', '𐑊'), + (0x10423, 'M', '𐑋'), + (0x10424, 'M', '𐑌'), + (0x10425, 'M', '𐑍'), + (0x10426, 'M', '𐑎'), + (0x10427, 'M', '𐑏'), + (0x10428, 'V'), + (0x1049E, 'X'), + (0x104A0, 'V'), + (0x104AA, 'X'), + (0x104B0, 'M', '𐓘'), + (0x104B1, 'M', '𐓙'), + (0x104B2, 'M', '𐓚'), + (0x104B3, 'M', '𐓛'), + (0x104B4, 'M', '𐓜'), + (0x104B5, 'M', '𐓝'), ] - def _seg_54() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x104BA, "M", "𐓢"), - (0x104BB, "M", "𐓣"), - (0x104BC, "M", "𐓤"), - (0x104BD, "M", "𐓥"), - (0x104BE, "M", "𐓦"), - (0x104BF, "M", "𐓧"), - (0x104C0, "M", "𐓨"), - (0x104C1, "M", "𐓩"), - (0x104C2, "M", "𐓪"), - (0x104C3, "M", "𐓫"), - (0x104C4, "M", "𐓬"), - (0x104C5, "M", "𐓭"), - (0x104C6, "M", "𐓮"), - (0x104C7, "M", "𐓯"), - (0x104C8, "M", "𐓰"), - (0x104C9, "M", "𐓱"), - (0x104CA, "M", "𐓲"), - (0x104CB, "M", "𐓳"), - (0x104CC, "M", "𐓴"), - (0x104CD, "M", "𐓵"), - (0x104CE, "M", "𐓶"), - (0x104CF, "M", "𐓷"), - (0x104D0, "M", "𐓸"), - (0x104D1, "M", "𐓹"), - (0x104D2, "M", "𐓺"), - (0x104D3, "M", "𐓻"), - (0x104D4, "X"), - (0x104D8, "V"), - (0x104FC, "X"), - (0x10500, "V"), - (0x10528, "X"), - (0x10530, "V"), - (0x10564, "X"), - (0x1056F, "V"), - (0x10570, "M", "𐖗"), - (0x10571, "M", "𐖘"), - (0x10572, "M", "𐖙"), - (0x10573, "M", "𐖚"), - (0x10574, "M", "𐖛"), - (0x10575, "M", "𐖜"), - (0x10576, "M", "𐖝"), - (0x10577, "M", "𐖞"), - (0x10578, "M", "𐖟"), - (0x10579, "M", "𐖠"), - (0x1057A, "M", "𐖡"), - (0x1057B, "X"), - (0x1057C, "M", "𐖣"), - (0x1057D, "M", "𐖤"), - (0x1057E, "M", "𐖥"), - (0x1057F, "M", "𐖦"), - (0x10580, "M", "𐖧"), - (0x10581, "M", "𐖨"), - (0x10582, "M", "𐖩"), - (0x10583, "M", "𐖪"), - (0x10584, "M", "𐖫"), - (0x10585, "M", "𐖬"), - (0x10586, "M", "𐖭"), - (0x10587, "M", "𐖮"), - (0x10588, "M", "𐖯"), - (0x10589, "M", "𐖰"), - (0x1058A, "M", "𐖱"), - (0x1058B, "X"), - (0x1058C, "M", "𐖳"), - (0x1058D, "M", "𐖴"), - (0x1058E, "M", "𐖵"), - (0x1058F, "M", "𐖶"), - (0x10590, "M", "𐖷"), - (0x10591, "M", "𐖸"), - (0x10592, "M", "𐖹"), - (0x10593, "X"), - (0x10594, "M", "𐖻"), - (0x10595, "M", "𐖼"), - (0x10596, "X"), - (0x10597, "V"), - (0x105A2, "X"), - (0x105A3, "V"), - (0x105B2, "X"), - (0x105B3, "V"), - (0x105BA, "X"), - (0x105BB, "V"), - (0x105BD, "X"), - (0x10600, "V"), - (0x10737, "X"), - (0x10740, "V"), - (0x10756, "X"), - (0x10760, "V"), - (0x10768, "X"), - (0x10780, "V"), - (0x10781, "M", "ː"), - (0x10782, "M", "ˑ"), - (0x10783, "M", "æ"), - (0x10784, "M", "ʙ"), - (0x10785, "M", "ɓ"), - (0x10786, "X"), - (0x10787, "M", "ʣ"), - (0x10788, "M", "ꭦ"), - (0x10789, "M", "ʥ"), - (0x1078A, "M", "ʤ"), - (0x1078B, "M", "ɖ"), - (0x1078C, "M", "ɗ"), + (0x104B6, 'M', '𐓞'), + (0x104B7, 'M', '𐓟'), + (0x104B8, 'M', '𐓠'), + (0x104B9, 'M', '𐓡'), + (0x104BA, 'M', '𐓢'), + (0x104BB, 'M', '𐓣'), + (0x104BC, 'M', '𐓤'), + (0x104BD, 'M', '𐓥'), + (0x104BE, 'M', '𐓦'), + (0x104BF, 'M', '𐓧'), + (0x104C0, 'M', '𐓨'), + (0x104C1, 'M', '𐓩'), + (0x104C2, 'M', '𐓪'), + (0x104C3, 'M', '𐓫'), + (0x104C4, 'M', '𐓬'), + (0x104C5, 'M', '𐓭'), + (0x104C6, 'M', '𐓮'), + (0x104C7, 'M', '𐓯'), + (0x104C8, 'M', '𐓰'), + (0x104C9, 'M', '𐓱'), + (0x104CA, 'M', '𐓲'), + (0x104CB, 'M', '𐓳'), + (0x104CC, 'M', '𐓴'), + (0x104CD, 'M', '𐓵'), + (0x104CE, 'M', '𐓶'), + (0x104CF, 'M', '𐓷'), + (0x104D0, 'M', '𐓸'), + (0x104D1, 'M', '𐓹'), + (0x104D2, 'M', '𐓺'), + (0x104D3, 'M', '𐓻'), + (0x104D4, 'X'), + (0x104D8, 'V'), + (0x104FC, 'X'), + (0x10500, 'V'), + (0x10528, 'X'), + (0x10530, 'V'), + (0x10564, 'X'), + (0x1056F, 'V'), + (0x10570, 'M', '𐖗'), + (0x10571, 'M', '𐖘'), + (0x10572, 'M', '𐖙'), + (0x10573, 'M', '𐖚'), + (0x10574, 'M', '𐖛'), + (0x10575, 'M', '𐖜'), + (0x10576, 'M', '𐖝'), + (0x10577, 'M', '𐖞'), + (0x10578, 'M', '𐖟'), + (0x10579, 'M', '𐖠'), + (0x1057A, 'M', '𐖡'), + (0x1057B, 'X'), + (0x1057C, 'M', '𐖣'), + (0x1057D, 'M', '𐖤'), + (0x1057E, 'M', '𐖥'), + (0x1057F, 'M', '𐖦'), + (0x10580, 'M', '𐖧'), + (0x10581, 'M', '𐖨'), + (0x10582, 'M', '𐖩'), + (0x10583, 'M', '𐖪'), + (0x10584, 'M', '𐖫'), + (0x10585, 'M', '𐖬'), + (0x10586, 'M', '𐖭'), + (0x10587, 'M', '𐖮'), + (0x10588, 'M', '𐖯'), + (0x10589, 'M', '𐖰'), + (0x1058A, 'M', '𐖱'), + (0x1058B, 'X'), + (0x1058C, 'M', '𐖳'), + (0x1058D, 'M', '𐖴'), + (0x1058E, 'M', '𐖵'), + (0x1058F, 'M', '𐖶'), + (0x10590, 'M', '𐖷'), + (0x10591, 'M', '𐖸'), + (0x10592, 'M', '𐖹'), + (0x10593, 'X'), + (0x10594, 'M', '𐖻'), + (0x10595, 'M', '𐖼'), + (0x10596, 'X'), + (0x10597, 'V'), + (0x105A2, 'X'), + (0x105A3, 'V'), + (0x105B2, 'X'), + (0x105B3, 'V'), + (0x105BA, 'X'), + (0x105BB, 'V'), + (0x105BD, 'X'), + (0x10600, 'V'), + (0x10737, 'X'), + (0x10740, 'V'), + (0x10756, 'X'), + (0x10760, 'V'), + (0x10768, 'X'), + (0x10780, 'V'), + (0x10781, 'M', 'ː'), + (0x10782, 'M', 'ˑ'), + (0x10783, 'M', 'æ'), + (0x10784, 'M', 'ʙ'), + (0x10785, 'M', 'ɓ'), + (0x10786, 'X'), + (0x10787, 'M', 'ʣ'), + (0x10788, 'M', 'ꭦ'), ] - def _seg_55() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x1078D, "M", "ᶑ"), - (0x1078E, "M", "ɘ"), - (0x1078F, "M", "ɞ"), - (0x10790, "M", "ʩ"), - (0x10791, "M", "ɤ"), - (0x10792, "M", "ɢ"), - (0x10793, "M", "ɠ"), - (0x10794, "M", "ʛ"), - (0x10795, "M", "ħ"), - (0x10796, "M", "ʜ"), - (0x10797, "M", "ɧ"), - (0x10798, "M", "ʄ"), - (0x10799, "M", "ʪ"), - (0x1079A, "M", "ʫ"), - (0x1079B, "M", "ɬ"), - (0x1079C, "M", "𝼄"), - (0x1079D, "M", "ꞎ"), - (0x1079E, "M", "ɮ"), - (0x1079F, "M", "𝼅"), - (0x107A0, "M", "ʎ"), - (0x107A1, "M", "𝼆"), - (0x107A2, "M", "ø"), - (0x107A3, "M", "ɶ"), - (0x107A4, "M", "ɷ"), - (0x107A5, "M", "q"), - (0x107A6, "M", "ɺ"), - (0x107A7, "M", "𝼈"), - (0x107A8, "M", "ɽ"), - (0x107A9, "M", "ɾ"), - (0x107AA, "M", "ʀ"), - (0x107AB, "M", "ʨ"), - (0x107AC, "M", "ʦ"), - (0x107AD, "M", "ꭧ"), - (0x107AE, "M", "ʧ"), - (0x107AF, "M", "ʈ"), - (0x107B0, "M", "ⱱ"), - (0x107B1, "X"), - (0x107B2, "M", "ʏ"), - (0x107B3, "M", "ʡ"), - (0x107B4, "M", "ʢ"), - (0x107B5, "M", "ʘ"), - (0x107B6, "M", "ǀ"), - (0x107B7, "M", "ǁ"), - (0x107B8, "M", "ǂ"), - (0x107B9, "M", "𝼊"), - (0x107BA, "M", "𝼞"), - (0x107BB, "X"), - (0x10800, "V"), - (0x10806, "X"), - (0x10808, "V"), - (0x10809, "X"), - (0x1080A, "V"), - (0x10836, "X"), - (0x10837, "V"), - (0x10839, "X"), - (0x1083C, "V"), - (0x1083D, "X"), - (0x1083F, "V"), - (0x10856, "X"), - (0x10857, "V"), - (0x1089F, "X"), - (0x108A7, "V"), - (0x108B0, "X"), - (0x108E0, "V"), - (0x108F3, "X"), - (0x108F4, "V"), - (0x108F6, "X"), - (0x108FB, "V"), - (0x1091C, "X"), - (0x1091F, "V"), - (0x1093A, "X"), - (0x1093F, "V"), - (0x10940, "X"), - (0x10980, "V"), - (0x109B8, "X"), - (0x109BC, "V"), - (0x109D0, "X"), - (0x109D2, "V"), - (0x10A04, "X"), - (0x10A05, "V"), - (0x10A07, "X"), - (0x10A0C, "V"), - (0x10A14, "X"), - (0x10A15, "V"), - (0x10A18, "X"), - (0x10A19, "V"), - (0x10A36, "X"), - (0x10A38, "V"), - (0x10A3B, "X"), - (0x10A3F, "V"), - (0x10A49, "X"), - (0x10A50, "V"), - (0x10A59, "X"), - (0x10A60, "V"), - (0x10AA0, "X"), - (0x10AC0, "V"), - (0x10AE7, "X"), - (0x10AEB, "V"), - (0x10AF7, "X"), - (0x10B00, "V"), + (0x10789, 'M', 'ʥ'), + (0x1078A, 'M', 'ʤ'), + (0x1078B, 'M', 'ɖ'), + (0x1078C, 'M', 'ɗ'), + (0x1078D, 'M', 'ᶑ'), + (0x1078E, 'M', 'ɘ'), + (0x1078F, 'M', 'ɞ'), + (0x10790, 'M', 'ʩ'), + (0x10791, 'M', 'ɤ'), + (0x10792, 'M', 'ɢ'), + (0x10793, 'M', 'ɠ'), + (0x10794, 'M', 'ʛ'), + (0x10795, 'M', 'ħ'), + (0x10796, 'M', 'ʜ'), + (0x10797, 'M', 'ɧ'), + (0x10798, 'M', 'ʄ'), + (0x10799, 'M', 'ʪ'), + (0x1079A, 'M', 'ʫ'), + (0x1079B, 'M', 'ɬ'), + (0x1079C, 'M', '𝼄'), + (0x1079D, 'M', 'ꞎ'), + (0x1079E, 'M', 'ɮ'), + (0x1079F, 'M', '𝼅'), + (0x107A0, 'M', 'ʎ'), + (0x107A1, 'M', '𝼆'), + (0x107A2, 'M', 'ø'), + (0x107A3, 'M', 'ɶ'), + (0x107A4, 'M', 'ɷ'), + (0x107A5, 'M', 'q'), + (0x107A6, 'M', 'ɺ'), + (0x107A7, 'M', '𝼈'), + (0x107A8, 'M', 'ɽ'), + (0x107A9, 'M', 'ɾ'), + (0x107AA, 'M', 'ʀ'), + (0x107AB, 'M', 'ʨ'), + (0x107AC, 'M', 'ʦ'), + (0x107AD, 'M', 'ꭧ'), + (0x107AE, 'M', 'ʧ'), + (0x107AF, 'M', 'ʈ'), + (0x107B0, 'M', 'ⱱ'), + (0x107B1, 'X'), + (0x107B2, 'M', 'ʏ'), + (0x107B3, 'M', 'ʡ'), + (0x107B4, 'M', 'ʢ'), + (0x107B5, 'M', 'ʘ'), + (0x107B6, 'M', 'ǀ'), + (0x107B7, 'M', 'ǁ'), + (0x107B8, 'M', 'ǂ'), + (0x107B9, 'M', '𝼊'), + (0x107BA, 'M', '𝼞'), + (0x107BB, 'X'), + (0x10800, 'V'), + (0x10806, 'X'), + (0x10808, 'V'), + (0x10809, 'X'), + (0x1080A, 'V'), + (0x10836, 'X'), + (0x10837, 'V'), + (0x10839, 'X'), + (0x1083C, 'V'), + (0x1083D, 'X'), + (0x1083F, 'V'), + (0x10856, 'X'), + (0x10857, 'V'), + (0x1089F, 'X'), + (0x108A7, 'V'), + (0x108B0, 'X'), + (0x108E0, 'V'), + (0x108F3, 'X'), + (0x108F4, 'V'), + (0x108F6, 'X'), + (0x108FB, 'V'), + (0x1091C, 'X'), + (0x1091F, 'V'), + (0x1093A, 'X'), + (0x1093F, 'V'), + (0x10940, 'X'), + (0x10980, 'V'), + (0x109B8, 'X'), + (0x109BC, 'V'), + (0x109D0, 'X'), + (0x109D2, 'V'), + (0x10A04, 'X'), + (0x10A05, 'V'), + (0x10A07, 'X'), + (0x10A0C, 'V'), + (0x10A14, 'X'), + (0x10A15, 'V'), + (0x10A18, 'X'), + (0x10A19, 'V'), + (0x10A36, 'X'), + (0x10A38, 'V'), + (0x10A3B, 'X'), + (0x10A3F, 'V'), + (0x10A49, 'X'), + (0x10A50, 'V'), + (0x10A59, 'X'), + (0x10A60, 'V'), + (0x10AA0, 'X'), + (0x10AC0, 'V'), ] - def _seg_56() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x10B36, "X"), - (0x10B39, "V"), - (0x10B56, "X"), - (0x10B58, "V"), - (0x10B73, "X"), - (0x10B78, "V"), - (0x10B92, "X"), - (0x10B99, "V"), - (0x10B9D, "X"), - (0x10BA9, "V"), - (0x10BB0, "X"), - (0x10C00, "V"), - (0x10C49, "X"), - (0x10C80, "M", "𐳀"), - (0x10C81, "M", "𐳁"), - (0x10C82, "M", "𐳂"), - (0x10C83, "M", "𐳃"), - (0x10C84, "M", "𐳄"), - (0x10C85, "M", "𐳅"), - (0x10C86, "M", "𐳆"), - (0x10C87, "M", "𐳇"), - (0x10C88, "M", "𐳈"), - (0x10C89, "M", "𐳉"), - (0x10C8A, "M", "𐳊"), - (0x10C8B, "M", "𐳋"), - (0x10C8C, "M", "𐳌"), - (0x10C8D, "M", "𐳍"), - (0x10C8E, "M", "𐳎"), - (0x10C8F, "M", "𐳏"), - (0x10C90, "M", "𐳐"), - (0x10C91, "M", "𐳑"), - (0x10C92, "M", "𐳒"), - (0x10C93, "M", "𐳓"), - (0x10C94, "M", "𐳔"), - (0x10C95, "M", "𐳕"), - (0x10C96, "M", "𐳖"), - (0x10C97, "M", "𐳗"), - (0x10C98, "M", "𐳘"), - (0x10C99, "M", "𐳙"), - (0x10C9A, "M", "𐳚"), - (0x10C9B, "M", "𐳛"), - (0x10C9C, "M", "𐳜"), - (0x10C9D, "M", "𐳝"), - (0x10C9E, "M", "𐳞"), - (0x10C9F, "M", "𐳟"), - (0x10CA0, "M", "𐳠"), - (0x10CA1, "M", "𐳡"), - (0x10CA2, "M", "𐳢"), - (0x10CA3, "M", "𐳣"), - (0x10CA4, "M", "𐳤"), - (0x10CA5, "M", "𐳥"), - (0x10CA6, "M", "𐳦"), - (0x10CA7, "M", "𐳧"), - (0x10CA8, "M", "𐳨"), - (0x10CA9, "M", "𐳩"), - (0x10CAA, "M", "𐳪"), - (0x10CAB, "M", "𐳫"), - (0x10CAC, "M", "𐳬"), - (0x10CAD, "M", "𐳭"), - (0x10CAE, "M", "𐳮"), - (0x10CAF, "M", "𐳯"), - (0x10CB0, "M", "𐳰"), - (0x10CB1, "M", "𐳱"), - (0x10CB2, "M", "𐳲"), - (0x10CB3, "X"), - (0x10CC0, "V"), - (0x10CF3, "X"), - (0x10CFA, "V"), - (0x10D28, "X"), - (0x10D30, "V"), - (0x10D3A, "X"), - (0x10E60, "V"), - (0x10E7F, "X"), - (0x10E80, "V"), - (0x10EAA, "X"), - (0x10EAB, "V"), - (0x10EAE, "X"), - (0x10EB0, "V"), - (0x10EB2, "X"), - (0x10EFD, "V"), - (0x10F28, "X"), - (0x10F30, "V"), - (0x10F5A, "X"), - (0x10F70, "V"), - (0x10F8A, "X"), - (0x10FB0, "V"), - (0x10FCC, "X"), - (0x10FE0, "V"), - (0x10FF7, "X"), - (0x11000, "V"), - (0x1104E, "X"), - (0x11052, "V"), - (0x11076, "X"), - (0x1107F, "V"), - (0x110BD, "X"), - (0x110BE, "V"), - (0x110C3, "X"), - (0x110D0, "V"), - (0x110E9, "X"), - (0x110F0, "V"), + (0x10AE7, 'X'), + (0x10AEB, 'V'), + (0x10AF7, 'X'), + (0x10B00, 'V'), + (0x10B36, 'X'), + (0x10B39, 'V'), + (0x10B56, 'X'), + (0x10B58, 'V'), + (0x10B73, 'X'), + (0x10B78, 'V'), + (0x10B92, 'X'), + (0x10B99, 'V'), + (0x10B9D, 'X'), + (0x10BA9, 'V'), + (0x10BB0, 'X'), + (0x10C00, 'V'), + (0x10C49, 'X'), + (0x10C80, 'M', '𐳀'), + (0x10C81, 'M', '𐳁'), + (0x10C82, 'M', '𐳂'), + (0x10C83, 'M', '𐳃'), + (0x10C84, 'M', '𐳄'), + (0x10C85, 'M', '𐳅'), + (0x10C86, 'M', '𐳆'), + (0x10C87, 'M', '𐳇'), + (0x10C88, 'M', '𐳈'), + (0x10C89, 'M', '𐳉'), + (0x10C8A, 'M', '𐳊'), + (0x10C8B, 'M', '𐳋'), + (0x10C8C, 'M', '𐳌'), + (0x10C8D, 'M', '𐳍'), + (0x10C8E, 'M', '𐳎'), + (0x10C8F, 'M', '𐳏'), + (0x10C90, 'M', '𐳐'), + (0x10C91, 'M', '𐳑'), + (0x10C92, 'M', '𐳒'), + (0x10C93, 'M', '𐳓'), + (0x10C94, 'M', '𐳔'), + (0x10C95, 'M', '𐳕'), + (0x10C96, 'M', '𐳖'), + (0x10C97, 'M', '𐳗'), + (0x10C98, 'M', '𐳘'), + (0x10C99, 'M', '𐳙'), + (0x10C9A, 'M', '𐳚'), + (0x10C9B, 'M', '𐳛'), + (0x10C9C, 'M', '𐳜'), + (0x10C9D, 'M', '𐳝'), + (0x10C9E, 'M', '𐳞'), + (0x10C9F, 'M', '𐳟'), + (0x10CA0, 'M', '𐳠'), + (0x10CA1, 'M', '𐳡'), + (0x10CA2, 'M', '𐳢'), + (0x10CA3, 'M', '𐳣'), + (0x10CA4, 'M', '𐳤'), + (0x10CA5, 'M', '𐳥'), + (0x10CA6, 'M', '𐳦'), + (0x10CA7, 'M', '𐳧'), + (0x10CA8, 'M', '𐳨'), + (0x10CA9, 'M', '𐳩'), + (0x10CAA, 'M', '𐳪'), + (0x10CAB, 'M', '𐳫'), + (0x10CAC, 'M', '𐳬'), + (0x10CAD, 'M', '𐳭'), + (0x10CAE, 'M', '𐳮'), + (0x10CAF, 'M', '𐳯'), + (0x10CB0, 'M', '𐳰'), + (0x10CB1, 'M', '𐳱'), + (0x10CB2, 'M', '𐳲'), + (0x10CB3, 'X'), + (0x10CC0, 'V'), + (0x10CF3, 'X'), + (0x10CFA, 'V'), + (0x10D28, 'X'), + (0x10D30, 'V'), + (0x10D3A, 'X'), + (0x10E60, 'V'), + (0x10E7F, 'X'), + (0x10E80, 'V'), + (0x10EAA, 'X'), + (0x10EAB, 'V'), + (0x10EAE, 'X'), + (0x10EB0, 'V'), + (0x10EB2, 'X'), + (0x10EFD, 'V'), + (0x10F28, 'X'), + (0x10F30, 'V'), + (0x10F5A, 'X'), + (0x10F70, 'V'), + (0x10F8A, 'X'), + (0x10FB0, 'V'), + (0x10FCC, 'X'), + (0x10FE0, 'V'), + (0x10FF7, 'X'), + (0x11000, 'V'), + (0x1104E, 'X'), + (0x11052, 'V'), + (0x11076, 'X'), + (0x1107F, 'V'), + (0x110BD, 'X'), + (0x110BE, 'V'), ] - def _seg_57() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x110FA, "X"), - (0x11100, "V"), - (0x11135, "X"), - (0x11136, "V"), - (0x11148, "X"), - (0x11150, "V"), - (0x11177, "X"), - (0x11180, "V"), - (0x111E0, "X"), - (0x111E1, "V"), - (0x111F5, "X"), - (0x11200, "V"), - (0x11212, "X"), - (0x11213, "V"), - (0x11242, "X"), - (0x11280, "V"), - (0x11287, "X"), - (0x11288, "V"), - (0x11289, "X"), - (0x1128A, "V"), - (0x1128E, "X"), - (0x1128F, "V"), - (0x1129E, "X"), - (0x1129F, "V"), - (0x112AA, "X"), - (0x112B0, "V"), - (0x112EB, "X"), - (0x112F0, "V"), - (0x112FA, "X"), - (0x11300, "V"), - (0x11304, "X"), - (0x11305, "V"), - (0x1130D, "X"), - (0x1130F, "V"), - (0x11311, "X"), - (0x11313, "V"), - (0x11329, "X"), - (0x1132A, "V"), - (0x11331, "X"), - (0x11332, "V"), - (0x11334, "X"), - (0x11335, "V"), - (0x1133A, "X"), - (0x1133B, "V"), - (0x11345, "X"), - (0x11347, "V"), - (0x11349, "X"), - (0x1134B, "V"), - (0x1134E, "X"), - (0x11350, "V"), - (0x11351, "X"), - (0x11357, "V"), - (0x11358, "X"), - (0x1135D, "V"), - (0x11364, "X"), - (0x11366, "V"), - (0x1136D, "X"), - (0x11370, "V"), - (0x11375, "X"), - (0x11400, "V"), - (0x1145C, "X"), - (0x1145D, "V"), - (0x11462, "X"), - (0x11480, "V"), - (0x114C8, "X"), - (0x114D0, "V"), - (0x114DA, "X"), - (0x11580, "V"), - (0x115B6, "X"), - (0x115B8, "V"), - (0x115DE, "X"), - (0x11600, "V"), - (0x11645, "X"), - (0x11650, "V"), - (0x1165A, "X"), - (0x11660, "V"), - (0x1166D, "X"), - (0x11680, "V"), - (0x116BA, "X"), - (0x116C0, "V"), - (0x116CA, "X"), - (0x11700, "V"), - (0x1171B, "X"), - (0x1171D, "V"), - (0x1172C, "X"), - (0x11730, "V"), - (0x11747, "X"), - (0x11800, "V"), - (0x1183C, "X"), - (0x118A0, "M", "𑣀"), - (0x118A1, "M", "𑣁"), - (0x118A2, "M", "𑣂"), - (0x118A3, "M", "𑣃"), - (0x118A4, "M", "𑣄"), - (0x118A5, "M", "𑣅"), - (0x118A6, "M", "𑣆"), - (0x118A7, "M", "𑣇"), - (0x118A8, "M", "𑣈"), - (0x118A9, "M", "𑣉"), - (0x118AA, "M", "𑣊"), + (0x110C3, 'X'), + (0x110D0, 'V'), + (0x110E9, 'X'), + (0x110F0, 'V'), + (0x110FA, 'X'), + (0x11100, 'V'), + (0x11135, 'X'), + (0x11136, 'V'), + (0x11148, 'X'), + (0x11150, 'V'), + (0x11177, 'X'), + (0x11180, 'V'), + (0x111E0, 'X'), + (0x111E1, 'V'), + (0x111F5, 'X'), + (0x11200, 'V'), + (0x11212, 'X'), + (0x11213, 'V'), + (0x11242, 'X'), + (0x11280, 'V'), + (0x11287, 'X'), + (0x11288, 'V'), + (0x11289, 'X'), + (0x1128A, 'V'), + (0x1128E, 'X'), + (0x1128F, 'V'), + (0x1129E, 'X'), + (0x1129F, 'V'), + (0x112AA, 'X'), + (0x112B0, 'V'), + (0x112EB, 'X'), + (0x112F0, 'V'), + (0x112FA, 'X'), + (0x11300, 'V'), + (0x11304, 'X'), + (0x11305, 'V'), + (0x1130D, 'X'), + (0x1130F, 'V'), + (0x11311, 'X'), + (0x11313, 'V'), + (0x11329, 'X'), + (0x1132A, 'V'), + (0x11331, 'X'), + (0x11332, 'V'), + (0x11334, 'X'), + (0x11335, 'V'), + (0x1133A, 'X'), + (0x1133B, 'V'), + (0x11345, 'X'), + (0x11347, 'V'), + (0x11349, 'X'), + (0x1134B, 'V'), + (0x1134E, 'X'), + (0x11350, 'V'), + (0x11351, 'X'), + (0x11357, 'V'), + (0x11358, 'X'), + (0x1135D, 'V'), + (0x11364, 'X'), + (0x11366, 'V'), + (0x1136D, 'X'), + (0x11370, 'V'), + (0x11375, 'X'), + (0x11400, 'V'), + (0x1145C, 'X'), + (0x1145D, 'V'), + (0x11462, 'X'), + (0x11480, 'V'), + (0x114C8, 'X'), + (0x114D0, 'V'), + (0x114DA, 'X'), + (0x11580, 'V'), + (0x115B6, 'X'), + (0x115B8, 'V'), + (0x115DE, 'X'), + (0x11600, 'V'), + (0x11645, 'X'), + (0x11650, 'V'), + (0x1165A, 'X'), + (0x11660, 'V'), + (0x1166D, 'X'), + (0x11680, 'V'), + (0x116BA, 'X'), + (0x116C0, 'V'), + (0x116CA, 'X'), + (0x11700, 'V'), + (0x1171B, 'X'), + (0x1171D, 'V'), + (0x1172C, 'X'), + (0x11730, 'V'), + (0x11747, 'X'), + (0x11800, 'V'), + (0x1183C, 'X'), + (0x118A0, 'M', '𑣀'), + (0x118A1, 'M', '𑣁'), + (0x118A2, 'M', '𑣂'), + (0x118A3, 'M', '𑣃'), + (0x118A4, 'M', '𑣄'), + (0x118A5, 'M', '𑣅'), + (0x118A6, 'M', '𑣆'), ] - def _seg_58() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x118AB, "M", "𑣋"), - (0x118AC, "M", "𑣌"), - (0x118AD, "M", "𑣍"), - (0x118AE, "M", "𑣎"), - (0x118AF, "M", "𑣏"), - (0x118B0, "M", "𑣐"), - (0x118B1, "M", "𑣑"), - (0x118B2, "M", "𑣒"), - (0x118B3, "M", "𑣓"), - (0x118B4, "M", "𑣔"), - (0x118B5, "M", "𑣕"), - (0x118B6, "M", "𑣖"), - (0x118B7, "M", "𑣗"), - (0x118B8, "M", "𑣘"), - (0x118B9, "M", "𑣙"), - (0x118BA, "M", "𑣚"), - (0x118BB, "M", "𑣛"), - (0x118BC, "M", "𑣜"), - (0x118BD, "M", "𑣝"), - (0x118BE, "M", "𑣞"), - (0x118BF, "M", "𑣟"), - (0x118C0, "V"), - (0x118F3, "X"), - (0x118FF, "V"), - (0x11907, "X"), - (0x11909, "V"), - (0x1190A, "X"), - (0x1190C, "V"), - (0x11914, "X"), - (0x11915, "V"), - (0x11917, "X"), - (0x11918, "V"), - (0x11936, "X"), - (0x11937, "V"), - (0x11939, "X"), - (0x1193B, "V"), - (0x11947, "X"), - (0x11950, "V"), - (0x1195A, "X"), - (0x119A0, "V"), - (0x119A8, "X"), - (0x119AA, "V"), - (0x119D8, "X"), - (0x119DA, "V"), - (0x119E5, "X"), - (0x11A00, "V"), - (0x11A48, "X"), - (0x11A50, "V"), - (0x11AA3, "X"), - (0x11AB0, "V"), - (0x11AF9, "X"), - (0x11B00, "V"), - (0x11B0A, "X"), - (0x11C00, "V"), - (0x11C09, "X"), - (0x11C0A, "V"), - (0x11C37, "X"), - (0x11C38, "V"), - (0x11C46, "X"), - (0x11C50, "V"), - (0x11C6D, "X"), - (0x11C70, "V"), - (0x11C90, "X"), - (0x11C92, "V"), - (0x11CA8, "X"), - (0x11CA9, "V"), - (0x11CB7, "X"), - (0x11D00, "V"), - (0x11D07, "X"), - (0x11D08, "V"), - (0x11D0A, "X"), - (0x11D0B, "V"), - (0x11D37, "X"), - (0x11D3A, "V"), - (0x11D3B, "X"), - (0x11D3C, "V"), - (0x11D3E, "X"), - (0x11D3F, "V"), - (0x11D48, "X"), - (0x11D50, "V"), - (0x11D5A, "X"), - (0x11D60, "V"), - (0x11D66, "X"), - (0x11D67, "V"), - (0x11D69, "X"), - (0x11D6A, "V"), - (0x11D8F, "X"), - (0x11D90, "V"), - (0x11D92, "X"), - (0x11D93, "V"), - (0x11D99, "X"), - (0x11DA0, "V"), - (0x11DAA, "X"), - (0x11EE0, "V"), - (0x11EF9, "X"), - (0x11F00, "V"), - (0x11F11, "X"), - (0x11F12, "V"), - (0x11F3B, "X"), - (0x11F3E, "V"), + (0x118A7, 'M', '𑣇'), + (0x118A8, 'M', '𑣈'), + (0x118A9, 'M', '𑣉'), + (0x118AA, 'M', '𑣊'), + (0x118AB, 'M', '𑣋'), + (0x118AC, 'M', '𑣌'), + (0x118AD, 'M', '𑣍'), + (0x118AE, 'M', '𑣎'), + (0x118AF, 'M', '𑣏'), + (0x118B0, 'M', '𑣐'), + (0x118B1, 'M', '𑣑'), + (0x118B2, 'M', '𑣒'), + (0x118B3, 'M', '𑣓'), + (0x118B4, 'M', '𑣔'), + (0x118B5, 'M', '𑣕'), + (0x118B6, 'M', '𑣖'), + (0x118B7, 'M', '𑣗'), + (0x118B8, 'M', '𑣘'), + (0x118B9, 'M', '𑣙'), + (0x118BA, 'M', '𑣚'), + (0x118BB, 'M', '𑣛'), + (0x118BC, 'M', '𑣜'), + (0x118BD, 'M', '𑣝'), + (0x118BE, 'M', '𑣞'), + (0x118BF, 'M', '𑣟'), + (0x118C0, 'V'), + (0x118F3, 'X'), + (0x118FF, 'V'), + (0x11907, 'X'), + (0x11909, 'V'), + (0x1190A, 'X'), + (0x1190C, 'V'), + (0x11914, 'X'), + (0x11915, 'V'), + (0x11917, 'X'), + (0x11918, 'V'), + (0x11936, 'X'), + (0x11937, 'V'), + (0x11939, 'X'), + (0x1193B, 'V'), + (0x11947, 'X'), + (0x11950, 'V'), + (0x1195A, 'X'), + (0x119A0, 'V'), + (0x119A8, 'X'), + (0x119AA, 'V'), + (0x119D8, 'X'), + (0x119DA, 'V'), + (0x119E5, 'X'), + (0x11A00, 'V'), + (0x11A48, 'X'), + (0x11A50, 'V'), + (0x11AA3, 'X'), + (0x11AB0, 'V'), + (0x11AF9, 'X'), + (0x11B00, 'V'), + (0x11B0A, 'X'), + (0x11C00, 'V'), + (0x11C09, 'X'), + (0x11C0A, 'V'), + (0x11C37, 'X'), + (0x11C38, 'V'), + (0x11C46, 'X'), + (0x11C50, 'V'), + (0x11C6D, 'X'), + (0x11C70, 'V'), + (0x11C90, 'X'), + (0x11C92, 'V'), + (0x11CA8, 'X'), + (0x11CA9, 'V'), + (0x11CB7, 'X'), + (0x11D00, 'V'), + (0x11D07, 'X'), + (0x11D08, 'V'), + (0x11D0A, 'X'), + (0x11D0B, 'V'), + (0x11D37, 'X'), + (0x11D3A, 'V'), + (0x11D3B, 'X'), + (0x11D3C, 'V'), + (0x11D3E, 'X'), + (0x11D3F, 'V'), + (0x11D48, 'X'), + (0x11D50, 'V'), + (0x11D5A, 'X'), + (0x11D60, 'V'), + (0x11D66, 'X'), + (0x11D67, 'V'), + (0x11D69, 'X'), + (0x11D6A, 'V'), + (0x11D8F, 'X'), + (0x11D90, 'V'), + (0x11D92, 'X'), + (0x11D93, 'V'), + (0x11D99, 'X'), + (0x11DA0, 'V'), + (0x11DAA, 'X'), + (0x11EE0, 'V'), + (0x11EF9, 'X'), + (0x11F00, 'V'), ] - def _seg_59() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x11F5A, "X"), - (0x11FB0, "V"), - (0x11FB1, "X"), - (0x11FC0, "V"), - (0x11FF2, "X"), - (0x11FFF, "V"), - (0x1239A, "X"), - (0x12400, "V"), - (0x1246F, "X"), - (0x12470, "V"), - (0x12475, "X"), - (0x12480, "V"), - (0x12544, "X"), - (0x12F90, "V"), - (0x12FF3, "X"), - (0x13000, "V"), - (0x13430, "X"), - (0x13440, "V"), - (0x13456, "X"), - (0x14400, "V"), - (0x14647, "X"), - (0x16800, "V"), - (0x16A39, "X"), - (0x16A40, "V"), - (0x16A5F, "X"), - (0x16A60, "V"), - (0x16A6A, "X"), - (0x16A6E, "V"), - (0x16ABF, "X"), - (0x16AC0, "V"), - (0x16ACA, "X"), - (0x16AD0, "V"), - (0x16AEE, "X"), - (0x16AF0, "V"), - (0x16AF6, "X"), - (0x16B00, "V"), - (0x16B46, "X"), - (0x16B50, "V"), - (0x16B5A, "X"), - (0x16B5B, "V"), - (0x16B62, "X"), - (0x16B63, "V"), - (0x16B78, "X"), - (0x16B7D, "V"), - (0x16B90, "X"), - (0x16E40, "M", "𖹠"), - (0x16E41, "M", "𖹡"), - (0x16E42, "M", "𖹢"), - (0x16E43, "M", "𖹣"), - (0x16E44, "M", "𖹤"), - (0x16E45, "M", "𖹥"), - (0x16E46, "M", "𖹦"), - (0x16E47, "M", "𖹧"), - (0x16E48, "M", "𖹨"), - (0x16E49, "M", "𖹩"), - (0x16E4A, "M", "𖹪"), - (0x16E4B, "M", "𖹫"), - (0x16E4C, "M", "𖹬"), - (0x16E4D, "M", "𖹭"), - (0x16E4E, "M", "𖹮"), - (0x16E4F, "M", "𖹯"), - (0x16E50, "M", "𖹰"), - (0x16E51, "M", "𖹱"), - (0x16E52, "M", "𖹲"), - (0x16E53, "M", "𖹳"), - (0x16E54, "M", "𖹴"), - (0x16E55, "M", "𖹵"), - (0x16E56, "M", "𖹶"), - (0x16E57, "M", "𖹷"), - (0x16E58, "M", "𖹸"), - (0x16E59, "M", "𖹹"), - (0x16E5A, "M", "𖹺"), - (0x16E5B, "M", "𖹻"), - (0x16E5C, "M", "𖹼"), - (0x16E5D, "M", "𖹽"), - (0x16E5E, "M", "𖹾"), - (0x16E5F, "M", "𖹿"), - (0x16E60, "V"), - (0x16E9B, "X"), - (0x16F00, "V"), - (0x16F4B, "X"), - (0x16F4F, "V"), - (0x16F88, "X"), - (0x16F8F, "V"), - (0x16FA0, "X"), - (0x16FE0, "V"), - (0x16FE5, "X"), - (0x16FF0, "V"), - (0x16FF2, "X"), - (0x17000, "V"), - (0x187F8, "X"), - (0x18800, "V"), - (0x18CD6, "X"), - (0x18D00, "V"), - (0x18D09, "X"), - (0x1AFF0, "V"), - (0x1AFF4, "X"), - (0x1AFF5, "V"), - (0x1AFFC, "X"), - (0x1AFFD, "V"), + (0x11F11, 'X'), + (0x11F12, 'V'), + (0x11F3B, 'X'), + (0x11F3E, 'V'), + (0x11F5A, 'X'), + (0x11FB0, 'V'), + (0x11FB1, 'X'), + (0x11FC0, 'V'), + (0x11FF2, 'X'), + (0x11FFF, 'V'), + (0x1239A, 'X'), + (0x12400, 'V'), + (0x1246F, 'X'), + (0x12470, 'V'), + (0x12475, 'X'), + (0x12480, 'V'), + (0x12544, 'X'), + (0x12F90, 'V'), + (0x12FF3, 'X'), + (0x13000, 'V'), + (0x13430, 'X'), + (0x13440, 'V'), + (0x13456, 'X'), + (0x14400, 'V'), + (0x14647, 'X'), + (0x16800, 'V'), + (0x16A39, 'X'), + (0x16A40, 'V'), + (0x16A5F, 'X'), + (0x16A60, 'V'), + (0x16A6A, 'X'), + (0x16A6E, 'V'), + (0x16ABF, 'X'), + (0x16AC0, 'V'), + (0x16ACA, 'X'), + (0x16AD0, 'V'), + (0x16AEE, 'X'), + (0x16AF0, 'V'), + (0x16AF6, 'X'), + (0x16B00, 'V'), + (0x16B46, 'X'), + (0x16B50, 'V'), + (0x16B5A, 'X'), + (0x16B5B, 'V'), + (0x16B62, 'X'), + (0x16B63, 'V'), + (0x16B78, 'X'), + (0x16B7D, 'V'), + (0x16B90, 'X'), + (0x16E40, 'M', '𖹠'), + (0x16E41, 'M', '𖹡'), + (0x16E42, 'M', '𖹢'), + (0x16E43, 'M', '𖹣'), + (0x16E44, 'M', '𖹤'), + (0x16E45, 'M', '𖹥'), + (0x16E46, 'M', '𖹦'), + (0x16E47, 'M', '𖹧'), + (0x16E48, 'M', '𖹨'), + (0x16E49, 'M', '𖹩'), + (0x16E4A, 'M', '𖹪'), + (0x16E4B, 'M', '𖹫'), + (0x16E4C, 'M', '𖹬'), + (0x16E4D, 'M', '𖹭'), + (0x16E4E, 'M', '𖹮'), + (0x16E4F, 'M', '𖹯'), + (0x16E50, 'M', '𖹰'), + (0x16E51, 'M', '𖹱'), + (0x16E52, 'M', '𖹲'), + (0x16E53, 'M', '𖹳'), + (0x16E54, 'M', '𖹴'), + (0x16E55, 'M', '𖹵'), + (0x16E56, 'M', '𖹶'), + (0x16E57, 'M', '𖹷'), + (0x16E58, 'M', '𖹸'), + (0x16E59, 'M', '𖹹'), + (0x16E5A, 'M', '𖹺'), + (0x16E5B, 'M', '𖹻'), + (0x16E5C, 'M', '𖹼'), + (0x16E5D, 'M', '𖹽'), + (0x16E5E, 'M', '𖹾'), + (0x16E5F, 'M', '𖹿'), + (0x16E60, 'V'), + (0x16E9B, 'X'), + (0x16F00, 'V'), + (0x16F4B, 'X'), + (0x16F4F, 'V'), + (0x16F88, 'X'), + (0x16F8F, 'V'), + (0x16FA0, 'X'), + (0x16FE0, 'V'), + (0x16FE5, 'X'), + (0x16FF0, 'V'), + (0x16FF2, 'X'), + (0x17000, 'V'), + (0x187F8, 'X'), + (0x18800, 'V'), + (0x18CD6, 'X'), + (0x18D00, 'V'), + (0x18D09, 'X'), + (0x1AFF0, 'V'), ] - def _seg_60() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x1AFFF, "X"), - (0x1B000, "V"), - (0x1B123, "X"), - (0x1B132, "V"), - (0x1B133, "X"), - (0x1B150, "V"), - (0x1B153, "X"), - (0x1B155, "V"), - (0x1B156, "X"), - (0x1B164, "V"), - (0x1B168, "X"), - (0x1B170, "V"), - (0x1B2FC, "X"), - (0x1BC00, "V"), - (0x1BC6B, "X"), - (0x1BC70, "V"), - (0x1BC7D, "X"), - (0x1BC80, "V"), - (0x1BC89, "X"), - (0x1BC90, "V"), - (0x1BC9A, "X"), - (0x1BC9C, "V"), - (0x1BCA0, "I"), - (0x1BCA4, "X"), - (0x1CF00, "V"), - (0x1CF2E, "X"), - (0x1CF30, "V"), - (0x1CF47, "X"), - (0x1CF50, "V"), - (0x1CFC4, "X"), - (0x1D000, "V"), - (0x1D0F6, "X"), - (0x1D100, "V"), - (0x1D127, "X"), - (0x1D129, "V"), - (0x1D15E, "M", "𝅗𝅥"), - (0x1D15F, "M", "𝅘𝅥"), - (0x1D160, "M", "𝅘𝅥𝅮"), - (0x1D161, "M", "𝅘𝅥𝅯"), - (0x1D162, "M", "𝅘𝅥𝅰"), - (0x1D163, "M", "𝅘𝅥𝅱"), - (0x1D164, "M", "𝅘𝅥𝅲"), - (0x1D165, "V"), - (0x1D173, "X"), - (0x1D17B, "V"), - (0x1D1BB, "M", "𝆹𝅥"), - (0x1D1BC, "M", "𝆺𝅥"), - (0x1D1BD, "M", "𝆹𝅥𝅮"), - (0x1D1BE, "M", "𝆺𝅥𝅮"), - (0x1D1BF, "M", "𝆹𝅥𝅯"), - (0x1D1C0, "M", "𝆺𝅥𝅯"), - (0x1D1C1, "V"), - (0x1D1EB, "X"), - (0x1D200, "V"), - (0x1D246, "X"), - (0x1D2C0, "V"), - (0x1D2D4, "X"), - (0x1D2E0, "V"), - (0x1D2F4, "X"), - (0x1D300, "V"), - (0x1D357, "X"), - (0x1D360, "V"), - (0x1D379, "X"), - (0x1D400, "M", "a"), - (0x1D401, "M", "b"), - (0x1D402, "M", "c"), - (0x1D403, "M", "d"), - (0x1D404, "M", "e"), - (0x1D405, "M", "f"), - (0x1D406, "M", "g"), - (0x1D407, "M", "h"), - (0x1D408, "M", "i"), - (0x1D409, "M", "j"), - (0x1D40A, "M", "k"), - (0x1D40B, "M", "l"), - (0x1D40C, "M", "m"), - (0x1D40D, "M", "n"), - (0x1D40E, "M", "o"), - (0x1D40F, "M", "p"), - (0x1D410, "M", "q"), - (0x1D411, "M", "r"), - (0x1D412, "M", "s"), - (0x1D413, "M", "t"), - (0x1D414, "M", "u"), - (0x1D415, "M", "v"), - (0x1D416, "M", "w"), - (0x1D417, "M", "x"), - (0x1D418, "M", "y"), - (0x1D419, "M", "z"), - (0x1D41A, "M", "a"), - (0x1D41B, "M", "b"), - (0x1D41C, "M", "c"), - (0x1D41D, "M", "d"), - (0x1D41E, "M", "e"), - (0x1D41F, "M", "f"), - (0x1D420, "M", "g"), - (0x1D421, "M", "h"), - (0x1D422, "M", "i"), - (0x1D423, "M", "j"), - (0x1D424, "M", "k"), + (0x1AFF4, 'X'), + (0x1AFF5, 'V'), + (0x1AFFC, 'X'), + (0x1AFFD, 'V'), + (0x1AFFF, 'X'), + (0x1B000, 'V'), + (0x1B123, 'X'), + (0x1B132, 'V'), + (0x1B133, 'X'), + (0x1B150, 'V'), + (0x1B153, 'X'), + (0x1B155, 'V'), + (0x1B156, 'X'), + (0x1B164, 'V'), + (0x1B168, 'X'), + (0x1B170, 'V'), + (0x1B2FC, 'X'), + (0x1BC00, 'V'), + (0x1BC6B, 'X'), + (0x1BC70, 'V'), + (0x1BC7D, 'X'), + (0x1BC80, 'V'), + (0x1BC89, 'X'), + (0x1BC90, 'V'), + (0x1BC9A, 'X'), + (0x1BC9C, 'V'), + (0x1BCA0, 'I'), + (0x1BCA4, 'X'), + (0x1CF00, 'V'), + (0x1CF2E, 'X'), + (0x1CF30, 'V'), + (0x1CF47, 'X'), + (0x1CF50, 'V'), + (0x1CFC4, 'X'), + (0x1D000, 'V'), + (0x1D0F6, 'X'), + (0x1D100, 'V'), + (0x1D127, 'X'), + (0x1D129, 'V'), + (0x1D15E, 'M', '𝅗𝅥'), + (0x1D15F, 'M', '𝅘𝅥'), + (0x1D160, 'M', '𝅘𝅥𝅮'), + (0x1D161, 'M', '𝅘𝅥𝅯'), + (0x1D162, 'M', '𝅘𝅥𝅰'), + (0x1D163, 'M', '𝅘𝅥𝅱'), + (0x1D164, 'M', '𝅘𝅥𝅲'), + (0x1D165, 'V'), + (0x1D173, 'X'), + (0x1D17B, 'V'), + (0x1D1BB, 'M', '𝆹𝅥'), + (0x1D1BC, 'M', '𝆺𝅥'), + (0x1D1BD, 'M', '𝆹𝅥𝅮'), + (0x1D1BE, 'M', '𝆺𝅥𝅮'), + (0x1D1BF, 'M', '𝆹𝅥𝅯'), + (0x1D1C0, 'M', '𝆺𝅥𝅯'), + (0x1D1C1, 'V'), + (0x1D1EB, 'X'), + (0x1D200, 'V'), + (0x1D246, 'X'), + (0x1D2C0, 'V'), + (0x1D2D4, 'X'), + (0x1D2E0, 'V'), + (0x1D2F4, 'X'), + (0x1D300, 'V'), + (0x1D357, 'X'), + (0x1D360, 'V'), + (0x1D379, 'X'), + (0x1D400, 'M', 'a'), + (0x1D401, 'M', 'b'), + (0x1D402, 'M', 'c'), + (0x1D403, 'M', 'd'), + (0x1D404, 'M', 'e'), + (0x1D405, 'M', 'f'), + (0x1D406, 'M', 'g'), + (0x1D407, 'M', 'h'), + (0x1D408, 'M', 'i'), + (0x1D409, 'M', 'j'), + (0x1D40A, 'M', 'k'), + (0x1D40B, 'M', 'l'), + (0x1D40C, 'M', 'm'), + (0x1D40D, 'M', 'n'), + (0x1D40E, 'M', 'o'), + (0x1D40F, 'M', 'p'), + (0x1D410, 'M', 'q'), + (0x1D411, 'M', 'r'), + (0x1D412, 'M', 's'), + (0x1D413, 'M', 't'), + (0x1D414, 'M', 'u'), + (0x1D415, 'M', 'v'), + (0x1D416, 'M', 'w'), + (0x1D417, 'M', 'x'), + (0x1D418, 'M', 'y'), + (0x1D419, 'M', 'z'), + (0x1D41A, 'M', 'a'), + (0x1D41B, 'M', 'b'), + (0x1D41C, 'M', 'c'), + (0x1D41D, 'M', 'd'), + (0x1D41E, 'M', 'e'), + (0x1D41F, 'M', 'f'), + (0x1D420, 'M', 'g'), ] - def _seg_61() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x1D425, "M", "l"), - (0x1D426, "M", "m"), - (0x1D427, "M", "n"), - (0x1D428, "M", "o"), - (0x1D429, "M", "p"), - (0x1D42A, "M", "q"), - (0x1D42B, "M", "r"), - (0x1D42C, "M", "s"), - (0x1D42D, "M", "t"), - (0x1D42E, "M", "u"), - (0x1D42F, "M", "v"), - (0x1D430, "M", "w"), - (0x1D431, "M", "x"), - (0x1D432, "M", "y"), - (0x1D433, "M", "z"), - (0x1D434, "M", "a"), - (0x1D435, "M", "b"), - (0x1D436, "M", "c"), - (0x1D437, "M", "d"), - (0x1D438, "M", "e"), - (0x1D439, "M", "f"), - (0x1D43A, "M", "g"), - (0x1D43B, "M", "h"), - (0x1D43C, "M", "i"), - (0x1D43D, "M", "j"), - (0x1D43E, "M", "k"), - (0x1D43F, "M", "l"), - (0x1D440, "M", "m"), - (0x1D441, "M", "n"), - (0x1D442, "M", "o"), - (0x1D443, "M", "p"), - (0x1D444, "M", "q"), - (0x1D445, "M", "r"), - (0x1D446, "M", "s"), - (0x1D447, "M", "t"), - (0x1D448, "M", "u"), - (0x1D449, "M", "v"), - (0x1D44A, "M", "w"), - (0x1D44B, "M", "x"), - (0x1D44C, "M", "y"), - (0x1D44D, "M", "z"), - (0x1D44E, "M", "a"), - (0x1D44F, "M", "b"), - (0x1D450, "M", "c"), - (0x1D451, "M", "d"), - (0x1D452, "M", "e"), - (0x1D453, "M", "f"), - (0x1D454, "M", "g"), - (0x1D455, "X"), - (0x1D456, "M", "i"), - (0x1D457, "M", "j"), - (0x1D458, "M", "k"), - (0x1D459, "M", "l"), - (0x1D45A, "M", "m"), - (0x1D45B, "M", "n"), - (0x1D45C, "M", "o"), - (0x1D45D, "M", "p"), - (0x1D45E, "M", "q"), - (0x1D45F, "M", "r"), - (0x1D460, "M", "s"), - (0x1D461, "M", "t"), - (0x1D462, "M", "u"), - (0x1D463, "M", "v"), - (0x1D464, "M", "w"), - (0x1D465, "M", "x"), - (0x1D466, "M", "y"), - (0x1D467, "M", "z"), - (0x1D468, "M", "a"), - (0x1D469, "M", "b"), - (0x1D46A, "M", "c"), - (0x1D46B, "M", "d"), - (0x1D46C, "M", "e"), - (0x1D46D, "M", "f"), - (0x1D46E, "M", "g"), - (0x1D46F, "M", "h"), - (0x1D470, "M", "i"), - (0x1D471, "M", "j"), - (0x1D472, "M", "k"), - (0x1D473, "M", "l"), - (0x1D474, "M", "m"), - (0x1D475, "M", "n"), - (0x1D476, "M", "o"), - (0x1D477, "M", "p"), - (0x1D478, "M", "q"), - (0x1D479, "M", "r"), - (0x1D47A, "M", "s"), - (0x1D47B, "M", "t"), - (0x1D47C, "M", "u"), - (0x1D47D, "M", "v"), - (0x1D47E, "M", "w"), - (0x1D47F, "M", "x"), - (0x1D480, "M", "y"), - (0x1D481, "M", "z"), - (0x1D482, "M", "a"), - (0x1D483, "M", "b"), - (0x1D484, "M", "c"), - (0x1D485, "M", "d"), - (0x1D486, "M", "e"), - (0x1D487, "M", "f"), - (0x1D488, "M", "g"), + (0x1D421, 'M', 'h'), + (0x1D422, 'M', 'i'), + (0x1D423, 'M', 'j'), + (0x1D424, 'M', 'k'), + (0x1D425, 'M', 'l'), + (0x1D426, 'M', 'm'), + (0x1D427, 'M', 'n'), + (0x1D428, 'M', 'o'), + (0x1D429, 'M', 'p'), + (0x1D42A, 'M', 'q'), + (0x1D42B, 'M', 'r'), + (0x1D42C, 'M', 's'), + (0x1D42D, 'M', 't'), + (0x1D42E, 'M', 'u'), + (0x1D42F, 'M', 'v'), + (0x1D430, 'M', 'w'), + (0x1D431, 'M', 'x'), + (0x1D432, 'M', 'y'), + (0x1D433, 'M', 'z'), + (0x1D434, 'M', 'a'), + (0x1D435, 'M', 'b'), + (0x1D436, 'M', 'c'), + (0x1D437, 'M', 'd'), + (0x1D438, 'M', 'e'), + (0x1D439, 'M', 'f'), + (0x1D43A, 'M', 'g'), + (0x1D43B, 'M', 'h'), + (0x1D43C, 'M', 'i'), + (0x1D43D, 'M', 'j'), + (0x1D43E, 'M', 'k'), + (0x1D43F, 'M', 'l'), + (0x1D440, 'M', 'm'), + (0x1D441, 'M', 'n'), + (0x1D442, 'M', 'o'), + (0x1D443, 'M', 'p'), + (0x1D444, 'M', 'q'), + (0x1D445, 'M', 'r'), + (0x1D446, 'M', 's'), + (0x1D447, 'M', 't'), + (0x1D448, 'M', 'u'), + (0x1D449, 'M', 'v'), + (0x1D44A, 'M', 'w'), + (0x1D44B, 'M', 'x'), + (0x1D44C, 'M', 'y'), + (0x1D44D, 'M', 'z'), + (0x1D44E, 'M', 'a'), + (0x1D44F, 'M', 'b'), + (0x1D450, 'M', 'c'), + (0x1D451, 'M', 'd'), + (0x1D452, 'M', 'e'), + (0x1D453, 'M', 'f'), + (0x1D454, 'M', 'g'), + (0x1D455, 'X'), + (0x1D456, 'M', 'i'), + (0x1D457, 'M', 'j'), + (0x1D458, 'M', 'k'), + (0x1D459, 'M', 'l'), + (0x1D45A, 'M', 'm'), + (0x1D45B, 'M', 'n'), + (0x1D45C, 'M', 'o'), + (0x1D45D, 'M', 'p'), + (0x1D45E, 'M', 'q'), + (0x1D45F, 'M', 'r'), + (0x1D460, 'M', 's'), + (0x1D461, 'M', 't'), + (0x1D462, 'M', 'u'), + (0x1D463, 'M', 'v'), + (0x1D464, 'M', 'w'), + (0x1D465, 'M', 'x'), + (0x1D466, 'M', 'y'), + (0x1D467, 'M', 'z'), + (0x1D468, 'M', 'a'), + (0x1D469, 'M', 'b'), + (0x1D46A, 'M', 'c'), + (0x1D46B, 'M', 'd'), + (0x1D46C, 'M', 'e'), + (0x1D46D, 'M', 'f'), + (0x1D46E, 'M', 'g'), + (0x1D46F, 'M', 'h'), + (0x1D470, 'M', 'i'), + (0x1D471, 'M', 'j'), + (0x1D472, 'M', 'k'), + (0x1D473, 'M', 'l'), + (0x1D474, 'M', 'm'), + (0x1D475, 'M', 'n'), + (0x1D476, 'M', 'o'), + (0x1D477, 'M', 'p'), + (0x1D478, 'M', 'q'), + (0x1D479, 'M', 'r'), + (0x1D47A, 'M', 's'), + (0x1D47B, 'M', 't'), + (0x1D47C, 'M', 'u'), + (0x1D47D, 'M', 'v'), + (0x1D47E, 'M', 'w'), + (0x1D47F, 'M', 'x'), + (0x1D480, 'M', 'y'), + (0x1D481, 'M', 'z'), + (0x1D482, 'M', 'a'), + (0x1D483, 'M', 'b'), + (0x1D484, 'M', 'c'), ] - def _seg_62() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x1D489, "M", "h"), - (0x1D48A, "M", "i"), - (0x1D48B, "M", "j"), - (0x1D48C, "M", "k"), - (0x1D48D, "M", "l"), - (0x1D48E, "M", "m"), - (0x1D48F, "M", "n"), - (0x1D490, "M", "o"), - (0x1D491, "M", "p"), - (0x1D492, "M", "q"), - (0x1D493, "M", "r"), - (0x1D494, "M", "s"), - (0x1D495, "M", "t"), - (0x1D496, "M", "u"), - (0x1D497, "M", "v"), - (0x1D498, "M", "w"), - (0x1D499, "M", "x"), - (0x1D49A, "M", "y"), - (0x1D49B, "M", "z"), - (0x1D49C, "M", "a"), - (0x1D49D, "X"), - (0x1D49E, "M", "c"), - (0x1D49F, "M", "d"), - (0x1D4A0, "X"), - (0x1D4A2, "M", "g"), - (0x1D4A3, "X"), - (0x1D4A5, "M", "j"), - (0x1D4A6, "M", "k"), - (0x1D4A7, "X"), - (0x1D4A9, "M", "n"), - (0x1D4AA, "M", "o"), - (0x1D4AB, "M", "p"), - (0x1D4AC, "M", "q"), - (0x1D4AD, "X"), - (0x1D4AE, "M", "s"), - (0x1D4AF, "M", "t"), - (0x1D4B0, "M", "u"), - (0x1D4B1, "M", "v"), - (0x1D4B2, "M", "w"), - (0x1D4B3, "M", "x"), - (0x1D4B4, "M", "y"), - (0x1D4B5, "M", "z"), - (0x1D4B6, "M", "a"), - (0x1D4B7, "M", "b"), - (0x1D4B8, "M", "c"), - (0x1D4B9, "M", "d"), - (0x1D4BA, "X"), - (0x1D4BB, "M", "f"), - (0x1D4BC, "X"), - (0x1D4BD, "M", "h"), - (0x1D4BE, "M", "i"), - (0x1D4BF, "M", "j"), - (0x1D4C0, "M", "k"), - (0x1D4C1, "M", "l"), - (0x1D4C2, "M", "m"), - (0x1D4C3, "M", "n"), - (0x1D4C4, "X"), - (0x1D4C5, "M", "p"), - (0x1D4C6, "M", "q"), - (0x1D4C7, "M", "r"), - (0x1D4C8, "M", "s"), - (0x1D4C9, "M", "t"), - (0x1D4CA, "M", "u"), - (0x1D4CB, "M", "v"), - (0x1D4CC, "M", "w"), - (0x1D4CD, "M", "x"), - (0x1D4CE, "M", "y"), - (0x1D4CF, "M", "z"), - (0x1D4D0, "M", "a"), - (0x1D4D1, "M", "b"), - (0x1D4D2, "M", "c"), - (0x1D4D3, "M", "d"), - (0x1D4D4, "M", "e"), - (0x1D4D5, "M", "f"), - (0x1D4D6, "M", "g"), - (0x1D4D7, "M", "h"), - (0x1D4D8, "M", "i"), - (0x1D4D9, "M", "j"), - (0x1D4DA, "M", "k"), - (0x1D4DB, "M", "l"), - (0x1D4DC, "M", "m"), - (0x1D4DD, "M", "n"), - (0x1D4DE, "M", "o"), - (0x1D4DF, "M", "p"), - (0x1D4E0, "M", "q"), - (0x1D4E1, "M", "r"), - (0x1D4E2, "M", "s"), - (0x1D4E3, "M", "t"), - (0x1D4E4, "M", "u"), - (0x1D4E5, "M", "v"), - (0x1D4E6, "M", "w"), - (0x1D4E7, "M", "x"), - (0x1D4E8, "M", "y"), - (0x1D4E9, "M", "z"), - (0x1D4EA, "M", "a"), - (0x1D4EB, "M", "b"), - (0x1D4EC, "M", "c"), - (0x1D4ED, "M", "d"), - (0x1D4EE, "M", "e"), - (0x1D4EF, "M", "f"), + (0x1D485, 'M', 'd'), + (0x1D486, 'M', 'e'), + (0x1D487, 'M', 'f'), + (0x1D488, 'M', 'g'), + (0x1D489, 'M', 'h'), + (0x1D48A, 'M', 'i'), + (0x1D48B, 'M', 'j'), + (0x1D48C, 'M', 'k'), + (0x1D48D, 'M', 'l'), + (0x1D48E, 'M', 'm'), + (0x1D48F, 'M', 'n'), + (0x1D490, 'M', 'o'), + (0x1D491, 'M', 'p'), + (0x1D492, 'M', 'q'), + (0x1D493, 'M', 'r'), + (0x1D494, 'M', 's'), + (0x1D495, 'M', 't'), + (0x1D496, 'M', 'u'), + (0x1D497, 'M', 'v'), + (0x1D498, 'M', 'w'), + (0x1D499, 'M', 'x'), + (0x1D49A, 'M', 'y'), + (0x1D49B, 'M', 'z'), + (0x1D49C, 'M', 'a'), + (0x1D49D, 'X'), + (0x1D49E, 'M', 'c'), + (0x1D49F, 'M', 'd'), + (0x1D4A0, 'X'), + (0x1D4A2, 'M', 'g'), + (0x1D4A3, 'X'), + (0x1D4A5, 'M', 'j'), + (0x1D4A6, 'M', 'k'), + (0x1D4A7, 'X'), + (0x1D4A9, 'M', 'n'), + (0x1D4AA, 'M', 'o'), + (0x1D4AB, 'M', 'p'), + (0x1D4AC, 'M', 'q'), + (0x1D4AD, 'X'), + (0x1D4AE, 'M', 's'), + (0x1D4AF, 'M', 't'), + (0x1D4B0, 'M', 'u'), + (0x1D4B1, 'M', 'v'), + (0x1D4B2, 'M', 'w'), + (0x1D4B3, 'M', 'x'), + (0x1D4B4, 'M', 'y'), + (0x1D4B5, 'M', 'z'), + (0x1D4B6, 'M', 'a'), + (0x1D4B7, 'M', 'b'), + (0x1D4B8, 'M', 'c'), + (0x1D4B9, 'M', 'd'), + (0x1D4BA, 'X'), + (0x1D4BB, 'M', 'f'), + (0x1D4BC, 'X'), + (0x1D4BD, 'M', 'h'), + (0x1D4BE, 'M', 'i'), + (0x1D4BF, 'M', 'j'), + (0x1D4C0, 'M', 'k'), + (0x1D4C1, 'M', 'l'), + (0x1D4C2, 'M', 'm'), + (0x1D4C3, 'M', 'n'), + (0x1D4C4, 'X'), + (0x1D4C5, 'M', 'p'), + (0x1D4C6, 'M', 'q'), + (0x1D4C7, 'M', 'r'), + (0x1D4C8, 'M', 's'), + (0x1D4C9, 'M', 't'), + (0x1D4CA, 'M', 'u'), + (0x1D4CB, 'M', 'v'), + (0x1D4CC, 'M', 'w'), + (0x1D4CD, 'M', 'x'), + (0x1D4CE, 'M', 'y'), + (0x1D4CF, 'M', 'z'), + (0x1D4D0, 'M', 'a'), + (0x1D4D1, 'M', 'b'), + (0x1D4D2, 'M', 'c'), + (0x1D4D3, 'M', 'd'), + (0x1D4D4, 'M', 'e'), + (0x1D4D5, 'M', 'f'), + (0x1D4D6, 'M', 'g'), + (0x1D4D7, 'M', 'h'), + (0x1D4D8, 'M', 'i'), + (0x1D4D9, 'M', 'j'), + (0x1D4DA, 'M', 'k'), + (0x1D4DB, 'M', 'l'), + (0x1D4DC, 'M', 'm'), + (0x1D4DD, 'M', 'n'), + (0x1D4DE, 'M', 'o'), + (0x1D4DF, 'M', 'p'), + (0x1D4E0, 'M', 'q'), + (0x1D4E1, 'M', 'r'), + (0x1D4E2, 'M', 's'), + (0x1D4E3, 'M', 't'), + (0x1D4E4, 'M', 'u'), + (0x1D4E5, 'M', 'v'), + (0x1D4E6, 'M', 'w'), + (0x1D4E7, 'M', 'x'), + (0x1D4E8, 'M', 'y'), + (0x1D4E9, 'M', 'z'), + (0x1D4EA, 'M', 'a'), + (0x1D4EB, 'M', 'b'), ] - def _seg_63() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x1D4F0, "M", "g"), - (0x1D4F1, "M", "h"), - (0x1D4F2, "M", "i"), - (0x1D4F3, "M", "j"), - (0x1D4F4, "M", "k"), - (0x1D4F5, "M", "l"), - (0x1D4F6, "M", "m"), - (0x1D4F7, "M", "n"), - (0x1D4F8, "M", "o"), - (0x1D4F9, "M", "p"), - (0x1D4FA, "M", "q"), - (0x1D4FB, "M", "r"), - (0x1D4FC, "M", "s"), - (0x1D4FD, "M", "t"), - (0x1D4FE, "M", "u"), - (0x1D4FF, "M", "v"), - (0x1D500, "M", "w"), - (0x1D501, "M", "x"), - (0x1D502, "M", "y"), - (0x1D503, "M", "z"), - (0x1D504, "M", "a"), - (0x1D505, "M", "b"), - (0x1D506, "X"), - (0x1D507, "M", "d"), - (0x1D508, "M", "e"), - (0x1D509, "M", "f"), - (0x1D50A, "M", "g"), - (0x1D50B, "X"), - (0x1D50D, "M", "j"), - (0x1D50E, "M", "k"), - (0x1D50F, "M", "l"), - (0x1D510, "M", "m"), - (0x1D511, "M", "n"), - (0x1D512, "M", "o"), - (0x1D513, "M", "p"), - (0x1D514, "M", "q"), - (0x1D515, "X"), - (0x1D516, "M", "s"), - (0x1D517, "M", "t"), - (0x1D518, "M", "u"), - (0x1D519, "M", "v"), - (0x1D51A, "M", "w"), - (0x1D51B, "M", "x"), - (0x1D51C, "M", "y"), - (0x1D51D, "X"), - (0x1D51E, "M", "a"), - (0x1D51F, "M", "b"), - (0x1D520, "M", "c"), - (0x1D521, "M", "d"), - (0x1D522, "M", "e"), - (0x1D523, "M", "f"), - (0x1D524, "M", "g"), - (0x1D525, "M", "h"), - (0x1D526, "M", "i"), - (0x1D527, "M", "j"), - (0x1D528, "M", "k"), - (0x1D529, "M", "l"), - (0x1D52A, "M", "m"), - (0x1D52B, "M", "n"), - (0x1D52C, "M", "o"), - (0x1D52D, "M", "p"), - (0x1D52E, "M", "q"), - (0x1D52F, "M", "r"), - (0x1D530, "M", "s"), - (0x1D531, "M", "t"), - (0x1D532, "M", "u"), - (0x1D533, "M", "v"), - (0x1D534, "M", "w"), - (0x1D535, "M", "x"), - (0x1D536, "M", "y"), - (0x1D537, "M", "z"), - (0x1D538, "M", "a"), - (0x1D539, "M", "b"), - (0x1D53A, "X"), - (0x1D53B, "M", "d"), - (0x1D53C, "M", "e"), - (0x1D53D, "M", "f"), - (0x1D53E, "M", "g"), - (0x1D53F, "X"), - (0x1D540, "M", "i"), - (0x1D541, "M", "j"), - (0x1D542, "M", "k"), - (0x1D543, "M", "l"), - (0x1D544, "M", "m"), - (0x1D545, "X"), - (0x1D546, "M", "o"), - (0x1D547, "X"), - (0x1D54A, "M", "s"), - (0x1D54B, "M", "t"), - (0x1D54C, "M", "u"), - (0x1D54D, "M", "v"), - (0x1D54E, "M", "w"), - (0x1D54F, "M", "x"), - (0x1D550, "M", "y"), - (0x1D551, "X"), - (0x1D552, "M", "a"), - (0x1D553, "M", "b"), - (0x1D554, "M", "c"), - (0x1D555, "M", "d"), - (0x1D556, "M", "e"), + (0x1D4EC, 'M', 'c'), + (0x1D4ED, 'M', 'd'), + (0x1D4EE, 'M', 'e'), + (0x1D4EF, 'M', 'f'), + (0x1D4F0, 'M', 'g'), + (0x1D4F1, 'M', 'h'), + (0x1D4F2, 'M', 'i'), + (0x1D4F3, 'M', 'j'), + (0x1D4F4, 'M', 'k'), + (0x1D4F5, 'M', 'l'), + (0x1D4F6, 'M', 'm'), + (0x1D4F7, 'M', 'n'), + (0x1D4F8, 'M', 'o'), + (0x1D4F9, 'M', 'p'), + (0x1D4FA, 'M', 'q'), + (0x1D4FB, 'M', 'r'), + (0x1D4FC, 'M', 's'), + (0x1D4FD, 'M', 't'), + (0x1D4FE, 'M', 'u'), + (0x1D4FF, 'M', 'v'), + (0x1D500, 'M', 'w'), + (0x1D501, 'M', 'x'), + (0x1D502, 'M', 'y'), + (0x1D503, 'M', 'z'), + (0x1D504, 'M', 'a'), + (0x1D505, 'M', 'b'), + (0x1D506, 'X'), + (0x1D507, 'M', 'd'), + (0x1D508, 'M', 'e'), + (0x1D509, 'M', 'f'), + (0x1D50A, 'M', 'g'), + (0x1D50B, 'X'), + (0x1D50D, 'M', 'j'), + (0x1D50E, 'M', 'k'), + (0x1D50F, 'M', 'l'), + (0x1D510, 'M', 'm'), + (0x1D511, 'M', 'n'), + (0x1D512, 'M', 'o'), + (0x1D513, 'M', 'p'), + (0x1D514, 'M', 'q'), + (0x1D515, 'X'), + (0x1D516, 'M', 's'), + (0x1D517, 'M', 't'), + (0x1D518, 'M', 'u'), + (0x1D519, 'M', 'v'), + (0x1D51A, 'M', 'w'), + (0x1D51B, 'M', 'x'), + (0x1D51C, 'M', 'y'), + (0x1D51D, 'X'), + (0x1D51E, 'M', 'a'), + (0x1D51F, 'M', 'b'), + (0x1D520, 'M', 'c'), + (0x1D521, 'M', 'd'), + (0x1D522, 'M', 'e'), + (0x1D523, 'M', 'f'), + (0x1D524, 'M', 'g'), + (0x1D525, 'M', 'h'), + (0x1D526, 'M', 'i'), + (0x1D527, 'M', 'j'), + (0x1D528, 'M', 'k'), + (0x1D529, 'M', 'l'), + (0x1D52A, 'M', 'm'), + (0x1D52B, 'M', 'n'), + (0x1D52C, 'M', 'o'), + (0x1D52D, 'M', 'p'), + (0x1D52E, 'M', 'q'), + (0x1D52F, 'M', 'r'), + (0x1D530, 'M', 's'), + (0x1D531, 'M', 't'), + (0x1D532, 'M', 'u'), + (0x1D533, 'M', 'v'), + (0x1D534, 'M', 'w'), + (0x1D535, 'M', 'x'), + (0x1D536, 'M', 'y'), + (0x1D537, 'M', 'z'), + (0x1D538, 'M', 'a'), + (0x1D539, 'M', 'b'), + (0x1D53A, 'X'), + (0x1D53B, 'M', 'd'), + (0x1D53C, 'M', 'e'), + (0x1D53D, 'M', 'f'), + (0x1D53E, 'M', 'g'), + (0x1D53F, 'X'), + (0x1D540, 'M', 'i'), + (0x1D541, 'M', 'j'), + (0x1D542, 'M', 'k'), + (0x1D543, 'M', 'l'), + (0x1D544, 'M', 'm'), + (0x1D545, 'X'), + (0x1D546, 'M', 'o'), + (0x1D547, 'X'), + (0x1D54A, 'M', 's'), + (0x1D54B, 'M', 't'), + (0x1D54C, 'M', 'u'), + (0x1D54D, 'M', 'v'), + (0x1D54E, 'M', 'w'), + (0x1D54F, 'M', 'x'), + (0x1D550, 'M', 'y'), + (0x1D551, 'X'), + (0x1D552, 'M', 'a'), ] - def _seg_64() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x1D557, "M", "f"), - (0x1D558, "M", "g"), - (0x1D559, "M", "h"), - (0x1D55A, "M", "i"), - (0x1D55B, "M", "j"), - (0x1D55C, "M", "k"), - (0x1D55D, "M", "l"), - (0x1D55E, "M", "m"), - (0x1D55F, "M", "n"), - (0x1D560, "M", "o"), - (0x1D561, "M", "p"), - (0x1D562, "M", "q"), - (0x1D563, "M", "r"), - (0x1D564, "M", "s"), - (0x1D565, "M", "t"), - (0x1D566, "M", "u"), - (0x1D567, "M", "v"), - (0x1D568, "M", "w"), - (0x1D569, "M", "x"), - (0x1D56A, "M", "y"), - (0x1D56B, "M", "z"), - (0x1D56C, "M", "a"), - (0x1D56D, "M", "b"), - (0x1D56E, "M", "c"), - (0x1D56F, "M", "d"), - (0x1D570, "M", "e"), - (0x1D571, "M", "f"), - (0x1D572, "M", "g"), - (0x1D573, "M", "h"), - (0x1D574, "M", "i"), - (0x1D575, "M", "j"), - (0x1D576, "M", "k"), - (0x1D577, "M", "l"), - (0x1D578, "M", "m"), - (0x1D579, "M", "n"), - (0x1D57A, "M", "o"), - (0x1D57B, "M", "p"), - (0x1D57C, "M", "q"), - (0x1D57D, "M", "r"), - (0x1D57E, "M", "s"), - (0x1D57F, "M", "t"), - (0x1D580, "M", "u"), - (0x1D581, "M", "v"), - (0x1D582, "M", "w"), - (0x1D583, "M", "x"), - (0x1D584, "M", "y"), - (0x1D585, "M", "z"), - (0x1D586, "M", "a"), - (0x1D587, "M", "b"), - (0x1D588, "M", "c"), - (0x1D589, "M", "d"), - (0x1D58A, "M", "e"), - (0x1D58B, "M", "f"), - (0x1D58C, "M", "g"), - (0x1D58D, "M", "h"), - (0x1D58E, "M", "i"), - (0x1D58F, "M", "j"), - (0x1D590, "M", "k"), - (0x1D591, "M", "l"), - (0x1D592, "M", "m"), - (0x1D593, "M", "n"), - (0x1D594, "M", "o"), - (0x1D595, "M", "p"), - (0x1D596, "M", "q"), - (0x1D597, "M", "r"), - (0x1D598, "M", "s"), - (0x1D599, "M", "t"), - (0x1D59A, "M", "u"), - (0x1D59B, "M", "v"), - (0x1D59C, "M", "w"), - (0x1D59D, "M", "x"), - (0x1D59E, "M", "y"), - (0x1D59F, "M", "z"), - (0x1D5A0, "M", "a"), - (0x1D5A1, "M", "b"), - (0x1D5A2, "M", "c"), - (0x1D5A3, "M", "d"), - (0x1D5A4, "M", "e"), - (0x1D5A5, "M", "f"), - (0x1D5A6, "M", "g"), - (0x1D5A7, "M", "h"), - (0x1D5A8, "M", "i"), - (0x1D5A9, "M", "j"), - (0x1D5AA, "M", "k"), - (0x1D5AB, "M", "l"), - (0x1D5AC, "M", "m"), - (0x1D5AD, "M", "n"), - (0x1D5AE, "M", "o"), - (0x1D5AF, "M", "p"), - (0x1D5B0, "M", "q"), - (0x1D5B1, "M", "r"), - (0x1D5B2, "M", "s"), - (0x1D5B3, "M", "t"), - (0x1D5B4, "M", "u"), - (0x1D5B5, "M", "v"), - (0x1D5B6, "M", "w"), - (0x1D5B7, "M", "x"), - (0x1D5B8, "M", "y"), - (0x1D5B9, "M", "z"), - (0x1D5BA, "M", "a"), + (0x1D553, 'M', 'b'), + (0x1D554, 'M', 'c'), + (0x1D555, 'M', 'd'), + (0x1D556, 'M', 'e'), + (0x1D557, 'M', 'f'), + (0x1D558, 'M', 'g'), + (0x1D559, 'M', 'h'), + (0x1D55A, 'M', 'i'), + (0x1D55B, 'M', 'j'), + (0x1D55C, 'M', 'k'), + (0x1D55D, 'M', 'l'), + (0x1D55E, 'M', 'm'), + (0x1D55F, 'M', 'n'), + (0x1D560, 'M', 'o'), + (0x1D561, 'M', 'p'), + (0x1D562, 'M', 'q'), + (0x1D563, 'M', 'r'), + (0x1D564, 'M', 's'), + (0x1D565, 'M', 't'), + (0x1D566, 'M', 'u'), + (0x1D567, 'M', 'v'), + (0x1D568, 'M', 'w'), + (0x1D569, 'M', 'x'), + (0x1D56A, 'M', 'y'), + (0x1D56B, 'M', 'z'), + (0x1D56C, 'M', 'a'), + (0x1D56D, 'M', 'b'), + (0x1D56E, 'M', 'c'), + (0x1D56F, 'M', 'd'), + (0x1D570, 'M', 'e'), + (0x1D571, 'M', 'f'), + (0x1D572, 'M', 'g'), + (0x1D573, 'M', 'h'), + (0x1D574, 'M', 'i'), + (0x1D575, 'M', 'j'), + (0x1D576, 'M', 'k'), + (0x1D577, 'M', 'l'), + (0x1D578, 'M', 'm'), + (0x1D579, 'M', 'n'), + (0x1D57A, 'M', 'o'), + (0x1D57B, 'M', 'p'), + (0x1D57C, 'M', 'q'), + (0x1D57D, 'M', 'r'), + (0x1D57E, 'M', 's'), + (0x1D57F, 'M', 't'), + (0x1D580, 'M', 'u'), + (0x1D581, 'M', 'v'), + (0x1D582, 'M', 'w'), + (0x1D583, 'M', 'x'), + (0x1D584, 'M', 'y'), + (0x1D585, 'M', 'z'), + (0x1D586, 'M', 'a'), + (0x1D587, 'M', 'b'), + (0x1D588, 'M', 'c'), + (0x1D589, 'M', 'd'), + (0x1D58A, 'M', 'e'), + (0x1D58B, 'M', 'f'), + (0x1D58C, 'M', 'g'), + (0x1D58D, 'M', 'h'), + (0x1D58E, 'M', 'i'), + (0x1D58F, 'M', 'j'), + (0x1D590, 'M', 'k'), + (0x1D591, 'M', 'l'), + (0x1D592, 'M', 'm'), + (0x1D593, 'M', 'n'), + (0x1D594, 'M', 'o'), + (0x1D595, 'M', 'p'), + (0x1D596, 'M', 'q'), + (0x1D597, 'M', 'r'), + (0x1D598, 'M', 's'), + (0x1D599, 'M', 't'), + (0x1D59A, 'M', 'u'), + (0x1D59B, 'M', 'v'), + (0x1D59C, 'M', 'w'), + (0x1D59D, 'M', 'x'), + (0x1D59E, 'M', 'y'), + (0x1D59F, 'M', 'z'), + (0x1D5A0, 'M', 'a'), + (0x1D5A1, 'M', 'b'), + (0x1D5A2, 'M', 'c'), + (0x1D5A3, 'M', 'd'), + (0x1D5A4, 'M', 'e'), + (0x1D5A5, 'M', 'f'), + (0x1D5A6, 'M', 'g'), + (0x1D5A7, 'M', 'h'), + (0x1D5A8, 'M', 'i'), + (0x1D5A9, 'M', 'j'), + (0x1D5AA, 'M', 'k'), + (0x1D5AB, 'M', 'l'), + (0x1D5AC, 'M', 'm'), + (0x1D5AD, 'M', 'n'), + (0x1D5AE, 'M', 'o'), + (0x1D5AF, 'M', 'p'), + (0x1D5B0, 'M', 'q'), + (0x1D5B1, 'M', 'r'), + (0x1D5B2, 'M', 's'), + (0x1D5B3, 'M', 't'), + (0x1D5B4, 'M', 'u'), + (0x1D5B5, 'M', 'v'), + (0x1D5B6, 'M', 'w'), ] - def _seg_65() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x1D5BB, "M", "b"), - (0x1D5BC, "M", "c"), - (0x1D5BD, "M", "d"), - (0x1D5BE, "M", "e"), - (0x1D5BF, "M", "f"), - (0x1D5C0, "M", "g"), - (0x1D5C1, "M", "h"), - (0x1D5C2, "M", "i"), - (0x1D5C3, "M", "j"), - (0x1D5C4, "M", "k"), - (0x1D5C5, "M", "l"), - (0x1D5C6, "M", "m"), - (0x1D5C7, "M", "n"), - (0x1D5C8, "M", "o"), - (0x1D5C9, "M", "p"), - (0x1D5CA, "M", "q"), - (0x1D5CB, "M", "r"), - (0x1D5CC, "M", "s"), - (0x1D5CD, "M", "t"), - (0x1D5CE, "M", "u"), - (0x1D5CF, "M", "v"), - (0x1D5D0, "M", "w"), - (0x1D5D1, "M", "x"), - (0x1D5D2, "M", "y"), - (0x1D5D3, "M", "z"), - (0x1D5D4, "M", "a"), - (0x1D5D5, "M", "b"), - (0x1D5D6, "M", "c"), - (0x1D5D7, "M", "d"), - (0x1D5D8, "M", "e"), - (0x1D5D9, "M", "f"), - (0x1D5DA, "M", "g"), - (0x1D5DB, "M", "h"), - (0x1D5DC, "M", "i"), - (0x1D5DD, "M", "j"), - (0x1D5DE, "M", "k"), - (0x1D5DF, "M", "l"), - (0x1D5E0, "M", "m"), - (0x1D5E1, "M", "n"), - (0x1D5E2, "M", "o"), - (0x1D5E3, "M", "p"), - (0x1D5E4, "M", "q"), - (0x1D5E5, "M", "r"), - (0x1D5E6, "M", "s"), - (0x1D5E7, "M", "t"), - (0x1D5E8, "M", "u"), - (0x1D5E9, "M", "v"), - (0x1D5EA, "M", "w"), - (0x1D5EB, "M", "x"), - (0x1D5EC, "M", "y"), - (0x1D5ED, "M", "z"), - (0x1D5EE, "M", "a"), - (0x1D5EF, "M", "b"), - (0x1D5F0, "M", "c"), - (0x1D5F1, "M", "d"), - (0x1D5F2, "M", "e"), - (0x1D5F3, "M", "f"), - (0x1D5F4, "M", "g"), - (0x1D5F5, "M", "h"), - (0x1D5F6, "M", "i"), - (0x1D5F7, "M", "j"), - (0x1D5F8, "M", "k"), - (0x1D5F9, "M", "l"), - (0x1D5FA, "M", "m"), - (0x1D5FB, "M", "n"), - (0x1D5FC, "M", "o"), - (0x1D5FD, "M", "p"), - (0x1D5FE, "M", "q"), - (0x1D5FF, "M", "r"), - (0x1D600, "M", "s"), - (0x1D601, "M", "t"), - (0x1D602, "M", "u"), - (0x1D603, "M", "v"), - (0x1D604, "M", "w"), - (0x1D605, "M", "x"), - (0x1D606, "M", "y"), - (0x1D607, "M", "z"), - (0x1D608, "M", "a"), - (0x1D609, "M", "b"), - (0x1D60A, "M", "c"), - (0x1D60B, "M", "d"), - (0x1D60C, "M", "e"), - (0x1D60D, "M", "f"), - (0x1D60E, "M", "g"), - (0x1D60F, "M", "h"), - (0x1D610, "M", "i"), - (0x1D611, "M", "j"), - (0x1D612, "M", "k"), - (0x1D613, "M", "l"), - (0x1D614, "M", "m"), - (0x1D615, "M", "n"), - (0x1D616, "M", "o"), - (0x1D617, "M", "p"), - (0x1D618, "M", "q"), - (0x1D619, "M", "r"), - (0x1D61A, "M", "s"), - (0x1D61B, "M", "t"), - (0x1D61C, "M", "u"), - (0x1D61D, "M", "v"), - (0x1D61E, "M", "w"), + (0x1D5B7, 'M', 'x'), + (0x1D5B8, 'M', 'y'), + (0x1D5B9, 'M', 'z'), + (0x1D5BA, 'M', 'a'), + (0x1D5BB, 'M', 'b'), + (0x1D5BC, 'M', 'c'), + (0x1D5BD, 'M', 'd'), + (0x1D5BE, 'M', 'e'), + (0x1D5BF, 'M', 'f'), + (0x1D5C0, 'M', 'g'), + (0x1D5C1, 'M', 'h'), + (0x1D5C2, 'M', 'i'), + (0x1D5C3, 'M', 'j'), + (0x1D5C4, 'M', 'k'), + (0x1D5C5, 'M', 'l'), + (0x1D5C6, 'M', 'm'), + (0x1D5C7, 'M', 'n'), + (0x1D5C8, 'M', 'o'), + (0x1D5C9, 'M', 'p'), + (0x1D5CA, 'M', 'q'), + (0x1D5CB, 'M', 'r'), + (0x1D5CC, 'M', 's'), + (0x1D5CD, 'M', 't'), + (0x1D5CE, 'M', 'u'), + (0x1D5CF, 'M', 'v'), + (0x1D5D0, 'M', 'w'), + (0x1D5D1, 'M', 'x'), + (0x1D5D2, 'M', 'y'), + (0x1D5D3, 'M', 'z'), + (0x1D5D4, 'M', 'a'), + (0x1D5D5, 'M', 'b'), + (0x1D5D6, 'M', 'c'), + (0x1D5D7, 'M', 'd'), + (0x1D5D8, 'M', 'e'), + (0x1D5D9, 'M', 'f'), + (0x1D5DA, 'M', 'g'), + (0x1D5DB, 'M', 'h'), + (0x1D5DC, 'M', 'i'), + (0x1D5DD, 'M', 'j'), + (0x1D5DE, 'M', 'k'), + (0x1D5DF, 'M', 'l'), + (0x1D5E0, 'M', 'm'), + (0x1D5E1, 'M', 'n'), + (0x1D5E2, 'M', 'o'), + (0x1D5E3, 'M', 'p'), + (0x1D5E4, 'M', 'q'), + (0x1D5E5, 'M', 'r'), + (0x1D5E6, 'M', 's'), + (0x1D5E7, 'M', 't'), + (0x1D5E8, 'M', 'u'), + (0x1D5E9, 'M', 'v'), + (0x1D5EA, 'M', 'w'), + (0x1D5EB, 'M', 'x'), + (0x1D5EC, 'M', 'y'), + (0x1D5ED, 'M', 'z'), + (0x1D5EE, 'M', 'a'), + (0x1D5EF, 'M', 'b'), + (0x1D5F0, 'M', 'c'), + (0x1D5F1, 'M', 'd'), + (0x1D5F2, 'M', 'e'), + (0x1D5F3, 'M', 'f'), + (0x1D5F4, 'M', 'g'), + (0x1D5F5, 'M', 'h'), + (0x1D5F6, 'M', 'i'), + (0x1D5F7, 'M', 'j'), + (0x1D5F8, 'M', 'k'), + (0x1D5F9, 'M', 'l'), + (0x1D5FA, 'M', 'm'), + (0x1D5FB, 'M', 'n'), + (0x1D5FC, 'M', 'o'), + (0x1D5FD, 'M', 'p'), + (0x1D5FE, 'M', 'q'), + (0x1D5FF, 'M', 'r'), + (0x1D600, 'M', 's'), + (0x1D601, 'M', 't'), + (0x1D602, 'M', 'u'), + (0x1D603, 'M', 'v'), + (0x1D604, 'M', 'w'), + (0x1D605, 'M', 'x'), + (0x1D606, 'M', 'y'), + (0x1D607, 'M', 'z'), + (0x1D608, 'M', 'a'), + (0x1D609, 'M', 'b'), + (0x1D60A, 'M', 'c'), + (0x1D60B, 'M', 'd'), + (0x1D60C, 'M', 'e'), + (0x1D60D, 'M', 'f'), + (0x1D60E, 'M', 'g'), + (0x1D60F, 'M', 'h'), + (0x1D610, 'M', 'i'), + (0x1D611, 'M', 'j'), + (0x1D612, 'M', 'k'), + (0x1D613, 'M', 'l'), + (0x1D614, 'M', 'm'), + (0x1D615, 'M', 'n'), + (0x1D616, 'M', 'o'), + (0x1D617, 'M', 'p'), + (0x1D618, 'M', 'q'), + (0x1D619, 'M', 'r'), + (0x1D61A, 'M', 's'), ] - def _seg_66() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x1D61F, "M", "x"), - (0x1D620, "M", "y"), - (0x1D621, "M", "z"), - (0x1D622, "M", "a"), - (0x1D623, "M", "b"), - (0x1D624, "M", "c"), - (0x1D625, "M", "d"), - (0x1D626, "M", "e"), - (0x1D627, "M", "f"), - (0x1D628, "M", "g"), - (0x1D629, "M", "h"), - (0x1D62A, "M", "i"), - (0x1D62B, "M", "j"), - (0x1D62C, "M", "k"), - (0x1D62D, "M", "l"), - (0x1D62E, "M", "m"), - (0x1D62F, "M", "n"), - (0x1D630, "M", "o"), - (0x1D631, "M", "p"), - (0x1D632, "M", "q"), - (0x1D633, "M", "r"), - (0x1D634, "M", "s"), - (0x1D635, "M", "t"), - (0x1D636, "M", "u"), - (0x1D637, "M", "v"), - (0x1D638, "M", "w"), - (0x1D639, "M", "x"), - (0x1D63A, "M", "y"), - (0x1D63B, "M", "z"), - (0x1D63C, "M", "a"), - (0x1D63D, "M", "b"), - (0x1D63E, "M", "c"), - (0x1D63F, "M", "d"), - (0x1D640, "M", "e"), - (0x1D641, "M", "f"), - (0x1D642, "M", "g"), - (0x1D643, "M", "h"), - (0x1D644, "M", "i"), - (0x1D645, "M", "j"), - (0x1D646, "M", "k"), - (0x1D647, "M", "l"), - (0x1D648, "M", "m"), - (0x1D649, "M", "n"), - (0x1D64A, "M", "o"), - (0x1D64B, "M", "p"), - (0x1D64C, "M", "q"), - (0x1D64D, "M", "r"), - (0x1D64E, "M", "s"), - (0x1D64F, "M", "t"), - (0x1D650, "M", "u"), - (0x1D651, "M", "v"), - (0x1D652, "M", "w"), - (0x1D653, "M", "x"), - (0x1D654, "M", "y"), - (0x1D655, "M", "z"), - (0x1D656, "M", "a"), - (0x1D657, "M", "b"), - (0x1D658, "M", "c"), - (0x1D659, "M", "d"), - (0x1D65A, "M", "e"), - (0x1D65B, "M", "f"), - (0x1D65C, "M", "g"), - (0x1D65D, "M", "h"), - (0x1D65E, "M", "i"), - (0x1D65F, "M", "j"), - (0x1D660, "M", "k"), - (0x1D661, "M", "l"), - (0x1D662, "M", "m"), - (0x1D663, "M", "n"), - (0x1D664, "M", "o"), - (0x1D665, "M", "p"), - (0x1D666, "M", "q"), - (0x1D667, "M", "r"), - (0x1D668, "M", "s"), - (0x1D669, "M", "t"), - (0x1D66A, "M", "u"), - (0x1D66B, "M", "v"), - (0x1D66C, "M", "w"), - (0x1D66D, "M", "x"), - (0x1D66E, "M", "y"), - (0x1D66F, "M", "z"), - (0x1D670, "M", "a"), - (0x1D671, "M", "b"), - (0x1D672, "M", "c"), - (0x1D673, "M", "d"), - (0x1D674, "M", "e"), - (0x1D675, "M", "f"), - (0x1D676, "M", "g"), - (0x1D677, "M", "h"), - (0x1D678, "M", "i"), - (0x1D679, "M", "j"), - (0x1D67A, "M", "k"), - (0x1D67B, "M", "l"), - (0x1D67C, "M", "m"), - (0x1D67D, "M", "n"), - (0x1D67E, "M", "o"), - (0x1D67F, "M", "p"), - (0x1D680, "M", "q"), - (0x1D681, "M", "r"), - (0x1D682, "M", "s"), + (0x1D61B, 'M', 't'), + (0x1D61C, 'M', 'u'), + (0x1D61D, 'M', 'v'), + (0x1D61E, 'M', 'w'), + (0x1D61F, 'M', 'x'), + (0x1D620, 'M', 'y'), + (0x1D621, 'M', 'z'), + (0x1D622, 'M', 'a'), + (0x1D623, 'M', 'b'), + (0x1D624, 'M', 'c'), + (0x1D625, 'M', 'd'), + (0x1D626, 'M', 'e'), + (0x1D627, 'M', 'f'), + (0x1D628, 'M', 'g'), + (0x1D629, 'M', 'h'), + (0x1D62A, 'M', 'i'), + (0x1D62B, 'M', 'j'), + (0x1D62C, 'M', 'k'), + (0x1D62D, 'M', 'l'), + (0x1D62E, 'M', 'm'), + (0x1D62F, 'M', 'n'), + (0x1D630, 'M', 'o'), + (0x1D631, 'M', 'p'), + (0x1D632, 'M', 'q'), + (0x1D633, 'M', 'r'), + (0x1D634, 'M', 's'), + (0x1D635, 'M', 't'), + (0x1D636, 'M', 'u'), + (0x1D637, 'M', 'v'), + (0x1D638, 'M', 'w'), + (0x1D639, 'M', 'x'), + (0x1D63A, 'M', 'y'), + (0x1D63B, 'M', 'z'), + (0x1D63C, 'M', 'a'), + (0x1D63D, 'M', 'b'), + (0x1D63E, 'M', 'c'), + (0x1D63F, 'M', 'd'), + (0x1D640, 'M', 'e'), + (0x1D641, 'M', 'f'), + (0x1D642, 'M', 'g'), + (0x1D643, 'M', 'h'), + (0x1D644, 'M', 'i'), + (0x1D645, 'M', 'j'), + (0x1D646, 'M', 'k'), + (0x1D647, 'M', 'l'), + (0x1D648, 'M', 'm'), + (0x1D649, 'M', 'n'), + (0x1D64A, 'M', 'o'), + (0x1D64B, 'M', 'p'), + (0x1D64C, 'M', 'q'), + (0x1D64D, 'M', 'r'), + (0x1D64E, 'M', 's'), + (0x1D64F, 'M', 't'), + (0x1D650, 'M', 'u'), + (0x1D651, 'M', 'v'), + (0x1D652, 'M', 'w'), + (0x1D653, 'M', 'x'), + (0x1D654, 'M', 'y'), + (0x1D655, 'M', 'z'), + (0x1D656, 'M', 'a'), + (0x1D657, 'M', 'b'), + (0x1D658, 'M', 'c'), + (0x1D659, 'M', 'd'), + (0x1D65A, 'M', 'e'), + (0x1D65B, 'M', 'f'), + (0x1D65C, 'M', 'g'), + (0x1D65D, 'M', 'h'), + (0x1D65E, 'M', 'i'), + (0x1D65F, 'M', 'j'), + (0x1D660, 'M', 'k'), + (0x1D661, 'M', 'l'), + (0x1D662, 'M', 'm'), + (0x1D663, 'M', 'n'), + (0x1D664, 'M', 'o'), + (0x1D665, 'M', 'p'), + (0x1D666, 'M', 'q'), + (0x1D667, 'M', 'r'), + (0x1D668, 'M', 's'), + (0x1D669, 'M', 't'), + (0x1D66A, 'M', 'u'), + (0x1D66B, 'M', 'v'), + (0x1D66C, 'M', 'w'), + (0x1D66D, 'M', 'x'), + (0x1D66E, 'M', 'y'), + (0x1D66F, 'M', 'z'), + (0x1D670, 'M', 'a'), + (0x1D671, 'M', 'b'), + (0x1D672, 'M', 'c'), + (0x1D673, 'M', 'd'), + (0x1D674, 'M', 'e'), + (0x1D675, 'M', 'f'), + (0x1D676, 'M', 'g'), + (0x1D677, 'M', 'h'), + (0x1D678, 'M', 'i'), + (0x1D679, 'M', 'j'), + (0x1D67A, 'M', 'k'), + (0x1D67B, 'M', 'l'), + (0x1D67C, 'M', 'm'), + (0x1D67D, 'M', 'n'), + (0x1D67E, 'M', 'o'), ] - def _seg_67() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x1D683, "M", "t"), - (0x1D684, "M", "u"), - (0x1D685, "M", "v"), - (0x1D686, "M", "w"), - (0x1D687, "M", "x"), - (0x1D688, "M", "y"), - (0x1D689, "M", "z"), - (0x1D68A, "M", "a"), - (0x1D68B, "M", "b"), - (0x1D68C, "M", "c"), - (0x1D68D, "M", "d"), - (0x1D68E, "M", "e"), - (0x1D68F, "M", "f"), - (0x1D690, "M", "g"), - (0x1D691, "M", "h"), - (0x1D692, "M", "i"), - (0x1D693, "M", "j"), - (0x1D694, "M", "k"), - (0x1D695, "M", "l"), - (0x1D696, "M", "m"), - (0x1D697, "M", "n"), - (0x1D698, "M", "o"), - (0x1D699, "M", "p"), - (0x1D69A, "M", "q"), - (0x1D69B, "M", "r"), - (0x1D69C, "M", "s"), - (0x1D69D, "M", "t"), - (0x1D69E, "M", "u"), - (0x1D69F, "M", "v"), - (0x1D6A0, "M", "w"), - (0x1D6A1, "M", "x"), - (0x1D6A2, "M", "y"), - (0x1D6A3, "M", "z"), - (0x1D6A4, "M", "ı"), - (0x1D6A5, "M", "ȷ"), - (0x1D6A6, "X"), - (0x1D6A8, "M", "α"), - (0x1D6A9, "M", "β"), - (0x1D6AA, "M", "γ"), - (0x1D6AB, "M", "δ"), - (0x1D6AC, "M", "ε"), - (0x1D6AD, "M", "ζ"), - (0x1D6AE, "M", "η"), - (0x1D6AF, "M", "θ"), - (0x1D6B0, "M", "ι"), - (0x1D6B1, "M", "κ"), - (0x1D6B2, "M", "λ"), - (0x1D6B3, "M", "μ"), - (0x1D6B4, "M", "ν"), - (0x1D6B5, "M", "ξ"), - (0x1D6B6, "M", "ο"), - (0x1D6B7, "M", "π"), - (0x1D6B8, "M", "ρ"), - (0x1D6B9, "M", "θ"), - (0x1D6BA, "M", "σ"), - (0x1D6BB, "M", "τ"), - (0x1D6BC, "M", "υ"), - (0x1D6BD, "M", "φ"), - (0x1D6BE, "M", "χ"), - (0x1D6BF, "M", "ψ"), - (0x1D6C0, "M", "ω"), - (0x1D6C1, "M", "∇"), - (0x1D6C2, "M", "α"), - (0x1D6C3, "M", "β"), - (0x1D6C4, "M", "γ"), - (0x1D6C5, "M", "δ"), - (0x1D6C6, "M", "ε"), - (0x1D6C7, "M", "ζ"), - (0x1D6C8, "M", "η"), - (0x1D6C9, "M", "θ"), - (0x1D6CA, "M", "ι"), - (0x1D6CB, "M", "κ"), - (0x1D6CC, "M", "λ"), - (0x1D6CD, "M", "μ"), - (0x1D6CE, "M", "ν"), - (0x1D6CF, "M", "ξ"), - (0x1D6D0, "M", "ο"), - (0x1D6D1, "M", "π"), - (0x1D6D2, "M", "ρ"), - (0x1D6D3, "M", "σ"), - (0x1D6D5, "M", "τ"), - (0x1D6D6, "M", "υ"), - (0x1D6D7, "M", "φ"), - (0x1D6D8, "M", "χ"), - (0x1D6D9, "M", "ψ"), - (0x1D6DA, "M", "ω"), - (0x1D6DB, "M", "∂"), - (0x1D6DC, "M", "ε"), - (0x1D6DD, "M", "θ"), - (0x1D6DE, "M", "κ"), - (0x1D6DF, "M", "φ"), - (0x1D6E0, "M", "ρ"), - (0x1D6E1, "M", "π"), - (0x1D6E2, "M", "α"), - (0x1D6E3, "M", "β"), - (0x1D6E4, "M", "γ"), - (0x1D6E5, "M", "δ"), - (0x1D6E6, "M", "ε"), - (0x1D6E7, "M", "ζ"), - (0x1D6E8, "M", "η"), + (0x1D67F, 'M', 'p'), + (0x1D680, 'M', 'q'), + (0x1D681, 'M', 'r'), + (0x1D682, 'M', 's'), + (0x1D683, 'M', 't'), + (0x1D684, 'M', 'u'), + (0x1D685, 'M', 'v'), + (0x1D686, 'M', 'w'), + (0x1D687, 'M', 'x'), + (0x1D688, 'M', 'y'), + (0x1D689, 'M', 'z'), + (0x1D68A, 'M', 'a'), + (0x1D68B, 'M', 'b'), + (0x1D68C, 'M', 'c'), + (0x1D68D, 'M', 'd'), + (0x1D68E, 'M', 'e'), + (0x1D68F, 'M', 'f'), + (0x1D690, 'M', 'g'), + (0x1D691, 'M', 'h'), + (0x1D692, 'M', 'i'), + (0x1D693, 'M', 'j'), + (0x1D694, 'M', 'k'), + (0x1D695, 'M', 'l'), + (0x1D696, 'M', 'm'), + (0x1D697, 'M', 'n'), + (0x1D698, 'M', 'o'), + (0x1D699, 'M', 'p'), + (0x1D69A, 'M', 'q'), + (0x1D69B, 'M', 'r'), + (0x1D69C, 'M', 's'), + (0x1D69D, 'M', 't'), + (0x1D69E, 'M', 'u'), + (0x1D69F, 'M', 'v'), + (0x1D6A0, 'M', 'w'), + (0x1D6A1, 'M', 'x'), + (0x1D6A2, 'M', 'y'), + (0x1D6A3, 'M', 'z'), + (0x1D6A4, 'M', 'ı'), + (0x1D6A5, 'M', 'ȷ'), + (0x1D6A6, 'X'), + (0x1D6A8, 'M', 'α'), + (0x1D6A9, 'M', 'β'), + (0x1D6AA, 'M', 'γ'), + (0x1D6AB, 'M', 'δ'), + (0x1D6AC, 'M', 'ε'), + (0x1D6AD, 'M', 'ζ'), + (0x1D6AE, 'M', 'η'), + (0x1D6AF, 'M', 'θ'), + (0x1D6B0, 'M', 'ι'), + (0x1D6B1, 'M', 'κ'), + (0x1D6B2, 'M', 'λ'), + (0x1D6B3, 'M', 'μ'), + (0x1D6B4, 'M', 'ν'), + (0x1D6B5, 'M', 'ξ'), + (0x1D6B6, 'M', 'ο'), + (0x1D6B7, 'M', 'π'), + (0x1D6B8, 'M', 'ρ'), + (0x1D6B9, 'M', 'θ'), + (0x1D6BA, 'M', 'σ'), + (0x1D6BB, 'M', 'τ'), + (0x1D6BC, 'M', 'υ'), + (0x1D6BD, 'M', 'φ'), + (0x1D6BE, 'M', 'χ'), + (0x1D6BF, 'M', 'ψ'), + (0x1D6C0, 'M', 'ω'), + (0x1D6C1, 'M', '∇'), + (0x1D6C2, 'M', 'α'), + (0x1D6C3, 'M', 'β'), + (0x1D6C4, 'M', 'γ'), + (0x1D6C5, 'M', 'δ'), + (0x1D6C6, 'M', 'ε'), + (0x1D6C7, 'M', 'ζ'), + (0x1D6C8, 'M', 'η'), + (0x1D6C9, 'M', 'θ'), + (0x1D6CA, 'M', 'ι'), + (0x1D6CB, 'M', 'κ'), + (0x1D6CC, 'M', 'λ'), + (0x1D6CD, 'M', 'μ'), + (0x1D6CE, 'M', 'ν'), + (0x1D6CF, 'M', 'ξ'), + (0x1D6D0, 'M', 'ο'), + (0x1D6D1, 'M', 'π'), + (0x1D6D2, 'M', 'ρ'), + (0x1D6D3, 'M', 'σ'), + (0x1D6D5, 'M', 'τ'), + (0x1D6D6, 'M', 'υ'), + (0x1D6D7, 'M', 'φ'), + (0x1D6D8, 'M', 'χ'), + (0x1D6D9, 'M', 'ψ'), + (0x1D6DA, 'M', 'ω'), + (0x1D6DB, 'M', '∂'), + (0x1D6DC, 'M', 'ε'), + (0x1D6DD, 'M', 'θ'), + (0x1D6DE, 'M', 'κ'), + (0x1D6DF, 'M', 'φ'), + (0x1D6E0, 'M', 'ρ'), + (0x1D6E1, 'M', 'π'), + (0x1D6E2, 'M', 'α'), + (0x1D6E3, 'M', 'β'), + (0x1D6E4, 'M', 'γ'), ] - def _seg_68() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x1D6E9, "M", "θ"), - (0x1D6EA, "M", "ι"), - (0x1D6EB, "M", "κ"), - (0x1D6EC, "M", "λ"), - (0x1D6ED, "M", "μ"), - (0x1D6EE, "M", "ν"), - (0x1D6EF, "M", "ξ"), - (0x1D6F0, "M", "ο"), - (0x1D6F1, "M", "π"), - (0x1D6F2, "M", "ρ"), - (0x1D6F3, "M", "θ"), - (0x1D6F4, "M", "σ"), - (0x1D6F5, "M", "τ"), - (0x1D6F6, "M", "υ"), - (0x1D6F7, "M", "φ"), - (0x1D6F8, "M", "χ"), - (0x1D6F9, "M", "ψ"), - (0x1D6FA, "M", "ω"), - (0x1D6FB, "M", "∇"), - (0x1D6FC, "M", "α"), - (0x1D6FD, "M", "β"), - (0x1D6FE, "M", "γ"), - (0x1D6FF, "M", "δ"), - (0x1D700, "M", "ε"), - (0x1D701, "M", "ζ"), - (0x1D702, "M", "η"), - (0x1D703, "M", "θ"), - (0x1D704, "M", "ι"), - (0x1D705, "M", "κ"), - (0x1D706, "M", "λ"), - (0x1D707, "M", "μ"), - (0x1D708, "M", "ν"), - (0x1D709, "M", "ξ"), - (0x1D70A, "M", "ο"), - (0x1D70B, "M", "π"), - (0x1D70C, "M", "ρ"), - (0x1D70D, "M", "σ"), - (0x1D70F, "M", "τ"), - (0x1D710, "M", "υ"), - (0x1D711, "M", "φ"), - (0x1D712, "M", "χ"), - (0x1D713, "M", "ψ"), - (0x1D714, "M", "ω"), - (0x1D715, "M", "∂"), - (0x1D716, "M", "ε"), - (0x1D717, "M", "θ"), - (0x1D718, "M", "κ"), - (0x1D719, "M", "φ"), - (0x1D71A, "M", "ρ"), - (0x1D71B, "M", "π"), - (0x1D71C, "M", "α"), - (0x1D71D, "M", "β"), - (0x1D71E, "M", "γ"), - (0x1D71F, "M", "δ"), - (0x1D720, "M", "ε"), - (0x1D721, "M", "ζ"), - (0x1D722, "M", "η"), - (0x1D723, "M", "θ"), - (0x1D724, "M", "ι"), - (0x1D725, "M", "κ"), - (0x1D726, "M", "λ"), - (0x1D727, "M", "μ"), - (0x1D728, "M", "ν"), - (0x1D729, "M", "ξ"), - (0x1D72A, "M", "ο"), - (0x1D72B, "M", "π"), - (0x1D72C, "M", "ρ"), - (0x1D72D, "M", "θ"), - (0x1D72E, "M", "σ"), - (0x1D72F, "M", "τ"), - (0x1D730, "M", "υ"), - (0x1D731, "M", "φ"), - (0x1D732, "M", "χ"), - (0x1D733, "M", "ψ"), - (0x1D734, "M", "ω"), - (0x1D735, "M", "∇"), - (0x1D736, "M", "α"), - (0x1D737, "M", "β"), - (0x1D738, "M", "γ"), - (0x1D739, "M", "δ"), - (0x1D73A, "M", "ε"), - (0x1D73B, "M", "ζ"), - (0x1D73C, "M", "η"), - (0x1D73D, "M", "θ"), - (0x1D73E, "M", "ι"), - (0x1D73F, "M", "κ"), - (0x1D740, "M", "λ"), - (0x1D741, "M", "μ"), - (0x1D742, "M", "ν"), - (0x1D743, "M", "ξ"), - (0x1D744, "M", "ο"), - (0x1D745, "M", "π"), - (0x1D746, "M", "ρ"), - (0x1D747, "M", "σ"), - (0x1D749, "M", "τ"), - (0x1D74A, "M", "υ"), - (0x1D74B, "M", "φ"), - (0x1D74C, "M", "χ"), - (0x1D74D, "M", "ψ"), - (0x1D74E, "M", "ω"), + (0x1D6E5, 'M', 'δ'), + (0x1D6E6, 'M', 'ε'), + (0x1D6E7, 'M', 'ζ'), + (0x1D6E8, 'M', 'η'), + (0x1D6E9, 'M', 'θ'), + (0x1D6EA, 'M', 'ι'), + (0x1D6EB, 'M', 'κ'), + (0x1D6EC, 'M', 'λ'), + (0x1D6ED, 'M', 'μ'), + (0x1D6EE, 'M', 'ν'), + (0x1D6EF, 'M', 'ξ'), + (0x1D6F0, 'M', 'ο'), + (0x1D6F1, 'M', 'π'), + (0x1D6F2, 'M', 'ρ'), + (0x1D6F3, 'M', 'θ'), + (0x1D6F4, 'M', 'σ'), + (0x1D6F5, 'M', 'τ'), + (0x1D6F6, 'M', 'υ'), + (0x1D6F7, 'M', 'φ'), + (0x1D6F8, 'M', 'χ'), + (0x1D6F9, 'M', 'ψ'), + (0x1D6FA, 'M', 'ω'), + (0x1D6FB, 'M', '∇'), + (0x1D6FC, 'M', 'α'), + (0x1D6FD, 'M', 'β'), + (0x1D6FE, 'M', 'γ'), + (0x1D6FF, 'M', 'δ'), + (0x1D700, 'M', 'ε'), + (0x1D701, 'M', 'ζ'), + (0x1D702, 'M', 'η'), + (0x1D703, 'M', 'θ'), + (0x1D704, 'M', 'ι'), + (0x1D705, 'M', 'κ'), + (0x1D706, 'M', 'λ'), + (0x1D707, 'M', 'μ'), + (0x1D708, 'M', 'ν'), + (0x1D709, 'M', 'ξ'), + (0x1D70A, 'M', 'ο'), + (0x1D70B, 'M', 'π'), + (0x1D70C, 'M', 'ρ'), + (0x1D70D, 'M', 'σ'), + (0x1D70F, 'M', 'τ'), + (0x1D710, 'M', 'υ'), + (0x1D711, 'M', 'φ'), + (0x1D712, 'M', 'χ'), + (0x1D713, 'M', 'ψ'), + (0x1D714, 'M', 'ω'), + (0x1D715, 'M', '∂'), + (0x1D716, 'M', 'ε'), + (0x1D717, 'M', 'θ'), + (0x1D718, 'M', 'κ'), + (0x1D719, 'M', 'φ'), + (0x1D71A, 'M', 'ρ'), + (0x1D71B, 'M', 'π'), + (0x1D71C, 'M', 'α'), + (0x1D71D, 'M', 'β'), + (0x1D71E, 'M', 'γ'), + (0x1D71F, 'M', 'δ'), + (0x1D720, 'M', 'ε'), + (0x1D721, 'M', 'ζ'), + (0x1D722, 'M', 'η'), + (0x1D723, 'M', 'θ'), + (0x1D724, 'M', 'ι'), + (0x1D725, 'M', 'κ'), + (0x1D726, 'M', 'λ'), + (0x1D727, 'M', 'μ'), + (0x1D728, 'M', 'ν'), + (0x1D729, 'M', 'ξ'), + (0x1D72A, 'M', 'ο'), + (0x1D72B, 'M', 'π'), + (0x1D72C, 'M', 'ρ'), + (0x1D72D, 'M', 'θ'), + (0x1D72E, 'M', 'σ'), + (0x1D72F, 'M', 'τ'), + (0x1D730, 'M', 'υ'), + (0x1D731, 'M', 'φ'), + (0x1D732, 'M', 'χ'), + (0x1D733, 'M', 'ψ'), + (0x1D734, 'M', 'ω'), + (0x1D735, 'M', '∇'), + (0x1D736, 'M', 'α'), + (0x1D737, 'M', 'β'), + (0x1D738, 'M', 'γ'), + (0x1D739, 'M', 'δ'), + (0x1D73A, 'M', 'ε'), + (0x1D73B, 'M', 'ζ'), + (0x1D73C, 'M', 'η'), + (0x1D73D, 'M', 'θ'), + (0x1D73E, 'M', 'ι'), + (0x1D73F, 'M', 'κ'), + (0x1D740, 'M', 'λ'), + (0x1D741, 'M', 'μ'), + (0x1D742, 'M', 'ν'), + (0x1D743, 'M', 'ξ'), + (0x1D744, 'M', 'ο'), + (0x1D745, 'M', 'π'), + (0x1D746, 'M', 'ρ'), + (0x1D747, 'M', 'σ'), + (0x1D749, 'M', 'τ'), + (0x1D74A, 'M', 'υ'), ] - def _seg_69() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x1D74F, "M", "∂"), - (0x1D750, "M", "ε"), - (0x1D751, "M", "θ"), - (0x1D752, "M", "κ"), - (0x1D753, "M", "φ"), - (0x1D754, "M", "ρ"), - (0x1D755, "M", "π"), - (0x1D756, "M", "α"), - (0x1D757, "M", "β"), - (0x1D758, "M", "γ"), - (0x1D759, "M", "δ"), - (0x1D75A, "M", "ε"), - (0x1D75B, "M", "ζ"), - (0x1D75C, "M", "η"), - (0x1D75D, "M", "θ"), - (0x1D75E, "M", "ι"), - (0x1D75F, "M", "κ"), - (0x1D760, "M", "λ"), - (0x1D761, "M", "μ"), - (0x1D762, "M", "ν"), - (0x1D763, "M", "ξ"), - (0x1D764, "M", "ο"), - (0x1D765, "M", "π"), - (0x1D766, "M", "ρ"), - (0x1D767, "M", "θ"), - (0x1D768, "M", "σ"), - (0x1D769, "M", "τ"), - (0x1D76A, "M", "υ"), - (0x1D76B, "M", "φ"), - (0x1D76C, "M", "χ"), - (0x1D76D, "M", "ψ"), - (0x1D76E, "M", "ω"), - (0x1D76F, "M", "∇"), - (0x1D770, "M", "α"), - (0x1D771, "M", "β"), - (0x1D772, "M", "γ"), - (0x1D773, "M", "δ"), - (0x1D774, "M", "ε"), - (0x1D775, "M", "ζ"), - (0x1D776, "M", "η"), - (0x1D777, "M", "θ"), - (0x1D778, "M", "ι"), - (0x1D779, "M", "κ"), - (0x1D77A, "M", "λ"), - (0x1D77B, "M", "μ"), - (0x1D77C, "M", "ν"), - (0x1D77D, "M", "ξ"), - (0x1D77E, "M", "ο"), - (0x1D77F, "M", "π"), - (0x1D780, "M", "ρ"), - (0x1D781, "M", "σ"), - (0x1D783, "M", "τ"), - (0x1D784, "M", "υ"), - (0x1D785, "M", "φ"), - (0x1D786, "M", "χ"), - (0x1D787, "M", "ψ"), - (0x1D788, "M", "ω"), - (0x1D789, "M", "∂"), - (0x1D78A, "M", "ε"), - (0x1D78B, "M", "θ"), - (0x1D78C, "M", "κ"), - (0x1D78D, "M", "φ"), - (0x1D78E, "M", "ρ"), - (0x1D78F, "M", "π"), - (0x1D790, "M", "α"), - (0x1D791, "M", "β"), - (0x1D792, "M", "γ"), - (0x1D793, "M", "δ"), - (0x1D794, "M", "ε"), - (0x1D795, "M", "ζ"), - (0x1D796, "M", "η"), - (0x1D797, "M", "θ"), - (0x1D798, "M", "ι"), - (0x1D799, "M", "κ"), - (0x1D79A, "M", "λ"), - (0x1D79B, "M", "μ"), - (0x1D79C, "M", "ν"), - (0x1D79D, "M", "ξ"), - (0x1D79E, "M", "ο"), - (0x1D79F, "M", "π"), - (0x1D7A0, "M", "ρ"), - (0x1D7A1, "M", "θ"), - (0x1D7A2, "M", "σ"), - (0x1D7A3, "M", "τ"), - (0x1D7A4, "M", "υ"), - (0x1D7A5, "M", "φ"), - (0x1D7A6, "M", "χ"), - (0x1D7A7, "M", "ψ"), - (0x1D7A8, "M", "ω"), - (0x1D7A9, "M", "∇"), - (0x1D7AA, "M", "α"), - (0x1D7AB, "M", "β"), - (0x1D7AC, "M", "γ"), - (0x1D7AD, "M", "δ"), - (0x1D7AE, "M", "ε"), - (0x1D7AF, "M", "ζ"), - (0x1D7B0, "M", "η"), - (0x1D7B1, "M", "θ"), - (0x1D7B2, "M", "ι"), - (0x1D7B3, "M", "κ"), + (0x1D74B, 'M', 'φ'), + (0x1D74C, 'M', 'χ'), + (0x1D74D, 'M', 'ψ'), + (0x1D74E, 'M', 'ω'), + (0x1D74F, 'M', '∂'), + (0x1D750, 'M', 'ε'), + (0x1D751, 'M', 'θ'), + (0x1D752, 'M', 'κ'), + (0x1D753, 'M', 'φ'), + (0x1D754, 'M', 'ρ'), + (0x1D755, 'M', 'π'), + (0x1D756, 'M', 'α'), + (0x1D757, 'M', 'β'), + (0x1D758, 'M', 'γ'), + (0x1D759, 'M', 'δ'), + (0x1D75A, 'M', 'ε'), + (0x1D75B, 'M', 'ζ'), + (0x1D75C, 'M', 'η'), + (0x1D75D, 'M', 'θ'), + (0x1D75E, 'M', 'ι'), + (0x1D75F, 'M', 'κ'), + (0x1D760, 'M', 'λ'), + (0x1D761, 'M', 'μ'), + (0x1D762, 'M', 'ν'), + (0x1D763, 'M', 'ξ'), + (0x1D764, 'M', 'ο'), + (0x1D765, 'M', 'π'), + (0x1D766, 'M', 'ρ'), + (0x1D767, 'M', 'θ'), + (0x1D768, 'M', 'σ'), + (0x1D769, 'M', 'τ'), + (0x1D76A, 'M', 'υ'), + (0x1D76B, 'M', 'φ'), + (0x1D76C, 'M', 'χ'), + (0x1D76D, 'M', 'ψ'), + (0x1D76E, 'M', 'ω'), + (0x1D76F, 'M', '∇'), + (0x1D770, 'M', 'α'), + (0x1D771, 'M', 'β'), + (0x1D772, 'M', 'γ'), + (0x1D773, 'M', 'δ'), + (0x1D774, 'M', 'ε'), + (0x1D775, 'M', 'ζ'), + (0x1D776, 'M', 'η'), + (0x1D777, 'M', 'θ'), + (0x1D778, 'M', 'ι'), + (0x1D779, 'M', 'κ'), + (0x1D77A, 'M', 'λ'), + (0x1D77B, 'M', 'μ'), + (0x1D77C, 'M', 'ν'), + (0x1D77D, 'M', 'ξ'), + (0x1D77E, 'M', 'ο'), + (0x1D77F, 'M', 'π'), + (0x1D780, 'M', 'ρ'), + (0x1D781, 'M', 'σ'), + (0x1D783, 'M', 'τ'), + (0x1D784, 'M', 'υ'), + (0x1D785, 'M', 'φ'), + (0x1D786, 'M', 'χ'), + (0x1D787, 'M', 'ψ'), + (0x1D788, 'M', 'ω'), + (0x1D789, 'M', '∂'), + (0x1D78A, 'M', 'ε'), + (0x1D78B, 'M', 'θ'), + (0x1D78C, 'M', 'κ'), + (0x1D78D, 'M', 'φ'), + (0x1D78E, 'M', 'ρ'), + (0x1D78F, 'M', 'π'), + (0x1D790, 'M', 'α'), + (0x1D791, 'M', 'β'), + (0x1D792, 'M', 'γ'), + (0x1D793, 'M', 'δ'), + (0x1D794, 'M', 'ε'), + (0x1D795, 'M', 'ζ'), + (0x1D796, 'M', 'η'), + (0x1D797, 'M', 'θ'), + (0x1D798, 'M', 'ι'), + (0x1D799, 'M', 'κ'), + (0x1D79A, 'M', 'λ'), + (0x1D79B, 'M', 'μ'), + (0x1D79C, 'M', 'ν'), + (0x1D79D, 'M', 'ξ'), + (0x1D79E, 'M', 'ο'), + (0x1D79F, 'M', 'π'), + (0x1D7A0, 'M', 'ρ'), + (0x1D7A1, 'M', 'θ'), + (0x1D7A2, 'M', 'σ'), + (0x1D7A3, 'M', 'τ'), + (0x1D7A4, 'M', 'υ'), + (0x1D7A5, 'M', 'φ'), + (0x1D7A6, 'M', 'χ'), + (0x1D7A7, 'M', 'ψ'), + (0x1D7A8, 'M', 'ω'), + (0x1D7A9, 'M', '∇'), + (0x1D7AA, 'M', 'α'), + (0x1D7AB, 'M', 'β'), + (0x1D7AC, 'M', 'γ'), + (0x1D7AD, 'M', 'δ'), + (0x1D7AE, 'M', 'ε'), + (0x1D7AF, 'M', 'ζ'), ] - def _seg_70() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x1D7B4, "M", "λ"), - (0x1D7B5, "M", "μ"), - (0x1D7B6, "M", "ν"), - (0x1D7B7, "M", "ξ"), - (0x1D7B8, "M", "ο"), - (0x1D7B9, "M", "π"), - (0x1D7BA, "M", "ρ"), - (0x1D7BB, "M", "σ"), - (0x1D7BD, "M", "τ"), - (0x1D7BE, "M", "υ"), - (0x1D7BF, "M", "φ"), - (0x1D7C0, "M", "χ"), - (0x1D7C1, "M", "ψ"), - (0x1D7C2, "M", "ω"), - (0x1D7C3, "M", "∂"), - (0x1D7C4, "M", "ε"), - (0x1D7C5, "M", "θ"), - (0x1D7C6, "M", "κ"), - (0x1D7C7, "M", "φ"), - (0x1D7C8, "M", "ρ"), - (0x1D7C9, "M", "π"), - (0x1D7CA, "M", "ϝ"), - (0x1D7CC, "X"), - (0x1D7CE, "M", "0"), - (0x1D7CF, "M", "1"), - (0x1D7D0, "M", "2"), - (0x1D7D1, "M", "3"), - (0x1D7D2, "M", "4"), - (0x1D7D3, "M", "5"), - (0x1D7D4, "M", "6"), - (0x1D7D5, "M", "7"), - (0x1D7D6, "M", "8"), - (0x1D7D7, "M", "9"), - (0x1D7D8, "M", "0"), - (0x1D7D9, "M", "1"), - (0x1D7DA, "M", "2"), - (0x1D7DB, "M", "3"), - (0x1D7DC, "M", "4"), - (0x1D7DD, "M", "5"), - (0x1D7DE, "M", "6"), - (0x1D7DF, "M", "7"), - (0x1D7E0, "M", "8"), - (0x1D7E1, "M", "9"), - (0x1D7E2, "M", "0"), - (0x1D7E3, "M", "1"), - (0x1D7E4, "M", "2"), - (0x1D7E5, "M", "3"), - (0x1D7E6, "M", "4"), - (0x1D7E7, "M", "5"), - (0x1D7E8, "M", "6"), - (0x1D7E9, "M", "7"), - (0x1D7EA, "M", "8"), - (0x1D7EB, "M", "9"), - (0x1D7EC, "M", "0"), - (0x1D7ED, "M", "1"), - (0x1D7EE, "M", "2"), - (0x1D7EF, "M", "3"), - (0x1D7F0, "M", "4"), - (0x1D7F1, "M", "5"), - (0x1D7F2, "M", "6"), - (0x1D7F3, "M", "7"), - (0x1D7F4, "M", "8"), - (0x1D7F5, "M", "9"), - (0x1D7F6, "M", "0"), - (0x1D7F7, "M", "1"), - (0x1D7F8, "M", "2"), - (0x1D7F9, "M", "3"), - (0x1D7FA, "M", "4"), - (0x1D7FB, "M", "5"), - (0x1D7FC, "M", "6"), - (0x1D7FD, "M", "7"), - (0x1D7FE, "M", "8"), - (0x1D7FF, "M", "9"), - (0x1D800, "V"), - (0x1DA8C, "X"), - (0x1DA9B, "V"), - (0x1DAA0, "X"), - (0x1DAA1, "V"), - (0x1DAB0, "X"), - (0x1DF00, "V"), - (0x1DF1F, "X"), - (0x1DF25, "V"), - (0x1DF2B, "X"), - (0x1E000, "V"), - (0x1E007, "X"), - (0x1E008, "V"), - (0x1E019, "X"), - (0x1E01B, "V"), - (0x1E022, "X"), - (0x1E023, "V"), - (0x1E025, "X"), - (0x1E026, "V"), - (0x1E02B, "X"), - (0x1E030, "M", "а"), - (0x1E031, "M", "б"), - (0x1E032, "M", "в"), - (0x1E033, "M", "г"), - (0x1E034, "M", "д"), - (0x1E035, "M", "е"), - (0x1E036, "M", "ж"), + (0x1D7B0, 'M', 'η'), + (0x1D7B1, 'M', 'θ'), + (0x1D7B2, 'M', 'ι'), + (0x1D7B3, 'M', 'κ'), + (0x1D7B4, 'M', 'λ'), + (0x1D7B5, 'M', 'μ'), + (0x1D7B6, 'M', 'ν'), + (0x1D7B7, 'M', 'ξ'), + (0x1D7B8, 'M', 'ο'), + (0x1D7B9, 'M', 'π'), + (0x1D7BA, 'M', 'ρ'), + (0x1D7BB, 'M', 'σ'), + (0x1D7BD, 'M', 'τ'), + (0x1D7BE, 'M', 'υ'), + (0x1D7BF, 'M', 'φ'), + (0x1D7C0, 'M', 'χ'), + (0x1D7C1, 'M', 'ψ'), + (0x1D7C2, 'M', 'ω'), + (0x1D7C3, 'M', '∂'), + (0x1D7C4, 'M', 'ε'), + (0x1D7C5, 'M', 'θ'), + (0x1D7C6, 'M', 'κ'), + (0x1D7C7, 'M', 'φ'), + (0x1D7C8, 'M', 'ρ'), + (0x1D7C9, 'M', 'π'), + (0x1D7CA, 'M', 'ϝ'), + (0x1D7CC, 'X'), + (0x1D7CE, 'M', '0'), + (0x1D7CF, 'M', '1'), + (0x1D7D0, 'M', '2'), + (0x1D7D1, 'M', '3'), + (0x1D7D2, 'M', '4'), + (0x1D7D3, 'M', '5'), + (0x1D7D4, 'M', '6'), + (0x1D7D5, 'M', '7'), + (0x1D7D6, 'M', '8'), + (0x1D7D7, 'M', '9'), + (0x1D7D8, 'M', '0'), + (0x1D7D9, 'M', '1'), + (0x1D7DA, 'M', '2'), + (0x1D7DB, 'M', '3'), + (0x1D7DC, 'M', '4'), + (0x1D7DD, 'M', '5'), + (0x1D7DE, 'M', '6'), + (0x1D7DF, 'M', '7'), + (0x1D7E0, 'M', '8'), + (0x1D7E1, 'M', '9'), + (0x1D7E2, 'M', '0'), + (0x1D7E3, 'M', '1'), + (0x1D7E4, 'M', '2'), + (0x1D7E5, 'M', '3'), + (0x1D7E6, 'M', '4'), + (0x1D7E7, 'M', '5'), + (0x1D7E8, 'M', '6'), + (0x1D7E9, 'M', '7'), + (0x1D7EA, 'M', '8'), + (0x1D7EB, 'M', '9'), + (0x1D7EC, 'M', '0'), + (0x1D7ED, 'M', '1'), + (0x1D7EE, 'M', '2'), + (0x1D7EF, 'M', '3'), + (0x1D7F0, 'M', '4'), + (0x1D7F1, 'M', '5'), + (0x1D7F2, 'M', '6'), + (0x1D7F3, 'M', '7'), + (0x1D7F4, 'M', '8'), + (0x1D7F5, 'M', '9'), + (0x1D7F6, 'M', '0'), + (0x1D7F7, 'M', '1'), + (0x1D7F8, 'M', '2'), + (0x1D7F9, 'M', '3'), + (0x1D7FA, 'M', '4'), + (0x1D7FB, 'M', '5'), + (0x1D7FC, 'M', '6'), + (0x1D7FD, 'M', '7'), + (0x1D7FE, 'M', '8'), + (0x1D7FF, 'M', '9'), + (0x1D800, 'V'), + (0x1DA8C, 'X'), + (0x1DA9B, 'V'), + (0x1DAA0, 'X'), + (0x1DAA1, 'V'), + (0x1DAB0, 'X'), + (0x1DF00, 'V'), + (0x1DF1F, 'X'), + (0x1DF25, 'V'), + (0x1DF2B, 'X'), + (0x1E000, 'V'), + (0x1E007, 'X'), + (0x1E008, 'V'), + (0x1E019, 'X'), + (0x1E01B, 'V'), + (0x1E022, 'X'), + (0x1E023, 'V'), + (0x1E025, 'X'), + (0x1E026, 'V'), + (0x1E02B, 'X'), + (0x1E030, 'M', 'а'), + (0x1E031, 'M', 'б'), + (0x1E032, 'M', 'в'), ] - def _seg_71() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x1E037, "M", "з"), - (0x1E038, "M", "и"), - (0x1E039, "M", "к"), - (0x1E03A, "M", "л"), - (0x1E03B, "M", "м"), - (0x1E03C, "M", "о"), - (0x1E03D, "M", "п"), - (0x1E03E, "M", "р"), - (0x1E03F, "M", "с"), - (0x1E040, "M", "т"), - (0x1E041, "M", "у"), - (0x1E042, "M", "ф"), - (0x1E043, "M", "х"), - (0x1E044, "M", "ц"), - (0x1E045, "M", "ч"), - (0x1E046, "M", "ш"), - (0x1E047, "M", "ы"), - (0x1E048, "M", "э"), - (0x1E049, "M", "ю"), - (0x1E04A, "M", "ꚉ"), - (0x1E04B, "M", "ә"), - (0x1E04C, "M", "і"), - (0x1E04D, "M", "ј"), - (0x1E04E, "M", "ө"), - (0x1E04F, "M", "ү"), - (0x1E050, "M", "ӏ"), - (0x1E051, "M", "а"), - (0x1E052, "M", "б"), - (0x1E053, "M", "в"), - (0x1E054, "M", "г"), - (0x1E055, "M", "д"), - (0x1E056, "M", "е"), - (0x1E057, "M", "ж"), - (0x1E058, "M", "з"), - (0x1E059, "M", "и"), - (0x1E05A, "M", "к"), - (0x1E05B, "M", "л"), - (0x1E05C, "M", "о"), - (0x1E05D, "M", "п"), - (0x1E05E, "M", "с"), - (0x1E05F, "M", "у"), - (0x1E060, "M", "ф"), - (0x1E061, "M", "х"), - (0x1E062, "M", "ц"), - (0x1E063, "M", "ч"), - (0x1E064, "M", "ш"), - (0x1E065, "M", "ъ"), - (0x1E066, "M", "ы"), - (0x1E067, "M", "ґ"), - (0x1E068, "M", "і"), - (0x1E069, "M", "ѕ"), - (0x1E06A, "M", "џ"), - (0x1E06B, "M", "ҫ"), - (0x1E06C, "M", "ꙑ"), - (0x1E06D, "M", "ұ"), - (0x1E06E, "X"), - (0x1E08F, "V"), - (0x1E090, "X"), - (0x1E100, "V"), - (0x1E12D, "X"), - (0x1E130, "V"), - (0x1E13E, "X"), - (0x1E140, "V"), - (0x1E14A, "X"), - (0x1E14E, "V"), - (0x1E150, "X"), - (0x1E290, "V"), - (0x1E2AF, "X"), - (0x1E2C0, "V"), - (0x1E2FA, "X"), - (0x1E2FF, "V"), - (0x1E300, "X"), - (0x1E4D0, "V"), - (0x1E4FA, "X"), - (0x1E7E0, "V"), - (0x1E7E7, "X"), - (0x1E7E8, "V"), - (0x1E7EC, "X"), - (0x1E7ED, "V"), - (0x1E7EF, "X"), - (0x1E7F0, "V"), - (0x1E7FF, "X"), - (0x1E800, "V"), - (0x1E8C5, "X"), - (0x1E8C7, "V"), - (0x1E8D7, "X"), - (0x1E900, "M", "𞤢"), - (0x1E901, "M", "𞤣"), - (0x1E902, "M", "𞤤"), - (0x1E903, "M", "𞤥"), - (0x1E904, "M", "𞤦"), - (0x1E905, "M", "𞤧"), - (0x1E906, "M", "𞤨"), - (0x1E907, "M", "𞤩"), - (0x1E908, "M", "𞤪"), - (0x1E909, "M", "𞤫"), - (0x1E90A, "M", "𞤬"), - (0x1E90B, "M", "𞤭"), - (0x1E90C, "M", "𞤮"), - (0x1E90D, "M", "𞤯"), + (0x1E033, 'M', 'г'), + (0x1E034, 'M', 'д'), + (0x1E035, 'M', 'е'), + (0x1E036, 'M', 'ж'), + (0x1E037, 'M', 'з'), + (0x1E038, 'M', 'и'), + (0x1E039, 'M', 'к'), + (0x1E03A, 'M', 'л'), + (0x1E03B, 'M', 'м'), + (0x1E03C, 'M', 'о'), + (0x1E03D, 'M', 'п'), + (0x1E03E, 'M', 'р'), + (0x1E03F, 'M', 'с'), + (0x1E040, 'M', 'т'), + (0x1E041, 'M', 'у'), + (0x1E042, 'M', 'ф'), + (0x1E043, 'M', 'х'), + (0x1E044, 'M', 'ц'), + (0x1E045, 'M', 'ч'), + (0x1E046, 'M', 'ш'), + (0x1E047, 'M', 'ы'), + (0x1E048, 'M', 'э'), + (0x1E049, 'M', 'ю'), + (0x1E04A, 'M', 'ꚉ'), + (0x1E04B, 'M', 'ә'), + (0x1E04C, 'M', 'і'), + (0x1E04D, 'M', 'ј'), + (0x1E04E, 'M', 'ө'), + (0x1E04F, 'M', 'ү'), + (0x1E050, 'M', 'ӏ'), + (0x1E051, 'M', 'а'), + (0x1E052, 'M', 'б'), + (0x1E053, 'M', 'в'), + (0x1E054, 'M', 'г'), + (0x1E055, 'M', 'д'), + (0x1E056, 'M', 'е'), + (0x1E057, 'M', 'ж'), + (0x1E058, 'M', 'з'), + (0x1E059, 'M', 'и'), + (0x1E05A, 'M', 'к'), + (0x1E05B, 'M', 'л'), + (0x1E05C, 'M', 'о'), + (0x1E05D, 'M', 'п'), + (0x1E05E, 'M', 'с'), + (0x1E05F, 'M', 'у'), + (0x1E060, 'M', 'ф'), + (0x1E061, 'M', 'х'), + (0x1E062, 'M', 'ц'), + (0x1E063, 'M', 'ч'), + (0x1E064, 'M', 'ш'), + (0x1E065, 'M', 'ъ'), + (0x1E066, 'M', 'ы'), + (0x1E067, 'M', 'ґ'), + (0x1E068, 'M', 'і'), + (0x1E069, 'M', 'ѕ'), + (0x1E06A, 'M', 'џ'), + (0x1E06B, 'M', 'ҫ'), + (0x1E06C, 'M', 'ꙑ'), + (0x1E06D, 'M', 'ұ'), + (0x1E06E, 'X'), + (0x1E08F, 'V'), + (0x1E090, 'X'), + (0x1E100, 'V'), + (0x1E12D, 'X'), + (0x1E130, 'V'), + (0x1E13E, 'X'), + (0x1E140, 'V'), + (0x1E14A, 'X'), + (0x1E14E, 'V'), + (0x1E150, 'X'), + (0x1E290, 'V'), + (0x1E2AF, 'X'), + (0x1E2C0, 'V'), + (0x1E2FA, 'X'), + (0x1E2FF, 'V'), + (0x1E300, 'X'), + (0x1E4D0, 'V'), + (0x1E4FA, 'X'), + (0x1E7E0, 'V'), + (0x1E7E7, 'X'), + (0x1E7E8, 'V'), + (0x1E7EC, 'X'), + (0x1E7ED, 'V'), + (0x1E7EF, 'X'), + (0x1E7F0, 'V'), + (0x1E7FF, 'X'), + (0x1E800, 'V'), + (0x1E8C5, 'X'), + (0x1E8C7, 'V'), + (0x1E8D7, 'X'), + (0x1E900, 'M', '𞤢'), + (0x1E901, 'M', '𞤣'), + (0x1E902, 'M', '𞤤'), + (0x1E903, 'M', '𞤥'), + (0x1E904, 'M', '𞤦'), + (0x1E905, 'M', '𞤧'), + (0x1E906, 'M', '𞤨'), + (0x1E907, 'M', '𞤩'), + (0x1E908, 'M', '𞤪'), + (0x1E909, 'M', '𞤫'), ] - def _seg_72() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x1E90E, "M", "𞤰"), - (0x1E90F, "M", "𞤱"), - (0x1E910, "M", "𞤲"), - (0x1E911, "M", "𞤳"), - (0x1E912, "M", "𞤴"), - (0x1E913, "M", "𞤵"), - (0x1E914, "M", "𞤶"), - (0x1E915, "M", "𞤷"), - (0x1E916, "M", "𞤸"), - (0x1E917, "M", "𞤹"), - (0x1E918, "M", "𞤺"), - (0x1E919, "M", "𞤻"), - (0x1E91A, "M", "𞤼"), - (0x1E91B, "M", "𞤽"), - (0x1E91C, "M", "𞤾"), - (0x1E91D, "M", "𞤿"), - (0x1E91E, "M", "𞥀"), - (0x1E91F, "M", "𞥁"), - (0x1E920, "M", "𞥂"), - (0x1E921, "M", "𞥃"), - (0x1E922, "V"), - (0x1E94C, "X"), - (0x1E950, "V"), - (0x1E95A, "X"), - (0x1E95E, "V"), - (0x1E960, "X"), - (0x1EC71, "V"), - (0x1ECB5, "X"), - (0x1ED01, "V"), - (0x1ED3E, "X"), - (0x1EE00, "M", "ا"), - (0x1EE01, "M", "ب"), - (0x1EE02, "M", "ج"), - (0x1EE03, "M", "د"), - (0x1EE04, "X"), - (0x1EE05, "M", "و"), - (0x1EE06, "M", "ز"), - (0x1EE07, "M", "ح"), - (0x1EE08, "M", "ط"), - (0x1EE09, "M", "ي"), - (0x1EE0A, "M", "ك"), - (0x1EE0B, "M", "ل"), - (0x1EE0C, "M", "م"), - (0x1EE0D, "M", "ن"), - (0x1EE0E, "M", "س"), - (0x1EE0F, "M", "ع"), - (0x1EE10, "M", "ف"), - (0x1EE11, "M", "ص"), - (0x1EE12, "M", "ق"), - (0x1EE13, "M", "ر"), - (0x1EE14, "M", "ش"), - (0x1EE15, "M", "ت"), - (0x1EE16, "M", "ث"), - (0x1EE17, "M", "خ"), - (0x1EE18, "M", "ذ"), - (0x1EE19, "M", "ض"), - (0x1EE1A, "M", "ظ"), - (0x1EE1B, "M", "غ"), - (0x1EE1C, "M", "ٮ"), - (0x1EE1D, "M", "ں"), - (0x1EE1E, "M", "ڡ"), - (0x1EE1F, "M", "ٯ"), - (0x1EE20, "X"), - (0x1EE21, "M", "ب"), - (0x1EE22, "M", "ج"), - (0x1EE23, "X"), - (0x1EE24, "M", "ه"), - (0x1EE25, "X"), - (0x1EE27, "M", "ح"), - (0x1EE28, "X"), - (0x1EE29, "M", "ي"), - (0x1EE2A, "M", "ك"), - (0x1EE2B, "M", "ل"), - (0x1EE2C, "M", "م"), - (0x1EE2D, "M", "ن"), - (0x1EE2E, "M", "س"), - (0x1EE2F, "M", "ع"), - (0x1EE30, "M", "ف"), - (0x1EE31, "M", "ص"), - (0x1EE32, "M", "ق"), - (0x1EE33, "X"), - (0x1EE34, "M", "ش"), - (0x1EE35, "M", "ت"), - (0x1EE36, "M", "ث"), - (0x1EE37, "M", "خ"), - (0x1EE38, "X"), - (0x1EE39, "M", "ض"), - (0x1EE3A, "X"), - (0x1EE3B, "M", "غ"), - (0x1EE3C, "X"), - (0x1EE42, "M", "ج"), - (0x1EE43, "X"), - (0x1EE47, "M", "ح"), - (0x1EE48, "X"), - (0x1EE49, "M", "ي"), - (0x1EE4A, "X"), - (0x1EE4B, "M", "ل"), - (0x1EE4C, "X"), - (0x1EE4D, "M", "ن"), - (0x1EE4E, "M", "س"), + (0x1E90A, 'M', '𞤬'), + (0x1E90B, 'M', '𞤭'), + (0x1E90C, 'M', '𞤮'), + (0x1E90D, 'M', '𞤯'), + (0x1E90E, 'M', '𞤰'), + (0x1E90F, 'M', '𞤱'), + (0x1E910, 'M', '𞤲'), + (0x1E911, 'M', '𞤳'), + (0x1E912, 'M', '𞤴'), + (0x1E913, 'M', '𞤵'), + (0x1E914, 'M', '𞤶'), + (0x1E915, 'M', '𞤷'), + (0x1E916, 'M', '𞤸'), + (0x1E917, 'M', '𞤹'), + (0x1E918, 'M', '𞤺'), + (0x1E919, 'M', '𞤻'), + (0x1E91A, 'M', '𞤼'), + (0x1E91B, 'M', '𞤽'), + (0x1E91C, 'M', '𞤾'), + (0x1E91D, 'M', '𞤿'), + (0x1E91E, 'M', '𞥀'), + (0x1E91F, 'M', '𞥁'), + (0x1E920, 'M', '𞥂'), + (0x1E921, 'M', '𞥃'), + (0x1E922, 'V'), + (0x1E94C, 'X'), + (0x1E950, 'V'), + (0x1E95A, 'X'), + (0x1E95E, 'V'), + (0x1E960, 'X'), + (0x1EC71, 'V'), + (0x1ECB5, 'X'), + (0x1ED01, 'V'), + (0x1ED3E, 'X'), + (0x1EE00, 'M', 'ا'), + (0x1EE01, 'M', 'ب'), + (0x1EE02, 'M', 'ج'), + (0x1EE03, 'M', 'د'), + (0x1EE04, 'X'), + (0x1EE05, 'M', 'و'), + (0x1EE06, 'M', 'ز'), + (0x1EE07, 'M', 'ح'), + (0x1EE08, 'M', 'ط'), + (0x1EE09, 'M', 'ي'), + (0x1EE0A, 'M', 'ك'), + (0x1EE0B, 'M', 'ل'), + (0x1EE0C, 'M', 'م'), + (0x1EE0D, 'M', 'ن'), + (0x1EE0E, 'M', 'س'), + (0x1EE0F, 'M', 'ع'), + (0x1EE10, 'M', 'ف'), + (0x1EE11, 'M', 'ص'), + (0x1EE12, 'M', 'ق'), + (0x1EE13, 'M', 'ر'), + (0x1EE14, 'M', 'ش'), + (0x1EE15, 'M', 'ت'), + (0x1EE16, 'M', 'ث'), + (0x1EE17, 'M', 'خ'), + (0x1EE18, 'M', 'ذ'), + (0x1EE19, 'M', 'ض'), + (0x1EE1A, 'M', 'ظ'), + (0x1EE1B, 'M', 'غ'), + (0x1EE1C, 'M', 'ٮ'), + (0x1EE1D, 'M', 'ں'), + (0x1EE1E, 'M', 'ڡ'), + (0x1EE1F, 'M', 'ٯ'), + (0x1EE20, 'X'), + (0x1EE21, 'M', 'ب'), + (0x1EE22, 'M', 'ج'), + (0x1EE23, 'X'), + (0x1EE24, 'M', 'ه'), + (0x1EE25, 'X'), + (0x1EE27, 'M', 'ح'), + (0x1EE28, 'X'), + (0x1EE29, 'M', 'ي'), + (0x1EE2A, 'M', 'ك'), + (0x1EE2B, 'M', 'ل'), + (0x1EE2C, 'M', 'م'), + (0x1EE2D, 'M', 'ن'), + (0x1EE2E, 'M', 'س'), + (0x1EE2F, 'M', 'ع'), + (0x1EE30, 'M', 'ف'), + (0x1EE31, 'M', 'ص'), + (0x1EE32, 'M', 'ق'), + (0x1EE33, 'X'), + (0x1EE34, 'M', 'ش'), + (0x1EE35, 'M', 'ت'), + (0x1EE36, 'M', 'ث'), + (0x1EE37, 'M', 'خ'), + (0x1EE38, 'X'), + (0x1EE39, 'M', 'ض'), + (0x1EE3A, 'X'), + (0x1EE3B, 'M', 'غ'), + (0x1EE3C, 'X'), + (0x1EE42, 'M', 'ج'), + (0x1EE43, 'X'), + (0x1EE47, 'M', 'ح'), + (0x1EE48, 'X'), + (0x1EE49, 'M', 'ي'), + (0x1EE4A, 'X'), ] - def _seg_73() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x1EE4F, "M", "ع"), - (0x1EE50, "X"), - (0x1EE51, "M", "ص"), - (0x1EE52, "M", "ق"), - (0x1EE53, "X"), - (0x1EE54, "M", "ش"), - (0x1EE55, "X"), - (0x1EE57, "M", "خ"), - (0x1EE58, "X"), - (0x1EE59, "M", "ض"), - (0x1EE5A, "X"), - (0x1EE5B, "M", "غ"), - (0x1EE5C, "X"), - (0x1EE5D, "M", "ں"), - (0x1EE5E, "X"), - (0x1EE5F, "M", "ٯ"), - (0x1EE60, "X"), - (0x1EE61, "M", "ب"), - (0x1EE62, "M", "ج"), - (0x1EE63, "X"), - (0x1EE64, "M", "ه"), - (0x1EE65, "X"), - (0x1EE67, "M", "ح"), - (0x1EE68, "M", "ط"), - (0x1EE69, "M", "ي"), - (0x1EE6A, "M", "ك"), - (0x1EE6B, "X"), - (0x1EE6C, "M", "م"), - (0x1EE6D, "M", "ن"), - (0x1EE6E, "M", "س"), - (0x1EE6F, "M", "ع"), - (0x1EE70, "M", "ف"), - (0x1EE71, "M", "ص"), - (0x1EE72, "M", "ق"), - (0x1EE73, "X"), - (0x1EE74, "M", "ش"), - (0x1EE75, "M", "ت"), - (0x1EE76, "M", "ث"), - (0x1EE77, "M", "خ"), - (0x1EE78, "X"), - (0x1EE79, "M", "ض"), - (0x1EE7A, "M", "ظ"), - (0x1EE7B, "M", "غ"), - (0x1EE7C, "M", "ٮ"), - (0x1EE7D, "X"), - (0x1EE7E, "M", "ڡ"), - (0x1EE7F, "X"), - (0x1EE80, "M", "ا"), - (0x1EE81, "M", "ب"), - (0x1EE82, "M", "ج"), - (0x1EE83, "M", "د"), - (0x1EE84, "M", "ه"), - (0x1EE85, "M", "و"), - (0x1EE86, "M", "ز"), - (0x1EE87, "M", "ح"), - (0x1EE88, "M", "ط"), - (0x1EE89, "M", "ي"), - (0x1EE8A, "X"), - (0x1EE8B, "M", "ل"), - (0x1EE8C, "M", "م"), - (0x1EE8D, "M", "ن"), - (0x1EE8E, "M", "س"), - (0x1EE8F, "M", "ع"), - (0x1EE90, "M", "ف"), - (0x1EE91, "M", "ص"), - (0x1EE92, "M", "ق"), - (0x1EE93, "M", "ر"), - (0x1EE94, "M", "ش"), - (0x1EE95, "M", "ت"), - (0x1EE96, "M", "ث"), - (0x1EE97, "M", "خ"), - (0x1EE98, "M", "ذ"), - (0x1EE99, "M", "ض"), - (0x1EE9A, "M", "ظ"), - (0x1EE9B, "M", "غ"), - (0x1EE9C, "X"), - (0x1EEA1, "M", "ب"), - (0x1EEA2, "M", "ج"), - (0x1EEA3, "M", "د"), - (0x1EEA4, "X"), - (0x1EEA5, "M", "و"), - (0x1EEA6, "M", "ز"), - (0x1EEA7, "M", "ح"), - (0x1EEA8, "M", "ط"), - (0x1EEA9, "M", "ي"), - (0x1EEAA, "X"), - (0x1EEAB, "M", "ل"), - (0x1EEAC, "M", "م"), - (0x1EEAD, "M", "ن"), - (0x1EEAE, "M", "س"), - (0x1EEAF, "M", "ع"), - (0x1EEB0, "M", "ف"), - (0x1EEB1, "M", "ص"), - (0x1EEB2, "M", "ق"), - (0x1EEB3, "M", "ر"), - (0x1EEB4, "M", "ش"), - (0x1EEB5, "M", "ت"), - (0x1EEB6, "M", "ث"), - (0x1EEB7, "M", "خ"), - (0x1EEB8, "M", "ذ"), + (0x1EE4B, 'M', 'ل'), + (0x1EE4C, 'X'), + (0x1EE4D, 'M', 'ن'), + (0x1EE4E, 'M', 'س'), + (0x1EE4F, 'M', 'ع'), + (0x1EE50, 'X'), + (0x1EE51, 'M', 'ص'), + (0x1EE52, 'M', 'ق'), + (0x1EE53, 'X'), + (0x1EE54, 'M', 'ش'), + (0x1EE55, 'X'), + (0x1EE57, 'M', 'خ'), + (0x1EE58, 'X'), + (0x1EE59, 'M', 'ض'), + (0x1EE5A, 'X'), + (0x1EE5B, 'M', 'غ'), + (0x1EE5C, 'X'), + (0x1EE5D, 'M', 'ں'), + (0x1EE5E, 'X'), + (0x1EE5F, 'M', 'ٯ'), + (0x1EE60, 'X'), + (0x1EE61, 'M', 'ب'), + (0x1EE62, 'M', 'ج'), + (0x1EE63, 'X'), + (0x1EE64, 'M', 'ه'), + (0x1EE65, 'X'), + (0x1EE67, 'M', 'ح'), + (0x1EE68, 'M', 'ط'), + (0x1EE69, 'M', 'ي'), + (0x1EE6A, 'M', 'ك'), + (0x1EE6B, 'X'), + (0x1EE6C, 'M', 'م'), + (0x1EE6D, 'M', 'ن'), + (0x1EE6E, 'M', 'س'), + (0x1EE6F, 'M', 'ع'), + (0x1EE70, 'M', 'ف'), + (0x1EE71, 'M', 'ص'), + (0x1EE72, 'M', 'ق'), + (0x1EE73, 'X'), + (0x1EE74, 'M', 'ش'), + (0x1EE75, 'M', 'ت'), + (0x1EE76, 'M', 'ث'), + (0x1EE77, 'M', 'خ'), + (0x1EE78, 'X'), + (0x1EE79, 'M', 'ض'), + (0x1EE7A, 'M', 'ظ'), + (0x1EE7B, 'M', 'غ'), + (0x1EE7C, 'M', 'ٮ'), + (0x1EE7D, 'X'), + (0x1EE7E, 'M', 'ڡ'), + (0x1EE7F, 'X'), + (0x1EE80, 'M', 'ا'), + (0x1EE81, 'M', 'ب'), + (0x1EE82, 'M', 'ج'), + (0x1EE83, 'M', 'د'), + (0x1EE84, 'M', 'ه'), + (0x1EE85, 'M', 'و'), + (0x1EE86, 'M', 'ز'), + (0x1EE87, 'M', 'ح'), + (0x1EE88, 'M', 'ط'), + (0x1EE89, 'M', 'ي'), + (0x1EE8A, 'X'), + (0x1EE8B, 'M', 'ل'), + (0x1EE8C, 'M', 'م'), + (0x1EE8D, 'M', 'ن'), + (0x1EE8E, 'M', 'س'), + (0x1EE8F, 'M', 'ع'), + (0x1EE90, 'M', 'ف'), + (0x1EE91, 'M', 'ص'), + (0x1EE92, 'M', 'ق'), + (0x1EE93, 'M', 'ر'), + (0x1EE94, 'M', 'ش'), + (0x1EE95, 'M', 'ت'), + (0x1EE96, 'M', 'ث'), + (0x1EE97, 'M', 'خ'), + (0x1EE98, 'M', 'ذ'), + (0x1EE99, 'M', 'ض'), + (0x1EE9A, 'M', 'ظ'), + (0x1EE9B, 'M', 'غ'), + (0x1EE9C, 'X'), + (0x1EEA1, 'M', 'ب'), + (0x1EEA2, 'M', 'ج'), + (0x1EEA3, 'M', 'د'), + (0x1EEA4, 'X'), + (0x1EEA5, 'M', 'و'), + (0x1EEA6, 'M', 'ز'), + (0x1EEA7, 'M', 'ح'), + (0x1EEA8, 'M', 'ط'), + (0x1EEA9, 'M', 'ي'), + (0x1EEAA, 'X'), + (0x1EEAB, 'M', 'ل'), + (0x1EEAC, 'M', 'م'), + (0x1EEAD, 'M', 'ن'), + (0x1EEAE, 'M', 'س'), + (0x1EEAF, 'M', 'ع'), + (0x1EEB0, 'M', 'ف'), + (0x1EEB1, 'M', 'ص'), + (0x1EEB2, 'M', 'ق'), + (0x1EEB3, 'M', 'ر'), + (0x1EEB4, 'M', 'ش'), ] - def _seg_74() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x1EEB9, "M", "ض"), - (0x1EEBA, "M", "ظ"), - (0x1EEBB, "M", "غ"), - (0x1EEBC, "X"), - (0x1EEF0, "V"), - (0x1EEF2, "X"), - (0x1F000, "V"), - (0x1F02C, "X"), - (0x1F030, "V"), - (0x1F094, "X"), - (0x1F0A0, "V"), - (0x1F0AF, "X"), - (0x1F0B1, "V"), - (0x1F0C0, "X"), - (0x1F0C1, "V"), - (0x1F0D0, "X"), - (0x1F0D1, "V"), - (0x1F0F6, "X"), - (0x1F101, "3", "0,"), - (0x1F102, "3", "1,"), - (0x1F103, "3", "2,"), - (0x1F104, "3", "3,"), - (0x1F105, "3", "4,"), - (0x1F106, "3", "5,"), - (0x1F107, "3", "6,"), - (0x1F108, "3", "7,"), - (0x1F109, "3", "8,"), - (0x1F10A, "3", "9,"), - (0x1F10B, "V"), - (0x1F110, "3", "(a)"), - (0x1F111, "3", "(b)"), - (0x1F112, "3", "(c)"), - (0x1F113, "3", "(d)"), - (0x1F114, "3", "(e)"), - (0x1F115, "3", "(f)"), - (0x1F116, "3", "(g)"), - (0x1F117, "3", "(h)"), - (0x1F118, "3", "(i)"), - (0x1F119, "3", "(j)"), - (0x1F11A, "3", "(k)"), - (0x1F11B, "3", "(l)"), - (0x1F11C, "3", "(m)"), - (0x1F11D, "3", "(n)"), - (0x1F11E, "3", "(o)"), - (0x1F11F, "3", "(p)"), - (0x1F120, "3", "(q)"), - (0x1F121, "3", "(r)"), - (0x1F122, "3", "(s)"), - (0x1F123, "3", "(t)"), - (0x1F124, "3", "(u)"), - (0x1F125, "3", "(v)"), - (0x1F126, "3", "(w)"), - (0x1F127, "3", "(x)"), - (0x1F128, "3", "(y)"), - (0x1F129, "3", "(z)"), - (0x1F12A, "M", "〔s〕"), - (0x1F12B, "M", "c"), - (0x1F12C, "M", "r"), - (0x1F12D, "M", "cd"), - (0x1F12E, "M", "wz"), - (0x1F12F, "V"), - (0x1F130, "M", "a"), - (0x1F131, "M", "b"), - (0x1F132, "M", "c"), - (0x1F133, "M", "d"), - (0x1F134, "M", "e"), - (0x1F135, "M", "f"), - (0x1F136, "M", "g"), - (0x1F137, "M", "h"), - (0x1F138, "M", "i"), - (0x1F139, "M", "j"), - (0x1F13A, "M", "k"), - (0x1F13B, "M", "l"), - (0x1F13C, "M", "m"), - (0x1F13D, "M", "n"), - (0x1F13E, "M", "o"), - (0x1F13F, "M", "p"), - (0x1F140, "M", "q"), - (0x1F141, "M", "r"), - (0x1F142, "M", "s"), - (0x1F143, "M", "t"), - (0x1F144, "M", "u"), - (0x1F145, "M", "v"), - (0x1F146, "M", "w"), - (0x1F147, "M", "x"), - (0x1F148, "M", "y"), - (0x1F149, "M", "z"), - (0x1F14A, "M", "hv"), - (0x1F14B, "M", "mv"), - (0x1F14C, "M", "sd"), - (0x1F14D, "M", "ss"), - (0x1F14E, "M", "ppv"), - (0x1F14F, "M", "wc"), - (0x1F150, "V"), - (0x1F16A, "M", "mc"), - (0x1F16B, "M", "md"), - (0x1F16C, "M", "mr"), - (0x1F16D, "V"), - (0x1F190, "M", "dj"), - (0x1F191, "V"), + (0x1EEB5, 'M', 'ت'), + (0x1EEB6, 'M', 'ث'), + (0x1EEB7, 'M', 'خ'), + (0x1EEB8, 'M', 'ذ'), + (0x1EEB9, 'M', 'ض'), + (0x1EEBA, 'M', 'ظ'), + (0x1EEBB, 'M', 'غ'), + (0x1EEBC, 'X'), + (0x1EEF0, 'V'), + (0x1EEF2, 'X'), + (0x1F000, 'V'), + (0x1F02C, 'X'), + (0x1F030, 'V'), + (0x1F094, 'X'), + (0x1F0A0, 'V'), + (0x1F0AF, 'X'), + (0x1F0B1, 'V'), + (0x1F0C0, 'X'), + (0x1F0C1, 'V'), + (0x1F0D0, 'X'), + (0x1F0D1, 'V'), + (0x1F0F6, 'X'), + (0x1F101, '3', '0,'), + (0x1F102, '3', '1,'), + (0x1F103, '3', '2,'), + (0x1F104, '3', '3,'), + (0x1F105, '3', '4,'), + (0x1F106, '3', '5,'), + (0x1F107, '3', '6,'), + (0x1F108, '3', '7,'), + (0x1F109, '3', '8,'), + (0x1F10A, '3', '9,'), + (0x1F10B, 'V'), + (0x1F110, '3', '(a)'), + (0x1F111, '3', '(b)'), + (0x1F112, '3', '(c)'), + (0x1F113, '3', '(d)'), + (0x1F114, '3', '(e)'), + (0x1F115, '3', '(f)'), + (0x1F116, '3', '(g)'), + (0x1F117, '3', '(h)'), + (0x1F118, '3', '(i)'), + (0x1F119, '3', '(j)'), + (0x1F11A, '3', '(k)'), + (0x1F11B, '3', '(l)'), + (0x1F11C, '3', '(m)'), + (0x1F11D, '3', '(n)'), + (0x1F11E, '3', '(o)'), + (0x1F11F, '3', '(p)'), + (0x1F120, '3', '(q)'), + (0x1F121, '3', '(r)'), + (0x1F122, '3', '(s)'), + (0x1F123, '3', '(t)'), + (0x1F124, '3', '(u)'), + (0x1F125, '3', '(v)'), + (0x1F126, '3', '(w)'), + (0x1F127, '3', '(x)'), + (0x1F128, '3', '(y)'), + (0x1F129, '3', '(z)'), + (0x1F12A, 'M', '〔s〕'), + (0x1F12B, 'M', 'c'), + (0x1F12C, 'M', 'r'), + (0x1F12D, 'M', 'cd'), + (0x1F12E, 'M', 'wz'), + (0x1F12F, 'V'), + (0x1F130, 'M', 'a'), + (0x1F131, 'M', 'b'), + (0x1F132, 'M', 'c'), + (0x1F133, 'M', 'd'), + (0x1F134, 'M', 'e'), + (0x1F135, 'M', 'f'), + (0x1F136, 'M', 'g'), + (0x1F137, 'M', 'h'), + (0x1F138, 'M', 'i'), + (0x1F139, 'M', 'j'), + (0x1F13A, 'M', 'k'), + (0x1F13B, 'M', 'l'), + (0x1F13C, 'M', 'm'), + (0x1F13D, 'M', 'n'), + (0x1F13E, 'M', 'o'), + (0x1F13F, 'M', 'p'), + (0x1F140, 'M', 'q'), + (0x1F141, 'M', 'r'), + (0x1F142, 'M', 's'), + (0x1F143, 'M', 't'), + (0x1F144, 'M', 'u'), + (0x1F145, 'M', 'v'), + (0x1F146, 'M', 'w'), + (0x1F147, 'M', 'x'), + (0x1F148, 'M', 'y'), + (0x1F149, 'M', 'z'), + (0x1F14A, 'M', 'hv'), + (0x1F14B, 'M', 'mv'), + (0x1F14C, 'M', 'sd'), + (0x1F14D, 'M', 'ss'), + (0x1F14E, 'M', 'ppv'), + (0x1F14F, 'M', 'wc'), + (0x1F150, 'V'), + (0x1F16A, 'M', 'mc'), + (0x1F16B, 'M', 'md'), ] - def _seg_75() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x1F1AE, "X"), - (0x1F1E6, "V"), - (0x1F200, "M", "ほか"), - (0x1F201, "M", "ココ"), - (0x1F202, "M", "サ"), - (0x1F203, "X"), - (0x1F210, "M", "手"), - (0x1F211, "M", "字"), - (0x1F212, "M", "双"), - (0x1F213, "M", "デ"), - (0x1F214, "M", "二"), - (0x1F215, "M", "多"), - (0x1F216, "M", "解"), - (0x1F217, "M", "天"), - (0x1F218, "M", "交"), - (0x1F219, "M", "映"), - (0x1F21A, "M", "無"), - (0x1F21B, "M", "料"), - (0x1F21C, "M", "前"), - (0x1F21D, "M", "後"), - (0x1F21E, "M", "再"), - (0x1F21F, "M", "新"), - (0x1F220, "M", "初"), - (0x1F221, "M", "終"), - (0x1F222, "M", "生"), - (0x1F223, "M", "販"), - (0x1F224, "M", "声"), - (0x1F225, "M", "吹"), - (0x1F226, "M", "演"), - (0x1F227, "M", "投"), - (0x1F228, "M", "捕"), - (0x1F229, "M", "一"), - (0x1F22A, "M", "三"), - (0x1F22B, "M", "遊"), - (0x1F22C, "M", "左"), - (0x1F22D, "M", "中"), - (0x1F22E, "M", "右"), - (0x1F22F, "M", "指"), - (0x1F230, "M", "走"), - (0x1F231, "M", "打"), - (0x1F232, "M", "禁"), - (0x1F233, "M", "空"), - (0x1F234, "M", "合"), - (0x1F235, "M", "満"), - (0x1F236, "M", "有"), - (0x1F237, "M", "月"), - (0x1F238, "M", "申"), - (0x1F239, "M", "割"), - (0x1F23A, "M", "営"), - (0x1F23B, "M", "配"), - (0x1F23C, "X"), - (0x1F240, "M", "〔本〕"), - (0x1F241, "M", "〔三〕"), - (0x1F242, "M", "〔二〕"), - (0x1F243, "M", "〔安〕"), - (0x1F244, "M", "〔点〕"), - (0x1F245, "M", "〔打〕"), - (0x1F246, "M", "〔盗〕"), - (0x1F247, "M", "〔勝〕"), - (0x1F248, "M", "〔敗〕"), - (0x1F249, "X"), - (0x1F250, "M", "得"), - (0x1F251, "M", "可"), - (0x1F252, "X"), - (0x1F260, "V"), - (0x1F266, "X"), - (0x1F300, "V"), - (0x1F6D8, "X"), - (0x1F6DC, "V"), - (0x1F6ED, "X"), - (0x1F6F0, "V"), - (0x1F6FD, "X"), - (0x1F700, "V"), - (0x1F777, "X"), - (0x1F77B, "V"), - (0x1F7DA, "X"), - (0x1F7E0, "V"), - (0x1F7EC, "X"), - (0x1F7F0, "V"), - (0x1F7F1, "X"), - (0x1F800, "V"), - (0x1F80C, "X"), - (0x1F810, "V"), - (0x1F848, "X"), - (0x1F850, "V"), - (0x1F85A, "X"), - (0x1F860, "V"), - (0x1F888, "X"), - (0x1F890, "V"), - (0x1F8AE, "X"), - (0x1F8B0, "V"), - (0x1F8B2, "X"), - (0x1F900, "V"), - (0x1FA54, "X"), - (0x1FA60, "V"), - (0x1FA6E, "X"), - (0x1FA70, "V"), - (0x1FA7D, "X"), - (0x1FA80, "V"), - (0x1FA89, "X"), + (0x1F16C, 'M', 'mr'), + (0x1F16D, 'V'), + (0x1F190, 'M', 'dj'), + (0x1F191, 'V'), + (0x1F1AE, 'X'), + (0x1F1E6, 'V'), + (0x1F200, 'M', 'ほか'), + (0x1F201, 'M', 'ココ'), + (0x1F202, 'M', 'サ'), + (0x1F203, 'X'), + (0x1F210, 'M', '手'), + (0x1F211, 'M', '字'), + (0x1F212, 'M', '双'), + (0x1F213, 'M', 'デ'), + (0x1F214, 'M', '二'), + (0x1F215, 'M', '多'), + (0x1F216, 'M', '解'), + (0x1F217, 'M', '天'), + (0x1F218, 'M', '交'), + (0x1F219, 'M', '映'), + (0x1F21A, 'M', '無'), + (0x1F21B, 'M', '料'), + (0x1F21C, 'M', '前'), + (0x1F21D, 'M', '後'), + (0x1F21E, 'M', '再'), + (0x1F21F, 'M', '新'), + (0x1F220, 'M', '初'), + (0x1F221, 'M', '終'), + (0x1F222, 'M', '生'), + (0x1F223, 'M', '販'), + (0x1F224, 'M', '声'), + (0x1F225, 'M', '吹'), + (0x1F226, 'M', '演'), + (0x1F227, 'M', '投'), + (0x1F228, 'M', '捕'), + (0x1F229, 'M', '一'), + (0x1F22A, 'M', '三'), + (0x1F22B, 'M', '遊'), + (0x1F22C, 'M', '左'), + (0x1F22D, 'M', '中'), + (0x1F22E, 'M', '右'), + (0x1F22F, 'M', '指'), + (0x1F230, 'M', '走'), + (0x1F231, 'M', '打'), + (0x1F232, 'M', '禁'), + (0x1F233, 'M', '空'), + (0x1F234, 'M', '合'), + (0x1F235, 'M', '満'), + (0x1F236, 'M', '有'), + (0x1F237, 'M', '月'), + (0x1F238, 'M', '申'), + (0x1F239, 'M', '割'), + (0x1F23A, 'M', '営'), + (0x1F23B, 'M', '配'), + (0x1F23C, 'X'), + (0x1F240, 'M', '〔本〕'), + (0x1F241, 'M', '〔三〕'), + (0x1F242, 'M', '〔二〕'), + (0x1F243, 'M', '〔安〕'), + (0x1F244, 'M', '〔点〕'), + (0x1F245, 'M', '〔打〕'), + (0x1F246, 'M', '〔盗〕'), + (0x1F247, 'M', '〔勝〕'), + (0x1F248, 'M', '〔敗〕'), + (0x1F249, 'X'), + (0x1F250, 'M', '得'), + (0x1F251, 'M', '可'), + (0x1F252, 'X'), + (0x1F260, 'V'), + (0x1F266, 'X'), + (0x1F300, 'V'), + (0x1F6D8, 'X'), + (0x1F6DC, 'V'), + (0x1F6ED, 'X'), + (0x1F6F0, 'V'), + (0x1F6FD, 'X'), + (0x1F700, 'V'), + (0x1F777, 'X'), + (0x1F77B, 'V'), + (0x1F7DA, 'X'), + (0x1F7E0, 'V'), + (0x1F7EC, 'X'), + (0x1F7F0, 'V'), + (0x1F7F1, 'X'), + (0x1F800, 'V'), + (0x1F80C, 'X'), + (0x1F810, 'V'), + (0x1F848, 'X'), + (0x1F850, 'V'), + (0x1F85A, 'X'), + (0x1F860, 'V'), + (0x1F888, 'X'), + (0x1F890, 'V'), + (0x1F8AE, 'X'), + (0x1F8B0, 'V'), + (0x1F8B2, 'X'), + (0x1F900, 'V'), + (0x1FA54, 'X'), + (0x1FA60, 'V'), + (0x1FA6E, 'X'), ] - def _seg_76() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x1FA90, "V"), - (0x1FABE, "X"), - (0x1FABF, "V"), - (0x1FAC6, "X"), - (0x1FACE, "V"), - (0x1FADC, "X"), - (0x1FAE0, "V"), - (0x1FAE9, "X"), - (0x1FAF0, "V"), - (0x1FAF9, "X"), - (0x1FB00, "V"), - (0x1FB93, "X"), - (0x1FB94, "V"), - (0x1FBCB, "X"), - (0x1FBF0, "M", "0"), - (0x1FBF1, "M", "1"), - (0x1FBF2, "M", "2"), - (0x1FBF3, "M", "3"), - (0x1FBF4, "M", "4"), - (0x1FBF5, "M", "5"), - (0x1FBF6, "M", "6"), - (0x1FBF7, "M", "7"), - (0x1FBF8, "M", "8"), - (0x1FBF9, "M", "9"), - (0x1FBFA, "X"), - (0x20000, "V"), - (0x2A6E0, "X"), - (0x2A700, "V"), - (0x2B73A, "X"), - (0x2B740, "V"), - (0x2B81E, "X"), - (0x2B820, "V"), - (0x2CEA2, "X"), - (0x2CEB0, "V"), - (0x2EBE1, "X"), - (0x2EBF0, "V"), - (0x2EE5E, "X"), - (0x2F800, "M", "丽"), - (0x2F801, "M", "丸"), - (0x2F802, "M", "乁"), - (0x2F803, "M", "𠄢"), - (0x2F804, "M", "你"), - (0x2F805, "M", "侮"), - (0x2F806, "M", "侻"), - (0x2F807, "M", "倂"), - (0x2F808, "M", "偺"), - (0x2F809, "M", "備"), - (0x2F80A, "M", "僧"), - (0x2F80B, "M", "像"), - (0x2F80C, "M", "㒞"), - (0x2F80D, "M", "𠘺"), - (0x2F80E, "M", "免"), - (0x2F80F, "M", "兔"), - (0x2F810, "M", "兤"), - (0x2F811, "M", "具"), - (0x2F812, "M", "𠔜"), - (0x2F813, "M", "㒹"), - (0x2F814, "M", "內"), - (0x2F815, "M", "再"), - (0x2F816, "M", "𠕋"), - (0x2F817, "M", "冗"), - (0x2F818, "M", "冤"), - (0x2F819, "M", "仌"), - (0x2F81A, "M", "冬"), - (0x2F81B, "M", "况"), - (0x2F81C, "M", "𩇟"), - (0x2F81D, "M", "凵"), - (0x2F81E, "M", "刃"), - (0x2F81F, "M", "㓟"), - (0x2F820, "M", "刻"), - (0x2F821, "M", "剆"), - (0x2F822, "M", "割"), - (0x2F823, "M", "剷"), - (0x2F824, "M", "㔕"), - (0x2F825, "M", "勇"), - (0x2F826, "M", "勉"), - (0x2F827, "M", "勤"), - (0x2F828, "M", "勺"), - (0x2F829, "M", "包"), - (0x2F82A, "M", "匆"), - (0x2F82B, "M", "北"), - (0x2F82C, "M", "卉"), - (0x2F82D, "M", "卑"), - (0x2F82E, "M", "博"), - (0x2F82F, "M", "即"), - (0x2F830, "M", "卽"), - (0x2F831, "M", "卿"), - (0x2F834, "M", "𠨬"), - (0x2F835, "M", "灰"), - (0x2F836, "M", "及"), - (0x2F837, "M", "叟"), - (0x2F838, "M", "𠭣"), - (0x2F839, "M", "叫"), - (0x2F83A, "M", "叱"), - (0x2F83B, "M", "吆"), - (0x2F83C, "M", "咞"), - (0x2F83D, "M", "吸"), - (0x2F83E, "M", "呈"), - (0x2F83F, "M", "周"), - (0x2F840, "M", "咢"), + (0x1FA70, 'V'), + (0x1FA7D, 'X'), + (0x1FA80, 'V'), + (0x1FA89, 'X'), + (0x1FA90, 'V'), + (0x1FABE, 'X'), + (0x1FABF, 'V'), + (0x1FAC6, 'X'), + (0x1FACE, 'V'), + (0x1FADC, 'X'), + (0x1FAE0, 'V'), + (0x1FAE9, 'X'), + (0x1FAF0, 'V'), + (0x1FAF9, 'X'), + (0x1FB00, 'V'), + (0x1FB93, 'X'), + (0x1FB94, 'V'), + (0x1FBCB, 'X'), + (0x1FBF0, 'M', '0'), + (0x1FBF1, 'M', '1'), + (0x1FBF2, 'M', '2'), + (0x1FBF3, 'M', '3'), + (0x1FBF4, 'M', '4'), + (0x1FBF5, 'M', '5'), + (0x1FBF6, 'M', '6'), + (0x1FBF7, 'M', '7'), + (0x1FBF8, 'M', '8'), + (0x1FBF9, 'M', '9'), + (0x1FBFA, 'X'), + (0x20000, 'V'), + (0x2A6E0, 'X'), + (0x2A700, 'V'), + (0x2B73A, 'X'), + (0x2B740, 'V'), + (0x2B81E, 'X'), + (0x2B820, 'V'), + (0x2CEA2, 'X'), + (0x2CEB0, 'V'), + (0x2EBE1, 'X'), + (0x2F800, 'M', '丽'), + (0x2F801, 'M', '丸'), + (0x2F802, 'M', '乁'), + (0x2F803, 'M', '𠄢'), + (0x2F804, 'M', '你'), + (0x2F805, 'M', '侮'), + (0x2F806, 'M', '侻'), + (0x2F807, 'M', '倂'), + (0x2F808, 'M', '偺'), + (0x2F809, 'M', '備'), + (0x2F80A, 'M', '僧'), + (0x2F80B, 'M', '像'), + (0x2F80C, 'M', '㒞'), + (0x2F80D, 'M', '𠘺'), + (0x2F80E, 'M', '免'), + (0x2F80F, 'M', '兔'), + (0x2F810, 'M', '兤'), + (0x2F811, 'M', '具'), + (0x2F812, 'M', '𠔜'), + (0x2F813, 'M', '㒹'), + (0x2F814, 'M', '內'), + (0x2F815, 'M', '再'), + (0x2F816, 'M', '𠕋'), + (0x2F817, 'M', '冗'), + (0x2F818, 'M', '冤'), + (0x2F819, 'M', '仌'), + (0x2F81A, 'M', '冬'), + (0x2F81B, 'M', '况'), + (0x2F81C, 'M', '𩇟'), + (0x2F81D, 'M', '凵'), + (0x2F81E, 'M', '刃'), + (0x2F81F, 'M', '㓟'), + (0x2F820, 'M', '刻'), + (0x2F821, 'M', '剆'), + (0x2F822, 'M', '割'), + (0x2F823, 'M', '剷'), + (0x2F824, 'M', '㔕'), + (0x2F825, 'M', '勇'), + (0x2F826, 'M', '勉'), + (0x2F827, 'M', '勤'), + (0x2F828, 'M', '勺'), + (0x2F829, 'M', '包'), + (0x2F82A, 'M', '匆'), + (0x2F82B, 'M', '北'), + (0x2F82C, 'M', '卉'), + (0x2F82D, 'M', '卑'), + (0x2F82E, 'M', '博'), + (0x2F82F, 'M', '即'), + (0x2F830, 'M', '卽'), + (0x2F831, 'M', '卿'), + (0x2F834, 'M', '𠨬'), + (0x2F835, 'M', '灰'), + (0x2F836, 'M', '及'), + (0x2F837, 'M', '叟'), + (0x2F838, 'M', '𠭣'), + (0x2F839, 'M', '叫'), + (0x2F83A, 'M', '叱'), + (0x2F83B, 'M', '吆'), + (0x2F83C, 'M', '咞'), + (0x2F83D, 'M', '吸'), + (0x2F83E, 'M', '呈'), ] - def _seg_77() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x2F841, "M", "哶"), - (0x2F842, "M", "唐"), - (0x2F843, "M", "啓"), - (0x2F844, "M", "啣"), - (0x2F845, "M", "善"), - (0x2F847, "M", "喙"), - (0x2F848, "M", "喫"), - (0x2F849, "M", "喳"), - (0x2F84A, "M", "嗂"), - (0x2F84B, "M", "圖"), - (0x2F84C, "M", "嘆"), - (0x2F84D, "M", "圗"), - (0x2F84E, "M", "噑"), - (0x2F84F, "M", "噴"), - (0x2F850, "M", "切"), - (0x2F851, "M", "壮"), - (0x2F852, "M", "城"), - (0x2F853, "M", "埴"), - (0x2F854, "M", "堍"), - (0x2F855, "M", "型"), - (0x2F856, "M", "堲"), - (0x2F857, "M", "報"), - (0x2F858, "M", "墬"), - (0x2F859, "M", "𡓤"), - (0x2F85A, "M", "売"), - (0x2F85B, "M", "壷"), - (0x2F85C, "M", "夆"), - (0x2F85D, "M", "多"), - (0x2F85E, "M", "夢"), - (0x2F85F, "M", "奢"), - (0x2F860, "M", "𡚨"), - (0x2F861, "M", "𡛪"), - (0x2F862, "M", "姬"), - (0x2F863, "M", "娛"), - (0x2F864, "M", "娧"), - (0x2F865, "M", "姘"), - (0x2F866, "M", "婦"), - (0x2F867, "M", "㛮"), - (0x2F868, "X"), - (0x2F869, "M", "嬈"), - (0x2F86A, "M", "嬾"), - (0x2F86C, "M", "𡧈"), - (0x2F86D, "M", "寃"), - (0x2F86E, "M", "寘"), - (0x2F86F, "M", "寧"), - (0x2F870, "M", "寳"), - (0x2F871, "M", "𡬘"), - (0x2F872, "M", "寿"), - (0x2F873, "M", "将"), - (0x2F874, "X"), - (0x2F875, "M", "尢"), - (0x2F876, "M", "㞁"), - (0x2F877, "M", "屠"), - (0x2F878, "M", "屮"), - (0x2F879, "M", "峀"), - (0x2F87A, "M", "岍"), - (0x2F87B, "M", "𡷤"), - (0x2F87C, "M", "嵃"), - (0x2F87D, "M", "𡷦"), - (0x2F87E, "M", "嵮"), - (0x2F87F, "M", "嵫"), - (0x2F880, "M", "嵼"), - (0x2F881, "M", "巡"), - (0x2F882, "M", "巢"), - (0x2F883, "M", "㠯"), - (0x2F884, "M", "巽"), - (0x2F885, "M", "帨"), - (0x2F886, "M", "帽"), - (0x2F887, "M", "幩"), - (0x2F888, "M", "㡢"), - (0x2F889, "M", "𢆃"), - (0x2F88A, "M", "㡼"), - (0x2F88B, "M", "庰"), - (0x2F88C, "M", "庳"), - (0x2F88D, "M", "庶"), - (0x2F88E, "M", "廊"), - (0x2F88F, "M", "𪎒"), - (0x2F890, "M", "廾"), - (0x2F891, "M", "𢌱"), - (0x2F893, "M", "舁"), - (0x2F894, "M", "弢"), - (0x2F896, "M", "㣇"), - (0x2F897, "M", "𣊸"), - (0x2F898, "M", "𦇚"), - (0x2F899, "M", "形"), - (0x2F89A, "M", "彫"), - (0x2F89B, "M", "㣣"), - (0x2F89C, "M", "徚"), - (0x2F89D, "M", "忍"), - (0x2F89E, "M", "志"), - (0x2F89F, "M", "忹"), - (0x2F8A0, "M", "悁"), - (0x2F8A1, "M", "㤺"), - (0x2F8A2, "M", "㤜"), - (0x2F8A3, "M", "悔"), - (0x2F8A4, "M", "𢛔"), - (0x2F8A5, "M", "惇"), - (0x2F8A6, "M", "慈"), - (0x2F8A7, "M", "慌"), - (0x2F8A8, "M", "慎"), + (0x2F83F, 'M', '周'), + (0x2F840, 'M', '咢'), + (0x2F841, 'M', '哶'), + (0x2F842, 'M', '唐'), + (0x2F843, 'M', '啓'), + (0x2F844, 'M', '啣'), + (0x2F845, 'M', '善'), + (0x2F847, 'M', '喙'), + (0x2F848, 'M', '喫'), + (0x2F849, 'M', '喳'), + (0x2F84A, 'M', '嗂'), + (0x2F84B, 'M', '圖'), + (0x2F84C, 'M', '嘆'), + (0x2F84D, 'M', '圗'), + (0x2F84E, 'M', '噑'), + (0x2F84F, 'M', '噴'), + (0x2F850, 'M', '切'), + (0x2F851, 'M', '壮'), + (0x2F852, 'M', '城'), + (0x2F853, 'M', '埴'), + (0x2F854, 'M', '堍'), + (0x2F855, 'M', '型'), + (0x2F856, 'M', '堲'), + (0x2F857, 'M', '報'), + (0x2F858, 'M', '墬'), + (0x2F859, 'M', '𡓤'), + (0x2F85A, 'M', '売'), + (0x2F85B, 'M', '壷'), + (0x2F85C, 'M', '夆'), + (0x2F85D, 'M', '多'), + (0x2F85E, 'M', '夢'), + (0x2F85F, 'M', '奢'), + (0x2F860, 'M', '𡚨'), + (0x2F861, 'M', '𡛪'), + (0x2F862, 'M', '姬'), + (0x2F863, 'M', '娛'), + (0x2F864, 'M', '娧'), + (0x2F865, 'M', '姘'), + (0x2F866, 'M', '婦'), + (0x2F867, 'M', '㛮'), + (0x2F868, 'X'), + (0x2F869, 'M', '嬈'), + (0x2F86A, 'M', '嬾'), + (0x2F86C, 'M', '𡧈'), + (0x2F86D, 'M', '寃'), + (0x2F86E, 'M', '寘'), + (0x2F86F, 'M', '寧'), + (0x2F870, 'M', '寳'), + (0x2F871, 'M', '𡬘'), + (0x2F872, 'M', '寿'), + (0x2F873, 'M', '将'), + (0x2F874, 'X'), + (0x2F875, 'M', '尢'), + (0x2F876, 'M', '㞁'), + (0x2F877, 'M', '屠'), + (0x2F878, 'M', '屮'), + (0x2F879, 'M', '峀'), + (0x2F87A, 'M', '岍'), + (0x2F87B, 'M', '𡷤'), + (0x2F87C, 'M', '嵃'), + (0x2F87D, 'M', '𡷦'), + (0x2F87E, 'M', '嵮'), + (0x2F87F, 'M', '嵫'), + (0x2F880, 'M', '嵼'), + (0x2F881, 'M', '巡'), + (0x2F882, 'M', '巢'), + (0x2F883, 'M', '㠯'), + (0x2F884, 'M', '巽'), + (0x2F885, 'M', '帨'), + (0x2F886, 'M', '帽'), + (0x2F887, 'M', '幩'), + (0x2F888, 'M', '㡢'), + (0x2F889, 'M', '𢆃'), + (0x2F88A, 'M', '㡼'), + (0x2F88B, 'M', '庰'), + (0x2F88C, 'M', '庳'), + (0x2F88D, 'M', '庶'), + (0x2F88E, 'M', '廊'), + (0x2F88F, 'M', '𪎒'), + (0x2F890, 'M', '廾'), + (0x2F891, 'M', '𢌱'), + (0x2F893, 'M', '舁'), + (0x2F894, 'M', '弢'), + (0x2F896, 'M', '㣇'), + (0x2F897, 'M', '𣊸'), + (0x2F898, 'M', '𦇚'), + (0x2F899, 'M', '形'), + (0x2F89A, 'M', '彫'), + (0x2F89B, 'M', '㣣'), + (0x2F89C, 'M', '徚'), + (0x2F89D, 'M', '忍'), + (0x2F89E, 'M', '志'), + (0x2F89F, 'M', '忹'), + (0x2F8A0, 'M', '悁'), + (0x2F8A1, 'M', '㤺'), + (0x2F8A2, 'M', '㤜'), + (0x2F8A3, 'M', '悔'), + (0x2F8A4, 'M', '𢛔'), + (0x2F8A5, 'M', '惇'), + (0x2F8A6, 'M', '慈'), ] - def _seg_78() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x2F8A9, "M", "慌"), - (0x2F8AA, "M", "慺"), - (0x2F8AB, "M", "憎"), - (0x2F8AC, "M", "憲"), - (0x2F8AD, "M", "憤"), - (0x2F8AE, "M", "憯"), - (0x2F8AF, "M", "懞"), - (0x2F8B0, "M", "懲"), - (0x2F8B1, "M", "懶"), - (0x2F8B2, "M", "成"), - (0x2F8B3, "M", "戛"), - (0x2F8B4, "M", "扝"), - (0x2F8B5, "M", "抱"), - (0x2F8B6, "M", "拔"), - (0x2F8B7, "M", "捐"), - (0x2F8B8, "M", "𢬌"), - (0x2F8B9, "M", "挽"), - (0x2F8BA, "M", "拼"), - (0x2F8BB, "M", "捨"), - (0x2F8BC, "M", "掃"), - (0x2F8BD, "M", "揤"), - (0x2F8BE, "M", "𢯱"), - (0x2F8BF, "M", "搢"), - (0x2F8C0, "M", "揅"), - (0x2F8C1, "M", "掩"), - (0x2F8C2, "M", "㨮"), - (0x2F8C3, "M", "摩"), - (0x2F8C4, "M", "摾"), - (0x2F8C5, "M", "撝"), - (0x2F8C6, "M", "摷"), - (0x2F8C7, "M", "㩬"), - (0x2F8C8, "M", "敏"), - (0x2F8C9, "M", "敬"), - (0x2F8CA, "M", "𣀊"), - (0x2F8CB, "M", "旣"), - (0x2F8CC, "M", "書"), - (0x2F8CD, "M", "晉"), - (0x2F8CE, "M", "㬙"), - (0x2F8CF, "M", "暑"), - (0x2F8D0, "M", "㬈"), - (0x2F8D1, "M", "㫤"), - (0x2F8D2, "M", "冒"), - (0x2F8D3, "M", "冕"), - (0x2F8D4, "M", "最"), - (0x2F8D5, "M", "暜"), - (0x2F8D6, "M", "肭"), - (0x2F8D7, "M", "䏙"), - (0x2F8D8, "M", "朗"), - (0x2F8D9, "M", "望"), - (0x2F8DA, "M", "朡"), - (0x2F8DB, "M", "杞"), - (0x2F8DC, "M", "杓"), - (0x2F8DD, "M", "𣏃"), - (0x2F8DE, "M", "㭉"), - (0x2F8DF, "M", "柺"), - (0x2F8E0, "M", "枅"), - (0x2F8E1, "M", "桒"), - (0x2F8E2, "M", "梅"), - (0x2F8E3, "M", "𣑭"), - (0x2F8E4, "M", "梎"), - (0x2F8E5, "M", "栟"), - (0x2F8E6, "M", "椔"), - (0x2F8E7, "M", "㮝"), - (0x2F8E8, "M", "楂"), - (0x2F8E9, "M", "榣"), - (0x2F8EA, "M", "槪"), - (0x2F8EB, "M", "檨"), - (0x2F8EC, "M", "𣚣"), - (0x2F8ED, "M", "櫛"), - (0x2F8EE, "M", "㰘"), - (0x2F8EF, "M", "次"), - (0x2F8F0, "M", "𣢧"), - (0x2F8F1, "M", "歔"), - (0x2F8F2, "M", "㱎"), - (0x2F8F3, "M", "歲"), - (0x2F8F4, "M", "殟"), - (0x2F8F5, "M", "殺"), - (0x2F8F6, "M", "殻"), - (0x2F8F7, "M", "𣪍"), - (0x2F8F8, "M", "𡴋"), - (0x2F8F9, "M", "𣫺"), - (0x2F8FA, "M", "汎"), - (0x2F8FB, "M", "𣲼"), - (0x2F8FC, "M", "沿"), - (0x2F8FD, "M", "泍"), - (0x2F8FE, "M", "汧"), - (0x2F8FF, "M", "洖"), - (0x2F900, "M", "派"), - (0x2F901, "M", "海"), - (0x2F902, "M", "流"), - (0x2F903, "M", "浩"), - (0x2F904, "M", "浸"), - (0x2F905, "M", "涅"), - (0x2F906, "M", "𣴞"), - (0x2F907, "M", "洴"), - (0x2F908, "M", "港"), - (0x2F909, "M", "湮"), - (0x2F90A, "M", "㴳"), - (0x2F90B, "M", "滋"), - (0x2F90C, "M", "滇"), + (0x2F8A7, 'M', '慌'), + (0x2F8A8, 'M', '慎'), + (0x2F8A9, 'M', '慌'), + (0x2F8AA, 'M', '慺'), + (0x2F8AB, 'M', '憎'), + (0x2F8AC, 'M', '憲'), + (0x2F8AD, 'M', '憤'), + (0x2F8AE, 'M', '憯'), + (0x2F8AF, 'M', '懞'), + (0x2F8B0, 'M', '懲'), + (0x2F8B1, 'M', '懶'), + (0x2F8B2, 'M', '成'), + (0x2F8B3, 'M', '戛'), + (0x2F8B4, 'M', '扝'), + (0x2F8B5, 'M', '抱'), + (0x2F8B6, 'M', '拔'), + (0x2F8B7, 'M', '捐'), + (0x2F8B8, 'M', '𢬌'), + (0x2F8B9, 'M', '挽'), + (0x2F8BA, 'M', '拼'), + (0x2F8BB, 'M', '捨'), + (0x2F8BC, 'M', '掃'), + (0x2F8BD, 'M', '揤'), + (0x2F8BE, 'M', '𢯱'), + (0x2F8BF, 'M', '搢'), + (0x2F8C0, 'M', '揅'), + (0x2F8C1, 'M', '掩'), + (0x2F8C2, 'M', '㨮'), + (0x2F8C3, 'M', '摩'), + (0x2F8C4, 'M', '摾'), + (0x2F8C5, 'M', '撝'), + (0x2F8C6, 'M', '摷'), + (0x2F8C7, 'M', '㩬'), + (0x2F8C8, 'M', '敏'), + (0x2F8C9, 'M', '敬'), + (0x2F8CA, 'M', '𣀊'), + (0x2F8CB, 'M', '旣'), + (0x2F8CC, 'M', '書'), + (0x2F8CD, 'M', '晉'), + (0x2F8CE, 'M', '㬙'), + (0x2F8CF, 'M', '暑'), + (0x2F8D0, 'M', '㬈'), + (0x2F8D1, 'M', '㫤'), + (0x2F8D2, 'M', '冒'), + (0x2F8D3, 'M', '冕'), + (0x2F8D4, 'M', '最'), + (0x2F8D5, 'M', '暜'), + (0x2F8D6, 'M', '肭'), + (0x2F8D7, 'M', '䏙'), + (0x2F8D8, 'M', '朗'), + (0x2F8D9, 'M', '望'), + (0x2F8DA, 'M', '朡'), + (0x2F8DB, 'M', '杞'), + (0x2F8DC, 'M', '杓'), + (0x2F8DD, 'M', '𣏃'), + (0x2F8DE, 'M', '㭉'), + (0x2F8DF, 'M', '柺'), + (0x2F8E0, 'M', '枅'), + (0x2F8E1, 'M', '桒'), + (0x2F8E2, 'M', '梅'), + (0x2F8E3, 'M', '𣑭'), + (0x2F8E4, 'M', '梎'), + (0x2F8E5, 'M', '栟'), + (0x2F8E6, 'M', '椔'), + (0x2F8E7, 'M', '㮝'), + (0x2F8E8, 'M', '楂'), + (0x2F8E9, 'M', '榣'), + (0x2F8EA, 'M', '槪'), + (0x2F8EB, 'M', '檨'), + (0x2F8EC, 'M', '𣚣'), + (0x2F8ED, 'M', '櫛'), + (0x2F8EE, 'M', '㰘'), + (0x2F8EF, 'M', '次'), + (0x2F8F0, 'M', '𣢧'), + (0x2F8F1, 'M', '歔'), + (0x2F8F2, 'M', '㱎'), + (0x2F8F3, 'M', '歲'), + (0x2F8F4, 'M', '殟'), + (0x2F8F5, 'M', '殺'), + (0x2F8F6, 'M', '殻'), + (0x2F8F7, 'M', '𣪍'), + (0x2F8F8, 'M', '𡴋'), + (0x2F8F9, 'M', '𣫺'), + (0x2F8FA, 'M', '汎'), + (0x2F8FB, 'M', '𣲼'), + (0x2F8FC, 'M', '沿'), + (0x2F8FD, 'M', '泍'), + (0x2F8FE, 'M', '汧'), + (0x2F8FF, 'M', '洖'), + (0x2F900, 'M', '派'), + (0x2F901, 'M', '海'), + (0x2F902, 'M', '流'), + (0x2F903, 'M', '浩'), + (0x2F904, 'M', '浸'), + (0x2F905, 'M', '涅'), + (0x2F906, 'M', '𣴞'), + (0x2F907, 'M', '洴'), + (0x2F908, 'M', '港'), + (0x2F909, 'M', '湮'), + (0x2F90A, 'M', '㴳'), ] - def _seg_79() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x2F90D, "M", "𣻑"), - (0x2F90E, "M", "淹"), - (0x2F90F, "M", "潮"), - (0x2F910, "M", "𣽞"), - (0x2F911, "M", "𣾎"), - (0x2F912, "M", "濆"), - (0x2F913, "M", "瀹"), - (0x2F914, "M", "瀞"), - (0x2F915, "M", "瀛"), - (0x2F916, "M", "㶖"), - (0x2F917, "M", "灊"), - (0x2F918, "M", "災"), - (0x2F919, "M", "灷"), - (0x2F91A, "M", "炭"), - (0x2F91B, "M", "𠔥"), - (0x2F91C, "M", "煅"), - (0x2F91D, "M", "𤉣"), - (0x2F91E, "M", "熜"), - (0x2F91F, "X"), - (0x2F920, "M", "爨"), - (0x2F921, "M", "爵"), - (0x2F922, "M", "牐"), - (0x2F923, "M", "𤘈"), - (0x2F924, "M", "犀"), - (0x2F925, "M", "犕"), - (0x2F926, "M", "𤜵"), - (0x2F927, "M", "𤠔"), - (0x2F928, "M", "獺"), - (0x2F929, "M", "王"), - (0x2F92A, "M", "㺬"), - (0x2F92B, "M", "玥"), - (0x2F92C, "M", "㺸"), - (0x2F92E, "M", "瑇"), - (0x2F92F, "M", "瑜"), - (0x2F930, "M", "瑱"), - (0x2F931, "M", "璅"), - (0x2F932, "M", "瓊"), - (0x2F933, "M", "㼛"), - (0x2F934, "M", "甤"), - (0x2F935, "M", "𤰶"), - (0x2F936, "M", "甾"), - (0x2F937, "M", "𤲒"), - (0x2F938, "M", "異"), - (0x2F939, "M", "𢆟"), - (0x2F93A, "M", "瘐"), - (0x2F93B, "M", "𤾡"), - (0x2F93C, "M", "𤾸"), - (0x2F93D, "M", "𥁄"), - (0x2F93E, "M", "㿼"), - (0x2F93F, "M", "䀈"), - (0x2F940, "M", "直"), - (0x2F941, "M", "𥃳"), - (0x2F942, "M", "𥃲"), - (0x2F943, "M", "𥄙"), - (0x2F944, "M", "𥄳"), - (0x2F945, "M", "眞"), - (0x2F946, "M", "真"), - (0x2F948, "M", "睊"), - (0x2F949, "M", "䀹"), - (0x2F94A, "M", "瞋"), - (0x2F94B, "M", "䁆"), - (0x2F94C, "M", "䂖"), - (0x2F94D, "M", "𥐝"), - (0x2F94E, "M", "硎"), - (0x2F94F, "M", "碌"), - (0x2F950, "M", "磌"), - (0x2F951, "M", "䃣"), - (0x2F952, "M", "𥘦"), - (0x2F953, "M", "祖"), - (0x2F954, "M", "𥚚"), - (0x2F955, "M", "𥛅"), - (0x2F956, "M", "福"), - (0x2F957, "M", "秫"), - (0x2F958, "M", "䄯"), - (0x2F959, "M", "穀"), - (0x2F95A, "M", "穊"), - (0x2F95B, "M", "穏"), - (0x2F95C, "M", "𥥼"), - (0x2F95D, "M", "𥪧"), - (0x2F95F, "X"), - (0x2F960, "M", "䈂"), - (0x2F961, "M", "𥮫"), - (0x2F962, "M", "篆"), - (0x2F963, "M", "築"), - (0x2F964, "M", "䈧"), - (0x2F965, "M", "𥲀"), - (0x2F966, "M", "糒"), - (0x2F967, "M", "䊠"), - (0x2F968, "M", "糨"), - (0x2F969, "M", "糣"), - (0x2F96A, "M", "紀"), - (0x2F96B, "M", "𥾆"), - (0x2F96C, "M", "絣"), - (0x2F96D, "M", "䌁"), - (0x2F96E, "M", "緇"), - (0x2F96F, "M", "縂"), - (0x2F970, "M", "繅"), - (0x2F971, "M", "䌴"), - (0x2F972, "M", "𦈨"), - (0x2F973, "M", "𦉇"), + (0x2F90B, 'M', '滋'), + (0x2F90C, 'M', '滇'), + (0x2F90D, 'M', '𣻑'), + (0x2F90E, 'M', '淹'), + (0x2F90F, 'M', '潮'), + (0x2F910, 'M', '𣽞'), + (0x2F911, 'M', '𣾎'), + (0x2F912, 'M', '濆'), + (0x2F913, 'M', '瀹'), + (0x2F914, 'M', '瀞'), + (0x2F915, 'M', '瀛'), + (0x2F916, 'M', '㶖'), + (0x2F917, 'M', '灊'), + (0x2F918, 'M', '災'), + (0x2F919, 'M', '灷'), + (0x2F91A, 'M', '炭'), + (0x2F91B, 'M', '𠔥'), + (0x2F91C, 'M', '煅'), + (0x2F91D, 'M', '𤉣'), + (0x2F91E, 'M', '熜'), + (0x2F91F, 'X'), + (0x2F920, 'M', '爨'), + (0x2F921, 'M', '爵'), + (0x2F922, 'M', '牐'), + (0x2F923, 'M', '𤘈'), + (0x2F924, 'M', '犀'), + (0x2F925, 'M', '犕'), + (0x2F926, 'M', '𤜵'), + (0x2F927, 'M', '𤠔'), + (0x2F928, 'M', '獺'), + (0x2F929, 'M', '王'), + (0x2F92A, 'M', '㺬'), + (0x2F92B, 'M', '玥'), + (0x2F92C, 'M', '㺸'), + (0x2F92E, 'M', '瑇'), + (0x2F92F, 'M', '瑜'), + (0x2F930, 'M', '瑱'), + (0x2F931, 'M', '璅'), + (0x2F932, 'M', '瓊'), + (0x2F933, 'M', '㼛'), + (0x2F934, 'M', '甤'), + (0x2F935, 'M', '𤰶'), + (0x2F936, 'M', '甾'), + (0x2F937, 'M', '𤲒'), + (0x2F938, 'M', '異'), + (0x2F939, 'M', '𢆟'), + (0x2F93A, 'M', '瘐'), + (0x2F93B, 'M', '𤾡'), + (0x2F93C, 'M', '𤾸'), + (0x2F93D, 'M', '𥁄'), + (0x2F93E, 'M', '㿼'), + (0x2F93F, 'M', '䀈'), + (0x2F940, 'M', '直'), + (0x2F941, 'M', '𥃳'), + (0x2F942, 'M', '𥃲'), + (0x2F943, 'M', '𥄙'), + (0x2F944, 'M', '𥄳'), + (0x2F945, 'M', '眞'), + (0x2F946, 'M', '真'), + (0x2F948, 'M', '睊'), + (0x2F949, 'M', '䀹'), + (0x2F94A, 'M', '瞋'), + (0x2F94B, 'M', '䁆'), + (0x2F94C, 'M', '䂖'), + (0x2F94D, 'M', '𥐝'), + (0x2F94E, 'M', '硎'), + (0x2F94F, 'M', '碌'), + (0x2F950, 'M', '磌'), + (0x2F951, 'M', '䃣'), + (0x2F952, 'M', '𥘦'), + (0x2F953, 'M', '祖'), + (0x2F954, 'M', '𥚚'), + (0x2F955, 'M', '𥛅'), + (0x2F956, 'M', '福'), + (0x2F957, 'M', '秫'), + (0x2F958, 'M', '䄯'), + (0x2F959, 'M', '穀'), + (0x2F95A, 'M', '穊'), + (0x2F95B, 'M', '穏'), + (0x2F95C, 'M', '𥥼'), + (0x2F95D, 'M', '𥪧'), + (0x2F95F, 'X'), + (0x2F960, 'M', '䈂'), + (0x2F961, 'M', '𥮫'), + (0x2F962, 'M', '篆'), + (0x2F963, 'M', '築'), + (0x2F964, 'M', '䈧'), + (0x2F965, 'M', '𥲀'), + (0x2F966, 'M', '糒'), + (0x2F967, 'M', '䊠'), + (0x2F968, 'M', '糨'), + (0x2F969, 'M', '糣'), + (0x2F96A, 'M', '紀'), + (0x2F96B, 'M', '𥾆'), + (0x2F96C, 'M', '絣'), + (0x2F96D, 'M', '䌁'), + (0x2F96E, 'M', '緇'), + (0x2F96F, 'M', '縂'), + (0x2F970, 'M', '繅'), + (0x2F971, 'M', '䌴'), ] - def _seg_80() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x2F974, "M", "䍙"), - (0x2F975, "M", "𦋙"), - (0x2F976, "M", "罺"), - (0x2F977, "M", "𦌾"), - (0x2F978, "M", "羕"), - (0x2F979, "M", "翺"), - (0x2F97A, "M", "者"), - (0x2F97B, "M", "𦓚"), - (0x2F97C, "M", "𦔣"), - (0x2F97D, "M", "聠"), - (0x2F97E, "M", "𦖨"), - (0x2F97F, "M", "聰"), - (0x2F980, "M", "𣍟"), - (0x2F981, "M", "䏕"), - (0x2F982, "M", "育"), - (0x2F983, "M", "脃"), - (0x2F984, "M", "䐋"), - (0x2F985, "M", "脾"), - (0x2F986, "M", "媵"), - (0x2F987, "M", "𦞧"), - (0x2F988, "M", "𦞵"), - (0x2F989, "M", "𣎓"), - (0x2F98A, "M", "𣎜"), - (0x2F98B, "M", "舁"), - (0x2F98C, "M", "舄"), - (0x2F98D, "M", "辞"), - (0x2F98E, "M", "䑫"), - (0x2F98F, "M", "芑"), - (0x2F990, "M", "芋"), - (0x2F991, "M", "芝"), - (0x2F992, "M", "劳"), - (0x2F993, "M", "花"), - (0x2F994, "M", "芳"), - (0x2F995, "M", "芽"), - (0x2F996, "M", "苦"), - (0x2F997, "M", "𦬼"), - (0x2F998, "M", "若"), - (0x2F999, "M", "茝"), - (0x2F99A, "M", "荣"), - (0x2F99B, "M", "莭"), - (0x2F99C, "M", "茣"), - (0x2F99D, "M", "莽"), - (0x2F99E, "M", "菧"), - (0x2F99F, "M", "著"), - (0x2F9A0, "M", "荓"), - (0x2F9A1, "M", "菊"), - (0x2F9A2, "M", "菌"), - (0x2F9A3, "M", "菜"), - (0x2F9A4, "M", "𦰶"), - (0x2F9A5, "M", "𦵫"), - (0x2F9A6, "M", "𦳕"), - (0x2F9A7, "M", "䔫"), - (0x2F9A8, "M", "蓱"), - (0x2F9A9, "M", "蓳"), - (0x2F9AA, "M", "蔖"), - (0x2F9AB, "M", "𧏊"), - (0x2F9AC, "M", "蕤"), - (0x2F9AD, "M", "𦼬"), - (0x2F9AE, "M", "䕝"), - (0x2F9AF, "M", "䕡"), - (0x2F9B0, "M", "𦾱"), - (0x2F9B1, "M", "𧃒"), - (0x2F9B2, "M", "䕫"), - (0x2F9B3, "M", "虐"), - (0x2F9B4, "M", "虜"), - (0x2F9B5, "M", "虧"), - (0x2F9B6, "M", "虩"), - (0x2F9B7, "M", "蚩"), - (0x2F9B8, "M", "蚈"), - (0x2F9B9, "M", "蜎"), - (0x2F9BA, "M", "蛢"), - (0x2F9BB, "M", "蝹"), - (0x2F9BC, "M", "蜨"), - (0x2F9BD, "M", "蝫"), - (0x2F9BE, "M", "螆"), - (0x2F9BF, "X"), - (0x2F9C0, "M", "蟡"), - (0x2F9C1, "M", "蠁"), - (0x2F9C2, "M", "䗹"), - (0x2F9C3, "M", "衠"), - (0x2F9C4, "M", "衣"), - (0x2F9C5, "M", "𧙧"), - (0x2F9C6, "M", "裗"), - (0x2F9C7, "M", "裞"), - (0x2F9C8, "M", "䘵"), - (0x2F9C9, "M", "裺"), - (0x2F9CA, "M", "㒻"), - (0x2F9CB, "M", "𧢮"), - (0x2F9CC, "M", "𧥦"), - (0x2F9CD, "M", "䚾"), - (0x2F9CE, "M", "䛇"), - (0x2F9CF, "M", "誠"), - (0x2F9D0, "M", "諭"), - (0x2F9D1, "M", "變"), - (0x2F9D2, "M", "豕"), - (0x2F9D3, "M", "𧲨"), - (0x2F9D4, "M", "貫"), - (0x2F9D5, "M", "賁"), - (0x2F9D6, "M", "贛"), - (0x2F9D7, "M", "起"), + (0x2F972, 'M', '𦈨'), + (0x2F973, 'M', '𦉇'), + (0x2F974, 'M', '䍙'), + (0x2F975, 'M', '𦋙'), + (0x2F976, 'M', '罺'), + (0x2F977, 'M', '𦌾'), + (0x2F978, 'M', '羕'), + (0x2F979, 'M', '翺'), + (0x2F97A, 'M', '者'), + (0x2F97B, 'M', '𦓚'), + (0x2F97C, 'M', '𦔣'), + (0x2F97D, 'M', '聠'), + (0x2F97E, 'M', '𦖨'), + (0x2F97F, 'M', '聰'), + (0x2F980, 'M', '𣍟'), + (0x2F981, 'M', '䏕'), + (0x2F982, 'M', '育'), + (0x2F983, 'M', '脃'), + (0x2F984, 'M', '䐋'), + (0x2F985, 'M', '脾'), + (0x2F986, 'M', '媵'), + (0x2F987, 'M', '𦞧'), + (0x2F988, 'M', '𦞵'), + (0x2F989, 'M', '𣎓'), + (0x2F98A, 'M', '𣎜'), + (0x2F98B, 'M', '舁'), + (0x2F98C, 'M', '舄'), + (0x2F98D, 'M', '辞'), + (0x2F98E, 'M', '䑫'), + (0x2F98F, 'M', '芑'), + (0x2F990, 'M', '芋'), + (0x2F991, 'M', '芝'), + (0x2F992, 'M', '劳'), + (0x2F993, 'M', '花'), + (0x2F994, 'M', '芳'), + (0x2F995, 'M', '芽'), + (0x2F996, 'M', '苦'), + (0x2F997, 'M', '𦬼'), + (0x2F998, 'M', '若'), + (0x2F999, 'M', '茝'), + (0x2F99A, 'M', '荣'), + (0x2F99B, 'M', '莭'), + (0x2F99C, 'M', '茣'), + (0x2F99D, 'M', '莽'), + (0x2F99E, 'M', '菧'), + (0x2F99F, 'M', '著'), + (0x2F9A0, 'M', '荓'), + (0x2F9A1, 'M', '菊'), + (0x2F9A2, 'M', '菌'), + (0x2F9A3, 'M', '菜'), + (0x2F9A4, 'M', '𦰶'), + (0x2F9A5, 'M', '𦵫'), + (0x2F9A6, 'M', '𦳕'), + (0x2F9A7, 'M', '䔫'), + (0x2F9A8, 'M', '蓱'), + (0x2F9A9, 'M', '蓳'), + (0x2F9AA, 'M', '蔖'), + (0x2F9AB, 'M', '𧏊'), + (0x2F9AC, 'M', '蕤'), + (0x2F9AD, 'M', '𦼬'), + (0x2F9AE, 'M', '䕝'), + (0x2F9AF, 'M', '䕡'), + (0x2F9B0, 'M', '𦾱'), + (0x2F9B1, 'M', '𧃒'), + (0x2F9B2, 'M', '䕫'), + (0x2F9B3, 'M', '虐'), + (0x2F9B4, 'M', '虜'), + (0x2F9B5, 'M', '虧'), + (0x2F9B6, 'M', '虩'), + (0x2F9B7, 'M', '蚩'), + (0x2F9B8, 'M', '蚈'), + (0x2F9B9, 'M', '蜎'), + (0x2F9BA, 'M', '蛢'), + (0x2F9BB, 'M', '蝹'), + (0x2F9BC, 'M', '蜨'), + (0x2F9BD, 'M', '蝫'), + (0x2F9BE, 'M', '螆'), + (0x2F9BF, 'X'), + (0x2F9C0, 'M', '蟡'), + (0x2F9C1, 'M', '蠁'), + (0x2F9C2, 'M', '䗹'), + (0x2F9C3, 'M', '衠'), + (0x2F9C4, 'M', '衣'), + (0x2F9C5, 'M', '𧙧'), + (0x2F9C6, 'M', '裗'), + (0x2F9C7, 'M', '裞'), + (0x2F9C8, 'M', '䘵'), + (0x2F9C9, 'M', '裺'), + (0x2F9CA, 'M', '㒻'), + (0x2F9CB, 'M', '𧢮'), + (0x2F9CC, 'M', '𧥦'), + (0x2F9CD, 'M', '䚾'), + (0x2F9CE, 'M', '䛇'), + (0x2F9CF, 'M', '誠'), + (0x2F9D0, 'M', '諭'), + (0x2F9D1, 'M', '變'), + (0x2F9D2, 'M', '豕'), + (0x2F9D3, 'M', '𧲨'), + (0x2F9D4, 'M', '貫'), + (0x2F9D5, 'M', '賁'), ] - def _seg_81() -> List[Union[Tuple[int, str], Tuple[int, str, str]]]: return [ - (0x2F9D8, "M", "𧼯"), - (0x2F9D9, "M", "𠠄"), - (0x2F9DA, "M", "跋"), - (0x2F9DB, "M", "趼"), - (0x2F9DC, "M", "跰"), - (0x2F9DD, "M", "𠣞"), - (0x2F9DE, "M", "軔"), - (0x2F9DF, "M", "輸"), - (0x2F9E0, "M", "𨗒"), - (0x2F9E1, "M", "𨗭"), - (0x2F9E2, "M", "邔"), - (0x2F9E3, "M", "郱"), - (0x2F9E4, "M", "鄑"), - (0x2F9E5, "M", "𨜮"), - (0x2F9E6, "M", "鄛"), - (0x2F9E7, "M", "鈸"), - (0x2F9E8, "M", "鋗"), - (0x2F9E9, "M", "鋘"), - (0x2F9EA, "M", "鉼"), - (0x2F9EB, "M", "鏹"), - (0x2F9EC, "M", "鐕"), - (0x2F9ED, "M", "𨯺"), - (0x2F9EE, "M", "開"), - (0x2F9EF, "M", "䦕"), - (0x2F9F0, "M", "閷"), - (0x2F9F1, "M", "𨵷"), - (0x2F9F2, "M", "䧦"), - (0x2F9F3, "M", "雃"), - (0x2F9F4, "M", "嶲"), - (0x2F9F5, "M", "霣"), - (0x2F9F6, "M", "𩅅"), - (0x2F9F7, "M", "𩈚"), - (0x2F9F8, "M", "䩮"), - (0x2F9F9, "M", "䩶"), - (0x2F9FA, "M", "韠"), - (0x2F9FB, "M", "𩐊"), - (0x2F9FC, "M", "䪲"), - (0x2F9FD, "M", "𩒖"), - (0x2F9FE, "M", "頋"), - (0x2FA00, "M", "頩"), - (0x2FA01, "M", "𩖶"), - (0x2FA02, "M", "飢"), - (0x2FA03, "M", "䬳"), - (0x2FA04, "M", "餩"), - (0x2FA05, "M", "馧"), - (0x2FA06, "M", "駂"), - (0x2FA07, "M", "駾"), - (0x2FA08, "M", "䯎"), - (0x2FA09, "M", "𩬰"), - (0x2FA0A, "M", "鬒"), - (0x2FA0B, "M", "鱀"), - (0x2FA0C, "M", "鳽"), - (0x2FA0D, "M", "䳎"), - (0x2FA0E, "M", "䳭"), - (0x2FA0F, "M", "鵧"), - (0x2FA10, "M", "𪃎"), - (0x2FA11, "M", "䳸"), - (0x2FA12, "M", "𪄅"), - (0x2FA13, "M", "𪈎"), - (0x2FA14, "M", "𪊑"), - (0x2FA15, "M", "麻"), - (0x2FA16, "M", "䵖"), - (0x2FA17, "M", "黹"), - (0x2FA18, "M", "黾"), - (0x2FA19, "M", "鼅"), - (0x2FA1A, "M", "鼏"), - (0x2FA1B, "M", "鼖"), - (0x2FA1C, "M", "鼻"), - (0x2FA1D, "M", "𪘀"), - (0x2FA1E, "X"), - (0x30000, "V"), - (0x3134B, "X"), - (0x31350, "V"), - (0x323B0, "X"), - (0xE0100, "I"), - (0xE01F0, "X"), + (0x2F9D6, 'M', '贛'), + (0x2F9D7, 'M', '起'), + (0x2F9D8, 'M', '𧼯'), + (0x2F9D9, 'M', '𠠄'), + (0x2F9DA, 'M', '跋'), + (0x2F9DB, 'M', '趼'), + (0x2F9DC, 'M', '跰'), + (0x2F9DD, 'M', '𠣞'), + (0x2F9DE, 'M', '軔'), + (0x2F9DF, 'M', '輸'), + (0x2F9E0, 'M', '𨗒'), + (0x2F9E1, 'M', '𨗭'), + (0x2F9E2, 'M', '邔'), + (0x2F9E3, 'M', '郱'), + (0x2F9E4, 'M', '鄑'), + (0x2F9E5, 'M', '𨜮'), + (0x2F9E6, 'M', '鄛'), + (0x2F9E7, 'M', '鈸'), + (0x2F9E8, 'M', '鋗'), + (0x2F9E9, 'M', '鋘'), + (0x2F9EA, 'M', '鉼'), + (0x2F9EB, 'M', '鏹'), + (0x2F9EC, 'M', '鐕'), + (0x2F9ED, 'M', '𨯺'), + (0x2F9EE, 'M', '開'), + (0x2F9EF, 'M', '䦕'), + (0x2F9F0, 'M', '閷'), + (0x2F9F1, 'M', '𨵷'), + (0x2F9F2, 'M', '䧦'), + (0x2F9F3, 'M', '雃'), + (0x2F9F4, 'M', '嶲'), + (0x2F9F5, 'M', '霣'), + (0x2F9F6, 'M', '𩅅'), + (0x2F9F7, 'M', '𩈚'), + (0x2F9F8, 'M', '䩮'), + (0x2F9F9, 'M', '䩶'), + (0x2F9FA, 'M', '韠'), + (0x2F9FB, 'M', '𩐊'), + (0x2F9FC, 'M', '䪲'), + (0x2F9FD, 'M', '𩒖'), + (0x2F9FE, 'M', '頋'), + (0x2FA00, 'M', '頩'), + (0x2FA01, 'M', '𩖶'), + (0x2FA02, 'M', '飢'), + (0x2FA03, 'M', '䬳'), + (0x2FA04, 'M', '餩'), + (0x2FA05, 'M', '馧'), + (0x2FA06, 'M', '駂'), + (0x2FA07, 'M', '駾'), + (0x2FA08, 'M', '䯎'), + (0x2FA09, 'M', '𩬰'), + (0x2FA0A, 'M', '鬒'), + (0x2FA0B, 'M', '鱀'), + (0x2FA0C, 'M', '鳽'), + (0x2FA0D, 'M', '䳎'), + (0x2FA0E, 'M', '䳭'), + (0x2FA0F, 'M', '鵧'), + (0x2FA10, 'M', '𪃎'), + (0x2FA11, 'M', '䳸'), + (0x2FA12, 'M', '𪄅'), + (0x2FA13, 'M', '𪈎'), + (0x2FA14, 'M', '𪊑'), + (0x2FA15, 'M', '麻'), + (0x2FA16, 'M', '䵖'), + (0x2FA17, 'M', '黹'), + (0x2FA18, 'M', '黾'), + (0x2FA19, 'M', '鼅'), + (0x2FA1A, 'M', '鼏'), + (0x2FA1B, 'M', '鼖'), + (0x2FA1C, 'M', '鼻'), + (0x2FA1D, 'M', '𪘀'), + (0x2FA1E, 'X'), + (0x30000, 'V'), + (0x3134B, 'X'), + (0x31350, 'V'), + (0x323B0, 'X'), + (0xE0100, 'I'), + (0xE01F0, 'X'), ] - uts46data = tuple( _seg_0() + _seg_1() diff --git a/venv1/Lib/site-packages/pip/_vendor/msgpack/__init__.py b/venv1/Lib/site-packages/pip/_vendor/msgpack/__init__.py index f3266b70..1300b866 100644 --- a/venv1/Lib/site-packages/pip/_vendor/msgpack/__init__.py +++ b/venv1/Lib/site-packages/pip/_vendor/msgpack/__init__.py @@ -1,20 +1,22 @@ -# ruff: noqa: F401 +# coding: utf-8 +from .exceptions import * +from .ext import ExtType, Timestamp + import os +import sys -from .exceptions import * # noqa: F403 -from .ext import ExtType, Timestamp -version = (1, 1, 2) -__version__ = "1.1.2" +version = (1, 0, 5) +__version__ = "1.0.5" -if os.environ.get("MSGPACK_PUREPYTHON"): - from .fallback import Packer, Unpacker, unpackb +if os.environ.get("MSGPACK_PUREPYTHON") or sys.version_info[0] == 2: + from .fallback import Packer, unpackb, Unpacker else: try: - from ._cmsgpack import Packer, Unpacker, unpackb + from ._cmsgpack import Packer, unpackb, Unpacker except ImportError: - from .fallback import Packer, Unpacker, unpackb + from .fallback import Packer, unpackb, Unpacker def pack(o, stream, **kwargs): diff --git a/venv1/Lib/site-packages/pip/_vendor/msgpack/ext.py b/venv1/Lib/site-packages/pip/_vendor/msgpack/ext.py index 9694819a..23e0d6b4 100644 --- a/venv1/Lib/site-packages/pip/_vendor/msgpack/ext.py +++ b/venv1/Lib/site-packages/pip/_vendor/msgpack/ext.py @@ -1,6 +1,21 @@ +# coding: utf-8 +from collections import namedtuple import datetime +import sys import struct -from collections import namedtuple + + +PY2 = sys.version_info[0] == 2 + +if PY2: + int_types = (int, long) + _utc = None +else: + int_types = int + try: + _utc = datetime.timezone.utc + except AttributeError: + _utc = datetime.timezone(datetime.timedelta(0)) class ExtType(namedtuple("ExtType", "code data")): @@ -13,15 +28,14 @@ def __new__(cls, code, data): raise TypeError("data must be bytes") if not 0 <= code <= 127: raise ValueError("code must be 0~127") - return super().__new__(cls, code, data) + return super(ExtType, cls).__new__(cls, code, data) -class Timestamp: +class Timestamp(object): """Timestamp represents the Timestamp extension type in msgpack. - When built with Cython, msgpack uses C methods to pack and unpack `Timestamp`. - When using pure-Python msgpack, :func:`to_bytes` and :func:`from_bytes` are used to pack and - unpack `Timestamp`. + When built with Cython, msgpack uses C methods to pack and unpack `Timestamp`. When using pure-Python + msgpack, :func:`to_bytes` and :func:`from_bytes` are used to pack and unpack `Timestamp`. This class is immutable: Do not override seconds and nanoseconds. """ @@ -39,25 +53,31 @@ def __init__(self, seconds, nanoseconds=0): Number of nanoseconds to add to `seconds` to get fractional time. Maximum is 999_999_999. Default is 0. - Note: Negative times (before the UNIX epoch) are represented as neg. seconds + pos. ns. + Note: Negative times (before the UNIX epoch) are represented as negative seconds + positive ns. """ - if not isinstance(seconds, int): + if not isinstance(seconds, int_types): raise TypeError("seconds must be an integer") - if not isinstance(nanoseconds, int): + if not isinstance(nanoseconds, int_types): raise TypeError("nanoseconds must be an integer") if not (0 <= nanoseconds < 10**9): - raise ValueError("nanoseconds must be a non-negative integer less than 999999999.") + raise ValueError( + "nanoseconds must be a non-negative integer less than 999999999." + ) self.seconds = seconds self.nanoseconds = nanoseconds def __repr__(self): """String representation of Timestamp.""" - return f"Timestamp(seconds={self.seconds}, nanoseconds={self.nanoseconds})" + return "Timestamp(seconds={0}, nanoseconds={1})".format( + self.seconds, self.nanoseconds + ) def __eq__(self, other): """Check for equality with another Timestamp object""" if type(other) is self.__class__: - return self.seconds == other.seconds and self.nanoseconds == other.nanoseconds + return ( + self.seconds == other.seconds and self.nanoseconds == other.nanoseconds + ) return False def __ne__(self, other): @@ -120,7 +140,7 @@ def from_unix(unix_sec): """Create a Timestamp from posix timestamp in seconds. :param unix_float: Posix timestamp in seconds. - :type unix_float: int or float + :type unix_float: int or float. """ seconds = int(unix_sec // 1) nanoseconds = int((unix_sec % 1) * 10**9) @@ -154,17 +174,20 @@ def to_unix_nano(self): def to_datetime(self): """Get the timestamp as a UTC datetime. - :rtype: `datetime.datetime` + Python 2 is not supported. + + :rtype: datetime. """ - utc = datetime.timezone.utc - return datetime.datetime.fromtimestamp(0, utc) + datetime.timedelta( - seconds=self.seconds, microseconds=self.nanoseconds // 1000 + return datetime.datetime.fromtimestamp(0, _utc) + datetime.timedelta( + seconds=self.to_unix() ) @staticmethod def from_datetime(dt): """Create a Timestamp from datetime with tzinfo. + Python 2 is not supported. + :rtype: Timestamp """ - return Timestamp(seconds=int(dt.timestamp()), nanoseconds=dt.microsecond * 1000) + return Timestamp.from_unix(dt.timestamp()) diff --git a/venv1/Lib/site-packages/pip/_vendor/msgpack/fallback.py b/venv1/Lib/site-packages/pip/_vendor/msgpack/fallback.py index b02e47cf..e8cebc1b 100644 --- a/venv1/Lib/site-packages/pip/_vendor/msgpack/fallback.py +++ b/venv1/Lib/site-packages/pip/_vendor/msgpack/fallback.py @@ -1,22 +1,60 @@ """Fallback pure Python implementation of msgpack""" - -import struct -import sys from datetime import datetime as _DateTime +import sys +import struct + + +PY2 = sys.version_info[0] == 2 +if PY2: + int_types = (int, long) + + def dict_iteritems(d): + return d.iteritems() + +else: + int_types = int + unicode = str + xrange = range + + def dict_iteritems(d): + return d.items() + + +if sys.version_info < (3, 5): + # Ugly hack... + RecursionError = RuntimeError + + def _is_recursionerror(e): + return ( + len(e.args) == 1 + and isinstance(e.args[0], str) + and e.args[0].startswith("maximum recursion depth exceeded") + ) + +else: + + def _is_recursionerror(e): + return True + if hasattr(sys, "pypy_version_info"): + # StringIO is slow on PyPy, StringIO is faster. However: PyPy's own + # StringBuilder is fastest. from __pypy__ import newlist_hint - from __pypy__.builders import BytesBuilder - _USING_STRINGBUILDER = True + try: + from __pypy__.builders import BytesBuilder as StringBuilder + except ImportError: + from __pypy__.builders import StringBuilder + USING_STRINGBUILDER = True - class BytesIO: + class StringIO(object): def __init__(self, s=b""): if s: - self.builder = BytesBuilder(len(s)) + self.builder = StringBuilder(len(s)) self.builder.append(s) else: - self.builder = BytesBuilder() + self.builder = StringBuilder() def write(self, s): if isinstance(s, memoryview): @@ -29,17 +67,17 @@ def getvalue(self): return self.builder.build() else: - from io import BytesIO + USING_STRINGBUILDER = False + from io import BytesIO as StringIO - _USING_STRINGBUILDER = False + newlist_hint = lambda size: [] - def newlist_hint(size): - return [] +from .exceptions import BufferFull, OutOfData, ExtraData, FormatError, StackError -from .exceptions import BufferFull, ExtraData, FormatError, OutOfData, StackError from .ext import ExtType, Timestamp + EX_SKIP = 0 EX_CONSTRUCT = 1 EX_READ_ARRAY_HEADER = 2 @@ -87,13 +125,24 @@ def unpackb(packed, **kwargs): ret = unpacker._unpack() except OutOfData: raise ValueError("Unpack failed: incomplete input") - except RecursionError: - raise StackError + except RecursionError as e: + if _is_recursionerror(e): + raise StackError + raise if unpacker._got_extradata(): raise ExtraData(ret, unpacker._get_extradata()) return ret +if sys.version_info < (2, 7, 6): + + def _unpack_from(f, b, o=0): + """Explicit type cast for legacy struct.unpack_from""" + return struct.unpack_from(f, bytes(b), o) + +else: + _unpack_from = struct.unpack_from + _NO_FORMAT_USED = "" _MSGPACK_HEADERS = { 0xC4: (1, _NO_FORMAT_USED, TYPE_BIN), @@ -127,14 +176,14 @@ def unpackb(packed, **kwargs): } -class Unpacker: +class Unpacker(object): """Streaming unpacker. Arguments: :param file_like: File-like object having `.read(n)` method. - If specified, unpacker reads serialized data from it and `.feed()` is not usable. + If specified, unpacker reads serialized data from it and :meth:`feed()` is not usable. :param int read_size: Used as `file_like.read(read_size)`. (default: `min(16*1024, max_buffer_size)`) @@ -153,17 +202,17 @@ class Unpacker: 0 - Timestamp 1 - float (Seconds from the EPOCH) 2 - int (Nanoseconds from the EPOCH) - 3 - datetime.datetime (UTC). + 3 - datetime.datetime (UTC). Python 2 is not supported. :param bool strict_map_key: If true (default), only str or bytes are accepted for map (dict) keys. - :param object_hook: + :param callable object_hook: When specified, it should be callable. Unpacker calls it with a dict argument after unpacking msgpack map. (See also simplejson) - :param object_pairs_hook: + :param callable object_pairs_hook: When specified, it should be callable. Unpacker calls it with a list of key-value pairs after unpacking msgpack map. (See also simplejson) @@ -226,7 +275,6 @@ class Unpacker: def __init__( self, file_like=None, - *, read_size=0, use_list=True, raw=False, @@ -311,7 +359,9 @@ def __init__( if object_pairs_hook is not None and not callable(object_pairs_hook): raise TypeError("`object_pairs_hook` is not callable") if object_hook is not None and object_pairs_hook is not None: - raise TypeError("object_pairs_hook and object_hook are mutually exclusive") + raise TypeError( + "object_pairs_hook and object_hook are mutually " "exclusive" + ) if not callable(ext_hook): raise TypeError("`ext_hook` is not callable") @@ -329,7 +379,6 @@ def feed(self, next_bytes): # Use extend here: INPLACE_ADD += doesn't reliably typecast memoryview in jython self._buffer.extend(view) - view.release() def _consume(self): """Gets rid of the used parts of the buffer.""" @@ -404,18 +453,20 @@ def _read_header(self): n = b & 0b00011111 typ = TYPE_RAW if n > self._max_str_len: - raise ValueError(f"{n} exceeds max_str_len({self._max_str_len})") + raise ValueError("%s exceeds max_str_len(%s)" % (n, self._max_str_len)) obj = self._read(n) elif b & 0b11110000 == 0b10010000: n = b & 0b00001111 typ = TYPE_ARRAY if n > self._max_array_len: - raise ValueError(f"{n} exceeds max_array_len({self._max_array_len})") + raise ValueError( + "%s exceeds max_array_len(%s)" % (n, self._max_array_len) + ) elif b & 0b11110000 == 0b10000000: n = b & 0b00001111 typ = TYPE_MAP if n > self._max_map_len: - raise ValueError(f"{n} exceeds max_map_len({self._max_map_len})") + raise ValueError("%s exceeds max_map_len(%s)" % (n, self._max_map_len)) elif b == 0xC0: obj = None elif b == 0xC2: @@ -426,61 +477,65 @@ def _read_header(self): size, fmt, typ = _MSGPACK_HEADERS[b] self._reserve(size) if len(fmt) > 0: - n = struct.unpack_from(fmt, self._buffer, self._buff_i)[0] + n = _unpack_from(fmt, self._buffer, self._buff_i)[0] else: n = self._buffer[self._buff_i] self._buff_i += size if n > self._max_bin_len: - raise ValueError(f"{n} exceeds max_bin_len({self._max_bin_len})") + raise ValueError("%s exceeds max_bin_len(%s)" % (n, self._max_bin_len)) obj = self._read(n) elif 0xC7 <= b <= 0xC9: size, fmt, typ = _MSGPACK_HEADERS[b] self._reserve(size) - L, n = struct.unpack_from(fmt, self._buffer, self._buff_i) + L, n = _unpack_from(fmt, self._buffer, self._buff_i) self._buff_i += size if L > self._max_ext_len: - raise ValueError(f"{L} exceeds max_ext_len({self._max_ext_len})") + raise ValueError("%s exceeds max_ext_len(%s)" % (L, self._max_ext_len)) obj = self._read(L) elif 0xCA <= b <= 0xD3: size, fmt = _MSGPACK_HEADERS[b] self._reserve(size) if len(fmt) > 0: - obj = struct.unpack_from(fmt, self._buffer, self._buff_i)[0] + obj = _unpack_from(fmt, self._buffer, self._buff_i)[0] else: obj = self._buffer[self._buff_i] self._buff_i += size elif 0xD4 <= b <= 0xD8: size, fmt, typ = _MSGPACK_HEADERS[b] if self._max_ext_len < size: - raise ValueError(f"{size} exceeds max_ext_len({self._max_ext_len})") + raise ValueError( + "%s exceeds max_ext_len(%s)" % (size, self._max_ext_len) + ) self._reserve(size + 1) - n, obj = struct.unpack_from(fmt, self._buffer, self._buff_i) + n, obj = _unpack_from(fmt, self._buffer, self._buff_i) self._buff_i += size + 1 elif 0xD9 <= b <= 0xDB: size, fmt, typ = _MSGPACK_HEADERS[b] self._reserve(size) if len(fmt) > 0: - (n,) = struct.unpack_from(fmt, self._buffer, self._buff_i) + (n,) = _unpack_from(fmt, self._buffer, self._buff_i) else: n = self._buffer[self._buff_i] self._buff_i += size if n > self._max_str_len: - raise ValueError(f"{n} exceeds max_str_len({self._max_str_len})") + raise ValueError("%s exceeds max_str_len(%s)" % (n, self._max_str_len)) obj = self._read(n) elif 0xDC <= b <= 0xDD: size, fmt, typ = _MSGPACK_HEADERS[b] self._reserve(size) - (n,) = struct.unpack_from(fmt, self._buffer, self._buff_i) + (n,) = _unpack_from(fmt, self._buffer, self._buff_i) self._buff_i += size if n > self._max_array_len: - raise ValueError(f"{n} exceeds max_array_len({self._max_array_len})") + raise ValueError( + "%s exceeds max_array_len(%s)" % (n, self._max_array_len) + ) elif 0xDE <= b <= 0xDF: size, fmt, typ = _MSGPACK_HEADERS[b] self._reserve(size) - (n,) = struct.unpack_from(fmt, self._buffer, self._buff_i) + (n,) = _unpack_from(fmt, self._buffer, self._buff_i) self._buff_i += size if n > self._max_map_len: - raise ValueError(f"{n} exceeds max_map_len({self._max_map_len})") + raise ValueError("%s exceeds max_map_len(%s)" % (n, self._max_map_len)) else: raise FormatError("Unknown header: 0x%x" % b) return typ, n, obj @@ -499,12 +554,12 @@ def _unpack(self, execute=EX_CONSTRUCT): # TODO should we eliminate the recursion? if typ == TYPE_ARRAY: if execute == EX_SKIP: - for i in range(n): + for i in xrange(n): # TODO check whether we need to call `list_hook` self._unpack(EX_SKIP) return ret = newlist_hint(n) - for i in range(n): + for i in xrange(n): ret.append(self._unpack(EX_CONSTRUCT)) if self._list_hook is not None: ret = self._list_hook(ret) @@ -512,22 +567,25 @@ def _unpack(self, execute=EX_CONSTRUCT): return ret if self._use_list else tuple(ret) if typ == TYPE_MAP: if execute == EX_SKIP: - for i in range(n): + for i in xrange(n): # TODO check whether we need to call hooks self._unpack(EX_SKIP) self._unpack(EX_SKIP) return if self._object_pairs_hook is not None: ret = self._object_pairs_hook( - (self._unpack(EX_CONSTRUCT), self._unpack(EX_CONSTRUCT)) for _ in range(n) + (self._unpack(EX_CONSTRUCT), self._unpack(EX_CONSTRUCT)) + for _ in xrange(n) ) else: ret = {} - for _ in range(n): + for _ in xrange(n): key = self._unpack(EX_CONSTRUCT) - if self._strict_map_key and type(key) not in (str, bytes): - raise ValueError("%s is not allowed for map key" % str(type(key))) - if isinstance(key, str): + if self._strict_map_key and type(key) not in (unicode, bytes): + raise ValueError( + "%s is not allowed for map key" % str(type(key)) + ) + if not PY2 and type(key) is str: key = sys.intern(key) ret[key] = self._unpack(EX_CONSTRUCT) if self._object_hook is not None: @@ -601,7 +659,7 @@ def tell(self): return self._stream_offset -class Packer: +class Packer(object): """ MessagePack Packer @@ -613,8 +671,7 @@ class Packer: Packer's constructor has some keyword arguments: - :param default: - When specified, it should be callable. + :param callable default: Convert user type to builtin type that Packer supports. See also simplejson's document. @@ -641,18 +698,38 @@ class Packer: If set to true, datetime with tzinfo is packed into Timestamp type. Note that the tzinfo is stripped in the timestamp. You can get UTC datetime with `timestamp=3` option of the Unpacker. + (Python 2 is not supported). :param str unicode_errors: The error handler for encoding unicode. (default: 'strict') DO NOT USE THIS!! This option is kept for very specific usage. - :param int buf_size: - Internal buffer size. This option is used only for C implementation. + Example of streaming deserialize from file-like object:: + + unpacker = Unpacker(file_like) + for o in unpacker: + process(o) + + Example of streaming deserialize from socket:: + + unpacker = Unpacker() + while True: + buf = sock.recv(1024**2) + if not buf: + break + unpacker.feed(buf) + for o in unpacker: + process(o) + + Raises ``ExtraData`` when *packed* contains extra bytes. + Raises ``OutOfData`` when *packed* is incomplete. + Raises ``FormatError`` when *packed* is not valid msgpack. + Raises ``StackError`` when *packed* contains too nested. + Other exceptions can be raised during unpacking. """ def __init__( self, - *, default=None, use_single_float=False, autoreset=True, @@ -660,17 +737,19 @@ def __init__( strict_types=False, datetime=False, unicode_errors=None, - buf_size=None, ): self._strict_types = strict_types self._use_float = use_single_float self._autoreset = autoreset self._use_bin_type = use_bin_type - self._buffer = BytesIO() + self._buffer = StringIO() + if PY2 and datetime: + raise ValueError("datetime is not supported in Python 2") self._datetime = bool(datetime) self._unicode_errors = unicode_errors or "strict" - if default is not None and not callable(default): - raise TypeError("default must be callable") + if default is not None: + if not callable(default): + raise TypeError("default must be callable") self._default = default def _pack( @@ -695,7 +774,7 @@ def _pack( if obj: return self._buffer.write(b"\xc3") return self._buffer.write(b"\xc2") - if check(obj, int): + if check(obj, int_types): if 0 <= obj < 0x80: return self._buffer.write(struct.pack("B", obj)) if -0x20 <= obj < 0: @@ -727,7 +806,7 @@ def _pack( raise ValueError("%s is too large" % type(obj).__name__) self._pack_bin_header(n) return self._buffer.write(obj) - if check(obj, str): + if check(obj, unicode): obj = obj.encode("utf-8", self._unicode_errors) n = len(obj) if n >= 2**32: @@ -776,11 +855,13 @@ def _pack( if check(obj, list_types): n = len(obj) self._pack_array_header(n) - for i in range(n): + for i in xrange(n): self._pack(obj[i], nest_limit - 1) return if check(obj, dict): - return self._pack_map_pairs(len(obj), obj.items(), nest_limit - 1) + return self._pack_map_pairs( + len(obj), dict_iteritems(obj), nest_limit - 1 + ) if self._datetime and check(obj, _DateTime) and obj.tzinfo is not None: obj = Timestamp.from_datetime(obj) @@ -793,26 +874,26 @@ def _pack( continue if self._datetime and check(obj, _DateTime): - raise ValueError(f"Cannot serialize {obj!r} where tzinfo=None") + raise ValueError("Cannot serialize %r where tzinfo=None" % (obj,)) - raise TypeError(f"Cannot serialize {obj!r}") + raise TypeError("Cannot serialize %r" % (obj,)) def pack(self, obj): try: self._pack(obj) except: - self._buffer = BytesIO() # force reset + self._buffer = StringIO() # force reset raise if self._autoreset: ret = self._buffer.getvalue() - self._buffer = BytesIO() + self._buffer = StringIO() return ret def pack_map_pairs(self, pairs): self._pack_map_pairs(len(pairs), pairs) if self._autoreset: ret = self._buffer.getvalue() - self._buffer = BytesIO() + self._buffer = StringIO() return ret def pack_array_header(self, n): @@ -821,7 +902,7 @@ def pack_array_header(self, n): self._pack_array_header(n) if self._autoreset: ret = self._buffer.getvalue() - self._buffer = BytesIO() + self._buffer = StringIO() return ret def pack_map_header(self, n): @@ -830,7 +911,7 @@ def pack_map_header(self, n): self._pack_map_header(n) if self._autoreset: ret = self._buffer.getvalue() - self._buffer = BytesIO() + self._buffer = StringIO() return ret def pack_ext_type(self, typecode, data): @@ -882,7 +963,7 @@ def _pack_map_header(self, n): def _pack_map_pairs(self, n, pairs, nest_limit=DEFAULT_RECURSE_LIMIT): self._pack_map_header(n) - for k, v in pairs: + for (k, v) in pairs: self._pack(k, nest_limit - 1) self._pack(v, nest_limit - 1) @@ -919,11 +1000,11 @@ def reset(self): This method is useful only when autoreset=False. """ - self._buffer = BytesIO() + self._buffer = StringIO() def getbuffer(self): """Return view of internal buffer.""" - if _USING_STRINGBUILDER: + if USING_STRINGBUILDER or PY2: return memoryview(self.bytes()) else: return self._buffer.getbuffer() diff --git a/venv1/Lib/site-packages/pip/_vendor/packaging/__init__.py b/venv1/Lib/site-packages/pip/_vendor/packaging/__init__.py index d45c22cf..3c50c5dc 100644 --- a/venv1/Lib/site-packages/pip/_vendor/packaging/__init__.py +++ b/venv1/Lib/site-packages/pip/_vendor/packaging/__init__.py @@ -2,14 +2,24 @@ # 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" +from .__about__ import ( + __author__, + __copyright__, + __email__, + __license__, + __summary__, + __title__, + __uri__, + __version__, +) -__version__ = "25.0" - -__author__ = "Donald Stufft and individual contributors" -__email__ = "donald@stufft.io" - -__license__ = "BSD-2-Clause or Apache-2.0" -__copyright__ = f"2014 {__author__}" +__all__ = [ + "__title__", + "__summary__", + "__uri__", + "__version__", + "__author__", + "__email__", + "__license__", + "__copyright__", +] diff --git a/venv1/Lib/site-packages/pip/_vendor/packaging/_elffile.py b/venv1/Lib/site-packages/pip/_vendor/packaging/_elffile.py deleted file mode 100644 index 7a5afc33..00000000 --- a/venv1/Lib/site-packages/pip/_vendor/packaging/_elffile.py +++ /dev/null @@ -1,109 +0,0 @@ -""" -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 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/venv1/Lib/site-packages/pip/_vendor/packaging/_manylinux.py b/venv1/Lib/site-packages/pip/_vendor/packaging/_manylinux.py index 95f55762..4c379aa6 100644 --- a/venv1/Lib/site-packages/pip/_vendor/packaging/_manylinux.py +++ b/venv1/Lib/site-packages/pip/_vendor/packaging/_manylinux.py @@ -1,72 +1,122 @@ -from __future__ import annotations - import collections -import contextlib import functools import os import re +import struct 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]: +from typing import IO, Dict, Iterator, NamedTuple, Optional, Tuple + + +# Python does not provide platform information at sufficient granularity to +# identify the architecture of the running executable in some cases, so we +# determine it dynamically by reading the information from the running +# process. This only applies on Linux, which uses the ELF format. +class _ELFFileHeader: + # https://en.wikipedia.org/wiki/Executable_and_Linkable_Format#File_header + class _InvalidELFFileHeader(ValueError): + """ + An invalid ELF file header was found. + """ + + ELF_MAGIC_NUMBER = 0x7F454C46 + ELFCLASS32 = 1 + ELFCLASS64 = 2 + ELFDATA2LSB = 1 + ELFDATA2MSB = 2 + EM_386 = 3 + EM_S390 = 22 + EM_ARM = 40 + EM_X86_64 = 62 + EF_ARM_ABIMASK = 0xFF000000 + EF_ARM_ABI_VER5 = 0x05000000 + EF_ARM_ABI_FLOAT_HARD = 0x00000400 + + def __init__(self, file: IO[bytes]) -> None: + def unpack(fmt: str) -> int: + try: + data = file.read(struct.calcsize(fmt)) + result: Tuple[int, ...] = struct.unpack(fmt, data) + except struct.error: + raise _ELFFileHeader._InvalidELFFileHeader() + return result[0] + + self.e_ident_magic = unpack(">I") + if self.e_ident_magic != self.ELF_MAGIC_NUMBER: + raise _ELFFileHeader._InvalidELFFileHeader() + self.e_ident_class = unpack("B") + if self.e_ident_class not in {self.ELFCLASS32, self.ELFCLASS64}: + raise _ELFFileHeader._InvalidELFFileHeader() + self.e_ident_data = unpack("B") + if self.e_ident_data not in {self.ELFDATA2LSB, self.ELFDATA2MSB}: + raise _ELFFileHeader._InvalidELFFileHeader() + self.e_ident_version = unpack("B") + self.e_ident_osabi = unpack("B") + self.e_ident_abiversion = unpack("B") + self.e_ident_pad = file.read(7) + format_h = "H" + format_i = "I" + format_q = "Q" + format_p = format_i if self.e_ident_class == self.ELFCLASS32 else format_q + self.e_type = unpack(format_h) + self.e_machine = unpack(format_h) + self.e_version = unpack(format_i) + self.e_entry = unpack(format_p) + self.e_phoff = unpack(format_p) + self.e_shoff = unpack(format_p) + self.e_flags = unpack(format_i) + self.e_ehsize = unpack(format_h) + self.e_phentsize = unpack(format_h) + self.e_phnum = unpack(format_h) + self.e_shentsize = unpack(format_h) + self.e_shnum = unpack(format_h) + self.e_shstrndx = unpack(format_h) + + +def _get_elf_header() -> Optional[_ELFFileHeader]: try: - with open(path, "rb") as f: - yield ELFFile(f) - except (OSError, TypeError, ValueError): - yield None + with open(sys.executable, "rb") as f: + elf_header = _ELFFileHeader(f) + except (OSError, TypeError, _ELFFileHeader._InvalidELFFileHeader): + return None + return elf_header -def _is_linux_armhf(executable: str) -> bool: +def _is_linux_armhf() -> 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 - ) + elf_header = _get_elf_header() + if elf_header is None: + return False + result = elf_header.e_ident_class == elf_header.ELFCLASS32 + result &= elf_header.e_ident_data == elf_header.ELFDATA2LSB + result &= elf_header.e_machine == elf_header.EM_ARM + result &= ( + elf_header.e_flags & elf_header.EF_ARM_ABIMASK + ) == elf_header.EF_ARM_ABI_VER5 + result &= ( + elf_header.e_flags & elf_header.EF_ARM_ABI_FLOAT_HARD + ) == elf_header.EF_ARM_ABI_FLOAT_HARD + return result + + +def _is_linux_i686() -> bool: + elf_header = _get_elf_header() + if elf_header is None: + return False + result = elf_header.e_ident_class == elf_header.ELFCLASS32 + result &= elf_header.e_ident_data == elf_header.ELFDATA2LSB + result &= elf_header.e_machine == elf_header.EM_386 + return result -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) +def _have_compatible_abi(arch: str) -> bool: + if arch == "armv7l": + return _is_linux_armhf() + if arch == "i686": + return _is_linux_i686() + return arch in {"x86_64", "aarch64", "ppc64", "ppc64le", "s390x"} # If glibc ever changes its major version, we need to know what the last @@ -74,7 +124,7 @@ def _have_compatible_abi(executable: str, archs: Sequence[str]) -> bool: # 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) +_LAST_GLIBC_MINOR: Dict[int, int] = collections.defaultdict(lambda: 50) class _GLibCVersion(NamedTuple): @@ -82,7 +132,7 @@ class _GLibCVersion(NamedTuple): minor: int -def _glibc_version_string_confstr() -> str | None: +def _glibc_version_string_confstr() -> Optional[str]: """ Primary implementation of glibc_version_string using os.confstr. """ @@ -91,17 +141,17 @@ def _glibc_version_string_confstr() -> str | None: # 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") + # os.confstr("CS_GNU_LIBC_VERSION") returns a string like "glibc 2.17". + version_string = os.confstr("CS_GNU_LIBC_VERSION") assert version_string is not None - _, version = version_string.rsplit() + _, version = version_string.split() 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: +def _glibc_version_string_ctypes() -> Optional[str]: """ Fallback implementation of glibc_version_string using ctypes. """ @@ -145,12 +195,12 @@ def _glibc_version_string_ctypes() -> str | None: return version_str -def _glibc_version_string() -> str | None: +def _glibc_version_string() -> Optional[str]: """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]: +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 @@ -161,16 +211,16 @@ def _parse_glibc_version(version_str: str) -> tuple[int, int]: 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, got: {version_str}", + "Expected glibc version with 2 components major.minor," + " got: %s" % 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]: +@functools.lru_cache() +def _get_glibc_version() -> Tuple[int, int]: version_str = _glibc_version_string() if version_str is None: return (-1, -1) @@ -178,13 +228,13 @@ def _get_glibc_version() -> tuple[int, int]: # From PEP 513, PEP 600 -def _is_compatible(arch: str, version: _GLibCVersion) -> bool: +def _is_compatible(name: str, 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 + import _manylinux # noqa except ImportError: return True if hasattr(_manylinux, "manylinux_compatible"): @@ -214,22 +264,12 @@ def _is_compatible(arch: str, version: _GLibCVersion) -> bool: } -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): +def platform_tags(linux: str, arch: str) -> Iterator[str]: + if not _have_compatible_abi(arch): return # Oldest glibc to be supported regardless of architecture is (2, 17). too_old_glibc2 = _GLibCVersion(2, 16) - if set(archs) & {"x86_64", "i686"}: + if arch in {"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()) @@ -243,20 +283,19 @@ def platform_tags(archs: Sequence[str]) -> Iterator[str]: 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}" + 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(tag, arch, glibc_version): + yield linux.replace("linux", tag) + # Handle the legacy manylinux1, manylinux2010, manylinux2014 tags. + if glibc_version in _LEGACY_MANYLINUX_MAP: + legacy_tag = _LEGACY_MANYLINUX_MAP[glibc_version] + if _is_compatible(legacy_tag, arch, glibc_version): + yield linux.replace("linux", legacy_tag) diff --git a/venv1/Lib/site-packages/pip/_vendor/packaging/_musllinux.py b/venv1/Lib/site-packages/pip/_vendor/packaging/_musllinux.py index d2bf30b5..8ac3059b 100644 --- a/venv1/Lib/site-packages/pip/_vendor/packaging/_musllinux.py +++ b/venv1/Lib/site-packages/pip/_vendor/packaging/_musllinux.py @@ -4,15 +4,68 @@ linked against musl, and what musl version is used. """ -from __future__ import annotations - +import contextlib import functools +import operator +import os import re +import struct import subprocess import sys -from typing import Iterator, NamedTuple, Sequence +from typing import IO, Iterator, NamedTuple, Optional, Tuple + + +def _read_unpacked(f: IO[bytes], fmt: str) -> Tuple[int, ...]: + return struct.unpack(fmt, f.read(struct.calcsize(fmt))) -from ._elffile import ELFFile + +def _parse_ld_musl_from_elf(f: IO[bytes]) -> Optional[str]: + """Detect musl libc location by parsing the Python executable. + + Based on: https://gist.github.com/lyssdod/f51579ae8d93c8657a5564aefc2ffbca + ELF header: https://refspecs.linuxfoundation.org/elf/gabi4+/ch4.eheader.html + """ + f.seek(0) + try: + ident = _read_unpacked(f, "16B") + except struct.error: + return None + if ident[:4] != tuple(b"\x7fELF"): # Invalid magic, not ELF. + return None + f.seek(struct.calcsize("HHI"), 1) # Skip file type, machine, and version. + + 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, p_fmt, p_idx = { + 1: ("IIIIHHH", "IIIIIIII", (0, 1, 4)), # 32-bit. + 2: ("QQQIHHH", "IIQQQQQQ", (0, 2, 5)), # 64-bit. + }[ident[4]] + except KeyError: + return None + else: + p_get = operator.itemgetter(*p_idx) + + # Find the interpreter section and return its content. + try: + _, e_phoff, _, _, _, e_phentsize, e_phnum = _read_unpacked(f, e_fmt) + except struct.error: + return None + for i in range(e_phnum + 1): + f.seek(e_phoff + e_phentsize * i) + try: + p_type, p_offset, p_filesz = p_get(_read_unpacked(f, p_fmt)) + except struct.error: + return None + if p_type != 3: # Not PT_INTERP. + continue + f.seek(p_offset) + interpreter = os.fsdecode(f.read(p_filesz)).strip("\0") + if "musl" not in interpreter: + return None + return interpreter + return None class _MuslVersion(NamedTuple): @@ -20,7 +73,7 @@ class _MuslVersion(NamedTuple): minor: int -def _parse_musl_version(output: str) -> _MuslVersion | None: +def _parse_musl_version(output: str) -> Optional[_MuslVersion]: 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 @@ -30,8 +83,8 @@ def _parse_musl_version(output: str) -> _MuslVersion | None: return _MuslVersion(major=int(m.group(1)), minor=int(m.group(2))) -@functools.lru_cache -def _get_musl_version(executable: str) -> _MuslVersion | None: +@functools.lru_cache() +def _get_musl_version(executable: str) -> Optional[_MuslVersion]: """Detect currently-running musl runtime version. This is done by checking the specified executable's dynamic linking @@ -42,34 +95,32 @@ def _get_musl_version(executable: str) -> _MuslVersion | None: 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: + with contextlib.ExitStack() as stack: + try: + f = stack.enter_context(open(executable, "rb")) + except OSError: + return None + ld = _parse_ld_musl_from_elf(f) + if not ld: return None - proc = subprocess.run([ld], stderr=subprocess.PIPE, text=True) + proc = subprocess.run([ld], stderr=subprocess.PIPE, universal_newlines=True) return _parse_musl_version(proc.stderr) -def platform_tags(archs: Sequence[str]) -> Iterator[str]: +def platform_tags(arch: 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. + :param arch: Should 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}" + for minor in range(sys_musl.minor, -1, -1): + yield f"musllinux_{sys_musl.major}_{minor}_{arch}" if __name__ == "__main__": # pragma: no cover diff --git a/venv1/Lib/site-packages/pip/_vendor/packaging/_parser.py b/venv1/Lib/site-packages/pip/_vendor/packaging/_parser.py deleted file mode 100644 index 0007c0aa..00000000 --- a/venv1/Lib/site-packages/pip/_vendor/packaging/_parser.py +++ /dev/null @@ -1,353 +0,0 @@ -"""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/venv1/Lib/site-packages/pip/_vendor/packaging/_tokenizer.py b/venv1/Lib/site-packages/pip/_vendor/packaging/_tokenizer.py deleted file mode 100644 index d28a9b6c..00000000 --- a/venv1/Lib/site-packages/pip/_vendor/packaging/_tokenizer.py +++ /dev/null @@ -1,195 +0,0 @@ -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) - |extras? - |dependency_groups - )\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/venv1/Lib/site-packages/pip/_vendor/packaging/markers.py b/venv1/Lib/site-packages/pip/_vendor/packaging/markers.py index e7cea572..540e7a4d 100644 --- a/venv1/Lib/site-packages/pip/_vendor/packaging/markers.py +++ b/venv1/Lib/site-packages/pip/_vendor/packaging/markers.py @@ -2,32 +2,35 @@ # 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 AbstractSet, Any, Callable, Literal, TypedDict, Union, cast +from typing import Any, Callable, Dict, List, Optional, Tuple, Union + +from pip._vendor.pyparsing import ( # noqa: N817 + Forward, + Group, + Literal as L, + ParseException, + ParseResults, + QuotedString, + ZeroOrMore, + stringEnd, + stringStart, +) -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__ = [ - "EvaluateContext", "InvalidMarker", - "Marker", "UndefinedComparison", "UndefinedEnvironmentName", + "Marker", "default_environment", ] -Operator = Callable[[str, Union[str, AbstractSet[str]]], bool] -EvaluateContext = Literal["metadata", "lock_file", "requirement"] -MARKERS_ALLOWING_SET = {"extras", "dependency_groups"} +Operator = Callable[[str, str], bool] class InvalidMarker(ValueError): @@ -49,97 +52,103 @@ class UndefinedEnvironmentName(ValueError): """ -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'``. +class Node: + def __init__(self, value: Any) -> None: + self.value = value - An empty string if the value cannot be determined. - """ - - platform_release: str - """ - The system's release, e.g. ``'2.2.0'`` or ``'NT'``. + def __str__(self) -> str: + return str(self.value) - An empty string if the value cannot be determined. - """ + 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) + + +VARIABLE = ( + L("implementation_version") + | L("platform_python_implementation") + | L("implementation_name") + | L("python_full_version") + | L("platform_release") + | L("platform_version") + | L("platform_machine") + | L("platform_system") + | L("python_version") + | L("sys_platform") + | L("os_name") + | L("os.name") # PEP-345 + | L("sys.platform") # PEP-345 + | L("platform.version") # PEP-345 + | L("platform.machine") # PEP-345 + | L("platform.python_implementation") # PEP-345 + | L("python_implementation") # undocumented setuptools legacy + | L("extra") # PEP-508 +) +ALIASES = { + "os.name": "os_name", + "sys.platform": "sys_platform", + "platform.version": "platform_version", + "platform.machine": "platform_machine", + "platform.python_implementation": "platform_python_implementation", + "python_implementation": "platform_python_implementation", +} +VARIABLE.setParseAction(lambda s, l, t: Variable(ALIASES.get(t[0], t[0]))) - platform_system: str - """ - The system/OS name, e.g. ``'Linux'``, ``'Windows'`` or ``'Java'``. +VERSION_CMP = ( + L("===") | L("==") | L(">=") | L("<=") | L("!=") | L("~=") | L(">") | L("<") +) - An empty string if the value cannot be determined. - """ +MARKER_OP = VERSION_CMP | L("not in") | L("in") +MARKER_OP.setParseAction(lambda s, l, t: Op(t[0])) - platform_version: str - """ - The system's release version, e.g. ``'#3 on degas'``. +MARKER_VALUE = QuotedString("'") | QuotedString('"') +MARKER_VALUE.setParseAction(lambda s, l, t: Value(t[0])) - An empty string if the value cannot be determined. - """ +BOOLOP = L("and") | L("or") - python_full_version: str - """ - The Python version as string ``'major.minor.patchlevel'``. +MARKER_VAR = VARIABLE | MARKER_VALUE - Note that unlike the Python :py:data:`sys.version`, this value will always include - the patchlevel (it defaults to 0). - """ +MARKER_ITEM = Group(MARKER_VAR + MARKER_OP + MARKER_VAR) +MARKER_ITEM.setParseAction(lambda s, l, t: tuple(t[0])) - platform_python_implementation: str - """ - A string identifying the Python implementation, e.g. ``'CPython'``. - """ +LPAREN = L("(").suppress() +RPAREN = L(")").suppress() - python_version: str - """The Python version as string ``'major.minor'``.""" +MARKER_EXPR = Forward() +MARKER_ATOM = MARKER_ITEM | Group(LPAREN + MARKER_EXPR + RPAREN) +MARKER_EXPR << MARKER_ATOM + ZeroOrMore(BOOLOP + MARKER_EXPR) - 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. +MARKER = stringStart + MARKER_EXPR + stringEnd - 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 _coerce_parse_result(results: Union[ParseResults, List[Any]]) -> List[Any]: + if isinstance(results, ParseResults): + return [_coerce_parse_result(i) for i in results] + else: + return results def _format_marker( - marker: list[str] | MarkerAtom | str, first: bool | None = True + marker: Union[List[str], Tuple[Node, ...], str], first: Optional[bool] = True ) -> str: + assert isinstance(marker, (list, tuple, str)) # Sometimes we have a structure like [[...]] which is a single item list @@ -165,7 +174,7 @@ def _format_marker( return marker -_operators: dict[str, Operator] = { +_operators: Dict[str, Operator] = { "in": lambda lhs, rhs: lhs in rhs, "not in": lambda lhs, rhs: lhs not in rhs, "<": operator.lt, @@ -177,46 +186,41 @@ def _format_marker( } -def _eval_op(lhs: str, op: Op, rhs: str | AbstractSet[str]) -> bool: - if isinstance(rhs, str): - try: - spec = Specifier("".join([op.serialize(), rhs])) - except InvalidSpecifier: - pass - else: - return spec.contains(lhs, prereleases=True) +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) - oper: Operator | None = _operators.get(op.serialize()) + oper: Optional[Operator] = _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( - lhs: str, rhs: str | AbstractSet[str], key: str -) -> tuple[str, str | AbstractSet[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": - assert isinstance(rhs, str), "extra value must be a string" - return (canonicalize_name(lhs), canonicalize_name(rhs)) - if key in MARKERS_ALLOWING_SET: - if isinstance(rhs, str): # pragma: no cover - return (canonicalize_name(lhs), canonicalize_name(rhs)) - else: - return (canonicalize_name(lhs), {canonicalize_name(v) for v in rhs}) +class Undefined: + pass + + +_undefined = Undefined() - # other environment markers don't have such standards - return lhs, rhs +def _get_env(environment: Dict[str, str], name: str) -> str: + value: Union[str, Undefined] = environment.get(name, _undefined) + + if isinstance(value, Undefined): + raise UndefinedEnvironmentName( + f"{name!r} does not exist in evaluation environment." + ) + + return value -def _evaluate_markers( - markers: MarkerList, environment: dict[str, str | AbstractSet[str]] -) -> bool: - groups: list[list[bool]] = [[]] + +def _evaluate_markers(markers: List[Any], environment: Dict[str, str]) -> bool: + groups: List[List[bool]] = [[]] for marker in markers: assert isinstance(marker, (list, tuple, str)) @@ -227,15 +231,12 @@ def _evaluate_markers( lhs, op, rhs = marker if isinstance(lhs, Variable): - environment_key = lhs.value - lhs_value = environment[environment_key] + lhs_value = _get_env(environment, lhs.value) rhs_value = rhs.value else: lhs_value = lhs.value - environment_key = rhs.value - rhs_value = environment[environment_key] - assert isinstance(lhs_value, str), "lhs must be a string" - lhs_value, rhs_value = _normalize(lhs_value, rhs_value, key=environment_key) + rhs_value = _get_env(environment, rhs.value) + groups[-1].append(_eval_op(lhs_value, op, rhs_value)) else: assert marker in ["and", "or"] @@ -245,15 +246,15 @@ def _evaluate_markers( 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}" +def format_full_version(info: "sys._version_info") -> str: + version = "{0.major}.{0.minor}.{0.micro}".format(info) kind = info.releaselevel if kind != "final": version += kind[0] + str(info.serial) return version -def default_environment() -> Environment: +def default_environment() -> Dict[str, str]: iver = format_full_version(sys.implementation.version) implementation_name = sys.implementation.name return { @@ -273,29 +274,13 @@ def default_environment() -> Environment: 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 + self._markers = _coerce_parse_result(MARKER.parseString(marker)) + except ParseException as e: + raise InvalidMarker( + f"Invalid marker: {marker!r}, parse error at " + f"{marker[e.loc : e.loc + 8]!r}" + ) def __str__(self) -> str: return _format_marker(self._markers) @@ -303,60 +288,17 @@ def __str__(self) -> str: 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, - context: EvaluateContext = "metadata", - ) -> bool: + def evaluate(self, environment: Optional[Dict[str, str]] = 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 *context* parameter specifies what - context the markers are being evaluated for, which influences what markers - are considered valid. Acceptable values are "metadata" (for core metadata; - default), "lock_file", and "requirement" (i.e. all other situations). + part of the determined environment. The environment is determined from the current Python process. """ - current_environment = cast( - "dict[str, str | AbstractSet[str]]", default_environment() - ) - if context == "lock_file": - current_environment.update( - extras=frozenset(), dependency_groups=frozenset() - ) - elif context == "metadata": - current_environment["extra"] = "" + current_environment = default_environment() 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 "extra" in current_environment and 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 | AbstractSet[str]], -) -> dict[str, str | AbstractSet[str]]: - """ - Work around platform.python_version() returning something that is not PEP 440 - compliant for non-tagged Python builds. - """ - python_full_version = cast(str, env["python_full_version"]) - if python_full_version.endswith("+"): - env["python_full_version"] = f"{python_full_version}local" - return env + return _evaluate_markers(self._markers, current_environment) diff --git a/venv1/Lib/site-packages/pip/_vendor/packaging/metadata.py b/venv1/Lib/site-packages/pip/_vendor/packaging/metadata.py deleted file mode 100644 index 3bd8602d..00000000 --- a/venv1/Lib/site-packages/pip/_vendor/packaging/metadata.py +++ /dev/null @@ -1,862 +0,0 @@ -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/venv1/Lib/site-packages/pip/_vendor/packaging/py.typed b/venv1/Lib/site-packages/pip/_vendor/packaging/py.typed deleted file mode 100644 index e69de29b..00000000 diff --git a/venv1/Lib/site-packages/pip/_vendor/packaging/requirements.py b/venv1/Lib/site-packages/pip/_vendor/packaging/requirements.py index 4e068c95..1eab7dd6 100644 --- a/venv1/Lib/site-packages/pip/_vendor/packaging/requirements.py +++ b/venv1/Lib/site-packages/pip/_vendor/packaging/requirements.py @@ -1,15 +1,27 @@ # 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 +import re +import string +import urllib.parse +from typing import List, Optional as TOptional, Set -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 +from pip._vendor.pyparsing import ( # noqa + Combine, + Literal as L, + Optional, + ParseException, + Regex, + Word, + ZeroOrMore, + originalTextFor, + stringEnd, + stringStart, +) + +from .markers import MARKER_EXPR, Marker +from .specifiers import LegacySpecifier, Specifier, SpecifierSet class InvalidRequirement(ValueError): @@ -18,6 +30,60 @@ class InvalidRequirement(ValueError): """ +ALPHANUM = Word(string.ascii_letters + string.digits) + +LBRACKET = L("[").suppress() +RBRACKET = L("]").suppress() +LPAREN = L("(").suppress() +RPAREN = L(")").suppress() +COMMA = L(",").suppress() +SEMICOLON = L(";").suppress() +AT = L("@").suppress() + +PUNCTUATION = Word("-_.") +IDENTIFIER_END = ALPHANUM | (ZeroOrMore(PUNCTUATION) + ALPHANUM) +IDENTIFIER = Combine(ALPHANUM + ZeroOrMore(IDENTIFIER_END)) + +NAME = IDENTIFIER("name") +EXTRA = IDENTIFIER + +URI = Regex(r"[^ ]+")("url") +URL = AT + URI + +EXTRAS_LIST = EXTRA + ZeroOrMore(COMMA + EXTRA) +EXTRAS = (LBRACKET + Optional(EXTRAS_LIST) + RBRACKET)("extras") + +VERSION_PEP440 = Regex(Specifier._regex_str, re.VERBOSE | re.IGNORECASE) +VERSION_LEGACY = Regex(LegacySpecifier._regex_str, re.VERBOSE | re.IGNORECASE) + +VERSION_ONE = VERSION_PEP440 ^ VERSION_LEGACY +VERSION_MANY = Combine( + VERSION_ONE + ZeroOrMore(COMMA + VERSION_ONE), joinString=",", adjacent=False +)("_raw_spec") +_VERSION_SPEC = Optional((LPAREN + VERSION_MANY + RPAREN) | VERSION_MANY) +_VERSION_SPEC.setParseAction(lambda s, l, t: t._raw_spec or "") + +VERSION_SPEC = originalTextFor(_VERSION_SPEC)("specifier") +VERSION_SPEC.setParseAction(lambda s, l, t: t[1]) + +MARKER_EXPR = originalTextFor(MARKER_EXPR())("marker") +MARKER_EXPR.setParseAction( + lambda s, l, t: Marker(s[t._original_start : t._original_end]) +) +MARKER_SEPARATOR = SEMICOLON +MARKER = MARKER_SEPARATOR + MARKER_EXPR + +VERSION_AND_MARKER = VERSION_SPEC + Optional(MARKER) +URL_AND_MARKER = URL + Optional(MARKER) + +NAMED_REQUIREMENT = NAME + Optional(EXTRAS) + (URL_AND_MARKER | VERSION_AND_MARKER) + +REQUIREMENT = stringStart + NAMED_REQUIREMENT + stringEnd +# pyparsing isn't thread safe during initialization, so we do it eagerly, see +# issue #104 +REQUIREMENT.parseString("x[]") + + class Requirement: """Parse a requirement. @@ -33,59 +99,48 @@ class Requirement: 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 + req = REQUIREMENT.parseString(requirement_string) + except ParseException as e: + raise InvalidRequirement( + f'Parse error at "{ requirement_string[e.loc : e.loc + 8]!r}": {e.msg}' + ) + + self.name: str = req.name + if req.url: + parsed_url = urllib.parse.urlparse(req.url) + if parsed_url.scheme == "file": + if urllib.parse.urlunparse(parsed_url) != req.url: + raise InvalidRequirement("Invalid URL given") + elif not (parsed_url.scheme and parsed_url.netloc) or ( + not parsed_url.scheme and not parsed_url.netloc + ): + raise InvalidRequirement(f"Invalid URL: {req.url}") + self.url: TOptional[str] = req.url + else: + self.url = None + self.extras: Set[str] = set(req.extras.asList() if req.extras else []) + self.specifier: SpecifierSet = SpecifierSet(req.specifier) + self.marker: TOptional[Marker] = req.marker if req.marker else None + + def __str__(self) -> str: + parts: List[str] = [self.name] if self.extras: formatted_extras = ",".join(sorted(self.extras)) - yield f"[{formatted_extras}]" + parts.append(f"[{formatted_extras}]") if self.specifier: - yield str(self.specifier) + parts.append(str(self.specifier)) if self.url: - yield f"@ {self.url}" + parts.append(f"@ {self.url}") if self.marker: - yield " " + parts.append(" ") if self.marker: - yield f"; {self.marker}" + parts.append(f"; {self.marker}") - def __str__(self) -> str: - return "".join(self._iter_parts(self.name)) + return "".join(parts) 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/venv1/Lib/site-packages/pip/_vendor/packaging/specifiers.py b/venv1/Lib/site-packages/pip/_vendor/packaging/specifiers.py index 47c3929a..0e218a6f 100644 --- a/venv1/Lib/site-packages/pip/_vendor/packaging/specifiers.py +++ b/venv1/Lib/site-packages/pip/_vendor/packaging/specifiers.py @@ -1,43 +1,38 @@ # 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 pip._vendor.packaging.specifiers import Specifier, SpecifierSet, InvalidSpecifier - from pip._vendor.packaging.version import Version -""" - -from __future__ import annotations import abc +import functools import itertools import re -from typing import Callable, Iterable, Iterator, TypeVar, Union +import warnings +from typing import ( + Callable, + Dict, + Iterable, + Iterator, + List, + Optional, + Pattern, + Set, + Tuple, + 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] - +from .version import LegacyVersion, Version, parse -def _coerce_version(version: UnparsedVersion) -> Version: - if not isinstance(version, Version): - version = Version(version) - return version +ParsedVersion = Union[Version, LegacyVersion] +UnparsedVersion = Union[Version, LegacyVersion, str] +VersionTypeVar = TypeVar("VersionTypeVar", bound=UnparsedVersion) +CallableOperator = Callable[[ParsedVersion, str], bool] 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' + An invalid specifier was found, users should refer to PEP 440. """ @@ -45,71 +40,266 @@ class BaseSpecifier(metaclass=abc.ABCMeta): @abc.abstractmethod def __str__(self) -> str: """ - Returns the str representation of this Specifier-like object. This + 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. + 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 + 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. + @abc.abstractproperty + def prereleases(self) -> Optional[bool]: + """ + Returns whether or not pre-releases as a whole are allowed by this + specifier. """ @prereleases.setter def prereleases(self, value: bool) -> None: - """Setter for :attr:`prereleases`. - - :param value: The value to set. + """ + Sets whether or not pre-releases as a whole are allowed by this + specifier. """ @abc.abstractmethod - def contains(self, item: str, prereleases: bool | None = None) -> bool: + def contains(self, item: str, prereleases: Optional[bool] = 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]: + self, iterable: Iterable[VersionTypeVar], prereleases: Optional[bool] = None + ) -> Iterable[VersionTypeVar]: """ 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. +class _IndividualSpecifier(BaseSpecifier): - .. tip:: + _operators: Dict[str, str] = {} + _regex: Pattern[str] - 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). - """ + def __init__(self, spec: str = "", prereleases: Optional[bool] = None) -> None: + match = self._regex.search(spec) + if not match: + raise InvalidSpecifier(f"Invalid specifier: '{spec}'") - _operator_regex_str = r""" - (?P(~=|==|!=|<=|>=|<|>|===)) + 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 + + def __repr__(self) -> str: + 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: + return "{}{}".format(*self._spec) + + @property + def _canonical_spec(self) -> Tuple[str, str]: + return self._spec[0], canonicalize_version(self._spec[1]) + + def __hash__(self) -> int: + return hash(self._canonical_spec) + + def __eq__(self, other: object) -> bool: + 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 _coerce_version(self, version: UnparsedVersion) -> ParsedVersion: + if not isinstance(version, (LegacyVersion, Version)): + version = parse(version) + return version + + @property + def operator(self) -> str: + return self._spec[0] + + @property + def version(self) -> str: + return self._spec[1] + + @property + def prereleases(self) -> Optional[bool]: + return self._prereleases + + @prereleases.setter + def prereleases(self, value: bool) -> None: + self._prereleases = value + + def __contains__(self, item: str) -> bool: + return self.contains(item) + + def contains( + self, item: UnparsedVersion, prereleases: Optional[bool] = None + ) -> bool: + + # Determine if prereleases are to be allowed or not. + if prereleases is None: + prereleases = self.prereleases + + # Normalize item to a Version or LegacyVersion, this allows us to have + # a shortcut for ``"2.0" in Specifier(">=2") + normalized_item = self._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[VersionTypeVar], prereleases: Optional[bool] = None + ) -> Iterable[VersionTypeVar]: + + 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 = self._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 + + +class LegacySpecifier(_IndividualSpecifier): + + _regex_str = r""" + (?P(==|!=|<=|>=|<|>)) + \s* + (?P + [^,;\s)]* # Since this is a "legacy" specifier, and the version + # string can be just about anything, we match everything + # except for whitespace, a semi-colon for marker support, + # a closing paren since versions can be enclosed in + # them, and a comma since it's a version separator. + ) """ - _version_regex_str = r""" + + _regex = re.compile(r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE) + + _operators = { + "==": "equal", + "!=": "not_equal", + "<=": "less_than_equal", + ">=": "greater_than_equal", + "<": "less_than", + ">": "greater_than", + } + + def __init__(self, spec: str = "", prereleases: Optional[bool] = None) -> None: + super().__init__(spec, prereleases) + + warnings.warn( + "Creating a LegacyVersion has been deprecated and will be " + "removed in the next major release", + DeprecationWarning, + ) + + def _coerce_version(self, version: UnparsedVersion) -> LegacyVersion: + if not isinstance(version, LegacyVersion): + version = LegacyVersion(str(version)) + return version + + def _compare_equal(self, prospective: LegacyVersion, spec: str) -> bool: + return prospective == self._coerce_version(spec) + + def _compare_not_equal(self, prospective: LegacyVersion, spec: str) -> bool: + return prospective != self._coerce_version(spec) + + def _compare_less_than_equal(self, prospective: LegacyVersion, spec: str) -> bool: + return prospective <= self._coerce_version(spec) + + def _compare_greater_than_equal( + self, prospective: LegacyVersion, spec: str + ) -> bool: + return prospective >= self._coerce_version(spec) + + def _compare_less_than(self, prospective: LegacyVersion, spec: str) -> bool: + return prospective < self._coerce_version(spec) + + def _compare_greater_than(self, prospective: LegacyVersion, spec: str) -> bool: + return prospective > self._coerce_version(spec) + + +def _require_version_compare( + fn: Callable[["Specifier", ParsedVersion, str], bool] +) -> Callable[["Specifier", ParsedVersion, str], bool]: + @functools.wraps(fn) + def wrapped(self: "Specifier", prospective: ParsedVersion, spec: str) -> bool: + if not isinstance(prospective, Version): + return False + return fn(self, prospective, spec) + + return wrapped + + +class Specifier(_IndividualSpecifier): + + _regex_str = r""" + (?P(~=|==|!=|<=|>=|<|>|===)) (?P (?: # The identity operators allow for an escape hatch that will @@ -119,10 +309,8 @@ class Specifier(BaseSpecifier): # 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. + [^\s]* # We just match everything, except for whitespace + # since we are only testing for strict identity. ) | (?: @@ -135,23 +323,23 @@ class Specifier(BaseSpecifier): v? (?:[0-9]+!)? # epoch [0-9]+(?:\.[0-9]+)* # release + (?: # pre release + [-_\.]? + (a|b|c|rc|alpha|beta|pre|preview) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? - # 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. + # You cannot use a wild card and 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 + | + \.\* # Wild card syntax of .* )? ) | @@ -166,7 +354,7 @@ class Specifier(BaseSpecifier): [0-9]+(?:\.[0-9]+)+ # release (We have a + instead of a *) (?: # pre release [-_\.]? - (alpha|beta|preview|pre|a|b|c|rc) + (a|b|c|rc|alpha|beta|pre|preview) [-_\.]? [0-9]* )? @@ -191,7 +379,7 @@ class Specifier(BaseSpecifier): [0-9]+(?:\.[0-9]+)* # release (?: # pre release [-_\.]? - (alpha|beta|preview|pre|a|b|c|rc) + (a|b|c|rc|alpha|beta|pre|preview) [-_\.]? [0-9]* )? @@ -203,10 +391,7 @@ class Specifier(BaseSpecifier): ) """ - _regex = re.compile( - r"^\s*" + _operator_regex_str + _version_regex_str + r"\s*$", - re.VERBOSE | re.IGNORECASE, - ) + _regex = re.compile(r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE) _operators = { "~=": "compatible", @@ -219,153 +404,9 @@ class Specifier(BaseSpecifier): "===": "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 + @_require_version_compare + def _compare_compatible(self, prospective: ParsedVersion, spec: str) -> bool: - @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 @@ -374,7 +415,7 @@ def _compare_compatible(self, prospective: Version, spec: str) -> bool: # We want everything but the last item in the version, but we want to # ignore suffix segments. - prefix = _version_join( + prefix = ".".join( list(itertools.takewhile(_is_not_suffix, _version_split(spec)))[:-1] ) @@ -385,34 +426,34 @@ def _compare_compatible(self, prospective: Version, spec: str) -> bool: prospective, prefix ) - def _compare_equal(self, prospective: Version, spec: str) -> bool: + @_require_version_compare + def _compare_equal(self, prospective: ParsedVersion, 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) + prospective = Version(prospective.public) + # Split the spec out by dots, and pretend that there is an implicit + # dot in between a release segment and a pre-release segment. + split_spec = _version_split(spec[:-2]) # Remove the trailing .* - # 0-pad the prospective version before shortening it to get the correct - # shortened version. - padded_prospective, _ = _pad_version(split_prospective, split_spec) + # Split the prospective version out by dots, and pretend that there + # is an implicit dot in between a release segment and a pre-release + # segment. + split_prospective = _version_split(str(prospective)) # 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)] + shortened_prospective = split_prospective[: len(split_spec)] - return shortened_prospective == split_spec + # Pad out our two sides with zeros so that they both equal the same + # length. + padded_spec, padded_prospective = _pad_version( + split_spec, shortened_prospective + ) + + return padded_prospective == padded_spec else: # Convert our spec string into a Version spec_version = Version(spec) @@ -425,22 +466,31 @@ def _compare_equal(self, prospective: Version, spec: str) -> bool: return prospective == spec_version - def _compare_not_equal(self, prospective: Version, spec: str) -> bool: + @_require_version_compare + def _compare_not_equal(self, prospective: ParsedVersion, spec: str) -> bool: return not self._compare_equal(prospective, spec) - def _compare_less_than_equal(self, prospective: Version, spec: str) -> bool: + @_require_version_compare + def _compare_less_than_equal(self, prospective: ParsedVersion, 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: + @_require_version_compare + def _compare_greater_than_equal( + self, prospective: ParsedVersion, 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: + @_require_version_compare + def _compare_less_than(self, prospective: ParsedVersion, 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) @@ -464,7 +514,9 @@ def _compare_less_than(self, prospective: Version, spec_str: str) -> bool: # version in the spec. return True - def _compare_greater_than(self, prospective: Version, spec_str: str) -> bool: + @_require_version_compare + def _compare_greater_than(self, prospective: ParsedVersion, 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) @@ -497,150 +549,42 @@ def _compare_greater_than(self, prospective: Version, spec_str: str) -> bool: 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'] - """ + @property + def prereleases(self) -> bool: - yielded = False - found_prereleases = [] + # 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 - kw = {"prereleases": prereleases if prereleases is not None else True} + # 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] - # 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) + # Parse the version, and if it is a pre-release than this + # specifier allows pre-releases. + if parse(version).is_prerelease: + return True - 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 + return False - # 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 + @prereleases.setter + def prereleases(self, value: bool) -> None: + self._prereleases = value _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("."): +def _version_split(version: str) -> List[str]: + result: List[str] = [] + for item in version.split("."): match = _prefix_regex.search(item) if match: result.extend(match.groups()) @@ -649,24 +593,13 @@ def _version_split(version: str) -> list[str]: 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]]: +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 @@ -681,91 +614,35 @@ def _pad_version(left: list[str], right: list[str]) -> tuple[list[str], list[str 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)), - ) + return (list(itertools.chain(*left_split)), list(itertools.chain(*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, + self, specifiers: str = "", prereleases: Optional[bool] = 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()] + # Split on , to break each individual specifier into it's 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) + # Parsed each individual specifier, attempting first to make it a + # Specifier and falling back to a LegacySpecifier. + parsed: Set[_IndividualSpecifier] = set() + for specifier in split_specifiers: + try: + parsed.add(Specifier(specifier)) + except InvalidSpecifier: + parsed.add(LegacySpecifier(specifier)) + + # Turn our parsed specifiers into a frozen set and save them for later. + self._specs = frozenset(parsed) # 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 @@ -775,31 +652,12 @@ def __repr__(self) -> str: 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')> - """ + def __and__(self, other: Union["SpecifierSet", str]) -> "SpecifierSet": if isinstance(other, str): other = SpecifierSet(other) elif not isinstance(other, SpecifierSet): @@ -816,31 +674,14 @@ def __and__(self, other: SpecifierSet | str) -> SpecifierSet: specifier._prereleases = self._prereleases else: raise ValueError( - "Cannot combine SpecifierSets with True and False prerelease overrides." + "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)): + if isinstance(other, (str, _IndividualSpecifier)): other = SpecifierSet(str(other)) elif not isinstance(other, SpecifierSet): return NotImplemented @@ -848,72 +689,43 @@ def __eq__(self, other: object) -> bool: 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')>] - """ + def __iter__(self) -> Iterator[_IndividualSpecifier]: return iter(self._specs) + @property + def prereleases(self) -> Optional[bool]: + + # 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 __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, + self, item: UnparsedVersion, prereleases: Optional[bool] = 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) + + # Ensure that our item is a Version or LegacyVersion instance. + if not isinstance(item, (LegacyVersion, Version)): + item = parse(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 @@ -930,9 +742,6 @@ def contains( 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 @@ -940,46 +749,9 @@ def contains( 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'] - """ + self, iterable: Iterable[VersionTypeVar], prereleases: Optional[bool] = None + ) -> Iterable[VersionTypeVar]: + # 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. @@ -992,16 +764,27 @@ def filter( if self._specs: for spec in self._specs: iterable = spec.filter(iterable, prereleases=bool(prereleases)) - return iter(iterable) + return 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. + # releases, and which will filter out LegacyVersion in general. else: - filtered: list[UnparsedVersionVar] = [] - found_prereleases: list[UnparsedVersionVar] = [] + filtered: List[VersionTypeVar] = [] + found_prereleases: List[VersionTypeVar] = [] + + item: UnparsedVersion + parsed_version: Union[Version, LegacyVersion] for item in iterable: - parsed_version = _coerce_version(item) + # Ensure that we some kind of Version class for this item. + if not isinstance(item, (LegacyVersion, Version)): + parsed_version = parse(item) + else: + parsed_version = item + + # Filter out any item which is parsed as a LegacyVersion + if isinstance(parsed_version, LegacyVersion): + continue # Store any item which is a pre-release for later unless we've # already found a final version or we are accepting prereleases @@ -1014,6 +797,6 @@ def filter( # 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 found_prereleases - return iter(filtered) + return filtered diff --git a/venv1/Lib/site-packages/pip/_vendor/packaging/tags.py b/venv1/Lib/site-packages/pip/_vendor/packaging/tags.py index 8522f59c..9a3d25a7 100644 --- a/venv1/Lib/site-packages/pip/_vendor/packaging/tags.py +++ b/venv1/Lib/site-packages/pip/_vendor/packaging/tags.py @@ -2,21 +2,21 @@ # 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 ( + Dict, + FrozenSet, Iterable, Iterator, + List, + Optional, Sequence, Tuple, + Union, cast, ) @@ -25,9 +25,9 @@ logger = logging.getLogger(__name__) PythonVersion = Sequence[int] -AppleVersion = Tuple[int, int] +MacVersion = Tuple[int, int] -INTERPRETER_SHORT_NAMES: dict[str, str] = { +INTERPRETER_SHORT_NAMES: Dict[str, str] = { "python": "py", # Generic. "cpython": "cp", "pypy": "pp", @@ -36,7 +36,7 @@ } -_32_BIT_INTERPRETER = struct.calcsize("P") == 4 +_32_BIT_INTERPRETER = sys.maxsize <= 2 ** 32 class Tag: @@ -47,7 +47,7 @@ class Tag: is also supported. """ - __slots__ = ["_abi", "_hash", "_interpreter", "_platform"] + __slots__ = ["_interpreter", "_abi", "_platform", "_hash"] def __init__(self, interpreter: str, abi: str, platform: str) -> None: self._interpreter = interpreter.lower() @@ -93,7 +93,7 @@ def __repr__(self) -> str: return f"<{self} @ {id(self)}>" -def parse_tag(tag: str) -> frozenset[Tag]: +def parse_tag(tag: str) -> FrozenSet[Tag]: """ Parses the provided tag (e.g. `py3-none-any`) into a frozenset of Tag instances. @@ -109,8 +109,8 @@ def parse_tag(tag: str) -> frozenset[Tag]: return frozenset(tags) -def _get_config_var(name: str, warn: bool = False) -> int | str | None: - value: int | str | None = sysconfig.get_config_var(name) +def _get_config_var(name: str, warn: bool = False) -> Union[int, str, None]: + value = 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 @@ -119,40 +119,23 @@ def _get_config_var(name: str, warn: bool = False) -> int | str | None: def _normalize_string(string: str) -> str: - return string.replace(".", "_").replace("-", "_").replace(" ", "_") - + return string.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: +def _abi3_applies(python_version: PythonVersion) -> 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. + PEP 384 was first implemented in Python 3.2. """ - return len(python_version) > 1 and tuple(python_version) >= (3, 2) and not threading + return len(python_version) > 1 and tuple(python_version) >= (3, 2) -def _cpython_abis(py_version: PythonVersion, warn: bool = False) -> list[str]: +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 = "" + 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 @@ -161,8 +144,6 @@ def _cpython_abis(py_version: PythonVersion, warn: bool = False) -> list[str]: 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: @@ -176,15 +157,20 @@ def _cpython_abis(py_version: PythonVersion, warn: bool = False) -> list[str]: 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}") + abis.append(f"cp{version}") + abis.insert( + 0, + "cp{version}{debug}{pymalloc}{ucs4}".format( + version=version, debug=debug, pymalloc=pymalloc, ucs4=ucs4 + ), + ) return abis def cpython_tags( - python_version: PythonVersion | None = None, - abis: Iterable[str] | None = None, - platforms: Iterable[str] | None = None, + python_version: Optional[PythonVersion] = None, + abis: Optional[Iterable[str]] = None, + platforms: Optional[Iterable[str]] = None, *, warn: bool = False, ) -> Iterator[Tag]: @@ -225,66 +211,29 @@ def cpython_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: + if _abi3_applies(python_version): yield from (Tag(interpreter, "abi3", platform_) for platform_ in platforms) yield from (Tag(interpreter, "none", platform_) for platform_ in platforms) - if use_abi3: + if _abi3_applies(python_version): 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}" + interpreter = "cp{version}".format( + version=_version_nodot((python_version[0], minor_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_abi() -> Iterator[str]: + abi = sysconfig.get_config_var("SOABI") + if abi: + yield _normalize_string(abi) def generic_tags( - interpreter: str | None = None, - abis: Iterable[str] | None = None, - platforms: Iterable[str] | None = None, + interpreter: Optional[str] = None, + abis: Optional[Iterable[str]] = None, + platforms: Optional[Iterable[str]] = None, *, warn: bool = False, ) -> Iterator[Tag]: @@ -302,9 +251,8 @@ def generic_tags( interpreter = "".join([interp_name, interp_version]) if abis is None: abis = _generic_abi() - else: - abis = list(abis) platforms = list(platforms or platform_tags()) + abis = list(abis) if "none" not in abis: abis.append("none") for abi in abis: @@ -328,9 +276,9 @@ def _py_interpreter_range(py_version: PythonVersion) -> Iterator[str]: def compatible_tags( - python_version: PythonVersion | None = None, - interpreter: str | None = None, - platforms: Iterable[str] | None = None, + python_version: Optional[PythonVersion] = None, + interpreter: Optional[str] = None, + platforms: Optional[Iterable[str]] = None, ) -> Iterator[Tag]: """ Yields the sequence of tags that are compatible with a specific version of Python. @@ -362,7 +310,7 @@ def _mac_arch(arch: str, is_32bit: bool = _32_BIT_INTERPRETER) -> str: return "i386" -def _mac_binary_formats(version: AppleVersion, cpu_arch: str) -> list[str]: +def _mac_binary_formats(version: MacVersion, cpu_arch: str) -> List[str]: formats = [cpu_arch] if cpu_arch == "x86_64": if version < (10, 4): @@ -395,7 +343,7 @@ def _mac_binary_formats(version: AppleVersion, cpu_arch: str) -> list[str]: def mac_platforms( - version: AppleVersion | None = None, arch: str | None = None + version: Optional[MacVersion] = None, arch: Optional[str] = None ) -> Iterator[str]: """ Yields the platform tags for a macOS system. @@ -407,23 +355,7 @@ def mac_platforms( """ 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]))) + version = cast("MacVersion", tuple(map(int, version_str.split(".")[:2]))) else: version = version if arch is None: @@ -434,22 +366,24 @@ def mac_platforms( 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 + compat_version = 10, 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}" + yield "macosx_{major}_{minor}_{binary_format}".format( + major=10, minor=minor_version, binary_format=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 + compat_version = major_version, 0 binary_formats = _mac_binary_formats(compat_version, arch) for binary_format in binary_formats: - yield f"macosx_{major_version}_{minor_version}_{binary_format}" + yield "macosx_{major}_{minor}_{binary_format}".format( + major=major_version, minor=0, binary_format=binary_format + ) if version >= (11, 0): # Mac OS 11 on x86_64 is compatible with binaries from previous releases. @@ -459,131 +393,38 @@ def mac_platforms( # 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 + compat_version = 10, 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}" + yield "macosx_{major}_{minor}_{binary_format}".format( + major=compat_version[0], + minor=compat_version[1], + binary_format=binary_format, + ) else: for minor_version in range(16, 3, -1): - compat_version = major_version, minor_version + compat_version = 10, 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 android_platforms( - api_level: int | None = None, abi: str | None = None -) -> Iterator[str]: - """ - Yields the :attr:`~Tag.platform` tags for Android. If this function is invoked on - non-Android platforms, the ``api_level`` and ``abi`` arguments are required. - - :param int api_level: The maximum `API level - `__ to return. Defaults - to the current system's version, as returned by ``platform.android_ver``. - :param str abi: The `Android ABI `__, - e.g. ``arm64_v8a``. Defaults to the current system's ABI , as returned by - ``sysconfig.get_platform``. Hyphens and periods will be replaced with - underscores. - """ - if platform.system() != "Android" and (api_level is None or abi is None): - raise TypeError( - "on non-Android platforms, the api_level and abi arguments are required" - ) - - if api_level is None: - # Python 3.13 was the first version to return platform.system() == "Android", - # and also the first version to define platform.android_ver(). - api_level = platform.android_ver().api_level # type: ignore[attr-defined] - - if abi is None: - abi = sysconfig.get_platform().split("-")[-1] - abi = _normalize_string(abi) - - # 16 is the minimum API level known to have enough features to support CPython - # without major patching. Yield every API level from the maximum down to the - # minimum, inclusive. - min_api_level = 16 - for ver in range(api_level, min_api_level - 1, -1): - yield f"android_{ver}_{abi}" + yield "macosx_{major}_{minor}_{binary_format}".format( + major=compat_version[0], + minor=compat_version[1], + binary_format=binary_format, + ) 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" + linux = "linux_armv7l" _, 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}" + yield from _manylinux.platform_tags(linux, arch) + yield from _musllinux.platform_tags(arch) + yield linux def _generic_platforms() -> Iterator[str]: @@ -596,10 +437,6 @@ def platform_tags() -> Iterator[str]: """ if platform.system() == "Darwin": return mac_platforms() - elif platform.system() == "iOS": - return ios_platforms() - elif platform.system() == "Android": - return android_platforms() elif platform.system() == "Linux": return _linux_platforms() else: @@ -609,9 +446,6 @@ def platform_tags() -> Iterator[str]: 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 @@ -648,9 +482,6 @@ def sys_tags(*, warn: bool = False) -> Iterator[Tag]: yield from generic_tags() if interp_name == "pp": - interp = "pp3" - elif interp_name == "cp": - interp = "cp" + interpreter_version(warn=warn) + yield from compatible_tags(interpreter="pp3") else: - interp = None - yield from compatible_tags(interpreter=interp) + yield from compatible_tags() diff --git a/venv1/Lib/site-packages/pip/_vendor/packaging/utils.py b/venv1/Lib/site-packages/pip/_vendor/packaging/utils.py index 23450953..bab11b80 100644 --- a/venv1/Lib/site-packages/pip/_vendor/packaging/utils.py +++ b/venv1/Lib/site-packages/pip/_vendor/packaging/utils.py @@ -2,25 +2,16 @@ # 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 typing import FrozenSet, NewType, Tuple, Union, cast from .tags import Tag, parse_tag -from .version import InvalidVersion, Version, _TrimmedRelease +from .version import InvalidVersion, Version 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. @@ -33,99 +24,88 @@ class InvalidSdistFilename(ValueError): """ -# 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}") +def canonicalize_name(name: str) -> NormalizedName: # 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: +def canonicalize_version(version: Union[Version, str]) -> str: """ - Return a canonical form of a version as a string. + This is very similar to Version.__str__, but has one subtle difference + with the way it handles the release segment. + """ + if isinstance(version, str): + try: + parsed = Version(version) + except InvalidVersion: + # Legacy versions cannot be normalized + return version + else: + parsed = version - >>> canonicalize_version('1.0.1') - '1.0.1' + parts = [] - Per PEP 625, versions may have multiple canonical forms, differing - only by trailing zeros. + # Epoch + if parsed.epoch != 0: + parts.append(f"{parsed.epoch}!") - >>> canonicalize_version('1.0.0') - '1' - >>> canonicalize_version('1.0.0', strip_trailing_zero=False) - '1.0.0' + # Release segment + # NB: This strips trailing '.0's to normalize + parts.append(re.sub(r"(\.0)+$", "", ".".join(str(x) for x in parsed.release))) - Invalid versions are returned unaltered. + # Pre-release + if parsed.pre is not None: + parts.append("".join(str(x) for x in parsed.pre)) - >>> canonicalize_version('foo bar baz') - 'foo bar baz' - """ - return str(_TrimmedRelease(str(version)) if strip_trailing_zero else version) + # Post-release + if parsed.post is not None: + parts.append(f".post{parsed.post}") + + # Development release + if parsed.dev is not None: + parts.append(f".dev{parsed.dev}") + # Local version segment + if parsed.local is not None: + parts.append(f"+{parsed.local}") -@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) + return "".join(parts) def parse_wheel_filename( filename: str, -) -> tuple[NormalizedName, Version, BuildTag, frozenset[Tag]]: +) -> Tuple[NormalizedName, Version, BuildTag, FrozenSet[Tag]]: if not filename.endswith(".whl"): raise InvalidWheelFilename( - f"Invalid wheel filename (extension must be '.whl'): {filename!r}" + f"Invalid wheel filename (extension must be '.whl'): {filename}" ) filename = filename[:-4] dashes = filename.count("-") if dashes not in (4, 5): raise InvalidWheelFilename( - f"Invalid wheel filename (wrong number of parts): {filename!r}" + f"Invalid wheel filename (wrong number of parts): {filename}" ) parts = filename.split("-", dashes - 2) name_part = parts[0] - # See PEP 427 for the rules on escaping the project name. + # 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}") + raise InvalidWheelFilename(f"Invalid project name: {filename}") 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 - + version = Version(parts[1]) 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}" + f"Invalid build number: {build_part} in '{filename}'" ) build = cast(BuildTag, (int(build_match.group(1)), build_match.group(2))) else: @@ -134,7 +114,7 @@ def parse_wheel_filename( return (name, version, build, tags) -def parse_sdist_filename(filename: str) -> tuple[NormalizedName, Version]: +def parse_sdist_filename(filename: str) -> Tuple[NormalizedName, Version]: if filename.endswith(".tar.gz"): file_stem = filename[: -len(".tar.gz")] elif filename.endswith(".zip"): @@ -142,22 +122,15 @@ def parse_sdist_filename(filename: str) -> tuple[NormalizedName, Version]: else: raise InvalidSdistFilename( f"Invalid sdist filename (extension must be '.tar.gz' or '.zip'):" - f" {filename!r}" + f" {filename}" ) # 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}") + raise InvalidSdistFilename(f"Invalid sdist filename: {filename}") 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 - + version = Version(version_part) return (name, version) diff --git a/venv1/Lib/site-packages/pip/_vendor/packaging/version.py b/venv1/Lib/site-packages/pip/_vendor/packaging/version.py index 21f44ca0..de9a09a4 100644 --- a/venv1/Lib/site-packages/pip/_vendor/packaging/version.py +++ b/venv1/Lib/site-packages/pip/_vendor/packaging/version.py @@ -1,73 +1,64 @@ # 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 pip._vendor.packaging.version import parse, Version -""" - -from __future__ import annotations +import collections import itertools import re -from typing import Any, Callable, NamedTuple, SupportsInt, Tuple, Union +import warnings +from typing import Callable, Iterator, List, Optional, SupportsInt, Tuple, Union from ._structures import Infinity, InfinityType, NegativeInfinity, NegativeInfinityType -__all__ = ["VERSION_PATTERN", "InvalidVersion", "Version", "parse"] - -LocalType = Tuple[Union[int, str], ...] +__all__ = ["parse", "Version", "LegacyVersion", "InvalidVersion", "VERSION_PATTERN"] -CmpPrePostDevType = Union[InfinityType, NegativeInfinityType, Tuple[str, int]] -CmpLocalType = Union[ +InfiniteTypes = Union[InfinityType, NegativeInfinityType] +PrePostDevType = Union[InfiniteTypes, Tuple[str, int]] +SubLocalType = Union[InfiniteTypes, int, str] +LocalType = Union[ NegativeInfinityType, - Tuple[Union[Tuple[int, str], Tuple[NegativeInfinityType, Union[int, str]]], ...], + Tuple[ + Union[ + SubLocalType, + Tuple[SubLocalType, str], + Tuple[NegativeInfinityType, SubLocalType], + ], + ..., + ], ] CmpKey = Tuple[ - int, - Tuple[int, ...], - CmpPrePostDevType, - CmpPrePostDevType, - CmpPrePostDevType, - CmpLocalType, + int, Tuple[int, ...], PrePostDevType, PrePostDevType, PrePostDevType, LocalType +] +LegacyCmpKey = Tuple[int, Tuple[str, ...]] +VersionComparisonMethod = Callable[ + [Union[CmpKey, LegacyCmpKey], Union[CmpKey, LegacyCmpKey]], bool ] -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. +_Version = collections.namedtuple( + "_Version", ["epoch", "release", "dev", "pre", "post", "local"] +) - >>> parse('1.0.dev1') - - :param version: The version string to parse. - :raises InvalidVersion: When the version string is not a valid version. +def parse(version: str) -> Union["LegacyVersion", "Version"]: """ - return Version(version) + Parse the given version string and return either a :class:`Version` object + or a :class:`LegacyVersion` object depending on if the given version is + a valid PEP 440 version or a legacy version. + """ + try: + return Version(version) + except InvalidVersion: + return LegacyVersion(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' + """ + An invalid version was found, users should refer to PEP 440. """ class _BaseVersion: - _key: tuple[Any, ...] + _key: Union[CmpKey, LegacyCmpKey] def __hash__(self) -> int: return hash(self._key) @@ -75,13 +66,13 @@ def __hash__(self) -> int: # 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: + def __lt__(self, other: "_BaseVersion") -> bool: if not isinstance(other, _BaseVersion): return NotImplemented return self._key < other._key - def __le__(self, other: _BaseVersion) -> bool: + def __le__(self, other: "_BaseVersion") -> bool: if not isinstance(other, _BaseVersion): return NotImplemented @@ -93,13 +84,13 @@ def __eq__(self, other: object) -> bool: return self._key == other._key - def __ge__(self, other: _BaseVersion) -> bool: + def __ge__(self, other: "_BaseVersion") -> bool: if not isinstance(other, _BaseVersion): return NotImplemented return self._key >= other._key - def __gt__(self, other: _BaseVersion) -> bool: + def __gt__(self, other: "_BaseVersion") -> bool: if not isinstance(other, _BaseVersion): return NotImplemented @@ -112,16 +103,133 @@ def __ne__(self, other: object) -> bool: return self._key != other._key +class LegacyVersion(_BaseVersion): + def __init__(self, version: str) -> None: + self._version = str(version) + self._key = _legacy_cmpkey(self._version) + + warnings.warn( + "Creating a LegacyVersion has been deprecated and will be " + "removed in the next major release", + DeprecationWarning, + ) + + def __str__(self) -> str: + return self._version + + def __repr__(self) -> str: + return f"" + + @property + def public(self) -> str: + return self._version + + @property + def base_version(self) -> str: + return self._version + + @property + def epoch(self) -> int: + return -1 + + @property + def release(self) -> None: + return None + + @property + def pre(self) -> None: + return None + + @property + def post(self) -> None: + return None + + @property + def dev(self) -> None: + return None + + @property + def local(self) -> None: + return None + + @property + def is_prerelease(self) -> bool: + return False + + @property + def is_postrelease(self) -> bool: + return False + + @property + def is_devrelease(self) -> bool: + return False + + +_legacy_version_component_re = re.compile(r"(\d+ | [a-z]+ | \.| -)", re.VERBOSE) + +_legacy_version_replacement_map = { + "pre": "c", + "preview": "c", + "-": "final-", + "rc": "c", + "dev": "@", +} + + +def _parse_version_parts(s: str) -> Iterator[str]: + for part in _legacy_version_component_re.split(s): + part = _legacy_version_replacement_map.get(part, part) + + if not part or part == ".": + continue + + if part[:1] in "0123456789": + # pad for numeric comparison + yield part.zfill(8) + else: + yield "*" + part + + # ensure that alpha/beta/candidate are before final + yield "*final" + + +def _legacy_cmpkey(version: str) -> LegacyCmpKey: + + # We hardcode an epoch of -1 here. A PEP 440 version can only have a epoch + # greater than or equal to 0. This will effectively put the LegacyVersion, + # which uses the defacto standard originally implemented by setuptools, + # as before all PEP 440 versions. + epoch = -1 + + # This scheme is taken from pkg_resources.parse_version setuptools prior to + # it's adoption of the packaging library. + parts: List[str] = [] + for part in _parse_version_parts(version.lower()): + if part.startswith("*"): + # remove "-" before a prerelease tag + if part < "*final": + while parts and parts[-1] == "*final-": + parts.pop() + + # remove trailing zeros from each series of numeric parts + while parts and parts[-1] == "00000000": + parts.pop() + + parts.append(part) + + return epoch, tuple(parts) + + # Deliberately not anchored to the start and end of the string, to make it # easier for 3rd party code to reuse -_VERSION_PATTERN = r""" +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(a|b|c|rc|alpha|beta|pre|preview))
             [-_\.]?
             (?P[0-9]+)?
         )?
@@ -145,61 +253,17 @@ def __ne__(self, other: object) -> bool:
     (?:\+(?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}")
+            raise InvalidVersion(f"Invalid version: '{version}'")
 
         # Store the parsed out pieces of the version
         self._version = _Version(
@@ -224,19 +288,9 @@ def __init__(self, version: str) -> None:
         )
 
     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
@@ -266,77 +320,29 @@ def __str__(self) -> str:
 
     @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
+        _epoch: int = self._version.epoch
+        return _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
+    def release(self) -> Tuple[int, ...]:
+        _release: Tuple[int, ...] = self._version.release
+        return _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
+    def pre(self) -> Optional[Tuple[str, int]]:
+        _pre: Optional[Tuple[str, int]] = self._version.pre
+        return _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
-        """
+    def post(self) -> Optional[int]:
         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
-        """
+    def dev(self) -> Optional[int]:
         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'
-        """
+    def local(self) -> Optional[str]:
         if self._version.local:
             return ".".join(str(x) for x in self._version.local)
         else:
@@ -344,31 +350,10 @@ def local(self) -> str | 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
@@ -382,95 +367,33 @@ def base_version(self) -> str:
 
     @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:
+    letter: str, number: Union[str, bytes, SupportsInt]
+) -> Optional[Tuple[str, int]]:
+
     if letter:
         # We consider there to be an implicit 0 in a pre-release if there is
         # not a numeral associated with it.
@@ -493,9 +416,7 @@ def _parse_letter_version(
             letter = "post"
 
         return letter, int(number)
-
-    assert not letter
-    if number:
+    if not letter and 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"
@@ -508,7 +429,7 @@ def _parse_letter_version(
 _local_version_separators = re.compile(r"[\._-]")
 
 
-def _parse_local_version(local: str | None) -> LocalType | None:
+def _parse_local_version(local: str) -> Optional[LocalType]:
     """
     Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").
     """
@@ -522,12 +443,13 @@ def _parse_local_version(local: str | None) -> LocalType | 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,
+    release: Tuple[int, ...],
+    pre: Optional[Tuple[str, int]],
+    post: Optional[Tuple[str, int]],
+    dev: Optional[Tuple[str, int]],
+    local: Optional[Tuple[SubLocalType]],
 ) -> 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
@@ -542,7 +464,7 @@ def _cmpkey(
     # 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
+        _pre: PrePostDevType = NegativeInfinity
     # Versions without a pre-release (except as noted above) should sort after
     # those with one.
     elif pre is None:
@@ -552,21 +474,21 @@ def _cmpkey(
 
     # Versions without a post segment should sort before those with one.
     if post is None:
-        _post: CmpPrePostDevType = NegativeInfinity
+        _post: PrePostDevType = NegativeInfinity
 
     else:
         _post = post
 
     # Versions without a development segment should sort after those with one.
     if dev is None:
-        _dev: CmpPrePostDevType = Infinity
+        _dev: PrePostDevType = Infinity
 
     else:
         _dev = dev
 
     if local is None:
         # Versions without a local segment should sort before those with one.
-        _local: CmpLocalType = NegativeInfinity
+        _local: LocalType = NegativeInfinity
     else:
         # Versions with a local segment need that segment parsed to implement
         # the sorting rules in PEP440.
diff --git a/venv1/Lib/site-packages/pip/_vendor/pkg_resources/__init__.py b/venv1/Lib/site-packages/pip/_vendor/pkg_resources/__init__.py
index 72f2b035..1bf26a94 100644
--- a/venv1/Lib/site-packages/pip/_vendor/pkg_resources/__init__.py
+++ b/venv1/Lib/site-packages/pip/_vendor/pkg_resources/__init__.py
@@ -1,6 +1,3 @@
-# TODO: Add Generic type annotations to initialized collections.
-# For now we'd simply use implicit Any/Unknown which would add redundant annotations
-# mypy: disable-error-code="var-annotated"
 """
 Package resource API
 --------------------
@@ -16,40 +13,19 @@
 .zip files and with custom PEP 302 loaders that support the ``get_data()``
 method.
 
-This module is deprecated. Users are directed to :mod:`importlib.resources`,
-:mod:`importlib.metadata` and :pypi:`packaging` instead.
+This module is deprecated. Users are directed to
+`importlib.resources `_
+and
+`importlib.metadata `_
+instead.
 """
 
-from __future__ import annotations
-
 import sys
-
-if sys.version_info < (3, 8):  # noqa: UP036 # Check for unsupported versions
-    raise RuntimeError("Python 3.8 or later is required")
-
 import os
 import io
 import time
 import re
 import types
-from typing import (
-    Any,
-    Literal,
-    Dict,
-    Iterator,
-    Mapping,
-    MutableSequence,
-    NamedTuple,
-    NoReturn,
-    Tuple,
-    Union,
-    TYPE_CHECKING,
-    Protocol,
-    Callable,
-    Iterable,
-    TypeVar,
-    overload,
-)
 import zipfile
 import zipimport
 import warnings
@@ -68,16 +44,21 @@
 import ntpath
 import posixpath
 import importlib
-import importlib.abc
-import importlib.machinery
 from pkgutil import get_importer
 
-import _imp
+try:
+    import _imp
+except ImportError:
+    # Python 3.2 compatibility
+    import imp as _imp
+
+try:
+    FileExistsError
+except NameError:
+    FileExistsError = OSError
 
 # capture these to bypass sandboxing
 from os import utime
-from os import open as os_open
-from os.path import isdir, split
 
 try:
     from os import mkdir, rename, unlink
@@ -87,57 +68,57 @@
     # no write support, probably under GAE
     WRITE_SUPPORT = False
 
+from os import open as os_open
+from os.path import isdir, split
+
+try:
+    import importlib.machinery as importlib_machinery
+
+    # access attribute to force import under delayed import mechanisms.
+    importlib_machinery.__name__
+except ImportError:
+    importlib_machinery = None
+
 from pip._internal.utils._jaraco_text import (
     yield_lines,
     drop_comment,
     join_continuation,
 )
-from pip._vendor.packaging import markers as _packaging_markers
-from pip._vendor.packaging import requirements as _packaging_requirements
-from pip._vendor.packaging import utils as _packaging_utils
-from pip._vendor.packaging import version as _packaging_version
-from pip._vendor.platformdirs import user_cache_dir as _user_cache_dir
-
-if TYPE_CHECKING:
-    from _typeshed import BytesPath, StrPath, StrOrBytesPath
-    from typing_extensions import Self
-
-
-# Patch: Remove deprecation warning from vendored pkg_resources.
-# Setting PYTHONWARNINGS=error to verify builds produce no warnings
-# causes immediate exceptions.
-# See https://github.com/pypa/pip/issues/12243
-
-
-_T = TypeVar("_T")
-_DistributionT = TypeVar("_DistributionT", bound="Distribution")
-# Type aliases
-_NestedStr = Union[str, Iterable[Union[str, Iterable["_NestedStr"]]]]
-_InstallerTypeT = Callable[["Requirement"], "_DistributionT"]
-_InstallerType = Callable[["Requirement"], Union["Distribution", None]]
-_PkgReqType = Union[str, "Requirement"]
-_EPDistType = Union["Distribution", _PkgReqType]
-_MetadataType = Union["IResourceProvider", None]
-_ResolvedEntryPoint = Any  # Can be any attribute in the module
-_ResourceStream = Any  # TODO / Incomplete: A readable file-like object
-# Any object works, but let's indicate we expect something like a module (optionally has __loader__ or __file__)
-_ModuleLike = Union[object, types.ModuleType]
-# Any: Should be _ModuleLike but we end up with issues where _ModuleLike doesn't have _ZipLoaderModule's __loader__
-_ProviderFactoryType = Callable[[Any], "IResourceProvider"]
-_DistFinderType = Callable[[_T, str, bool], Iterable["Distribution"]]
-_NSHandlerType = Callable[[_T, str, str, types.ModuleType], Union[str, None]]
-_AdapterT = TypeVar(
-    "_AdapterT", _DistFinderType[Any], _ProviderFactoryType, _NSHandlerType[Any]
-)
-
 
-# Use _typeshed.importlib.LoaderProtocol once available https://github.com/python/typeshed/pull/11890
-class _LoaderProtocol(Protocol):
-    def load_module(self, fullname: str, /) -> types.ModuleType: ...
-
-
-class _ZipLoaderModule(Protocol):
-    __loader__: zipimport.zipimporter
+from pip._vendor import platformdirs
+from pip._vendor import packaging
+
+__import__('pip._vendor.packaging.version')
+__import__('pip._vendor.packaging.specifiers')
+__import__('pip._vendor.packaging.requirements')
+__import__('pip._vendor.packaging.markers')
+__import__('pip._vendor.packaging.utils')
+
+if sys.version_info < (3, 5):
+    raise RuntimeError("Python 3.5 or later is required")
+
+# declare some globals that will be defined later to
+# satisfy the linters.
+require = None
+working_set = None
+add_activation_listener = None
+resources_stream = None
+cleanup_resources = None
+resource_dir = None
+resource_stream = None
+set_extraction_path = None
+resource_isdir = None
+resource_string = None
+iter_entry_points = None
+resource_listdir = None
+resource_filename = None
+resource_exists = None
+_distribution_finders = None
+_namespace_handlers = None
+_namespace_packages = None
+
+
+warnings.warn("pkg_resources is deprecated as an API", DeprecationWarning)
 
 
 _PEP440_FALLBACK = re.compile(r"^v?(?P(?:[0-9]+!)?[0-9]+(?:\.[0-9]+)*)", re.I)
@@ -150,18 +131,18 @@ class PEP440Warning(RuntimeWarning):
     """
 
 
-parse_version = _packaging_version.Version
+parse_version = packaging.version.Version
 
 
-_state_vars: dict[str, str] = {}
+_state_vars = {}
 
 
-def _declare_state(vartype: str, varname: str, initial_value: _T) -> _T:
-    _state_vars[varname] = vartype
-    return initial_value
+def _declare_state(vartype, **kw):
+    globals().update(kw)
+    _state_vars.update(dict.fromkeys(kw, vartype))
 
 
-def __getstate__() -> dict[str, Any]:
+def __getstate__():
     state = {}
     g = globals()
     for k, v in _state_vars.items():
@@ -169,7 +150,7 @@ def __getstate__() -> dict[str, Any]:
     return state
 
 
-def __setstate__(state: dict[str, Any]) -> dict[str, Any]:
+def __setstate__(state):
     g = globals()
     for k, v in state.items():
         g['_sset_' + _state_vars[k]](k, g[k], v)
@@ -324,17 +305,17 @@ class VersionConflict(ResolutionError):
     _template = "{self.dist} is installed but {self.req} is required"
 
     @property
-    def dist(self) -> Distribution:
+    def dist(self):
         return self.args[0]
 
     @property
-    def req(self) -> Requirement:
+    def req(self):
         return self.args[1]
 
     def report(self):
         return self._template.format(**locals())
 
-    def with_context(self, required_by: set[Distribution | str]):
+    def with_context(self, required_by):
         """
         If required_by is non-empty, return a version of self that is a
         ContextualVersionConflict.
@@ -354,7 +335,7 @@ class ContextualVersionConflict(VersionConflict):
     _template = VersionConflict._template + ' by {self.required_by}'
 
     @property
-    def required_by(self) -> set[str]:
+    def required_by(self):
         return self.args[2]
 
 
@@ -367,11 +348,11 @@ class DistributionNotFound(ResolutionError):
     )
 
     @property
-    def req(self) -> Requirement:
+    def req(self):
         return self.args[0]
 
     @property
-    def requirers(self) -> set[str] | None:
+    def requirers(self):
         return self.args[1]
 
     @property
@@ -391,7 +372,7 @@ class UnknownExtra(ResolutionError):
     """Distribution doesn't have an "extra feature" of the given name"""
 
 
-_provider_factories: dict[type[_ModuleLike], _ProviderFactoryType] = {}
+_provider_factories = {}
 
 PY_MAJOR = '{}.{}'.format(*sys.version_info)
 EGG_DIST = 3
@@ -401,9 +382,7 @@ class UnknownExtra(ResolutionError):
 DEVELOP_DIST = -1
 
 
-def register_loader_type(
-    loader_type: type[_ModuleLike], provider_factory: _ProviderFactoryType
-):
+def register_loader_type(loader_type, provider_factory):
     """Register `provider_factory` to make providers for `loader_type`
 
     `loader_type` is the type or class of a PEP 302 ``module.__loader__``,
@@ -413,11 +392,7 @@ def register_loader_type(
     _provider_factories[loader_type] = provider_factory
 
 
-@overload
-def get_provider(moduleOrReq: str) -> IResourceProvider: ...
-@overload
-def get_provider(moduleOrReq: Requirement) -> Distribution: ...
-def get_provider(moduleOrReq: str | Requirement) -> IResourceProvider | Distribution:
+def get_provider(moduleOrReq):
     """Return an IResourceProvider for the named module or requirement"""
     if isinstance(moduleOrReq, Requirement):
         return working_set.find(moduleOrReq) or require(str(moduleOrReq))[0]
@@ -430,18 +405,20 @@ def get_provider(moduleOrReq: str | Requirement) -> IResourceProvider | Distribu
     return _find_adapter(_provider_factories, loader)(module)
 
 
-@functools.lru_cache(maxsize=None)
-def _macos_vers():
-    version = platform.mac_ver()[0]
-    # fallback for MacPorts
-    if version == '':
-        plist = '/System/Library/CoreServices/SystemVersion.plist'
-        if os.path.exists(plist):
-            with open(plist, 'rb') as fh:
-                plist_content = plistlib.load(fh)
-            if 'ProductVersion' in plist_content:
-                version = plist_content['ProductVersion']
-    return version.split('.')
+def _macos_vers(_cache=[]):
+    if not _cache:
+        version = platform.mac_ver()[0]
+        # fallback for MacPorts
+        if version == '':
+            plist = '/System/Library/CoreServices/SystemVersion.plist'
+            if os.path.exists(plist):
+                if hasattr(plistlib, 'readPlist'):
+                    plist_content = plistlib.readPlist(plist)
+                    if 'ProductVersion' in plist_content:
+                        version = plist_content['ProductVersion']
+
+        _cache.append(version.split('.'))
+    return _cache[0]
 
 
 def _macos_arch(machine):
@@ -479,7 +456,7 @@ def get_build_platform():
 get_platform = get_build_platform
 
 
-def compatible_platforms(provided: str | None, required: str | None):
+def compatible_platforms(provided, required):
     """Can code for the `provided` platform run on the `required` platform?
 
     Returns true if either platform is ``None``, or the platforms are equal.
@@ -528,106 +505,102 @@ def compatible_platforms(provided: str | None, required: str | None):
     return False
 
 
-@overload
-def get_distribution(dist: _DistributionT) -> _DistributionT: ...
-@overload
-def get_distribution(dist: _PkgReqType) -> Distribution: ...
-def get_distribution(dist: Distribution | _PkgReqType) -> Distribution:
+def run_script(dist_spec, script_name):
+    """Locate distribution `dist_spec` and run its `script_name` script"""
+    ns = sys._getframe(1).f_globals
+    name = ns['__name__']
+    ns.clear()
+    ns['__name__'] = name
+    require(dist_spec)[0].run_script(script_name, ns)
+
+
+# backward compatibility
+run_main = run_script
+
+
+def get_distribution(dist):
     """Return a current distribution object for a Requirement or string"""
     if isinstance(dist, str):
         dist = Requirement.parse(dist)
     if isinstance(dist, Requirement):
-        # Bad type narrowing, dist has to be a Requirement here, so get_provider has to return Distribution
-        dist = get_provider(dist)  # type: ignore[assignment]
+        dist = get_provider(dist)
     if not isinstance(dist, Distribution):
-        raise TypeError("Expected str, Requirement, or Distribution", dist)
+        raise TypeError("Expected string, Requirement, or Distribution", dist)
     return dist
 
 
-def load_entry_point(dist: _EPDistType, group: str, name: str) -> _ResolvedEntryPoint:
+def load_entry_point(dist, group, name):
     """Return `name` entry point of `group` for `dist` or raise ImportError"""
     return get_distribution(dist).load_entry_point(group, name)
 
 
-@overload
-def get_entry_map(
-    dist: _EPDistType, group: None = None
-) -> dict[str, dict[str, EntryPoint]]: ...
-@overload
-def get_entry_map(dist: _EPDistType, group: str) -> dict[str, EntryPoint]: ...
-def get_entry_map(dist: _EPDistType, group: str | None = None):
+def get_entry_map(dist, group=None):
     """Return the entry point map for `group`, or the full entry map"""
     return get_distribution(dist).get_entry_map(group)
 
 
-def get_entry_info(dist: _EPDistType, group: str, name: str):
+def get_entry_info(dist, group, name):
     """Return the EntryPoint object for `group`+`name`, or ``None``"""
     return get_distribution(dist).get_entry_info(group, name)
 
 
-class IMetadataProvider(Protocol):
-    def has_metadata(self, name: str) -> bool:
+class IMetadataProvider:
+    def has_metadata(name):
         """Does the package's distribution contain the named metadata?"""
 
-    def get_metadata(self, name: str) -> str:
+    def get_metadata(name):
         """The named metadata resource as a string"""
 
-    def get_metadata_lines(self, name: str) -> Iterator[str]:
+    def get_metadata_lines(name):
         """Yield named metadata resource as list of non-blank non-comment lines
 
         Leading and trailing whitespace is stripped from each line, and lines
         with ``#`` as the first non-blank character are omitted."""
 
-    def metadata_isdir(self, name: str) -> bool:
+    def metadata_isdir(name):
         """Is the named metadata a directory?  (like ``os.path.isdir()``)"""
 
-    def metadata_listdir(self, name: str) -> list[str]:
+    def metadata_listdir(name):
         """List of metadata names in the directory (like ``os.listdir()``)"""
 
-    def run_script(self, script_name: str, namespace: dict[str, Any]) -> None:
+    def run_script(script_name, namespace):
         """Execute the named script in the supplied namespace dictionary"""
 
 
-class IResourceProvider(IMetadataProvider, Protocol):
+class IResourceProvider(IMetadataProvider):
     """An object that provides access to package resources"""
 
-    def get_resource_filename(
-        self, manager: ResourceManager, resource_name: str
-    ) -> str:
+    def get_resource_filename(manager, resource_name):
         """Return a true filesystem path for `resource_name`
 
-        `manager` must be a ``ResourceManager``"""
+        `manager` must be an ``IResourceManager``"""
 
-    def get_resource_stream(
-        self, manager: ResourceManager, resource_name: str
-    ) -> _ResourceStream:
+    def get_resource_stream(manager, resource_name):
         """Return a readable file-like object for `resource_name`
 
-        `manager` must be a ``ResourceManager``"""
+        `manager` must be an ``IResourceManager``"""
 
-    def get_resource_string(
-        self, manager: ResourceManager, resource_name: str
-    ) -> bytes:
-        """Return the contents of `resource_name` as :obj:`bytes`
+    def get_resource_string(manager, resource_name):
+        """Return a string containing the contents of `resource_name`
 
-        `manager` must be a ``ResourceManager``"""
+        `manager` must be an ``IResourceManager``"""
 
-    def has_resource(self, resource_name: str) -> bool:
+    def has_resource(resource_name):
         """Does the package contain the named resource?"""
 
-    def resource_isdir(self, resource_name: str) -> bool:
+    def resource_isdir(resource_name):
         """Is the named resource a directory?  (like ``os.path.isdir()``)"""
 
-    def resource_listdir(self, resource_name: str) -> list[str]:
+    def resource_listdir(resource_name):
         """List of resource names in the directory (like ``os.listdir()``)"""
 
 
 class WorkingSet:
     """A collection of active distributions on sys.path (or a similar list)"""
 
-    def __init__(self, entries: Iterable[str] | None = None):
+    def __init__(self, entries=None):
         """Create working set from list of path entries (default=sys.path)"""
-        self.entries: list[str] = []
+        self.entries = []
         self.entry_keys = {}
         self.by_key = {}
         self.normalized_to_canonical_keys = {}
@@ -681,7 +654,7 @@ def _build_from_requirements(cls, req_spec):
         sys.path[:] = ws.entries
         return ws
 
-    def add_entry(self, entry: str):
+    def add_entry(self, entry):
         """Add a path item to ``.entries``, finding any distributions on it
 
         ``find_distributions(entry, True)`` is used to find distributions
@@ -696,11 +669,11 @@ def add_entry(self, entry: str):
         for dist in find_distributions(entry, True):
             self.add(dist, entry, False)
 
-    def __contains__(self, dist: Distribution) -> bool:
+    def __contains__(self, dist):
         """True if `dist` is the active distribution for its project"""
         return self.by_key.get(dist.key) == dist
 
-    def find(self, req: Requirement) -> Distribution | None:
+    def find(self, req):
         """Find a distribution matching requirement `req`
 
         If there is an active distribution for the requested project, this
@@ -724,7 +697,7 @@ def find(self, req: Requirement) -> Distribution | None:
             raise VersionConflict(dist, req)
         return dist
 
-    def iter_entry_points(self, group: str, name: str | None = None):
+    def iter_entry_points(self, group, name=None):
         """Yield entry point objects from `group` matching `name`
 
         If `name` is None, yields all entry points in `group` from all
@@ -738,7 +711,7 @@ def iter_entry_points(self, group: str, name: str | None = None):
             if name is None or name == entry.name
         )
 
-    def run_script(self, requires: str, script_name: str):
+    def run_script(self, requires, script_name):
         """Locate distribution for `requires` and run `script_name` script"""
         ns = sys._getframe(1).f_globals
         name = ns['__name__']
@@ -746,13 +719,13 @@ def run_script(self, requires: str, script_name: str):
         ns['__name__'] = name
         self.require(requires)[0].run_script(script_name, ns)
 
-    def __iter__(self) -> Iterator[Distribution]:
+    def __iter__(self):
         """Yield distributions for non-duplicate projects in the working set
 
         The yield order is the order in which the items' path entries were
         added to the working set.
         """
-        seen = set()
+        seen = {}
         for item in self.entries:
             if item not in self.entry_keys:
                 # workaround a cache issue
@@ -760,16 +733,10 @@ def __iter__(self) -> Iterator[Distribution]:
 
             for key in self.entry_keys[item]:
                 if key not in seen:
-                    seen.add(key)
+                    seen[key] = 1
                     yield self.by_key[key]
 
-    def add(
-        self,
-        dist: Distribution,
-        entry: str | None = None,
-        insert: bool = True,
-        replace: bool = False,
-    ):
+    def add(self, dist, entry=None, insert=True, replace=False):
         """Add `dist` to working set, associated with `entry`
 
         If `entry` is unspecified, it defaults to the ``.location`` of `dist`.
@@ -793,7 +760,7 @@ def add(
             return
 
         self.by_key[dist.key] = dist
-        normalized_name = _packaging_utils.canonicalize_name(dist.key)
+        normalized_name = packaging.utils.canonicalize_name(dist.key)
         self.normalized_to_canonical_keys[normalized_name] = dist.key
         if dist.key not in keys:
             keys.append(dist.key)
@@ -801,42 +768,14 @@ def add(
             keys2.append(dist.key)
         self._added_new(dist)
 
-    @overload
-    def resolve(
-        self,
-        requirements: Iterable[Requirement],
-        env: Environment | None,
-        installer: _InstallerTypeT[_DistributionT],
-        replace_conflicting: bool = False,
-        extras: tuple[str, ...] | None = None,
-    ) -> list[_DistributionT]: ...
-    @overload
-    def resolve(
-        self,
-        requirements: Iterable[Requirement],
-        env: Environment | None = None,
-        *,
-        installer: _InstallerTypeT[_DistributionT],
-        replace_conflicting: bool = False,
-        extras: tuple[str, ...] | None = None,
-    ) -> list[_DistributionT]: ...
-    @overload
-    def resolve(
-        self,
-        requirements: Iterable[Requirement],
-        env: Environment | None = None,
-        installer: _InstallerType | None = None,
-        replace_conflicting: bool = False,
-        extras: tuple[str, ...] | None = None,
-    ) -> list[Distribution]: ...
     def resolve(
         self,
-        requirements: Iterable[Requirement],
-        env: Environment | None = None,
-        installer: _InstallerType | None | _InstallerTypeT[_DistributionT] = None,
-        replace_conflicting: bool = False,
-        extras: tuple[str, ...] | None = None,
-    ) -> list[Distribution] | list[_DistributionT]:
+        requirements,
+        env=None,
+        installer=None,
+        replace_conflicting=False,
+        extras=None,
+    ):
         """List all distributions needed to (recursively) meet `requirements`
 
         `requirements` must be a sequence of ``Requirement`` objects.  `env`,
@@ -864,7 +803,7 @@ def resolve(
         # set up the stack
         requirements = list(requirements)[::-1]
         # set of processed requirements
-        processed = set()
+        processed = {}
         # key -> dist
         best = {}
         to_activate = []
@@ -898,14 +837,14 @@ def resolve(
                 required_by[new_requirement].add(req.project_name)
                 req_extras[new_requirement] = req.extras
 
-            processed.add(req)
+            processed[req] = True
 
         # return list of distros to activate
         return to_activate
 
     def _resolve_dist(
         self, req, best, replace_conflicting, env, installer, required_by, to_activate
-    ) -> Distribution:
+    ):
         dist = best.get(req.key)
         if dist is None:
             # Find the best distribution and add it to the map
@@ -934,41 +873,7 @@ def _resolve_dist(
             raise VersionConflict(dist, req).with_context(dependent_req)
         return dist
 
-    @overload
-    def find_plugins(
-        self,
-        plugin_env: Environment,
-        full_env: Environment | None,
-        installer: _InstallerTypeT[_DistributionT],
-        fallback: bool = True,
-    ) -> tuple[list[_DistributionT], dict[Distribution, Exception]]: ...
-    @overload
-    def find_plugins(
-        self,
-        plugin_env: Environment,
-        full_env: Environment | None = None,
-        *,
-        installer: _InstallerTypeT[_DistributionT],
-        fallback: bool = True,
-    ) -> tuple[list[_DistributionT], dict[Distribution, Exception]]: ...
-    @overload
-    def find_plugins(
-        self,
-        plugin_env: Environment,
-        full_env: Environment | None = None,
-        installer: _InstallerType | None = None,
-        fallback: bool = True,
-    ) -> tuple[list[Distribution], dict[Distribution, Exception]]: ...
-    def find_plugins(
-        self,
-        plugin_env: Environment,
-        full_env: Environment | None = None,
-        installer: _InstallerType | None | _InstallerTypeT[_DistributionT] = None,
-        fallback: bool = True,
-    ) -> tuple[
-        list[Distribution] | list[_DistributionT],
-        dict[Distribution, Exception],
-    ]:
+    def find_plugins(self, plugin_env, full_env=None, installer=None, fallback=True):
         """Find all activatable distributions in `plugin_env`
 
         Example usage::
@@ -1007,8 +912,8 @@ def find_plugins(
         # scan project names in alphabetic order
         plugin_projects.sort()
 
-        error_info: dict[Distribution, Exception] = {}
-        distributions: dict[Distribution, Exception | None] = {}
+        error_info = {}
+        distributions = {}
 
         if full_env is None:
             env = Environment(self.entries)
@@ -1044,12 +949,12 @@ def find_plugins(
                     # success, no need to try any more versions of this project
                     break
 
-        sorted_distributions = list(distributions)
-        sorted_distributions.sort()
+        distributions = list(distributions)
+        distributions.sort()
 
-        return sorted_distributions, error_info
+        return distributions, error_info
 
-    def require(self, *requirements: _NestedStr):
+    def require(self, *requirements):
         """Ensure that distributions matching `requirements` are activated
 
         `requirements` must be a string or a (possibly-nested) sequence
@@ -1065,9 +970,7 @@ def require(self, *requirements: _NestedStr):
 
         return needed
 
-    def subscribe(
-        self, callback: Callable[[Distribution], object], existing: bool = True
-    ):
+    def subscribe(self, callback, existing=True):
         """Invoke `callback` for all distributions
 
         If `existing=True` (default),
@@ -1103,12 +1006,12 @@ def __setstate__(self, e_k_b_n_c):
         self.callbacks = callbacks[:]
 
 
-class _ReqExtras(Dict["Requirement", Tuple[str, ...]]):
+class _ReqExtras(dict):
     """
     Map each requirement to the extras that demanded it.
     """
 
-    def markers_pass(self, req: Requirement, extras: tuple[str, ...] | None = None):
+    def markers_pass(self, req, extras=None):
         """
         Evaluate markers for req against each extra that
         demanded it.
@@ -1127,10 +1030,7 @@ class Environment:
     """Searchable snapshot of distributions on a search path"""
 
     def __init__(
-        self,
-        search_path: Iterable[str] | None = None,
-        platform: str | None = get_supported_platform(),
-        python: str | None = PY_MAJOR,
+        self, search_path=None, platform=get_supported_platform(), python=PY_MAJOR
     ):
         """Snapshot distributions available on a search path
 
@@ -1153,7 +1053,7 @@ def __init__(
         self.python = python
         self.scan(search_path)
 
-    def can_add(self, dist: Distribution):
+    def can_add(self, dist):
         """Is distribution `dist` acceptable for this environment?
 
         The distribution must match the platform and python version
@@ -1167,11 +1067,11 @@ def can_add(self, dist: Distribution):
         )
         return py_compat and compatible_platforms(dist.platform, self.platform)
 
-    def remove(self, dist: Distribution):
+    def remove(self, dist):
         """Remove `dist` from the environment"""
         self._distmap[dist.key].remove(dist)
 
-    def scan(self, search_path: Iterable[str] | None = None):
+    def scan(self, search_path=None):
         """Scan `search_path` for distributions usable in this environment
 
         Any distributions found are added to the environment.
@@ -1186,7 +1086,7 @@ def scan(self, search_path: Iterable[str] | None = None):
             for dist in find_distributions(item):
                 self.add(dist)
 
-    def __getitem__(self, project_name: str) -> list[Distribution]:
+    def __getitem__(self, project_name):
         """Return a newest-to-oldest list of distributions for `project_name`
 
         Uses case-insensitive `project_name` comparison, assuming all the
@@ -1197,7 +1097,7 @@ def __getitem__(self, project_name: str) -> list[Distribution]:
         distribution_key = project_name.lower()
         return self._distmap.get(distribution_key, [])
 
-    def add(self, dist: Distribution):
+    def add(self, dist):
         """Add `dist` if we ``can_add()`` it and it has not already been added"""
         if self.can_add(dist) and dist.has_version():
             dists = self._distmap.setdefault(dist.key, [])
@@ -1205,29 +1105,7 @@ def add(self, dist: Distribution):
                 dists.append(dist)
                 dists.sort(key=operator.attrgetter('hashcmp'), reverse=True)
 
-    @overload
-    def best_match(
-        self,
-        req: Requirement,
-        working_set: WorkingSet,
-        installer: _InstallerTypeT[_DistributionT],
-        replace_conflicting: bool = False,
-    ) -> _DistributionT: ...
-    @overload
-    def best_match(
-        self,
-        req: Requirement,
-        working_set: WorkingSet,
-        installer: _InstallerType | None = None,
-        replace_conflicting: bool = False,
-    ) -> Distribution | None: ...
-    def best_match(
-        self,
-        req: Requirement,
-        working_set: WorkingSet,
-        installer: _InstallerType | None | _InstallerTypeT[_DistributionT] = None,
-        replace_conflicting: bool = False,
-    ) -> Distribution | None:
+    def best_match(self, req, working_set, installer=None, replace_conflicting=False):
         """Find distribution best matching `req` and usable on `working_set`
 
         This calls the ``find(req)`` method of the `working_set` to see if a
@@ -1254,32 +1132,7 @@ def best_match(
         # try to download/install
         return self.obtain(req, installer)
 
-    @overload
-    def obtain(
-        self,
-        requirement: Requirement,
-        installer: _InstallerTypeT[_DistributionT],
-    ) -> _DistributionT: ...
-    @overload
-    def obtain(
-        self,
-        requirement: Requirement,
-        installer: Callable[[Requirement], None] | None = None,
-    ) -> None: ...
-    @overload
-    def obtain(
-        self,
-        requirement: Requirement,
-        installer: _InstallerType | None = None,
-    ) -> Distribution | None: ...
-    def obtain(
-        self,
-        requirement: Requirement,
-        installer: Callable[[Requirement], None]
-        | _InstallerType
-        | None
-        | _InstallerTypeT[_DistributionT] = None,
-    ) -> Distribution | None:
+    def obtain(self, requirement, installer=None):
         """Obtain a distribution matching `requirement` (e.g. via download)
 
         Obtain a distro that matches requirement (e.g. via download).  In the
@@ -1288,15 +1141,16 @@ def obtain(
         None is returned instead.  This method is a hook that allows subclasses
         to attempt other ways of obtaining a distribution before falling back
         to the `installer` argument."""
-        return installer(requirement) if installer else None
+        if installer is not None:
+            return installer(requirement)
 
-    def __iter__(self) -> Iterator[str]:
+    def __iter__(self):
         """Yield the unique project names of the available distributions"""
         for key in self._distmap.keys():
             if self[key]:
                 yield key
 
-    def __iadd__(self, other: Distribution | Environment):
+    def __iadd__(self, other):
         """In-place addition of a distribution or environment"""
         if isinstance(other, Distribution):
             self.add(other)
@@ -1308,7 +1162,7 @@ def __iadd__(self, other: Distribution | Environment):
             raise TypeError("Can't add %r to environment" % (other,))
         return self
 
-    def __add__(self, other: Distribution | Environment):
+    def __add__(self, other):
         """Add an environment or distribution to an environment"""
         new = self.__class__([], platform=None, python=None)
         for env in self, other:
@@ -1335,54 +1189,46 @@ class ExtractionError(RuntimeError):
         The exception instance that caused extraction to fail
     """
 
-    manager: ResourceManager
-    cache_path: str
-    original_error: BaseException | None
-
 
 class ResourceManager:
     """Manage resource extraction and packages"""
 
-    extraction_path: str | None = None
+    extraction_path = None
 
     def __init__(self):
         self.cached_files = {}
 
-    def resource_exists(self, package_or_requirement: _PkgReqType, resource_name: str):
+    def resource_exists(self, package_or_requirement, resource_name):
         """Does the named resource exist?"""
         return get_provider(package_or_requirement).has_resource(resource_name)
 
-    def resource_isdir(self, package_or_requirement: _PkgReqType, resource_name: str):
+    def resource_isdir(self, package_or_requirement, resource_name):
         """Is the named resource an existing directory?"""
         return get_provider(package_or_requirement).resource_isdir(resource_name)
 
-    def resource_filename(
-        self, package_or_requirement: _PkgReqType, resource_name: str
-    ):
+    def resource_filename(self, package_or_requirement, resource_name):
         """Return a true filesystem path for specified resource"""
         return get_provider(package_or_requirement).get_resource_filename(
             self, resource_name
         )
 
-    def resource_stream(self, package_or_requirement: _PkgReqType, resource_name: str):
+    def resource_stream(self, package_or_requirement, resource_name):
         """Return a readable file-like object for specified resource"""
         return get_provider(package_or_requirement).get_resource_stream(
             self, resource_name
         )
 
-    def resource_string(
-        self, package_or_requirement: _PkgReqType, resource_name: str
-    ) -> bytes:
-        """Return specified resource as :obj:`bytes`"""
+    def resource_string(self, package_or_requirement, resource_name):
+        """Return specified resource as a string"""
         return get_provider(package_or_requirement).get_resource_string(
             self, resource_name
         )
 
-    def resource_listdir(self, package_or_requirement: _PkgReqType, resource_name: str):
+    def resource_listdir(self, package_or_requirement, resource_name):
         """List the contents of the named resource directory"""
         return get_provider(package_or_requirement).resource_listdir(resource_name)
 
-    def extraction_error(self) -> NoReturn:
+    def extraction_error(self):
         """Give an error message for problems extracting file(s)"""
 
         old_exc = sys.exc_info()[1]
@@ -1412,7 +1258,7 @@ def extraction_error(self) -> NoReturn:
         err.original_error = old_exc
         raise err
 
-    def get_cache_path(self, archive_name: str, names: Iterable[StrPath] = ()):
+    def get_cache_path(self, archive_name, names=()):
         """Return absolute location in cache for `archive_name` and `names`
 
         The parent directory of the resulting path will be created if it does
@@ -1434,7 +1280,7 @@ def get_cache_path(self, archive_name: str, names: Iterable[StrPath] = ()):
 
         self._warn_unsafe_extraction_path(extract_path)
 
-        self.cached_files[target_path] = True
+        self.cached_files[target_path] = 1
         return target_path
 
     @staticmethod
@@ -1464,7 +1310,7 @@ def _warn_unsafe_extraction_path(path):
             ).format(**locals())
             warnings.warn(msg, UserWarning)
 
-    def postprocess(self, tempname: StrOrBytesPath, filename: StrOrBytesPath):
+    def postprocess(self, tempname, filename):
         """Perform any platform-specific postprocessing of `tempname`
 
         This is where Mac header rewrites should be done; other platforms don't
@@ -1484,7 +1330,7 @@ def postprocess(self, tempname: StrOrBytesPath, filename: StrOrBytesPath):
             mode = ((os.stat(tempname).st_mode) | 0o555) & 0o7777
             os.chmod(tempname, mode)
 
-    def set_extraction_path(self, path: str):
+    def set_extraction_path(self, path):
         """Set the base path where resources will be extracted to, if needed.
 
         If you do not call this routine before any extractions take place, the
@@ -1508,7 +1354,7 @@ def set_extraction_path(self, path: str):
 
         self.extraction_path = path
 
-    def cleanup_resources(self, force: bool = False) -> list[str]:
+    def cleanup_resources(self, force=False):
         """
         Delete all extracted resource files and directories, returning a list
         of the file and directory names that could not be successfully removed.
@@ -1520,19 +1366,20 @@ def cleanup_resources(self, force: bool = False) -> list[str]:
         directory used for extractions.
         """
         # XXX
-        return []
 
 
-def get_default_cache() -> str:
+def get_default_cache():
     """
     Return the ``PYTHON_EGG_CACHE`` environment variable
     or a platform-relevant user cache dir for an app
     named "Python-Eggs".
     """
-    return os.environ.get('PYTHON_EGG_CACHE') or _user_cache_dir(appname='Python-Eggs')
+    return os.environ.get('PYTHON_EGG_CACHE') or platformdirs.user_cache_dir(
+        appname='Python-Eggs'
+    )
 
 
-def safe_name(name: str):
+def safe_name(name):
     """Convert an arbitrary string to a standard distribution name
 
     Any runs of non-alphanumeric/. characters are replaced with a single '-'.
@@ -1540,14 +1387,14 @@ def safe_name(name: str):
     return re.sub('[^A-Za-z0-9.]+', '-', name)
 
 
-def safe_version(version: str):
+def safe_version(version):
     """
     Convert an arbitrary string to a standard version string
     """
     try:
         # normalize the version
-        return str(_packaging_version.Version(version))
-    except _packaging_version.InvalidVersion:
+        return str(packaging.version.Version(version))
+    except packaging.version.InvalidVersion:
         version = version.replace(' ', '.')
         return re.sub('[^A-Za-z0-9.]+', '-', version)
 
@@ -1569,7 +1416,7 @@ def _forgiving_version(version):
     match = _PEP440_FALLBACK.search(version)
     if match:
         safe = match["safe"]
-        rest = version[len(safe) :]
+        rest = version[len(safe):]
     else:
         safe = "0"
         rest = version
@@ -1584,7 +1431,7 @@ def _safe_segment(segment):
     return re.sub(r'\.[^A-Za-z0-9]+', '.', segment).strip(".-")
 
 
-def safe_extra(extra: str):
+def safe_extra(extra):
     """Convert an arbitrary string to a standard 'extra' name
 
     Any runs of non-alphanumeric characters are replaced with a single '_',
@@ -1593,7 +1440,7 @@ def safe_extra(extra: str):
     return re.sub('[^A-Za-z0-9.-]+', '_', extra).lower()
 
 
-def to_filename(name: str):
+def to_filename(name):
     """Convert a project or version name to its filename-escaped form
 
     Any '-' characters are currently replaced with '_'.
@@ -1601,7 +1448,7 @@ def to_filename(name: str):
     return name.replace('-', '_')
 
 
-def invalid_marker(text: str):
+def invalid_marker(text):
     """
     Validate text as a PEP 508 environment marker; return an exception
     if invalid or False otherwise.
@@ -1615,7 +1462,7 @@ def invalid_marker(text: str):
     return False
 
 
-def evaluate_marker(text: str, extra: str | None = None) -> bool:
+def evaluate_marker(text, extra=None):
     """
     Evaluate a PEP 508 environment marker.
     Return a boolean indicating the marker result in this environment.
@@ -1624,48 +1471,46 @@ def evaluate_marker(text: str, extra: str | None = None) -> bool:
     This implementation uses the 'pyparsing' module.
     """
     try:
-        marker = _packaging_markers.Marker(text)
+        marker = packaging.markers.Marker(text)
         return marker.evaluate()
-    except _packaging_markers.InvalidMarker as e:
+    except packaging.markers.InvalidMarker as e:
         raise SyntaxError(e) from e
 
 
 class NullProvider:
     """Try to implement resources and metadata for arbitrary PEP 302 loaders"""
 
-    egg_name: str | None = None
-    egg_info: str | None = None
-    loader: _LoaderProtocol | None = None
+    egg_name = None
+    egg_info = None
+    loader = None
 
-    def __init__(self, module: _ModuleLike):
+    def __init__(self, module):
         self.loader = getattr(module, '__loader__', None)
         self.module_path = os.path.dirname(getattr(module, '__file__', ''))
 
-    def get_resource_filename(self, manager: ResourceManager, resource_name: str):
+    def get_resource_filename(self, manager, resource_name):
         return self._fn(self.module_path, resource_name)
 
-    def get_resource_stream(self, manager: ResourceManager, resource_name: str):
+    def get_resource_stream(self, manager, resource_name):
         return io.BytesIO(self.get_resource_string(manager, resource_name))
 
-    def get_resource_string(
-        self, manager: ResourceManager, resource_name: str
-    ) -> bytes:
+    def get_resource_string(self, manager, resource_name):
         return self._get(self._fn(self.module_path, resource_name))
 
-    def has_resource(self, resource_name: str):
+    def has_resource(self, resource_name):
         return self._has(self._fn(self.module_path, resource_name))
 
     def _get_metadata_path(self, name):
         return self._fn(self.egg_info, name)
 
-    def has_metadata(self, name: str) -> bool:
+    def has_metadata(self, name):
         if not self.egg_info:
-            return False
+            return self.egg_info
 
         path = self._get_metadata_path(name)
         return self._has(path)
 
-    def get_metadata(self, name: str):
+    def get_metadata(self, name):
         if not self.egg_info:
             return ""
         path = self._get_metadata_path(name)
@@ -1678,24 +1523,24 @@ def get_metadata(self, name: str):
             exc.reason += ' in {} file at path: {}'.format(name, path)
             raise
 
-    def get_metadata_lines(self, name: str) -> Iterator[str]:
+    def get_metadata_lines(self, name):
         return yield_lines(self.get_metadata(name))
 
-    def resource_isdir(self, resource_name: str):
+    def resource_isdir(self, resource_name):
         return self._isdir(self._fn(self.module_path, resource_name))
 
-    def metadata_isdir(self, name: str) -> bool:
-        return bool(self.egg_info and self._isdir(self._fn(self.egg_info, name)))
+    def metadata_isdir(self, name):
+        return self.egg_info and self._isdir(self._fn(self.egg_info, name))
 
-    def resource_listdir(self, resource_name: str):
+    def resource_listdir(self, resource_name):
         return self._listdir(self._fn(self.module_path, resource_name))
 
-    def metadata_listdir(self, name: str) -> list[str]:
+    def metadata_listdir(self, name):
         if self.egg_info:
             return self._listdir(self._fn(self.egg_info, name))
         return []
 
-    def run_script(self, script_name: str, namespace: dict[str, Any]):
+    def run_script(self, script_name, namespace):
         script = 'scripts/' + script_name
         if not self.has_metadata(script):
             raise ResolutionError(
@@ -1703,13 +1548,13 @@ def run_script(self, script_name: str, namespace: dict[str, Any]):
                     **locals()
                 ),
             )
-
         script_text = self.get_metadata(script).replace('\r\n', '\n')
         script_text = script_text.replace('\r', '\n')
         script_filename = self._fn(self.egg_info, script)
         namespace['__file__'] = script_filename
         if os.path.exists(script_filename):
-            source = _read_utf8_with_fallback(script_filename)
+            with open(script_filename) as fid:
+                source = fid.read()
             code = compile(source, script_filename, 'exec')
             exec(code, namespace, namespace)
         else:
@@ -1724,26 +1569,22 @@ def run_script(self, script_name: str, namespace: dict[str, Any]):
             script_code = compile(script_text, script_filename, 'exec')
             exec(script_code, namespace, namespace)
 
-    def _has(self, path) -> bool:
+    def _has(self, path):
         raise NotImplementedError(
             "Can't perform this operation for unregistered loader type"
         )
 
-    def _isdir(self, path) -> bool:
+    def _isdir(self, path):
         raise NotImplementedError(
             "Can't perform this operation for unregistered loader type"
         )
 
-    def _listdir(self, path) -> list[str]:
+    def _listdir(self, path):
         raise NotImplementedError(
             "Can't perform this operation for unregistered loader type"
         )
 
-    def _fn(self, base: str | None, resource_name: str):
-        if base is None:
-            raise TypeError(
-                "`base` parameter in `_fn` is `None`. Either override this method or check the parameter first."
-            )
+    def _fn(self, base, resource_name):
         self._validate_resource_path(resource_name)
         if resource_name:
             return os.path.join(base, *resource_name.split('/'))
@@ -1806,7 +1647,6 @@ def _validate_resource_path(path):
             os.path.pardir in path.split(posixpath.sep)
             or posixpath.isabs(path)
             or ntpath.isabs(path)
-            or path.startswith("\\")
         )
         if not invalid:
             return
@@ -1814,20 +1654,20 @@ def _validate_resource_path(path):
         msg = "Use of .. or absolute path in a resource path is not allowed."
 
         # Aggressively disallow Windows absolute paths
-        if (path.startswith("\\") or ntpath.isabs(path)) and not posixpath.isabs(path):
+        if ntpath.isabs(path) and not posixpath.isabs(path):
             raise ValueError(msg)
 
         # for compatibility, warn; in future
         # raise ValueError(msg)
-        issue_warning(
+        warnings.warn(
             msg[:-1] + " and will raise exceptions in a future release.",
             DeprecationWarning,
+            stacklevel=4,
         )
 
-    def _get(self, path) -> bytes:
-        if hasattr(self.loader, 'get_data') and self.loader:
-            # Already checked get_data exists
-            return self.loader.get_data(path)  # type: ignore[attr-defined]
+    def _get(self, path):
+        if hasattr(self.loader, 'get_data'):
+            return self.loader.get_data(path)
         raise NotImplementedError(
             "Can't perform this operation for loaders without 'get_data()'"
         )
@@ -1850,7 +1690,7 @@ def _parents(path):
 class EggProvider(NullProvider):
     """Provider based on a virtual filesystem"""
 
-    def __init__(self, module: _ModuleLike):
+    def __init__(self, module):
         super().__init__(module)
         self._setup_prefix()
 
@@ -1861,7 +1701,7 @@ def _setup_prefix(self):
         egg = next(eggs, None)
         egg and self._set_egg(egg)
 
-    def _set_egg(self, path: str):
+    def _set_egg(self, path):
         self.egg_name = os.path.basename(path)
         self.egg_info = os.path.join(path, 'EGG-INFO')
         self.egg_root = path
@@ -1870,19 +1710,19 @@ def _set_egg(self, path: str):
 class DefaultProvider(EggProvider):
     """Provides access to package resources in the filesystem"""
 
-    def _has(self, path) -> bool:
+    def _has(self, path):
         return os.path.exists(path)
 
-    def _isdir(self, path) -> bool:
+    def _isdir(self, path):
         return os.path.isdir(path)
 
     def _listdir(self, path):
         return os.listdir(path)
 
-    def get_resource_stream(self, manager: object, resource_name: str):
+    def get_resource_stream(self, manager, resource_name):
         return open(self._fn(self.module_path, resource_name), 'rb')
 
-    def _get(self, path) -> bytes:
+    def _get(self, path):
         with open(path, 'rb') as stream:
             return stream.read()
 
@@ -1893,7 +1733,7 @@ def _register(cls):
             'SourcelessFileLoader',
         )
         for name in loader_names:
-            loader_cls = getattr(importlib.machinery, name, type(None))
+            loader_cls = getattr(importlib_machinery, name, type(None))
             register_loader_type(loader_cls, cls)
 
 
@@ -1903,13 +1743,12 @@ def _register(cls):
 class EmptyProvider(NullProvider):
     """Provider that returns nothing for all requests"""
 
-    # A special case, we don't want all Providers inheriting from NullProvider to have a potentially None module_path
-    module_path: str | None = None  # type: ignore[assignment]
+    module_path = None
 
     _isdir = _has = lambda self, path: False
 
-    def _get(self, path) -> bytes:
-        return b''
+    def _get(self, path):
+        return ''
 
     def _listdir(self, path):
         return []
@@ -1921,14 +1760,13 @@ def __init__(self):
 empty_provider = EmptyProvider()
 
 
-class ZipManifests(Dict[str, "MemoizedZipManifests.manifest_mod"]):
+class ZipManifests(dict):
     """
     zip manifest builder
     """
 
-    # `path` could be `StrPath | IO[bytes]` but that violates the LSP for `MemoizedZipManifests.load`
     @classmethod
-    def build(cls, path: str):
+    def build(cls, path):
         """
         Build a dictionary similar to the zipimport directory
         caches, except instead of tuples, store ZipInfo objects.
@@ -1954,11 +1792,9 @@ class MemoizedZipManifests(ZipManifests):
     Memoized zipfile manifests.
     """
 
-    class manifest_mod(NamedTuple):
-        manifest: dict[str, zipfile.ZipInfo]
-        mtime: float
+    manifest_mod = collections.namedtuple('manifest_mod', 'manifest mtime')
 
-    def load(self, path: str) -> dict[str, zipfile.ZipInfo]:  # type: ignore[override] # ZipManifests.load is a classmethod
+    def load(self, path):
         """
         Load a manifest at path or return a suitable manifest already loaded.
         """
@@ -1975,12 +1811,10 @@ def load(self, path: str) -> dict[str, zipfile.ZipInfo]:  # type: ignore[overrid
 class ZipProvider(EggProvider):
     """Resource support for zips and eggs"""
 
-    eagers: list[str] | None = None
+    eagers = None
     _zip_manifests = MemoizedZipManifests()
-    # ZipProvider's loader should always be a zipimporter or equivalent
-    loader: zipimport.zipimporter
 
-    def __init__(self, module: _ZipLoaderModule):
+    def __init__(self, module):
         super().__init__(module)
         self.zip_pre = self.loader.archive + os.sep
 
@@ -2006,7 +1840,7 @@ def _parts(self, zip_path):
     def zipinfo(self):
         return self._zip_manifests.load(self.loader.archive)
 
-    def get_resource_filename(self, manager: ResourceManager, resource_name: str):
+    def get_resource_filename(self, manager, resource_name):
         if not self.egg_name:
             raise NotImplementedError(
                 "resource_filename() only supported for .egg, not .zip"
@@ -2029,7 +1863,7 @@ def _get_date_and_size(zip_stat):
         return timestamp, size
 
     # FIXME: 'ZipProvider._extract_resource' is too complex (12)
-    def _extract_resource(self, manager: ResourceManager, zip_path) -> str:  # noqa: C901
+    def _extract_resource(self, manager, zip_path):  # noqa: C901
         if zip_path in self._index():
             for name in self._index()[zip_path]:
                 last = self._extract_resource(manager, os.path.join(zip_path, name))
@@ -2039,14 +1873,10 @@ def _extract_resource(self, manager: ResourceManager, zip_path) -> str:  # noqa:
         timestamp, size = self._get_date_and_size(self.zipinfo[zip_path])
 
         if not WRITE_SUPPORT:
-            raise OSError(
-                '"os.rename" and "os.unlink" are not supported on this platform'
+            raise IOError(
+                '"os.rename" and "os.unlink" are not supported ' 'on this platform'
             )
         try:
-            if not self.egg_name:
-                raise OSError(
-                    '"egg_name" is empty. This likely means no egg could be found from the "module_path".'
-                )
             real_path = manager.get_cache_path(self.egg_name, self._parts(zip_path))
 
             if self._is_current(real_path, zip_path):
@@ -2064,7 +1894,7 @@ def _extract_resource(self, manager: ResourceManager, zip_path) -> str:  # noqa:
             try:
                 rename(tmpnam, real_path)
 
-            except OSError:
+            except os.error:
                 if os.path.isfile(real_path):
                     if self._is_current(real_path, zip_path):
                         # the file became current since it was checked above,
@@ -2077,7 +1907,7 @@ def _extract_resource(self, manager: ResourceManager, zip_path) -> str:  # noqa:
                         return real_path
                 raise
 
-        except OSError:
+        except os.error:
             # report a user-friendly error
             manager.extraction_error()
 
@@ -2125,20 +1955,20 @@ def _index(self):
             self._dirindex = ind
             return ind
 
-    def _has(self, fspath) -> bool:
+    def _has(self, fspath):
         zip_path = self._zipinfo_name(fspath)
         return zip_path in self.zipinfo or zip_path in self._index()
 
-    def _isdir(self, fspath) -> bool:
+    def _isdir(self, fspath):
         return self._zipinfo_name(fspath) in self._index()
 
     def _listdir(self, fspath):
         return list(self._index().get(self._zipinfo_name(fspath), ()))
 
-    def _eager_to_zip(self, resource_name: str):
+    def _eager_to_zip(self, resource_name):
         return self._zipinfo_name(self._fn(self.egg_root, resource_name))
 
-    def _resource_to_zip(self, resource_name: str):
+    def _resource_to_zip(self, resource_name):
         return self._zipinfo_name(self._fn(self.module_path, resource_name))
 
 
@@ -2157,20 +1987,20 @@ class FileMetadata(EmptyProvider):
     the provided location.
     """
 
-    def __init__(self, path: StrPath):
+    def __init__(self, path):
         self.path = path
 
     def _get_metadata_path(self, name):
         return self.path
 
-    def has_metadata(self, name: str) -> bool:
+    def has_metadata(self, name):
         return name == 'PKG-INFO' and os.path.isfile(self.path)
 
-    def get_metadata(self, name: str):
+    def get_metadata(self, name):
         if name != 'PKG-INFO':
             raise KeyError("No metadata except PKG-INFO is available")
 
-        with open(self.path, encoding='utf-8', errors="replace") as f:
+        with io.open(self.path, encoding='utf-8', errors="replace") as f:
             metadata = f.read()
         self._warn_on_replacement(metadata)
         return metadata
@@ -2182,7 +2012,7 @@ def _warn_on_replacement(self, metadata):
             msg = tmpl.format(**locals())
             warnings.warn(msg)
 
-    def get_metadata_lines(self, name: str) -> Iterator[str]:
+    def get_metadata_lines(self, name):
         return yield_lines(self.get_metadata(name))
 
 
@@ -2206,7 +2036,7 @@ class PathMetadata(DefaultProvider):
         dist = Distribution.from_filename(egg_path, metadata=metadata)
     """
 
-    def __init__(self, path: str, egg_info: str):
+    def __init__(self, path, egg_info):
         self.module_path = path
         self.egg_info = egg_info
 
@@ -2214,7 +2044,7 @@ def __init__(self, path: str, egg_info: str):
 class EggMetadata(ZipProvider):
     """Metadata provider for .egg files"""
 
-    def __init__(self, importer: zipimport.zipimporter):
+    def __init__(self, importer):
         """Create a metadata provider from a zipimporter"""
 
         self.zip_pre = importer.archive + os.sep
@@ -2226,12 +2056,10 @@ def __init__(self, importer: zipimport.zipimporter):
         self._setup_prefix()
 
 
-_distribution_finders: dict[type, _DistFinderType[Any]] = _declare_state(
-    'dict', '_distribution_finders', {}
-)
+_declare_state('dict', _distribution_finders={})
 
 
-def register_finder(importer_type: type[_T], distribution_finder: _DistFinderType[_T]):
+def register_finder(importer_type, distribution_finder):
     """Register `distribution_finder` to find distributions in sys.path items
 
     `importer_type` is the type or class of a PEP 302 "Importer" (sys.path item
@@ -2241,16 +2069,14 @@ def register_finder(importer_type: type[_T], distribution_finder: _DistFinderTyp
     _distribution_finders[importer_type] = distribution_finder
 
 
-def find_distributions(path_item: str, only: bool = False):
+def find_distributions(path_item, only=False):
     """Yield distributions accessible via `path_item`"""
     importer = get_importer(path_item)
     finder = _find_adapter(_distribution_finders, importer)
     return finder(importer, path_item, only)
 
 
-def find_eggs_in_zip(
-    importer: zipimport.zipimporter, path_item: str, only: bool = False
-) -> Iterator[Distribution]:
+def find_eggs_in_zip(importer, path_item, only=False):
     """
     Find eggs in zip files; possibly multiple nested eggs.
     """
@@ -2268,7 +2094,8 @@ def find_eggs_in_zip(
         if _is_egg_path(subitem):
             subpath = os.path.join(path_item, subitem)
             dists = find_eggs_in_zip(zipimport.zipimporter(subpath), subpath)
-            yield from dists
+            for dist in dists:
+                yield dist
         elif subitem.lower().endswith(('.dist-info', '.egg-info')):
             subpath = os.path.join(path_item, subitem)
             submeta = EggMetadata(zipimport.zipimporter(subpath))
@@ -2279,16 +2106,14 @@ def find_eggs_in_zip(
 register_finder(zipimport.zipimporter, find_eggs_in_zip)
 
 
-def find_nothing(
-    importer: object | None, path_item: str | None, only: bool | None = False
-):
+def find_nothing(importer, path_item, only=False):
     return ()
 
 
 register_finder(object, find_nothing)
 
 
-def find_on_path(importer: object | None, path_item, only=False):
+def find_on_path(importer, path_item, only=False):
     """Yield distributions accessible on a sys.path directory"""
     path_item = _normalize_cached(path_item)
 
@@ -2305,7 +2130,8 @@ def find_on_path(importer: object | None, path_item, only=False):
     for entry in sorted(entries):
         fullpath = os.path.join(path_item, entry)
         factory = dist_factory(path_item, entry, only)
-        yield from factory(fullpath)
+        for dist in factory(fullpath):
+            yield dist
 
 
 def dist_factory(path_item, entry, only):
@@ -2343,7 +2169,7 @@ def __call__(self, fullpath):
         return iter(())
 
 
-def safe_listdir(path: StrOrBytesPath):
+def safe_listdir(path):
     """
     Attempt to list contents of path, but suppress some exceptions.
     """
@@ -2359,13 +2185,13 @@ def safe_listdir(path: StrOrBytesPath):
     return ()
 
 
-def distributions_from_metadata(path: str):
+def distributions_from_metadata(path):
     root = os.path.dirname(path)
     if os.path.isdir(path):
         if len(os.listdir(path)) == 0:
             # empty metadata dir; skip
             return
-        metadata: _MetadataType = PathMetadata(root, path)
+        metadata = PathMetadata(root, path)
     else:
         metadata = FileMetadata(path)
     entry = os.path.basename(path)
@@ -2381,10 +2207,11 @@ def non_empty_lines(path):
     """
     Yield non-empty lines from file at path
     """
-    for line in _read_utf8_with_fallback(path).splitlines():
-        line = line.strip()
-        if line:
-            yield line
+    with open(path) as f:
+        for line in f:
+            line = line.strip()
+            if line:
+                yield line
 
 
 def resolve_egg_link(path):
@@ -2403,19 +2230,13 @@ def resolve_egg_link(path):
 if hasattr(pkgutil, 'ImpImporter'):
     register_finder(pkgutil.ImpImporter, find_on_path)
 
-register_finder(importlib.machinery.FileFinder, find_on_path)
+register_finder(importlib_machinery.FileFinder, find_on_path)
 
-_namespace_handlers: dict[type, _NSHandlerType[Any]] = _declare_state(
-    'dict', '_namespace_handlers', {}
-)
-_namespace_packages: dict[str | None, list[str]] = _declare_state(
-    'dict', '_namespace_packages', {}
-)
+_declare_state('dict', _namespace_handlers={})
+_declare_state('dict', _namespace_packages={})
 
 
-def register_namespace_handler(
-    importer_type: type[_T], namespace_handler: _NSHandlerType[_T]
-):
+def register_namespace_handler(importer_type, namespace_handler):
     """Register `namespace_handler` to declare namespace packages
 
     `importer_type` is the type or class of a PEP 302 "Importer" (sys.path item
@@ -2470,7 +2291,7 @@ def _handle_ns(packageName, path_item):
     return subpath
 
 
-def _rebuild_mod_path(orig_path, package_name, module: types.ModuleType):
+def _rebuild_mod_path(orig_path, package_name, module):
     """
     Rebuild module.__path__ ensuring that all entries are ordered
     corresponding to their sys.path order
@@ -2504,7 +2325,7 @@ def position_in_sys_path(path):
         module.__path__ = new_path
 
 
-def declare_namespace(packageName: str):
+def declare_namespace(packageName):
     """Declare that package 'packageName' is a namespace package"""
 
     msg = (
@@ -2521,7 +2342,7 @@ def declare_namespace(packageName: str):
         if packageName in _namespace_packages:
             return
 
-        path: MutableSequence[str] = sys.path
+        path = sys.path
         parent, _, _ = packageName.rpartition('.')
 
         if parent:
@@ -2547,7 +2368,7 @@ def declare_namespace(packageName: str):
         _imp.release_lock()
 
 
-def fixup_namespace_packages(path_item: str, parent: str | None = None):
+def fixup_namespace_packages(path_item, parent=None):
     """Ensure that previously-declared namespace packages include path_item"""
     _imp.acquire_lock()
     try:
@@ -2559,12 +2380,7 @@ def fixup_namespace_packages(path_item: str, parent: str | None = None):
         _imp.release_lock()
 
 
-def file_ns_handler(
-    importer: object,
-    path_item: StrPath,
-    packageName: str,
-    module: types.ModuleType,
-):
+def file_ns_handler(importer, path_item, packageName, module):
     """Compute an ns-package subpath for a filesystem or zipfile importer"""
 
     subpath = os.path.join(path_item, packageName.split('.')[-1])
@@ -2581,31 +2397,22 @@ def file_ns_handler(
     register_namespace_handler(pkgutil.ImpImporter, file_ns_handler)
 
 register_namespace_handler(zipimport.zipimporter, file_ns_handler)
-register_namespace_handler(importlib.machinery.FileFinder, file_ns_handler)
+register_namespace_handler(importlib_machinery.FileFinder, file_ns_handler)
 
 
-def null_ns_handler(
-    importer: object,
-    path_item: str | None,
-    packageName: str | None,
-    module: _ModuleLike | None,
-):
+def null_ns_handler(importer, path_item, packageName, module):
     return None
 
 
 register_namespace_handler(object, null_ns_handler)
 
 
-@overload
-def normalize_path(filename: StrPath) -> str: ...
-@overload
-def normalize_path(filename: BytesPath) -> bytes: ...
-def normalize_path(filename: StrOrBytesPath):
+def normalize_path(filename):
     """Normalize a file/dir name for comparison purposes"""
     return os.path.normcase(os.path.realpath(os.path.normpath(_cygwin_patch(filename))))
 
 
-def _cygwin_patch(filename: StrOrBytesPath):  # pragma: nocover
+def _cygwin_patch(filename):  # pragma: nocover
     """
     Contrary to POSIX 2008, on Cygwin, getcwd (3) contains
     symlink components. Using
@@ -2616,19 +2423,12 @@ def _cygwin_patch(filename: StrOrBytesPath):  # pragma: nocover
     return os.path.abspath(filename) if sys.platform == 'cygwin' else filename
 
 
-if TYPE_CHECKING:
-    # https://github.com/python/mypy/issues/16261
-    # https://github.com/python/typeshed/issues/6347
-    @overload
-    def _normalize_cached(filename: StrPath) -> str: ...
-    @overload
-    def _normalize_cached(filename: BytesPath) -> bytes: ...
-    def _normalize_cached(filename: StrOrBytesPath) -> str | bytes: ...
-else:
-
-    @functools.lru_cache(maxsize=None)
-    def _normalize_cached(filename):
-        return normalize_path(filename)
+def _normalize_cached(filename, _cache={}):
+    try:
+        return _cache[filename]
+    except KeyError:
+        _cache[filename] = result = normalize_path(filename)
+        return result
 
 
 def _is_egg_path(path):
@@ -2681,14 +2481,7 @@ def _set_parent_ns(packageName):
 class EntryPoint:
     """Object representing an advertised importable object"""
 
-    def __init__(
-        self,
-        name: str,
-        module_name: str,
-        attrs: Iterable[str] = (),
-        extras: Iterable[str] = (),
-        dist: Distribution | None = None,
-    ):
+    def __init__(self, name, module_name, attrs=(), extras=(), dist=None):
         if not MODULE(module_name):
             raise ValueError("Invalid module name", module_name)
         self.name = name
@@ -2708,26 +2501,7 @@ def __str__(self):
     def __repr__(self):
         return "EntryPoint.parse(%r)" % str(self)
 
-    @overload
-    def load(
-        self,
-        require: Literal[True] = True,
-        env: Environment | None = None,
-        installer: _InstallerType | None = None,
-    ) -> _ResolvedEntryPoint: ...
-    @overload
-    def load(
-        self,
-        require: Literal[False],
-        *args: Any,
-        **kwargs: Any,
-    ) -> _ResolvedEntryPoint: ...
-    def load(
-        self,
-        require: bool = True,
-        *args: Environment | _InstallerType | None,
-        **kwargs: Environment | _InstallerType | None,
-    ) -> _ResolvedEntryPoint:
+    def load(self, require=True, *args, **kwargs):
         """
         Require packages for this EntryPoint, then resolve it.
         """
@@ -2739,12 +2513,10 @@ def load(
                 stacklevel=2,
             )
         if require:
-            # We could pass `env` and `installer` directly,
-            # but keeping `*args` and `**kwargs` for backwards compatibility
-            self.require(*args, **kwargs)  # type: ignore
+            self.require(*args, **kwargs)
         return self.resolve()
 
-    def resolve(self) -> _ResolvedEntryPoint:
+    def resolve(self):
         """
         Resolve the entry point from its module and attrs.
         """
@@ -2754,14 +2526,9 @@ def resolve(self) -> _ResolvedEntryPoint:
         except AttributeError as exc:
             raise ImportError(str(exc)) from exc
 
-    def require(
-        self,
-        env: Environment | None = None,
-        installer: _InstallerType | None = None,
-    ):
-        if not self.dist:
-            error_cls = UnknownExtra if self.extras else AttributeError
-            raise error_cls("Can't require() without a distribution", self)
+    def require(self, env=None, installer=None):
+        if self.extras and not self.dist:
+            raise UnknownExtra("Can't require() without a distribution", self)
 
         # Get the requirements for this entry point with all its extras and
         # then resolve them. We have to pass `extras` along when resolving so
@@ -2782,7 +2549,7 @@ def require(
     )
 
     @classmethod
-    def parse(cls, src: str, dist: Distribution | None = None):
+    def parse(cls, src, dist=None):
         """Parse a single entry point from string `src`
 
         Entry point syntax follows the form::
@@ -2807,20 +2574,15 @@ def _parse_extras(cls, extras_spec):
             return ()
         req = Requirement.parse('x' + extras_spec)
         if req.specs:
-            raise ValueError
+            raise ValueError()
         return req.extras
 
     @classmethod
-    def parse_group(
-        cls,
-        group: str,
-        lines: _NestedStr,
-        dist: Distribution | None = None,
-    ):
+    def parse_group(cls, group, lines, dist=None):
         """Parse an entry point group"""
         if not MODULE(group):
             raise ValueError("Invalid group name", group)
-        this: dict[str, Self] = {}
+        this = {}
         for line in yield_lines(lines):
             ep = cls.parse(line, dist)
             if ep.name in this:
@@ -2829,19 +2591,14 @@ def parse_group(
         return this
 
     @classmethod
-    def parse_map(
-        cls,
-        data: str | Iterable[str] | dict[str, str | Iterable[str]],
-        dist: Distribution | None = None,
-    ):
+    def parse_map(cls, data, dist=None):
         """Parse a map of entry point groups"""
-        _data: Iterable[tuple[str | None, str | Iterable[str]]]
         if isinstance(data, dict):
-            _data = data.items()
+            data = data.items()
         else:
-            _data = split_sections(data)
-        maps: dict[str, dict[str, Self]] = {}
-        for group, lines in _data:
+            data = split_sections(data)
+        maps = {}
+        for group, lines in data:
             if group is None:
                 if not lines:
                     continue
@@ -2875,13 +2632,13 @@ class Distribution:
 
     def __init__(
         self,
-        location: str | None = None,
-        metadata: _MetadataType = None,
-        project_name: str | None = None,
-        version: str | None = None,
-        py_version: str | None = PY_MAJOR,
-        platform: str | None = None,
-        precedence: int = EGG_DIST,
+        location=None,
+        metadata=None,
+        project_name=None,
+        version=None,
+        py_version=PY_MAJOR,
+        platform=None,
+        precedence=EGG_DIST,
     ):
         self.project_name = safe_name(project_name or 'Unknown')
         if version is not None:
@@ -2893,13 +2650,7 @@ def __init__(
         self._provider = metadata or empty_provider
 
     @classmethod
-    def from_location(
-        cls,
-        location: str,
-        basename: StrPath,
-        metadata: _MetadataType = None,
-        **kw: int,  # We could set `precedence` explicitly, but keeping this as `**kw` for full backwards and subclassing compatibility
-    ) -> Distribution:
+    def from_location(cls, location, basename, metadata=None, **kw):
         project_name, version, py_version, platform = [None] * 4
         basename, ext = os.path.splitext(basename)
         if ext.lower() in _distributionImpl:
@@ -2937,25 +2688,25 @@ def hashcmp(self):
     def __hash__(self):
         return hash(self.hashcmp)
 
-    def __lt__(self, other: Distribution):
+    def __lt__(self, other):
         return self.hashcmp < other.hashcmp
 
-    def __le__(self, other: Distribution):
+    def __le__(self, other):
         return self.hashcmp <= other.hashcmp
 
-    def __gt__(self, other: Distribution):
+    def __gt__(self, other):
         return self.hashcmp > other.hashcmp
 
-    def __ge__(self, other: Distribution):
+    def __ge__(self, other):
         return self.hashcmp >= other.hashcmp
 
-    def __eq__(self, other: object):
+    def __eq__(self, other):
         if not isinstance(other, self.__class__):
             # It's not a Distribution, so they are not equal
             return False
         return self.hashcmp == other.hashcmp
 
-    def __ne__(self, other: object):
+    def __ne__(self, other):
         return not self == other
 
     # These properties have to be lazy so that we don't have to load any
@@ -2975,12 +2726,12 @@ def parsed_version(self):
         if not hasattr(self, "_parsed_version"):
             try:
                 self._parsed_version = parse_version(self.version)
-            except _packaging_version.InvalidVersion as ex:
+            except packaging.version.InvalidVersion as ex:
                 info = f"(package: {self.project_name})"
                 if hasattr(ex, "add_note"):
                     ex.add_note(info)  # PEP 678
                     raise
-                raise _packaging_version.InvalidVersion(f"{str(ex)} {info}") from None
+                raise packaging.version.InvalidVersion(f"{str(ex)} {info}") from None
 
         return self._parsed_version
 
@@ -2988,7 +2739,7 @@ def parsed_version(self):
     def _forgiving_parsed_version(self):
         try:
             return self.parsed_version
-        except _packaging_version.InvalidVersion as ex:
+        except packaging.version.InvalidVersion as ex:
             self._parsed_version = parse_version(_forgiving_version(self.version))
 
             notes = "\n".join(getattr(ex, "__notes__", []))  # PEP 678
@@ -3038,14 +2789,14 @@ def _dep_map(self):
         return self.__dep_map
 
     @staticmethod
-    def _filter_extras(dm: dict[str | None, list[Requirement]]):
+    def _filter_extras(dm):
         """
         Given a mapping of extras to dependencies, strip off
         environment markers and filter out any dependencies
         not matching the markers.
         """
         for extra in list(filter(None, dm)):
-            new_extra: str | None = extra
+            new_extra = extra
             reqs = dm.pop(extra)
             new_extra, _, marker = extra.partition(':')
             fails_marker = marker and (
@@ -3065,10 +2816,10 @@ def _build_dep_map(self):
                 dm.setdefault(extra, []).extend(parse_requirements(reqs))
         return dm
 
-    def requires(self, extras: Iterable[str] = ()):
+    def requires(self, extras=()):
         """List of Requirements needed for this distro if `extras` are used"""
         dm = self._dep_map
-        deps: list[Requirement] = []
+        deps = []
         deps.extend(dm.get(None, ()))
         for ext in extras:
             try:
@@ -3098,18 +2849,21 @@ def _get_metadata_path_for_display(self, name):
 
     def _get_metadata(self, name):
         if self.has_metadata(name):
-            yield from self.get_metadata_lines(name)
+            for line in self.get_metadata_lines(name):
+                yield line
 
     def _get_version(self):
         lines = self._get_metadata(self.PKG_INFO)
-        return _version_from_file(lines)
+        version = _version_from_file(lines)
 
-    def activate(self, path: list[str] | None = None, replace: bool = False):
+        return version
+
+    def activate(self, path=None, replace=False):
         """Ensure distribution is importable on `path` (default=sys.path)"""
         if path is None:
             path = sys.path
         self.insert_on(path, replace=replace)
-        if path is sys.path and self.location is not None:
+        if path is sys.path:
             fixup_namespace_packages(self.location)
             for pkg in self._get_metadata('namespace_packages.txt'):
                 if pkg in sys.modules:
@@ -3149,62 +2903,50 @@ def __getattr__(self, attr):
 
     def __dir__(self):
         return list(
-            set(super().__dir__())
+            set(super(Distribution, self).__dir__())
             | set(attr for attr in self._provider.__dir__() if not attr.startswith('_'))
         )
 
     @classmethod
-    def from_filename(
-        cls,
-        filename: StrPath,
-        metadata: _MetadataType = None,
-        **kw: int,  # We could set `precedence` explicitly, but keeping this as `**kw` for full backwards and subclassing compatibility
-    ):
+    def from_filename(cls, filename, metadata=None, **kw):
         return cls.from_location(
             _normalize_cached(filename), os.path.basename(filename), metadata, **kw
         )
 
     def as_requirement(self):
         """Return a ``Requirement`` that matches this distribution exactly"""
-        if isinstance(self.parsed_version, _packaging_version.Version):
+        if isinstance(self.parsed_version, packaging.version.Version):
             spec = "%s==%s" % (self.project_name, self.parsed_version)
         else:
             spec = "%s===%s" % (self.project_name, self.parsed_version)
 
         return Requirement.parse(spec)
 
-    def load_entry_point(self, group: str, name: str) -> _ResolvedEntryPoint:
+    def load_entry_point(self, group, name):
         """Return the `name` entry point of `group` or raise ImportError"""
         ep = self.get_entry_info(group, name)
         if ep is None:
             raise ImportError("Entry point %r not found" % ((group, name),))
         return ep.load()
 
-    @overload
-    def get_entry_map(self, group: None = None) -> dict[str, dict[str, EntryPoint]]: ...
-    @overload
-    def get_entry_map(self, group: str) -> dict[str, EntryPoint]: ...
-    def get_entry_map(self, group: str | None = None):
+    def get_entry_map(self, group=None):
         """Return the entry point map for `group`, or the full entry map"""
-        if not hasattr(self, "_ep_map"):
-            self._ep_map = EntryPoint.parse_map(
+        try:
+            ep_map = self._ep_map
+        except AttributeError:
+            ep_map = self._ep_map = EntryPoint.parse_map(
                 self._get_metadata('entry_points.txt'), self
             )
         if group is not None:
-            return self._ep_map.get(group, {})
-        return self._ep_map
+            return ep_map.get(group, {})
+        return ep_map
 
-    def get_entry_info(self, group: str, name: str):
+    def get_entry_info(self, group, name):
         """Return the EntryPoint object for `group`+`name`, or ``None``"""
         return self.get_entry_map(group).get(name)
 
     # FIXME: 'Distribution.insert_on' is too complex (13)
-    def insert_on(  # noqa: C901
-        self,
-        path: list[str],
-        loc=None,
-        replace: bool = False,
-    ):
+    def insert_on(self, path, loc=None, replace=False):  # noqa: C901
         """Ensure self.location is on path
 
         If replace=False (default):
@@ -3309,14 +3051,13 @@ def has_version(self):
             return False
         return True
 
-    def clone(self, **kw: str | int | IResourceProvider | None):
+    def clone(self, **kw):
         """Copy this distribution, substituting in any changed keyword args"""
         names = 'project_name version py_version platform location precedence'
         for attr in names.split():
             kw.setdefault(attr, getattr(self, attr, None))
         kw.setdefault('metadata', self._provider)
-        # Unsafely unpacking. But keeping **kw for backwards and subclassing compatibility
-        return self.__class__(**kw)  # type:ignore[arg-type]
+        return self.__class__(**kw)
 
     @property
     def extras(self):
@@ -3369,11 +3110,11 @@ def _dep_map(self):
             self.__dep_map = self._compute_dependencies()
             return self.__dep_map
 
-    def _compute_dependencies(self) -> dict[str | None, list[Requirement]]:
+    def _compute_dependencies(self):
         """Recompute this distribution's dependencies."""
-        self.__dep_map: dict[str | None, list[Requirement]] = {None: []}
+        dm = self.__dep_map = {None: []}
 
-        reqs: list[Requirement] = []
+        reqs = []
         # Including any condition expressions
         for req in self._parsed_pkg_info.get_all('Requires-Dist') or []:
             reqs.extend(parse_requirements(req))
@@ -3384,15 +3125,13 @@ def reqs_for_extra(extra):
                     yield req
 
         common = types.MappingProxyType(dict.fromkeys(reqs_for_extra(None)))
-        self.__dep_map[None].extend(common)
+        dm[None].extend(common)
 
         for extra in self._parsed_pkg_info.get_all('Provides-Extra') or []:
             s_extra = safe_extra(extra.strip())
-            self.__dep_map[s_extra] = [
-                r for r in reqs_for_extra(extra) if r not in common
-            ]
+            dm[s_extra] = [r for r in reqs_for_extra(extra) if r not in common]
 
-        return self.__dep_map
+        return dm
 
 
 _distributionImpl = {
@@ -3415,7 +3154,7 @@ def issue_warning(*args, **kw):
     warnings.warn(stacklevel=level + 1, *args, **kw)
 
 
-def parse_requirements(strs: _NestedStr):
+def parse_requirements(strs):
     """
     Yield ``Requirement`` objects for each specification in `strs`.
 
@@ -3424,20 +3163,19 @@ def parse_requirements(strs: _NestedStr):
     return map(Requirement, join_continuation(map(drop_comment, yield_lines(strs))))
 
 
-class RequirementParseError(_packaging_requirements.InvalidRequirement):
+class RequirementParseError(packaging.requirements.InvalidRequirement):
     "Compatibility wrapper for InvalidRequirement"
 
 
-class Requirement(_packaging_requirements.Requirement):
-    def __init__(self, requirement_string: str):
+class Requirement(packaging.requirements.Requirement):
+    def __init__(self, requirement_string):
         """DO NOT CALL THIS UNDOCUMENTED METHOD; use Requirement.parse()!"""
-        super().__init__(requirement_string)
+        super(Requirement, self).__init__(requirement_string)
         self.unsafe_name = self.name
         project_name = safe_name(self.name)
         self.project_name, self.key = project_name, project_name.lower()
         self.specs = [(spec.operator, spec.version) for spec in self.specifier]
-        # packaging.requirements.Requirement uses a set for its extras. We use a variable-length tuple
-        self.extras: tuple[str] = tuple(map(safe_extra, self.extras))
+        self.extras = tuple(map(safe_extra, self.extras))
         self.hashCmp = (
             self.key,
             self.url,
@@ -3447,13 +3185,13 @@ def __init__(self, requirement_string: str):
         )
         self.__hash = hash(self.hashCmp)
 
-    def __eq__(self, other: object):
+    def __eq__(self, other):
         return isinstance(other, Requirement) and self.hashCmp == other.hashCmp
 
     def __ne__(self, other):
         return not self == other
 
-    def __contains__(self, item: Distribution | str | tuple[str, ...]) -> bool:
+    def __contains__(self, item):
         if isinstance(item, Distribution):
             if item.key != self.key:
                 return False
@@ -3472,7 +3210,7 @@ def __repr__(self):
         return "Requirement.parse(%r)" % str(self)
 
     @staticmethod
-    def parse(s: str | Iterable[str]):
+    def parse(s):
         (req,) = parse_requirements(s)
         return req
 
@@ -3487,18 +3225,15 @@ def _always_object(classes):
     return classes
 
 
-def _find_adapter(registry: Mapping[type, _AdapterT], ob: object) -> _AdapterT:
+def _find_adapter(registry, ob):
     """Return an adapter factory for `ob` from `registry`"""
     types = _always_object(inspect.getmro(getattr(ob, '__class__', type(ob))))
     for t in types:
         if t in registry:
             return registry[t]
-    # _find_adapter would previously return None, and immediately be called.
-    # So we're raising a TypeError to keep backward compatibility if anyone depended on that behaviour.
-    raise TypeError(f"Could not find adapter for {registry} and {ob}")
 
 
-def ensure_directory(path: StrOrBytesPath):
+def ensure_directory(path):
     """Ensure that the parent directory of `path` exists"""
     dirname = os.path.dirname(path)
     os.makedirs(dirname, exist_ok=True)
@@ -3507,7 +3242,7 @@ def ensure_directory(path: StrOrBytesPath):
 def _bypass_ensure_directory(path):
     """Sandbox-bypassing version of ensure_directory()"""
     if not WRITE_SUPPORT:
-        raise OSError('"os.mkdir" not supported on this platform.')
+        raise IOError('"os.mkdir" not supported on this platform.')
     dirname, filename = split(path)
     if dirname and filename and not isdir(dirname):
         _bypass_ensure_directory(dirname)
@@ -3517,7 +3252,7 @@ def _bypass_ensure_directory(path):
             pass
 
 
-def split_sections(s: _NestedStr) -> Iterator[tuple[str | None, list[str]]]:
+def split_sections(s):
     """Split a string or iterable thereof into (section, content) pairs
 
     Each ``section`` is a stripped version of the section header ("[section]")
@@ -3561,47 +3296,6 @@ def _mkstemp(*args, **kw):
 warnings.filterwarnings("ignore", category=PEP440Warning, append=True)
 
 
-class PkgResourcesDeprecationWarning(Warning):
-    """
-    Base class for warning about deprecations in ``pkg_resources``
-
-    This class is not derived from ``DeprecationWarning``, and as such is
-    visible by default.
-    """
-
-
-# Ported from ``setuptools`` to avoid introducing an import inter-dependency:
-_LOCALE_ENCODING = "locale" if sys.version_info >= (3, 10) else None
-
-
-def _read_utf8_with_fallback(file: str, fallback_encoding=_LOCALE_ENCODING) -> str:
-    """See setuptools.unicode_utils._read_utf8_with_fallback"""
-    try:
-        with open(file, "r", encoding="utf-8") as f:
-            return f.read()
-    except UnicodeDecodeError:  # pragma: no cover
-        msg = f"""\
-        ********************************************************************************
-        `encoding="utf-8"` fails with {file!r}, trying `encoding={fallback_encoding!r}`.
-
-        This fallback behaviour is considered **deprecated** and future versions of
-        `setuptools/pkg_resources` may not implement it.
-
-        Please encode {file!r} with "utf-8" to ensure future builds will succeed.
-
-        If this file was produced by `setuptools` itself, cleaning up the cached files
-        and re-building/re-installing the package with a newer version of `setuptools`
-        (e.g. by updating `build-system.requires` in its `pyproject.toml`)
-        might solve the problem.
-        ********************************************************************************
-        """
-        # TODO: Add a deadline?
-        #       See comment in setuptools.unicode_utils._Utf8EncodingNeeded
-        warnings.warn(msg, PkgResourcesDeprecationWarning, stacklevel=2)
-        with open(file, "r", encoding=fallback_encoding) as f:
-            return f.read()
-
-
 # from jaraco.functools 1.3
 def _call_aside(f, *args, **kwargs):
     f(*args, **kwargs)
@@ -3620,6 +3314,15 @@ def _initialize(g=globals()):
     )
 
 
+class PkgResourcesDeprecationWarning(Warning):
+    """
+    Base class for warning about deprecations in ``pkg_resources``
+
+    This class is not derived from ``DeprecationWarning``, and as such is
+    visible by default.
+    """
+
+
 @_call_aside
 def _initialize_master_working_set():
     """
@@ -3633,7 +3336,8 @@ def _initialize_master_working_set():
     Invocation by other packages is unsupported and done
     at their own risk.
     """
-    working_set = _declare_state('object', 'working_set', WorkingSet._build_master())
+    working_set = WorkingSet._build_master()
+    _declare_state('object', working_set=working_set)
 
     require = working_set.require
     iter_entry_points = working_set.iter_entry_points
@@ -3654,23 +3358,3 @@ def _initialize_master_working_set():
     # match order
     list(map(working_set.add_entry, sys.path))
     globals().update(locals())
-
-
-if TYPE_CHECKING:
-    # All of these are set by the @_call_aside methods above
-    __resource_manager = ResourceManager()  # Won't exist at runtime
-    resource_exists = __resource_manager.resource_exists
-    resource_isdir = __resource_manager.resource_isdir
-    resource_filename = __resource_manager.resource_filename
-    resource_stream = __resource_manager.resource_stream
-    resource_string = __resource_manager.resource_string
-    resource_listdir = __resource_manager.resource_listdir
-    set_extraction_path = __resource_manager.set_extraction_path
-    cleanup_resources = __resource_manager.cleanup_resources
-
-    working_set = WorkingSet()
-    require = working_set.require
-    iter_entry_points = working_set.iter_entry_points
-    add_activation_listener = working_set.subscribe
-    run_script = working_set.run_script
-    run_main = run_script
diff --git a/venv1/Lib/site-packages/pip/_vendor/platformdirs/__init__.py b/venv1/Lib/site-packages/pip/_vendor/platformdirs/__init__.py
index 2325ec2e..c46a145c 100644
--- a/venv1/Lib/site-packages/pip/_vendor/platformdirs/__init__.py
+++ b/venv1/Lib/site-packages/pip/_vendor/platformdirs/__init__.py
@@ -1,61 +1,55 @@
 """
-Utilities for determining application-specific dirs.
-
-See  for details and usage.
-
+Utilities for determining application-specific dirs. See  for details and
+usage.
 """
-
 from __future__ import annotations
 
 import os
 import sys
-from typing import TYPE_CHECKING
+from pathlib import Path
+
+if sys.version_info >= (3, 8):  # pragma: no cover (py38+)
+    from typing import Literal
+else:  # pragma: no cover (py38+)
+    from pip._vendor.typing_extensions import Literal
 
 from .api import PlatformDirsABC
 from .version import __version__
 from .version import __version_tuple__ as __version_info__
 
-if TYPE_CHECKING:
-    from pathlib import Path
-    from typing import Literal
-
-if sys.platform == "win32":
-    from pip._vendor.platformdirs.windows import Windows as _Result
-elif sys.platform == "darwin":
-    from pip._vendor.platformdirs.macos import MacOS as _Result
-else:
-    from pip._vendor.platformdirs.unix import Unix as _Result
-
 
 def _set_platform_dir_class() -> type[PlatformDirsABC]:
+    if sys.platform == "win32":
+        from pip._vendor.platformdirs.windows import Windows as Result
+    elif sys.platform == "darwin":
+        from pip._vendor.platformdirs.macos import MacOS as Result
+    else:
+        from pip._vendor.platformdirs.unix import Unix as Result
+
     if os.getenv("ANDROID_DATA") == "/data" and os.getenv("ANDROID_ROOT") == "/system":
         if os.getenv("SHELL") or os.getenv("PREFIX"):
-            return _Result
+            return Result
 
-        from pip._vendor.platformdirs.android import _android_folder  # noqa: PLC0415
+        from pip._vendor.platformdirs.android import _android_folder
 
         if _android_folder() is not None:
-            from pip._vendor.platformdirs.android import Android  # noqa: PLC0415
+            from pip._vendor.platformdirs.android import Android
 
-            return Android  # return to avoid redefinition of a result
+            return Android  # return to avoid redefinition of result
 
-    return _Result
+    return Result
 
 
-if TYPE_CHECKING:
-    # Work around mypy issue: https://github.com/python/mypy/issues/10962
-    PlatformDirs = _Result
-else:
-    PlatformDirs = _set_platform_dir_class()  #: Currently active platform
+PlatformDirs = _set_platform_dir_class()  #: Currently active platform
 AppDirs = PlatformDirs  #: Backwards compatibility with appdirs
 
 
 def user_data_dir(
     appname: str | None = None,
-    appauthor: str | Literal[False] | None = None,
+    appauthor: str | None | Literal[False] = None,
     version: str | None = None,
-    roaming: bool = False,  # noqa: FBT001, FBT002
-    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+    roaming: bool = False,
+    ensure_exists: bool = False,
 ) -> str:
     """
     :param appname: See `appname `.
@@ -76,10 +70,10 @@ def user_data_dir(
 
 def site_data_dir(
     appname: str | None = None,
-    appauthor: str | Literal[False] | None = None,
+    appauthor: str | None | Literal[False] = None,
     version: str | None = None,
-    multipath: bool = False,  # noqa: FBT001, FBT002
-    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+    multipath: bool = False,
+    ensure_exists: bool = False,
 ) -> str:
     """
     :param appname: See `appname `.
@@ -100,10 +94,10 @@ def site_data_dir(
 
 def user_config_dir(
     appname: str | None = None,
-    appauthor: str | Literal[False] | None = None,
+    appauthor: str | None | Literal[False] = None,
     version: str | None = None,
-    roaming: bool = False,  # noqa: FBT001, FBT002
-    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+    roaming: bool = False,
+    ensure_exists: bool = False,
 ) -> str:
     """
     :param appname: See `appname `.
@@ -124,10 +118,10 @@ def user_config_dir(
 
 def site_config_dir(
     appname: str | None = None,
-    appauthor: str | Literal[False] | None = None,
+    appauthor: str | None | Literal[False] = None,
     version: str | None = None,
-    multipath: bool = False,  # noqa: FBT001, FBT002
-    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+    multipath: bool = False,
+    ensure_exists: bool = False,
 ) -> str:
     """
     :param appname: See `appname `.
@@ -148,10 +142,10 @@ def site_config_dir(
 
 def user_cache_dir(
     appname: str | None = None,
-    appauthor: str | Literal[False] | None = None,
+    appauthor: str | None | Literal[False] = None,
     version: str | None = None,
-    opinion: bool = True,  # noqa: FBT001, FBT002
-    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+    opinion: bool = True,
+    ensure_exists: bool = False,
 ) -> str:
     """
     :param appname: See `appname `.
@@ -172,10 +166,10 @@ def user_cache_dir(
 
 def site_cache_dir(
     appname: str | None = None,
-    appauthor: str | Literal[False] | None = None,
+    appauthor: str | None | Literal[False] = None,
     version: str | None = None,
-    opinion: bool = True,  # noqa: FBT001, FBT002
-    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+    opinion: bool = True,
+    ensure_exists: bool = False,
 ) -> str:
     """
     :param appname: See `appname `.
@@ -196,10 +190,10 @@ def site_cache_dir(
 
 def user_state_dir(
     appname: str | None = None,
-    appauthor: str | Literal[False] | None = None,
+    appauthor: str | None | Literal[False] = None,
     version: str | None = None,
-    roaming: bool = False,  # noqa: FBT001, FBT002
-    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+    roaming: bool = False,
+    ensure_exists: bool = False,
 ) -> str:
     """
     :param appname: See `appname `.
@@ -220,10 +214,10 @@ def user_state_dir(
 
 def user_log_dir(
     appname: str | None = None,
-    appauthor: str | Literal[False] | None = None,
+    appauthor: str | None | Literal[False] = None,
     version: str | None = None,
-    opinion: bool = True,  # noqa: FBT001, FBT002
-    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+    opinion: bool = True,
+    ensure_exists: bool = False,
 ) -> str:
     """
     :param appname: See `appname `.
@@ -243,41 +237,18 @@ def user_log_dir(
 
 
 def user_documents_dir() -> str:
-    """:returns: documents directory tied to the user"""
+    """
+    :returns: documents directory tied to the user
+    """
     return PlatformDirs().user_documents_dir
 
 
-def user_downloads_dir() -> str:
-    """:returns: downloads directory tied to the user"""
-    return PlatformDirs().user_downloads_dir
-
-
-def user_pictures_dir() -> str:
-    """:returns: pictures directory tied to the user"""
-    return PlatformDirs().user_pictures_dir
-
-
-def user_videos_dir() -> str:
-    """:returns: videos directory tied to the user"""
-    return PlatformDirs().user_videos_dir
-
-
-def user_music_dir() -> str:
-    """:returns: music directory tied to the user"""
-    return PlatformDirs().user_music_dir
-
-
-def user_desktop_dir() -> str:
-    """:returns: desktop directory tied to the user"""
-    return PlatformDirs().user_desktop_dir
-
-
 def user_runtime_dir(
     appname: str | None = None,
-    appauthor: str | Literal[False] | None = None,
+    appauthor: str | None | Literal[False] = None,
     version: str | None = None,
-    opinion: bool = True,  # noqa: FBT001, FBT002
-    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+    opinion: bool = True,
+    ensure_exists: bool = False,
 ) -> str:
     """
     :param appname: See `appname `.
@@ -296,36 +267,12 @@ def user_runtime_dir(
     ).user_runtime_dir
 
 
-def site_runtime_dir(
-    appname: str | None = None,
-    appauthor: str | Literal[False] | None = None,
-    version: str | None = None,
-    opinion: bool = True,  # noqa: FBT001, FBT002
-    ensure_exists: bool = False,  # noqa: FBT001, FBT002
-) -> str:
-    """
-    :param appname: See `appname `.
-    :param appauthor: See `appauthor `.
-    :param version: See `version `.
-    :param opinion: See `opinion `.
-    :param ensure_exists: See `ensure_exists `.
-    :returns: runtime directory shared by users
-    """
-    return PlatformDirs(
-        appname=appname,
-        appauthor=appauthor,
-        version=version,
-        opinion=opinion,
-        ensure_exists=ensure_exists,
-    ).site_runtime_dir
-
-
 def user_data_path(
     appname: str | None = None,
-    appauthor: str | Literal[False] | None = None,
+    appauthor: str | None | Literal[False] = None,
     version: str | None = None,
-    roaming: bool = False,  # noqa: FBT001, FBT002
-    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+    roaming: bool = False,
+    ensure_exists: bool = False,
 ) -> Path:
     """
     :param appname: See `appname `.
@@ -346,10 +293,10 @@ def user_data_path(
 
 def site_data_path(
     appname: str | None = None,
-    appauthor: str | Literal[False] | None = None,
+    appauthor: str | None | Literal[False] = None,
     version: str | None = None,
-    multipath: bool = False,  # noqa: FBT001, FBT002
-    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+    multipath: bool = False,
+    ensure_exists: bool = False,
 ) -> Path:
     """
     :param appname: See `appname `.
@@ -370,10 +317,10 @@ def site_data_path(
 
 def user_config_path(
     appname: str | None = None,
-    appauthor: str | Literal[False] | None = None,
+    appauthor: str | None | Literal[False] = None,
     version: str | None = None,
-    roaming: bool = False,  # noqa: FBT001, FBT002
-    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+    roaming: bool = False,
+    ensure_exists: bool = False,
 ) -> Path:
     """
     :param appname: See `appname `.
@@ -394,10 +341,10 @@ def user_config_path(
 
 def site_config_path(
     appname: str | None = None,
-    appauthor: str | Literal[False] | None = None,
+    appauthor: str | None | Literal[False] = None,
     version: str | None = None,
-    multipath: bool = False,  # noqa: FBT001, FBT002
-    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+    multipath: bool = False,
+    ensure_exists: bool = False,
 ) -> Path:
     """
     :param appname: See `appname `.
@@ -418,10 +365,10 @@ def site_config_path(
 
 def site_cache_path(
     appname: str | None = None,
-    appauthor: str | Literal[False] | None = None,
+    appauthor: str | None | Literal[False] = None,
     version: str | None = None,
-    opinion: bool = True,  # noqa: FBT001, FBT002
-    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+    opinion: bool = True,
+    ensure_exists: bool = False,
 ) -> Path:
     """
     :param appname: See `appname `.
@@ -442,10 +389,10 @@ def site_cache_path(
 
 def user_cache_path(
     appname: str | None = None,
-    appauthor: str | Literal[False] | None = None,
+    appauthor: str | None | Literal[False] = None,
     version: str | None = None,
-    opinion: bool = True,  # noqa: FBT001, FBT002
-    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+    opinion: bool = True,
+    ensure_exists: bool = False,
 ) -> Path:
     """
     :param appname: See `appname `.
@@ -466,10 +413,10 @@ def user_cache_path(
 
 def user_state_path(
     appname: str | None = None,
-    appauthor: str | Literal[False] | None = None,
+    appauthor: str | None | Literal[False] = None,
     version: str | None = None,
-    roaming: bool = False,  # noqa: FBT001, FBT002
-    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+    roaming: bool = False,
+    ensure_exists: bool = False,
 ) -> Path:
     """
     :param appname: See `appname `.
@@ -490,10 +437,10 @@ def user_state_path(
 
 def user_log_path(
     appname: str | None = None,
-    appauthor: str | Literal[False] | None = None,
+    appauthor: str | None | Literal[False] = None,
     version: str | None = None,
-    opinion: bool = True,  # noqa: FBT001, FBT002
-    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+    opinion: bool = True,
+    ensure_exists: bool = False,
 ) -> Path:
     """
     :param appname: See `appname `.
@@ -513,41 +460,18 @@ def user_log_path(
 
 
 def user_documents_path() -> Path:
-    """:returns: documents a path tied to the user"""
+    """
+    :returns: documents path tied to the user
+    """
     return PlatformDirs().user_documents_path
 
 
-def user_downloads_path() -> Path:
-    """:returns: downloads path tied to the user"""
-    return PlatformDirs().user_downloads_path
-
-
-def user_pictures_path() -> Path:
-    """:returns: pictures path tied to the user"""
-    return PlatformDirs().user_pictures_path
-
-
-def user_videos_path() -> Path:
-    """:returns: videos path tied to the user"""
-    return PlatformDirs().user_videos_path
-
-
-def user_music_path() -> Path:
-    """:returns: music path tied to the user"""
-    return PlatformDirs().user_music_path
-
-
-def user_desktop_path() -> Path:
-    """:returns: desktop path tied to the user"""
-    return PlatformDirs().user_desktop_path
-
-
 def user_runtime_path(
     appname: str | None = None,
-    appauthor: str | Literal[False] | None = None,
+    appauthor: str | None | Literal[False] = None,
     version: str | None = None,
-    opinion: bool = True,  # noqa: FBT001, FBT002
-    ensure_exists: bool = False,  # noqa: FBT001, FBT002
+    opinion: bool = True,
+    ensure_exists: bool = False,
 ) -> Path:
     """
     :param appname: See `appname `.
@@ -566,66 +490,30 @@ def user_runtime_path(
     ).user_runtime_path
 
 
-def site_runtime_path(
-    appname: str | None = None,
-    appauthor: str | Literal[False] | None = None,
-    version: str | None = None,
-    opinion: bool = True,  # noqa: FBT001, FBT002
-    ensure_exists: bool = False,  # noqa: FBT001, FBT002
-) -> Path:
-    """
-    :param appname: See `appname `.
-    :param appauthor: See `appauthor `.
-    :param version: See `version `.
-    :param opinion: See `opinion `.
-    :param ensure_exists: See `ensure_exists `.
-    :returns: runtime path shared by users
-    """
-    return PlatformDirs(
-        appname=appname,
-        appauthor=appauthor,
-        version=version,
-        opinion=opinion,
-        ensure_exists=ensure_exists,
-    ).site_runtime_path
-
-
 __all__ = [
-    "AppDirs",
-    "PlatformDirs",
-    "PlatformDirsABC",
     "__version__",
     "__version_info__",
-    "site_cache_dir",
-    "site_cache_path",
-    "site_config_dir",
-    "site_config_path",
-    "site_data_dir",
-    "site_data_path",
-    "site_runtime_dir",
-    "site_runtime_path",
-    "user_cache_dir",
-    "user_cache_path",
-    "user_config_dir",
-    "user_config_path",
+    "PlatformDirs",
+    "AppDirs",
+    "PlatformDirsABC",
     "user_data_dir",
-    "user_data_path",
-    "user_desktop_dir",
-    "user_desktop_path",
-    "user_documents_dir",
-    "user_documents_path",
-    "user_downloads_dir",
-    "user_downloads_path",
+    "user_config_dir",
+    "user_cache_dir",
+    "user_state_dir",
     "user_log_dir",
-    "user_log_path",
-    "user_music_dir",
-    "user_music_path",
-    "user_pictures_dir",
-    "user_pictures_path",
+    "user_documents_dir",
     "user_runtime_dir",
-    "user_runtime_path",
-    "user_state_dir",
+    "site_data_dir",
+    "site_config_dir",
+    "site_cache_dir",
+    "user_data_path",
+    "user_config_path",
+    "user_cache_path",
     "user_state_path",
-    "user_videos_dir",
-    "user_videos_path",
+    "user_log_path",
+    "user_documents_path",
+    "user_runtime_path",
+    "site_data_path",
+    "site_config_path",
+    "site_cache_path",
 ]
diff --git a/venv1/Lib/site-packages/pip/_vendor/platformdirs/__main__.py b/venv1/Lib/site-packages/pip/_vendor/platformdirs/__main__.py
index fa8a677a..7171f131 100644
--- a/venv1/Lib/site-packages/pip/_vendor/platformdirs/__main__.py
+++ b/venv1/Lib/site-packages/pip/_vendor/platformdirs/__main__.py
@@ -1,5 +1,3 @@
-"""Main entry point."""
-
 from __future__ import annotations
 
 from pip._vendor.platformdirs import PlatformDirs, __version__
@@ -11,44 +9,38 @@
     "user_state_dir",
     "user_log_dir",
     "user_documents_dir",
-    "user_downloads_dir",
-    "user_pictures_dir",
-    "user_videos_dir",
-    "user_music_dir",
     "user_runtime_dir",
     "site_data_dir",
     "site_config_dir",
     "site_cache_dir",
-    "site_runtime_dir",
 )
 
 
 def main() -> None:
-    """Run the main entry point."""
     app_name = "MyApp"
     app_author = "MyCompany"
 
-    print(f"-- platformdirs {__version__} --")  # noqa: T201
+    print(f"-- platformdirs {__version__} --")
 
-    print("-- app dirs (with optional 'version')")  # noqa: T201
+    print("-- app dirs (with optional 'version')")
     dirs = PlatformDirs(app_name, app_author, version="1.0")
     for prop in PROPS:
-        print(f"{prop}: {getattr(dirs, prop)}")  # noqa: T201
+        print(f"{prop}: {getattr(dirs, prop)}")
 
-    print("\n-- app dirs (without optional 'version')")  # noqa: T201
+    print("\n-- app dirs (without optional 'version')")
     dirs = PlatformDirs(app_name, app_author)
     for prop in PROPS:
-        print(f"{prop}: {getattr(dirs, prop)}")  # noqa: T201
+        print(f"{prop}: {getattr(dirs, prop)}")
 
-    print("\n-- app dirs (without optional 'appauthor')")  # noqa: T201
+    print("\n-- app dirs (without optional 'appauthor')")
     dirs = PlatformDirs(app_name)
     for prop in PROPS:
-        print(f"{prop}: {getattr(dirs, prop)}")  # noqa: T201
+        print(f"{prop}: {getattr(dirs, prop)}")
 
-    print("\n-- app dirs (with disabled 'appauthor')")  # noqa: T201
+    print("\n-- app dirs (with disabled 'appauthor')")
     dirs = PlatformDirs(app_name, appauthor=False)
     for prop in PROPS:
-        print(f"{prop}: {getattr(dirs, prop)}")  # noqa: T201
+        print(f"{prop}: {getattr(dirs, prop)}")
 
 
 if __name__ == "__main__":
diff --git a/venv1/Lib/site-packages/pip/_vendor/platformdirs/android.py b/venv1/Lib/site-packages/pip/_vendor/platformdirs/android.py
index 92efc852..f6de7451 100644
--- a/venv1/Lib/site-packages/pip/_vendor/platformdirs/android.py
+++ b/venv1/Lib/site-packages/pip/_vendor/platformdirs/android.py
@@ -1,29 +1,26 @@
-"""Android."""
-
 from __future__ import annotations
 
 import os
 import re
 import sys
 from functools import lru_cache
-from typing import TYPE_CHECKING, cast
+from typing import cast
 
 from .api import PlatformDirsABC
 
 
 class Android(PlatformDirsABC):
     """
-    Follows the guidance `from here `_.
-
-    Makes use of the `appname `, `version
-    `, `ensure_exists `.
-
+    Follows the guidance `from here `_. Makes use of the
+    `appname `,
+    `version `,
+    `ensure_exists `.
     """
 
     @property
     def user_data_dir(self) -> str:
         """:return: data directory tied to the user, e.g. ``/data/user///files/``"""
-        return self._append_app_name_and_version(cast("str", _android_folder()), "files")
+        return self._append_app_name_and_version(cast(str, _android_folder()), "files")
 
     @property
     def site_data_dir(self) -> str:
@@ -33,10 +30,9 @@ def site_data_dir(self) -> str:
     @property
     def user_config_dir(self) -> str:
         """
-        :return: config directory tied to the user, e.g. \
-        ``/data/user///shared_prefs/``
+        :return: config directory tied to the user, e.g. ``/data/user///shared_prefs/``
         """
-        return self._append_app_name_and_version(cast("str", _android_folder()), "shared_prefs")
+        return self._append_app_name_and_version(cast(str, _android_folder()), "shared_prefs")
 
     @property
     def site_config_dir(self) -> str:
@@ -45,8 +41,8 @@ def site_config_dir(self) -> str:
 
     @property
     def user_cache_dir(self) -> str:
-        """:return: cache directory tied to the user, e.g.,``/data/user///cache/``"""
-        return self._append_app_name_and_version(cast("str", _android_folder()), "cache")
+        """:return: cache directory tied to the user, e.g. e.g. ``/data/user///cache/``"""
+        return self._append_app_name_and_version(cast(str, _android_folder()), "cache")
 
     @property
     def site_cache_dir(self) -> str:
@@ -66,39 +62,16 @@ def user_log_dir(self) -> str:
         """
         path = self.user_cache_dir
         if self.opinion:
-            path = os.path.join(path, "log")  # noqa: PTH118
+            path = os.path.join(path, "log")
         return path
 
     @property
     def user_documents_dir(self) -> str:
-        """:return: documents directory tied to the user e.g. ``/storage/emulated/0/Documents``"""
+        """
+        :return: documents directory tied to the user e.g. ``/storage/emulated/0/Documents``
+        """
         return _android_documents_folder()
 
-    @property
-    def user_downloads_dir(self) -> str:
-        """:return: downloads directory tied to the user e.g. ``/storage/emulated/0/Downloads``"""
-        return _android_downloads_folder()
-
-    @property
-    def user_pictures_dir(self) -> str:
-        """:return: pictures directory tied to the user e.g. ``/storage/emulated/0/Pictures``"""
-        return _android_pictures_folder()
-
-    @property
-    def user_videos_dir(self) -> str:
-        """:return: videos directory tied to the user e.g. ``/storage/emulated/0/DCIM/Camera``"""
-        return _android_videos_folder()
-
-    @property
-    def user_music_dir(self) -> str:
-        """:return: music directory tied to the user e.g. ``/storage/emulated/0/Music``"""
-        return _android_music_folder()
-
-    @property
-    def user_desktop_dir(self) -> str:
-        """:return: desktop directory tied to the user e.g. ``/storage/emulated/0/Desktop``"""
-        return "/storage/emulated/0/Desktop"
-
     @property
     def user_runtime_dir(self) -> str:
         """
@@ -107,43 +80,21 @@ def user_runtime_dir(self) -> str:
         """
         path = self.user_cache_dir
         if self.opinion:
-            path = os.path.join(path, "tmp")  # noqa: PTH118
+            path = os.path.join(path, "tmp")
         return path
 
-    @property
-    def site_runtime_dir(self) -> str:
-        """:return: runtime directory shared by users, same as `user_runtime_dir`"""
-        return self.user_runtime_dir
-
 
 @lru_cache(maxsize=1)
-def _android_folder() -> str | None:  # noqa: C901
-    """:return: base folder for the Android OS or None if it cannot be found"""
-    result: str | None = None
-    # type checker isn't happy with our "import android", just don't do this when type checking see
-    # https://stackoverflow.com/a/61394121
-    if not TYPE_CHECKING:
-        try:
-            # First try to get a path to android app using python4android (if available)...
-            from android import mActivity  # noqa: PLC0415
-
-            context = cast("android.content.Context", mActivity.getApplicationContext())  # noqa: F821
-            result = context.getFilesDir().getParentFile().getAbsolutePath()
-        except Exception:  # noqa: BLE001
-            result = None
-    if result is None:
-        try:
-            # ...and fall back to using plain pyjnius, if python4android isn't available or doesn't deliver any useful
-            # result...
-            from jnius import autoclass  # noqa: PLC0415
-
-            context = autoclass("android.content.Context")
-            result = context.getFilesDir().getParentFile().getAbsolutePath()
-        except Exception:  # noqa: BLE001
-            result = None
-    if result is None:
-        # and if that fails, too, find an android folder looking at path on the sys.path
-        # warning: only works for apps installed under /data, not adopted storage etc.
+def _android_folder() -> str | None:
+    """:return: base folder for the Android OS or None if cannot be found"""
+    try:
+        # First try to get path to android app via pyjnius
+        from jnius import autoclass
+
+        Context = autoclass("android.content.Context")  # noqa: N806
+        result: str | None = Context.getFilesDir().getParentFile().getAbsolutePath()
+    except Exception:
+        # if fails find an android folder looking path on the sys.path
         pattern = re.compile(r"/data/(data|user/\d+)/(.+)/files")
         for path in sys.path:
             if pattern.match(path):
@@ -151,16 +102,6 @@ def _android_folder() -> str | None:  # noqa: C901
                 break
         else:
             result = None
-    if result is None:
-        # one last try: find an android folder looking at path on the sys.path taking adopted storage paths into
-        # account
-        pattern = re.compile(r"/mnt/expand/[a-fA-F0-9-]{36}/(data|user/\d+)/(.+)/files")
-        for path in sys.path:
-            if pattern.match(path):
-                result = path.split("/files")[0]
-                break
-        else:
-            result = None
     return result
 
 
@@ -169,81 +110,17 @@ def _android_documents_folder() -> str:
     """:return: documents folder for the Android OS"""
     # Get directories with pyjnius
     try:
-        from jnius import autoclass  # noqa: PLC0415
+        from jnius import autoclass
 
-        context = autoclass("android.content.Context")
-        environment = autoclass("android.os.Environment")
-        documents_dir: str = context.getExternalFilesDir(environment.DIRECTORY_DOCUMENTS).getAbsolutePath()
-    except Exception:  # noqa: BLE001
+        Context = autoclass("android.content.Context")  # noqa: N806
+        Environment = autoclass("android.os.Environment")  # noqa: N806
+        documents_dir: str = Context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath()
+    except Exception:
         documents_dir = "/storage/emulated/0/Documents"
 
     return documents_dir
 
 
-@lru_cache(maxsize=1)
-def _android_downloads_folder() -> str:
-    """:return: downloads folder for the Android OS"""
-    # Get directories with pyjnius
-    try:
-        from jnius import autoclass  # noqa: PLC0415
-
-        context = autoclass("android.content.Context")
-        environment = autoclass("android.os.Environment")
-        downloads_dir: str = context.getExternalFilesDir(environment.DIRECTORY_DOWNLOADS).getAbsolutePath()
-    except Exception:  # noqa: BLE001
-        downloads_dir = "/storage/emulated/0/Downloads"
-
-    return downloads_dir
-
-
-@lru_cache(maxsize=1)
-def _android_pictures_folder() -> str:
-    """:return: pictures folder for the Android OS"""
-    # Get directories with pyjnius
-    try:
-        from jnius import autoclass  # noqa: PLC0415
-
-        context = autoclass("android.content.Context")
-        environment = autoclass("android.os.Environment")
-        pictures_dir: str = context.getExternalFilesDir(environment.DIRECTORY_PICTURES).getAbsolutePath()
-    except Exception:  # noqa: BLE001
-        pictures_dir = "/storage/emulated/0/Pictures"
-
-    return pictures_dir
-
-
-@lru_cache(maxsize=1)
-def _android_videos_folder() -> str:
-    """:return: videos folder for the Android OS"""
-    # Get directories with pyjnius
-    try:
-        from jnius import autoclass  # noqa: PLC0415
-
-        context = autoclass("android.content.Context")
-        environment = autoclass("android.os.Environment")
-        videos_dir: str = context.getExternalFilesDir(environment.DIRECTORY_DCIM).getAbsolutePath()
-    except Exception:  # noqa: BLE001
-        videos_dir = "/storage/emulated/0/DCIM/Camera"
-
-    return videos_dir
-
-
-@lru_cache(maxsize=1)
-def _android_music_folder() -> str:
-    """:return: music folder for the Android OS"""
-    # Get directories with pyjnius
-    try:
-        from jnius import autoclass  # noqa: PLC0415
-
-        context = autoclass("android.content.Context")
-        environment = autoclass("android.os.Environment")
-        music_dir: str = context.getExternalFilesDir(environment.DIRECTORY_MUSIC).getAbsolutePath()
-    except Exception:  # noqa: BLE001
-        music_dir = "/storage/emulated/0/Music"
-
-    return music_dir
-
-
 __all__ = [
     "Android",
 ]
diff --git a/venv1/Lib/site-packages/pip/_vendor/platformdirs/api.py b/venv1/Lib/site-packages/pip/_vendor/platformdirs/api.py
index 251600e6..f140e8b6 100644
--- a/venv1/Lib/site-packages/pip/_vendor/platformdirs/api.py
+++ b/venv1/Lib/site-packages/pip/_vendor/platformdirs/api.py
@@ -1,30 +1,29 @@
-"""Base API."""
-
 from __future__ import annotations
 
 import os
+import sys
 from abc import ABC, abstractmethod
 from pathlib import Path
-from typing import TYPE_CHECKING
 
-if TYPE_CHECKING:
-    from collections.abc import Iterator
-    from typing import Literal
+if sys.version_info >= (3, 8):  # pragma: no branch
+    from typing import Literal  # pragma: no cover
 
 
-class PlatformDirsABC(ABC):  # noqa: PLR0904
-    """Abstract base class for platform directories."""
+class PlatformDirsABC(ABC):
+    """
+    Abstract base class for platform directories.
+    """
 
-    def __init__(  # noqa: PLR0913, PLR0917
+    def __init__(
         self,
         appname: str | None = None,
-        appauthor: str | Literal[False] | None = None,
+        appauthor: str | None | Literal[False] = None,
         version: str | None = None,
-        roaming: bool = False,  # noqa: FBT001, FBT002
-        multipath: bool = False,  # noqa: FBT001, FBT002
-        opinion: bool = True,  # noqa: FBT001, FBT002
-        ensure_exists: bool = False,  # noqa: FBT001, FBT002
-    ) -> None:
+        roaming: bool = False,
+        multipath: bool = False,
+        opinion: bool = True,
+        ensure_exists: bool = False,
+    ):
         """
         Create a new platform directory.
 
@@ -35,47 +34,34 @@ def __init__(  # noqa: PLR0913, PLR0917
         :param multipath: See `multipath`.
         :param opinion: See `opinion`.
         :param ensure_exists: See `ensure_exists`.
-
         """
         self.appname = appname  #: The name of application.
         self.appauthor = appauthor
         """
-        The name of the app author or distributing body for this application.
-
-        Typically, it is the owning company name. Defaults to `appname`. You may pass ``False`` to disable it.
-
+        The name of the app author or distributing body for this application. Typically, it is the owning company name.
+        Defaults to `appname`. You may pass ``False`` to disable it.
         """
         self.version = version
         """
-        An optional version path element to append to the path.
-
-        You might want to use this if you want multiple versions of your app to be able to run independently. If used,
-        this would typically be ``.``.
-
+        An optional version path element to append to the path. You might want to use this if you want multiple versions
+        of your app to be able to run independently. If used, this would typically be ``.``.
         """
         self.roaming = roaming
         """
-        Whether to use the roaming appdata directory on Windows.
-
-        That means that for users on a Windows network setup for roaming profiles, this user data will be synced on
-        login (see
-        `here `_).
-
+        Whether to use the roaming appdata directory on Windows. That means that for users on a Windows network setup
+        for roaming profiles, this user data will be synced on login (see
+        `here `_).
         """
         self.multipath = multipath
         """
-        An optional parameter which indicates that the entire list of data dirs should be returned.
-
-        By default, the first item would only be returned.
-
+        An optional parameter only applicable to Unix/Linux which indicates that the entire list of data dirs should be
+        returned. By default, the first item would only be returned.
         """
         self.opinion = opinion  #: A flag to indicating to use opinionated values.
         self.ensure_exists = ensure_exists
         """
         Optionally create the directory (and any missing parents) upon access if it does not exist.
-
         By default, no directories are created.
-
         """
 
     def _append_app_name_and_version(self, *base: str) -> str:
@@ -84,7 +70,7 @@ def _append_app_name_and_version(self, *base: str) -> str:
             params.append(self.appname)
             if self.version:
                 params.append(self.version)
-        path = os.path.join(base[0], *params)  # noqa: PTH118
+        path = os.path.join(base[0], *params)
         self._optionally_create_directory(path)
         return path
 
@@ -92,12 +78,6 @@ def _optionally_create_directory(self, path: str) -> None:
         if self.ensure_exists:
             Path(path).mkdir(parents=True, exist_ok=True)
 
-    def _first_item_as_path_if_multipath(self, directory: str) -> Path:
-        if self.multipath:
-            # If multipath is True, the first path is returned.
-            directory = directory.partition(os.pathsep)[0]
-        return Path(directory)
-
     @property
     @abstractmethod
     def user_data_dir(self) -> str:
@@ -143,41 +123,11 @@ def user_log_dir(self) -> str:
     def user_documents_dir(self) -> str:
         """:return: documents directory tied to the user"""
 
-    @property
-    @abstractmethod
-    def user_downloads_dir(self) -> str:
-        """:return: downloads directory tied to the user"""
-
-    @property
-    @abstractmethod
-    def user_pictures_dir(self) -> str:
-        """:return: pictures directory tied to the user"""
-
-    @property
-    @abstractmethod
-    def user_videos_dir(self) -> str:
-        """:return: videos directory tied to the user"""
-
-    @property
-    @abstractmethod
-    def user_music_dir(self) -> str:
-        """:return: music directory tied to the user"""
-
-    @property
-    @abstractmethod
-    def user_desktop_dir(self) -> str:
-        """:return: desktop directory tied to the user"""
-
     @property
     @abstractmethod
     def user_runtime_dir(self) -> str:
         """:return: runtime directory tied to the user"""
 
-    @property
-    @abstractmethod
-    def site_runtime_dir(self) -> str:
-        """:return: runtime directory shared by users"""
-
     @property
     def user_data_path(self) -> Path:
         """:return: data path tied to the user"""
@@ -220,80 +170,10 @@ def user_log_path(self) -> Path:
 
     @property
     def user_documents_path(self) -> Path:
-        """:return: documents a path tied to the user"""
+        """:return: documents path tied to the user"""
         return Path(self.user_documents_dir)
 
-    @property
-    def user_downloads_path(self) -> Path:
-        """:return: downloads path tied to the user"""
-        return Path(self.user_downloads_dir)
-
-    @property
-    def user_pictures_path(self) -> Path:
-        """:return: pictures path tied to the user"""
-        return Path(self.user_pictures_dir)
-
-    @property
-    def user_videos_path(self) -> Path:
-        """:return: videos path tied to the user"""
-        return Path(self.user_videos_dir)
-
-    @property
-    def user_music_path(self) -> Path:
-        """:return: music path tied to the user"""
-        return Path(self.user_music_dir)
-
-    @property
-    def user_desktop_path(self) -> Path:
-        """:return: desktop path tied to the user"""
-        return Path(self.user_desktop_dir)
-
     @property
     def user_runtime_path(self) -> Path:
         """:return: runtime path tied to the user"""
         return Path(self.user_runtime_dir)
-
-    @property
-    def site_runtime_path(self) -> Path:
-        """:return: runtime path shared by users"""
-        return Path(self.site_runtime_dir)
-
-    def iter_config_dirs(self) -> Iterator[str]:
-        """:yield: all user and site configuration directories."""
-        yield self.user_config_dir
-        yield self.site_config_dir
-
-    def iter_data_dirs(self) -> Iterator[str]:
-        """:yield: all user and site data directories."""
-        yield self.user_data_dir
-        yield self.site_data_dir
-
-    def iter_cache_dirs(self) -> Iterator[str]:
-        """:yield: all user and site cache directories."""
-        yield self.user_cache_dir
-        yield self.site_cache_dir
-
-    def iter_runtime_dirs(self) -> Iterator[str]:
-        """:yield: all user and site runtime directories."""
-        yield self.user_runtime_dir
-        yield self.site_runtime_dir
-
-    def iter_config_paths(self) -> Iterator[Path]:
-        """:yield: all user and site configuration paths."""
-        for path in self.iter_config_dirs():
-            yield Path(path)
-
-    def iter_data_paths(self) -> Iterator[Path]:
-        """:yield: all user and site data paths."""
-        for path in self.iter_data_dirs():
-            yield Path(path)
-
-    def iter_cache_paths(self) -> Iterator[Path]:
-        """:yield: all user and site cache paths."""
-        for path in self.iter_cache_dirs():
-            yield Path(path)
-
-    def iter_runtime_paths(self) -> Iterator[Path]:
-        """:yield: all user and site runtime paths."""
-        for path in self.iter_runtime_dirs():
-            yield Path(path)
diff --git a/venv1/Lib/site-packages/pip/_vendor/platformdirs/macos.py b/venv1/Lib/site-packages/pip/_vendor/platformdirs/macos.py
index 30ab3689..ec975112 100644
--- a/venv1/Lib/site-packages/pip/_vendor/platformdirs/macos.py
+++ b/venv1/Lib/site-packages/pip/_vendor/platformdirs/macos.py
@@ -1,56 +1,28 @@
-"""macOS."""
-
 from __future__ import annotations
 
-import os.path
-import sys
-from typing import TYPE_CHECKING
+import os
 
 from .api import PlatformDirsABC
 
-if TYPE_CHECKING:
-    from pathlib import Path
-
 
 class MacOS(PlatformDirsABC):
     """
-    Platform directories for the macOS operating system.
-
-    Follows the guidance from
-    `Apple documentation `_.
+    Platform directories for the macOS operating system. Follows the guidance from `Apple documentation
+    `_.
     Makes use of the `appname `,
     `version `,
     `ensure_exists `.
-
     """
 
     @property
     def user_data_dir(self) -> str:
         """:return: data directory tied to the user, e.g. ``~/Library/Application Support/$appname/$version``"""
-        return self._append_app_name_and_version(os.path.expanduser("~/Library/Application Support"))  # noqa: PTH111
+        return self._append_app_name_and_version(os.path.expanduser("~/Library/Application Support"))
 
     @property
     def site_data_dir(self) -> str:
-        """
-        :return: data directory shared by users, e.g. ``/Library/Application Support/$appname/$version``.
-          If we're using a Python binary managed by `Homebrew `_, the directory
-          will be under the Homebrew prefix, e.g. ``$homebrew_prefix/share/$appname/$version``.
-          If `multipath ` is enabled, and we're in Homebrew,
-          the response is a multi-path string separated by ":", e.g.
-          ``$homebrew_prefix/share/$appname/$version:/Library/Application Support/$appname/$version``
-        """
-        is_homebrew = "/opt/python" in sys.prefix
-        homebrew_prefix = sys.prefix.split("/opt/python")[0] if is_homebrew else ""
-        path_list = [self._append_app_name_and_version(f"{homebrew_prefix}/share")] if is_homebrew else []
-        path_list.append(self._append_app_name_and_version("/Library/Application Support"))
-        if self.multipath:
-            return os.pathsep.join(path_list)
-        return path_list[0]
-
-    @property
-    def site_data_path(self) -> Path:
-        """:return: data path shared by users. Only return the first item, even if ``multipath`` is set to ``True``"""
-        return self._first_item_as_path_if_multipath(self.site_data_dir)
+        """:return: data directory shared by users, e.g. ``/Library/Application Support/$appname/$version``"""
+        return self._append_app_name_and_version("/Library/Application Support")
 
     @property
     def user_config_dir(self) -> str:
@@ -65,30 +37,12 @@ def site_config_dir(self) -> str:
     @property
     def user_cache_dir(self) -> str:
         """:return: cache directory tied to the user, e.g. ``~/Library/Caches/$appname/$version``"""
-        return self._append_app_name_and_version(os.path.expanduser("~/Library/Caches"))  # noqa: PTH111
+        return self._append_app_name_and_version(os.path.expanduser("~/Library/Caches"))
 
     @property
     def site_cache_dir(self) -> str:
-        """
-        :return: cache directory shared by users, e.g. ``/Library/Caches/$appname/$version``.
-          If we're using a Python binary managed by `Homebrew `_, the directory
-          will be under the Homebrew prefix, e.g. ``$homebrew_prefix/var/cache/$appname/$version``.
-          If `multipath ` is enabled, and we're in Homebrew,
-          the response is a multi-path string separated by ":", e.g.
-          ``$homebrew_prefix/var/cache/$appname/$version:/Library/Caches/$appname/$version``
-        """
-        is_homebrew = "/opt/python" in sys.prefix
-        homebrew_prefix = sys.prefix.split("/opt/python")[0] if is_homebrew else ""
-        path_list = [self._append_app_name_and_version(f"{homebrew_prefix}/var/cache")] if is_homebrew else []
-        path_list.append(self._append_app_name_and_version("/Library/Caches"))
-        if self.multipath:
-            return os.pathsep.join(path_list)
-        return path_list[0]
-
-    @property
-    def site_cache_path(self) -> Path:
-        """:return: cache path shared by users. Only return the first item, even if ``multipath`` is set to ``True``"""
-        return self._first_item_as_path_if_multipath(self.site_cache_dir)
+        """:return: cache directory shared by users, e.g. ``/Library/Caches/$appname/$version``"""
+        return self._append_app_name_and_version("/Library/Caches")
 
     @property
     def user_state_dir(self) -> str:
@@ -98,47 +52,17 @@ def user_state_dir(self) -> str:
     @property
     def user_log_dir(self) -> str:
         """:return: log directory tied to the user, e.g. ``~/Library/Logs/$appname/$version``"""
-        return self._append_app_name_and_version(os.path.expanduser("~/Library/Logs"))  # noqa: PTH111
+        return self._append_app_name_and_version(os.path.expanduser("~/Library/Logs"))
 
     @property
     def user_documents_dir(self) -> str:
         """:return: documents directory tied to the user, e.g. ``~/Documents``"""
-        return os.path.expanduser("~/Documents")  # noqa: PTH111
-
-    @property
-    def user_downloads_dir(self) -> str:
-        """:return: downloads directory tied to the user, e.g. ``~/Downloads``"""
-        return os.path.expanduser("~/Downloads")  # noqa: PTH111
-
-    @property
-    def user_pictures_dir(self) -> str:
-        """:return: pictures directory tied to the user, e.g. ``~/Pictures``"""
-        return os.path.expanduser("~/Pictures")  # noqa: PTH111
-
-    @property
-    def user_videos_dir(self) -> str:
-        """:return: videos directory tied to the user, e.g. ``~/Movies``"""
-        return os.path.expanduser("~/Movies")  # noqa: PTH111
-
-    @property
-    def user_music_dir(self) -> str:
-        """:return: music directory tied to the user, e.g. ``~/Music``"""
-        return os.path.expanduser("~/Music")  # noqa: PTH111
-
-    @property
-    def user_desktop_dir(self) -> str:
-        """:return: desktop directory tied to the user, e.g. ``~/Desktop``"""
-        return os.path.expanduser("~/Desktop")  # noqa: PTH111
+        return os.path.expanduser("~/Documents")
 
     @property
     def user_runtime_dir(self) -> str:
         """:return: runtime directory tied to the user, e.g. ``~/Library/Caches/TemporaryItems/$appname/$version``"""
-        return self._append_app_name_and_version(os.path.expanduser("~/Library/Caches/TemporaryItems"))  # noqa: PTH111
-
-    @property
-    def site_runtime_dir(self) -> str:
-        """:return: runtime directory shared by users, same as `user_runtime_dir`"""
-        return self.user_runtime_dir
+        return self._append_app_name_and_version(os.path.expanduser("~/Library/Caches/TemporaryItems"))
 
 
 __all__ = [
diff --git a/venv1/Lib/site-packages/pip/_vendor/platformdirs/py.typed b/venv1/Lib/site-packages/pip/_vendor/platformdirs/py.typed
deleted file mode 100644
index e69de29b..00000000
diff --git a/venv1/Lib/site-packages/pip/_vendor/platformdirs/unix.py b/venv1/Lib/site-packages/pip/_vendor/platformdirs/unix.py
index fc75d8d0..17d355da 100644
--- a/venv1/Lib/site-packages/pip/_vendor/platformdirs/unix.py
+++ b/venv1/Lib/site-packages/pip/_vendor/platformdirs/unix.py
@@ -1,39 +1,31 @@
-"""Unix."""
-
 from __future__ import annotations
 
 import os
 import sys
 from configparser import ConfigParser
 from pathlib import Path
-from typing import TYPE_CHECKING, NoReturn
 
 from .api import PlatformDirsABC
 
-if TYPE_CHECKING:
-    from collections.abc import Iterator
-
-if sys.platform == "win32":
-
-    def getuid() -> NoReturn:
-        msg = "should only be used on Unix"
-        raise RuntimeError(msg)
-
-else:
+if sys.platform.startswith("linux"):  # pragma: no branch # no op check, only to please the type checker
     from os import getuid
+else:
 
+    def getuid() -> int:
+        raise RuntimeError("should only be used on Linux")
 
-class Unix(PlatformDirsABC):  # noqa: PLR0904
-    """
-    On Unix/Linux, we follow the `XDG Basedir Spec `_.
-
-    The spec allows overriding directories with environment variables. The examples shown are the default values,
-    alongside the name of the environment variable that overrides them. Makes use of the `appname
-    `, `version `, `multipath
-    `, `opinion `, `ensure_exists
-    `.
 
+class Unix(PlatformDirsABC):
+    """
+    On Unix/Linux, we follow the
+    `XDG Basedir Spec `_. The spec allows
+    overriding directories with environment variables. The examples show are the default values, alongside the name of
+    the environment variable that overrides them. Makes use of the
+    `appname `,
+    `version `,
+    `multipath `,
+    `opinion `,
+    `ensure_exists `.
     """
 
     @property
@@ -44,28 +36,28 @@ def user_data_dir(self) -> str:
         """
         path = os.environ.get("XDG_DATA_HOME", "")
         if not path.strip():
-            path = os.path.expanduser("~/.local/share")  # noqa: PTH111
+            path = os.path.expanduser("~/.local/share")
         return self._append_app_name_and_version(path)
 
-    @property
-    def _site_data_dirs(self) -> list[str]:
-        path = os.environ.get("XDG_DATA_DIRS", "")
-        if not path.strip():
-            path = f"/usr/local/share{os.pathsep}/usr/share"
-        return [self._append_app_name_and_version(p) for p in path.split(os.pathsep)]
-
     @property
     def site_data_dir(self) -> str:
         """
         :return: data directories shared by users (if `multipath ` is
-         enabled and ``XDG_DATA_DIRS`` is set and a multi path the response is also a multi path separated by the
-         OS path separator), e.g. ``/usr/local/share/$appname/$version`` or ``/usr/share/$appname/$version``
+         enabled and ``XDG_DATA_DIR`` is set and a multi path the response is also a multi path separated by the OS
+         path separator), e.g. ``/usr/local/share/$appname/$version`` or ``/usr/share/$appname/$version``
         """
         # XDG default for $XDG_DATA_DIRS; only first, if multipath is False
-        dirs = self._site_data_dirs
+        path = os.environ.get("XDG_DATA_DIRS", "")
+        if not path.strip():
+            path = f"/usr/local/share{os.pathsep}/usr/share"
+        return self._with_multi_path(path)
+
+    def _with_multi_path(self, path: str) -> str:
+        path_list = path.split(os.pathsep)
         if not self.multipath:
-            return dirs[0]
-        return os.pathsep.join(dirs)
+            path_list = path_list[0:1]
+        path_list = [self._append_app_name_and_version(os.path.expanduser(p)) for p in path_list]
+        return os.pathsep.join(path_list)
 
     @property
     def user_config_dir(self) -> str:
@@ -75,28 +67,21 @@ def user_config_dir(self) -> str:
         """
         path = os.environ.get("XDG_CONFIG_HOME", "")
         if not path.strip():
-            path = os.path.expanduser("~/.config")  # noqa: PTH111
+            path = os.path.expanduser("~/.config")
         return self._append_app_name_and_version(path)
 
-    @property
-    def _site_config_dirs(self) -> list[str]:
-        path = os.environ.get("XDG_CONFIG_DIRS", "")
-        if not path.strip():
-            path = "/etc/xdg"
-        return [self._append_app_name_and_version(p) for p in path.split(os.pathsep)]
-
     @property
     def site_config_dir(self) -> str:
         """
         :return: config directories shared by users (if `multipath `
-         is enabled and ``XDG_CONFIG_DIRS`` is set and a multi path the response is also a multi path separated by
-         the OS path separator), e.g. ``/etc/xdg/$appname/$version``
+         is enabled and ``XDG_DATA_DIR`` is set and a multi path the response is also a multi path separated by the OS
+         path separator), e.g. ``/etc/xdg/$appname/$version``
         """
         # XDG default for $XDG_CONFIG_DIRS only first, if multipath is False
-        dirs = self._site_config_dirs
-        if not self.multipath:
-            return dirs[0]
-        return os.pathsep.join(dirs)
+        path = os.environ.get("XDG_CONFIG_DIRS", "")
+        if not path.strip():
+            path = "/etc/xdg"
+        return self._with_multi_path(path)
 
     @property
     def user_cache_dir(self) -> str:
@@ -106,13 +91,15 @@ def user_cache_dir(self) -> str:
         """
         path = os.environ.get("XDG_CACHE_HOME", "")
         if not path.strip():
-            path = os.path.expanduser("~/.cache")  # noqa: PTH111
+            path = os.path.expanduser("~/.cache")
         return self._append_app_name_and_version(path)
 
     @property
     def site_cache_dir(self) -> str:
-        """:return: cache directory shared by users, e.g. ``/var/cache/$appname/$version``"""
-        return self._append_app_name_and_version("/var/cache")
+        """
+        :return: cache directory shared by users, e.g. ``/var/tmp/$appname/$version``
+        """
+        return self._append_app_name_and_version("/var/tmp")
 
     @property
     def user_state_dir(self) -> str:
@@ -122,138 +109,72 @@ def user_state_dir(self) -> str:
         """
         path = os.environ.get("XDG_STATE_HOME", "")
         if not path.strip():
-            path = os.path.expanduser("~/.local/state")  # noqa: PTH111
+            path = os.path.expanduser("~/.local/state")
         return self._append_app_name_and_version(path)
 
     @property
     def user_log_dir(self) -> str:
-        """:return: log directory tied to the user, same as `user_state_dir` if not opinionated else ``log`` in it"""
+        """
+        :return: log directory tied to the user, same as `user_state_dir` if not opinionated else ``log`` in it
+        """
         path = self.user_state_dir
         if self.opinion:
-            path = os.path.join(path, "log")  # noqa: PTH118
-            self._optionally_create_directory(path)
+            path = os.path.join(path, "log")
         return path
 
     @property
     def user_documents_dir(self) -> str:
-        """:return: documents directory tied to the user, e.g. ``~/Documents``"""
-        return _get_user_media_dir("XDG_DOCUMENTS_DIR", "~/Documents")
-
-    @property
-    def user_downloads_dir(self) -> str:
-        """:return: downloads directory tied to the user, e.g. ``~/Downloads``"""
-        return _get_user_media_dir("XDG_DOWNLOAD_DIR", "~/Downloads")
-
-    @property
-    def user_pictures_dir(self) -> str:
-        """:return: pictures directory tied to the user, e.g. ``~/Pictures``"""
-        return _get_user_media_dir("XDG_PICTURES_DIR", "~/Pictures")
-
-    @property
-    def user_videos_dir(self) -> str:
-        """:return: videos directory tied to the user, e.g. ``~/Videos``"""
-        return _get_user_media_dir("XDG_VIDEOS_DIR", "~/Videos")
-
-    @property
-    def user_music_dir(self) -> str:
-        """:return: music directory tied to the user, e.g. ``~/Music``"""
-        return _get_user_media_dir("XDG_MUSIC_DIR", "~/Music")
+        """
+        :return: documents directory tied to the user, e.g. ``~/Documents``
+        """
+        documents_dir = _get_user_dirs_folder("XDG_DOCUMENTS_DIR")
+        if documents_dir is None:
+            documents_dir = os.environ.get("XDG_DOCUMENTS_DIR", "").strip()
+            if not documents_dir:
+                documents_dir = os.path.expanduser("~/Documents")
 
-    @property
-    def user_desktop_dir(self) -> str:
-        """:return: desktop directory tied to the user, e.g. ``~/Desktop``"""
-        return _get_user_media_dir("XDG_DESKTOP_DIR", "~/Desktop")
+        return documents_dir
 
     @property
     def user_runtime_dir(self) -> str:
         """
         :return: runtime directory tied to the user, e.g. ``/run/user/$(id -u)/$appname/$version`` or
-         ``$XDG_RUNTIME_DIR/$appname/$version``.
-
-         For FreeBSD/OpenBSD/NetBSD, it would return ``/var/run/user/$(id -u)/$appname/$version`` if
-         exists, otherwise ``/tmp/runtime-$(id -u)/$appname/$version``, if``$XDG_RUNTIME_DIR``
-         is not set.
+         ``$XDG_RUNTIME_DIR/$appname/$version``
         """
         path = os.environ.get("XDG_RUNTIME_DIR", "")
         if not path.strip():
-            if sys.platform.startswith(("freebsd", "openbsd", "netbsd")):
-                path = f"/var/run/user/{getuid()}"
-                if not Path(path).exists():
-                    path = f"/tmp/runtime-{getuid()}"  # noqa: S108
-            else:
-                path = f"/run/user/{getuid()}"
-        return self._append_app_name_and_version(path)
-
-    @property
-    def site_runtime_dir(self) -> str:
-        """
-        :return: runtime directory shared by users, e.g. ``/run/$appname/$version`` or \
-        ``$XDG_RUNTIME_DIR/$appname/$version``.
-
-        Note that this behaves almost exactly like `user_runtime_dir` if ``$XDG_RUNTIME_DIR`` is set, but will
-        fall back to paths associated to the root user instead of a regular logged-in user if it's not set.
-
-        If you wish to ensure that a logged-in root user path is returned e.g. ``/run/user/0``, use `user_runtime_dir`
-        instead.
-
-        For FreeBSD/OpenBSD/NetBSD, it would return ``/var/run/$appname/$version`` if ``$XDG_RUNTIME_DIR`` is not set.
-        """
-        path = os.environ.get("XDG_RUNTIME_DIR", "")
-        if not path.strip():
-            if sys.platform.startswith(("freebsd", "openbsd", "netbsd")):
-                path = "/var/run"
-            else:
-                path = "/run"
+            path = f"/run/user/{getuid()}"
         return self._append_app_name_and_version(path)
 
     @property
     def site_data_path(self) -> Path:
-        """:return: data path shared by users. Only return the first item, even if ``multipath`` is set to ``True``"""
+        """:return: data path shared by users. Only return first item, even if ``multipath`` is set to ``True``"""
         return self._first_item_as_path_if_multipath(self.site_data_dir)
 
     @property
     def site_config_path(self) -> Path:
-        """:return: config path shared by the users, returns the first item, even if ``multipath`` is set to ``True``"""
+        """:return: config path shared by the users. Only return first item, even if ``multipath`` is set to ``True``"""
         return self._first_item_as_path_if_multipath(self.site_config_dir)
 
     @property
     def site_cache_path(self) -> Path:
-        """:return: cache path shared by users. Only return the first item, even if ``multipath`` is set to ``True``"""
+        """:return: cache path shared by users. Only return first item, even if ``multipath`` is set to ``True``"""
         return self._first_item_as_path_if_multipath(self.site_cache_dir)
 
-    def iter_config_dirs(self) -> Iterator[str]:
-        """:yield: all user and site configuration directories."""
-        yield self.user_config_dir
-        yield from self._site_config_dirs
-
-    def iter_data_dirs(self) -> Iterator[str]:
-        """:yield: all user and site data directories."""
-        yield self.user_data_dir
-        yield from self._site_data_dirs
-
-
-def _get_user_media_dir(env_var: str, fallback_tilde_path: str) -> str:
-    media_dir = _get_user_dirs_folder(env_var)
-    if media_dir is None:
-        media_dir = os.environ.get(env_var, "").strip()
-        if not media_dir:
-            media_dir = os.path.expanduser(fallback_tilde_path)  # noqa: PTH111
-
-    return media_dir
+    def _first_item_as_path_if_multipath(self, directory: str) -> Path:
+        if self.multipath:
+            # If multipath is True, the first path is returned.
+            directory = directory.split(os.pathsep)[0]
+        return Path(directory)
 
 
 def _get_user_dirs_folder(key: str) -> str | None:
-    """
-    Return directory from user-dirs.dirs config file.
-
-    See https://freedesktop.org/wiki/Software/xdg-user-dirs/.
-
-    """
-    user_dirs_config_path = Path(Unix().user_config_dir) / "user-dirs.dirs"
-    if user_dirs_config_path.exists():
+    """Return directory from user-dirs.dirs config file. See https://freedesktop.org/wiki/Software/xdg-user-dirs/"""
+    user_dirs_config_path = os.path.join(Unix().user_config_dir, "user-dirs.dirs")
+    if os.path.exists(user_dirs_config_path):
         parser = ConfigParser()
 
-        with user_dirs_config_path.open() as stream:
+        with open(user_dirs_config_path) as stream:
             # Add fake section header, so ConfigParser doesn't complain
             parser.read_string(f"[top]\n{stream.read()}")
 
@@ -262,7 +183,8 @@ def _get_user_dirs_folder(key: str) -> str | None:
 
         path = parser["top"][key].strip('"')
         # Handle relative home paths
-        return path.replace("$HOME", os.path.expanduser("~"))  # noqa: PTH111
+        path = path.replace("$HOME", os.path.expanduser("~"))
+        return path
 
     return None
 
diff --git a/venv1/Lib/site-packages/pip/_vendor/platformdirs/version.py b/venv1/Lib/site-packages/pip/_vendor/platformdirs/version.py
index 35752825..d906a2c9 100644
--- a/venv1/Lib/site-packages/pip/_vendor/platformdirs/version.py
+++ b/venv1/Lib/site-packages/pip/_vendor/platformdirs/version.py
@@ -1,34 +1,4 @@
-# file generated by setuptools-scm
+# file generated by setuptools_scm
 # don't change, don't track in version control
-
-__all__ = [
-    "__version__",
-    "__version_tuple__",
-    "version",
-    "version_tuple",
-    "__commit_id__",
-    "commit_id",
-]
-
-TYPE_CHECKING = False
-if TYPE_CHECKING:
-    from typing import Tuple
-    from typing import Union
-
-    VERSION_TUPLE = Tuple[Union[int, str], ...]
-    COMMIT_ID = Union[str, None]
-else:
-    VERSION_TUPLE = object
-    COMMIT_ID = object
-
-version: str
-__version__: str
-__version_tuple__: VERSION_TUPLE
-version_tuple: VERSION_TUPLE
-commit_id: COMMIT_ID
-__commit_id__: COMMIT_ID
-
-__version__ = version = '4.5.0'
-__version_tuple__ = version_tuple = (4, 5, 0)
-
-__commit_id__ = commit_id = None
+__version__ = version = '3.2.0'
+__version_tuple__ = version_tuple = (3, 2, 0)
diff --git a/venv1/Lib/site-packages/pip/_vendor/platformdirs/windows.py b/venv1/Lib/site-packages/pip/_vendor/platformdirs/windows.py
index d7bc9609..e7573c3d 100644
--- a/venv1/Lib/site-packages/pip/_vendor/platformdirs/windows.py
+++ b/venv1/Lib/site-packages/pip/_vendor/platformdirs/windows.py
@@ -1,27 +1,24 @@
-"""Windows."""
-
 from __future__ import annotations
 
+import ctypes
 import os
 import sys
 from functools import lru_cache
-from typing import TYPE_CHECKING
+from typing import Callable
 
 from .api import PlatformDirsABC
 
-if TYPE_CHECKING:
-    from collections.abc import Callable
-
 
 class Windows(PlatformDirsABC):
-    """
-    `MSDN on where to store app data files `_.
-
-    Makes use of the `appname `, `appauthor
-    `, `version `, `roaming
-    `, `opinion `, `ensure_exists
-    `.
-
+    """`MSDN on where to store app data files
+    `_.
+    Makes use of the
+    `appname `,
+    `appauthor `,
+    `version `,
+    `roaming `,
+    `opinion `,
+    `ensure_exists `.
     """
 
     @property
@@ -46,7 +43,7 @@ def _append_parts(self, path: str, *, opinion_value: str | None = None) -> str:
                 params.append(opinion_value)
             if self.version:
                 params.append(self.version)
-        path = os.path.join(path, *params)  # noqa: PTH118
+        path = os.path.join(path, *params)
         self._optionally_create_directory(path)
         return path
 
@@ -88,63 +85,36 @@ def user_state_dir(self) -> str:
 
     @property
     def user_log_dir(self) -> str:
-        """:return: log directory tied to the user, same as `user_data_dir` if not opinionated else ``Logs`` in it"""
+        """
+        :return: log directory tied to the user, same as `user_data_dir` if not opinionated else ``Logs`` in it
+        """
         path = self.user_data_dir
         if self.opinion:
-            path = os.path.join(path, "Logs")  # noqa: PTH118
+            path = os.path.join(path, "Logs")
             self._optionally_create_directory(path)
         return path
 
     @property
     def user_documents_dir(self) -> str:
-        """:return: documents directory tied to the user e.g. ``%USERPROFILE%\\Documents``"""
+        """
+        :return: documents directory tied to the user e.g. ``%USERPROFILE%\\Documents``
+        """
         return os.path.normpath(get_win_folder("CSIDL_PERSONAL"))
 
-    @property
-    def user_downloads_dir(self) -> str:
-        """:return: downloads directory tied to the user e.g. ``%USERPROFILE%\\Downloads``"""
-        return os.path.normpath(get_win_folder("CSIDL_DOWNLOADS"))
-
-    @property
-    def user_pictures_dir(self) -> str:
-        """:return: pictures directory tied to the user e.g. ``%USERPROFILE%\\Pictures``"""
-        return os.path.normpath(get_win_folder("CSIDL_MYPICTURES"))
-
-    @property
-    def user_videos_dir(self) -> str:
-        """:return: videos directory tied to the user e.g. ``%USERPROFILE%\\Videos``"""
-        return os.path.normpath(get_win_folder("CSIDL_MYVIDEO"))
-
-    @property
-    def user_music_dir(self) -> str:
-        """:return: music directory tied to the user e.g. ``%USERPROFILE%\\Music``"""
-        return os.path.normpath(get_win_folder("CSIDL_MYMUSIC"))
-
-    @property
-    def user_desktop_dir(self) -> str:
-        """:return: desktop directory tied to the user, e.g. ``%USERPROFILE%\\Desktop``"""
-        return os.path.normpath(get_win_folder("CSIDL_DESKTOPDIRECTORY"))
-
     @property
     def user_runtime_dir(self) -> str:
         """
         :return: runtime directory tied to the user, e.g.
          ``%USERPROFILE%\\AppData\\Local\\Temp\\$appauthor\\$appname``
         """
-        path = os.path.normpath(os.path.join(get_win_folder("CSIDL_LOCAL_APPDATA"), "Temp"))  # noqa: PTH118
+        path = os.path.normpath(os.path.join(get_win_folder("CSIDL_LOCAL_APPDATA"), "Temp"))
         return self._append_parts(path)
 
-    @property
-    def site_runtime_dir(self) -> str:
-        """:return: runtime directory shared by users, same as `user_runtime_dir`"""
-        return self.user_runtime_dir
-
 
 def get_win_folder_from_env_vars(csidl_name: str) -> str:
     """Get folder from environment variables."""
-    result = get_win_folder_if_csidl_name_not_env_var(csidl_name)
-    if result is not None:
-        return result
+    if csidl_name == "CSIDL_PERSONAL":  # does not have an environment name
+        return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Documents")
 
     env_var_name = {
         "CSIDL_APPDATA": "APPDATA",
@@ -152,58 +122,31 @@ def get_win_folder_from_env_vars(csidl_name: str) -> str:
         "CSIDL_LOCAL_APPDATA": "LOCALAPPDATA",
     }.get(csidl_name)
     if env_var_name is None:
-        msg = f"Unknown CSIDL name: {csidl_name}"
-        raise ValueError(msg)
+        raise ValueError(f"Unknown CSIDL name: {csidl_name}")
     result = os.environ.get(env_var_name)
     if result is None:
-        msg = f"Unset environment variable: {env_var_name}"
-        raise ValueError(msg)
+        raise ValueError(f"Unset environment variable: {env_var_name}")
     return result
 
 
-def get_win_folder_if_csidl_name_not_env_var(csidl_name: str) -> str | None:
-    """Get a folder for a CSIDL name that does not exist as an environment variable."""
-    if csidl_name == "CSIDL_PERSONAL":
-        return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Documents")  # noqa: PTH118
-
-    if csidl_name == "CSIDL_DOWNLOADS":
-        return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Downloads")  # noqa: PTH118
-
-    if csidl_name == "CSIDL_MYPICTURES":
-        return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Pictures")  # noqa: PTH118
-
-    if csidl_name == "CSIDL_MYVIDEO":
-        return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Videos")  # noqa: PTH118
-
-    if csidl_name == "CSIDL_MYMUSIC":
-        return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Music")  # noqa: PTH118
-    return None
-
-
 def get_win_folder_from_registry(csidl_name: str) -> str:
-    """
-    Get folder from the registry.
-
-    This is a fallback technique at best. I'm not sure if using the registry for these guarantees us the correct answer
-    for all CSIDL_* names.
+    """Get folder from the registry.
 
+    This is a fallback technique at best. I'm not sure if using the
+    registry for this guarantees us the correct answer for all CSIDL_*
+    names.
     """
     shell_folder_name = {
         "CSIDL_APPDATA": "AppData",
         "CSIDL_COMMON_APPDATA": "Common AppData",
         "CSIDL_LOCAL_APPDATA": "Local AppData",
         "CSIDL_PERSONAL": "Personal",
-        "CSIDL_DOWNLOADS": "{374DE290-123F-4565-9164-39C4925E467B}",
-        "CSIDL_MYPICTURES": "My Pictures",
-        "CSIDL_MYVIDEO": "My Video",
-        "CSIDL_MYMUSIC": "My Music",
     }.get(csidl_name)
     if shell_folder_name is None:
-        msg = f"Unknown CSIDL name: {csidl_name}"
-        raise ValueError(msg)
+        raise ValueError(f"Unknown CSIDL name: {csidl_name}")
     if sys.platform != "win32":  # only needed for mypy type checker to know that this code runs only on Windows
         raise NotImplementedError
-    import winreg  # noqa: PLC0415
+    import winreg
 
     key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders")
     directory, _ = winreg.QueryValueEx(key, shell_folder_name)
@@ -212,53 +155,33 @@ def get_win_folder_from_registry(csidl_name: str) -> str:
 
 def get_win_folder_via_ctypes(csidl_name: str) -> str:
     """Get folder with ctypes."""
-    # There is no 'CSIDL_DOWNLOADS'.
-    # Use 'CSIDL_PROFILE' (40) and append the default folder 'Downloads' instead.
-    # https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid
-
-    import ctypes  # noqa: PLC0415
-
     csidl_const = {
         "CSIDL_APPDATA": 26,
         "CSIDL_COMMON_APPDATA": 35,
         "CSIDL_LOCAL_APPDATA": 28,
         "CSIDL_PERSONAL": 5,
-        "CSIDL_MYPICTURES": 39,
-        "CSIDL_MYVIDEO": 14,
-        "CSIDL_MYMUSIC": 13,
-        "CSIDL_DOWNLOADS": 40,
-        "CSIDL_DESKTOPDIRECTORY": 16,
     }.get(csidl_name)
     if csidl_const is None:
-        msg = f"Unknown CSIDL name: {csidl_name}"
-        raise ValueError(msg)
+        raise ValueError(f"Unknown CSIDL name: {csidl_name}")
 
     buf = ctypes.create_unicode_buffer(1024)
     windll = getattr(ctypes, "windll")  # noqa: B009 # using getattr to avoid false positive with mypy type checker
     windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf)
 
-    # Downgrade to short path name if it has high-bit chars.
-    if any(ord(c) > 255 for c in buf):  # noqa: PLR2004
+    # Downgrade to short path name if it has highbit chars.
+    if any(ord(c) > 255 for c in buf):
         buf2 = ctypes.create_unicode_buffer(1024)
         if windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024):
             buf = buf2
 
-    if csidl_name == "CSIDL_DOWNLOADS":
-        return os.path.join(buf.value, "Downloads")  # noqa: PTH118
-
     return buf.value
 
 
 def _pick_get_win_folder() -> Callable[[str], str]:
+    if hasattr(ctypes, "windll"):
+        return get_win_folder_via_ctypes
     try:
-        import ctypes  # noqa: PLC0415
-    except ImportError:
-        pass
-    else:
-        if hasattr(ctypes, "windll"):
-            return get_win_folder_via_ctypes
-    try:
-        import winreg  # noqa: PLC0415, F401
+        import winreg  # noqa: F401
     except ImportError:
         return get_win_folder_from_env_vars
     else:
diff --git a/venv1/Lib/site-packages/pip/_vendor/pygments/__init__.py b/venv1/Lib/site-packages/pip/_vendor/pygments/__init__.py
index cb229c98..d9b0a8de 100644
--- a/venv1/Lib/site-packages/pip/_vendor/pygments/__init__.py
+++ b/venv1/Lib/site-packages/pip/_vendor/pygments/__init__.py
@@ -21,12 +21,12 @@
     .. _Pygments master branch:
        https://github.com/pygments/pygments/archive/master.zip#egg=Pygments-dev
 
-    :copyright: Copyright 2006-2025 by the Pygments team, see AUTHORS.
+    :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS.
     :license: BSD, see LICENSE for details.
 """
 from io import StringIO, BytesIO
 
-__version__ = '2.19.2'
+__version__ = '2.14.0'
 __docformat__ = 'restructuredtext'
 
 __all__ = ['lex', 'format', 'highlight']
@@ -34,9 +34,7 @@
 
 def lex(code, lexer):
     """
-    Lex `code` with the `lexer` (must be a `Lexer` instance)
-    and return an iterable of tokens. Currently, this only calls
-    `lexer.get_tokens()`.
+    Lex ``code`` with ``lexer`` and return an iterable of tokens.
     """
     try:
         return lexer.get_tokens(code)
@@ -51,12 +49,11 @@ def lex(code, lexer):
 
 def format(tokens, formatter, outfile=None):  # pylint: disable=redefined-builtin
     """
-    Format ``tokens`` (an iterable of tokens) with the formatter ``formatter``
-    (a `Formatter` instance).
+    Format a tokenlist ``tokens`` with the formatter ``formatter``.
 
-    If ``outfile`` is given and a valid file object (an object with a
-    ``write`` method), the result will be written to it, otherwise it
-    is returned as a string.
+    If ``outfile`` is given and a valid file object (an object
+    with a ``write`` method), the result will be written to it, otherwise
+    it is returned as a string.
     """
     try:
         if not outfile:
@@ -76,7 +73,10 @@ def format(tokens, formatter, outfile=None):  # pylint: disable=redefined-builti
 
 def highlight(code, lexer, formatter, outfile=None):
     """
-    This is the most high-level highlighting function. It combines `lex` and
-    `format` in one function.
+    Lex ``code`` with ``lexer`` and format it with the formatter ``formatter``.
+
+    If ``outfile`` is given and a valid file object (an object
+    with a ``write`` method), the result will be written to it, otherwise
+    it is returned as a string.
     """
     return format(lex(code, lexer), formatter, outfile)
diff --git a/venv1/Lib/site-packages/pip/_vendor/pygments/__main__.py b/venv1/Lib/site-packages/pip/_vendor/pygments/__main__.py
index a2e612f5..90cafd93 100644
--- a/venv1/Lib/site-packages/pip/_vendor/pygments/__main__.py
+++ b/venv1/Lib/site-packages/pip/_vendor/pygments/__main__.py
@@ -4,7 +4,7 @@
 
     Main entry point for ``python -m pygments``.
 
-    :copyright: Copyright 2006-2025 by the Pygments team, see AUTHORS.
+    :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS.
     :license: BSD, see LICENSE for details.
 """
 
diff --git a/venv1/Lib/site-packages/pip/_vendor/pygments/console.py b/venv1/Lib/site-packages/pip/_vendor/pygments/console.py
index ee1ac27a..2ada68e0 100644
--- a/venv1/Lib/site-packages/pip/_vendor/pygments/console.py
+++ b/venv1/Lib/site-packages/pip/_vendor/pygments/console.py
@@ -4,7 +4,7 @@
 
     Format colored console output.
 
-    :copyright: Copyright 2006-2025 by the Pygments team, see AUTHORS.
+    :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS.
     :license: BSD, see LICENSE for details.
 """
 
@@ -27,12 +27,12 @@
                 "brightmagenta", "brightcyan", "white"]
 
 x = 30
-for dark, light in zip(dark_colors, light_colors):
-    codes[dark] = esc + "%im" % x
-    codes[light] = esc + "%im" % (60 + x)
+for d, l in zip(dark_colors, light_colors):
+    codes[d] = esc + "%im" % x
+    codes[l] = esc + "%im" % (60 + x)
     x += 1
 
-del dark, light, x
+del d, l, x
 
 codes["white"] = codes["bold"]
 
diff --git a/venv1/Lib/site-packages/pip/_vendor/pygments/filter.py b/venv1/Lib/site-packages/pip/_vendor/pygments/filter.py
index 5efff438..e5c96649 100644
--- a/venv1/Lib/site-packages/pip/_vendor/pygments/filter.py
+++ b/venv1/Lib/site-packages/pip/_vendor/pygments/filter.py
@@ -4,7 +4,7 @@
 
     Module that implements the default filter.
 
-    :copyright: Copyright 2006-2025 by the Pygments team, see AUTHORS.
+    :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS.
     :license: BSD, see LICENSE for details.
 """
 
@@ -62,7 +62,8 @@ class FunctionFilter(Filter):
 
     def __init__(self, **options):
         if not hasattr(self, 'function'):
-            raise TypeError(f'{self.__class__.__name__!r} used without bound function')
+            raise TypeError('%r used without bound function' %
+                            self.__class__.__name__)
         Filter.__init__(self, **options)
 
     def filter(self, lexer, stream):
diff --git a/venv1/Lib/site-packages/pip/_vendor/pygments/filters/__init__.py b/venv1/Lib/site-packages/pip/_vendor/pygments/filters/__init__.py
index 97380c92..c302a6c0 100644
--- a/venv1/Lib/site-packages/pip/_vendor/pygments/filters/__init__.py
+++ b/venv1/Lib/site-packages/pip/_vendor/pygments/filters/__init__.py
@@ -5,7 +5,7 @@
     Module containing filter lookup functions and default
     filters.
 
-    :copyright: Copyright 2006-2025 by the Pygments team, see AUTHORS.
+    :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS.
     :license: BSD, see LICENSE for details.
 """
 
@@ -39,7 +39,7 @@ def get_filter_by_name(filtername, **options):
     if cls:
         return cls(**options)
     else:
-        raise ClassNotFound(f'filter {filtername!r} not found')
+        raise ClassNotFound('filter %r not found' % filtername)
 
 
 def get_all_filters():
@@ -79,9 +79,9 @@ def __init__(self, **options):
         Filter.__init__(self, **options)
         tags = get_list_opt(options, 'codetags',
                             ['XXX', 'TODO', 'FIXME', 'BUG', 'NOTE'])
-        self.tag_re = re.compile(r'\b({})\b'.format('|'.join([
+        self.tag_re = re.compile(r'\b(%s)\b' % '|'.join([
             re.escape(tag) for tag in tags if tag
-        ])))
+        ]))
 
     def filter(self, lexer, stream):
         regex = self.tag_re
diff --git a/venv1/Lib/site-packages/pip/_vendor/pygments/formatter.py b/venv1/Lib/site-packages/pip/_vendor/pygments/formatter.py
index 0041e41a..a2349ef8 100644
--- a/venv1/Lib/site-packages/pip/_vendor/pygments/formatter.py
+++ b/venv1/Lib/site-packages/pip/_vendor/pygments/formatter.py
@@ -4,7 +4,7 @@
 
     Base formatter class.
 
-    :copyright: Copyright 2006-2025 by the Pygments team, see AUTHORS.
+    :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS.
     :license: BSD, see LICENSE for details.
 """
 
@@ -26,21 +26,7 @@ class Formatter:
     """
     Converts a token stream to text.
 
-    Formatters should have attributes to help selecting them. These
-    are similar to the corresponding :class:`~pygments.lexer.Lexer`
-    attributes.
-
-    .. autoattribute:: name
-       :no-value:
-
-    .. autoattribute:: aliases
-       :no-value:
-
-    .. autoattribute:: filenames
-       :no-value:
-
-    You can pass options as keyword arguments to the constructor.
-    All formatters accept these basic options:
+    Options accepted:
 
     ``style``
         The style to use, can be a string or a Style subclass
@@ -61,19 +47,15 @@ class Formatter:
         support (default: None).
     ``outencoding``
         Overrides ``encoding`` if given.
-
     """
 
-    #: Full name for the formatter, in human-readable form.
+    #: Name of the formatter
     name = None
 
-    #: A list of short, unique identifiers that can be used to lookup
-    #: the formatter from a list, e.g. using :func:`.get_formatter_by_name()`.
+    #: Shortcuts for the formatter
     aliases = []
 
-    #: A list of fnmatch patterns that match filenames for which this
-    #: formatter can produce output. The patterns in this list should be unique
-    #: among all formatters.
+    #: fn match rules
     filenames = []
 
     #: If True, this formatter outputs Unicode strings when no encoding
@@ -81,11 +63,6 @@ class Formatter:
     unicodeoutput = True
 
     def __init__(self, **options):
-        """
-        As with lexers, this constructor takes arbitrary optional arguments,
-        and if you override it, you should first process your own options, then
-        call the base class implementation.
-        """
         self.style = _lookup_style(options.get('style', 'default'))
         self.full = get_bool_opt(options, 'full', False)
         self.title = options.get('title', '')
@@ -98,32 +75,20 @@ def __init__(self, **options):
 
     def get_style_defs(self, arg=''):
         """
-        This method must return statements or declarations suitable to define
-        the current style for subsequent highlighted text (e.g. CSS classes
-        in the `HTMLFormatter`).
-
-        The optional argument `arg` can be used to modify the generation and
-        is formatter dependent (it is standardized because it can be given on
-        the command line).
+        Return the style definitions for the current style as a string.
 
-        This method is called by the ``-S`` :doc:`command-line option `,
-        the `arg` is then given by the ``-a`` option.
+        ``arg`` is an additional argument whose meaning depends on the
+        formatter used. Note that ``arg`` can also be a list or tuple
+        for some formatters like the html formatter.
         """
         return ''
 
     def format(self, tokensource, outfile):
         """
-        This method must format the tokens from the `tokensource` iterable and
-        write the formatted version to the file object `outfile`.
-
-        Formatter options can control how exactly the tokens are converted.
+        Format ``tokensource``, an iterable of ``(tokentype, tokenstring)``
+        tuples and write it into ``outfile``.
         """
         if self.encoding:
             # wrap the outfile in a StreamWriter
             outfile = codecs.lookup(self.encoding)[3](outfile)
         return self.format_unencoded(tokensource, outfile)
-
-    # Allow writing Formatter[str] or Formatter[bytes]. That's equivalent to
-    # Formatter. This helps when using third-party type stubs from typeshed.
-    def __class_getitem__(cls, name):
-        return cls
diff --git a/venv1/Lib/site-packages/pip/_vendor/pygments/formatters/__init__.py b/venv1/Lib/site-packages/pip/_vendor/pygments/formatters/__init__.py
index 014f2ee8..7ecf7eee 100644
--- a/venv1/Lib/site-packages/pip/_vendor/pygments/formatters/__init__.py
+++ b/venv1/Lib/site-packages/pip/_vendor/pygments/formatters/__init__.py
@@ -4,14 +4,13 @@
 
     Pygments formatters.
 
-    :copyright: Copyright 2006-2025 by the Pygments team, see AUTHORS.
+    :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS.
     :license: BSD, see LICENSE for details.
 """
 
-import re
 import sys
 import types
-import fnmatch
+from fnmatch import fnmatch
 from os.path import basename
 
 from pip._vendor.pygments.formatters._mapping import FORMATTERS
@@ -22,16 +21,6 @@
            'get_all_formatters', 'load_formatter_from_file'] + list(FORMATTERS)
 
 _formatter_cache = {}  # classes by name
-_pattern_cache = {}
-
-
-def _fn_matches(fn, glob):
-    """Return whether the supplied file name fn matches pattern filename."""
-    if glob not in _pattern_cache:
-        pattern = _pattern_cache[glob] = re.compile(fnmatch.translate(glob))
-        return pattern.match(fn)
-    return _pattern_cache[glob].match(fn)
-
 
 def _load_formatters(module_name):
     """Load a formatter (and all others in the module too)."""
@@ -68,31 +57,29 @@ def find_formatter_class(alias):
 
 
 def get_formatter_by_name(_alias, **options):
-    """
-    Return an instance of a :class:`.Formatter` subclass that has `alias` in its
-    aliases list. The formatter is given the `options` at its instantiation.
+    """Lookup and instantiate a formatter by alias.
 
-    Will raise :exc:`pygments.util.ClassNotFound` if no formatter with that
-    alias is found.
+    Raises ClassNotFound if not found.
     """
     cls = find_formatter_class(_alias)
     if cls is None:
-        raise ClassNotFound(f"no formatter found for name {_alias!r}")
+        raise ClassNotFound("no formatter found for name %r" % _alias)
     return cls(**options)
 
 
-def load_formatter_from_file(filename, formattername="CustomFormatter", **options):
-    """
-    Return a `Formatter` subclass instance loaded from the provided file, relative
-    to the current directory.
+def load_formatter_from_file(filename, formattername="CustomFormatter",
+                             **options):
+    """Load a formatter from a file.
+
+    This method expects a file located relative to the current working
+    directory, which contains a class named CustomFormatter. By default,
+    it expects the Formatter to be named CustomFormatter; you can specify
+    your own class name as the second argument to this function.
 
-    The file is expected to contain a Formatter class named ``formattername``
-    (by default, CustomFormatter). Users should be very careful with the input, because
-    this method is equivalent to running ``eval()`` on the input file. The formatter is
-    given the `options` at its instantiation.
+    Users should be very careful with the input, because this method
+    is equivalent to running eval on the input file.
 
-    :exc:`pygments.util.ClassNotFound` is raised if there are any errors loading
-    the formatter.
+    Raises ClassNotFound if there are any problems importing the Formatter.
 
     .. versionadded:: 2.2
     """
@@ -103,38 +90,36 @@ def load_formatter_from_file(filename, formattername="CustomFormatter", **option
             exec(f.read(), custom_namespace)
         # Retrieve the class `formattername` from that namespace
         if formattername not in custom_namespace:
-            raise ClassNotFound(f'no valid {formattername} class found in {filename}')
+            raise ClassNotFound('no valid %s class found in %s' %
+                                (formattername, filename))
         formatter_class = custom_namespace[formattername]
         # And finally instantiate it with the options
         return formatter_class(**options)
     except OSError as err:
-        raise ClassNotFound(f'cannot read {filename}: {err}')
+        raise ClassNotFound('cannot read %s: %s' % (filename, err))
     except ClassNotFound:
         raise
     except Exception as err:
-        raise ClassNotFound(f'error when loading custom formatter: {err}')
+        raise ClassNotFound('error when loading custom formatter: %s' % err)
 
 
 def get_formatter_for_filename(fn, **options):
-    """
-    Return a :class:`.Formatter` subclass instance that has a filename pattern
-    matching `fn`. The formatter is given the `options` at its instantiation.
+    """Lookup and instantiate a formatter by filename pattern.
 
-    Will raise :exc:`pygments.util.ClassNotFound` if no formatter for that filename
-    is found.
+    Raises ClassNotFound if not found.
     """
     fn = basename(fn)
     for modname, name, _, filenames, _ in FORMATTERS.values():
         for filename in filenames:
-            if _fn_matches(fn, filename):
+            if fnmatch(fn, filename):
                 if name not in _formatter_cache:
                     _load_formatters(modname)
                 return _formatter_cache[name](**options)
-    for _name, cls in find_plugin_formatters():
+    for cls in find_plugin_formatters():
         for filename in cls.filenames:
-            if _fn_matches(fn, filename):
+            if fnmatch(fn, filename):
                 return cls(**options)
-    raise ClassNotFound(f"no formatter found for file name {fn!r}")
+    raise ClassNotFound("no formatter found for file name %r" % fn)
 
 
 class _automodule(types.ModuleType):
diff --git a/venv1/Lib/site-packages/pip/_vendor/pygments/formatters/_mapping.py b/venv1/Lib/site-packages/pip/_vendor/pygments/formatters/_mapping.py
index 72ca8404..6e34f960 100644
--- a/venv1/Lib/site-packages/pip/_vendor/pygments/formatters/_mapping.py
+++ b/venv1/Lib/site-packages/pip/_vendor/pygments/formatters/_mapping.py
@@ -1,12 +1,12 @@
 # Automatically generated by scripts/gen_mapfiles.py.
-# DO NOT EDIT BY HAND; run `tox -e mapfiles` instead.
+# DO NOT EDIT BY HAND; run `make mapfiles` instead.
 
 FORMATTERS = {
     'BBCodeFormatter': ('pygments.formatters.bbcode', 'BBCode', ('bbcode', 'bb'), (), 'Format tokens with BBcodes. These formatting codes are used by many bulletin boards, so you can highlight your sourcecode with pygments before posting it there.'),
     'BmpImageFormatter': ('pygments.formatters.img', 'img_bmp', ('bmp', 'bitmap'), ('*.bmp',), 'Create a bitmap image from source code. This uses the Python Imaging Library to generate a pixmap from the source code.'),
     'GifImageFormatter': ('pygments.formatters.img', 'img_gif', ('gif',), ('*.gif',), 'Create a GIF image from source code. This uses the Python Imaging Library to generate a pixmap from the source code.'),
     'GroffFormatter': ('pygments.formatters.groff', 'groff', ('groff', 'troff', 'roff'), (), 'Format tokens with groff escapes to change their color and font style.'),
-    'HtmlFormatter': ('pygments.formatters.html', 'HTML', ('html',), ('*.html', '*.htm'), "Format tokens as HTML 4 ```` tags. By default, the content is enclosed in a ``
`` tag, itself wrapped in a ``
`` tag (but see the `nowrap` option). The ``
``'s CSS class can be set by the `cssclass` option."), + 'HtmlFormatter': ('pygments.formatters.html', 'HTML', ('html',), ('*.html', '*.htm'), "Format tokens as HTML 4 ```` tags within a ``
`` tag, wrapped in a ``
`` tag. The ``
``'s CSS class can be set by the `cssclass` option."), 'IRCFormatter': ('pygments.formatters.irc', 'IRC', ('irc', 'IRC'), (), 'Format tokens with IRC color sequences'), 'ImageFormatter': ('pygments.formatters.img', 'img', ('img', 'IMG', 'png'), ('*.png',), 'Create a PNG image from source code. This uses the Python Imaging Library to generate a pixmap from the source code.'), 'JpgImageFormatter': ('pygments.formatters.img', 'img_jpg', ('jpg', 'jpeg'), ('*.jpg',), 'Create a JPEG image from source code. This uses the Python Imaging Library to generate a pixmap from the source code.'), diff --git a/venv1/Lib/site-packages/pip/_vendor/pygments/lexer.py b/venv1/Lib/site-packages/pip/_vendor/pygments/lexer.py index c05aa819..74ab9b90 100644 --- a/venv1/Lib/site-packages/pip/_vendor/pygments/lexer.py +++ b/venv1/Lib/site-packages/pip/_vendor/pygments/lexer.py @@ -4,7 +4,7 @@ Base lexer classes. - :copyright: Copyright 2006-2025 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -50,38 +50,7 @@ class Lexer(metaclass=LexerMeta): """ Lexer for a specific language. - See also :doc:`lexerdevelopment`, a high-level guide to writing - lexers. - - Lexer classes have attributes used for choosing the most appropriate - lexer based on various criteria. - - .. autoattribute:: name - :no-value: - .. autoattribute:: aliases - :no-value: - .. autoattribute:: filenames - :no-value: - .. autoattribute:: alias_filenames - .. autoattribute:: mimetypes - :no-value: - .. autoattribute:: priority - - Lexers included in Pygments should have two additional attributes: - - .. autoattribute:: url - :no-value: - .. autoattribute:: version_added - :no-value: - - Lexers included in Pygments may have additional attributes: - - .. autoattribute:: _example - :no-value: - - You can pass options to the constructor. The basic options recognized - by all lexers and processed by the base `Lexer` class are: - + Basic options recognized: ``stripnl`` Strip leading and trailing newlines from the input (default: True). ``stripall`` @@ -105,62 +74,28 @@ class Lexer(metaclass=LexerMeta): Overrides the ``encoding`` if given. """ - #: Full name of the lexer, in human-readable form + #: Name of the lexer name = None - #: A list of short, unique identifiers that can be used to look - #: up the lexer from a list, e.g., using `get_lexer_by_name()`. + #: URL of the language specification/definition + url = None + + #: Shortcuts for the lexer aliases = [] - #: A list of `fnmatch` patterns that match filenames which contain - #: content for this lexer. The patterns in this list should be unique among - #: all lexers. + #: File name globs filenames = [] - #: A list of `fnmatch` patterns that match filenames which may or may not - #: contain content for this lexer. This list is used by the - #: :func:`.guess_lexer_for_filename()` function, to determine which lexers - #: are then included in guessing the correct one. That means that - #: e.g. every lexer for HTML and a template language should include - #: ``\*.html`` in this list. + #: Secondary file name globs alias_filenames = [] - #: A list of MIME types for content that can be lexed with this lexer. + #: MIME types mimetypes = [] #: Priority, should multiple lexers match and no content is provided priority = 0 - #: URL of the language specification/definition. Used in the Pygments - #: documentation. Set to an empty string to disable. - url = None - - #: Version of Pygments in which the lexer was added. - version_added = None - - #: Example file name. Relative to the ``tests/examplefiles`` directory. - #: This is used by the documentation generator to show an example. - _example = None - def __init__(self, **options): - """ - This constructor takes arbitrary options as keyword arguments. - Every subclass must first process its own options and then call - the `Lexer` constructor, since it processes the basic - options like `stripnl`. - - An example looks like this: - - .. sourcecode:: python - - def __init__(self, **options): - self.compress = options.get('compress', '') - Lexer.__init__(self, **options) - - As these options must all be specifiable as strings (due to the - command line usage), there are various utility functions - available to help with that, see `Utilities`_. - """ self.options = options self.stripnl = get_bool_opt(options, 'stripnl', True) self.stripall = get_bool_opt(options, 'stripall', False) @@ -174,9 +109,10 @@ def __init__(self, **options): def __repr__(self): if self.options: - return f'' + return '' % (self.__class__.__name__, + self.options) else: - return f'' + return '' % self.__class__.__name__ def add_filter(self, filter_, **options): """ @@ -188,13 +124,10 @@ def add_filter(self, filter_, **options): def analyse_text(text): """ - A static method which is called for lexer guessing. - - It should analyse the text and return a float in the range - from ``0.0`` to ``1.0``. If it returns ``0.0``, the lexer - will not be selected as the most probable one, if it returns - ``1.0``, it will be selected immediately. This is used by - `guess_lexer`. + Has to return a float between ``0`` and ``1`` that indicates + if a lexer wants to highlight this text. Used by ``guess_lexer``. + If this method returns ``0`` it won't highlight it in any case, if + it returns ``1`` highlighting with this lexer is guaranteed. The `LexerMeta` metaclass automatically wraps this function so that it works like a static method (no ``self`` or ``cls`` @@ -203,17 +136,21 @@ def analyse_text(text): it's the same as if the return values was ``0.0``. """ - def _preprocess_lexer_input(self, text): - """Apply preprocessing such as decoding the input, removing BOM and normalizing newlines.""" + def get_tokens(self, text, unfiltered=False): + """ + Return an iterable of (tokentype, value) pairs generated from + `text`. If `unfiltered` is set to `True`, the filtering mechanism + is bypassed even if filters are defined. + Also preprocess the text, i.e. expand tabs and strip it if + wanted and applies registered filters. + """ if not isinstance(text, str): if self.encoding == 'guess': text, _ = guess_decode(text) elif self.encoding == 'chardet': try: - # pip vendoring note: this code is not reachable by pip, - # removed import of chardet to make it clear. - raise ImportError('chardet is not vendored by pip') + from pip._vendor import chardet except ImportError as e: raise ImportError('To enable chardet encoding guessing, ' 'please install the chardet library ' @@ -250,24 +187,6 @@ def _preprocess_lexer_input(self, text): if self.ensurenl and not text.endswith('\n'): text += '\n' - return text - - def get_tokens(self, text, unfiltered=False): - """ - This method is the basic interface of a lexer. It is called by - the `highlight()` function. It must process the text and return an - iterable of ``(tokentype, value)`` pairs from `text`. - - Normally, you don't need to override this method. The default - implementation processes the options recognized by all lexers - (`stripnl`, `stripall` and so on), and then yields all tokens - from `get_tokens_unprocessed()`, with the ``index`` dropped. - - If `unfiltered` is set to `True`, the filtering mechanism is - bypassed even if filters are defined. - """ - text = self._preprocess_lexer_input(text) - def streamer(): for _, t, v in self.get_tokens_unprocessed(text): yield t, v @@ -278,12 +197,11 @@ def streamer(): def get_tokens_unprocessed(self, text): """ - This method should process the text and return an iterable of - ``(index, tokentype, value)`` tuples where ``index`` is the starting - position of the token within the input text. + Return an iterable of (index, tokentype, value) pairs where "index" + is the starting position of the token within the input text. - It must be overridden by subclasses. It is recommended to - implement it as a generator to maximize effectiveness. + In subclasses, implement this method as a generator to + maximize effectiveness. """ raise NotImplementedError @@ -512,7 +430,7 @@ def _process_regex(cls, regex, rflags, state): def _process_token(cls, token): """Preprocess the token component of a token definition.""" assert type(token) is _TokenType or callable(token), \ - f'token type must be simple type or callable, not {token!r}' + 'token type must be simple type or callable, not %r' % (token,) return token def _process_new_state(cls, new_state, unprocessed, processed): @@ -528,14 +446,14 @@ def _process_new_state(cls, new_state, unprocessed, processed): elif new_state[:5] == '#pop:': return -int(new_state[5:]) else: - assert False, f'unknown new state {new_state!r}' + assert False, 'unknown new state %r' % new_state elif isinstance(new_state, combined): # combine a new state from existing ones tmp_state = '_tmp_%d' % cls._tmpname cls._tmpname += 1 itokens = [] for istate in new_state: - assert istate != new_state, f'circular state ref {istate!r}' + assert istate != new_state, 'circular state ref %r' % istate itokens.extend(cls._process_state(unprocessed, processed, istate)) processed[tmp_state] = itokens @@ -548,12 +466,12 @@ def _process_new_state(cls, new_state, unprocessed, processed): 'unknown new state ' + istate return new_state else: - assert False, f'unknown new state def {new_state!r}' + assert False, 'unknown new state def %r' % new_state def _process_state(cls, unprocessed, processed, state): """Preprocess a single state definition.""" - assert isinstance(state, str), f"wrong state name {state!r}" - assert state[0] != '#', f"invalid state name {state!r}" + assert type(state) is str, "wrong state name %r" % state + assert state[0] != '#', "invalid state name %r" % state if state in processed: return processed[state] tokens = processed[state] = [] @@ -561,7 +479,7 @@ def _process_state(cls, unprocessed, processed, state): for tdef in unprocessed[state]: if isinstance(tdef, include): # it's a state reference - assert tdef != state, f"circular state reference {state!r}" + assert tdef != state, "circular state reference %r" % state tokens.extend(cls._process_state(unprocessed, processed, str(tdef))) continue @@ -575,12 +493,13 @@ def _process_state(cls, unprocessed, processed, state): tokens.append((re.compile('').match, None, new_state)) continue - assert type(tdef) is tuple, f"wrong rule def {tdef!r}" + assert type(tdef) is tuple, "wrong rule def %r" % tdef try: rex = cls._process_regex(tdef[0], rflags, state) except Exception as err: - raise ValueError(f"uncompilable regex {tdef[0]!r} in state {state!r} of {cls!r}: {err}") from err + raise ValueError("uncompilable regex %r in state %r of %r: %s" % + (tdef[0], state, cls, err)) from err token = cls._process_token(tdef[1]) @@ -741,7 +660,7 @@ def get_tokens_unprocessed(self, text, stack=('root',)): elif new_state == '#push': statestack.append(statestack[-1]) else: - assert False, f"wrong state def: {new_state!r}" + assert False, "wrong state def: %r" % new_state statetokens = tokendefs[statestack[-1]] break else: @@ -773,7 +692,8 @@ def __init__(self, text, pos, stack=None, end=None): self.stack = stack or ['root'] def __repr__(self): - return f'LexerContext({self.text!r}, {self.pos!r}, {self.stack!r})' + return 'LexerContext(%r, %r, %r)' % ( + self.text, self.pos, self.stack) class ExtendedRegexLexer(RegexLexer): @@ -828,7 +748,7 @@ def get_tokens_unprocessed(self, text=None, context=None): elif new_state == '#push': ctx.stack.append(ctx.stack[-1]) else: - assert False, f"wrong state def: {new_state!r}" + assert False, "wrong state def: %r" % new_state statetokens = tokendefs[ctx.stack[-1]] break else: diff --git a/venv1/Lib/site-packages/pip/_vendor/pygments/lexers/__init__.py b/venv1/Lib/site-packages/pip/_vendor/pygments/lexers/__init__.py index 49184ec8..e75a0579 100644 --- a/venv1/Lib/site-packages/pip/_vendor/pygments/lexers/__init__.py +++ b/venv1/Lib/site-packages/pip/_vendor/pygments/lexers/__init__.py @@ -4,14 +4,13 @@ Pygments lexers. - :copyright: Copyright 2006-2025 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ -import re import sys import types -import fnmatch +from fnmatch import fnmatch from os.path import basename from pip._vendor.pygments.lexers._mapping import LEXERS @@ -22,23 +21,12 @@ COMPAT = { 'Python3Lexer': 'PythonLexer', 'Python3TracebackLexer': 'PythonTracebackLexer', - 'LeanLexer': 'Lean3Lexer', } __all__ = ['get_lexer_by_name', 'get_lexer_for_filename', 'find_lexer_class', 'guess_lexer', 'load_lexer_from_file'] + list(LEXERS) + list(COMPAT) _lexer_cache = {} -_pattern_cache = {} - - -def _fn_matches(fn, glob): - """Return whether the supplied file name fn matches pattern filename.""" - if glob not in _pattern_cache: - pattern = _pattern_cache[glob] = re.compile(fnmatch.translate(glob)) - return pattern.match(fn) - return _pattern_cache[glob].match(fn) - def _load_lexers(module_name): """Load a lexer (and all others in the module too).""" @@ -63,9 +51,9 @@ def get_all_lexers(plugins=True): def find_lexer_class(name): - """ - Return the `Lexer` subclass that with the *name* attribute as given by - the *name* argument. + """Lookup a lexer class by name. + + Return None if not found. """ if name in _lexer_cache: return _lexer_cache[name] @@ -81,19 +69,14 @@ def find_lexer_class(name): def find_lexer_class_by_name(_alias): - """ - Return the `Lexer` subclass that has `alias` in its aliases list, without - instantiating it. + """Lookup a lexer class by alias. Like `get_lexer_by_name`, but does not instantiate the class. - Will raise :exc:`pygments.util.ClassNotFound` if no lexer with that alias is - found. - .. versionadded:: 2.2 """ if not _alias: - raise ClassNotFound(f'no lexer for alias {_alias!r} found') + raise ClassNotFound('no lexer for alias %r found' % _alias) # lookup builtin lexers for module_name, name, aliases, _, _ in LEXERS.values(): if _alias.lower() in aliases: @@ -104,20 +87,16 @@ def find_lexer_class_by_name(_alias): for cls in find_plugin_lexers(): if _alias.lower() in cls.aliases: return cls - raise ClassNotFound(f'no lexer for alias {_alias!r} found') + raise ClassNotFound('no lexer for alias %r found' % _alias) def get_lexer_by_name(_alias, **options): - """ - Return an instance of a `Lexer` subclass that has `alias` in its - aliases list. The lexer is given the `options` at its - instantiation. + """Get a lexer by an alias. - Will raise :exc:`pygments.util.ClassNotFound` if no lexer with that alias is - found. + Raises ClassNotFound if not found. """ if not _alias: - raise ClassNotFound(f'no lexer for alias {_alias!r} found') + raise ClassNotFound('no lexer for alias %r found' % _alias) # lookup builtin lexers for module_name, name, aliases, _, _ in LEXERS.values(): @@ -129,7 +108,7 @@ def get_lexer_by_name(_alias, **options): for cls in find_plugin_lexers(): if _alias.lower() in cls.aliases: return cls(**options) - raise ClassNotFound(f'no lexer for alias {_alias!r} found') + raise ClassNotFound('no lexer for alias %r found' % _alias) def load_lexer_from_file(filename, lexername="CustomLexer", **options): @@ -154,16 +133,17 @@ def load_lexer_from_file(filename, lexername="CustomLexer", **options): exec(f.read(), custom_namespace) # Retrieve the class `lexername` from that namespace if lexername not in custom_namespace: - raise ClassNotFound(f'no valid {lexername} class found in {filename}') + raise ClassNotFound('no valid %s class found in %s' % + (lexername, filename)) lexer_class = custom_namespace[lexername] # And finally instantiate it with the options return lexer_class(**options) except OSError as err: - raise ClassNotFound(f'cannot read {filename}: {err}') + raise ClassNotFound('cannot read %s: %s' % (filename, err)) except ClassNotFound: raise except Exception as err: - raise ClassNotFound(f'error when loading custom lexer: {err}') + raise ClassNotFound('error when loading custom lexer: %s' % err) def find_lexer_class_for_filename(_fn, code=None): @@ -178,13 +158,13 @@ def find_lexer_class_for_filename(_fn, code=None): fn = basename(_fn) for modname, name, _, filenames, _ in LEXERS.values(): for filename in filenames: - if _fn_matches(fn, filename): + if fnmatch(fn, filename): if name not in _lexer_cache: _load_lexers(modname) matches.append((_lexer_cache[name], filename)) for cls in find_plugin_lexers(): for filename in cls.filenames: - if _fn_matches(fn, filename): + if fnmatch(fn, filename): matches.append((cls, filename)) if isinstance(code, bytes): @@ -212,29 +192,21 @@ def get_rating(info): def get_lexer_for_filename(_fn, code=None, **options): """Get a lexer for a filename. - Return a `Lexer` subclass instance that has a filename pattern - matching `fn`. The lexer is given the `options` at its - instantiation. - - Raise :exc:`pygments.util.ClassNotFound` if no lexer for that filename - is found. + If multiple lexers match the filename pattern, use ``analyse_text()`` to + figure out which one is more appropriate. - If multiple lexers match the filename pattern, use their ``analyse_text()`` - methods to figure out which one is more appropriate. + Raises ClassNotFound if not found. """ res = find_lexer_class_for_filename(_fn, code) if not res: - raise ClassNotFound(f'no lexer for filename {_fn!r} found') + raise ClassNotFound('no lexer for filename %r found' % _fn) return res(**options) def get_lexer_for_mimetype(_mime, **options): - """ - Return a `Lexer` subclass instance that has `mime` in its mimetype - list. The lexer is given the `options` at its instantiation. + """Get a lexer for a mimetype. - Will raise :exc:`pygments.util.ClassNotFound` if not lexer for that mimetype - is found. + Raises ClassNotFound if not found. """ for modname, name, _, _, mimetypes in LEXERS.values(): if _mime in mimetypes: @@ -244,7 +216,7 @@ def get_lexer_for_mimetype(_mime, **options): for cls in find_plugin_lexers(): if _mime in cls.mimetypes: return cls(**options) - raise ClassNotFound(f'no lexer for mimetype {_mime!r} found') + raise ClassNotFound('no lexer for mimetype %r found' % _mime) def _iter_lexerclasses(plugins=True): @@ -260,26 +232,34 @@ def _iter_lexerclasses(plugins=True): def guess_lexer_for_filename(_fn, _text, **options): """ - As :func:`guess_lexer()`, but only lexers which have a pattern in `filenames` - or `alias_filenames` that matches `filename` are taken into consideration. - - :exc:`pygments.util.ClassNotFound` is raised if no lexer thinks it can - handle the content. + Lookup all lexers that handle those filenames primary (``filenames``) + or secondary (``alias_filenames``). Then run a text analysis for those + lexers and choose the best result. + + usage:: + + >>> from pygments.lexers import guess_lexer_for_filename + >>> guess_lexer_for_filename('hello.html', '<%= @foo %>') + + >>> guess_lexer_for_filename('hello.html', '

{{ title|e }}

') + + >>> guess_lexer_for_filename('style.css', 'a { color: }') + """ fn = basename(_fn) primary = {} matching_lexers = set() for lexer in _iter_lexerclasses(): for filename in lexer.filenames: - if _fn_matches(fn, filename): + if fnmatch(fn, filename): matching_lexers.add(lexer) primary[lexer] = True for filename in lexer.alias_filenames: - if _fn_matches(fn, filename): + if fnmatch(fn, filename): matching_lexers.add(lexer) primary[lexer] = False if not matching_lexers: - raise ClassNotFound(f'no lexer for filename {fn!r} found') + raise ClassNotFound('no lexer for filename %r found' % fn) if len(matching_lexers) == 1: return matching_lexers.pop()(**options) result = [] @@ -302,15 +282,7 @@ def type_sort(t): def guess_lexer(_text, **options): - """ - Return a `Lexer` subclass instance that's guessed from the text in - `text`. For that, the :meth:`.analyse_text()` method of every known lexer - class is called with the text as argument, and the lexer which returned the - highest value will be instantiated and returned. - - :exc:`pygments.util.ClassNotFound` is raised if no lexer thinks it can - handle the content. - """ + """Guess a lexer by strong distinctions in the text (eg, shebang).""" if not isinstance(_text, str): inencoding = options.get('inencoding', options.get('encoding')) diff --git a/venv1/Lib/site-packages/pip/_vendor/pygments/lexers/_mapping.py b/venv1/Lib/site-packages/pip/_vendor/pygments/lexers/_mapping.py index c0d6a8ad..1eaaf56e 100644 --- a/venv1/Lib/site-packages/pip/_vendor/pygments/lexers/_mapping.py +++ b/venv1/Lib/site-packages/pip/_vendor/pygments/lexers/_mapping.py @@ -1,5 +1,5 @@ # Automatically generated by scripts/gen_mapfiles.py. -# DO NOT EDIT BY HAND; run `tox -e mapfiles` instead. +# DO NOT EDIT BY HAND; run `make mapfiles` instead. LEXERS = { 'ABAPLexer': ('pip._vendor.pygments.lexers.business', 'ABAP', ('abap',), ('*.abap', '*.ABAP'), ('text/x-abap',)), @@ -31,8 +31,7 @@ 'ArduinoLexer': ('pip._vendor.pygments.lexers.c_like', 'Arduino', ('arduino',), ('*.ino',), ('text/x-arduino',)), 'ArrowLexer': ('pip._vendor.pygments.lexers.arrow', 'Arrow', ('arrow',), ('*.arw',), ()), 'ArturoLexer': ('pip._vendor.pygments.lexers.arturo', 'Arturo', ('arturo', 'art'), ('*.art',), ()), - 'AscLexer': ('pip._vendor.pygments.lexers.asc', 'ASCII armored', ('asc', 'pem'), ('*.asc', '*.pem', 'id_dsa', 'id_ecdsa', 'id_ecdsa_sk', 'id_ed25519', 'id_ed25519_sk', 'id_rsa'), ('application/pgp-keys', 'application/pgp-encrypted', 'application/pgp-signature', 'application/pem-certificate-chain')), - 'Asn1Lexer': ('pip._vendor.pygments.lexers.asn1', 'ASN.1', ('asn1',), ('*.asn1',), ()), + 'AscLexer': ('pip._vendor.pygments.lexers.asc', 'ASCII armored', ('asc', 'pem'), ('*.asc', '*.pem', 'id_dsa', 'id_ecdsa', 'id_ecdsa_sk', 'id_ed25519', 'id_ed25519_sk', 'id_rsa'), ('application/pgp-keys', 'application/pgp-encrypted', 'application/pgp-signature')), 'AspectJLexer': ('pip._vendor.pygments.lexers.jvm', 'AspectJ', ('aspectj',), ('*.aj',), ('text/x-aspectj',)), 'AsymptoteLexer': ('pip._vendor.pygments.lexers.graphics', 'Asymptote', ('asymptote', 'asy'), ('*.asy',), ('text/x-asymptote',)), 'AugeasLexer': ('pip._vendor.pygments.lexers.configs', 'Augeas', ('augeas',), ('*.aug',), ()), @@ -42,11 +41,10 @@ 'BBCBasicLexer': ('pip._vendor.pygments.lexers.basic', 'BBC Basic', ('bbcbasic',), ('*.bbc',), ()), 'BBCodeLexer': ('pip._vendor.pygments.lexers.markup', 'BBCode', ('bbcode',), (), ('text/x-bbcode',)), 'BCLexer': ('pip._vendor.pygments.lexers.algebra', 'BC', ('bc',), ('*.bc',), ()), - 'BQNLexer': ('pip._vendor.pygments.lexers.bqn', 'BQN', ('bqn',), ('*.bqn',), ()), 'BSTLexer': ('pip._vendor.pygments.lexers.bibtex', 'BST', ('bst', 'bst-pybtex'), ('*.bst',), ()), 'BareLexer': ('pip._vendor.pygments.lexers.bare', 'BARE', ('bare',), ('*.bare',), ()), 'BaseMakefileLexer': ('pip._vendor.pygments.lexers.make', 'Base Makefile', ('basemake',), (), ()), - 'BashLexer': ('pip._vendor.pygments.lexers.shell', 'Bash', ('bash', 'sh', 'ksh', 'zsh', 'shell', 'openrc'), ('*.sh', '*.ksh', '*.bash', '*.ebuild', '*.eclass', '*.exheres-0', '*.exlib', '*.zsh', '.bashrc', 'bashrc', '.bash_*', 'bash_*', 'zshrc', '.zshrc', '.kshrc', 'kshrc', 'PKGBUILD'), ('application/x-sh', 'application/x-shellscript', 'text/x-shellscript')), + 'BashLexer': ('pip._vendor.pygments.lexers.shell', 'Bash', ('bash', 'sh', 'ksh', 'zsh', 'shell'), ('*.sh', '*.ksh', '*.bash', '*.ebuild', '*.eclass', '*.exheres-0', '*.exlib', '*.zsh', '.bashrc', 'bashrc', '.bash_*', 'bash_*', 'zshrc', '.zshrc', '.kshrc', 'kshrc', 'PKGBUILD'), ('application/x-sh', 'application/x-shellscript', 'text/x-shellscript')), 'BashSessionLexer': ('pip._vendor.pygments.lexers.shell', 'Bash Session', ('console', 'shell-session'), ('*.sh-session', '*.shell-session'), ('application/x-shell-session', 'application/x-sh-session')), 'BatchLexer': ('pip._vendor.pygments.lexers.shell', 'Batchfile', ('batch', 'bat', 'dosbatch', 'winbatch'), ('*.bat', '*.cmd'), ('application/x-dos-batch',)), 'BddLexer': ('pip._vendor.pygments.lexers.bdd', 'Bdd', ('bdd',), ('*.feature',), ('text/x-bdd',)), @@ -55,7 +53,6 @@ 'BibTeXLexer': ('pip._vendor.pygments.lexers.bibtex', 'BibTeX', ('bibtex', 'bib'), ('*.bib',), ('text/x-bibtex',)), 'BlitzBasicLexer': ('pip._vendor.pygments.lexers.basic', 'BlitzBasic', ('blitzbasic', 'b3d', 'bplus'), ('*.bb', '*.decls'), ('text/x-bb',)), 'BlitzMaxLexer': ('pip._vendor.pygments.lexers.basic', 'BlitzMax', ('blitzmax', 'bmax'), ('*.bmx',), ('text/x-bmx',)), - 'BlueprintLexer': ('pip._vendor.pygments.lexers.blueprint', 'Blueprint', ('blueprint',), ('*.blp',), ('text/x-blueprint',)), 'BnfLexer': ('pip._vendor.pygments.lexers.grammar_notation', 'BNF', ('bnf',), ('*.bnf',), ('text/x-bnf',)), 'BoaLexer': ('pip._vendor.pygments.lexers.boa', 'Boa', ('boa',), ('*.boa',), ()), 'BooLexer': ('pip._vendor.pygments.lexers.dotnet', 'Boo', ('boo',), ('*.boo',), ('text/x-boo',)), @@ -74,7 +71,6 @@ 'CadlLexer': ('pip._vendor.pygments.lexers.archetype', 'cADL', ('cadl',), ('*.cadl',), ()), 'CapDLLexer': ('pip._vendor.pygments.lexers.esoteric', 'CapDL', ('capdl',), ('*.cdl',), ()), 'CapnProtoLexer': ('pip._vendor.pygments.lexers.capnproto', "Cap'n Proto", ('capnp',), ('*.capnp',), ()), - 'CarbonLexer': ('pip._vendor.pygments.lexers.carbon', 'Carbon', ('carbon',), ('*.carbon',), ('text/x-carbon',)), 'CbmBasicV2Lexer': ('pip._vendor.pygments.lexers.basic', 'CBM BASIC V2', ('cbmbas',), ('*.bas',), ()), 'CddlLexer': ('pip._vendor.pygments.lexers.cddl', 'CDDL', ('cddl',), ('*.cddl',), ('text/x-cddl',)), 'CeylonLexer': ('pip._vendor.pygments.lexers.jvm', 'Ceylon', ('ceylon',), ('*.ceylon',), ('text/x-ceylon',)), @@ -93,7 +89,6 @@ 'ClojureScriptLexer': ('pip._vendor.pygments.lexers.jvm', 'ClojureScript', ('clojurescript', 'cljs'), ('*.cljs',), ('text/x-clojurescript', 'application/x-clojurescript')), 'CobolFreeformatLexer': ('pip._vendor.pygments.lexers.business', 'COBOLFree', ('cobolfree',), ('*.cbl', '*.CBL'), ()), 'CobolLexer': ('pip._vendor.pygments.lexers.business', 'COBOL', ('cobol',), ('*.cob', '*.COB', '*.cpy', '*.CPY'), ('text/x-cobol',)), - 'CodeQLLexer': ('pip._vendor.pygments.lexers.codeql', 'CodeQL', ('codeql', 'ql'), ('*.ql', '*.qll'), ()), 'CoffeeScriptLexer': ('pip._vendor.pygments.lexers.javascript', 'CoffeeScript', ('coffeescript', 'coffee-script', 'coffee'), ('*.coffee',), ('text/coffeescript',)), 'ColdfusionCFCLexer': ('pip._vendor.pygments.lexers.templates', 'Coldfusion CFC', ('cfc',), ('*.cfc',), ()), 'ColdfusionHtmlLexer': ('pip._vendor.pygments.lexers.templates', 'Coldfusion HTML', ('cfm',), ('*.cfm', '*.cfml'), ('application/x-coldfusion',)), @@ -126,16 +121,12 @@ 'DarcsPatchLexer': ('pip._vendor.pygments.lexers.diff', 'Darcs Patch', ('dpatch',), ('*.dpatch', '*.darcspatch'), ()), 'DartLexer': ('pip._vendor.pygments.lexers.javascript', 'Dart', ('dart',), ('*.dart',), ('text/x-dart',)), 'Dasm16Lexer': ('pip._vendor.pygments.lexers.asm', 'DASM16', ('dasm16',), ('*.dasm16', '*.dasm'), ('text/x-dasm16',)), - 'DaxLexer': ('pip._vendor.pygments.lexers.dax', 'Dax', ('dax',), ('*.dax',), ()), 'DebianControlLexer': ('pip._vendor.pygments.lexers.installers', 'Debian Control file', ('debcontrol', 'control'), ('control',), ()), - 'DebianSourcesLexer': ('pip._vendor.pygments.lexers.installers', 'Debian Sources file', ('debian.sources',), ('*.sources',), ()), 'DelphiLexer': ('pip._vendor.pygments.lexers.pascal', 'Delphi', ('delphi', 'pas', 'pascal', 'objectpascal'), ('*.pas', '*.dpr'), ('text/x-pascal',)), - 'DesktopLexer': ('pip._vendor.pygments.lexers.configs', 'Desktop file', ('desktop',), ('*.desktop',), ('application/x-desktop',)), 'DevicetreeLexer': ('pip._vendor.pygments.lexers.devicetree', 'Devicetree', ('devicetree', 'dts'), ('*.dts', '*.dtsi'), ('text/x-c',)), 'DgLexer': ('pip._vendor.pygments.lexers.python', 'dg', ('dg',), ('*.dg',), ('text/x-dg',)), 'DiffLexer': ('pip._vendor.pygments.lexers.diff', 'Diff', ('diff', 'udiff'), ('*.diff', '*.patch'), ('text/x-diff', 'text/x-patch')), 'DjangoLexer': ('pip._vendor.pygments.lexers.templates', 'Django/Jinja', ('django', 'jinja'), (), ('application/x-django-templating', 'application/x-jinja')), - 'DnsZoneLexer': ('pip._vendor.pygments.lexers.dns', 'Zone', ('zone',), ('*.zone',), ('text/dns',)), 'DockerLexer': ('pip._vendor.pygments.lexers.configs', 'Docker', ('docker', 'dockerfile'), ('Dockerfile', '*.docker'), ('text/x-dockerfile-config',)), 'DtdLexer': ('pip._vendor.pygments.lexers.html', 'DTD', ('dtd',), ('*.dtd',), ('application/xml-dtd',)), 'DuelLexer': ('pip._vendor.pygments.lexers.webmisc', 'Duel', ('duel', 'jbst', 'jsonml+bst'), ('*.duel', '*.jbst'), ('text/x-duel', 'text/x-jbst')), @@ -157,9 +148,9 @@ 'ErbLexer': ('pip._vendor.pygments.lexers.templates', 'ERB', ('erb',), (), ('application/x-ruby-templating',)), 'ErlangLexer': ('pip._vendor.pygments.lexers.erlang', 'Erlang', ('erlang',), ('*.erl', '*.hrl', '*.es', '*.escript'), ('text/x-erlang',)), 'ErlangShellLexer': ('pip._vendor.pygments.lexers.erlang', 'Erlang erl session', ('erl',), ('*.erl-sh',), ('text/x-erl-shellsession',)), - 'EvoqueHtmlLexer': ('pip._vendor.pygments.lexers.templates', 'HTML+Evoque', ('html+evoque',), (), ('text/html+evoque',)), + 'EvoqueHtmlLexer': ('pip._vendor.pygments.lexers.templates', 'HTML+Evoque', ('html+evoque',), ('*.html',), ('text/html+evoque',)), 'EvoqueLexer': ('pip._vendor.pygments.lexers.templates', 'Evoque', ('evoque',), ('*.evoque',), ('application/x-evoque',)), - 'EvoqueXmlLexer': ('pip._vendor.pygments.lexers.templates', 'XML+Evoque', ('xml+evoque',), (), ('application/xml+evoque',)), + 'EvoqueXmlLexer': ('pip._vendor.pygments.lexers.templates', 'XML+Evoque', ('xml+evoque',), ('*.xml',), ('application/xml+evoque',)), 'ExeclineLexer': ('pip._vendor.pygments.lexers.shell', 'execline', ('execline',), ('*.exec',), ()), 'EzhilLexer': ('pip._vendor.pygments.lexers.ezhil', 'Ezhil', ('ezhil',), ('*.n',), ('text/x-ezhil',)), 'FSharpLexer': ('pip._vendor.pygments.lexers.dotnet', 'F#', ('fsharp', 'f#'), ('*.fs', '*.fsi', '*.fsx'), ('text/x-fsharp',)), @@ -191,15 +182,12 @@ 'GenshiTextLexer': ('pip._vendor.pygments.lexers.templates', 'Genshi Text', ('genshitext',), (), ('application/x-genshi-text', 'text/x-genshi')), 'GettextLexer': ('pip._vendor.pygments.lexers.textfmts', 'Gettext Catalog', ('pot', 'po'), ('*.pot', '*.po'), ('application/x-gettext', 'text/x-gettext', 'text/gettext')), 'GherkinLexer': ('pip._vendor.pygments.lexers.testing', 'Gherkin', ('gherkin', 'cucumber'), ('*.feature',), ('text/x-gherkin',)), - 'GleamLexer': ('pip._vendor.pygments.lexers.gleam', 'Gleam', ('gleam',), ('*.gleam',), ('text/x-gleam',)), 'GnuplotLexer': ('pip._vendor.pygments.lexers.graphics', 'Gnuplot', ('gnuplot',), ('*.plot', '*.plt'), ('text/x-gnuplot',)), 'GoLexer': ('pip._vendor.pygments.lexers.go', 'Go', ('go', 'golang'), ('*.go',), ('text/x-gosrc',)), 'GoloLexer': ('pip._vendor.pygments.lexers.jvm', 'Golo', ('golo',), ('*.golo',), ()), 'GoodDataCLLexer': ('pip._vendor.pygments.lexers.business', 'GoodData-CL', ('gooddata-cl',), ('*.gdc',), ('text/x-gooddata-cl',)), - 'GoogleSqlLexer': ('pip._vendor.pygments.lexers.sql', 'GoogleSQL', ('googlesql', 'zetasql'), ('*.googlesql', '*.googlesql.sql'), ('text/x-google-sql', 'text/x-google-sql-aux')), 'GosuLexer': ('pip._vendor.pygments.lexers.jvm', 'Gosu', ('gosu',), ('*.gs', '*.gsx', '*.gsp', '*.vark'), ('text/x-gosu',)), 'GosuTemplateLexer': ('pip._vendor.pygments.lexers.jvm', 'Gosu Template', ('gst',), ('*.gst',), ('text/x-gosu-template',)), - 'GraphQLLexer': ('pip._vendor.pygments.lexers.graphql', 'GraphQL', ('graphql',), ('*.graphql',), ()), 'GraphvizLexer': ('pip._vendor.pygments.lexers.graphviz', 'Graphviz', ('graphviz', 'dot'), ('*.gv', '*.dot'), ('text/x-graphviz', 'text/vnd.graphviz')), 'GroffLexer': ('pip._vendor.pygments.lexers.markup', 'Groff', ('groff', 'nroff', 'man'), ('*.[1-9]', '*.man', '*.1p', '*.3pm'), ('application/x-troff', 'text/troff')), 'GroovyLexer': ('pip._vendor.pygments.lexers.jvm', 'Groovy', ('groovy',), ('*.groovy', '*.gradle'), ('text/x-groovy',)), @@ -208,7 +196,6 @@ 'HamlLexer': ('pip._vendor.pygments.lexers.html', 'Haml', ('haml',), ('*.haml',), ('text/x-haml',)), 'HandlebarsHtmlLexer': ('pip._vendor.pygments.lexers.templates', 'HTML+Handlebars', ('html+handlebars',), ('*.handlebars', '*.hbs'), ('text/html+handlebars', 'text/x-handlebars-template')), 'HandlebarsLexer': ('pip._vendor.pygments.lexers.templates', 'Handlebars', ('handlebars',), (), ()), - 'HareLexer': ('pip._vendor.pygments.lexers.hare', 'Hare', ('hare',), ('*.ha',), ('text/x-hare',)), 'HaskellLexer': ('pip._vendor.pygments.lexers.haskell', 'Haskell', ('haskell', 'hs'), ('*.hs',), ('text/x-haskell',)), 'HaxeLexer': ('pip._vendor.pygments.lexers.haxe', 'Haxe', ('haxe', 'hxsl', 'hx'), ('*.hx', '*.hxsl'), ('text/haxe', 'text/x-haxe', 'text/x-hx')), 'HexdumpLexer': ('pip._vendor.pygments.lexers.hexdump', 'Hexdump', ('hexdump',), (), ()), @@ -221,8 +208,8 @@ 'HtmlSmartyLexer': ('pip._vendor.pygments.lexers.templates', 'HTML+Smarty', ('html+smarty',), (), ('text/html+smarty',)), 'HttpLexer': ('pip._vendor.pygments.lexers.textfmts', 'HTTP', ('http',), (), ()), 'HxmlLexer': ('pip._vendor.pygments.lexers.haxe', 'Hxml', ('haxeml', 'hxml'), ('*.hxml',), ()), - 'HyLexer': ('pip._vendor.pygments.lexers.lisp', 'Hy', ('hylang', 'hy'), ('*.hy',), ('text/x-hy', 'application/x-hy')), - 'HybrisLexer': ('pip._vendor.pygments.lexers.scripting', 'Hybris', ('hybris',), ('*.hyb',), ('text/x-hybris', 'application/x-hybris')), + 'HyLexer': ('pip._vendor.pygments.lexers.lisp', 'Hy', ('hylang',), ('*.hy',), ('text/x-hy', 'application/x-hy')), + 'HybrisLexer': ('pip._vendor.pygments.lexers.scripting', 'Hybris', ('hybris', 'hy'), ('*.hy', '*.hyb'), ('text/x-hybris', 'application/x-hybris')), 'IDLLexer': ('pip._vendor.pygments.lexers.idl', 'IDL', ('idl',), ('*.pro',), ('text/idl',)), 'IconLexer': ('pip._vendor.pygments.lexers.unicon', 'Icon', ('icon',), ('*.icon', '*.ICON'), ()), 'IdrisLexer': ('pip._vendor.pygments.lexers.haskell', 'Idris', ('idris', 'idr'), ('*.idr',), ('text/x-idris',)), @@ -230,7 +217,7 @@ 'Inform6Lexer': ('pip._vendor.pygments.lexers.int_fiction', 'Inform 6', ('inform6', 'i6'), ('*.inf',), ()), 'Inform6TemplateLexer': ('pip._vendor.pygments.lexers.int_fiction', 'Inform 6 template', ('i6t',), ('*.i6t',), ()), 'Inform7Lexer': ('pip._vendor.pygments.lexers.int_fiction', 'Inform 7', ('inform7', 'i7'), ('*.ni', '*.i7x'), ()), - 'IniLexer': ('pip._vendor.pygments.lexers.configs', 'INI', ('ini', 'cfg', 'dosini'), ('*.ini', '*.cfg', '*.inf', '.editorconfig'), ('text/x-ini', 'text/inf')), + 'IniLexer': ('pip._vendor.pygments.lexers.configs', 'INI', ('ini', 'cfg', 'dosini'), ('*.ini', '*.cfg', '*.inf', '.editorconfig', '*.service', '*.socket', '*.device', '*.mount', '*.automount', '*.swap', '*.target', '*.path', '*.timer', '*.slice', '*.scope'), ('text/x-ini', 'text/inf')), 'IoLexer': ('pip._vendor.pygments.lexers.iolang', 'Io', ('io',), ('*.io',), ('text/x-iosrc',)), 'IokeLexer': ('pip._vendor.pygments.lexers.jvm', 'Ioke', ('ioke', 'ik'), ('*.ik',), ('text/x-iokesrc',)), 'IrcLogsLexer': ('pip._vendor.pygments.lexers.textfmts', 'IRC logs', ('irc',), ('*.weechatlog',), ('text/x-irclog',)), @@ -239,7 +226,6 @@ 'JMESPathLexer': ('pip._vendor.pygments.lexers.jmespath', 'JMESPath', ('jmespath', 'jp'), ('*.jp',), ()), 'JSLTLexer': ('pip._vendor.pygments.lexers.jslt', 'JSLT', ('jslt',), ('*.jslt',), ('text/x-jslt',)), 'JagsLexer': ('pip._vendor.pygments.lexers.modeling', 'JAGS', ('jags',), ('*.jag', '*.bug'), ()), - 'JanetLexer': ('pip._vendor.pygments.lexers.lisp', 'Janet', ('janet',), ('*.janet', '*.jdn'), ('text/x-janet', 'application/x-janet')), 'JasminLexer': ('pip._vendor.pygments.lexers.jvm', 'Jasmin', ('jasmin', 'jasminxt'), ('*.j',), ()), 'JavaLexer': ('pip._vendor.pygments.lexers.jvm', 'Java', ('java',), ('*.java',), ('text/x-java',)), 'JavascriptDjangoLexer': ('pip._vendor.pygments.lexers.templates', 'JavaScript+Django/Jinja', ('javascript+django', 'js+django', 'javascript+jinja', 'js+jinja'), ('*.js.j2', '*.js.jinja2'), ('application/x-javascript+django', 'application/x-javascript+jinja', 'text/x-javascript+django', 'text/x-javascript+jinja', 'text/javascript+django', 'text/javascript+jinja')), @@ -251,13 +237,11 @@ 'JavascriptUL4Lexer': ('pip._vendor.pygments.lexers.ul4', 'Javascript+UL4', ('js+ul4',), ('*.jsul4',), ()), 'JclLexer': ('pip._vendor.pygments.lexers.scripting', 'JCL', ('jcl',), ('*.jcl',), ('text/x-jcl',)), 'JsgfLexer': ('pip._vendor.pygments.lexers.grammar_notation', 'JSGF', ('jsgf',), ('*.jsgf',), ('application/jsgf', 'application/x-jsgf', 'text/jsgf')), - 'Json5Lexer': ('pip._vendor.pygments.lexers.json5', 'JSON5', ('json5',), ('*.json5',), ()), 'JsonBareObjectLexer': ('pip._vendor.pygments.lexers.data', 'JSONBareObject', (), (), ()), 'JsonLdLexer': ('pip._vendor.pygments.lexers.data', 'JSON-LD', ('jsonld', 'json-ld'), ('*.jsonld',), ('application/ld+json',)), - 'JsonLexer': ('pip._vendor.pygments.lexers.data', 'JSON', ('json', 'json-object'), ('*.json', '*.jsonl', '*.ndjson', 'Pipfile.lock'), ('application/json', 'application/json-object', 'application/x-ndjson', 'application/jsonl', 'application/json-seq')), + 'JsonLexer': ('pip._vendor.pygments.lexers.data', 'JSON', ('json', 'json-object'), ('*.json', 'Pipfile.lock'), ('application/json', 'application/json-object')), 'JsonnetLexer': ('pip._vendor.pygments.lexers.jsonnet', 'Jsonnet', ('jsonnet',), ('*.jsonnet', '*.libsonnet'), ()), 'JspLexer': ('pip._vendor.pygments.lexers.templates', 'Java Server Page', ('jsp',), ('*.jsp',), ('application/x-jsp',)), - 'JsxLexer': ('pip._vendor.pygments.lexers.jsx', 'JSX', ('jsx', 'react'), ('*.jsx', '*.react'), ('text/jsx', 'text/typescript-jsx')), 'JuliaConsoleLexer': ('pip._vendor.pygments.lexers.julia', 'Julia console', ('jlcon', 'julia-repl'), (), ()), 'JuliaLexer': ('pip._vendor.pygments.lexers.julia', 'Julia', ('julia', 'jl'), ('*.jl',), ('text/x-julia', 'application/x-julia')), 'JuttleLexer': ('pip._vendor.pygments.lexers.javascript', 'Juttle', ('juttle',), ('*.juttle',), ('application/juttle', 'application/x-juttle', 'text/x-juttle', 'text/juttle')), @@ -268,17 +252,13 @@ 'KokaLexer': ('pip._vendor.pygments.lexers.haskell', 'Koka', ('koka',), ('*.kk', '*.kki'), ('text/x-koka',)), 'KotlinLexer': ('pip._vendor.pygments.lexers.jvm', 'Kotlin', ('kotlin',), ('*.kt', '*.kts'), ('text/x-kotlin',)), 'KuinLexer': ('pip._vendor.pygments.lexers.kuin', 'Kuin', ('kuin',), ('*.kn',), ()), - 'KustoLexer': ('pip._vendor.pygments.lexers.kusto', 'Kusto', ('kql', 'kusto'), ('*.kql', '*.kusto', '.csl'), ()), 'LSLLexer': ('pip._vendor.pygments.lexers.scripting', 'LSL', ('lsl',), ('*.lsl',), ('text/x-lsl',)), 'LassoCssLexer': ('pip._vendor.pygments.lexers.templates', 'CSS+Lasso', ('css+lasso',), (), ('text/css+lasso',)), 'LassoHtmlLexer': ('pip._vendor.pygments.lexers.templates', 'HTML+Lasso', ('html+lasso',), (), ('text/html+lasso', 'application/x-httpd-lasso', 'application/x-httpd-lasso[89]')), 'LassoJavascriptLexer': ('pip._vendor.pygments.lexers.templates', 'JavaScript+Lasso', ('javascript+lasso', 'js+lasso'), (), ('application/x-javascript+lasso', 'text/x-javascript+lasso', 'text/javascript+lasso')), 'LassoLexer': ('pip._vendor.pygments.lexers.javascript', 'Lasso', ('lasso', 'lassoscript'), ('*.lasso', '*.lasso[89]'), ('text/x-lasso',)), 'LassoXmlLexer': ('pip._vendor.pygments.lexers.templates', 'XML+Lasso', ('xml+lasso',), (), ('application/xml+lasso',)), - 'LdaprcLexer': ('pip._vendor.pygments.lexers.ldap', 'LDAP configuration file', ('ldapconf', 'ldaprc'), ('.ldaprc', 'ldaprc', 'ldap.conf'), ('text/x-ldapconf',)), - 'LdifLexer': ('pip._vendor.pygments.lexers.ldap', 'LDIF', ('ldif',), ('*.ldif',), ('text/x-ldif',)), - 'Lean3Lexer': ('pip._vendor.pygments.lexers.lean', 'Lean', ('lean', 'lean3'), ('*.lean',), ('text/x-lean', 'text/x-lean3')), - 'Lean4Lexer': ('pip._vendor.pygments.lexers.lean', 'Lean4', ('lean4',), ('*.lean',), ('text/x-lean4',)), + 'LeanLexer': ('pip._vendor.pygments.lexers.theorem', 'Lean', ('lean',), ('*.lean',), ('text/x-lean',)), 'LessCssLexer': ('pip._vendor.pygments.lexers.css', 'LessCss', ('less',), ('*.less',), ('text/x-less-css',)), 'LighttpdConfLexer': ('pip._vendor.pygments.lexers.configs', 'Lighttpd configuration file', ('lighttpd', 'lighty'), ('lighttpd.conf',), ('text/x-lighttpd-conf',)), 'LilyPondLexer': ('pip._vendor.pygments.lexers.lilypond', 'LilyPond', ('lilypond',), ('*.ly',), ()), @@ -295,7 +275,6 @@ 'LogosLexer': ('pip._vendor.pygments.lexers.objective', 'Logos', ('logos',), ('*.x', '*.xi', '*.xm', '*.xmi'), ('text/x-logos',)), 'LogtalkLexer': ('pip._vendor.pygments.lexers.prolog', 'Logtalk', ('logtalk',), ('*.lgt', '*.logtalk'), ('text/x-logtalk',)), 'LuaLexer': ('pip._vendor.pygments.lexers.scripting', 'Lua', ('lua',), ('*.lua', '*.wlua'), ('text/x-lua', 'application/x-lua')), - 'LuauLexer': ('pip._vendor.pygments.lexers.scripting', 'Luau', ('luau',), ('*.luau',), ()), 'MCFunctionLexer': ('pip._vendor.pygments.lexers.minecraft', 'MCFunction', ('mcfunction', 'mcf'), ('*.mcfunction',), ('text/mcfunction',)), 'MCSchemaLexer': ('pip._vendor.pygments.lexers.minecraft', 'MCSchema', ('mcschema',), ('*.mcschema',), ('text/mcschema',)), 'MIMELexer': ('pip._vendor.pygments.lexers.mime', 'MIME', ('mime',), (), ('multipart/mixed', 'multipart/related', 'multipart/alternative')), @@ -309,7 +288,6 @@ 'MakoJavascriptLexer': ('pip._vendor.pygments.lexers.templates', 'JavaScript+Mako', ('javascript+mako', 'js+mako'), (), ('application/x-javascript+mako', 'text/x-javascript+mako', 'text/javascript+mako')), 'MakoLexer': ('pip._vendor.pygments.lexers.templates', 'Mako', ('mako',), ('*.mao',), ('application/x-mako',)), 'MakoXmlLexer': ('pip._vendor.pygments.lexers.templates', 'XML+Mako', ('xml+mako',), (), ('application/xml+mako',)), - 'MapleLexer': ('pip._vendor.pygments.lexers.maple', 'Maple', ('maple',), ('*.mpl', '*.mi', '*.mm'), ('text/x-maple',)), 'MaqlLexer': ('pip._vendor.pygments.lexers.business', 'MAQL', ('maql',), ('*.maql',), ('text/x-gooddata-maql', 'application/x-gooddata-maql')), 'MarkdownLexer': ('pip._vendor.pygments.lexers.markup', 'Markdown', ('markdown', 'md'), ('*.md', '*.markdown'), ('text/x-markdown',)), 'MaskLexer': ('pip._vendor.pygments.lexers.javascript', 'Mask', ('mask',), ('*.mask',), ('text/x-mask',)), @@ -324,7 +302,6 @@ 'ModelicaLexer': ('pip._vendor.pygments.lexers.modeling', 'Modelica', ('modelica',), ('*.mo',), ('text/x-modelica',)), 'Modula2Lexer': ('pip._vendor.pygments.lexers.modula2', 'Modula-2', ('modula2', 'm2'), ('*.def', '*.mod'), ('text/x-modula2',)), 'MoinWikiLexer': ('pip._vendor.pygments.lexers.markup', 'MoinMoin/Trac Wiki markup', ('trac-wiki', 'moin'), (), ('text/x-trac-wiki',)), - 'MojoLexer': ('pip._vendor.pygments.lexers.mojo', 'Mojo', ('mojo', '🔥'), ('*.mojo', '*.🔥'), ('text/x-mojo', 'application/x-mojo')), 'MonkeyLexer': ('pip._vendor.pygments.lexers.basic', 'Monkey', ('monkey',), ('*.monkey',), ('text/x-monkey',)), 'MonteLexer': ('pip._vendor.pygments.lexers.monte', 'Monte', ('monte',), ('*.mt',), ()), 'MoonScriptLexer': ('pip._vendor.pygments.lexers.scripting', 'MoonScript', ('moonscript', 'moon'), ('*.moon',), ('text/x-moonscript', 'application/x-moonscript')), @@ -361,7 +338,6 @@ 'NotmuchLexer': ('pip._vendor.pygments.lexers.textfmts', 'Notmuch', ('notmuch',), (), ()), 'NuSMVLexer': ('pip._vendor.pygments.lexers.smv', 'NuSMV', ('nusmv',), ('*.smv',), ()), 'NumPyLexer': ('pip._vendor.pygments.lexers.python', 'NumPy', ('numpy',), (), ()), - 'NumbaIRLexer': ('pip._vendor.pygments.lexers.numbair', 'Numba_IR', ('numba_ir', 'numbair'), ('*.numba_ir',), ('text/x-numba_ir', 'text/x-numbair')), 'ObjdumpLexer': ('pip._vendor.pygments.lexers.asm', 'objdump', ('objdump',), ('*.objdump',), ('text/x-objdump',)), 'ObjectiveCLexer': ('pip._vendor.pygments.lexers.objective', 'Objective-C', ('objective-c', 'objectivec', 'obj-c', 'objc'), ('*.m', '*.h'), ('text/x-objective-c',)), 'ObjectiveCppLexer': ('pip._vendor.pygments.lexers.objective', 'Objective-C++', ('objective-c++', 'objectivec++', 'obj-c++', 'objc++'), ('*.mm', '*.hh'), ('text/x-objective-c++',)), @@ -373,14 +349,11 @@ 'OocLexer': ('pip._vendor.pygments.lexers.ooc', 'Ooc', ('ooc',), ('*.ooc',), ('text/x-ooc',)), 'OpaLexer': ('pip._vendor.pygments.lexers.ml', 'Opa', ('opa',), ('*.opa',), ('text/x-opa',)), 'OpenEdgeLexer': ('pip._vendor.pygments.lexers.business', 'OpenEdge ABL', ('openedge', 'abl', 'progress'), ('*.p', '*.cls'), ('text/x-openedge', 'application/x-openedge')), - 'OpenScadLexer': ('pip._vendor.pygments.lexers.openscad', 'OpenSCAD', ('openscad',), ('*.scad',), ('application/x-openscad',)), - 'OrgLexer': ('pip._vendor.pygments.lexers.markup', 'Org Mode', ('org', 'orgmode', 'org-mode'), ('*.org',), ('text/org',)), 'OutputLexer': ('pip._vendor.pygments.lexers.special', 'Text output', ('output',), (), ()), 'PacmanConfLexer': ('pip._vendor.pygments.lexers.configs', 'PacmanConf', ('pacmanconf',), ('pacman.conf',), ()), 'PanLexer': ('pip._vendor.pygments.lexers.dsls', 'Pan', ('pan',), ('*.pan',), ()), 'ParaSailLexer': ('pip._vendor.pygments.lexers.parasail', 'ParaSail', ('parasail',), ('*.psi', '*.psl'), ('text/x-parasail',)), 'PawnLexer': ('pip._vendor.pygments.lexers.pawn', 'Pawn', ('pawn',), ('*.p', '*.pwn', '*.inc'), ('text/x-pawn',)), - 'PddlLexer': ('pip._vendor.pygments.lexers.pddl', 'PDDL', ('pddl',), ('*.pddl',), ()), 'PegLexer': ('pip._vendor.pygments.lexers.grammar_notation', 'PEG', ('peg',), ('*.peg',), ('text/x-peg',)), 'Perl6Lexer': ('pip._vendor.pygments.lexers.perl', 'Perl6', ('perl6', 'pl6', 'raku'), ('*.pl', '*.pm', '*.nqp', '*.p6', '*.6pl', '*.p6l', '*.pl6', '*.6pm', '*.p6m', '*.pm6', '*.t', '*.raku', '*.rakumod', '*.rakutest', '*.rakudoc'), ('text/x-perl6', 'application/x-perl6')), 'PerlLexer': ('pip._vendor.pygments.lexers.perl', 'Perl', ('perl', 'pl'), ('*.pl', '*.pm', '*.t', '*.perl'), ('text/x-perl', 'application/x-perl')), @@ -395,7 +368,6 @@ 'PortugolLexer': ('pip._vendor.pygments.lexers.pascal', 'Portugol', ('portugol',), ('*.alg', '*.portugol'), ()), 'PostScriptLexer': ('pip._vendor.pygments.lexers.graphics', 'PostScript', ('postscript', 'postscr'), ('*.ps', '*.eps'), ('application/postscript',)), 'PostgresConsoleLexer': ('pip._vendor.pygments.lexers.sql', 'PostgreSQL console (psql)', ('psql', 'postgresql-console', 'postgres-console'), (), ('text/x-postgresql-psql',)), - 'PostgresExplainLexer': ('pip._vendor.pygments.lexers.sql', 'PostgreSQL EXPLAIN dialect', ('postgres-explain',), ('*.explain',), ('text/x-postgresql-explain',)), 'PostgresLexer': ('pip._vendor.pygments.lexers.sql', 'PostgreSQL SQL dialect', ('postgresql', 'postgres'), (), ('text/x-postgresql',)), 'PovrayLexer': ('pip._vendor.pygments.lexers.graphics', 'POVRay', ('pov',), ('*.pov', '*.inc'), ('text/x-povray',)), 'PowerShellLexer': ('pip._vendor.pygments.lexers.shell', 'PowerShell', ('powershell', 'pwsh', 'posh', 'ps1', 'psm1'), ('*.ps1', '*.psm1'), ('text/x-powershell',)), @@ -404,19 +376,16 @@ 'ProcfileLexer': ('pip._vendor.pygments.lexers.procfile', 'Procfile', ('procfile',), ('Procfile',), ()), 'PrologLexer': ('pip._vendor.pygments.lexers.prolog', 'Prolog', ('prolog',), ('*.ecl', '*.prolog', '*.pro', '*.pl'), ('text/x-prolog',)), 'PromQLLexer': ('pip._vendor.pygments.lexers.promql', 'PromQL', ('promql',), ('*.promql',), ()), - 'PromelaLexer': ('pip._vendor.pygments.lexers.c_like', 'Promela', ('promela',), ('*.pml', '*.prom', '*.prm', '*.promela', '*.pr', '*.pm'), ('text/x-promela',)), 'PropertiesLexer': ('pip._vendor.pygments.lexers.configs', 'Properties', ('properties', 'jproperties'), ('*.properties',), ('text/x-java-properties',)), 'ProtoBufLexer': ('pip._vendor.pygments.lexers.dsls', 'Protocol Buffer', ('protobuf', 'proto'), ('*.proto',), ()), - 'PrqlLexer': ('pip._vendor.pygments.lexers.prql', 'PRQL', ('prql',), ('*.prql',), ('application/prql', 'application/x-prql')), 'PsyshConsoleLexer': ('pip._vendor.pygments.lexers.php', 'PsySH console session for PHP', ('psysh',), (), ()), - 'PtxLexer': ('pip._vendor.pygments.lexers.ptx', 'PTX', ('ptx',), ('*.ptx',), ('text/x-ptx',)), 'PugLexer': ('pip._vendor.pygments.lexers.html', 'Pug', ('pug', 'jade'), ('*.pug', '*.jade'), ('text/x-pug', 'text/x-jade')), 'PuppetLexer': ('pip._vendor.pygments.lexers.dsls', 'Puppet', ('puppet',), ('*.pp',), ()), 'PyPyLogLexer': ('pip._vendor.pygments.lexers.console', 'PyPy Log', ('pypylog', 'pypy'), ('*.pypylog',), ('application/x-pypylog',)), 'Python2Lexer': ('pip._vendor.pygments.lexers.python', 'Python 2.x', ('python2', 'py2'), (), ('text/x-python2', 'application/x-python2')), 'Python2TracebackLexer': ('pip._vendor.pygments.lexers.python', 'Python 2.x Traceback', ('py2tb',), ('*.py2tb',), ('text/x-python2-traceback',)), - 'PythonConsoleLexer': ('pip._vendor.pygments.lexers.python', 'Python console session', ('pycon', 'python-console'), (), ('text/x-python-doctest',)), - 'PythonLexer': ('pip._vendor.pygments.lexers.python', 'Python', ('python', 'py', 'sage', 'python3', 'py3', 'bazel', 'starlark', 'pyi'), ('*.py', '*.pyw', '*.pyi', '*.jy', '*.sage', '*.sc', 'SConstruct', 'SConscript', '*.bzl', 'BUCK', 'BUILD', 'BUILD.bazel', 'WORKSPACE', '*.tac'), ('text/x-python', 'application/x-python', 'text/x-python3', 'application/x-python3')), + 'PythonConsoleLexer': ('pip._vendor.pygments.lexers.python', 'Python console session', ('pycon',), (), ('text/x-python-doctest',)), + 'PythonLexer': ('pip._vendor.pygments.lexers.python', 'Python', ('python', 'py', 'sage', 'python3', 'py3'), ('*.py', '*.pyw', '*.pyi', '*.jy', '*.sage', '*.sc', 'SConstruct', 'SConscript', '*.bzl', 'BUCK', 'BUILD', 'BUILD.bazel', 'WORKSPACE', '*.tac'), ('text/x-python', 'application/x-python', 'text/x-python3', 'application/x-python3')), 'PythonTracebackLexer': ('pip._vendor.pygments.lexers.python', 'Python Traceback', ('pytb', 'py3tb'), ('*.pytb', '*.py3tb'), ('text/x-python-traceback', 'text/x-python3-traceback')), 'PythonUL4Lexer': ('pip._vendor.pygments.lexers.ul4', 'Python+UL4', ('py+ul4',), ('*.pyul4',), ()), 'QBasicLexer': ('pip._vendor.pygments.lexers.basic', 'QBasic', ('qbasic', 'basic'), ('*.BAS', '*.bas'), ('text/basic',)), @@ -443,7 +412,6 @@ 'RedLexer': ('pip._vendor.pygments.lexers.rebol', 'Red', ('red', 'red/system'), ('*.red', '*.reds'), ('text/x-red', 'text/x-red-system')), 'RedcodeLexer': ('pip._vendor.pygments.lexers.esoteric', 'Redcode', ('redcode',), ('*.cw',), ()), 'RegeditLexer': ('pip._vendor.pygments.lexers.configs', 'reg', ('registry',), ('*.reg',), ('text/x-windows-registry',)), - 'RegoLexer': ('pip._vendor.pygments.lexers.rego', 'Rego', ('rego',), ('*.rego',), ('text/x-rego',)), 'ResourceLexer': ('pip._vendor.pygments.lexers.resource', 'ResourceBundle', ('resourcebundle', 'resource'), (), ()), 'RexxLexer': ('pip._vendor.pygments.lexers.scripting', 'Rexx', ('rexx', 'arexx'), ('*.rexx', '*.rex', '*.rx', '*.arexx'), ('text/x-rexx',)), 'RhtmlLexer': ('pip._vendor.pygments.lexers.templates', 'RHTML', ('rhtml', 'html+erb', 'html+ruby'), ('*.rhtml',), ('text/html+ruby',)), @@ -489,7 +457,6 @@ 'SnobolLexer': ('pip._vendor.pygments.lexers.snobol', 'Snobol', ('snobol',), ('*.snobol',), ('text/x-snobol',)), 'SnowballLexer': ('pip._vendor.pygments.lexers.dsls', 'Snowball', ('snowball',), ('*.sbl',), ()), 'SolidityLexer': ('pip._vendor.pygments.lexers.solidity', 'Solidity', ('solidity',), ('*.sol',), ()), - 'SoongLexer': ('pip._vendor.pygments.lexers.soong', 'Soong', ('androidbp', 'bp', 'soong'), ('Android.bp',), ()), 'SophiaLexer': ('pip._vendor.pygments.lexers.sophia', 'Sophia', ('sophia',), ('*.aes',), ()), 'SourcePawnLexer': ('pip._vendor.pygments.lexers.pawn', 'SourcePawn', ('sp',), ('*.sp',), ('text/x-sourcepawn',)), 'SourcesListLexer': ('pip._vendor.pygments.lexers.installers', 'Debian Sourcelist', ('debsources', 'sourceslist', 'sources.list'), ('sources.list',), ()), @@ -507,12 +474,9 @@ 'SwiftLexer': ('pip._vendor.pygments.lexers.objective', 'Swift', ('swift',), ('*.swift',), ('text/x-swift',)), 'SwigLexer': ('pip._vendor.pygments.lexers.c_like', 'SWIG', ('swig',), ('*.swg', '*.i'), ('text/swig',)), 'SystemVerilogLexer': ('pip._vendor.pygments.lexers.hdl', 'systemverilog', ('systemverilog', 'sv'), ('*.sv', '*.svh'), ('text/x-systemverilog',)), - 'SystemdLexer': ('pip._vendor.pygments.lexers.configs', 'Systemd', ('systemd',), ('*.service', '*.socket', '*.device', '*.mount', '*.automount', '*.swap', '*.target', '*.path', '*.timer', '*.slice', '*.scope'), ()), 'TAPLexer': ('pip._vendor.pygments.lexers.testing', 'TAP', ('tap',), ('*.tap',), ()), 'TNTLexer': ('pip._vendor.pygments.lexers.tnt', 'Typographic Number Theory', ('tnt',), ('*.tnt',), ()), - 'TOMLLexer': ('pip._vendor.pygments.lexers.configs', 'TOML', ('toml',), ('*.toml', 'Pipfile', 'poetry.lock'), ('application/toml',)), - 'TableGenLexer': ('pip._vendor.pygments.lexers.tablegen', 'TableGen', ('tablegen', 'td'), ('*.td',), ()), - 'TactLexer': ('pip._vendor.pygments.lexers.tact', 'Tact', ('tact',), ('*.tact',), ()), + 'TOMLLexer': ('pip._vendor.pygments.lexers.configs', 'TOML', ('toml',), ('*.toml', 'Pipfile', 'poetry.lock'), ()), 'Tads3Lexer': ('pip._vendor.pygments.lexers.int_fiction', 'TADS 3', ('tads3',), ('*.t',), ()), 'TalLexer': ('pip._vendor.pygments.lexers.tal', 'Tal', ('tal', 'uxntal'), ('*.tal',), ('text/x-uxntal',)), 'TasmLexer': ('pip._vendor.pygments.lexers.asm', 'TASM', ('tasm',), ('*.asm', '*.ASM', '*.tasm'), ('text/x-tasm',)), @@ -524,18 +488,16 @@ 'TeraTermLexer': ('pip._vendor.pygments.lexers.teraterm', 'Tera Term macro', ('teratermmacro', 'teraterm', 'ttl'), ('*.ttl',), ('text/x-teratermmacro',)), 'TermcapLexer': ('pip._vendor.pygments.lexers.configs', 'Termcap', ('termcap',), ('termcap', 'termcap.src'), ()), 'TerminfoLexer': ('pip._vendor.pygments.lexers.configs', 'Terminfo', ('terminfo',), ('terminfo', 'terminfo.src'), ()), - 'TerraformLexer': ('pip._vendor.pygments.lexers.configs', 'Terraform', ('terraform', 'tf', 'hcl'), ('*.tf', '*.hcl'), ('application/x-tf', 'application/x-terraform')), + 'TerraformLexer': ('pip._vendor.pygments.lexers.configs', 'Terraform', ('terraform', 'tf'), ('*.tf',), ('application/x-tf', 'application/x-terraform')), 'TexLexer': ('pip._vendor.pygments.lexers.markup', 'TeX', ('tex', 'latex'), ('*.tex', '*.aux', '*.toc'), ('text/x-tex', 'text/x-latex')), 'TextLexer': ('pip._vendor.pygments.lexers.special', 'Text only', ('text',), ('*.txt',), ('text/plain',)), 'ThingsDBLexer': ('pip._vendor.pygments.lexers.thingsdb', 'ThingsDB', ('ti', 'thingsdb'), ('*.ti',), ()), 'ThriftLexer': ('pip._vendor.pygments.lexers.dsls', 'Thrift', ('thrift',), ('*.thrift',), ('application/x-thrift',)), 'TiddlyWiki5Lexer': ('pip._vendor.pygments.lexers.markup', 'tiddler', ('tid',), ('*.tid',), ('text/vnd.tiddlywiki',)), 'TlbLexer': ('pip._vendor.pygments.lexers.tlb', 'Tl-b', ('tlb',), ('*.tlb',), ()), - 'TlsLexer': ('pip._vendor.pygments.lexers.tls', 'TLS Presentation Language', ('tls',), (), ()), 'TodotxtLexer': ('pip._vendor.pygments.lexers.textfmts', 'Todotxt', ('todotxt',), ('todo.txt', '*.todotxt'), ('text/x-todo',)), 'TransactSqlLexer': ('pip._vendor.pygments.lexers.sql', 'Transact-SQL', ('tsql', 't-sql'), ('*.sql',), ('text/x-tsql',)), 'TreetopLexer': ('pip._vendor.pygments.lexers.parsers', 'Treetop', ('treetop',), ('*.treetop', '*.tt'), ()), - 'TsxLexer': ('pip._vendor.pygments.lexers.jsx', 'TSX', ('tsx',), ('*.tsx',), ('text/typescript-tsx',)), 'TurtleLexer': ('pip._vendor.pygments.lexers.rdf', 'Turtle', ('turtle',), ('*.ttl',), ('text/turtle', 'application/x-turtle')), 'TwigHtmlLexer': ('pip._vendor.pygments.lexers.templates', 'HTML+Twig', ('html+twig',), ('*.twig',), ('text/html+twig',)), 'TwigLexer': ('pip._vendor.pygments.lexers.templates', 'Twig', ('twig',), (), ('application/x-twig',)), @@ -543,13 +505,11 @@ 'TypoScriptCssDataLexer': ('pip._vendor.pygments.lexers.typoscript', 'TypoScriptCssData', ('typoscriptcssdata',), (), ()), 'TypoScriptHtmlDataLexer': ('pip._vendor.pygments.lexers.typoscript', 'TypoScriptHtmlData', ('typoscripthtmldata',), (), ()), 'TypoScriptLexer': ('pip._vendor.pygments.lexers.typoscript', 'TypoScript', ('typoscript',), ('*.typoscript',), ('text/x-typoscript',)), - 'TypstLexer': ('pip._vendor.pygments.lexers.typst', 'Typst', ('typst',), ('*.typ',), ('text/x-typst',)), 'UL4Lexer': ('pip._vendor.pygments.lexers.ul4', 'UL4', ('ul4',), ('*.ul4',), ()), 'UcodeLexer': ('pip._vendor.pygments.lexers.unicon', 'ucode', ('ucode',), ('*.u', '*.u1', '*.u2'), ()), 'UniconLexer': ('pip._vendor.pygments.lexers.unicon', 'Unicon', ('unicon',), ('*.icn',), ('text/unicon',)), 'UnixConfigLexer': ('pip._vendor.pygments.lexers.configs', 'Unix/Linux config files', ('unixconfig', 'linuxconfig'), (), ()), 'UrbiscriptLexer': ('pip._vendor.pygments.lexers.urbi', 'UrbiScript', ('urbiscript',), ('*.u',), ('application/x-urbiscript',)), - 'UrlEncodedLexer': ('pip._vendor.pygments.lexers.html', 'urlencoded', ('urlencoded',), (), ('application/x-www-form-urlencoded',)), 'UsdLexer': ('pip._vendor.pygments.lexers.usd', 'USD', ('usd', 'usda'), ('*.usd', '*.usda'), ()), 'VBScriptLexer': ('pip._vendor.pygments.lexers.basic', 'VBScript', ('vbscript',), ('*.vbs', '*.VBS'), ()), 'VCLLexer': ('pip._vendor.pygments.lexers.varnish', 'VCL', ('vcl',), ('*.vcl',), ('text/x-vclsrc',)), @@ -558,24 +518,17 @@ 'VGLLexer': ('pip._vendor.pygments.lexers.dsls', 'VGL', ('vgl',), ('*.rpf',), ()), 'ValaLexer': ('pip._vendor.pygments.lexers.c_like', 'Vala', ('vala', 'vapi'), ('*.vala', '*.vapi'), ('text/x-vala',)), 'VbNetAspxLexer': ('pip._vendor.pygments.lexers.dotnet', 'aspx-vb', ('aspx-vb',), ('*.aspx', '*.asax', '*.ascx', '*.ashx', '*.asmx', '*.axd'), ()), - 'VbNetLexer': ('pip._vendor.pygments.lexers.dotnet', 'VB.net', ('vb.net', 'vbnet', 'lobas', 'oobas', 'sobas', 'visual-basic', 'visualbasic'), ('*.vb', '*.bas'), ('text/x-vbnet', 'text/x-vba')), + 'VbNetLexer': ('pip._vendor.pygments.lexers.dotnet', 'VB.net', ('vb.net', 'vbnet', 'lobas', 'oobas', 'sobas'), ('*.vb', '*.bas'), ('text/x-vbnet', 'text/x-vba')), 'VelocityHtmlLexer': ('pip._vendor.pygments.lexers.templates', 'HTML+Velocity', ('html+velocity',), (), ('text/html+velocity',)), 'VelocityLexer': ('pip._vendor.pygments.lexers.templates', 'Velocity', ('velocity',), ('*.vm', '*.fhtml'), ()), 'VelocityXmlLexer': ('pip._vendor.pygments.lexers.templates', 'XML+Velocity', ('xml+velocity',), (), ('application/xml+velocity',)), - 'VerifpalLexer': ('pip._vendor.pygments.lexers.verifpal', 'Verifpal', ('verifpal',), ('*.vp',), ('text/x-verifpal',)), 'VerilogLexer': ('pip._vendor.pygments.lexers.hdl', 'verilog', ('verilog', 'v'), ('*.v',), ('text/x-verilog',)), 'VhdlLexer': ('pip._vendor.pygments.lexers.hdl', 'vhdl', ('vhdl',), ('*.vhdl', '*.vhd'), ('text/x-vhdl',)), 'VimLexer': ('pip._vendor.pygments.lexers.textedit', 'VimL', ('vim',), ('*.vim', '.vimrc', '.exrc', '.gvimrc', '_vimrc', '_exrc', '_gvimrc', 'vimrc', 'gvimrc'), ('text/x-vim',)), - 'VisualPrologGrammarLexer': ('pip._vendor.pygments.lexers.vip', 'Visual Prolog Grammar', ('visualprologgrammar',), ('*.vipgrm',), ()), - 'VisualPrologLexer': ('pip._vendor.pygments.lexers.vip', 'Visual Prolog', ('visualprolog',), ('*.pro', '*.cl', '*.i', '*.pack', '*.ph'), ()), - 'VueLexer': ('pip._vendor.pygments.lexers.html', 'Vue', ('vue',), ('*.vue',), ()), - 'VyperLexer': ('pip._vendor.pygments.lexers.vyper', 'Vyper', ('vyper',), ('*.vy',), ()), 'WDiffLexer': ('pip._vendor.pygments.lexers.diff', 'WDiff', ('wdiff',), ('*.wdiff',), ()), 'WatLexer': ('pip._vendor.pygments.lexers.webassembly', 'WebAssembly', ('wast', 'wat'), ('*.wat', '*.wast'), ()), 'WebIDLLexer': ('pip._vendor.pygments.lexers.webidl', 'Web IDL', ('webidl',), ('*.webidl',), ()), - 'WgslLexer': ('pip._vendor.pygments.lexers.wgsl', 'WebGPU Shading Language', ('wgsl',), ('*.wgsl',), ('text/wgsl',)), 'WhileyLexer': ('pip._vendor.pygments.lexers.whiley', 'Whiley', ('whiley',), ('*.whiley',), ('text/x-whiley',)), - 'WikitextLexer': ('pip._vendor.pygments.lexers.markup', 'Wikitext', ('wikitext', 'mediawiki'), (), ('text/x-wiki',)), 'WoWTocLexer': ('pip._vendor.pygments.lexers.wowtoc', 'World of Warcraft TOC', ('wowtoc',), ('*.toc',), ()), 'WrenLexer': ('pip._vendor.pygments.lexers.wren', 'Wren', ('wren',), ('*.wren',), ()), 'X10Lexer': ('pip._vendor.pygments.lexers.x10', 'X10', ('x10', 'xten'), ('*.x10',), ('text/x-x10',)), @@ -587,14 +540,12 @@ 'XmlPhpLexer': ('pip._vendor.pygments.lexers.templates', 'XML+PHP', ('xml+php',), (), ('application/xml+php',)), 'XmlSmartyLexer': ('pip._vendor.pygments.lexers.templates', 'XML+Smarty', ('xml+smarty',), (), ('application/xml+smarty',)), 'XorgLexer': ('pip._vendor.pygments.lexers.xorg', 'Xorg', ('xorg.conf',), ('xorg.conf',), ()), - 'XppLexer': ('pip._vendor.pygments.lexers.dotnet', 'X++', ('xpp', 'x++'), ('*.xpp',), ()), 'XsltLexer': ('pip._vendor.pygments.lexers.html', 'XSLT', ('xslt',), ('*.xsl', '*.xslt', '*.xpl'), ('application/xsl+xml', 'application/xslt+xml')), 'XtendLexer': ('pip._vendor.pygments.lexers.jvm', 'Xtend', ('xtend',), ('*.xtend',), ('text/x-xtend',)), 'XtlangLexer': ('pip._vendor.pygments.lexers.lisp', 'xtlang', ('extempore',), ('*.xtm',), ()), 'YamlJinjaLexer': ('pip._vendor.pygments.lexers.templates', 'YAML+Jinja', ('yaml+jinja', 'salt', 'sls'), ('*.sls', '*.yaml.j2', '*.yml.j2', '*.yaml.jinja2', '*.yml.jinja2'), ('text/x-yaml+jinja', 'text/x-sls')), 'YamlLexer': ('pip._vendor.pygments.lexers.data', 'YAML', ('yaml',), ('*.yaml', '*.yml'), ('text/x-yaml',)), 'YangLexer': ('pip._vendor.pygments.lexers.yang', 'YANG', ('yang',), ('*.yang',), ('application/yang',)), - 'YaraLexer': ('pip._vendor.pygments.lexers.yara', 'YARA', ('yara', 'yar'), ('*.yar',), ('text/x-yara',)), 'ZeekLexer': ('pip._vendor.pygments.lexers.dsls', 'Zeek', ('zeek', 'bro'), ('*.zeek', '*.bro'), ()), 'ZephirLexer': ('pip._vendor.pygments.lexers.php', 'Zephir', ('zephir',), ('*.zep',), ()), 'ZigLexer': ('pip._vendor.pygments.lexers.zig', 'Zig', ('zig',), ('*.zig',), ('text/zig',)), diff --git a/venv1/Lib/site-packages/pip/_vendor/pygments/lexers/python.py b/venv1/Lib/site-packages/pip/_vendor/pygments/lexers/python.py index 1b788296..3341a382 100644 --- a/venv1/Lib/site-packages/pip/_vendor/pygments/lexers/python.py +++ b/venv1/Lib/site-packages/pip/_vendor/pygments/lexers/python.py @@ -4,14 +4,15 @@ Lexers for Python and related languages. - :copyright: Copyright 2006-2025 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ +import re import keyword -from pip._vendor.pygments.lexer import DelegatingLexer, RegexLexer, include, \ - bygroups, using, default, words, combined, this +from pip._vendor.pygments.lexer import Lexer, RegexLexer, include, bygroups, using, \ + default, words, combined, do_insertions, this, line_re from pip._vendor.pygments.util import get_bool_opt, shebang_matches from pip._vendor.pygments.token import Text, Comment, Operator, Keyword, Name, String, \ Number, Punctuation, Generic, Other, Error, Whitespace @@ -26,14 +27,16 @@ class PythonLexer(RegexLexer): """ For Python source code (version 3.x). + .. versionadded:: 0.10 + .. versionchanged:: 2.5 This is now the default ``PythonLexer``. It is still available as the alias ``Python3Lexer``. """ name = 'Python' - url = 'https://www.python.org' - aliases = ['python', 'py', 'sage', 'python3', 'py3', 'bazel', 'starlark', 'pyi'] + url = 'http://www.python.org' + aliases = ['python', 'py', 'sage', 'python3', 'py3'] filenames = [ '*.py', '*.pyw', @@ -58,9 +61,8 @@ class PythonLexer(RegexLexer): ] mimetypes = ['text/x-python', 'application/x-python', 'text/x-python3', 'application/x-python3'] - version_added = '0.10' - uni_name = f"[{uni.xid_start}][{uni.xid_continue}]*" + uni_name = "[%s][%s]*" % (uni.xid_start, uni.xid_continue) def innerstring_rules(ttype): return [ @@ -109,11 +111,11 @@ def fstring_rules(ttype): (r'\\', Text), include('keywords'), include('soft-keywords'), - (r'(def)((?:\s|\\\s)+)', bygroups(Keyword, Whitespace), 'funcname'), - (r'(class)((?:\s|\\\s)+)', bygroups(Keyword, Whitespace), 'classname'), - (r'(from)((?:\s|\\\s)+)', bygroups(Keyword.Namespace, Whitespace), + (r'(def)((?:\s|\\\s)+)', bygroups(Keyword, Text), 'funcname'), + (r'(class)((?:\s|\\\s)+)', bygroups(Keyword, Text), 'classname'), + (r'(from)((?:\s|\\\s)+)', bygroups(Keyword.Namespace, Text), 'fromimport'), - (r'(import)((?:\s|\\\s)+)', bygroups(Keyword.Namespace, Whitespace), + (r'(import)((?:\s|\\\s)+)', bygroups(Keyword.Namespace, Text), 'import'), include('expr'), ], @@ -222,8 +224,7 @@ def fstring_rules(ttype): r'(match|case)\b' # a possible keyword r'(?![ \t]*(?:' # not followed by... r'[:,;=^&|@~)\]}]|(?:' + # characters and keywords that mean this isn't - # pattern matching (but None/True/False is ok) - r'|'.join(k for k in keyword.kwlist if k[0].islower()) + r')\b))', + r'|'.join(keyword.kwlist) + r')\b))', # pattern matching bygroups(Text, Keyword), 'soft-keywords-inner'), ], 'soft-keywords-inner': [ @@ -233,16 +234,16 @@ def fstring_rules(ttype): ], 'builtins': [ (words(( - '__import__', 'abs', 'aiter', 'all', 'any', 'bin', 'bool', 'bytearray', - 'breakpoint', 'bytes', 'callable', 'chr', 'classmethod', 'compile', - 'complex', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', - 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', - 'hasattr', 'hash', 'hex', 'id', 'input', 'int', 'isinstance', - 'issubclass', 'iter', 'len', 'list', 'locals', 'map', 'max', - 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', - 'print', 'property', 'range', 'repr', 'reversed', 'round', 'set', - 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', - 'tuple', 'type', 'vars', 'zip'), prefix=r'(?>|[-~+/*%=<>&^|.]', Operator), include('keywords'), - (r'(def)((?:\s|\\\s)+)', bygroups(Keyword, Whitespace), 'funcname'), - (r'(class)((?:\s|\\\s)+)', bygroups(Keyword, Whitespace), 'classname'), - (r'(from)((?:\s|\\\s)+)', bygroups(Keyword.Namespace, Whitespace), + (r'(def)((?:\s|\\\s)+)', bygroups(Keyword, Text), 'funcname'), + (r'(class)((?:\s|\\\s)+)', bygroups(Keyword, Text), 'classname'), + (r'(from)((?:\s|\\\s)+)', bygroups(Keyword.Namespace, Text), 'fromimport'), - (r'(import)((?:\s|\\\s)+)', bygroups(Keyword.Namespace, Whitespace), + (r'(import)((?:\s|\\\s)+)', bygroups(Keyword.Namespace, Text), 'import'), include('builtins'), include('magicfuncs'), @@ -636,51 +636,14 @@ def analyse_text(text): return shebang_matches(text, r'pythonw?2(\.\d)?') -class _PythonConsoleLexerBase(RegexLexer): - name = 'Python console session' - aliases = ['pycon', 'python-console'] - mimetypes = ['text/x-python-doctest'] - - """Auxiliary lexer for `PythonConsoleLexer`. - - Code tokens are output as ``Token.Other.Code``, traceback tokens as - ``Token.Other.Traceback``. - """ - tokens = { - 'root': [ - (r'(>>> )(.*\n)', bygroups(Generic.Prompt, Other.Code), 'continuations'), - # This happens, e.g., when tracebacks are embedded in documentation; - # trailing whitespaces are often stripped in such contexts. - (r'(>>>)(\n)', bygroups(Generic.Prompt, Whitespace)), - (r'(\^C)?Traceback \(most recent call last\):\n', Other.Traceback, 'traceback'), - # SyntaxError starts with this - (r' File "[^"]+", line \d+', Other.Traceback, 'traceback'), - (r'.*\n', Generic.Output), - ], - 'continuations': [ - (r'(\.\.\. )(.*\n)', bygroups(Generic.Prompt, Other.Code)), - # See above. - (r'(\.\.\.)(\n)', bygroups(Generic.Prompt, Whitespace)), - default('#pop'), - ], - 'traceback': [ - # As soon as we see a traceback, consume everything until the next - # >>> prompt. - (r'(?=>>>( |$))', Text, '#pop'), - (r'(KeyboardInterrupt)(\n)', bygroups(Name.Class, Whitespace)), - (r'.*\n', Other.Traceback), - ], - } - - -class PythonConsoleLexer(DelegatingLexer): +class PythonConsoleLexer(Lexer): """ For Python console output or doctests, such as: .. sourcecode:: pycon >>> a = 'foo' - >>> print(a) + >>> print a foo >>> 1 / 0 Traceback (most recent call last): @@ -696,36 +659,77 @@ class PythonConsoleLexer(DelegatingLexer): .. versionchanged:: 2.5 Now defaults to ``True``. """ - name = 'Python console session' - aliases = ['pycon', 'python-console'] + aliases = ['pycon'] mimetypes = ['text/x-python-doctest'] - url = 'https://python.org' - version_added = '' def __init__(self, **options): - python3 = get_bool_opt(options, 'python3', True) - if python3: - pylexer = PythonLexer - tblexer = PythonTracebackLexer + self.python3 = get_bool_opt(options, 'python3', True) + Lexer.__init__(self, **options) + + def get_tokens_unprocessed(self, text): + if self.python3: + pylexer = PythonLexer(**self.options) + tblexer = PythonTracebackLexer(**self.options) else: - pylexer = Python2Lexer - tblexer = Python2TracebackLexer - # We have two auxiliary lexers. Use DelegatingLexer twice with - # different tokens. TODO: DelegatingLexer should support this - # directly, by accepting a tuplet of auxiliary lexers and a tuple of - # distinguishing tokens. Then we wouldn't need this intermediary - # class. - class _ReplaceInnerCode(DelegatingLexer): - def __init__(self, **options): - super().__init__(pylexer, _PythonConsoleLexerBase, Other.Code, **options) - super().__init__(tblexer, _ReplaceInnerCode, Other.Traceback, **options) + pylexer = Python2Lexer(**self.options) + tblexer = Python2TracebackLexer(**self.options) + + curcode = '' + insertions = [] + curtb = '' + tbindex = 0 + tb = 0 + for match in line_re.finditer(text): + line = match.group() + if line.startswith('>>> ') or line.startswith('... '): + tb = 0 + insertions.append((len(curcode), + [(0, Generic.Prompt, line[:4])])) + curcode += line[4:] + elif line.rstrip() == '...' and not tb: + # only a new >>> prompt can end an exception block + # otherwise an ellipsis in place of the traceback frames + # will be mishandled + insertions.append((len(curcode), + [(0, Generic.Prompt, '...')])) + curcode += line[3:] + else: + if curcode: + yield from do_insertions( + insertions, pylexer.get_tokens_unprocessed(curcode)) + curcode = '' + insertions = [] + if (line.startswith('Traceback (most recent call last):') or + re.match(' File "[^"]+", line \\d+\\n$', line)): + tb = 1 + curtb = line + tbindex = match.start() + elif line == 'KeyboardInterrupt\n': + yield match.start(), Name.Class, line + elif tb: + curtb += line + if not (line.startswith(' ') or line.strip() == '...'): + tb = 0 + for i, t, v in tblexer.get_tokens_unprocessed(curtb): + yield tbindex+i, t, v + curtb = '' + else: + yield match.start(), Generic.Output, line + if curcode: + yield from do_insertions(insertions, + pylexer.get_tokens_unprocessed(curcode)) + if curtb: + for i, t, v in tblexer.get_tokens_unprocessed(curtb): + yield tbindex+i, t, v class PythonTracebackLexer(RegexLexer): """ For Python 3.x tracebacks, with support for chained exceptions. + .. versionadded:: 1.0 + .. versionchanged:: 2.5 This is now the default ``PythonTracebackLexer``. It is still available as the alias ``Python3TracebackLexer``. @@ -735,13 +739,11 @@ class PythonTracebackLexer(RegexLexer): aliases = ['pytb', 'py3tb'] filenames = ['*.pytb', '*.py3tb'] mimetypes = ['text/x-python-traceback', 'text/x-python3-traceback'] - url = 'https://python.org' - version_added = '1.0' tokens = { 'root': [ (r'\n', Whitespace), - (r'^(\^C)?Traceback \(most recent call last\):\n', Generic.Traceback, 'intb'), + (r'^Traceback \(most recent call last\):\n', Generic.Traceback, 'intb'), (r'^During handling of the above exception, another ' r'exception occurred:\n\n', Generic.Traceback), (r'^The above exception was the direct cause of the ' @@ -761,8 +763,7 @@ class PythonTracebackLexer(RegexLexer): (r'^([^:]+)(: )(.+)(\n)', bygroups(Generic.Error, Text, Name, Whitespace), '#pop'), (r'^([a-zA-Z_][\w.]*)(:?\n)', - bygroups(Generic.Error, Whitespace), '#pop'), - default('#pop'), + bygroups(Generic.Error, Whitespace), '#pop') ], 'markers': [ # Either `PEP 657 ` @@ -783,6 +784,8 @@ class Python2TracebackLexer(RegexLexer): """ For Python tracebacks. + .. versionadded:: 0.7 + .. versionchanged:: 2.5 This class has been renamed from ``PythonTracebackLexer``. ``PythonTracebackLexer`` now refers to the Python 3 variant. @@ -792,8 +795,6 @@ class Python2TracebackLexer(RegexLexer): aliases = ['py2tb'] filenames = ['*.py2tb'] mimetypes = ['text/x-python2-traceback'] - url = 'https://python.org' - version_added = '0.7' tokens = { 'root': [ @@ -830,14 +831,15 @@ class Python2TracebackLexer(RegexLexer): class CythonLexer(RegexLexer): """ For Pyrex and Cython source code. + + .. versionadded:: 1.1 """ name = 'Cython' - url = 'https://cython.org' + url = 'http://cython.org' aliases = ['cython', 'pyx', 'pyrex'] filenames = ['*.pyx', '*.pxd', '*.pxi'] mimetypes = ['text/x-cython', 'application/x-cython'] - version_added = '1.1' tokens = { 'root': [ @@ -854,16 +856,16 @@ class CythonLexer(RegexLexer): bygroups(Punctuation, Keyword.Type, Punctuation)), (r'!=|==|<<|>>|[-~+/*%=<>&^|.?]', Operator), (r'(from)(\d+)(<=)(\s+)(<)(\d+)(:)', - bygroups(Keyword, Number.Integer, Operator, Whitespace, Operator, + bygroups(Keyword, Number.Integer, Operator, Name, Operator, Name, Punctuation)), include('keywords'), - (r'(def|property)(\s+)', bygroups(Keyword, Whitespace), 'funcname'), - (r'(cp?def)(\s+)', bygroups(Keyword, Whitespace), 'cdef'), + (r'(def|property)(\s+)', bygroups(Keyword, Text), 'funcname'), + (r'(cp?def)(\s+)', bygroups(Keyword, Text), 'cdef'), # (should actually start a block with only cdefs) (r'(cdef)(:)', bygroups(Keyword, Punctuation)), - (r'(class|struct)(\s+)', bygroups(Keyword, Whitespace), 'classname'), - (r'(from)(\s+)', bygroups(Keyword, Whitespace), 'fromimport'), - (r'(c?import)(\s+)', bygroups(Keyword, Whitespace), 'import'), + (r'(class|struct)(\s+)', bygroups(Keyword, Text), 'classname'), + (r'(from)(\s+)', bygroups(Keyword, Text), 'fromimport'), + (r'(c?import)(\s+)', bygroups(Keyword, Text), 'import'), include('builtins'), include('backtick'), ('(?:[rR]|[uU][rR]|[rR][uU])"""', String, 'tdqs'), @@ -941,9 +943,9 @@ class CythonLexer(RegexLexer): (r'(public|readonly|extern|api|inline)\b', Keyword.Reserved), (r'(struct|enum|union|class)\b', Keyword), (r'([a-zA-Z_]\w*)(\s*)(?=[(:#=]|$)', - bygroups(Name.Function, Whitespace), '#pop'), + bygroups(Name.Function, Text), '#pop'), (r'([a-zA-Z_]\w*)(\s*)(,)', - bygroups(Name.Function, Whitespace, Punctuation)), + bygroups(Name.Function, Text, Punctuation)), (r'from\b', Keyword, '#pop'), (r'as\b', Keyword), (r':', Punctuation, '#pop'), @@ -955,13 +957,13 @@ class CythonLexer(RegexLexer): (r'[a-zA-Z_]\w*', Name.Class, '#pop') ], 'import': [ - (r'(\s+)(as)(\s+)', bygroups(Whitespace, Keyword, Whitespace)), + (r'(\s+)(as)(\s+)', bygroups(Text, Keyword, Text)), (r'[a-zA-Z_][\w.]*', Name.Namespace), - (r'(\s*)(,)(\s*)', bygroups(Whitespace, Operator, Whitespace)), + (r'(\s*)(,)(\s*)', bygroups(Text, Operator, Text)), default('#pop') # all else: go back ], 'fromimport': [ - (r'(\s+)(c?import)\b', bygroups(Whitespace, Keyword), '#pop'), + (r'(\s+)(c?import)\b', bygroups(Text, Keyword), '#pop'), (r'[a-zA-Z_.][\w.]*', Name.Namespace), # ``cdef foo from "header"``, or ``for foo from 0 < i < 10`` default('#pop'), @@ -1011,13 +1013,13 @@ class DgLexer(RegexLexer): Lexer for dg, a functional and object-oriented programming language running on the CPython 3 VM. + + .. versionadded:: 1.6 """ name = 'dg' aliases = ['dg'] filenames = ['*.dg'] mimetypes = ['text/x-dg'] - url = 'http://pyos.github.io/dg' - version_added = '1.6' tokens = { 'root': [ @@ -1108,12 +1110,13 @@ class DgLexer(RegexLexer): class NumPyLexer(PythonLexer): """ A Python lexer recognizing Numerical Python builtins. + + .. versionadded:: 0.10 """ name = 'NumPy' url = 'https://numpy.org/' aliases = ['numpy'] - version_added = '0.10' # override the mimetypes to not inherit them from python mimetypes = [] diff --git a/venv1/Lib/site-packages/pip/_vendor/pygments/modeline.py b/venv1/Lib/site-packages/pip/_vendor/pygments/modeline.py index c310f0ed..43630835 100644 --- a/venv1/Lib/site-packages/pip/_vendor/pygments/modeline.py +++ b/venv1/Lib/site-packages/pip/_vendor/pygments/modeline.py @@ -4,7 +4,7 @@ A simple modeline parser (based on pymodeline). - :copyright: Copyright 2006-2025 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -19,7 +19,7 @@ ''', re.VERBOSE) -def get_filetype_from_line(l): # noqa: E741 +def get_filetype_from_line(l): m = modeline_re.search(l) if m: return m.group(1) @@ -30,8 +30,8 @@ def get_filetype_from_buffer(buf, max_lines=5): Scan the buffer for modelines and return filetype if one is found. """ lines = buf.splitlines() - for line in lines[-1:-max_lines-1:-1]: - ret = get_filetype_from_line(line) + for l in lines[-1:-max_lines-1:-1]: + ret = get_filetype_from_line(l) if ret: return ret for i in range(max_lines, -1, -1): diff --git a/venv1/Lib/site-packages/pip/_vendor/pygments/plugin.py b/venv1/Lib/site-packages/pip/_vendor/pygments/plugin.py index 498db423..3590bee8 100644 --- a/venv1/Lib/site-packages/pip/_vendor/pygments/plugin.py +++ b/venv1/Lib/site-packages/pip/_vendor/pygments/plugin.py @@ -2,7 +2,12 @@ pygments.plugin ~~~~~~~~~~~~~~~ - Pygments plugin interface. + Pygments plugin interface. By default, this tries to use + ``importlib.metadata``, which is in the Python standard + library since Python 3.8, or its ``importlib_metadata`` + backport for earlier versions of Python. It falls back on + ``pkg_resources`` if not found. Finally, if ``pkg_resources`` + is not found either, no plugins are loaded at all. lexer plugins:: @@ -29,10 +34,9 @@ yourfilter = yourfilter:YourFilter - :copyright: Copyright 2006-2025 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ -from importlib.metadata import entry_points LEXER_ENTRY_POINT = 'pygments.lexers' FORMATTER_ENTRY_POINT = 'pygments.formatters' @@ -41,6 +45,18 @@ def iter_entry_points(group_name): + try: + from importlib.metadata import entry_points + except ImportError: + try: + from importlib_metadata import entry_points + except ImportError: + try: + from pip._vendor.pkg_resources import iter_entry_points + except (ImportError, OSError): + return [] + else: + return iter_entry_points(group_name) groups = entry_points() if hasattr(groups, 'select'): # New interface in Python 3.10 and newer versions of the diff --git a/venv1/Lib/site-packages/pip/_vendor/pygments/regexopt.py b/venv1/Lib/site-packages/pip/_vendor/pygments/regexopt.py index cc8d2c31..ae007919 100644 --- a/venv1/Lib/site-packages/pip/_vendor/pygments/regexopt.py +++ b/venv1/Lib/site-packages/pip/_vendor/pygments/regexopt.py @@ -5,7 +5,7 @@ An algorithm that generates optimized regexes for matching long lists of literal strings. - :copyright: Copyright 2006-2025 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/venv1/Lib/site-packages/pip/_vendor/pygments/scanner.py b/venv1/Lib/site-packages/pip/_vendor/pygments/scanner.py index 3c8c8487..d47ed482 100644 --- a/venv1/Lib/site-packages/pip/_vendor/pygments/scanner.py +++ b/venv1/Lib/site-packages/pip/_vendor/pygments/scanner.py @@ -11,7 +11,7 @@ Have a look at the `DelphiLexer` to get an idea of how to use this scanner. - :copyright: Copyright 2006-2025 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ import re diff --git a/venv1/Lib/site-packages/pip/_vendor/pygments/sphinxext.py b/venv1/Lib/site-packages/pip/_vendor/pygments/sphinxext.py index 955d9584..3537ecdb 100644 --- a/venv1/Lib/site-packages/pip/_vendor/pygments/sphinxext.py +++ b/venv1/Lib/site-packages/pip/_vendor/pygments/sphinxext.py @@ -5,7 +5,7 @@ Sphinx extension to generate automatic documentation of lexers, formatters and filters. - :copyright: Copyright 2006-2025 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -33,8 +33,6 @@ %s - %s - ''' FMTERDOC = ''' @@ -121,11 +119,11 @@ def format_link(name, url): def write_row(*columns): """Format a table row""" out = [] - for length, col in zip(column_lengths, columns): - if col: - out.append(col.ljust(length)) + for l, c in zip(column_lengths, columns): + if c: + out.append(c.ljust(l)) else: - out.append(' '*length) + out.append(' '*l) return ' '.join(out) @@ -149,10 +147,6 @@ def write_seperator(): def document_lexers(self): from pip._vendor.pygments.lexers._mapping import LEXERS - from pip._vendor import pygments - import inspect - import pathlib - out = [] modules = {} moduledocstrings = {} @@ -162,40 +156,16 @@ def document_lexers(self): self.filenames.add(mod.__file__) cls = getattr(mod, classname) if not cls.__doc__: - print(f"Warning: {classname} does not have a docstring.") + print("Warning: %s does not have a docstring." % classname) docstring = cls.__doc__ if isinstance(docstring, bytes): docstring = docstring.decode('utf8') - - example_file = getattr(cls, '_example', None) - if example_file: - p = pathlib.Path(inspect.getabsfile(pygments)).parent.parent /\ - 'tests' / 'examplefiles' / example_file - content = p.read_text(encoding='utf-8') - if not content: - raise Exception( - f"Empty example file '{example_file}' for lexer " - f"{classname}") - - if data[2]: - lexer_name = data[2][0] - docstring += '\n\n .. admonition:: Example\n' - docstring += f'\n .. code-block:: {lexer_name}\n\n' - for line in content.splitlines(): - docstring += f' {line}\n' - - if cls.version_added: - version_line = f'.. versionadded:: {cls.version_added}' - else: - version_line = '' - modules.setdefault(module, []).append(( classname, ', '.join(data[2]) or 'None', ', '.join(data[3]).replace('*', '\\*').replace('_', '\\') or 'None', ', '.join(data[4]) or 'None', - docstring, - version_line)) + docstring)) if module not in moduledocstrings: moddoc = mod.__doc__ if isinstance(moddoc, bytes): @@ -204,7 +174,7 @@ def document_lexers(self): for module, lexers in sorted(modules.items(), key=lambda x: x[0]): if moduledocstrings[module] is None: - raise Exception(f"Missing docstring for {module}") + raise Exception("Missing docstring for %s" % (module,)) heading = moduledocstrings[module].splitlines()[4].strip().rstrip('.') out.append(MODULEDOC % (module, heading, '-'*len(heading))) for data in lexers: diff --git a/venv1/Lib/site-packages/pip/_vendor/pygments/style.py b/venv1/Lib/site-packages/pip/_vendor/pygments/style.py index be5f8322..84abbc20 100644 --- a/venv1/Lib/site-packages/pip/_vendor/pygments/style.py +++ b/venv1/Lib/site-packages/pip/_vendor/pygments/style.py @@ -4,7 +4,7 @@ Basic style object. - :copyright: Copyright 2006-2025 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -76,7 +76,7 @@ def colorformat(text): return '' elif text.startswith('var') or text.startswith('calc'): return text - assert False, f"wrong color format {text!r}" + assert False, "wrong color format %r" % text _styles = obj._styles = {} @@ -190,12 +190,6 @@ class Style(metaclass=StyleMeta): #: Style definitions for individual token types. styles = {} - #: user-friendly style name (used when selecting the style, so this - # should be all-lowercase, no spaces, hyphens) - name = 'unnamed' - - aliases = [] - # Attribute for lexers defined within Pygments. If set # to True, the style is not shown in the style gallery # on the website. This is intended for language-specific diff --git a/venv1/Lib/site-packages/pip/_vendor/pygments/styles/__init__.py b/venv1/Lib/site-packages/pip/_vendor/pygments/styles/__init__.py index 96d53dce..44cc0efb 100644 --- a/venv1/Lib/site-packages/pip/_vendor/pygments/styles/__init__.py +++ b/venv1/Lib/site-packages/pip/_vendor/pygments/styles/__init__.py @@ -4,33 +4,70 @@ Contains built-in styles. - :copyright: Copyright 2006-2025 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ from pip._vendor.pygments.plugin import find_plugin_styles from pip._vendor.pygments.util import ClassNotFound -from pip._vendor.pygments.styles._mapping import STYLES -#: A dictionary of built-in styles, mapping style names to -#: ``'submodule::classname'`` strings. -#: This list is deprecated. Use `pygments.styles.STYLES` instead -STYLE_MAP = {v[1]: v[0].split('.')[-1] + '::' + k for k, v in STYLES.items()} -#: Internal reverse mapping to make `get_style_by_name` more efficient -_STYLE_NAME_TO_MODULE_MAP = {v[1]: (v[0], k) for k, v in STYLES.items()} +#: Maps style names to 'submodule::classname'. +STYLE_MAP = { + 'default': 'default::DefaultStyle', + 'emacs': 'emacs::EmacsStyle', + 'friendly': 'friendly::FriendlyStyle', + 'friendly_grayscale': 'friendly_grayscale::FriendlyGrayscaleStyle', + 'colorful': 'colorful::ColorfulStyle', + 'autumn': 'autumn::AutumnStyle', + 'murphy': 'murphy::MurphyStyle', + 'manni': 'manni::ManniStyle', + 'material': 'material::MaterialStyle', + 'monokai': 'monokai::MonokaiStyle', + 'perldoc': 'perldoc::PerldocStyle', + 'pastie': 'pastie::PastieStyle', + 'borland': 'borland::BorlandStyle', + 'trac': 'trac::TracStyle', + 'native': 'native::NativeStyle', + 'fruity': 'fruity::FruityStyle', + 'bw': 'bw::BlackWhiteStyle', + 'vim': 'vim::VimStyle', + 'vs': 'vs::VisualStudioStyle', + 'tango': 'tango::TangoStyle', + 'rrt': 'rrt::RrtStyle', + 'xcode': 'xcode::XcodeStyle', + 'igor': 'igor::IgorStyle', + 'paraiso-light': 'paraiso_light::ParaisoLightStyle', + 'paraiso-dark': 'paraiso_dark::ParaisoDarkStyle', + 'lovelace': 'lovelace::LovelaceStyle', + 'algol': 'algol::AlgolStyle', + 'algol_nu': 'algol_nu::Algol_NuStyle', + 'arduino': 'arduino::ArduinoStyle', + 'rainbow_dash': 'rainbow_dash::RainbowDashStyle', + 'abap': 'abap::AbapStyle', + 'solarized-dark': 'solarized::SolarizedDarkStyle', + 'solarized-light': 'solarized::SolarizedLightStyle', + 'sas': 'sas::SasStyle', + 'staroffice' : 'staroffice::StarofficeStyle', + 'stata': 'stata_light::StataLightStyle', + 'stata-light': 'stata_light::StataLightStyle', + 'stata-dark': 'stata_dark::StataDarkStyle', + 'inkpot': 'inkpot::InkPotStyle', + 'zenburn': 'zenburn::ZenburnStyle', + 'gruvbox-dark': 'gruvbox::GruvboxDarkStyle', + 'gruvbox-light': 'gruvbox::GruvboxLightStyle', + 'dracula': 'dracula::DraculaStyle', + 'one-dark': 'onedark::OneDarkStyle', + 'lilypond' : 'lilypond::LilyPondStyle', + 'nord': 'nord::NordStyle', + 'nord-darker': 'nord::NordDarkerStyle', + 'github-dark': 'gh_dark::GhDarkStyle' +} def get_style_by_name(name): - """ - Return a style class by its short name. The names of the builtin styles - are listed in :data:`pygments.styles.STYLE_MAP`. - - Will raise :exc:`pygments.util.ClassNotFound` if no style of that name is - found. - """ - if name in _STYLE_NAME_TO_MODULE_MAP: - mod, cls = _STYLE_NAME_TO_MODULE_MAP[name] + if name in STYLE_MAP: + mod, cls = STYLE_MAP[name].split('::') builtin = "yes" else: for found_name, style in find_plugin_styles(): @@ -38,24 +75,23 @@ def get_style_by_name(name): return style # perhaps it got dropped into our styles package builtin = "" - mod = 'pygments.styles.' + name + mod = name cls = name.title() + "Style" try: - mod = __import__(mod, None, None, [cls]) + mod = __import__('pygments.styles.' + mod, None, None, [cls]) except ImportError: - raise ClassNotFound(f"Could not find style module {mod!r}" + - (builtin and ", though it should be builtin") - + ".") + raise ClassNotFound("Could not find style module %r" % mod + + (builtin and ", though it should be builtin") + ".") try: return getattr(mod, cls) except AttributeError: - raise ClassNotFound(f"Could not find style class {cls!r} in style module.") + raise ClassNotFound("Could not find style class %r in style module." % cls) def get_all_styles(): - """Return a generator for all styles by name, both builtin and plugin.""" - for v in STYLES.values(): - yield v[1] + """Return a generator for all styles by name, + both builtin and plugin.""" + yield from STYLE_MAP for name, _ in find_plugin_styles(): yield name diff --git a/venv1/Lib/site-packages/pip/_vendor/pygments/styles/_mapping.py b/venv1/Lib/site-packages/pip/_vendor/pygments/styles/_mapping.py deleted file mode 100644 index 49a7fae9..00000000 --- a/venv1/Lib/site-packages/pip/_vendor/pygments/styles/_mapping.py +++ /dev/null @@ -1,54 +0,0 @@ -# Automatically generated by scripts/gen_mapfiles.py. -# DO NOT EDIT BY HAND; run `tox -e mapfiles` instead. - -STYLES = { - 'AbapStyle': ('pygments.styles.abap', 'abap', ()), - 'AlgolStyle': ('pygments.styles.algol', 'algol', ()), - 'Algol_NuStyle': ('pygments.styles.algol_nu', 'algol_nu', ()), - 'ArduinoStyle': ('pygments.styles.arduino', 'arduino', ()), - 'AutumnStyle': ('pygments.styles.autumn', 'autumn', ()), - 'BlackWhiteStyle': ('pygments.styles.bw', 'bw', ()), - 'BorlandStyle': ('pygments.styles.borland', 'borland', ()), - 'CoffeeStyle': ('pygments.styles.coffee', 'coffee', ()), - 'ColorfulStyle': ('pygments.styles.colorful', 'colorful', ()), - 'DefaultStyle': ('pygments.styles.default', 'default', ()), - 'DraculaStyle': ('pygments.styles.dracula', 'dracula', ()), - 'EmacsStyle': ('pygments.styles.emacs', 'emacs', ()), - 'FriendlyGrayscaleStyle': ('pygments.styles.friendly_grayscale', 'friendly_grayscale', ()), - 'FriendlyStyle': ('pygments.styles.friendly', 'friendly', ()), - 'FruityStyle': ('pygments.styles.fruity', 'fruity', ()), - 'GhDarkStyle': ('pygments.styles.gh_dark', 'github-dark', ()), - 'GruvboxDarkStyle': ('pygments.styles.gruvbox', 'gruvbox-dark', ()), - 'GruvboxLightStyle': ('pygments.styles.gruvbox', 'gruvbox-light', ()), - 'IgorStyle': ('pygments.styles.igor', 'igor', ()), - 'InkPotStyle': ('pygments.styles.inkpot', 'inkpot', ()), - 'LightbulbStyle': ('pygments.styles.lightbulb', 'lightbulb', ()), - 'LilyPondStyle': ('pygments.styles.lilypond', 'lilypond', ()), - 'LovelaceStyle': ('pygments.styles.lovelace', 'lovelace', ()), - 'ManniStyle': ('pygments.styles.manni', 'manni', ()), - 'MaterialStyle': ('pygments.styles.material', 'material', ()), - 'MonokaiStyle': ('pygments.styles.monokai', 'monokai', ()), - 'MurphyStyle': ('pygments.styles.murphy', 'murphy', ()), - 'NativeStyle': ('pygments.styles.native', 'native', ()), - 'NordDarkerStyle': ('pygments.styles.nord', 'nord-darker', ()), - 'NordStyle': ('pygments.styles.nord', 'nord', ()), - 'OneDarkStyle': ('pygments.styles.onedark', 'one-dark', ()), - 'ParaisoDarkStyle': ('pygments.styles.paraiso_dark', 'paraiso-dark', ()), - 'ParaisoLightStyle': ('pygments.styles.paraiso_light', 'paraiso-light', ()), - 'PastieStyle': ('pygments.styles.pastie', 'pastie', ()), - 'PerldocStyle': ('pygments.styles.perldoc', 'perldoc', ()), - 'RainbowDashStyle': ('pygments.styles.rainbow_dash', 'rainbow_dash', ()), - 'RrtStyle': ('pygments.styles.rrt', 'rrt', ()), - 'SasStyle': ('pygments.styles.sas', 'sas', ()), - 'SolarizedDarkStyle': ('pygments.styles.solarized', 'solarized-dark', ()), - 'SolarizedLightStyle': ('pygments.styles.solarized', 'solarized-light', ()), - 'StarofficeStyle': ('pygments.styles.staroffice', 'staroffice', ()), - 'StataDarkStyle': ('pygments.styles.stata_dark', 'stata-dark', ()), - 'StataLightStyle': ('pygments.styles.stata_light', 'stata-light', ()), - 'TangoStyle': ('pygments.styles.tango', 'tango', ()), - 'TracStyle': ('pygments.styles.trac', 'trac', ()), - 'VimStyle': ('pygments.styles.vim', 'vim', ()), - 'VisualStudioStyle': ('pygments.styles.vs', 'vs', ()), - 'XcodeStyle': ('pygments.styles.xcode', 'xcode', ()), - 'ZenburnStyle': ('pygments.styles.zenburn', 'zenburn', ()), -} diff --git a/venv1/Lib/site-packages/pip/_vendor/pygments/token.py b/venv1/Lib/site-packages/pip/_vendor/pygments/token.py index 2f3b97e0..e3e565ad 100644 --- a/venv1/Lib/site-packages/pip/_vendor/pygments/token.py +++ b/venv1/Lib/site-packages/pip/_vendor/pygments/token.py @@ -4,7 +4,7 @@ Basic token types and the standard tokens. - :copyright: Copyright 2006-2025 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -209,6 +209,5 @@ def string_to_tokentype(s): Generic.Prompt: 'gp', Generic.Strong: 'gs', Generic.Subheading: 'gu', - Generic.EmphStrong: 'ges', Generic.Traceback: 'gt', } diff --git a/venv1/Lib/site-packages/pip/_vendor/pygments/unistring.py b/venv1/Lib/site-packages/pip/_vendor/pygments/unistring.py index e3bd2e72..2e3c8086 100644 --- a/venv1/Lib/site-packages/pip/_vendor/pygments/unistring.py +++ b/venv1/Lib/site-packages/pip/_vendor/pygments/unistring.py @@ -7,7 +7,7 @@ Inspired by chartypes_create.py from the MoinMoin project. - :copyright: Copyright 2006-2025 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -104,7 +104,7 @@ def _handle_runs(char_list): # pragma: no cover if a == b: yield a else: - yield f'{a}-{b}' + yield '%s-%s' % (a, b) if __name__ == '__main__': # pragma: no cover @@ -112,7 +112,7 @@ def _handle_runs(char_list): # pragma: no cover categories = {'xid_start': [], 'xid_continue': []} - with open(__file__, encoding='utf-8') as fp: + with open(__file__) as fp: content = fp.read() header = content[:content.find('Cc =')] @@ -136,18 +136,18 @@ def _handle_runs(char_list): # pragma: no cover if ('a' + c).isidentifier(): categories['xid_continue'].append(c) - with open(__file__, 'w', encoding='utf-8') as fp: + with open(__file__, 'w') as fp: fp.write(header) for cat in sorted(categories): val = ''.join(_handle_runs(categories[cat])) - fp.write(f'{cat} = {val!a}\n\n') + fp.write('%s = %a\n\n' % (cat, val)) cats = sorted(categories) cats.remove('xid_start') cats.remove('xid_continue') - fp.write(f'cats = {cats!r}\n\n') + fp.write('cats = %r\n\n' % cats) - fp.write(f'# Generated from unidata {unicodedata.unidata_version}\n\n') + fp.write('# Generated from unidata %s\n\n' % (unicodedata.unidata_version,)) fp.write(footer) diff --git a/venv1/Lib/site-packages/pip/_vendor/pygments/util.py b/venv1/Lib/site-packages/pip/_vendor/pygments/util.py index 71c5710a..8032962d 100644 --- a/venv1/Lib/site-packages/pip/_vendor/pygments/util.py +++ b/venv1/Lib/site-packages/pip/_vendor/pygments/util.py @@ -4,7 +4,7 @@ Utility functions. - :copyright: Copyright 2006-2025 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -32,79 +32,63 @@ class ClassNotFound(ValueError): class OptionError(Exception): - """ - This exception will be raised by all option processing functions if - the type or value of the argument is not correct. - """ + pass + def get_choice_opt(options, optname, allowed, default=None, normcase=False): - """ - If the key `optname` from the dictionary is not in the sequence - `allowed`, raise an error, otherwise return it. - """ string = options.get(optname, default) if normcase: string = string.lower() if string not in allowed: - raise OptionError('Value for option {} must be one of {}'.format(optname, ', '.join(map(str, allowed)))) + raise OptionError('Value for option %s must be one of %s' % + (optname, ', '.join(map(str, allowed)))) return string def get_bool_opt(options, optname, default=None): - """ - Intuitively, this is `options.get(optname, default)`, but restricted to - Boolean value. The Booleans can be represented as string, in order to accept - Boolean value from the command line arguments. If the key `optname` is - present in the dictionary `options` and is not associated with a Boolean, - raise an `OptionError`. If it is absent, `default` is returned instead. - - The valid string values for ``True`` are ``1``, ``yes``, ``true`` and - ``on``, the ones for ``False`` are ``0``, ``no``, ``false`` and ``off`` - (matched case-insensitively). - """ string = options.get(optname, default) if isinstance(string, bool): return string elif isinstance(string, int): return bool(string) elif not isinstance(string, str): - raise OptionError(f'Invalid type {string!r} for option {optname}; use ' - '1/0, yes/no, true/false, on/off') + raise OptionError('Invalid type %r for option %s; use ' + '1/0, yes/no, true/false, on/off' % ( + string, optname)) elif string.lower() in ('1', 'yes', 'true', 'on'): return True elif string.lower() in ('0', 'no', 'false', 'off'): return False else: - raise OptionError(f'Invalid value {string!r} for option {optname}; use ' - '1/0, yes/no, true/false, on/off') + raise OptionError('Invalid value %r for option %s; use ' + '1/0, yes/no, true/false, on/off' % ( + string, optname)) def get_int_opt(options, optname, default=None): - """As :func:`get_bool_opt`, but interpret the value as an integer.""" string = options.get(optname, default) try: return int(string) except TypeError: - raise OptionError(f'Invalid type {string!r} for option {optname}; you ' - 'must give an integer value') + raise OptionError('Invalid type %r for option %s; you ' + 'must give an integer value' % ( + string, optname)) except ValueError: - raise OptionError(f'Invalid value {string!r} for option {optname}; you ' - 'must give an integer value') + raise OptionError('Invalid value %r for option %s; you ' + 'must give an integer value' % ( + string, optname)) + def get_list_opt(options, optname, default=None): - """ - If the key `optname` from the dictionary `options` is a string, - split it at whitespace and return it. If it is already a list - or a tuple, it is returned as a list. - """ val = options.get(optname, default) if isinstance(val, str): return val.split() elif isinstance(val, (list, tuple)): return list(val) else: - raise OptionError(f'Invalid type {val!r} for option {optname}; you ' - 'must give a list value') + raise OptionError('Invalid type %r for option %s; you ' + 'must give a list value' % ( + val, optname)) def docstring_headline(obj): @@ -175,7 +159,7 @@ def shebang_matches(text, regex): if x and not x.startswith('-')][-1] except IndexError: return False - regex = re.compile(rf'^{regex}(\.(exe|cmd|bat|bin))?$', re.IGNORECASE) + regex = re.compile(r'^%s(\.(exe|cmd|bat|bin))?$' % regex, re.IGNORECASE) if regex.search(found) is not None: return True return False diff --git a/venv1/Lib/site-packages/pip/_vendor/pyproject_hooks/__init__.py b/venv1/Lib/site-packages/pip/_vendor/pyproject_hooks/__init__.py index 746b89f7..ddfcf7f7 100644 --- a/venv1/Lib/site-packages/pip/_vendor/pyproject_hooks/__init__.py +++ b/venv1/Lib/site-packages/pip/_vendor/pyproject_hooks/__init__.py @@ -1,9 +1,8 @@ """Wrappers to call pyproject.toml-based build backend hooks. """ -from typing import TYPE_CHECKING - from ._impl import ( + BackendInvalid, BackendUnavailable, BuildBackendHookCaller, HookMissing, @@ -12,20 +11,13 @@ quiet_subprocess_runner, ) -__version__ = "1.2.0" +__version__ = '1.0.0' __all__ = [ - "BackendUnavailable", - "BackendInvalid", - "HookMissing", - "UnsupportedOperation", - "default_subprocess_runner", - "quiet_subprocess_runner", - "BuildBackendHookCaller", + 'BackendUnavailable', + 'BackendInvalid', + 'HookMissing', + 'UnsupportedOperation', + 'default_subprocess_runner', + 'quiet_subprocess_runner', + 'BuildBackendHookCaller', ] - -BackendInvalid = BackendUnavailable # Deprecated alias, previously a separate exception - -if TYPE_CHECKING: - from ._impl import SubprocessRunner - - __all__ += ["SubprocessRunner"] diff --git a/venv1/Lib/site-packages/pip/_vendor/pyproject_hooks/_impl.py b/venv1/Lib/site-packages/pip/_vendor/pyproject_hooks/_impl.py index d1e9d7bb..37b0e653 100644 --- a/venv1/Lib/site-packages/pip/_vendor/pyproject_hooks/_impl.py +++ b/venv1/Lib/site-packages/pip/_vendor/pyproject_hooks/_impl.py @@ -6,72 +6,48 @@ from os.path import abspath from os.path import join as pjoin from subprocess import STDOUT, check_call, check_output -from typing import TYPE_CHECKING, Any, Iterator, Mapping, Optional, Sequence from ._in_process import _in_proc_script_path -if TYPE_CHECKING: - from typing import Protocol - class SubprocessRunner(Protocol): - """A protocol for the subprocess runner.""" - - def __call__( - self, - cmd: Sequence[str], - cwd: Optional[str] = None, - extra_environ: Optional[Mapping[str, str]] = None, - ) -> None: - ... - - -def write_json(obj: Mapping[str, Any], path: str, **kwargs) -> None: - with open(path, "w", encoding="utf-8") as f: +def write_json(obj, path, **kwargs): + with open(path, 'w', encoding='utf-8') as f: json.dump(obj, f, **kwargs) -def read_json(path: str) -> Mapping[str, Any]: - with open(path, encoding="utf-8") as f: +def read_json(path): + with open(path, encoding='utf-8') as f: return json.load(f) class BackendUnavailable(Exception): """Will be raised if the backend cannot be imported in the hook process.""" + def __init__(self, traceback): + self.traceback = traceback - def __init__( - self, - traceback: str, - message: Optional[str] = None, - backend_name: Optional[str] = None, - backend_path: Optional[Sequence[str]] = None, - ) -> None: - # Preserving arg order for the sake of API backward compatibility. + +class BackendInvalid(Exception): + """Will be raised if the backend is invalid.""" + def __init__(self, backend_name, backend_path, message): + super().__init__(message) self.backend_name = backend_name self.backend_path = backend_path - self.traceback = traceback - super().__init__(message or "Error while importing backend") class HookMissing(Exception): """Will be raised on missing hooks (if a fallback can't be used).""" - - def __init__(self, hook_name: str) -> None: + def __init__(self, hook_name): super().__init__(hook_name) self.hook_name = hook_name class UnsupportedOperation(Exception): """May be raised by build_sdist if the backend indicates that it can't.""" - - def __init__(self, traceback: str) -> None: + def __init__(self, traceback): self.traceback = traceback -def default_subprocess_runner( - cmd: Sequence[str], - cwd: Optional[str] = None, - extra_environ: Optional[Mapping[str, str]] = None, -) -> None: +def default_subprocess_runner(cmd, cwd=None, extra_environ=None): """The default method of calling the wrapper subprocess. This uses :func:`subprocess.check_call` under the hood. @@ -83,11 +59,7 @@ def default_subprocess_runner( check_call(cmd, cwd=cwd, env=env) -def quiet_subprocess_runner( - cmd: Sequence[str], - cwd: Optional[str] = None, - extra_environ: Optional[Mapping[str, str]] = None, -) -> None: +def quiet_subprocess_runner(cmd, cwd=None, extra_environ=None): """Call the subprocess while suppressing output. This uses :func:`subprocess.check_output` under the hood. @@ -99,7 +71,7 @@ def quiet_subprocess_runner( check_output(cmd, cwd=cwd, env=env, stderr=STDOUT) -def norm_and_check(source_tree: str, requested: str) -> str: +def norm_and_check(source_tree, requested): """Normalise and check a backend path. Ensure that the requested backend path is specified as a relative path, @@ -124,16 +96,17 @@ def norm_and_check(source_tree: str, requested: str) -> str: class BuildBackendHookCaller: - """A wrapper to call the build backend hooks for a source directory.""" + """A wrapper to call the build backend hooks for a source directory. + """ def __init__( - self, - source_dir: str, - build_backend: str, - backend_path: Optional[Sequence[str]] = None, - runner: Optional["SubprocessRunner"] = None, - python_executable: Optional[str] = None, - ) -> None: + self, + source_dir, + build_backend, + backend_path=None, + runner=None, + python_executable=None, + ): """ :param source_dir: The source directory to invoke the build backend for :param build_backend: The build backend spec @@ -148,7 +121,9 @@ def __init__( self.source_dir = abspath(source_dir) self.build_backend = build_backend if backend_path: - backend_path = [norm_and_check(self.source_dir, p) for p in backend_path] + backend_path = [ + norm_and_check(self.source_dir, p) for p in backend_path + ] self.backend_path = backend_path self._subprocess_runner = runner if not python_executable: @@ -156,12 +131,10 @@ def __init__( self.python_executable = python_executable @contextmanager - def subprocess_runner(self, runner: "SubprocessRunner") -> Iterator[None]: + def subprocess_runner(self, runner): """A context manager for temporarily overriding the default :ref:`subprocess runner `. - :param runner: The new subprocess runner to use within the context. - .. code-block:: python hook_caller = BuildBackendHookCaller(...) @@ -175,44 +148,33 @@ def subprocess_runner(self, runner: "SubprocessRunner") -> Iterator[None]: finally: self._subprocess_runner = prev - def _supported_features(self) -> Sequence[str]: + def _supported_features(self): """Return the list of optional features supported by the backend.""" - return self._call_hook("_supported_features", {}) + return self._call_hook('_supported_features', {}) - def get_requires_for_build_wheel( - self, - config_settings: Optional[Mapping[str, Any]] = None, - ) -> Sequence[str]: + def get_requires_for_build_wheel(self, config_settings=None): """Get additional dependencies required for building a wheel. - :param config_settings: The configuration settings for the build backend :returns: A list of :pep:`dependency specifiers <508>`. + :rtype: list[str] .. admonition:: Fallback If the build backend does not defined a hook with this name, an empty list will be returned. """ - return self._call_hook( - "get_requires_for_build_wheel", {"config_settings": config_settings} - ) + return self._call_hook('get_requires_for_build_wheel', { + 'config_settings': config_settings + }) def prepare_metadata_for_build_wheel( - self, - metadata_directory: str, - config_settings: Optional[Mapping[str, Any]] = None, - _allow_fallback: bool = True, - ) -> str: + self, metadata_directory, config_settings=None, + _allow_fallback=True): """Prepare a ``*.dist-info`` folder with metadata for this project. - :param metadata_directory: The directory to write the metadata to - :param config_settings: The configuration settings for the build backend - :param _allow_fallback: - Whether to allow the fallback to building a wheel and extracting - the metadata from it. Should be passed as a keyword argument only. - :returns: Name of the newly created subfolder within ``metadata_directory``, containing the metadata. + :rtype: str .. admonition:: Fallback @@ -221,26 +183,17 @@ def prepare_metadata_for_build_wheel( wheel via the ``build_wheel`` hook and the dist-info extracted from that will be returned. """ - return self._call_hook( - "prepare_metadata_for_build_wheel", - { - "metadata_directory": abspath(metadata_directory), - "config_settings": config_settings, - "_allow_fallback": _allow_fallback, - }, - ) + return self._call_hook('prepare_metadata_for_build_wheel', { + 'metadata_directory': abspath(metadata_directory), + 'config_settings': config_settings, + '_allow_fallback': _allow_fallback, + }) def build_wheel( - self, - wheel_directory: str, - config_settings: Optional[Mapping[str, Any]] = None, - metadata_directory: Optional[str] = None, - ) -> str: + self, wheel_directory, config_settings=None, + metadata_directory=None): """Build a wheel from this project. - :param wheel_directory: The directory to write the wheel to - :param config_settings: The configuration settings for the build backend - :param metadata_directory: The directory to reuse existing metadata from :returns: The name of the newly created wheel within ``wheel_directory``. @@ -253,48 +206,35 @@ def build_wheel( """ if metadata_directory is not None: metadata_directory = abspath(metadata_directory) - return self._call_hook( - "build_wheel", - { - "wheel_directory": abspath(wheel_directory), - "config_settings": config_settings, - "metadata_directory": metadata_directory, - }, - ) - - def get_requires_for_build_editable( - self, - config_settings: Optional[Mapping[str, Any]] = None, - ) -> Sequence[str]: + return self._call_hook('build_wheel', { + 'wheel_directory': abspath(wheel_directory), + 'config_settings': config_settings, + 'metadata_directory': metadata_directory, + }) + + def get_requires_for_build_editable(self, config_settings=None): """Get additional dependencies required for building an editable wheel. - :param config_settings: The configuration settings for the build backend :returns: A list of :pep:`dependency specifiers <508>`. + :rtype: list[str] .. admonition:: Fallback If the build backend does not defined a hook with this name, an empty list will be returned. """ - return self._call_hook( - "get_requires_for_build_editable", {"config_settings": config_settings} - ) + return self._call_hook('get_requires_for_build_editable', { + 'config_settings': config_settings + }) def prepare_metadata_for_build_editable( - self, - metadata_directory: str, - config_settings: Optional[Mapping[str, Any]] = None, - _allow_fallback: bool = True, - ) -> Optional[str]: + self, metadata_directory, config_settings=None, + _allow_fallback=True): """Prepare a ``*.dist-info`` folder with metadata for this project. - :param metadata_directory: The directory to write the metadata to - :param config_settings: The configuration settings for the build backend - :param _allow_fallback: - Whether to allow the fallback to building a wheel and extracting - the metadata from it. Should be passed as a keyword argument only. :returns: Name of the newly created subfolder within ``metadata_directory``, containing the metadata. + :rtype: str .. admonition:: Fallback @@ -303,26 +243,17 @@ def prepare_metadata_for_build_editable( wheel via the ``build_editable`` hook and the dist-info extracted from that will be returned. """ - return self._call_hook( - "prepare_metadata_for_build_editable", - { - "metadata_directory": abspath(metadata_directory), - "config_settings": config_settings, - "_allow_fallback": _allow_fallback, - }, - ) + return self._call_hook('prepare_metadata_for_build_editable', { + 'metadata_directory': abspath(metadata_directory), + 'config_settings': config_settings, + '_allow_fallback': _allow_fallback, + }) def build_editable( - self, - wheel_directory: str, - config_settings: Optional[Mapping[str, Any]] = None, - metadata_directory: Optional[str] = None, - ) -> str: + self, wheel_directory, config_settings=None, + metadata_directory=None): """Build an editable wheel from this project. - :param wheel_directory: The directory to write the wheel to - :param config_settings: The configuration settings for the build backend - :param metadata_directory: The directory to reuse existing metadata from :returns: The name of the newly created wheel within ``wheel_directory``. @@ -336,55 +267,43 @@ def build_editable( """ if metadata_directory is not None: metadata_directory = abspath(metadata_directory) - return self._call_hook( - "build_editable", - { - "wheel_directory": abspath(wheel_directory), - "config_settings": config_settings, - "metadata_directory": metadata_directory, - }, - ) - - def get_requires_for_build_sdist( - self, - config_settings: Optional[Mapping[str, Any]] = None, - ) -> Sequence[str]: + return self._call_hook('build_editable', { + 'wheel_directory': abspath(wheel_directory), + 'config_settings': config_settings, + 'metadata_directory': metadata_directory, + }) + + def get_requires_for_build_sdist(self, config_settings=None): """Get additional dependencies required for building an sdist. :returns: A list of :pep:`dependency specifiers <508>`. + :rtype: list[str] """ - return self._call_hook( - "get_requires_for_build_sdist", {"config_settings": config_settings} - ) - - def build_sdist( - self, - sdist_directory: str, - config_settings: Optional[Mapping[str, Any]] = None, - ) -> str: + return self._call_hook('get_requires_for_build_sdist', { + 'config_settings': config_settings + }) + + def build_sdist(self, sdist_directory, config_settings=None): """Build an sdist from this project. :returns: The name of the newly created sdist within ``wheel_directory``. """ - return self._call_hook( - "build_sdist", - { - "sdist_directory": abspath(sdist_directory), - "config_settings": config_settings, - }, - ) + return self._call_hook('build_sdist', { + 'sdist_directory': abspath(sdist_directory), + 'config_settings': config_settings, + }) - def _call_hook(self, hook_name: str, kwargs: Mapping[str, Any]) -> Any: - extra_environ = {"_PYPROJECT_HOOKS_BUILD_BACKEND": self.build_backend} + def _call_hook(self, hook_name, kwargs): + extra_environ = {'PEP517_BUILD_BACKEND': self.build_backend} if self.backend_path: backend_path = os.pathsep.join(self.backend_path) - extra_environ["_PYPROJECT_HOOKS_BACKEND_PATH"] = backend_path + extra_environ['PEP517_BACKEND_PATH'] = backend_path with tempfile.TemporaryDirectory() as td: - hook_input = {"kwargs": kwargs} - write_json(hook_input, pjoin(td, "input.json"), indent=2) + hook_input = {'kwargs': kwargs} + write_json(hook_input, pjoin(td, 'input.json'), indent=2) # Run the hook in a subprocess with _in_proc_script_path() as script: @@ -392,19 +311,20 @@ def _call_hook(self, hook_name: str, kwargs: Mapping[str, Any]) -> Any: self._subprocess_runner( [python, abspath(str(script)), hook_name, td], cwd=self.source_dir, - extra_environ=extra_environ, + extra_environ=extra_environ ) - data = read_json(pjoin(td, "output.json")) - if data.get("unsupported"): - raise UnsupportedOperation(data.get("traceback", "")) - if data.get("no_backend"): - raise BackendUnavailable( - data.get("traceback", ""), - message=data.get("backend_error", ""), + data = read_json(pjoin(td, 'output.json')) + if data.get('unsupported'): + raise UnsupportedOperation(data.get('traceback', '')) + if data.get('no_backend'): + raise BackendUnavailable(data.get('traceback', '')) + if data.get('backend_invalid'): + raise BackendInvalid( backend_name=self.build_backend, backend_path=self.backend_path, + message=data.get('backend_error', '') ) - if data.get("hook_missing"): - raise HookMissing(data.get("missing_hook_name") or hook_name) - return data["return_val"] + if data.get('hook_missing'): + raise HookMissing(data.get('missing_hook_name') or hook_name) + return data['return_val'] diff --git a/venv1/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/__init__.py b/venv1/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/__init__.py index 906d0ba2..917fa065 100644 --- a/venv1/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/__init__.py +++ b/venv1/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/__init__.py @@ -11,11 +11,8 @@ except AttributeError: # Python 3.8 compatibility def _in_proc_script_path(): - return resources.path(__package__, "_in_process.py") - + return resources.path(__package__, '_in_process.py') else: - def _in_proc_script_path(): return resources.as_file( - resources.files(__package__).joinpath("_in_process.py") - ) + resources.files(__package__).joinpath('_in_process.py')) diff --git a/venv1/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py b/venv1/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py index d689bab7..ee511ff2 100644 --- a/venv1/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py +++ b/venv1/Lib/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py @@ -3,8 +3,8 @@ It expects: - Command line args: hook_name, control_dir - Environment variables: - _PYPROJECT_HOOKS_BUILD_BACKEND=entry.point:spec - _PYPROJECT_HOOKS_BACKEND_PATH=paths (separated with os.pathsep) + PEP517_BUILD_BACKEND=entry.point:spec + PEP517_BACKEND_PATH=paths (separated with os.pathsep) - control_dir/input.json: - {"kwargs": {...}} @@ -21,7 +21,6 @@ import traceback from glob import glob from importlib import import_module -from importlib.machinery import PathFinder from os.path import join as pjoin # This file is run as a script, and `import wrappers` is not zip-safe, so we @@ -29,93 +28,69 @@ def write_json(obj, path, **kwargs): - with open(path, "w", encoding="utf-8") as f: + with open(path, 'w', encoding='utf-8') as f: json.dump(obj, f, **kwargs) def read_json(path): - with open(path, encoding="utf-8") as f: + with open(path, encoding='utf-8') as f: return json.load(f) class BackendUnavailable(Exception): """Raised if we cannot import the backend""" + def __init__(self, traceback): + self.traceback = traceback - def __init__(self, message, traceback=None): - super().__init__(message) + +class BackendInvalid(Exception): + """Raised if the backend is invalid""" + def __init__(self, message): self.message = message - self.traceback = traceback class HookMissing(Exception): """Raised if a hook is missing and we are not executing the fallback""" - def __init__(self, hook_name=None): super().__init__(hook_name) self.hook_name = hook_name +def contained_in(filename, directory): + """Test if a file is located within the given directory.""" + filename = os.path.normcase(os.path.abspath(filename)) + directory = os.path.normcase(os.path.abspath(directory)) + return os.path.commonprefix([filename, directory]) == directory + + def _build_backend(): """Find and load the build backend""" - backend_path = os.environ.get("_PYPROJECT_HOOKS_BACKEND_PATH") - ep = os.environ["_PYPROJECT_HOOKS_BUILD_BACKEND"] - mod_path, _, obj_path = ep.partition(":") - + # Add in-tree backend directories to the front of sys.path. + backend_path = os.environ.get('PEP517_BACKEND_PATH') if backend_path: - # Ensure in-tree backend directories have the highest priority when importing. extra_pathitems = backend_path.split(os.pathsep) - sys.meta_path.insert(0, _BackendPathFinder(extra_pathitems, mod_path)) + sys.path[:0] = extra_pathitems + ep = os.environ['PEP517_BUILD_BACKEND'] + mod_path, _, obj_path = ep.partition(':') try: obj = import_module(mod_path) except ImportError: - msg = f"Cannot import {mod_path!r}" - raise BackendUnavailable(msg, traceback.format_exc()) + raise BackendUnavailable(traceback.format_exc()) + + if backend_path: + if not any( + contained_in(obj.__file__, path) + for path in extra_pathitems + ): + raise BackendInvalid("Backend was not loaded from backend-path") if obj_path: - for path_part in obj_path.split("."): + for path_part in obj_path.split('.'): obj = getattr(obj, path_part) return obj -class _BackendPathFinder: - """Implements the MetaPathFinder interface to locate modules in ``backend-path``. - - Since the environment provided by the frontend can contain all sorts of - MetaPathFinders, the only way to ensure the backend is loaded from the - right place is to prepend our own. - """ - - def __init__(self, backend_path, backend_module): - self.backend_path = backend_path - self.backend_module = backend_module - self.backend_parent, _, _ = backend_module.partition(".") - - def find_spec(self, fullname, _path, _target=None): - if "." in fullname: - # Rely on importlib to find nested modules based on parent's path - return None - - # Ignore other items in _path or sys.path and use backend_path instead: - spec = PathFinder.find_spec(fullname, path=self.backend_path) - if spec is None and fullname == self.backend_parent: - # According to the spec, the backend MUST be loaded from backend-path. - # Therefore, we can halt the import machinery and raise a clean error. - msg = f"Cannot find module {self.backend_module!r} in {self.backend_path!r}" - raise BackendUnavailable(msg) - - return spec - - if sys.version_info >= (3, 8): - - def find_distributions(self, context=None): - # Delayed import: Python 3.7 does not contain importlib.metadata - from importlib.metadata import DistributionFinder, MetadataPathFinder - - context = DistributionFinder.Context(path=self.backend_path) - return MetadataPathFinder.find_distributions(context=context) - - def _supported_features(): """Return the list of options features supported by the backend. @@ -158,8 +133,7 @@ def get_requires_for_build_editable(config_settings): def prepare_metadata_for_build_wheel( - metadata_directory, config_settings, _allow_fallback -): + metadata_directory, config_settings, _allow_fallback): """Invoke optional prepare_metadata_for_build_wheel Implements a fallback by building a wheel if the hook isn't defined, @@ -176,14 +150,12 @@ def prepare_metadata_for_build_wheel( # fallback to build_wheel outside the try block to avoid exception chaining # which can be confusing to users and is not relevant whl_basename = backend.build_wheel(metadata_directory, config_settings) - return _get_wheel_metadata_from_wheel( - whl_basename, metadata_directory, config_settings - ) + return _get_wheel_metadata_from_wheel(whl_basename, metadata_directory, + config_settings) def prepare_metadata_for_build_editable( - metadata_directory, config_settings, _allow_fallback -): + metadata_directory, config_settings, _allow_fallback): """Invoke optional prepare_metadata_for_build_editable Implements a fallback by building an editable wheel if the hook isn't @@ -199,24 +171,24 @@ def prepare_metadata_for_build_editable( try: build_hook = backend.build_editable except AttributeError: - raise HookMissing(hook_name="build_editable") + raise HookMissing(hook_name='build_editable') else: whl_basename = build_hook(metadata_directory, config_settings) - return _get_wheel_metadata_from_wheel( - whl_basename, metadata_directory, config_settings - ) + return _get_wheel_metadata_from_wheel(whl_basename, + metadata_directory, + config_settings) else: return hook(metadata_directory, config_settings) -WHEEL_BUILT_MARKER = "PYPROJECT_HOOKS_ALREADY_BUILT_WHEEL" +WHEEL_BUILT_MARKER = 'PEP517_ALREADY_BUILT_WHEEL' def _dist_info_files(whl_zip): """Identify the .dist-info folder inside a wheel ZipFile.""" res = [] for path in whl_zip.namelist(): - m = re.match(r"[^/\\]+-[^/\\]+\.dist-info/", path) + m = re.match(r'[^/\\]+-[^/\\]+\.dist-info/', path) if m: res.append(path) if res: @@ -224,41 +196,40 @@ def _dist_info_files(whl_zip): raise Exception("No .dist-info folder found in wheel") -def _get_wheel_metadata_from_wheel(whl_basename, metadata_directory, config_settings): +def _get_wheel_metadata_from_wheel( + whl_basename, metadata_directory, config_settings): """Extract the metadata from a wheel. Fallback for when the build backend does not define the 'get_wheel_metadata' hook. """ from zipfile import ZipFile - - with open(os.path.join(metadata_directory, WHEEL_BUILT_MARKER), "wb"): + with open(os.path.join(metadata_directory, WHEEL_BUILT_MARKER), 'wb'): pass # Touch marker file whl_file = os.path.join(metadata_directory, whl_basename) with ZipFile(whl_file) as zipf: dist_info = _dist_info_files(zipf) zipf.extractall(path=metadata_directory, members=dist_info) - return dist_info[0].split("/")[0] + return dist_info[0].split('/')[0] def _find_already_built_wheel(metadata_directory): - """Check for a wheel already built during the get_wheel_metadata hook.""" + """Check for a wheel already built during the get_wheel_metadata hook. + """ if not metadata_directory: return None metadata_parent = os.path.dirname(metadata_directory) if not os.path.isfile(pjoin(metadata_parent, WHEEL_BUILT_MARKER)): return None - whl_files = glob(os.path.join(metadata_parent, "*.whl")) + whl_files = glob(os.path.join(metadata_parent, '*.whl')) if not whl_files: - print("Found wheel built marker, but no .whl files") + print('Found wheel built marker, but no .whl files') return None if len(whl_files) > 1: - print( - "Found multiple .whl files; unspecified behaviour. " - "Will call build_wheel." - ) + print('Found multiple .whl files; unspecified behaviour. ' + 'Will call build_wheel.') return None # Exactly one .whl file @@ -277,9 +248,8 @@ def build_wheel(wheel_directory, config_settings, metadata_directory=None): shutil.copy2(prebuilt_whl, wheel_directory) return os.path.basename(prebuilt_whl) - return _build_backend().build_wheel( - wheel_directory, config_settings, metadata_directory - ) + return _build_backend().build_wheel(wheel_directory, config_settings, + metadata_directory) def build_editable(wheel_directory, config_settings, metadata_directory=None): @@ -323,7 +293,6 @@ class _DummyException(Exception): class GotUnsupportedOperation(Exception): """For internal use when backend raises UnsupportedOperation""" - def __init__(self, traceback): self.traceback = traceback @@ -333,20 +302,20 @@ def build_sdist(sdist_directory, config_settings): backend = _build_backend() try: return backend.build_sdist(sdist_directory, config_settings) - except getattr(backend, "UnsupportedOperation", _DummyException): + except getattr(backend, 'UnsupportedOperation', _DummyException): raise GotUnsupportedOperation(traceback.format_exc()) HOOK_NAMES = { - "get_requires_for_build_wheel", - "prepare_metadata_for_build_wheel", - "build_wheel", - "get_requires_for_build_editable", - "prepare_metadata_for_build_editable", - "build_editable", - "get_requires_for_build_sdist", - "build_sdist", - "_supported_features", + 'get_requires_for_build_wheel', + 'prepare_metadata_for_build_wheel', + 'build_wheel', + 'get_requires_for_build_editable', + 'prepare_metadata_for_build_editable', + 'build_editable', + 'get_requires_for_build_sdist', + 'build_sdist', + '_supported_features', } @@ -357,33 +326,28 @@ def main(): control_dir = sys.argv[2] if hook_name not in HOOK_NAMES: sys.exit("Unknown hook: %s" % hook_name) - - # Remove the parent directory from sys.path to avoid polluting the backend - # import namespace with this directory. - here = os.path.dirname(__file__) - if here in sys.path: - sys.path.remove(here) - hook = globals()[hook_name] - hook_input = read_json(pjoin(control_dir, "input.json")) + hook_input = read_json(pjoin(control_dir, 'input.json')) - json_out = {"unsupported": False, "return_val": None} + json_out = {'unsupported': False, 'return_val': None} try: - json_out["return_val"] = hook(**hook_input["kwargs"]) + json_out['return_val'] = hook(**hook_input['kwargs']) except BackendUnavailable as e: - json_out["no_backend"] = True - json_out["traceback"] = e.traceback - json_out["backend_error"] = e.message + json_out['no_backend'] = True + json_out['traceback'] = e.traceback + except BackendInvalid as e: + json_out['backend_invalid'] = True + json_out['backend_error'] = e.message except GotUnsupportedOperation as e: - json_out["unsupported"] = True - json_out["traceback"] = e.traceback + json_out['unsupported'] = True + json_out['traceback'] = e.traceback except HookMissing as e: - json_out["hook_missing"] = True - json_out["missing_hook_name"] = e.hook_name or hook_name + json_out['hook_missing'] = True + json_out['missing_hook_name'] = e.hook_name or hook_name - write_json(json_out, pjoin(control_dir, "output.json"), indent=2) + write_json(json_out, pjoin(control_dir, 'output.json'), indent=2) -if __name__ == "__main__": +if __name__ == '__main__': main() diff --git a/venv1/Lib/site-packages/pip/_vendor/requests/__init__.py b/venv1/Lib/site-packages/pip/_vendor/requests/__init__.py index 04230fc8..a4776248 100644 --- a/venv1/Lib/site-packages/pip/_vendor/requests/__init__.py +++ b/venv1/Lib/site-packages/pip/_vendor/requests/__init__.py @@ -45,7 +45,11 @@ from .exceptions import RequestsDependencyWarning charset_normalizer_version = None -chardet_version = None + +try: + from pip._vendor.chardet import __version__ as chardet_version +except ImportError: + chardet_version = None def check_compatibility(urllib3_version, chardet_version, charset_normalizer_version): @@ -59,10 +63,10 @@ def check_compatibility(urllib3_version, chardet_version, charset_normalizer_ver # Check urllib3 for compatibility. major, minor, patch = urllib3_version # noqa: F811 major, minor, patch = int(major), int(minor), int(patch) - # urllib3 >= 1.21.1 - assert major >= 1 - if major == 1: - assert minor >= 21 + # urllib3 >= 1.21.1, <= 1.26 + assert major == 1 + assert minor >= 21 + assert minor <= 26 # Check charset_normalizer for compatibility. if chardet_version: @@ -76,8 +80,7 @@ def check_compatibility(urllib3_version, chardet_version, charset_normalizer_ver # charset_normalizer >= 2.0.0 < 4.0.0 assert (2, 0, 0) <= (major, minor, patch) < (4, 0, 0) else: - # pip does not need or use character detection - pass + raise Exception("You need either charset_normalizer or chardet installed") def _check_cryptography(cryptography_version): diff --git a/venv1/Lib/site-packages/pip/_vendor/requests/__version__.py b/venv1/Lib/site-packages/pip/_vendor/requests/__version__.py index effdd98c..69be3dec 100644 --- a/venv1/Lib/site-packages/pip/_vendor/requests/__version__.py +++ b/venv1/Lib/site-packages/pip/_vendor/requests/__version__.py @@ -5,10 +5,10 @@ __title__ = "requests" __description__ = "Python HTTP for Humans." __url__ = "https://requests.readthedocs.io" -__version__ = "2.32.5" -__build__ = 0x023205 +__version__ = "2.28.2" +__build__ = 0x022802 __author__ = "Kenneth Reitz" __author_email__ = "me@kennethreitz.org" -__license__ = "Apache-2.0" +__license__ = "Apache 2.0" __copyright__ = "Copyright Kenneth Reitz" __cake__ = "\u2728 \U0001f370 \u2728" diff --git a/venv1/Lib/site-packages/pip/_vendor/requests/_internal_utils.py b/venv1/Lib/site-packages/pip/_vendor/requests/_internal_utils.py index f2cf635e..7dc9bc53 100644 --- a/venv1/Lib/site-packages/pip/_vendor/requests/_internal_utils.py +++ b/venv1/Lib/site-packages/pip/_vendor/requests/_internal_utils.py @@ -14,11 +14,9 @@ _VALID_HEADER_VALUE_RE_BYTE = re.compile(rb"^\S[^\r\n]*$|^$") _VALID_HEADER_VALUE_RE_STR = re.compile(r"^\S[^\r\n]*$|^$") -_HEADER_VALIDATORS_STR = (_VALID_HEADER_NAME_RE_STR, _VALID_HEADER_VALUE_RE_STR) -_HEADER_VALIDATORS_BYTE = (_VALID_HEADER_NAME_RE_BYTE, _VALID_HEADER_VALUE_RE_BYTE) HEADER_VALIDATORS = { - bytes: _HEADER_VALIDATORS_BYTE, - str: _HEADER_VALIDATORS_STR, + bytes: (_VALID_HEADER_NAME_RE_BYTE, _VALID_HEADER_VALUE_RE_BYTE), + str: (_VALID_HEADER_NAME_RE_STR, _VALID_HEADER_VALUE_RE_STR), } diff --git a/venv1/Lib/site-packages/pip/_vendor/requests/adapters.py b/venv1/Lib/site-packages/pip/_vendor/requests/adapters.py index 67ccebcb..f68f7d46 100644 --- a/venv1/Lib/site-packages/pip/_vendor/requests/adapters.py +++ b/venv1/Lib/site-packages/pip/_vendor/requests/adapters.py @@ -8,8 +8,6 @@ import os.path import socket # noqa: F401 -import typing -import warnings from pip._vendor.urllib3.exceptions import ClosedPoolError, ConnectTimeoutError from pip._vendor.urllib3.exceptions import HTTPError as _HTTPError @@ -24,6 +22,7 @@ from pip._vendor.urllib3.exceptions import ReadTimeoutError, ResponseError from pip._vendor.urllib3.exceptions import SSLError as _SSLError from pip._vendor.urllib3.poolmanager import PoolManager, proxy_from_url +from pip._vendor.urllib3.response import HTTPResponse from pip._vendor.urllib3.util import Timeout as TimeoutSauce from pip._vendor.urllib3.util import parse_url from pip._vendor.urllib3.util.retry import Retry @@ -63,53 +62,12 @@ def SOCKSProxyManager(*args, **kwargs): raise InvalidSchema("Missing dependencies for SOCKS support.") -if typing.TYPE_CHECKING: - from .models import PreparedRequest - - DEFAULT_POOLBLOCK = False DEFAULT_POOLSIZE = 10 DEFAULT_RETRIES = 0 DEFAULT_POOL_TIMEOUT = None -def _urllib3_request_context( - request: "PreparedRequest", - verify: "bool | str | None", - client_cert: "typing.Tuple[str, str] | str | None", - poolmanager: "PoolManager", -) -> "(typing.Dict[str, typing.Any], typing.Dict[str, typing.Any])": - host_params = {} - pool_kwargs = {} - parsed_request_url = urlparse(request.url) - scheme = parsed_request_url.scheme.lower() - port = parsed_request_url.port - - cert_reqs = "CERT_REQUIRED" - if verify is False: - cert_reqs = "CERT_NONE" - elif isinstance(verify, str): - if not os.path.isdir(verify): - pool_kwargs["ca_certs"] = verify - else: - pool_kwargs["ca_cert_dir"] = verify - pool_kwargs["cert_reqs"] = cert_reqs - if client_cert is not None: - if isinstance(client_cert, tuple) and len(client_cert) == 2: - pool_kwargs["cert_file"] = client_cert[0] - pool_kwargs["key_file"] = client_cert[1] - else: - # According to our docs, we allow users to specify just the client - # cert path - pool_kwargs["cert_file"] = client_cert - host_params = { - "scheme": scheme, - "host": parsed_request_url.hostname, - "port": port, - } - return host_params, pool_kwargs - - class BaseAdapter: """The Base Transport Adapter""" @@ -236,6 +194,7 @@ def init_poolmanager( num_pools=connections, maxsize=maxsize, block=block, + strict=True, **pool_kwargs, ) @@ -290,6 +249,7 @@ def cert_verify(self, conn, url, verify, cert): :param cert: The SSL certificate to verify. """ if url.lower().startswith("https") and verify: + cert_loc = None # Allow self-specified cert location. @@ -370,110 +330,8 @@ def build_response(self, req, resp): return response - def build_connection_pool_key_attributes(self, request, verify, cert=None): - """Build the PoolKey attributes used by urllib3 to return a connection. - - This looks at the PreparedRequest, the user-specified verify value, - and the value of the cert parameter to determine what PoolKey values - to use to select a connection from a given urllib3 Connection Pool. - - The SSL related pool key arguments are not consistently set. As of - this writing, use the following to determine what keys may be in that - dictionary: - - * If ``verify`` is ``True``, ``"ssl_context"`` will be set and will be the - default Requests SSL Context - * If ``verify`` is ``False``, ``"ssl_context"`` will not be set but - ``"cert_reqs"`` will be set - * If ``verify`` is a string, (i.e., it is a user-specified trust bundle) - ``"ca_certs"`` will be set if the string is not a directory recognized - by :py:func:`os.path.isdir`, otherwise ``"ca_cert_dir"`` will be - set. - * If ``"cert"`` is specified, ``"cert_file"`` will always be set. If - ``"cert"`` is a tuple with a second item, ``"key_file"`` will also - be present - - To override these settings, one may subclass this class, call this - method and use the above logic to change parameters as desired. For - example, if one wishes to use a custom :py:class:`ssl.SSLContext` one - must both set ``"ssl_context"`` and based on what else they require, - alter the other keys to ensure the desired behaviour. - - :param request: - The PreparedReqest being sent over the connection. - :type request: - :class:`~requests.models.PreparedRequest` - :param verify: - Either a boolean, in which case it controls whether - we verify the server's TLS certificate, or a string, in which case it - must be a path to a CA bundle to use. - :param cert: - (optional) Any user-provided SSL certificate for client - authentication (a.k.a., mTLS). This may be a string (i.e., just - the path to a file which holds both certificate and key) or a - tuple of length 2 with the certificate file path and key file - path. - :returns: - A tuple of two dictionaries. The first is the "host parameters" - portion of the Pool Key including scheme, hostname, and port. The - second is a dictionary of SSLContext related parameters. - """ - return _urllib3_request_context(request, verify, cert, self.poolmanager) - - def get_connection_with_tls_context(self, request, verify, proxies=None, cert=None): - """Returns a urllib3 connection for the given request and TLS settings. - This should not be called from user code, and is only exposed for use - when subclassing the :class:`HTTPAdapter `. - - :param request: - The :class:`PreparedRequest ` object to be sent - over the connection. - :param verify: - Either a boolean, in which case it controls whether we verify the - server's TLS certificate, or a string, in which case it must be a - path to a CA bundle to use. - :param proxies: - (optional) The proxies dictionary to apply to the request. - :param cert: - (optional) Any user-provided SSL certificate to be used for client - authentication (a.k.a., mTLS). - :rtype: - urllib3.ConnectionPool - """ - proxy = select_proxy(request.url, proxies) - try: - host_params, pool_kwargs = self.build_connection_pool_key_attributes( - request, - verify, - cert, - ) - except ValueError as e: - raise InvalidURL(e, request=request) - if proxy: - proxy = prepend_scheme_if_needed(proxy, "http") - proxy_url = parse_url(proxy) - if not proxy_url.host: - raise InvalidProxyURL( - "Please check proxy URL. It is malformed " - "and could be missing the host." - ) - proxy_manager = self.proxy_manager_for(proxy) - conn = proxy_manager.connection_from_host( - **host_params, pool_kwargs=pool_kwargs - ) - else: - # Only scheme should be lower case - conn = self.poolmanager.connection_from_host( - **host_params, pool_kwargs=pool_kwargs - ) - - return conn - def get_connection(self, url, proxies=None): - """DEPRECATED: Users should move to `get_connection_with_tls_context` - for all subclasses of HTTPAdapter using Requests>=2.32.2. - - Returns a urllib3 connection for the given URL. This should not be + """Returns a urllib3 connection for the given URL. This should not be called from user code, and is only exposed for use when subclassing the :class:`HTTPAdapter `. @@ -481,15 +339,6 @@ def get_connection(self, url, proxies=None): :param proxies: (optional) A Requests-style dictionary of proxies used on this request. :rtype: urllib3.ConnectionPool """ - warnings.warn( - ( - "`get_connection` has been deprecated in favor of " - "`get_connection_with_tls_context`. Custom HTTPAdapter subclasses " - "will need to migrate for Requests>=2.32.2. Please see " - "https://github.com/psf/requests/pull/6710 for more details." - ), - DeprecationWarning, - ) proxy = select_proxy(url, proxies) if proxy: @@ -544,9 +393,6 @@ def request_url(self, request, proxies): using_socks_proxy = proxy_scheme.startswith("socks") url = request.path_url - if url.startswith("//"): # Don't confuse urllib3 - url = f"/{url.lstrip('/')}" - if is_proxied_http_request and not using_socks_proxy: url = urldefragauth(request.url) @@ -607,9 +453,7 @@ def send( """ try: - conn = self.get_connection_with_tls_context( - request, verify, proxies=proxies, cert=cert - ) + conn = self.get_connection(request.url, proxies) except LocationValueError as e: raise InvalidURL(e, request=request) @@ -641,19 +485,63 @@ def send( timeout = TimeoutSauce(connect=timeout, read=timeout) try: - resp = conn.urlopen( - method=request.method, - url=url, - body=request.body, - headers=request.headers, - redirect=False, - assert_same_host=False, - preload_content=False, - decode_content=False, - retries=self.max_retries, - timeout=timeout, - chunked=chunked, - ) + if not chunked: + resp = conn.urlopen( + method=request.method, + url=url, + body=request.body, + headers=request.headers, + redirect=False, + assert_same_host=False, + preload_content=False, + decode_content=False, + retries=self.max_retries, + timeout=timeout, + ) + + # Send the request. + else: + if hasattr(conn, "proxy_pool"): + conn = conn.proxy_pool + + low_conn = conn._get_conn(timeout=DEFAULT_POOL_TIMEOUT) + + try: + skip_host = "Host" in request.headers + low_conn.putrequest( + request.method, + url, + skip_accept_encoding=True, + skip_host=skip_host, + ) + + for header, value in request.headers.items(): + low_conn.putheader(header, value) + + low_conn.endheaders() + + for i in request.body: + low_conn.send(hex(len(i))[2:].encode("utf-8")) + low_conn.send(b"\r\n") + low_conn.send(i) + low_conn.send(b"\r\n") + low_conn.send(b"0\r\n\r\n") + + # Receive the response from the server + r = low_conn.getresponse() + + resp = HTTPResponse.from_httplib( + r, + pool=conn, + connection=low_conn, + preload_content=False, + decode_content=False, + ) + except Exception: + # If we hit any problems here, clean up the connection. + # Then, raise so that we can handle the actual exception. + low_conn.close() + raise except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) diff --git a/venv1/Lib/site-packages/pip/_vendor/requests/api.py b/venv1/Lib/site-packages/pip/_vendor/requests/api.py index 59607445..2f71aaed 100644 --- a/venv1/Lib/site-packages/pip/_vendor/requests/api.py +++ b/venv1/Lib/site-packages/pip/_vendor/requests/api.py @@ -25,7 +25,7 @@ def request(method, url, **kwargs): :param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`. :param files: (optional) Dictionary of ``'name': file-like-objects`` (or ``{'name': file-tuple}``) for multipart encoding upload. ``file-tuple`` can be a 2-tuple ``('filename', fileobj)``, 3-tuple ``('filename', fileobj, 'content_type')`` - or a 4-tuple ``('filename', fileobj, 'content_type', custom_headers)``, where ``'content_type'`` is a string + or a 4-tuple ``('filename', fileobj, 'content_type', custom_headers)``, where ``'content-type'`` is a string defining the content type of the given file and ``custom_headers`` a dict-like object containing additional headers to add for the file. :param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth. @@ -106,7 +106,7 @@ def post(url, data=None, json=None, **kwargs): :param url: URL for the new :class:`Request` object. :param data: (optional) Dictionary, list of tuples, bytes, or file-like object to send in the body of the :class:`Request`. - :param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`. + :param json: (optional) json data to send in the body of the :class:`Request`. :param \*\*kwargs: Optional arguments that ``request`` takes. :return: :class:`Response ` object :rtype: requests.Response @@ -121,7 +121,7 @@ def put(url, data=None, **kwargs): :param url: URL for the new :class:`Request` object. :param data: (optional) Dictionary, list of tuples, bytes, or file-like object to send in the body of the :class:`Request`. - :param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`. + :param json: (optional) json data to send in the body of the :class:`Request`. :param \*\*kwargs: Optional arguments that ``request`` takes. :return: :class:`Response ` object :rtype: requests.Response @@ -136,7 +136,7 @@ def patch(url, data=None, **kwargs): :param url: URL for the new :class:`Request` object. :param data: (optional) Dictionary, list of tuples, bytes, or file-like object to send in the body of the :class:`Request`. - :param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`. + :param json: (optional) json data to send in the body of the :class:`Request`. :param \*\*kwargs: Optional arguments that ``request`` takes. :return: :class:`Response ` object :rtype: requests.Response diff --git a/venv1/Lib/site-packages/pip/_vendor/requests/auth.py b/venv1/Lib/site-packages/pip/_vendor/requests/auth.py index 4a7ce6dc..9733686d 100644 --- a/venv1/Lib/site-packages/pip/_vendor/requests/auth.py +++ b/venv1/Lib/site-packages/pip/_vendor/requests/auth.py @@ -258,6 +258,7 @@ def handle_401(self, r, **kwargs): s_auth = r.headers.get("www-authenticate", "") if "digest" in s_auth.lower() and self._thread_local.num_401_calls < 2: + self._thread_local.num_401_calls += 1 pat = re.compile(r"digest ", flags=re.IGNORECASE) self._thread_local.chal = parse_dict_header(pat.sub("", s_auth, count=1)) diff --git a/venv1/Lib/site-packages/pip/_vendor/requests/certs.py b/venv1/Lib/site-packages/pip/_vendor/requests/certs.py index 2743144b..38696a1f 100644 --- a/venv1/Lib/site-packages/pip/_vendor/requests/certs.py +++ b/venv1/Lib/site-packages/pip/_vendor/requests/certs.py @@ -11,7 +11,14 @@ environment, you can change the definition of where() to return a separately packaged CA bundle. """ -from pip._vendor.certifi import where + +import os + +if "_PIP_STANDALONE_CERT" not in os.environ: + from pip._vendor.certifi import where +else: + def where(): + return os.environ["_PIP_STANDALONE_CERT"] if __name__ == "__main__": print(where()) diff --git a/venv1/Lib/site-packages/pip/_vendor/requests/compat.py b/venv1/Lib/site-packages/pip/_vendor/requests/compat.py index b95a9214..9ab2bb48 100644 --- a/venv1/Lib/site-packages/pip/_vendor/requests/compat.py +++ b/venv1/Lib/site-packages/pip/_vendor/requests/compat.py @@ -7,32 +7,9 @@ compatibility until the next major version. """ -import sys - -# ------- -# urllib3 -# ------- -from pip._vendor.urllib3 import __version__ as urllib3_version - -# Detect which major version of urllib3 is being used. -try: - is_urllib3_1 = int(urllib3_version.split(".")[0]) == 1 -except (TypeError, AttributeError): - # If we can't discern a version, prefer old functionality. - is_urllib3_1 = True +from pip._vendor import chardet -# ------------------- -# Character Detection -# ------------------- - - -def _resolve_char_detection(): - """Find supported character detection libraries.""" - chardet = None - return chardet - - -chardet = _resolve_char_detection() +import sys # ------- # Pythons diff --git a/venv1/Lib/site-packages/pip/_vendor/requests/cookies.py b/venv1/Lib/site-packages/pip/_vendor/requests/cookies.py index f69d0cda..bf54ab23 100644 --- a/venv1/Lib/site-packages/pip/_vendor/requests/cookies.py +++ b/venv1/Lib/site-packages/pip/_vendor/requests/cookies.py @@ -2,7 +2,7 @@ requests.cookies ~~~~~~~~~~~~~~~~ -Compatibility code to be able to use `http.cookiejar.CookieJar` with requests. +Compatibility code to be able to use `cookielib.CookieJar` with requests. requests.utils imports from here, so be careful with imports. """ @@ -23,7 +23,7 @@ class MockRequest: """Wraps a `requests.Request` to mimic a `urllib2.Request`. - The code in `http.cookiejar.CookieJar` expects this interface in order to correctly + The code in `cookielib.CookieJar` expects this interface in order to correctly manage cookie policies, i.e., determine whether a cookie can be set, given the domains of the request and the cookie. @@ -76,7 +76,7 @@ def get_header(self, name, default=None): return self._r.headers.get(name, self._new_headers.get(name, default)) def add_header(self, key, val): - """cookiejar has no legitimate use for this method; add it back if you find one.""" + """cookielib has no legitimate use for this method; add it back if you find one.""" raise NotImplementedError( "Cookie headers should be added with add_unredirected_header()" ) @@ -104,11 +104,11 @@ class MockResponse: """Wraps a `httplib.HTTPMessage` to mimic a `urllib.addinfourl`. ...what? Basically, expose the parsed HTTP headers from the server response - the way `http.cookiejar` expects to see them. + the way `cookielib` expects to see them. """ def __init__(self, headers): - """Make a MockResponse for `cookiejar` to read. + """Make a MockResponse for `cookielib` to read. :param headers: a httplib.HTTPMessage or analogous carrying the headers """ @@ -124,7 +124,7 @@ def getheaders(self, name): def extract_cookies_to_jar(jar, request, response): """Extract the cookies from the response into a CookieJar. - :param jar: http.cookiejar.CookieJar (not necessarily a RequestsCookieJar) + :param jar: cookielib.CookieJar (not necessarily a RequestsCookieJar) :param request: our own requests.Request object :param response: urllib3.HTTPResponse object """ @@ -174,7 +174,7 @@ class CookieConflictError(RuntimeError): class RequestsCookieJar(cookielib.CookieJar, MutableMapping): - """Compatibility class; is a http.cookiejar.CookieJar, but exposes a dict + """Compatibility class; is a cookielib.CookieJar, but exposes a dict interface. This is the CookieJar we create by default for requests and sessions that @@ -341,7 +341,7 @@ def __setitem__(self, name, value): self.set(name, value) def __delitem__(self, name): - """Deletes a cookie given a name. Wraps ``http.cookiejar.CookieJar``'s + """Deletes a cookie given a name. Wraps ``cookielib.CookieJar``'s ``remove_cookie_by_name()``. """ remove_cookie_by_name(self, name) diff --git a/venv1/Lib/site-packages/pip/_vendor/requests/exceptions.py b/venv1/Lib/site-packages/pip/_vendor/requests/exceptions.py index 7f3660f0..168d0739 100644 --- a/venv1/Lib/site-packages/pip/_vendor/requests/exceptions.py +++ b/venv1/Lib/site-packages/pip/_vendor/requests/exceptions.py @@ -41,16 +41,6 @@ def __init__(self, *args, **kwargs): CompatJSONDecodeError.__init__(self, *args) InvalidJSONError.__init__(self, *self.args, **kwargs) - def __reduce__(self): - """ - The __reduce__ method called when pickling the object must - be the one from the JSONDecodeError (be it json/simplejson) - as it expects all the arguments for instantiation, not just - one like the IOError, and the MRO would by default call the - __reduce__ method from the IOError due to the inheritance order. - """ - return CompatJSONDecodeError.__reduce__(self) - class HTTPError(RequestException): """An HTTP error occurred.""" diff --git a/venv1/Lib/site-packages/pip/_vendor/requests/help.py b/venv1/Lib/site-packages/pip/_vendor/requests/help.py index ddbb6150..2d292c2f 100644 --- a/venv1/Lib/site-packages/pip/_vendor/requests/help.py +++ b/venv1/Lib/site-packages/pip/_vendor/requests/help.py @@ -11,7 +11,11 @@ from . import __version__ as requests_version charset_normalizer = None -chardet = None + +try: + from pip._vendor import chardet +except ImportError: + chardet = None try: from pip._vendor.urllib3.contrib import pyopenssl diff --git a/venv1/Lib/site-packages/pip/_vendor/requests/models.py b/venv1/Lib/site-packages/pip/_vendor/requests/models.py index 22de95c0..76e6f199 100644 --- a/venv1/Lib/site-packages/pip/_vendor/requests/models.py +++ b/venv1/Lib/site-packages/pip/_vendor/requests/models.py @@ -170,7 +170,7 @@ def _encode_files(files, data): ) ) - for k, v in files: + for (k, v) in files: # support for explicit filename ft = None fh = None @@ -268,6 +268,7 @@ def __init__( hooks=None, json=None, ): + # Default empty dicts for dict params. data = [] if data is None else data files = [] if files is None else files @@ -276,7 +277,7 @@ def __init__( hooks = {} if hooks is None else hooks self.hooks = default_hooks() - for k, v in list(hooks.items()): + for (k, v) in list(hooks.items()): self.register_hook(event=k, hook=v) self.method = method @@ -789,12 +790,7 @@ def next(self): @property def apparent_encoding(self): """The apparent encoding, provided by the charset_normalizer or chardet libraries.""" - if chardet is not None: - return chardet.detect(self.content)["encoding"] - else: - # If no character detection library is available, we'll fall back - # to a standard Python utf-8 str. - return "utf-8" + return chardet.detect(self.content)["encoding"] def iter_content(self, chunk_size=1, decode_unicode=False): """Iterates over the response data. When stream=True is set on the @@ -869,6 +865,7 @@ def iter_lines( for chunk in self.iter_content( chunk_size=chunk_size, decode_unicode=decode_unicode ): + if pending is not None: chunk = pending + chunk @@ -945,9 +942,7 @@ def text(self): return content def json(self, **kwargs): - r"""Decodes the JSON response body (if any) as a Python object. - - This may return a dictionary, list, etc. depending on what is in the response. + r"""Returns the json-encoded content of a response, if any. :param \*\*kwargs: Optional arguments that ``json.loads`` takes. :raises requests.exceptions.JSONDecodeError: If the response body does not diff --git a/venv1/Lib/site-packages/pip/_vendor/requests/packages.py b/venv1/Lib/site-packages/pip/_vendor/requests/packages.py index 200c3828..9582fa73 100644 --- a/venv1/Lib/site-packages/pip/_vendor/requests/packages.py +++ b/venv1/Lib/site-packages/pip/_vendor/requests/packages.py @@ -1,11 +1,9 @@ import sys -from .compat import chardet - # This code exists for backwards compatibility reasons. # I don't like it either. Just look the other way. :) -for package in ("urllib3", "idna"): +for package in ('urllib3', 'idna', 'chardet'): vendored_package = "pip._vendor." + package locals()[package] = __import__(vendored_package) # This traversal is apparently necessary such that the identities are @@ -15,11 +13,4 @@ unprefixed_mod = mod[len("pip._vendor."):] sys.modules['pip._vendor.requests.packages.' + unprefixed_mod] = sys.modules[mod] -if chardet is not None: - target = chardet.__name__ - for mod in list(sys.modules): - if mod == target or mod.startswith(f"{target}."): - imported_mod = sys.modules[mod] - sys.modules[f"requests.packages.{mod}"] = imported_mod - mod = mod.replace(target, "chardet") - sys.modules[f"requests.packages.{mod}"] = imported_mod +# Kinda cool, though, right? diff --git a/venv1/Lib/site-packages/pip/_vendor/requests/sessions.py b/venv1/Lib/site-packages/pip/_vendor/requests/sessions.py index 731550de..6cb3b4da 100644 --- a/venv1/Lib/site-packages/pip/_vendor/requests/sessions.py +++ b/venv1/Lib/site-packages/pip/_vendor/requests/sessions.py @@ -262,6 +262,7 @@ def resolve_redirects( if yield_requests: yield req else: + resp = self.send( req, stream=stream, @@ -323,9 +324,7 @@ def rebuild_proxies(self, prepared_request, proxies): except KeyError: username, password = None, None - # urllib3 handles proxy authorization for us in the standard adapter. - # Avoid appending this to TLS tunneled requests where it may be leaked. - if not scheme.startswith("https") and username and password: + if username and password: headers["Proxy-Authorization"] = _basic_auth_str(username, password) return new_proxies @@ -388,6 +387,7 @@ class Session(SessionRedirectMixin): ] def __init__(self): + #: A case-insensitive dictionary of headers to be sent on each #: :class:`Request ` sent from this #: :class:`Session `. @@ -535,7 +535,7 @@ def request( for multipart encoding upload. :param auth: (optional) Auth tuple or callable to enable Basic/Digest/Custom HTTP Auth. - :param timeout: (optional) How many seconds to wait for the server to send + :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple @@ -543,8 +543,6 @@ def request( :type allow_redirects: bool :param proxies: (optional) Dictionary mapping protocol or protocol and hostname to the URL of the proxy. - :param hooks: (optional) Dictionary mapping hook name to one event or - list of events, event must be callable. :param stream: (optional) whether to immediately download the response content. Defaults to ``False``. :param verify: (optional) Either a boolean, in which case it controls whether we verify @@ -711,6 +709,7 @@ def send(self, request, **kwargs): # Persist cookies if r.history: + # If the hooks create history then we want those cookies too for resp in r.history: extract_cookies_to_jar(self.cookies, resp.request, resp.raw) @@ -758,7 +757,7 @@ def merge_environment_settings(self, url, proxies, stream, verify, cert): # Set environment's proxies. no_proxy = proxies.get("no_proxy") if proxies is not None else None env_proxies = get_environ_proxies(url, no_proxy=no_proxy) - for k, v in env_proxies.items(): + for (k, v) in env_proxies.items(): proxies.setdefault(k, v) # Look for requests environment configuration @@ -784,7 +783,8 @@ def get_adapter(self, url): :rtype: requests.adapters.BaseAdapter """ - for prefix, adapter in self.adapters.items(): + for (prefix, adapter) in self.adapters.items(): + if url.lower().startswith(prefix.lower()): return adapter diff --git a/venv1/Lib/site-packages/pip/_vendor/requests/status_codes.py b/venv1/Lib/site-packages/pip/_vendor/requests/status_codes.py index c7945a2f..4bd072be 100644 --- a/venv1/Lib/site-packages/pip/_vendor/requests/status_codes.py +++ b/venv1/Lib/site-packages/pip/_vendor/requests/status_codes.py @@ -24,7 +24,7 @@ # Informational. 100: ("continue",), 101: ("switching_protocols",), - 102: ("processing", "early-hints"), + 102: ("processing",), 103: ("checkpoint",), 122: ("uri_too_long", "request_uri_too_long"), 200: ("ok", "okay", "all_ok", "all_okay", "all_good", "\\o/", "✓"), @@ -65,8 +65,8 @@ 410: ("gone",), 411: ("length_required",), 412: ("precondition_failed", "precondition"), - 413: ("request_entity_too_large", "content_too_large"), - 414: ("request_uri_too_large", "uri_too_long"), + 413: ("request_entity_too_large",), + 414: ("request_uri_too_large",), 415: ("unsupported_media_type", "unsupported_media", "media_type"), 416: ( "requested_range_not_satisfiable", @@ -76,10 +76,10 @@ 417: ("expectation_failed",), 418: ("im_a_teapot", "teapot", "i_am_a_teapot"), 421: ("misdirected_request",), - 422: ("unprocessable_entity", "unprocessable", "unprocessable_content"), + 422: ("unprocessable_entity", "unprocessable"), 423: ("locked",), 424: ("failed_dependency", "dependency"), - 425: ("unordered_collection", "unordered", "too_early"), + 425: ("unordered_collection", "unordered"), 426: ("upgrade_required", "upgrade"), 428: ("precondition_required", "precondition"), 429: ("too_many_requests", "too_many"), diff --git a/venv1/Lib/site-packages/pip/_vendor/requests/utils.py b/venv1/Lib/site-packages/pip/_vendor/requests/utils.py index e8ea5ad3..33f394d2 100644 --- a/venv1/Lib/site-packages/pip/_vendor/requests/utils.py +++ b/venv1/Lib/site-packages/pip/_vendor/requests/utils.py @@ -25,12 +25,7 @@ from .__version__ import __version__ # to_native_string is unused here, but imported here for backwards compatibility -from ._internal_utils import ( # noqa: F401 - _HEADER_VALIDATORS_BYTE, - _HEADER_VALIDATORS_STR, - HEADER_VALIDATORS, - to_native_string, -) +from ._internal_utils import HEADER_VALIDATORS, to_native_string # noqa: F401 from .compat import ( Mapping, basestring, @@ -38,7 +33,6 @@ getproxies, getproxies_environment, integer_types, - is_urllib3_1, ) from .compat import parse_http_list as _parse_list_header from .compat import ( @@ -98,8 +92,6 @@ def proxy_bypass_registry(host): # '' string by the localhost entry and the corresponding # canonical entry. proxyOverride = proxyOverride.split(";") - # filter out empty strings to avoid re.match return true in the following code. - proxyOverride = filter(None, proxyOverride) # now check if we match one of the registry values. for test in proxyOverride: if test == "": @@ -137,11 +129,6 @@ def super_len(o): total_length = None current_position = 0 - if not is_urllib3_1 and isinstance(o, str): - # urllib3 2.x+ treats all strings as utf-8 instead - # of latin-1 (iso-8859-1) like http.client. - o = o.encode("utf-8") - if hasattr(o, "__len__"): total_length = len(o) @@ -219,7 +206,14 @@ def get_netrc_auth(url, raise_errors=False): netrc_path = None for f in netrc_locations: - loc = os.path.expanduser(f) + try: + loc = os.path.expanduser(f) + except KeyError: + # os.path.expanduser can fail when $HOME is undefined and + # getpwuid fails. See https://bugs.python.org/issue20164 & + # https://github.com/psf/requests/issues/1846 + return + if os.path.exists(loc): netrc_path = loc break @@ -229,7 +223,13 @@ def get_netrc_auth(url, raise_errors=False): return ri = urlparse(url) - host = ri.hostname + + # Strip port numbers from netloc. This weird `if...encode`` dance is + # used for Python 3.2, which doesn't support unicode literals. + splitstr = b":" + if isinstance(url, str): + splitstr = splitstr.decode("ascii") + host = ri.netloc.split(splitstr)[0] try: _netrc = netrc(netrc_path).authenticators(host) @@ -461,7 +461,11 @@ def dict_from_cookiejar(cj): :rtype: dict """ - cookie_dict = {cookie.name: cookie.value for cookie in cj} + cookie_dict = {} + + for cookie in cj: + cookie_dict[cookie.name] = cookie.value + return cookie_dict @@ -758,7 +762,6 @@ def should_bypass_proxies(url, no_proxy): :rtype: bool """ - # Prioritize lowercase environment variables over uppercase # to keep a consistent behaviour with other http projects (curl, wget). def get_proxy(key): @@ -854,7 +857,7 @@ def select_proxy(url, proxies): def resolve_proxies(request, proxies, trust_env=True): """This method takes proxy information from a request and configuration input to resolve a mapping of target proxies. This will consider settings - such as NO_PROXY to strip proxy configurations. + such a NO_PROXY to strip proxy configurations. :param request: Request or PreparedRequest :param proxies: A dictionary of schemes or schemes and hosts to proxy URLs @@ -1028,25 +1031,22 @@ def check_header_validity(header): :param header: tuple, in the format (name, value). """ name, value = header - _validate_header_part(header, name, 0) - _validate_header_part(header, value, 1) + for part in header: + if type(part) not in HEADER_VALIDATORS: + raise InvalidHeader( + f"Header part ({part!r}) from {{{name!r}: {value!r}}} must be " + f"of type str or bytes, not {type(part)}" + ) + + _validate_header_part(name, "name", HEADER_VALIDATORS[type(name)][0]) + _validate_header_part(value, "value", HEADER_VALIDATORS[type(value)][1]) -def _validate_header_part(header, header_part, header_validator_index): - if isinstance(header_part, str): - validator = _HEADER_VALIDATORS_STR[header_validator_index] - elif isinstance(header_part, bytes): - validator = _HEADER_VALIDATORS_BYTE[header_validator_index] - else: - raise InvalidHeader( - f"Header part ({header_part!r}) from {header} " - f"must be of type str or bytes, not {type(header_part)}" - ) +def _validate_header_part(header_part, header_kind, validator): if not validator.match(header_part): - header_kind = "name" if header_validator_index == 0 else "value" raise InvalidHeader( - f"Invalid leading whitespace, reserved character(s), or return " + f"Invalid leading whitespace, reserved character(s), or return" f"character(s) in header {header_kind}: {header_part!r}" ) diff --git a/venv1/Lib/site-packages/pip/_vendor/resolvelib/__init__.py b/venv1/Lib/site-packages/pip/_vendor/resolvelib/__init__.py index 4c7f815a..d92acc7b 100644 --- a/venv1/Lib/site-packages/pip/_vendor/resolvelib/__init__.py +++ b/venv1/Lib/site-packages/pip/_vendor/resolvelib/__init__.py @@ -1,23 +1,22 @@ __all__ = [ + "__version__", "AbstractProvider", "AbstractResolver", "BaseReporter", "InconsistentCandidate", + "Resolver", "RequirementsConflicted", "ResolutionError", "ResolutionImpossible", "ResolutionTooDeep", - "Resolver", - "__version__", ] -__version__ = "1.2.1" +__version__ = "1.0.1" -from .providers import AbstractProvider +from .providers import AbstractProvider, AbstractResolver from .reporters import BaseReporter from .resolvers import ( - AbstractResolver, InconsistentCandidate, RequirementsConflicted, ResolutionError, diff --git a/venv1/Lib/site-packages/pip/_vendor/resolvelib/providers.py b/venv1/Lib/site-packages/pip/_vendor/resolvelib/providers.py index 524e3d83..e99d87ee 100644 --- a/venv1/Lib/site-packages/pip/_vendor/resolvelib/providers.py +++ b/venv1/Lib/site-packages/pip/_vendor/resolvelib/providers.py @@ -1,58 +1,30 @@ -from __future__ import annotations - -from typing import ( - TYPE_CHECKING, - Generic, - Iterable, - Iterator, - Mapping, - Sequence, -) - -from .structs import CT, KT, RT, Matches, RequirementInformation - -if TYPE_CHECKING: - from typing import Any, Protocol - - class Preference(Protocol): - def __lt__(self, __other: Any) -> bool: ... - - -class AbstractProvider(Generic[RT, CT, KT]): +class AbstractProvider(object): """Delegate class to provide the required interface for the resolver.""" - def identify(self, requirement_or_candidate: RT | CT) -> KT: - """Given a requirement or candidate, return an identifier for it. + def identify(self, requirement_or_candidate): + """Given a requirement, return an identifier for it. - This is used to identify, e.g. whether two requirements - should have their specifier parts merged or a candidate matches a - requirement via ``find_matches()``. + This is used to identify a requirement, e.g. whether two requirements + should have their specifier parts merged. """ raise NotImplementedError def get_preference( self, - identifier: KT, - resolutions: Mapping[KT, CT], - candidates: Mapping[KT, Iterator[CT]], - information: Mapping[KT, Iterator[RequirementInformation[RT, CT]]], - backtrack_causes: Sequence[RequirementInformation[RT, CT]], - ) -> Preference: + identifier, + resolutions, + candidates, + information, + backtrack_causes, + ): """Produce a sort key for given requirement based on preference. - As this is a sort key it will be called O(n) times per backtrack - step, where n is the number of `identifier`s, if you have a check - which is expensive in some sense. E.g. It needs to make O(n) checks - per call or takes significant wall clock time, consider using - `narrow_requirement_selection` to filter the `identifier`s, which - is applied before this sort key is called. - The preference is defined as "I think this requirement should be resolved first". The lower the return value is, the more preferred this group of arguments is. :param identifier: An identifier as returned by ``identify()``. This - identifies the requirement being considered. + identifies the dependency matches which should be returned. :param resolutions: Mapping of candidates currently pinned by the resolver. Each key is an identifier, and the value is a candidate. The candidate may conflict with requirements from ``information``. @@ -60,9 +32,8 @@ def get_preference( Each value is an iterator of candidates. :param information: Mapping of requirement information of each package. Each value is an iterator of *requirement information*. - :param backtrack_causes: Sequence of *requirement information* that are - the requirements that caused the resolver to most recently - backtrack. + :param backtrack_causes: Sequence of requirement information that were + the requirements that caused the resolver to most recently backtrack. A *requirement information* instance is a named tuple with two members: @@ -89,21 +60,15 @@ def get_preference( """ raise NotImplementedError - def find_matches( - self, - identifier: KT, - requirements: Mapping[KT, Iterator[RT]], - incompatibilities: Mapping[KT, Iterator[CT]], - ) -> Matches[CT]: + def find_matches(self, identifier, requirements, incompatibilities): """Find all possible candidates that satisfy the given constraints. - :param identifier: An identifier as returned by ``identify()``. All - candidates returned by this method should produce the same - identifier. + :param identifier: An identifier as returned by ``identify()``. This + identifies the dependency matches of which should be returned. :param requirements: A mapping of requirements that all returned candidates must satisfy. Each key is an identifier, and the value an iterator of requirements for that dependency. - :param incompatibilities: A mapping of known incompatibile candidates of + :param incompatibilities: A mapping of known incompatibilities of each dependency. Each key is an identifier, and the value an iterator of incompatibilities known to the resolver. All incompatibilities *must* be excluded from the return value. @@ -124,7 +89,7 @@ def find_matches( """ raise NotImplementedError - def is_satisfied_by(self, requirement: RT, candidate: CT) -> bool: + def is_satisfied_by(self, requirement, candidate): """Whether the given requirement can be satisfied by a candidate. The candidate is guaranteed to have been generated from the @@ -135,7 +100,7 @@ def is_satisfied_by(self, requirement: RT, candidate: CT) -> bool: """ raise NotImplementedError - def get_dependencies(self, candidate: CT) -> Iterable[RT]: + def get_dependencies(self, candidate): """Get dependencies of a candidate. This should return a collection of requirements that `candidate` @@ -143,54 +108,26 @@ def get_dependencies(self, candidate: CT) -> Iterable[RT]: """ raise NotImplementedError - def narrow_requirement_selection( - self, - identifiers: Iterable[KT], - resolutions: Mapping[KT, CT], - candidates: Mapping[KT, Iterator[CT]], - information: Mapping[KT, Iterator[RequirementInformation[RT, CT]]], - backtrack_causes: Sequence[RequirementInformation[RT, CT]], - ) -> Iterable[KT]: - """ - An optional method to narrow the selection of requirements being - considered during resolution. This method is called O(1) time per - backtrack step. - - :param identifiers: An iterable of `identifiers` as returned by - ``identify()``. These identify all requirements currently being - considered. - :param resolutions: A mapping of candidates currently pinned by the - resolver. Each key is an identifier, and the value is a candidate - that may conflict with requirements from ``information``. - :param candidates: A mapping of each dependency's possible candidates. - Each value is an iterator of candidates. - :param information: A mapping of requirement information for each package. - Each value is an iterator of *requirement information*. - :param backtrack_causes: A sequence of *requirement information* that are - the requirements causing the resolver to most recently - backtrack. - A *requirement information* instance is a named tuple with two members: +class AbstractResolver(object): + """The thing that performs the actual resolution work.""" - * ``requirement`` specifies a requirement contributing to the current - list of candidates. - * ``parent`` specifies the candidate that provides (is depended on for) - the requirement, or ``None`` to indicate a root requirement. - - Must return a non-empty subset of `identifiers`, with the default - implementation being to return `identifiers` unchanged. Those `identifiers` - will then be passed to the sort key `get_preference` to pick the most - prefered requirement to attempt to pin, unless `narrow_requirement_selection` - returns only 1 requirement, in which case that will be used without - calling the sort key `get_preference`. - - This method is designed to be used by the provider to optimize the - dependency resolution, e.g. if a check cost is O(m) and it can be done - against all identifiers at once then filtering the requirement selection - here will cost O(m) but making it part of the sort key in `get_preference` - will cost O(m*n), where n is the number of `identifiers`. - - Returns: - Iterable[KT]: A non-empty subset of `identifiers`. + base_exception = Exception + + def __init__(self, provider, reporter): + self.provider = provider + self.reporter = reporter + + def resolve(self, requirements, **kwargs): + """Take a collection of constraints, spit out the resolution result. + + This returns a representation of the final resolution state, with one + guarenteed attribute ``mapping`` that contains resolved candidates as + values. The keys are their respective identifiers. + + :param requirements: A collection of constraints. + :param kwargs: Additional keyword arguments that subclasses may accept. + + :raises: ``self.base_exception`` or its subclass. """ - return identifiers + raise NotImplementedError diff --git a/venv1/Lib/site-packages/pip/_vendor/resolvelib/py.typed b/venv1/Lib/site-packages/pip/_vendor/resolvelib/py.typed deleted file mode 100644 index e69de29b..00000000 diff --git a/venv1/Lib/site-packages/pip/_vendor/resolvelib/reporters.py b/venv1/Lib/site-packages/pip/_vendor/resolvelib/reporters.py index 6c142204..688b5e10 100644 --- a/venv1/Lib/site-packages/pip/_vendor/resolvelib/reporters.py +++ b/venv1/Lib/site-packages/pip/_vendor/resolvelib/reporters.py @@ -1,36 +1,26 @@ -from __future__ import annotations +class BaseReporter(object): + """Delegate class to provider progress reporting for the resolver.""" -from typing import TYPE_CHECKING, Collection, Generic - -from .structs import CT, KT, RT, RequirementInformation, State - -if TYPE_CHECKING: - from .resolvers import Criterion - - -class BaseReporter(Generic[RT, CT, KT]): - """Delegate class to provide progress reporting for the resolver.""" - - def starting(self) -> None: + def starting(self): """Called before the resolution actually starts.""" - def starting_round(self, index: int) -> None: + def starting_round(self, index): """Called before each round of resolution starts. The index is zero-based. """ - def ending_round(self, index: int, state: State[RT, CT, KT]) -> None: + def ending_round(self, index, state): """Called before each round of resolution ends. This is NOT called if the resolution ends at this round. Use `ending` if you want to report finalization. The index is zero-based. """ - def ending(self, state: State[RT, CT, KT]) -> None: + def ending(self, state): """Called before the resolution ends successfully.""" - def adding_requirement(self, requirement: RT, parent: CT | None) -> None: + def adding_requirement(self, requirement, parent): """Called when adding a new requirement into the resolve criteria. :param requirement: The additional requirement to be applied to filter @@ -40,16 +30,14 @@ def adding_requirement(self, requirement: RT, parent: CT | None) -> None: requirements passed in from ``Resolver.resolve()``. """ - def resolving_conflicts( - self, causes: Collection[RequirementInformation[RT, CT]] - ) -> None: + def resolving_conflicts(self, causes): """Called when starting to attempt requirement conflict resolution. :param causes: The information on the collision that caused the backtracking. """ - def rejecting_candidate(self, criterion: Criterion[RT, CT], candidate: CT) -> None: + def rejecting_candidate(self, criterion, candidate): """Called when rejecting a candidate during backtracking.""" - def pinning(self, candidate: CT) -> None: + def pinning(self, candidate): """Called when adding a candidate to the potential solution.""" diff --git a/venv1/Lib/site-packages/pip/_vendor/resolvelib/structs.py b/venv1/Lib/site-packages/pip/_vendor/resolvelib/structs.py index 18c74d41..359a34f6 100644 --- a/venv1/Lib/site-packages/pip/_vendor/resolvelib/structs.py +++ b/venv1/Lib/site-packages/pip/_vendor/resolvelib/structs.py @@ -1,73 +1,34 @@ -from __future__ import annotations - import itertools -from collections import namedtuple -from typing import ( - TYPE_CHECKING, - Callable, - Generic, - Iterable, - Iterator, - Mapping, - NamedTuple, - Sequence, - TypeVar, - Union, -) - -KT = TypeVar("KT") # Identifier. -RT = TypeVar("RT") # Requirement. -CT = TypeVar("CT") # Candidate. - -Matches = Union[Iterable[CT], Callable[[], Iterable[CT]]] - -if TYPE_CHECKING: - from .resolvers.criterion import Criterion - - class RequirementInformation(NamedTuple, Generic[RT, CT]): - requirement: RT - parent: CT | None - - class State(NamedTuple, Generic[RT, CT, KT]): - """Resolution state in a round.""" - - mapping: dict[KT, CT] - criteria: dict[KT, Criterion[RT, CT]] - backtrack_causes: list[RequirementInformation[RT, CT]] - -else: - RequirementInformation = namedtuple( - "RequirementInformation", ["requirement", "parent"] - ) - State = namedtuple("State", ["mapping", "criteria", "backtrack_causes"]) - - -class DirectedGraph(Generic[KT]): + +from .compat import collections_abc + + +class DirectedGraph(object): """A graph structure with directed edges.""" - def __init__(self) -> None: - self._vertices: set[KT] = set() - self._forwards: dict[KT, set[KT]] = {} # -> Set[] - self._backwards: dict[KT, set[KT]] = {} # -> Set[] + def __init__(self): + self._vertices = set() + self._forwards = {} # -> Set[] + self._backwards = {} # -> Set[] - def __iter__(self) -> Iterator[KT]: + def __iter__(self): return iter(self._vertices) - def __len__(self) -> int: + def __len__(self): return len(self._vertices) - def __contains__(self, key: KT) -> bool: + def __contains__(self, key): return key in self._vertices - def copy(self) -> DirectedGraph[KT]: + def copy(self): """Return a shallow copy of this graph.""" - other = type(self)() + other = DirectedGraph() other._vertices = set(self._vertices) other._forwards = {k: set(v) for k, v in self._forwards.items()} other._backwards = {k: set(v) for k, v in self._backwards.items()} return other - def add(self, key: KT) -> None: + def add(self, key): """Add a new vertex to the graph.""" if key in self._vertices: raise ValueError("vertex exists") @@ -75,7 +36,7 @@ def add(self, key: KT) -> None: self._forwards[key] = set() self._backwards[key] = set() - def remove(self, key: KT) -> None: + def remove(self, key): """Remove a vertex from the graph, disconnecting all edges from/to it.""" self._vertices.remove(key) for f in self._forwards.pop(key): @@ -83,10 +44,10 @@ def remove(self, key: KT) -> None: for t in self._backwards.pop(key): self._forwards[t].remove(key) - def connected(self, f: KT, t: KT) -> bool: + def connected(self, f, t): return f in self._backwards[t] and t in self._forwards[f] - def connect(self, f: KT, t: KT) -> None: + def connect(self, f, t): """Connect two existing vertices. Nothing happens if the vertices are already connected. @@ -96,59 +57,56 @@ def connect(self, f: KT, t: KT) -> None: self._forwards[f].add(t) self._backwards[t].add(f) - def iter_edges(self) -> Iterator[tuple[KT, KT]]: + def iter_edges(self): for f, children in self._forwards.items(): for t in children: yield f, t - def iter_children(self, key: KT) -> Iterator[KT]: + def iter_children(self, key): return iter(self._forwards[key]) - def iter_parents(self, key: KT) -> Iterator[KT]: + def iter_parents(self, key): return iter(self._backwards[key]) -class IteratorMapping(Mapping[KT, Iterator[CT]], Generic[RT, CT, KT]): - def __init__( - self, - mapping: Mapping[KT, RT], - accessor: Callable[[RT], Iterable[CT]], - appends: Mapping[KT, Iterable[CT]] | None = None, - ) -> None: +class IteratorMapping(collections_abc.Mapping): + def __init__(self, mapping, accessor, appends=None): self._mapping = mapping self._accessor = accessor - self._appends: Mapping[KT, Iterable[CT]] = appends or {} + self._appends = appends or {} - def __repr__(self) -> str: + def __repr__(self): return "IteratorMapping({!r}, {!r}, {!r})".format( self._mapping, self._accessor, self._appends, ) - def __bool__(self) -> bool: + def __bool__(self): return bool(self._mapping or self._appends) - def __contains__(self, key: object) -> bool: + __nonzero__ = __bool__ # XXX: Python 2. + + def __contains__(self, key): return key in self._mapping or key in self._appends - def __getitem__(self, k: KT) -> Iterator[CT]: + def __getitem__(self, k): try: v = self._mapping[k] except KeyError: return iter(self._appends[k]) return itertools.chain(self._accessor(v), self._appends.get(k, ())) - def __iter__(self) -> Iterator[KT]: + def __iter__(self): more = (k for k in self._appends if k not in self._mapping) return itertools.chain(self._mapping, more) - def __len__(self) -> int: + def __len__(self): more = sum(1 for k in self._appends if k not in self._mapping) return len(self._mapping) + more -class _FactoryIterableView(Iterable[RT]): +class _FactoryIterableView(object): """Wrap an iterator factory returned by `find_matches()`. Calling `iter()` on this class would invoke the underlying iterator @@ -157,53 +115,56 @@ class _FactoryIterableView(Iterable[RT]): built-in Python sequence types. """ - def __init__(self, factory: Callable[[], Iterable[RT]]) -> None: + def __init__(self, factory): self._factory = factory - self._iterable: Iterable[RT] | None = None + self._iterable = None - def __repr__(self) -> str: - return f"{type(self).__name__}({list(self)})" + def __repr__(self): + return "{}({})".format(type(self).__name__, list(self)) - def __bool__(self) -> bool: + def __bool__(self): try: next(iter(self)) except StopIteration: return False return True - def __iter__(self) -> Iterator[RT]: - iterable = self._factory() if self._iterable is None else self._iterable + __nonzero__ = __bool__ # XXX: Python 2. + + def __iter__(self): + iterable = ( + self._factory() if self._iterable is None else self._iterable + ) self._iterable, current = itertools.tee(iterable) return current -class _SequenceIterableView(Iterable[RT]): +class _SequenceIterableView(object): """Wrap an iterable returned by find_matches(). This is essentially just a proxy to the underlying sequence that provides the same interface as `_FactoryIterableView`. """ - def __init__(self, sequence: Sequence[RT]): + def __init__(self, sequence): self._sequence = sequence - def __repr__(self) -> str: - return f"{type(self).__name__}({self._sequence})" + def __repr__(self): + return "{}({})".format(type(self).__name__, self._sequence) - def __bool__(self) -> bool: + def __bool__(self): return bool(self._sequence) - def __iter__(self) -> Iterator[RT]: + __nonzero__ = __bool__ # XXX: Python 2. + + def __iter__(self): return iter(self._sequence) -def build_iter_view(matches: Matches[CT]) -> Iterable[CT]: +def build_iter_view(matches): """Build an iterable view from the value returned by `find_matches()`.""" if callable(matches): return _FactoryIterableView(matches) - if not isinstance(matches, Sequence): + if not isinstance(matches, collections_abc.Sequence): matches = list(matches) return _SequenceIterableView(matches) - - -IterableView = Iterable diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/__main__.py b/venv1/Lib/site-packages/pip/_vendor/rich/__main__.py index a583f1ef..270629fd 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/__main__.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/__main__.py @@ -207,7 +207,6 @@ def iter_last(values: Iterable[T]) -> Iterable[Tuple[bool, T]]: if __name__ == "__main__": # pragma: no cover - from pip._vendor.rich.panel import Panel console = Console( file=io.StringIO(), @@ -229,17 +228,47 @@ def iter_last(values: Iterable[T]) -> Iterable[Tuple[bool, T]]: c = Console(record=True) c.print(test_card) + print(f"rendered in {pre_cache_taken}ms (cold cache)") + print(f"rendered in {taken}ms (warm cache)") + + from pip._vendor.rich.panel import Panel + console = Console() - console.print(f"[dim]rendered in [not dim]{pre_cache_taken}ms[/] (cold cache)") - console.print(f"[dim]rendered in [not dim]{taken}ms[/] (warm cache)") - console.print() + + sponsor_message = Table.grid(padding=1) + sponsor_message.add_column(style="green", justify="right") + sponsor_message.add_column(no_wrap=True) + + sponsor_message.add_row( + "Textualize", + "[u blue link=https://github.com/textualize]https://github.com/textualize", + ) + sponsor_message.add_row( + "Twitter", + "[u blue link=https://twitter.com/willmcgugan]https://twitter.com/willmcgugan", + ) + + intro_message = Text.from_markup( + """\ +We hope you enjoy using Rich! + +Rich is maintained with [red]:heart:[/] by [link=https://www.textualize.io]Textualize.io[/] + +- Will McGugan""" + ) + + message = Table.grid(padding=2) + message.add_column() + message.add_column(no_wrap=True) + message.add_row(intro_message, sponsor_message) + console.print( Panel.fit( - "[b magenta]Hope you enjoy using Rich![/]\n\n" - "Please consider sponsoring me if you get value from my work.\n\n" - "Even the price of a ☕ can brighten my day!\n\n" - "https://github.com/sponsors/willmcgugan", - border_style="red", - title="Help ensure Rich is maintained", - ) + message, + box=box.ROUNDED, + padding=(1, 2), + title="[b red]Thanks for trying out Rich!", + border_style="bright_blue", + ), + justify="center", ) diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/_cell_widths.py b/venv1/Lib/site-packages/pip/_vendor/rich/_cell_widths.py index 608ae3a7..36286df3 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/_cell_widths.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/_cell_widths.py @@ -4,7 +4,6 @@ (0, 0, 0), (1, 31, -1), (127, 159, -1), - (173, 173, 0), (768, 879, 0), (1155, 1161, 0), (1425, 1469, 0), @@ -12,16 +11,13 @@ (1473, 1474, 0), (1476, 1477, 0), (1479, 1479, 0), - (1536, 1541, 0), (1552, 1562, 0), - (1564, 1564, 0), (1611, 1631, 0), (1648, 1648, 0), - (1750, 1757, 0), + (1750, 1756, 0), (1759, 1764, 0), (1767, 1768, 0), (1770, 1773, 0), - (1807, 1807, 0), (1809, 1809, 0), (1840, 1866, 0), (1958, 1968, 0), @@ -32,137 +28,149 @@ (2085, 2087, 0), (2089, 2093, 0), (2137, 2139, 0), - (2192, 2193, 0), - (2200, 2207, 0), - (2250, 2307, 0), - (2362, 2364, 0), - (2366, 2383, 0), + (2259, 2273, 0), + (2275, 2306, 0), + (2362, 2362, 0), + (2364, 2364, 0), + (2369, 2376, 0), + (2381, 2381, 0), (2385, 2391, 0), (2402, 2403, 0), - (2433, 2435, 0), + (2433, 2433, 0), (2492, 2492, 0), - (2494, 2500, 0), - (2503, 2504, 0), - (2507, 2509, 0), - (2519, 2519, 0), + (2497, 2500, 0), + (2509, 2509, 0), (2530, 2531, 0), (2558, 2558, 0), - (2561, 2563, 0), + (2561, 2562, 0), (2620, 2620, 0), - (2622, 2626, 0), + (2625, 2626, 0), (2631, 2632, 0), (2635, 2637, 0), (2641, 2641, 0), (2672, 2673, 0), (2677, 2677, 0), - (2689, 2691, 0), + (2689, 2690, 0), (2748, 2748, 0), - (2750, 2757, 0), - (2759, 2761, 0), - (2763, 2765, 0), + (2753, 2757, 0), + (2759, 2760, 0), + (2765, 2765, 0), (2786, 2787, 0), (2810, 2815, 0), - (2817, 2819, 0), + (2817, 2817, 0), (2876, 2876, 0), - (2878, 2884, 0), - (2887, 2888, 0), - (2891, 2893, 0), - (2901, 2903, 0), + (2879, 2879, 0), + (2881, 2884, 0), + (2893, 2893, 0), + (2901, 2902, 0), (2914, 2915, 0), (2946, 2946, 0), - (3006, 3010, 0), - (3014, 3016, 0), - (3018, 3021, 0), - (3031, 3031, 0), - (3072, 3076, 0), - (3132, 3132, 0), - (3134, 3140, 0), + (3008, 3008, 0), + (3021, 3021, 0), + (3072, 3072, 0), + (3076, 3076, 0), + (3134, 3136, 0), (3142, 3144, 0), (3146, 3149, 0), (3157, 3158, 0), (3170, 3171, 0), - (3201, 3203, 0), + (3201, 3201, 0), (3260, 3260, 0), - (3262, 3268, 0), - (3270, 3272, 0), - (3274, 3277, 0), - (3285, 3286, 0), + (3263, 3263, 0), + (3270, 3270, 0), + (3276, 3277, 0), (3298, 3299, 0), - (3315, 3315, 0), - (3328, 3331, 0), + (3328, 3329, 0), (3387, 3388, 0), - (3390, 3396, 0), - (3398, 3400, 0), - (3402, 3405, 0), - (3415, 3415, 0), + (3393, 3396, 0), + (3405, 3405, 0), (3426, 3427, 0), - (3457, 3459, 0), + (3457, 3457, 0), (3530, 3530, 0), - (3535, 3540, 0), + (3538, 3540, 0), (3542, 3542, 0), - (3544, 3551, 0), - (3570, 3571, 0), (3633, 3633, 0), (3636, 3642, 0), (3655, 3662, 0), (3761, 3761, 0), (3764, 3772, 0), - (3784, 3790, 0), + (3784, 3789, 0), (3864, 3865, 0), (3893, 3893, 0), (3895, 3895, 0), (3897, 3897, 0), - (3902, 3903, 0), - (3953, 3972, 0), + (3953, 3966, 0), + (3968, 3972, 0), (3974, 3975, 0), (3981, 3991, 0), (3993, 4028, 0), (4038, 4038, 0), - (4139, 4158, 0), - (4182, 4185, 0), + (4141, 4144, 0), + (4146, 4151, 0), + (4153, 4154, 0), + (4157, 4158, 0), + (4184, 4185, 0), (4190, 4192, 0), - (4194, 4196, 0), - (4199, 4205, 0), (4209, 4212, 0), - (4226, 4237, 0), - (4239, 4239, 0), - (4250, 4253, 0), + (4226, 4226, 0), + (4229, 4230, 0), + (4237, 4237, 0), + (4253, 4253, 0), (4352, 4447, 2), - (4448, 4607, 0), (4957, 4959, 0), - (5906, 5909, 0), + (5906, 5908, 0), (5938, 5940, 0), (5970, 5971, 0), (6002, 6003, 0), - (6068, 6099, 0), + (6068, 6069, 0), + (6071, 6077, 0), + (6086, 6086, 0), + (6089, 6099, 0), (6109, 6109, 0), - (6155, 6159, 0), + (6155, 6157, 0), (6277, 6278, 0), (6313, 6313, 0), - (6432, 6443, 0), - (6448, 6459, 0), - (6679, 6683, 0), - (6741, 6750, 0), - (6752, 6780, 0), + (6432, 6434, 0), + (6439, 6440, 0), + (6450, 6450, 0), + (6457, 6459, 0), + (6679, 6680, 0), + (6683, 6683, 0), + (6742, 6742, 0), + (6744, 6750, 0), + (6752, 6752, 0), + (6754, 6754, 0), + (6757, 6764, 0), + (6771, 6780, 0), (6783, 6783, 0), - (6832, 6862, 0), - (6912, 6916, 0), - (6964, 6980, 0), + (6832, 6848, 0), + (6912, 6915, 0), + (6964, 6964, 0), + (6966, 6970, 0), + (6972, 6972, 0), + (6978, 6978, 0), (7019, 7027, 0), - (7040, 7042, 0), - (7073, 7085, 0), - (7142, 7155, 0), - (7204, 7223, 0), + (7040, 7041, 0), + (7074, 7077, 0), + (7080, 7081, 0), + (7083, 7085, 0), + (7142, 7142, 0), + (7144, 7145, 0), + (7149, 7149, 0), + (7151, 7153, 0), + (7212, 7219, 0), + (7222, 7223, 0), (7376, 7378, 0), - (7380, 7400, 0), + (7380, 7392, 0), + (7394, 7400, 0), (7405, 7405, 0), (7412, 7412, 0), - (7415, 7417, 0), - (7616, 7679, 0), + (7416, 7417, 0), + (7616, 7673, 0), + (7675, 7679, 0), (8203, 8207, 0), (8232, 8238, 0), - (8288, 8292, 0), - (8294, 8303, 0), + (8288, 8291, 0), (8400, 8432, 0), (8986, 8987, 2), (9001, 9002, 2), @@ -204,16 +212,17 @@ (11904, 11929, 2), (11931, 12019, 2), (12032, 12245, 2), - (12272, 12329, 2), - (12330, 12335, 0), - (12336, 12350, 2), + (12272, 12283, 2), + (12288, 12329, 2), + (12330, 12333, 0), + (12334, 12350, 2), (12353, 12438, 2), (12441, 12442, 0), (12443, 12543, 2), (12549, 12591, 2), (12593, 12686, 2), (12688, 12771, 2), - (12783, 12830, 2), + (12784, 12830, 2), (12832, 12871, 2), (12880, 19903, 2), (19968, 42124, 2), @@ -225,33 +234,36 @@ (43010, 43010, 0), (43014, 43014, 0), (43019, 43019, 0), - (43043, 43047, 0), + (43045, 43046, 0), (43052, 43052, 0), - (43136, 43137, 0), - (43188, 43205, 0), + (43204, 43205, 0), (43232, 43249, 0), (43263, 43263, 0), (43302, 43309, 0), - (43335, 43347, 0), + (43335, 43345, 0), (43360, 43388, 2), - (43392, 43395, 0), - (43443, 43456, 0), + (43392, 43394, 0), + (43443, 43443, 0), + (43446, 43449, 0), + (43452, 43453, 0), (43493, 43493, 0), - (43561, 43574, 0), + (43561, 43566, 0), + (43569, 43570, 0), + (43573, 43574, 0), (43587, 43587, 0), - (43596, 43597, 0), - (43643, 43645, 0), + (43596, 43596, 0), + (43644, 43644, 0), (43696, 43696, 0), (43698, 43700, 0), (43703, 43704, 0), (43710, 43711, 0), (43713, 43713, 0), - (43755, 43759, 0), - (43765, 43766, 0), - (44003, 44010, 0), - (44012, 44013, 0), + (43756, 43757, 0), + (43766, 43766, 0), + (44005, 44005, 0), + (44008, 44008, 0), + (44013, 44013, 0), (44032, 55203, 2), - (55216, 55295, 0), (63744, 64255, 2), (64286, 64286, 0), (65024, 65039, 0), @@ -260,10 +272,8 @@ (65072, 65106, 2), (65108, 65126, 2), (65128, 65131, 2), - (65279, 65279, 0), (65281, 65376, 2), (65504, 65510, 2), - (65529, 65531, 0), (66045, 66045, 0), (66272, 66272, 0), (66422, 66426, 0), @@ -275,108 +285,102 @@ (68325, 68326, 0), (68900, 68903, 0), (69291, 69292, 0), - (69373, 69375, 0), (69446, 69456, 0), - (69506, 69509, 0), - (69632, 69634, 0), + (69633, 69633, 0), (69688, 69702, 0), - (69744, 69744, 0), - (69747, 69748, 0), - (69759, 69762, 0), - (69808, 69818, 0), - (69821, 69821, 0), - (69826, 69826, 0), - (69837, 69837, 0), + (69759, 69761, 0), + (69811, 69814, 0), + (69817, 69818, 0), (69888, 69890, 0), - (69927, 69940, 0), - (69957, 69958, 0), + (69927, 69931, 0), + (69933, 69940, 0), (70003, 70003, 0), - (70016, 70018, 0), - (70067, 70080, 0), + (70016, 70017, 0), + (70070, 70078, 0), (70089, 70092, 0), - (70094, 70095, 0), - (70188, 70199, 0), + (70095, 70095, 0), + (70191, 70193, 0), + (70196, 70196, 0), + (70198, 70199, 0), (70206, 70206, 0), - (70209, 70209, 0), - (70367, 70378, 0), - (70400, 70403, 0), + (70367, 70367, 0), + (70371, 70378, 0), + (70400, 70401, 0), (70459, 70460, 0), - (70462, 70468, 0), - (70471, 70472, 0), - (70475, 70477, 0), - (70487, 70487, 0), - (70498, 70499, 0), + (70464, 70464, 0), (70502, 70508, 0), (70512, 70516, 0), - (70709, 70726, 0), + (70712, 70719, 0), + (70722, 70724, 0), + (70726, 70726, 0), (70750, 70750, 0), - (70832, 70851, 0), - (71087, 71093, 0), - (71096, 71104, 0), + (70835, 70840, 0), + (70842, 70842, 0), + (70847, 70848, 0), + (70850, 70851, 0), + (71090, 71093, 0), + (71100, 71101, 0), + (71103, 71104, 0), (71132, 71133, 0), - (71216, 71232, 0), - (71339, 71351, 0), - (71453, 71467, 0), - (71724, 71738, 0), - (71984, 71989, 0), - (71991, 71992, 0), - (71995, 71998, 0), - (72000, 72000, 0), - (72002, 72003, 0), - (72145, 72151, 0), - (72154, 72160, 0), - (72164, 72164, 0), + (71219, 71226, 0), + (71229, 71229, 0), + (71231, 71232, 0), + (71339, 71339, 0), + (71341, 71341, 0), + (71344, 71349, 0), + (71351, 71351, 0), + (71453, 71455, 0), + (71458, 71461, 0), + (71463, 71467, 0), + (71727, 71735, 0), + (71737, 71738, 0), + (71995, 71996, 0), + (71998, 71998, 0), + (72003, 72003, 0), + (72148, 72151, 0), + (72154, 72155, 0), + (72160, 72160, 0), (72193, 72202, 0), - (72243, 72249, 0), + (72243, 72248, 0), (72251, 72254, 0), (72263, 72263, 0), - (72273, 72283, 0), - (72330, 72345, 0), - (72751, 72758, 0), - (72760, 72767, 0), + (72273, 72278, 0), + (72281, 72283, 0), + (72330, 72342, 0), + (72344, 72345, 0), + (72752, 72758, 0), + (72760, 72765, 0), + (72767, 72767, 0), (72850, 72871, 0), - (72873, 72886, 0), + (72874, 72880, 0), + (72882, 72883, 0), + (72885, 72886, 0), (73009, 73014, 0), (73018, 73018, 0), (73020, 73021, 0), (73023, 73029, 0), (73031, 73031, 0), - (73098, 73102, 0), (73104, 73105, 0), - (73107, 73111, 0), - (73459, 73462, 0), - (73472, 73473, 0), - (73475, 73475, 0), - (73524, 73530, 0), - (73534, 73538, 0), - (78896, 78912, 0), - (78919, 78933, 0), + (73109, 73109, 0), + (73111, 73111, 0), + (73459, 73460, 0), (92912, 92916, 0), (92976, 92982, 0), (94031, 94031, 0), - (94033, 94087, 0), (94095, 94098, 0), (94176, 94179, 2), (94180, 94180, 0), - (94192, 94193, 0), + (94192, 94193, 2), (94208, 100343, 2), (100352, 101589, 2), (101632, 101640, 2), - (110576, 110579, 2), - (110581, 110587, 2), - (110589, 110590, 2), - (110592, 110882, 2), - (110898, 110898, 2), + (110592, 110878, 2), (110928, 110930, 2), - (110933, 110933, 2), (110948, 110951, 2), (110960, 111355, 2), (113821, 113822, 0), - (113824, 113827, 0), - (118528, 118573, 0), - (118576, 118598, 0), - (119141, 119145, 0), - (119149, 119170, 0), + (119143, 119145, 0), + (119163, 119170, 0), (119173, 119179, 0), (119210, 119213, 0), (119362, 119364, 0), @@ -391,11 +395,8 @@ (122907, 122913, 0), (122915, 122916, 0), (122918, 122922, 0), - (123023, 123023, 0), (123184, 123190, 0), - (123566, 123566, 0), (123628, 123631, 0), - (124140, 124143, 0), (125136, 125142, 0), (125252, 125258, 0), (126980, 126980, 2), @@ -415,9 +416,7 @@ (127951, 127955, 2), (127968, 127984, 2), (127988, 127988, 2), - (127992, 127994, 2), - (127995, 127999, 0), - (128000, 128062, 2), + (127992, 128062, 2), (128064, 128064, 2), (128066, 128252, 2), (128255, 128317, 2), @@ -431,24 +430,22 @@ (128716, 128716, 2), (128720, 128722, 2), (128725, 128727, 2), - (128732, 128735, 2), (128747, 128748, 2), (128756, 128764, 2), (128992, 129003, 2), - (129008, 129008, 2), (129292, 129338, 2), (129340, 129349, 2), - (129351, 129535, 2), - (129648, 129660, 2), - (129664, 129672, 2), - (129680, 129725, 2), - (129727, 129733, 2), - (129742, 129755, 2), - (129760, 129768, 2), - (129776, 129784, 2), + (129351, 129400, 2), + (129402, 129483, 2), + (129485, 129535, 2), + (129648, 129652, 2), + (129656, 129658, 2), + (129664, 129670, 2), + (129680, 129704, 2), + (129712, 129718, 2), + (129728, 129730, 2), + (129744, 129750, 2), (131072, 196605, 2), (196608, 262141, 2), - (917505, 917505, 0), - (917536, 917631, 0), (917760, 917999, 0), ] diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/_export_format.py b/venv1/Lib/site-packages/pip/_vendor/rich/_export_format.py index e7527e52..094d2dc2 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/_export_format.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/_export_format.py @@ -1,6 +1,5 @@ CONSOLE_HTML_FORMAT = """\ - + -
{code}
+
{code}
""" diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/_inspect.py b/venv1/Lib/site-packages/pip/_vendor/rich/_inspect.py index 27d65cec..30446ceb 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/_inspect.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/_inspect.py @@ -1,3 +1,5 @@ +from __future__ import absolute_import + import inspect from inspect import cleandoc, getdoc, getfile, isclass, ismodule, signature from typing import Any, Collection, Iterable, Optional, Tuple, Type, Union @@ -214,7 +216,7 @@ def safe_getattr(attr_name: str) -> Tuple[Any, Any]: def _get_formatted_doc(self, object_: Any) -> Optional[str]: """ Extract the docstring of an object, process it and returns it. - The processing consists in cleaning up the docstring's indentation, + The processing consists in cleaning up the doctring's indentation, taking only its 1st paragraph if `self.help` is not True, and escape its control codes. diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/_null_file.py b/venv1/Lib/site-packages/pip/_vendor/rich/_null_file.py index 6ae05d3e..b659673e 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/_null_file.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/_null_file.py @@ -46,7 +46,7 @@ def __iter__(self) -> Iterator[str]: return iter([""]) def __enter__(self) -> IO[str]: - return self + pass def __exit__( self, diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/_ratio.py b/venv1/Lib/site-packages/pip/_vendor/rich/_ratio.py index 5fd5a383..e8a3a674 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/_ratio.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/_ratio.py @@ -1,6 +1,12 @@ +import sys from fractions import Fraction from math import ceil -from typing import cast, List, Optional, Sequence, Protocol +from typing import cast, List, Optional, Sequence + +if sys.version_info >= (3, 8): + from typing import Protocol +else: + from pip._vendor.typing_extensions import Protocol # pragma: no cover class Edge(Protocol): @@ -145,6 +151,7 @@ def ratio_distribute( @dataclass class E: + size: Optional[int] = None ratio: int = 1 minimum_size: int = 1 diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/_win32_console.py b/venv1/Lib/site-packages/pip/_vendor/rich/_win32_console.py index 2eba1b9b..81b10829 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/_win32_console.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/_win32_console.py @@ -2,7 +2,6 @@ The API that this module wraps is documented at https://docs.microsoft.com/en-us/windows/console/console-functions """ - import ctypes import sys from typing import Any @@ -381,7 +380,7 @@ def cursor_position(self) -> WindowsCoordinates: WindowsCoordinates: The current cursor position. """ coord: COORD = GetConsoleScreenBufferInfo(self._handle).dwCursorPosition - return WindowsCoordinates(row=coord.Y, col=coord.X) + return WindowsCoordinates(row=cast(int, coord.Y), col=cast(int, coord.X)) @property def screen_size(self) -> WindowsCoordinates: @@ -391,7 +390,9 @@ def screen_size(self) -> WindowsCoordinates: WindowsCoordinates: The width and height of the screen as WindowsCoordinates. """ screen_size: COORD = GetConsoleScreenBufferInfo(self._handle).dwSize - return WindowsCoordinates(row=screen_size.Y, col=screen_size.X) + return WindowsCoordinates( + row=cast(int, screen_size.Y), col=cast(int, screen_size.X) + ) def write_text(self, text: str) -> None: """Write text directly to the terminal without any modification of styles diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/_windows.py b/venv1/Lib/site-packages/pip/_vendor/rich/_windows.py index 7520a9f9..10fc0d7e 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/_windows.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/_windows.py @@ -30,6 +30,7 @@ class WindowsConsoleFeatures: ) except (AttributeError, ImportError, ValueError): + # Fallback if we can't load the Windows DLL def get_windows_console_features() -> WindowsConsoleFeatures: features = WindowsConsoleFeatures() diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/_wrap.py b/venv1/Lib/site-packages/pip/_vendor/rich/_wrap.py index 2e94ff6f..c45f193f 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/_wrap.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/_wrap.py @@ -1,7 +1,5 @@ -from __future__ import annotations - import re -from typing import Iterable +from typing import Iterable, List, Tuple from ._loop import loop_last from .cells import cell_len, chop_cells @@ -9,11 +7,7 @@ re_word = re.compile(r"\s*\S+\s*") -def words(text: str) -> Iterable[tuple[int, int, str]]: - """Yields each word from the text as a tuple - containing (start_index, end_index, word). A "word" in this context may - include the actual word and any whitespace to the right. - """ +def words(text: str) -> Iterable[Tuple[int, int, str]]: position = 0 word_match = re_word.match(text, position) while word_match is not None: @@ -23,59 +17,35 @@ def words(text: str) -> Iterable[tuple[int, int, str]]: word_match = re_word.match(text, end) -def divide_line(text: str, width: int, fold: bool = True) -> list[int]: - """Given a string of text, and a width (measured in cells), return a list - of cell offsets which the string should be split at in order for it to fit - within the given width. - - Args: - text: The text to examine. - width: The available cell width. - fold: If True, words longer than `width` will be folded onto a new line. - - Returns: - A list of indices to break the line at. - """ - break_positions: list[int] = [] # offsets to insert the breaks at - append = break_positions.append - cell_offset = 0 +def divide_line(text: str, width: int, fold: bool = True) -> List[int]: + divides: List[int] = [] + append = divides.append + line_position = 0 _cell_len = cell_len - for start, _end, word in words(text): word_length = _cell_len(word.rstrip()) - remaining_space = width - cell_offset - word_fits_remaining_space = remaining_space >= word_length - - if word_fits_remaining_space: - # Simplest case - the word fits within the remaining width for this line. - cell_offset += _cell_len(word) - else: - # Not enough space remaining for this word on the current line. + if line_position + word_length > width: if word_length > width: - # The word doesn't fit on any line, so we can't simply - # place it on the next line... if fold: - # Fold the word across multiple lines. - folded_word = chop_cells(word, width=width) - for last, line in loop_last(folded_word): + chopped_words = chop_cells(word, max_size=width, position=0) + for last, line in loop_last(chopped_words): if start: append(start) + if last: - cell_offset = _cell_len(line) + line_position = _cell_len(line) else: start += len(line) else: - # Folding isn't allowed, so crop the word. if start: append(start) - cell_offset = _cell_len(word) - elif cell_offset and start: - # The word doesn't fit within the remaining space on the current - # line, but it *can* fit on to the next (empty) line. + line_position = _cell_len(word) + elif line_position and start: append(start) - cell_offset = _cell_len(word) - - return break_positions + line_position = _cell_len(word) + else: + line_position += _cell_len(word) + return divides if __name__ == "__main__": # pragma: no cover @@ -83,11 +53,4 @@ def divide_line(text: str, width: int, fold: bool = True) -> list[int]: console = Console(width=10) console.print("12345 abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ 12345") - print(chop_cells("abcdefghijklmnopqrstuvwxyz", 10)) - - console = Console(width=20) - console.rule() - console.print("TextualはPythonの高速アプリケーション開発フレームワークです") - - console.rule() - console.print("アプリケーションは1670万色を使用でき") + print(chop_cells("abcdefghijklmnopqrstuvwxyz", 10, position=2)) diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/align.py b/venv1/Lib/site-packages/pip/_vendor/rich/align.py index e65dc5ba..c310b66e 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/align.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/align.py @@ -1,5 +1,11 @@ +import sys from itertools import chain -from typing import TYPE_CHECKING, Iterable, Optional, Literal +from typing import TYPE_CHECKING, Iterable, Optional + +if sys.version_info >= (3, 8): + from typing import Literal +else: + from pip._vendor.typing_extensions import Literal # pragma: no cover from .constrain import Constrain from .jupyter import JupyterMixin @@ -21,7 +27,7 @@ class Align(JupyterMixin): renderable (RenderableType): A console renderable. align (AlignMethod): One of "left", "center", or "right"" style (StyleType, optional): An optional style to apply to the background. - vertical (Optional[VerticalAlignMethod], optional): Optional vertical align, one of "top", "middle", or "bottom". Defaults to None. + vertical (Optional[VerticalAlginMethod], optional): Optional vertical align, one of "top", "middle", or "bottom". Defaults to None. pad (bool, optional): Pad the right with spaces. Defaults to True. width (int, optional): Restrict contents to given width, or None to use default width. Defaults to None. height (int, optional): Set height of align renderable, or None to fit to contents. Defaults to None. @@ -234,7 +240,6 @@ class VerticalCenter(JupyterMixin): Args: renderable (RenderableType): A renderable object. - style (StyleType, optional): An optional style to apply to the background. Defaults to None. """ def __init__( diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/ansi.py b/venv1/Lib/site-packages/pip/_vendor/rich/ansi.py index 7de86ce5..66365e65 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/ansi.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/ansi.py @@ -9,7 +9,6 @@ re_ansi = re.compile( r""" -(?:\x1b[0-?])| (?:\x1b\](.*?)\x1b\\)| (?:\x1b([(@-Z\\-_]|\[[0-?]*[ -/]*[@-~])) """, diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/bar.py b/venv1/Lib/site-packages/pip/_vendor/rich/bar.py index 022284b5..ed86a552 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/bar.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/bar.py @@ -48,6 +48,7 @@ def __repr__(self) -> str: def __rich_console__( self, console: Console, options: ConsoleOptions ) -> RenderResult: + width = min( self.width if self.width is not None else options.max_width, options.max_width, diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/box.py b/venv1/Lib/site-packages/pip/_vendor/rich/box.py index 3f330ccb..97d2a944 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/box.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/box.py @@ -1,4 +1,10 @@ -from typing import TYPE_CHECKING, Iterable, List, Literal +import sys +from typing import TYPE_CHECKING, Iterable, List + +if sys.version_info >= (3, 8): + from typing import Literal +else: + from pip._vendor.typing_extensions import Literal # pragma: no cover from ._loop import loop_last @@ -182,224 +188,260 @@ def get_bottom(self, widths: Iterable[int]) -> str: return "".join(parts) -# fmt: off ASCII: Box = Box( - "+--+\n" - "| ||\n" - "|-+|\n" - "| ||\n" - "|-+|\n" - "|-+|\n" - "| ||\n" - "+--+\n", + """\ ++--+ +| || +|-+| +| || +|-+| +|-+| +| || ++--+ +""", ascii=True, ) ASCII2: Box = Box( - "+-++\n" - "| ||\n" - "+-++\n" - "| ||\n" - "+-++\n" - "+-++\n" - "| ||\n" - "+-++\n", + """\ ++-++ +| || ++-++ +| || ++-++ ++-++ +| || ++-++ +""", ascii=True, ) ASCII_DOUBLE_HEAD: Box = Box( - "+-++\n" - "| ||\n" - "+=++\n" - "| ||\n" - "+-++\n" - "+-++\n" - "| ||\n" - "+-++\n", + """\ ++-++ +| || ++=++ +| || ++-++ ++-++ +| || ++-++ +""", ascii=True, ) SQUARE: Box = Box( - "┌─┬┐\n" - "│ ││\n" - "├─┼┤\n" - "│ ││\n" - "├─┼┤\n" - "├─┼┤\n" - "│ ││\n" - "└─┴┘\n" + """\ +┌─┬┐ +│ ││ +├─┼┤ +│ ││ +├─┼┤ +├─┼┤ +│ ││ +└─┴┘ +""" ) SQUARE_DOUBLE_HEAD: Box = Box( - "┌─┬┐\n" - "│ ││\n" - "╞═╪╡\n" - "│ ││\n" - "├─┼┤\n" - "├─┼┤\n" - "│ ││\n" - "└─┴┘\n" + """\ +┌─┬┐ +│ ││ +╞═╪╡ +│ ││ +├─┼┤ +├─┼┤ +│ ││ +└─┴┘ +""" ) MINIMAL: Box = Box( - " ╷ \n" - " │ \n" - "╶─┼╴\n" - " │ \n" - "╶─┼╴\n" - "╶─┼╴\n" - " │ \n" - " ╵ \n" + """\ + ╷ + │ +╶─┼╴ + │ +╶─┼╴ +╶─┼╴ + │ + ╵ +""" ) MINIMAL_HEAVY_HEAD: Box = Box( - " ╷ \n" - " │ \n" - "╺━┿╸\n" - " │ \n" - "╶─┼╴\n" - "╶─┼╴\n" - " │ \n" - " ╵ \n" + """\ + ╷ + │ +╺━┿╸ + │ +╶─┼╴ +╶─┼╴ + │ + ╵ +""" ) MINIMAL_DOUBLE_HEAD: Box = Box( - " ╷ \n" - " │ \n" - " ═╪ \n" - " │ \n" - " ─┼ \n" - " ─┼ \n" - " │ \n" - " ╵ \n" + """\ + ╷ + │ + ═╪ + │ + ─┼ + ─┼ + │ + ╵ +""" ) SIMPLE: Box = Box( - " \n" - " \n" - " ── \n" - " \n" - " \n" - " ── \n" - " \n" - " \n" + """\ + + + ── + + + ── + + +""" ) SIMPLE_HEAD: Box = Box( - " \n" - " \n" - " ── \n" - " \n" - " \n" - " \n" - " \n" - " \n" + """\ + + + ── + + + + + +""" ) SIMPLE_HEAVY: Box = Box( - " \n" - " \n" - " ━━ \n" - " \n" - " \n" - " ━━ \n" - " \n" - " \n" + """\ + + + ━━ + + + ━━ + + +""" ) HORIZONTALS: Box = Box( - " ── \n" - " \n" - " ── \n" - " \n" - " ── \n" - " ── \n" - " \n" - " ── \n" + """\ + ── + + ── + + ── + ── + + ── +""" ) ROUNDED: Box = Box( - "╭─┬╮\n" - "│ ││\n" - "├─┼┤\n" - "│ ││\n" - "├─┼┤\n" - "├─┼┤\n" - "│ ││\n" - "╰─┴╯\n" + """\ +╭─┬╮ +│ ││ +├─┼┤ +│ ││ +├─┼┤ +├─┼┤ +│ ││ +╰─┴╯ +""" ) HEAVY: Box = Box( - "┏━┳┓\n" - "┃ ┃┃\n" - "┣━╋┫\n" - "┃ ┃┃\n" - "┣━╋┫\n" - "┣━╋┫\n" - "┃ ┃┃\n" - "┗━┻┛\n" + """\ +┏━┳┓ +┃ ┃┃ +┣━╋┫ +┃ ┃┃ +┣━╋┫ +┣━╋┫ +┃ ┃┃ +┗━┻┛ +""" ) HEAVY_EDGE: Box = Box( - "┏━┯┓\n" - "┃ │┃\n" - "┠─┼┨\n" - "┃ │┃\n" - "┠─┼┨\n" - "┠─┼┨\n" - "┃ │┃\n" - "┗━┷┛\n" + """\ +┏━┯┓ +┃ │┃ +┠─┼┨ +┃ │┃ +┠─┼┨ +┠─┼┨ +┃ │┃ +┗━┷┛ +""" ) HEAVY_HEAD: Box = Box( - "┏━┳┓\n" - "┃ ┃┃\n" - "┡━╇┩\n" - "│ ││\n" - "├─┼┤\n" - "├─┼┤\n" - "│ ││\n" - "└─┴┘\n" + """\ +┏━┳┓ +┃ ┃┃ +┡━╇┩ +│ ││ +├─┼┤ +├─┼┤ +│ ││ +└─┴┘ +""" ) DOUBLE: Box = Box( - "╔═╦╗\n" - "║ ║║\n" - "╠═╬╣\n" - "║ ║║\n" - "╠═╬╣\n" - "╠═╬╣\n" - "║ ║║\n" - "╚═╩╝\n" + """\ +╔═╦╗ +║ ║║ +╠═╬╣ +║ ║║ +╠═╬╣ +╠═╬╣ +║ ║║ +╚═╩╝ +""" ) DOUBLE_EDGE: Box = Box( - "╔═╤╗\n" - "║ │║\n" - "╟─┼╢\n" - "║ │║\n" - "╟─┼╢\n" - "╟─┼╢\n" - "║ │║\n" - "╚═╧╝\n" + """\ +╔═╤╗ +║ │║ +╟─┼╢ +║ │║ +╟─┼╢ +╟─┼╢ +║ │║ +╚═╧╝ +""" ) MARKDOWN: Box = Box( - " \n" - "| ||\n" - "|-||\n" - "| ||\n" - "|-||\n" - "|-||\n" - "| ||\n" - " \n", + """\ + +| || +|-|| +| || +|-|| +|-|| +| || + +""", ascii=True, ) -# fmt: on # Map Boxes that don't render with raster fonts on to equivalent that do LEGACY_WINDOWS_SUBSTITUTIONS = { @@ -422,6 +464,7 @@ def get_bottom(self, widths: Iterable[int]) -> str: if __name__ == "__main__": # pragma: no cover + from pip._vendor.rich.columns import Columns from pip._vendor.rich.panel import Panel diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/cells.py b/venv1/Lib/site-packages/pip/_vendor/rich/cells.py index a8546227..9354f9e3 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/cells.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/cells.py @@ -1,33 +1,11 @@ -from __future__ import annotations - +import re from functools import lru_cache -from typing import Callable +from typing import Callable, List from ._cell_widths import CELL_WIDTHS -# Ranges of unicode ordinals that produce a 1-cell wide character -# This is non-exhaustive, but covers most common Western characters -_SINGLE_CELL_UNICODE_RANGES: list[tuple[int, int]] = [ - (0x20, 0x7E), # Latin (excluding non-printable) - (0xA0, 0xAC), - (0xAE, 0x002FF), - (0x00370, 0x00482), # Greek / Cyrillic - (0x02500, 0x025FC), # Box drawing, box elements, geometric shapes - (0x02800, 0x028FF), # Braille -] - -# A set of characters that are a single cell wide -_SINGLE_CELLS = frozenset( - [ - character - for _start, _end in _SINGLE_CELL_UNICODE_RANGES - for character in map(chr, range(_start, _end + 1)) - ] -) - -# When called with a string this will return True if all -# characters are single-cell, otherwise False -_is_single_cell_widths: Callable[[str], bool] = _SINGLE_CELLS.issuperset +# Regex to match sequence of the most common character ranges +_is_single_cell_widths = re.compile("^[\u0020-\u006f\u00a0\u02ff\u0370-\u0482]*$").match @lru_cache(4096) @@ -43,9 +21,9 @@ def cached_cell_len(text: str) -> int: Returns: int: Get the number of cells required to display text. """ - if _is_single_cell_widths(text): - return len(text) - return sum(map(get_character_cell_size, text)) + _get_size = get_character_cell_size + total_size = sum(_get_size(character) for character in text) + return total_size def cell_len(text: str, _cell_len: Callable[[str], int] = cached_cell_len) -> int: @@ -59,9 +37,9 @@ def cell_len(text: str, _cell_len: Callable[[str], int] = cached_cell_len) -> in """ if len(text) < 512: return _cell_len(text) - if _is_single_cell_widths(text): - return len(text) - return sum(map(get_character_cell_size, text)) + _get_size = get_character_cell_size + total_size = sum(_get_size(character) for character in text) + return total_size @lru_cache(maxsize=4096) @@ -74,7 +52,20 @@ def get_character_cell_size(character: str) -> int: Returns: int: Number of cells (0, 1 or 2) occupied by that character. """ - codepoint = ord(character) + return _get_codepoint_cell_size(ord(character)) + + +@lru_cache(maxsize=4096) +def _get_codepoint_cell_size(codepoint: int) -> int: + """Get the cell size of a character. + + Args: + codepoint (int): Codepoint of a character. + + Returns: + int: Number of cells (0, 1 or 2) occupied by that character. + """ + _table = CELL_WIDTHS lower_bound = 0 upper_bound = len(_table) - 1 @@ -128,44 +119,33 @@ def set_cell_size(text: str, total: int) -> str: start = pos -def chop_cells( - text: str, - width: int, -) -> list[str]: - """Split text into lines such that each line fits within the available (cell) width. - - Args: - text: The text to fold such that it fits in the given width. - width: The width available (number of cells). - - Returns: - A list of strings such that each string in the list has cell width - less than or equal to the available width. - """ +# TODO: This is inefficient +# TODO: This might not work with CWJ type characters +def chop_cells(text: str, max_size: int, position: int = 0) -> List[str]: + """Break text in to equal (cell) length strings, returning the characters in reverse + order""" _get_character_cell_size = get_character_cell_size - lines: list[list[str]] = [[]] - - append_new_line = lines.append - append_to_last_line = lines[-1].append - - total_width = 0 - - for character in text: - cell_width = _get_character_cell_size(character) - char_doesnt_fit = total_width + cell_width > width - - if char_doesnt_fit: - append_new_line([character]) - append_to_last_line = lines[-1].append - total_width = cell_width + characters = [ + (character, _get_character_cell_size(character)) for character in text + ] + total_size = position + lines: List[List[str]] = [[]] + append = lines[-1].append + + for character, size in reversed(characters): + if total_size + size > max_size: + lines.append([character]) + append = lines[-1].append + total_size = size else: - append_to_last_line(character) - total_width += cell_width + total_size += size + append(character) return ["".join(line) for line in lines] if __name__ == "__main__": # pragma: no cover + print(get_character_cell_size("😽")) for line in chop_cells("""这是对亚洲语言支持的测试。面对模棱两可的想法,拒绝猜测的诱惑。""", 8): print(line) diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/color.py b/venv1/Lib/site-packages/pip/_vendor/rich/color.py index e2c23a6a..dfe45593 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/color.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/color.py @@ -1,5 +1,5 @@ +import platform import re -import sys from colorsys import rgb_to_hls from enum import IntEnum from functools import lru_cache @@ -15,7 +15,7 @@ from .text import Text -WINDOWS = sys.platform == "win32" +WINDOWS = platform.system() == "Windows" class ColorSystem(IntEnum): @@ -592,6 +592,7 @@ def blend_rgb( if __name__ == "__main__": # pragma: no cover + from .console import Console from .table import Table from .text import Text diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/console.py b/venv1/Lib/site-packages/pip/_vendor/rich/console.py index db2ba55a..7c363dfd 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/console.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/console.py @@ -1,5 +1,6 @@ import inspect import os +import platform import sys import threading import zlib @@ -22,21 +23,27 @@ Dict, Iterable, List, - Literal, Mapping, NamedTuple, Optional, - Protocol, TextIO, Tuple, Type, Union, cast, - runtime_checkable, ) from pip._vendor.rich._null_file import NULL_FILE +if sys.version_info >= (3, 8): + from typing import Literal, Protocol, runtime_checkable +else: + from pip._vendor.typing_extensions import ( + Literal, + Protocol, + runtime_checkable, + ) # pragma: no cover + from . import errors, themes from ._emoji_replace import _emoji_replace from ._export_format import CONSOLE_HTML_FORMAT, CONSOLE_SVG_FORMAT @@ -69,7 +76,7 @@ JUPYTER_DEFAULT_COLUMNS = 115 JUPYTER_DEFAULT_LINES = 100 -WINDOWS = sys.platform == "win32" +WINDOWS = platform.system() == "Windows" HighlighterType = Callable[[Union[str, "Text"]], "Text"] JustifyMethod = Literal["default", "left", "center", "right", "full"] @@ -83,15 +90,15 @@ class NoChange: NO_CHANGE = NoChange() try: - _STDIN_FILENO = sys.__stdin__.fileno() # type: ignore[union-attr] + _STDIN_FILENO = sys.__stdin__.fileno() except Exception: _STDIN_FILENO = 0 try: - _STDOUT_FILENO = sys.__stdout__.fileno() # type: ignore[union-attr] + _STDOUT_FILENO = sys.__stdout__.fileno() except Exception: _STDOUT_FILENO = 1 try: - _STDERR_FILENO = sys.__stderr__.fileno() # type: ignore[union-attr] + _STDERR_FILENO = sys.__stderr__.fileno() except Exception: _STDERR_FILENO = 2 @@ -271,7 +278,6 @@ def __rich_console__( # A type that may be rendered by Console. RenderableType = Union[ConsoleRenderable, RichCast, str] -"""A string or any object that may be rendered by Rich.""" # The result of calling a __rich_console__ method. RenderResult = Iterable[Union[RenderableType, Segment]] @@ -494,7 +500,7 @@ def group(fit: bool = True) -> Callable[..., Callable[..., Group]]: """ def decorator( - method: Callable[..., Iterable[RenderableType]], + method: Callable[..., Iterable[RenderableType]] ) -> Callable[..., Group]: """Convert a method that returns an iterable of renderables in to a Group.""" @@ -729,18 +735,8 @@ def __init__( self.get_time = get_time or monotonic self.style = style self.no_color = ( - no_color - if no_color is not None - else self._environ.get("NO_COLOR", "") != "" + no_color if no_color is not None else "NO_COLOR" in self._environ ) - if force_interactive is None: - tty_interactive = self._environ.get("TTY_INTERACTIVE", None) - if tty_interactive is not None: - if tty_interactive == "0": - force_interactive = False - elif tty_interactive == "1": - force_interactive = True - self.is_interactive = ( (self.is_terminal and not self.is_dumb_terminal) if force_interactive is None @@ -753,7 +749,7 @@ def __init__( ) self._record_buffer: List[Segment] = [] self._render_hooks: List[RenderHook] = [] - self._live_stack: List[Live] = [] + self._live: Optional["Live"] = None self._is_alt_screen = False def __repr__(self) -> str: @@ -825,26 +821,24 @@ def _exit_buffer(self) -> None: self._buffer_index -= 1 self._check_buffer() - def set_live(self, live: "Live") -> bool: - """Set Live instance. Used by Live context manager (no need to call directly). + def set_live(self, live: "Live") -> None: + """Set Live instance. Used by Live context manager. Args: live (Live): Live instance using this Console. - Returns: - Boolean that indicates if the live is the topmost of the stack. - Raises: errors.LiveError: If this Console has a Live context currently active. """ with self._lock: - self._live_stack.append(live) - return len(self._live_stack) == 1 + if self._live is not None: + raise errors.LiveError("Only one live display may be active at once") + self._live = live def clear_live(self) -> None: - """Clear the Live instance. Used by the Live context manager (no need to call directly).""" + """Clear the Live instance.""" with self._lock: - self._live_stack.pop() + self._live = None def push_render_hook(self, hook: RenderHook) -> None: """Add a new render hook to the stack. @@ -939,13 +933,11 @@ def is_terminal(self) -> bool: Returns: bool: True if the console writing to a device capable of - understanding escape sequences, otherwise False. + understanding terminal codes, otherwise False. """ - # If dev has explicitly set this value, return it if self._force_terminal is not None: return self._force_terminal - # Fudge for Idle if hasattr(sys.stdin, "__module__") and sys.stdin.__module__.startswith( "idlelib" ): @@ -956,22 +948,11 @@ def is_terminal(self) -> bool: # return False for Jupyter, which may have FORCE_COLOR set return False - environ = self._environ - - tty_compatible = environ.get("TTY_COMPATIBLE", "") - # 0 indicates device is not tty compatible - if tty_compatible == "0": - return False - # 1 indicates device is tty compatible - if tty_compatible == "1": - return True - - # https://force-color.org/ - force_color = environ.get("FORCE_COLOR") + # If FORCE_COLOR env var has any value at all, we assume a terminal. + force_color = self._environ.get("FORCE_COLOR") if force_color is not None: - return force_color != "" + self._force_terminal = True - # Any other value defaults to auto detect isatty: Optional[Callable[[], bool]] = getattr(self.file, "isatty", None) try: return False if isatty is None else isatty() @@ -996,13 +977,12 @@ def is_dumb_terminal(self) -> bool: @property def options(self) -> ConsoleOptions: """Get default console options.""" - size = self.size return ConsoleOptions( - max_height=size.height, - size=size, + max_height=self.size.height, + size=self.size, legacy_windows=self.legacy_windows, min_width=1, - max_width=size.width, + max_width=self.width, encoding=self.encoding, is_terminal=self.is_terminal, ) @@ -1024,14 +1004,19 @@ def size(self) -> ConsoleDimensions: width: Optional[int] = None height: Optional[int] = None - streams = _STD_STREAMS_OUTPUT if WINDOWS else _STD_STREAMS - for file_descriptor in streams: + if WINDOWS: # pragma: no cover try: - width, height = os.get_terminal_size(file_descriptor) + width, height = os.get_terminal_size() except (AttributeError, ValueError, OSError): # Probably not a terminal pass - else: - break + else: + for file_descriptor in _STD_STREAMS: + try: + width, height = os.get_terminal_size(file_descriptor) + except (AttributeError, ValueError, OSError): + pass + else: + break columns = self._environ.get("COLUMNS") if columns is not None and columns.isdigit(): @@ -1322,7 +1307,7 @@ def render( renderable = rich_cast(renderable) if hasattr(renderable, "__rich_console__") and not isclass(renderable): - render_iterable = renderable.__rich_console__(self, _options) + render_iterable = renderable.__rich_console__(self, _options) # type: ignore[union-attr] elif isinstance(renderable, str): text_renderable = self.render_str( renderable, highlight=_options.highlight, markup=_options.markup @@ -1399,14 +1384,9 @@ def render_lines( extra_lines = render_options.height - len(lines) if extra_lines > 0: pad_line = [ - ( - [ - Segment(" " * render_options.max_width, style), - Segment("\n"), - ] - if new_lines - else [Segment(" " * render_options.max_width, style)] - ) + [Segment(" " * render_options.max_width, style), Segment("\n")] + if new_lines + else [Segment(" " * render_options.max_width, style)] ] lines.extend(pad_line * extra_lines) @@ -1455,11 +1435,9 @@ def render_str( rich_text.overflow = overflow else: rich_text = Text( - ( - _emoji_replace(text, default_variant=self._emoji_variant) - if emoji_enabled - else text - ), + _emoji_replace(text, default_variant=self._emoji_variant) + if emoji_enabled + else text, justify=justify, overflow=overflow, style=style, @@ -1556,11 +1534,7 @@ def check_text() -> None: if isinstance(renderable, str): append_text( self.render_str( - renderable, - emoji=emoji, - markup=markup, - highlight=highlight, - highlighter=_highlighter, + renderable, emoji=emoji, markup=markup, highlighter=_highlighter ) ) elif isinstance(renderable, Text): @@ -1950,6 +1924,7 @@ def log( end (str, optional): String to write at end of print data. Defaults to "\\\\n". style (Union[str, Style], optional): A style to apply to output. Defaults to None. justify (str, optional): One of "left", "right", "center", or "full". Defaults to ``None``. + overflow (str, optional): Overflow method: "crop", "fold", or "ellipsis". Defaults to None. emoji (Optional[bool], optional): Enable emoji code, or ``None`` to use console default. Defaults to None. markup (Optional[bool], optional): Enable markup, or ``None`` to use console default. Defaults to None. highlight (Optional[bool], optional): Enable automatic highlighting, or ``None`` to use console default. Defaults to None. @@ -2010,20 +1985,6 @@ def log( ): buffer_extend(line) - def on_broken_pipe(self) -> None: - """This function is called when a `BrokenPipeError` is raised. - - This can occur when piping Textual output in Linux and macOS. - The default implementation is to exit the app, but you could implement - this method in a subclass to change the behavior. - - See https://docs.python.org/3/library/signal.html#note-on-sigpipe for details. - """ - self.quiet = True - devnull = os.open(os.devnull, os.O_WRONLY) - os.dup2(devnull, sys.stdout.fileno()) - raise SystemExit(1) - def _check_buffer(self) -> None: """Check if the buffer may be rendered. Render it if it can (e.g. Console.quiet is False) Rendering is supported on Windows, Unix and Jupyter environments. For @@ -2033,21 +1994,13 @@ def _check_buffer(self) -> None: if self.quiet: del self._buffer[:] return - - try: - self._write_buffer() - except BrokenPipeError: - self.on_broken_pipe() - - def _write_buffer(self) -> None: - """Write the buffer to the output file.""" - with self._lock: - if self.record and not self._buffer_index: + if self.record: with self._record_buffer_lock: self._record_buffer.extend(self._buffer[:]) if self._buffer_index == 0: + if self.is_jupyter: # pragma: no cover from .jupyter import display @@ -2213,7 +2166,7 @@ def save_text(self, path: str, *, clear: bool = True, styles: bool = False) -> N """ text = self.export_text(clear=clear, styles=styles) - with open(path, "w", encoding="utf-8") as write_file: + with open(path, "wt", encoding="utf-8") as write_file: write_file.write(text) def export_html( @@ -2319,7 +2272,7 @@ def save_html( code_format=code_format, inline_styles=inline_styles, ) - with open(path, "w", encoding="utf-8") as write_file: + with open(path, "wt", encoding="utf-8") as write_file: write_file.write(html) def export_svg( @@ -2608,7 +2561,7 @@ def save_svg( font_aspect_ratio=font_aspect_ratio, unique_id=unique_id, ) - with open(path, "w", encoding="utf-8") as write_file: + with open(path, "wt", encoding="utf-8") as write_file: write_file.write(svg) diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/containers.py b/venv1/Lib/site-packages/pip/_vendor/rich/containers.py index 901ff8ba..e29cf368 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/containers.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/containers.py @@ -1,13 +1,13 @@ from itertools import zip_longest from typing import ( - TYPE_CHECKING, - Iterable, Iterator, + Iterable, List, Optional, - TypeVar, Union, overload, + TypeVar, + TYPE_CHECKING, ) if TYPE_CHECKING: @@ -119,7 +119,7 @@ def justify( Args: console (Console): Console instance. - width (int): Number of cells available per line. + width (int): Number of characters per line. justify (str, optional): Default justify method for text: "left", "center", "full" or "right". Defaults to "left". overflow (str, optional): Default overflow for text: "crop", "fold", or "ellipsis". Defaults to "fold". diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/control.py b/venv1/Lib/site-packages/pip/_vendor/rich/control.py index 84963e9d..88fcb929 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/control.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/control.py @@ -1,5 +1,11 @@ +import sys import time -from typing import TYPE_CHECKING, Callable, Dict, Iterable, List, Union, Final +from typing import TYPE_CHECKING, Callable, Dict, Iterable, List, Union + +if sys.version_info >= (3, 8): + from typing import Final +else: + from pip._vendor.typing_extensions import Final # pragma: no cover from .segment import ControlCode, ControlType, Segment diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/default_styles.py b/venv1/Lib/site-packages/pip/_vendor/rich/default_styles.py index 61797bf3..dca37193 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/default_styles.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/default_styles.py @@ -54,7 +54,7 @@ "logging.level.notset": Style(dim=True), "logging.level.debug": Style(color="green"), "logging.level.info": Style(color="blue"), - "logging.level.warning": Style(color="yellow"), + "logging.level.warning": Style(color="red"), "logging.level.error": Style(color="red", bold=True), "logging.level.critical": Style(color="red", bold=True, reverse=True), "log.level": Style.null(), @@ -120,9 +120,6 @@ "traceback.exc_type": Style(color="bright_red", bold=True), "traceback.exc_value": Style.null(), "traceback.offset": Style(color="bright_red", bold=True), - "traceback.error_range": Style(underline=True, bold=True), - "traceback.note": Style(color="green", bold=True), - "traceback.group.border": Style(color="magenta"), "bar.back": Style(color="grey23"), "bar.complete": Style(color="rgb(249,38,114)"), "bar.finished": Style(color="rgb(114,156,31)"), diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/diagnose.py b/venv1/Lib/site-packages/pip/_vendor/rich/diagnose.py index 92893b32..ad361838 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/diagnose.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/diagnose.py @@ -15,18 +15,16 @@ def report() -> None: # pragma: no cover inspect(features) env_names = ( - "CLICOLOR", + "TERM", "COLORTERM", + "CLICOLOR", + "NO_COLOR", + "TERM_PROGRAM", "COLUMNS", - "JPY_PARENT_PID", + "LINES", "JUPYTER_COLUMNS", "JUPYTER_LINES", - "LINES", - "NO_COLOR", - "TERM_PROGRAM", - "TERM", - "TTY_COMPATIBLE", - "TTY_INTERACTIVE", + "JPY_PARENT_PID", "VSCODE_VERBOSE_LOGGING", ) env = {name: os.getenv(name) for name in env_names} diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/emoji.py b/venv1/Lib/site-packages/pip/_vendor/rich/emoji.py index 4a667edd..791f0465 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/emoji.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/emoji.py @@ -1,5 +1,5 @@ import sys -from typing import TYPE_CHECKING, Optional, Union, Literal +from typing import TYPE_CHECKING, Optional, Union from .jupyter import JupyterMixin from .segment import Segment @@ -7,6 +7,11 @@ from ._emoji_codes import EMOJI from ._emoji_replace import _emoji_replace +if sys.version_info >= (3, 8): + from typing import Literal +else: + from pip._vendor.typing_extensions import Literal # pragma: no cover + if TYPE_CHECKING: from .console import Console, ConsoleOptions, RenderResult diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/filesize.py b/venv1/Lib/site-packages/pip/_vendor/rich/filesize.py index 83bc9118..99f118e2 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/filesize.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/filesize.py @@ -1,3 +1,4 @@ +# coding: utf-8 """Functions for reporting filesizes. Borrowed from https://github.com/PyFilesystem/pyfilesystem2 The functions declared in this module should cover the different @@ -26,7 +27,7 @@ def _to_str( if size == 1: return "1 byte" elif size < base: - return f"{size:,} bytes" + return "{:,} bytes".format(size) for i, suffix in enumerate(suffixes, 2): # noqa: B007 unit = base**i diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/highlighter.py b/venv1/Lib/site-packages/pip/_vendor/rich/highlighter.py index e4c462e2..c2646794 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/highlighter.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/highlighter.py @@ -98,7 +98,7 @@ class ReprHighlighter(RegexHighlighter): r"(?P(?\B(/[-\w._+]+)*\/)(?P[-\w._+]*)?", r"(?b?'''.*?(?(file|https|http|ws|wss)://[-0-9a-zA-Z$_+!`(),.?/;:&=%#~@]*)", + r"(?P(file|https|http|ws|wss)://[-0-9a-zA-Z$_+!`(),.?/;:&=%#]*)", ), ] diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/json.py b/venv1/Lib/site-packages/pip/_vendor/rich/json.py index 4087c79b..ea94493f 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/json.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/json.py @@ -103,6 +103,7 @@ def __rich__(self) -> Text: if __name__ == "__main__": + import argparse import sys diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/layout.py b/venv1/Lib/site-packages/pip/_vendor/rich/layout.py index a6f1a31b..849356ea 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/layout.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/layout.py @@ -227,6 +227,7 @@ def tree(self) -> "Tree": from pip._vendor.rich.tree import Tree def summary(layout: "Layout") -> Table: + icon = layout.splitter.get_tree_icon() table = Table.grid(padding=(0, 1, 0, 0)) @@ -402,7 +403,7 @@ def __rich_console__( self._render_map = render_map layout_lines: List[List[Segment]] = [[] for _ in range(height)] _islice = islice - for region, lines in render_map.values(): + for (region, lines) in render_map.values(): _x, y, _layout_width, layout_height = region for row, line in zip( _islice(layout_lines, y, y + layout_height), lines diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/live.py b/venv1/Lib/site-packages/pip/_vendor/rich/live.py index cc3a39bd..3ebbbc4c 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/live.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/live.py @@ -1,12 +1,10 @@ -from __future__ import annotations - import sys from threading import Event, RLock, Thread from types import TracebackType -from typing import IO, TYPE_CHECKING, Any, Callable, List, Optional, TextIO, Type, cast +from typing import IO, Any, Callable, List, Optional, TextIO, Type, cast from . import get_console -from .console import Console, ConsoleRenderable, Group, RenderableType, RenderHook +from .console import Console, ConsoleRenderable, RenderableType, RenderHook from .control import Control from .file_proxy import FileProxy from .jupyter import JupyterMixin @@ -14,10 +12,6 @@ from .screen import Screen from .text import Text -if TYPE_CHECKING: - # Can be replaced with `from typing import Self` in Python 3.11+ - from typing_extensions import Self # pragma: no cover - class _RefreshThread(Thread): """A thread that calls refresh() at regular intervals.""" @@ -43,7 +37,7 @@ class Live(JupyterMixin, RenderHook): Args: renderable (RenderableType, optional): The renderable to live display. Defaults to displaying nothing. - console (Console, optional): Optional Console instance. Defaults to an internal Console instance writing to stdout. + console (Console, optional): Optional Console instance. Default will an internal Console instance writing to stdout. screen (bool, optional): Enable alternate screen mode. Defaults to False. auto_refresh (bool, optional): Enable auto refresh. If disabled, you will need to call `refresh()` or `update()` with refresh flag. Defaults to True refresh_per_second (float, optional): Number of times per second to refresh the live display. Defaults to 4. @@ -93,7 +87,6 @@ def __init__( self._live_render = LiveRender( self.get_renderable(), vertical_overflow=vertical_overflow ) - self._nested = False @property def is_started(self) -> bool: @@ -117,12 +110,8 @@ def start(self, refresh: bool = False) -> None: with self._lock: if self._started: return + self.console.set_live(self) self._started = True - - if not self.console.set_live(self): - self._nested = True - return - if self._screen: self._alt_screen = self.console.set_alt_screen(True) self.console.show_cursor(False) @@ -147,12 +136,8 @@ def stop(self) -> None: with self._lock: if not self._started: return - self._started = False self.console.clear_live() - if self._nested: - if not self.transient: - self.console.print(self.renderable) - return + self._started = False if self.auto_refresh and self._refresh_thread is not None: self._refresh_thread.stop() @@ -171,12 +156,13 @@ def stop(self) -> None: self.console.show_cursor(True) if self._alt_screen: self.console.set_alt_screen(False) + if self.transient and not self._alt_screen: self.console.control(self._live_render.restore_cursor()) if self.ipy_widget is not None and self.transient: self.ipy_widget.close() # pragma: no cover - def __enter__(self) -> Self: + def __enter__(self) -> "Live": self.start(refresh=self._renderable is not None) return self @@ -214,13 +200,7 @@ def renderable(self) -> RenderableType: Returns: RenderableType: Displayed renderable. """ - live_stack = self.console._live_stack - renderable: RenderableType - if live_stack and self is live_stack[0]: - # The first Live instance will render everything in the Live stack - renderable = Group(*[live.get_renderable() for live in live_stack]) - else: - renderable = self.get_renderable() + renderable = self.get_renderable() return Screen(renderable) if self._alt_screen else renderable def update(self, renderable: RenderableType, *, refresh: bool = False) -> None: @@ -241,11 +221,6 @@ def refresh(self) -> None: """Update the display of the Live Render.""" with self._lock: self._live_render.set_renderable(self.renderable) - if self._nested: - if self.console._live_stack: - self.console._live_stack[0].refresh() - return - if self.console.is_jupyter: # pragma: no cover try: from IPython.display import display @@ -387,7 +362,7 @@ def process_renderables( table.add_column("Destination Currency") table.add_column("Exchange Rate") - for (source, dest), exchange_rate in exchange_rate_dict.items(): + for ((source, dest), exchange_rate) in exchange_rate_dict.items(): table.add_row( source, dest, diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/live_render.py b/venv1/Lib/site-packages/pip/_vendor/rich/live_render.py index d3da5111..b90fbf7f 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/live_render.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/live_render.py @@ -1,4 +1,10 @@ -from typing import Optional, Tuple, Literal +import sys +from typing import Optional, Tuple + +if sys.version_info >= (3, 8): + from typing import Literal +else: + from pip._vendor.typing_extensions import Literal # pragma: no cover from ._loop import loop_last @@ -76,6 +82,7 @@ def restore_cursor(self) -> Control: def __rich_console__( self, console: Console, options: ConsoleOptions ) -> RenderResult: + renderable = self.renderable style = console.get_style(self.style) lines = console.render_lines(renderable, options, style=style, pad=False) diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/logging.py b/venv1/Lib/site-packages/pip/_vendor/rich/logging.py index 08f34c70..91368dda 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/logging.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/logging.py @@ -36,13 +36,11 @@ class RichHandler(Handler): markup (bool, optional): Enable console markup in log messages. Defaults to False. rich_tracebacks (bool, optional): Enable rich tracebacks with syntax highlighting and formatting. Defaults to False. tracebacks_width (Optional[int], optional): Number of characters used to render tracebacks, or None for full width. Defaults to None. - tracebacks_code_width (int, optional): Number of code characters used to render tracebacks, or None for full width. Defaults to 88. tracebacks_extra_lines (int, optional): Additional lines of code to render tracebacks, or None for full width. Defaults to None. tracebacks_theme (str, optional): Override pygments theme used in traceback. tracebacks_word_wrap (bool, optional): Enable word wrapping of long tracebacks lines. Defaults to True. tracebacks_show_locals (bool, optional): Enable display of locals in tracebacks. Defaults to False. tracebacks_suppress (Sequence[Union[str, ModuleType]]): Optional sequence of modules or paths to exclude from traceback. - tracebacks_max_frames (int, optional): Optional maximum number of frames returned by traceback. locals_max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation. Defaults to 10. locals_max_string (int, optional): Maximum length of string before truncating, or None to disable. Defaults to 80. @@ -76,13 +74,11 @@ def __init__( markup: bool = False, rich_tracebacks: bool = False, tracebacks_width: Optional[int] = None, - tracebacks_code_width: Optional[int] = 88, tracebacks_extra_lines: int = 3, tracebacks_theme: Optional[str] = None, tracebacks_word_wrap: bool = True, tracebacks_show_locals: bool = False, tracebacks_suppress: Iterable[Union[str, ModuleType]] = (), - tracebacks_max_frames: int = 100, locals_max_length: int = 10, locals_max_string: int = 80, log_time_format: Union[str, FormatTimeCallable] = "[%x %X]", @@ -108,8 +104,6 @@ def __init__( self.tracebacks_word_wrap = tracebacks_word_wrap self.tracebacks_show_locals = tracebacks_show_locals self.tracebacks_suppress = tracebacks_suppress - self.tracebacks_max_frames = tracebacks_max_frames - self.tracebacks_code_width = tracebacks_code_width self.locals_max_length = locals_max_length self.locals_max_string = locals_max_string self.keywords = keywords @@ -146,7 +140,6 @@ def emit(self, record: LogRecord) -> None: exc_value, exc_traceback, width=self.tracebacks_width, - code_width=self.tracebacks_code_width, extra_lines=self.tracebacks_extra_lines, theme=self.tracebacks_theme, word_wrap=self.tracebacks_word_wrap, @@ -154,7 +147,6 @@ def emit(self, record: LogRecord) -> None: locals_max_length=self.locals_max_length, locals_max_string=self.locals_max_string, suppress=self.tracebacks_suppress, - max_frames=self.tracebacks_max_frames, ) message = record.getMessage() if self.formatter: diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/markup.py b/venv1/Lib/site-packages/pip/_vendor/rich/markup.py index f6171878..fd80d8c1 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/markup.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/markup.py @@ -64,9 +64,6 @@ def escape_backslashes(match: Match[str]) -> str: return f"{backslashes}{backslashes}\\{text}" markup = _escape(escape_backslashes, markup) - if markup.endswith("\\") and not markup.endswith("\\\\"): - return markup + "\\" - return markup @@ -113,10 +110,7 @@ def render( Args: markup (str): A string containing console markup. - style: (Union[str, Style]): The style to use. emoji (bool, optional): Also render emoji code. Defaults to True. - emoji_variant (str, optional): Optional emoji variant, either "text" or "emoji". Defaults to None. - Raises: MarkupError: If there is a syntax error in the markup. @@ -232,6 +226,7 @@ def pop_style(style_name: str) -> Tuple[int, Tag]: if __name__ == "__main__": # pragma: no cover + MARKUP = [ "[red]Hello World[/red]", "[magenta]Hello [b]World[/b]", diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/padding.py b/venv1/Lib/site-packages/pip/_vendor/rich/padding.py index 0161cd18..1b2204f5 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/padding.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/padding.py @@ -1,4 +1,4 @@ -from typing import TYPE_CHECKING, List, Optional, Tuple, Union +from typing import cast, List, Optional, Tuple, TYPE_CHECKING, Union if TYPE_CHECKING: from .console import ( @@ -7,11 +7,11 @@ RenderableType, RenderResult, ) - from .jupyter import JupyterMixin from .measure import Measurement -from .segment import Segment from .style import Style +from .segment import Segment + PaddingDimensions = Union[int, Tuple[int], Tuple[int, int], Tuple[int, int, int, int]] @@ -66,10 +66,10 @@ def unpack(pad: "PaddingDimensions") -> Tuple[int, int, int, int]: _pad = pad[0] return (_pad, _pad, _pad, _pad) if len(pad) == 2: - pad_top, pad_right = pad + pad_top, pad_right = cast(Tuple[int, int], pad) return (pad_top, pad_right, pad_top, pad_right) if len(pad) == 4: - top, right, bottom, left = pad + top, right, bottom, left = cast(Tuple[int, int, int, int], pad) return (top, right, bottom, left) raise ValueError(f"1, 2 or 4 integers required for padding; {len(pad)} given") diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/panel.py b/venv1/Lib/site-packages/pip/_vendor/rich/panel.py index 07587e3b..d522d80b 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/panel.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/panel.py @@ -22,13 +22,11 @@ class Panel(JupyterMixin): Args: renderable (RenderableType): A console renderable object. - box (Box): A Box instance that defines the look of the border (see :ref:`appendix_box`. Defaults to box.ROUNDED. - title (Optional[TextType], optional): Optional title displayed in panel header. Defaults to None. - title_align (AlignMethod, optional): Alignment of title. Defaults to "center". - subtitle (Optional[TextType], optional): Optional subtitle displayed in panel footer. Defaults to None. - subtitle_align (AlignMethod, optional): Alignment of subtitle. Defaults to "center". + box (Box, optional): A Box instance that defines the look of the border (see :ref:`appendix_box`. + Defaults to box.ROUNDED. safe_box (bool, optional): Disable box characters that don't display on windows legacy terminal with *raster* fonts. Defaults to True. - expand (bool, optional): If True the panel will stretch to fill the console width, otherwise it will be sized to fit the contents. Defaults to True. + expand (bool, optional): If True the panel will stretch to fill the console + width, otherwise it will be sized to fit the contents. Defaults to True. style (str, optional): The style of the panel (border and contents). Defaults to "none". border_style (str, optional): The style of the border. Defaults to "none". width (Optional[int], optional): Optional width of panel. Defaults to None to auto-detect. @@ -84,9 +82,7 @@ def fit( style: StyleType = "none", border_style: StyleType = "none", width: Optional[int] = None, - height: Optional[int] = None, padding: PaddingDimensions = (0, 1), - highlight: bool = False, ) -> "Panel": """An alternative constructor that sets expand=False.""" return cls( @@ -100,9 +96,7 @@ def fit( style=style, border_style=border_style, width=width, - height=height, padding=padding, - highlight=highlight, expand=False, ) @@ -174,9 +168,6 @@ def align_text( text = text.copy() text.truncate(width) excess_space = width - cell_len(text.plain) - if text.style: - text.stylize(console.get_style(text.style)) - if excess_space: if align == "left": return Text.assemble( diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/pretty.py b/venv1/Lib/site-packages/pip/_vendor/rich/pretty.py index c4a274f8..2bd9eb00 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/pretty.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/pretty.py @@ -3,7 +3,6 @@ import dataclasses import inspect import os -import reprlib import sys from array import array from collections import Counter, UserDict, UserList, defaultdict, deque @@ -16,7 +15,6 @@ Any, Callable, DefaultDict, - Deque, Dict, Iterable, List, @@ -79,10 +77,7 @@ def _is_dataclass_repr(obj: object) -> bool: # Digging in to a lot of internals here # Catching all exceptions in case something is missing on a non CPython implementation try: - return obj.__repr__.__code__.co_filename in ( - dataclasses.__file__, - reprlib.__file__, - ) + return obj.__repr__.__code__.co_filename == dataclasses.__file__ except Exception: # pragma: no coverage return False @@ -135,19 +130,17 @@ def _ipy_display_hook( if _safe_isinstance(value, ConsoleRenderable): console.line() console.print( - ( - value - if _safe_isinstance(value, RichRenderable) - else Pretty( - value, - overflow=overflow, - indent_guides=indent_guides, - max_length=max_length, - max_string=max_string, - max_depth=max_depth, - expand_all=expand_all, - margin=12, - ) + value + if _safe_isinstance(value, RichRenderable) + else Pretty( + value, + overflow=overflow, + indent_guides=indent_guides, + max_length=max_length, + max_string=max_string, + max_depth=max_depth, + expand_all=expand_all, + margin=12, ), crop=crop, new_line_start=True, @@ -203,28 +196,23 @@ def display_hook(value: Any) -> None: assert console is not None builtins._ = None # type: ignore[attr-defined] console.print( - ( - value - if _safe_isinstance(value, RichRenderable) - else Pretty( - value, - overflow=overflow, - indent_guides=indent_guides, - max_length=max_length, - max_string=max_string, - max_depth=max_depth, - expand_all=expand_all, - ) + value + if _safe_isinstance(value, RichRenderable) + else Pretty( + value, + overflow=overflow, + indent_guides=indent_guides, + max_length=max_length, + max_string=max_string, + max_depth=max_depth, + expand_all=expand_all, ), crop=crop, ) builtins._ = value # type: ignore[attr-defined] - try: + if "get_ipython" in globals(): ip = get_ipython() # type: ignore[name-defined] - except NameError: - sys.displayhook = display_hook - else: from IPython.core.formatters import BaseFormatter class RichFormatter(BaseFormatter): # type: ignore[misc] @@ -248,6 +236,8 @@ def __call__(self, value: Any) -> Any: # replace plain text formatter with rich formatter rich_formatter = RichFormatter() ip.display_formatter.formatters["text/plain"] = rich_formatter + else: + sys.displayhook = display_hook class Pretty(JupyterMixin): @@ -362,16 +352,6 @@ def _get_braces_for_defaultdict(_object: DefaultDict[Any, Any]) -> Tuple[str, st ) -def _get_braces_for_deque(_object: Deque[Any]) -> Tuple[str, str, str]: - if _object.maxlen is None: - return ("deque([", "])", "deque()") - return ( - "deque([", - f"], maxlen={_object.maxlen})", - f"deque(maxlen={_object.maxlen})", - ) - - def _get_braces_for_array(_object: "array[Any]") -> Tuple[str, str, str]: return (f"array({_object.typecode!r}, [", "])", f"array({_object.typecode!r})") @@ -381,7 +361,7 @@ def _get_braces_for_array(_object: "array[Any]") -> Tuple[str, str, str]: array: _get_braces_for_array, defaultdict: _get_braces_for_defaultdict, Counter: lambda _object: ("Counter({", "})", "Counter()"), - deque: _get_braces_for_deque, + deque: lambda _object: ("deque([", "])", "deque()"), dict: lambda _object: ("{", "}", "{}"), UserDict: lambda _object: ("{", "}", "{}"), frozenset: lambda _object: ("frozenset({", "})", "frozenset()"), @@ -728,9 +708,9 @@ def iter_rich_args(rich_args: Any) -> Iterable[Union[Any, Tuple[str, Any]]]: last=root, ) - def iter_attrs() -> ( - Iterable[Tuple[str, Any, Optional[Callable[[Any], str]]]] - ): + def iter_attrs() -> Iterable[ + Tuple[str, Any, Optional[Callable[[Any], str]]] + ]: """Iterate over attr fields and values.""" for attr in attr_fields: if attr.repr: @@ -781,9 +761,7 @@ def iter_attrs() -> ( ) for last, field in loop_last( - field - for field in fields(obj) - if field.repr and hasattr(obj, field.name) + field for field in fields(obj) if field.repr ): child_node = _traverse(getattr(obj, field.name), depth=depth + 1) child_node.key_repr = field.name @@ -867,7 +845,7 @@ def iter_attrs() -> ( pop_visited(obj_id) else: node = Node(value_repr=to_repr(obj), last=root) - node.is_tuple = type(obj) == tuple + node.is_tuple = _safe_isinstance(obj, tuple) node.is_namedtuple = _is_namedtuple(obj) return node @@ -1007,7 +985,7 @@ class StockKeepingUnit(NamedTuple): from pip._vendor.rich import print - print(Pretty(data, indent_guides=True, max_string=20)) + # print(Pretty(data, indent_guides=True, max_string=20)) class Thing: def __repr__(self) -> str: diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/progress.py b/venv1/Lib/site-packages/pip/_vendor/rich/progress.py index ef6ad60f..8b0a315f 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/progress.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/progress.py @@ -1,6 +1,5 @@ -from __future__ import annotations - import io +import sys import typing import warnings from abc import ABC, abstractmethod @@ -15,7 +14,6 @@ from threading import Event, RLock, Thread from types import TracebackType from typing import ( - TYPE_CHECKING, Any, BinaryIO, Callable, @@ -25,10 +23,10 @@ Generic, Iterable, List, - Literal, NamedTuple, NewType, Optional, + Sequence, TextIO, Tuple, Type, @@ -36,9 +34,10 @@ Union, ) -if TYPE_CHECKING: - # Can be replaced with `from typing import Self` in Python 3.11+ - from typing_extensions import Self # pragma: no cover +if sys.version_info >= (3, 8): + from typing import Literal +else: + from pip._vendor.typing_extensions import Literal # pragma: no cover from . import filesize, get_console from .console import Console, Group, JustifyMethod, RenderableType @@ -71,7 +70,7 @@ def __init__(self, progress: "Progress", task_id: "TaskID", update_period: float self.done = Event() self.completed = 0 - super().__init__(daemon=True) + super().__init__() def run(self) -> None: task_id = self.task_id @@ -79,7 +78,7 @@ def run(self) -> None: update_period = self.update_period last_completed = 0 wait = self.done.wait - while not wait(update_period) and self.progress.live.is_started: + while not wait(update_period): completed = self.completed if last_completed != completed: advance(task_id, completed - last_completed) @@ -102,10 +101,9 @@ def __exit__( def track( - sequence: Iterable[ProgressType], + sequence: Union[Sequence[ProgressType], Iterable[ProgressType]], description: str = "Working...", total: Optional[float] = None, - completed: int = 0, auto_refresh: bool = True, console: Optional[Console] = None, transient: bool = False, @@ -121,13 +119,10 @@ def track( ) -> Iterable[ProgressType]: """Track progress by iterating over a sequence. - You can also track progress of an iterable, which might require that you additionally specify ``total``. - Args: - sequence (Iterable[ProgressType]): Values you wish to iterate over and track progress. + sequence (Iterable[ProgressType]): A sequence (must support "len") you wish to iterate over. description (str, optional): Description of task show next to progress bar. Defaults to "Working". total: (float, optional): Total number of steps. Default is len(sequence). - completed (int, optional): Number of steps completed so far. Defaults to 0. auto_refresh (bool, optional): Automatic refresh, disable to force a refresh after each iteration. Default is True. transient: (bool, optional): Clear the progress on exit. Defaults to False. console (Console, optional): Console to write to. Default creates internal Console instance. @@ -171,11 +166,7 @@ def track( with progress: yield from progress.track( - sequence, - total=total, - completed=completed, - description=description, - update_period=update_period, + sequence, total=total, description=description, update_period=update_period ) @@ -278,9 +269,6 @@ def tell(self) -> int: def write(self, s: Any) -> int: raise UnsupportedOperation("write") - def writelines(self, lines: Iterable[Any]) -> None: - raise UnsupportedOperation("writelines") - class _ReadContext(ContextManager[_I], Generic[_I]): """A utility class to handle a context for both a reader and a progress.""" @@ -693,7 +681,7 @@ def render(self, task: "Task") -> Text: elapsed = task.finished_time if task.finished else task.elapsed if elapsed is None: return Text("-:--:--", style="progress.elapsed") - delta = timedelta(seconds=max(0, int(elapsed))) + delta = timedelta(seconds=int(elapsed)) return Text(str(delta), style="progress.elapsed") @@ -722,6 +710,7 @@ def __init__( table_column: Optional[Column] = None, show_speed: bool = False, ) -> None: + self.text_format_no_percentage = text_format_no_percentage self.show_speed = show_speed super().__init__( @@ -1062,7 +1051,7 @@ class Progress(JupyterMixin): """Renders an auto-updating progress bar(s). Args: - console (Console, optional): Optional Console instance. Defaults to an internal Console instance writing to stdout. + console (Console, optional): Optional Console instance. Default will an internal Console instance writing to stdout. auto_refresh (bool, optional): Enable auto refresh. If disabled, you will need to call `refresh()`. refresh_per_second (Optional[float], optional): Number of times per second to refresh the progress information or None to use default (10). Defaults to None. speed_estimate_period: (float, optional): Period (in seconds) used to calculate the speed estimate. Defaults to 30. @@ -1125,7 +1114,7 @@ def get_default_columns(cls) -> Tuple[ProgressColumn, ...]: progress = Progress( SpinnerColumn(), - *Progress.get_default_columns(), + *Progress.default_columns(), "Elapsed:", TimeElapsedColumn(), ) @@ -1173,10 +1162,10 @@ def start(self) -> None: def stop(self) -> None: """Stop the progress display.""" self.live.stop() - if not self.console.is_interactive and not self.console.is_jupyter: + if not self.console.is_interactive: self.console.print() - def __enter__(self) -> Self: + def __enter__(self) -> "Progress": self.start() return self @@ -1190,21 +1179,17 @@ def __exit__( def track( self, - sequence: Iterable[ProgressType], + sequence: Union[Iterable[ProgressType], Sequence[ProgressType]], total: Optional[float] = None, - completed: int = 0, task_id: Optional[TaskID] = None, description: str = "Working...", update_period: float = 0.1, ) -> Iterable[ProgressType]: """Track progress by iterating over a sequence. - You can also track progress of an iterable, which might require that you additionally specify ``total``. - Args: - sequence (Iterable[ProgressType]): Values you want to iterate over and track progress. + sequence (Sequence[ProgressType]): A sequence of values you want to iterate over and track progress. total: (float, optional): Total number of steps. Default is len(sequence). - completed (int, optional): Number of steps completed so far. Defaults to 0. task_id: (TaskID): Task to track. Default is new task. description: (str, optional): Description of task, if new task is created. update_period (float, optional): Minimum time (in seconds) between calls to update(). Defaults to 0.1. @@ -1216,9 +1201,9 @@ def track( total = float(length_hint(sequence)) or None if task_id is None: - task_id = self.add_task(description, total=total, completed=completed) + task_id = self.add_task(description, total=total) else: - self.update(task_id, total=total, completed=completed) + self.update(task_id, total=total) if self.live.auto_refresh: with _TrackThread(self, task_id, update_period) as track_thread: @@ -1342,7 +1327,7 @@ def open( # normalize the mode (always rb, rt) _mode = "".join(sorted(mode, reverse=False)) if _mode not in ("br", "rt", "r"): - raise ValueError(f"invalid mode {mode!r}") + raise ValueError("invalid mode {!r}".format(mode)) # patch buffering to provide the same behaviour as the builtin `open` line_buffering = buffering == 1 @@ -1651,6 +1636,7 @@ def remove_task(self, task_id: TaskID) -> None: if __name__ == "__main__": # pragma: no coverage + import random import time @@ -1703,6 +1689,7 @@ def remove_task(self, task_id: TaskID) -> None: console=console, transient=False, ) as progress: + task1 = progress.add_task("[red]Downloading", total=1000) task2 = progress.add_task("[green]Processing", total=1000) task3 = progress.add_task("[yellow]Thinking", total=None) diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/progress_bar.py b/venv1/Lib/site-packages/pip/_vendor/rich/progress_bar.py index 41794f76..67361df2 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/progress_bar.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/progress_bar.py @@ -108,7 +108,7 @@ def _get_pulse_segments( for index in range(PULSE_SIZE): position = index / PULSE_SIZE - fade = 0.5 + cos(position * pi * 2) / 2.0 + fade = 0.5 + cos((position * pi * 2)) / 2.0 color = blend_rgb(fore_color, back_color, cross_fade=fade) append(_Segment(bar, _Style(color=from_triplet(color)))) return segments @@ -156,6 +156,7 @@ def _render_pulse( def __rich_console__( self, console: Console, options: ConsoleOptions ) -> RenderResult: + width = min(self.width or options.max_width, options.max_width) ascii = options.legacy_windows or options.ascii_only should_pulse = self.pulse or self.total is None diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/prompt.py b/venv1/Lib/site-packages/pip/_vendor/rich/prompt.py index fccb70db..2bd0a772 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/prompt.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/prompt.py @@ -36,7 +36,6 @@ class PromptBase(Generic[PromptType]): console (Console, optional): A Console instance or None to use global console. Defaults to None. password (bool, optional): Enable password input. Defaults to False. choices (List[str], optional): A list of valid choices. Defaults to None. - case_sensitive (bool, optional): Matching of choices should be case-sensitive. Defaults to True. show_default (bool, optional): Show default in prompt. Defaults to True. show_choices (bool, optional): Show choices in prompt. Defaults to True. """ @@ -58,7 +57,6 @@ def __init__( console: Optional[Console] = None, password: bool = False, choices: Optional[List[str]] = None, - case_sensitive: bool = True, show_default: bool = True, show_choices: bool = True, ) -> None: @@ -71,7 +69,6 @@ def __init__( self.password = password if choices is not None: self.choices = choices - self.case_sensitive = case_sensitive self.show_default = show_default self.show_choices = show_choices @@ -84,7 +81,6 @@ def ask( console: Optional[Console] = None, password: bool = False, choices: Optional[List[str]] = None, - case_sensitive: bool = True, show_default: bool = True, show_choices: bool = True, default: DefaultType, @@ -101,7 +97,6 @@ def ask( console: Optional[Console] = None, password: bool = False, choices: Optional[List[str]] = None, - case_sensitive: bool = True, show_default: bool = True, show_choices: bool = True, stream: Optional[TextIO] = None, @@ -116,7 +111,6 @@ def ask( console: Optional[Console] = None, password: bool = False, choices: Optional[List[str]] = None, - case_sensitive: bool = True, show_default: bool = True, show_choices: bool = True, default: Any = ..., @@ -132,7 +126,6 @@ def ask( console (Console, optional): A Console instance or None to use global console. Defaults to None. password (bool, optional): Enable password input. Defaults to False. choices (List[str], optional): A list of valid choices. Defaults to None. - case_sensitive (bool, optional): Matching of choices should be case-sensitive. Defaults to True. show_default (bool, optional): Show default in prompt. Defaults to True. show_choices (bool, optional): Show choices in prompt. Defaults to True. stream (TextIO, optional): Optional text file open for reading to get input. Defaults to None. @@ -142,7 +135,6 @@ def ask( console=console, password=password, choices=choices, - case_sensitive=case_sensitive, show_default=show_default, show_choices=show_choices, ) @@ -220,9 +212,7 @@ def check_choice(self, value: str) -> bool: bool: True if choice was valid, otherwise False. """ assert self.choices is not None - if self.case_sensitive: - return value.strip() in self.choices - return value.strip().lower() in [choice.lower() for choice in self.choices] + return value.strip() in self.choices def process_response(self, value: str) -> PromptType: """Process response from user, convert to prompt type. @@ -242,17 +232,9 @@ def process_response(self, value: str) -> PromptType: except ValueError: raise InvalidResponse(self.validate_error_message) - if self.choices is not None: - if not self.check_choice(value): - raise InvalidResponse(self.illegal_choice_message) - - if not self.case_sensitive: - # return the original choice, not the lower case version - return_value = self.response_type( - self.choices[ - [choice.lower() for choice in self.choices].index(value.lower()) - ] - ) + if self.choices is not None and not self.check_choice(value): + raise InvalidResponse(self.illegal_choice_message) + return return_value def on_validate_error(self, value: str, error: InvalidResponse) -> None: @@ -325,7 +307,7 @@ class IntPrompt(PromptBase[int]): validate_error_message = "[prompt.invalid]Please enter a valid integer number" -class FloatPrompt(PromptBase[float]): +class FloatPrompt(PromptBase[int]): """A prompt that returns a float. Example: @@ -364,6 +346,7 @@ def process_response(self, value: str) -> bool: if __name__ == "__main__": # pragma: no cover + from pip._vendor.rich import print if Confirm.ask("Run [i]prompt[/i] tests?", default=True): @@ -389,12 +372,5 @@ def process_response(self, value: str) -> bool: fruit = Prompt.ask("Enter a fruit", choices=["apple", "orange", "pear"]) print(f"fruit={fruit!r}") - doggie = Prompt.ask( - "What's the best Dog? (Case INSENSITIVE)", - choices=["Border Terrier", "Collie", "Labradoodle"], - case_sensitive=False, - ) - print(f"doggie={doggie!r}") - else: print("[b]OK :loudly_crying_face:") diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/py.typed b/venv1/Lib/site-packages/pip/_vendor/rich/py.typed deleted file mode 100644 index e69de29b..00000000 diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/repr.py b/venv1/Lib/site-packages/pip/_vendor/rich/repr.py index 10efc427..f284bcaf 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/repr.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/repr.py @@ -76,7 +76,7 @@ def auto_rich_repr(self: Type[T]) -> Result: param.POSITIONAL_OR_KEYWORD, param.KEYWORD_ONLY, ): - if param.default is param.empty: + if param.default == param.empty: yield getattr(self, param.name) else: yield param.name, getattr(self, param.name), param.default diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/segment.py b/venv1/Lib/site-packages/pip/_vendor/rich/segment.py index 4b5f9979..e1257984 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/segment.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/segment.py @@ -109,51 +109,42 @@ def is_control(self) -> bool: @classmethod @lru_cache(1024 * 16) def _split_cells(cls, segment: "Segment", cut: int) -> Tuple["Segment", "Segment"]: - """Split a segment in to two at a given cell position. - Note that splitting a double-width character, may result in that character turning - into two spaces. - - Args: - segment (Segment): A segment to split. - cut (int): A cell position to cut on. - - Returns: - A tuple of two segments. - """ text, style, control = segment _Segment = Segment + cell_length = segment.cell_length if cut >= cell_length: return segment, _Segment("", style, control) cell_size = get_character_cell_size - pos = int((cut / cell_length) * len(text)) + pos = int((cut / cell_length) * (len(text) - 1)) - while True: + before = text[:pos] + cell_pos = cell_len(before) + if cell_pos == cut: + return ( + _Segment(before, style, control), + _Segment(text[pos:], style, control), + ) + while pos < len(text): + char = text[pos] + pos += 1 + cell_pos += cell_size(char) before = text[:pos] - cell_pos = cell_len(before) - out_by = cell_pos - cut - if not out_by: + if cell_pos == cut: return ( _Segment(before, style, control), _Segment(text[pos:], style, control), ) - if out_by == -1 and cell_size(text[pos]) == 2: - return ( - _Segment(text[:pos] + " ", style, control), - _Segment(" " + text[pos + 1 :], style, control), - ) - if out_by == +1 and cell_size(text[pos - 1]) == 2: + if cell_pos > cut: return ( - _Segment(text[: pos - 1] + " ", style, control), + _Segment(before[: pos - 1] + " ", style, control), _Segment(" " + text[pos:], style, control), ) - if cell_pos < cut: - pos += 1 - else: - pos -= 1 + + raise AssertionError("Will never reach here") def split_cells(self, cut: int) -> Tuple["Segment", "Segment"]: """Split segment in to two segments at the specified column. @@ -161,14 +152,10 @@ def split_cells(self, cut: int) -> Tuple["Segment", "Segment"]: If the cut point falls in the middle of a 2-cell wide character then it is replaced by two spaces, to preserve the display width of the parent segment. - Args: - cut (int): Offset within the segment to cut. - Returns: Tuple[Segment, Segment]: Two segments. """ text, style, control = self - assert cut >= 0 if _is_single_cell_widths(text): # Fast path with all 1 cell characters @@ -618,7 +605,7 @@ def divide( while True: cut = next(iter_cuts, -1) if cut == -1: - return + return [] if cut != 0: break yield [] diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/spinner.py b/venv1/Lib/site-packages/pip/_vendor/rich/spinner.py index a3a3caf8..91ea630e 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/spinner.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/spinner.py @@ -1,4 +1,4 @@ -from typing import TYPE_CHECKING, List, Optional, Union, cast +from typing import cast, List, Optional, TYPE_CHECKING, Union from ._spinners import SPINNERS from .measure import Measurement @@ -6,7 +6,7 @@ from .text import Text if TYPE_CHECKING: - from .console import Console, ConsoleOptions, RenderableType, RenderResult + from .console import Console, ConsoleOptions, RenderResult, RenderableType from .style import StyleType @@ -38,7 +38,6 @@ def __init__( self.text: "Union[RenderableType, Text]" = ( Text.from_markup(text) if isinstance(text, str) else text ) - self.name = name self.frames = cast(List[str], spinner["frames"])[:] self.interval = cast(float, spinner["interval"]) self.start_time: Optional[float] = None @@ -117,16 +116,22 @@ def update( if __name__ == "__main__": # pragma: no cover from time import sleep - from .console import Group + from .columns import Columns + from .panel import Panel from .live import Live - all_spinners = Group( - *[ + all_spinners = Columns( + [ Spinner(spinner_name, text=Text(repr(spinner_name), style="green")) for spinner_name in sorted(SPINNERS.keys()) - ] + ], + column_first=True, + expand=True, ) - with Live(all_spinners, refresh_per_second=20) as live: + with Live( + Panel(all_spinners, title="Spinners", border_style="blue"), + refresh_per_second=20, + ) as live: while True: sleep(0.1) diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/status.py b/venv1/Lib/site-packages/pip/_vendor/rich/status.py index 65744838..09eff405 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/status.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/status.py @@ -107,6 +107,7 @@ def __exit__( if __name__ == "__main__": # pragma: no cover + from time import sleep from .console import Console diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/style.py b/venv1/Lib/site-packages/pip/_vendor/rich/style.py index 52942418..313c8894 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/style.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/style.py @@ -1,7 +1,6 @@ import sys from functools import lru_cache -from operator import attrgetter -from pickle import dumps, loads +from marshal import dumps, loads from random import randint from typing import Any, Dict, Iterable, List, Optional, Type, Union, cast @@ -10,10 +9,6 @@ from .repr import Result, rich_repr from .terminal_theme import DEFAULT_TERMINAL_THEME, TerminalTheme -_hash_getter = attrgetter( - "_color", "_bgcolor", "_attributes", "_set_attributes", "_link", "_meta" -) - # Style instances and style definitions are often interchangeable StyleType = Union[str, "Style"] @@ -437,7 +432,16 @@ def __ne__(self, other: Any) -> bool: def __hash__(self) -> int: if self._hash is not None: return self._hash - self._hash = hash(_hash_getter(self)) + self._hash = hash( + ( + self._color, + self._bgcolor, + self._attributes, + self._set_attributes, + self._link, + self._meta, + ) + ) return self._hash @property @@ -520,7 +524,7 @@ def parse(cls, style_definition: str) -> "Style": if not word: raise errors.StyleSyntaxError("color expected after 'on'") try: - Color.parse(word) + Color.parse(word) is None except ColorParseError as error: raise errors.StyleSyntaxError( f"unable to parse {word!r} as background color; {error}" @@ -659,7 +663,7 @@ def clear_meta_and_links(self) -> "Style": style._set_attributes = self._set_attributes style._link = None style._link_id = "" - style._hash = None + style._hash = self._hash style._null = False style._meta = None return style diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/syntax.py b/venv1/Lib/site-packages/pip/_vendor/rich/syntax.py index ec0d903e..25b226a3 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/syntax.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/syntax.py @@ -1,6 +1,5 @@ -from __future__ import annotations - import os.path +import platform import re import sys import textwrap @@ -53,7 +52,7 @@ TokenType = Tuple[str, ...] -WINDOWS = sys.platform == "win32" +WINDOWS = platform.system() == "Windows" DEFAULT_THEME = "monokai" # The following styles are based on https://github.com/pygments/pygments/blob/master/pygments/formatters/terminal.py @@ -223,18 +222,6 @@ class _SyntaxHighlightRange(NamedTuple): style: StyleType start: SyntaxPosition end: SyntaxPosition - style_before: bool = False - - -class PaddingProperty: - """Descriptor to get and set padding.""" - - def __get__(self, obj: Syntax, objtype: Type[Syntax]) -> Tuple[int, int, int, int]: - """Space around the Syntax.""" - return obj._padding - - def __set__(self, obj: Syntax, padding: PaddingDimensions) -> None: - obj._padding = Padding.unpack(padding) class Syntax(JupyterMixin): @@ -306,13 +293,11 @@ def __init__( Style(bgcolor=background_color) if background_color else Style() ) self.indent_guides = indent_guides - self._padding = Padding.unpack(padding) + self.padding = padding self._theme = self.get_theme(theme) self._stylized_ranges: List[_SyntaxHighlightRange] = [] - padding = PaddingProperty() - @classmethod def from_path( cls, @@ -386,8 +371,8 @@ def guess_lexer(cls, path: str, code: Optional[str] = None) -> str: is supplied, the lexer will be chosen based on the file extension.. Args: - path (AnyStr): The path to the file containing the code you wish to know the lexer for. - code (str, optional): Optional string of code that will be used as a fallback if no lexer + path (AnyStr): The path to the file containing the code you wish to know the lexer for. + code (str, optional): Optional string of code that will be used as a fallback if no lexer is found for the supplied path. Returns: @@ -454,16 +439,6 @@ def lexer(self) -> Optional[Lexer]: except ClassNotFound: return None - @property - def default_lexer(self) -> Lexer: - """A Pygments Lexer to use if one is not specified or invalid.""" - return get_lexer_by_name( - "text", - stripnl=False, - ensurenl=True, - tabsize=self.tab_size, - ) - def highlight( self, code: str, @@ -492,7 +467,7 @@ def highlight( ) _get_theme_style = self._theme.get_style_for_token - lexer = self.lexer or self.default_lexer + lexer = self.lexer if lexer is None: text.append(code) @@ -550,11 +525,7 @@ def tokens_to_spans() -> Iterable[Tuple[str, Optional[Style]]]: return text def stylize_range( - self, - style: StyleType, - start: SyntaxPosition, - end: SyntaxPosition, - style_before: bool = False, + self, style: StyleType, start: SyntaxPosition, end: SyntaxPosition ) -> None: """ Adds a custom style on a part of the code, that will be applied to the syntax display when it's rendered. @@ -564,11 +535,8 @@ def stylize_range( style (StyleType): The style to apply. start (Tuple[int, int]): The start of the range, in the form `[line number, column index]`. end (Tuple[int, int]): The end of the range, in the form `[line number, column index]`. - style_before (bool): Apply the style before any existing styles. """ - self._stylized_ranges.append( - _SyntaxHighlightRange(style, start, end, style_before) - ) + self._stylized_ranges.append(_SyntaxHighlightRange(style, start, end)) def _get_line_numbers_color(self, blend: float = 0.3) -> Color: background_style = self._theme.get_background_style() + self.background_style @@ -622,7 +590,8 @@ def _get_number_styles(self, console: Console) -> Tuple[Style, Style, Style]: def __rich_measure__( self, console: "Console", options: "ConsoleOptions" ) -> "Measurement": - _, right, _, left = self.padding + + _, right, _, left = Padding.unpack(self.padding) padding = left + right if self.code_width is not None: width = self.code_width + self._numbers_column_width + padding + 1 @@ -641,8 +610,10 @@ def __rich_console__( self, console: Console, options: ConsoleOptions ) -> RenderResult: segments = Segments(self._get_syntax(console, options)) - if any(self.padding): - yield Padding(segments, style=self._get_base_style(), pad=self.padding) + if self.padding: + yield Padding( + segments, style=self._theme.get_background_style(), pad=self.padding + ) else: yield segments @@ -655,19 +626,15 @@ def _get_syntax( Get the Segments for the Syntax object, excluding any vertical/horizontal padding """ transparent_background = self._get_base_style().transparent_background - _pad_top, pad_right, _pad_bottom, pad_left = self.padding - horizontal_padding = pad_left + pad_right code_width = ( ( (options.max_width - self._numbers_column_width - 1) if self.line_numbers else options.max_width ) - - horizontal_padding if self.code_width is None else self.code_width ) - code_width = max(0, code_width) ends_on_nl, processed_code = self._process_code(self.code) text = self.highlight(processed_code, self.line_range) @@ -721,7 +688,7 @@ def _get_syntax( lines = ( Text("\n") .join(lines) - .with_indent_guides(self.tab_size, style=style + Style(italic=False)) + .with_indent_guides(self.tab_size, style=style) .split("\n", allow_blank=True) ) @@ -812,10 +779,7 @@ def _apply_stylized_ranges(self, text: Text) -> None: newlines_offsets, stylized_range.end ) if start is not None and end is not None: - if stylized_range.style_before: - text.stylize_before(stylized_range.style, start, end) - else: - text.stylize(stylized_range.style, start, end) + text.stylize(stylized_range.style, start, end) def _process_code(self, code: str) -> Tuple[bool, str]: """ @@ -866,6 +830,7 @@ def _get_code_index_for_syntax_position( if __name__ == "__main__": # pragma: no cover + import argparse import sys diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/table.py b/venv1/Lib/site-packages/pip/_vendor/rich/table.py index 2b9e3b5d..17409f2e 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/table.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/table.py @@ -54,7 +54,7 @@ class Column: show_footer (bool, optional): Show a footer row. Defaults to False. show_edge (bool, optional): Draw a box around the outside of the table. Defaults to True. show_lines (bool, optional): Draw lines between every row. Defaults to False. - leading (int, optional): Number of blank lines between rows (precludes ``show_lines``). Defaults to 0. + leading (bool, optional): Number of blank lines between rows (precludes ``show_lines``). Defaults to 0. style (Union[str, Style], optional): Default style for the table. Defaults to "none". row_styles (List[Union, str], optional): Optional list of row styles, if more than one style is given then the styles will alternate. Defaults to None. header_style (Union[str, Style], optional): Style of the header. Defaults to "table.header". @@ -106,9 +106,6 @@ class Column: no_wrap: bool = False """bool: Prevent wrapping of text within the column. Defaults to ``False``.""" - highlight: bool = False - """bool: Apply highlighter to column. Defaults to ``False``.""" - _index: int = 0 """Index of column.""" @@ -170,7 +167,7 @@ class Table(JupyterMixin): show_footer (bool, optional): Show a footer row. Defaults to False. show_edge (bool, optional): Draw a box around the outside of the table. Defaults to True. show_lines (bool, optional): Draw lines between every row. Defaults to False. - leading (int, optional): Number of blank lines between rows (precludes ``show_lines``). Defaults to 0. + leading (bool, optional): Number of blank lines between rows (precludes ``show_lines``). Defaults to 0. style (Union[str, Style], optional): Default style for the table. Defaults to "none". row_styles (List[Union, str], optional): Optional list of row styles, if more than one style is given then the styles will alternate. Defaults to None. header_style (Union[str, Style], optional): Style of the header. Defaults to "table.header". @@ -215,6 +212,7 @@ def __init__( caption_justify: "JustifyMethod" = "center", highlight: bool = False, ) -> None: + self.columns: List[Column] = [] self.rows: List[Row] = [] self.title = title @@ -368,7 +366,6 @@ def add_column( footer: "RenderableType" = "", *, header_style: Optional[StyleType] = None, - highlight: Optional[bool] = None, footer_style: Optional[StyleType] = None, style: Optional[StyleType] = None, justify: "JustifyMethod" = "left", @@ -388,7 +385,6 @@ def add_column( footer (RenderableType, optional): Text or renderable for the footer. Defaults to "". header_style (Union[str, Style], optional): Style for the header, or None for default. Defaults to None. - highlight (bool, optional): Whether to highlight the text. The default of None uses the value of the table (self) object. footer_style (Union[str, Style], optional): Style for the footer, or None for default. Defaults to None. style (Union[str, Style], optional): Style for the column cells, or None for default. Defaults to None. justify (JustifyMethod, optional): Alignment for cells. Defaults to "left". @@ -406,7 +402,6 @@ def add_column( header=header, footer=footer, header_style=header_style or "", - highlight=highlight if highlight is not None else self.highlight, footer_style=footer_style or "", style=style or "", justify=justify, @@ -451,7 +446,7 @@ def add_cell(column: Column, renderable: "RenderableType") -> None: ] for index, renderable in enumerate(cell_renderables): if index == len(columns): - column = Column(_index=index, highlight=self.highlight) + column = Column(_index=index) for _ in self.rows: add_cell(column, Text("")) self.columns.append(column) @@ -476,6 +471,7 @@ def add_section(self) -> None: def __rich_console__( self, console: "Console", options: "ConsoleOptions" ) -> "RenderResult": + if not self.columns: yield Segment("\n") return @@ -689,7 +685,7 @@ def get_padding(first_row: bool, last_row: bool) -> Tuple[int, int, int, int]: getattr(renderable, "vertical", None) or column.vertical, ) else: - for style, renderable in raw_cells: + for (style, renderable) in raw_cells: yield _Cell( style, renderable, @@ -781,16 +777,16 @@ def _render( _Segment(_box.head_right, border_style), _Segment(_box.head_vertical, border_style), ), - ( - _Segment(_box.mid_left, border_style), - _Segment(_box.mid_right, border_style), - _Segment(_box.mid_vertical, border_style), - ), ( _Segment(_box.foot_left, border_style), _Segment(_box.foot_right, border_style), _Segment(_box.foot_vertical, border_style), ), + ( + _Segment(_box.mid_left, border_style), + _Segment(_box.mid_right, border_style), + _Segment(_box.mid_vertical, border_style), + ), ] if show_edge: yield _Segment(_box.get_top(widths), border_style) @@ -824,7 +820,6 @@ def _render( no_wrap=column.no_wrap, overflow=column.overflow, height=None, - highlight=column.highlight, ) lines = console.render_lines( cell.renderable, @@ -929,6 +924,7 @@ def align_cell( if __name__ == "__main__": # pragma: no cover from pip._vendor.rich.console import Console from pip._vendor.rich.highlighter import ReprHighlighter + from pip._vendor.rich.table import Table as Table from ._timer import timer diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/text.py b/venv1/Lib/site-packages/pip/_vendor/rich/text.py index 5a0c6b14..998cb87d 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/text.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/text.py @@ -11,7 +11,6 @@ List, NamedTuple, Optional, - Pattern, Tuple, Union, ) @@ -39,7 +38,6 @@ _re_whitespace = re.compile(r"\s+$") TextType = Union[str, "Text"] -"""A plain string or a :class:`Text` instance.""" GetStyleCallable = Callable[[str], Optional[StyleType]] @@ -99,21 +97,6 @@ def right_crop(self, offset: int) -> "Span": return self return Span(start, min(offset, end), style) - def extend(self, cells: int) -> "Span": - """Extend the span by the given number of cells. - - Args: - cells (int): Additional space to add to end of span. - - Returns: - Span: A span. - """ - if cells: - start, end, style = self - return Span(start, end + cells, style) - else: - return self - class Text(JupyterMixin): """Text with color / style. @@ -125,7 +108,7 @@ class Text(JupyterMixin): overflow (str, optional): Overflow method: "crop", "fold", "ellipsis". Defaults to None. no_wrap (bool, optional): Disable text wrapping, or None for default. Defaults to None. end (str, optional): Character to end text with. Defaults to "\\\\n". - tab_size (int): Number of spaces per tab, or ``None`` to use ``console.tab_size``. Defaults to None. + tab_size (int): Number of spaces per tab, or ``None`` to use ``console.tab_size``. Defaults to 8. spans (List[Span], optional). A list of predefined style spans. Defaults to None. """ @@ -150,7 +133,7 @@ def __init__( overflow: Optional["OverflowMethod"] = None, no_wrap: Optional[bool] = None, end: str = "\n", - tab_size: Optional[int] = None, + tab_size: Optional[int] = 8, spans: Optional[List[Span]] = None, ) -> None: sanitized_text = strip_control_codes(text) @@ -174,7 +157,7 @@ def __str__(self) -> str: return self.plain def __repr__(self) -> str: - return f"" + return f"" def __add__(self, other: Any) -> "Text": if isinstance(other, (str, Text)): @@ -272,9 +255,7 @@ def from_markup( Args: text (str): A string containing console markup. - style (Union[str, Style], optional): Base style for text. Defaults to "". emoji (bool, optional): Also render emoji code. Defaults to True. - emoji_variant (str, optional): Optional emoji variant, either "text" or "emoji". Defaults to None. justify (str, optional): Justify method: "left", "center", "full", "right". Defaults to None. overflow (str, optional): Overflow method: "crop", "fold", "ellipsis". Defaults to None. end (str, optional): Character to end text with. Defaults to "\\\\n". @@ -311,7 +292,7 @@ def from_ansi( overflow (str, optional): Overflow method: "crop", "fold", "ellipsis". Defaults to None. no_wrap (bool, optional): Disable text wrapping, or None for default. Defaults to None. end (str, optional): Character to end text with. Defaults to "\\\\n". - tab_size (int): Number of spaces per tab, or ``None`` to use ``console.tab_size``. Defaults to None. + tab_size (int): Number of spaces per tab, or ``None`` to use ``console.tab_size``. Defaults to 8. """ from .ansi import AnsiDecoder @@ -372,9 +353,8 @@ def assemble( style (Union[str, Style], optional): Base style for text. Defaults to "". justify (str, optional): Justify method: "left", "center", "full", "right". Defaults to None. overflow (str, optional): Overflow method: "crop", "fold", "ellipsis". Defaults to None. - no_wrap (bool, optional): Disable text wrapping, or None for default. Defaults to None. end (str, optional): Character to end text with. Defaults to "\\\\n". - tab_size (int): Number of spaces per tab, or ``None`` to use ``console.tab_size``. Defaults to None. + tab_size (int): Number of spaces per tab, or ``None`` to use ``console.tab_size``. Defaults to 8. meta (Dict[str, Any], optional). Meta data to apply to text, or None for no meta data. Default to None Returns: @@ -428,7 +408,7 @@ def spans(self, spans: List[Span]) -> None: self._spans = spans[:] def blank_copy(self, plain: str = "") -> "Text": - """Return a new Text instance with copied metadata (but not the string or spans).""" + """Return a new Text instance with copied meta data (but not the string or spans).""" copy_self = Text( plain, style=self.style, @@ -509,7 +489,7 @@ def stylize_before( def apply_meta( self, meta: Dict[str, Any], start: int = 0, end: Optional[int] = None ) -> None: - """Apply metadata to the text, or a portion of the text. + """Apply meta data to the text, or a portion of the text. Args: meta (Dict[str, Any]): A dict of meta information. @@ -569,30 +549,9 @@ def get_style_at_offset(self, console: "Console", offset: int) -> Style: style += get_style(span_style, default="") return style - def extend_style(self, spaces: int) -> None: - """Extend the Text given number of spaces where the spaces have the same style as the last character. - - Args: - spaces (int): Number of spaces to add to the Text. - """ - if spaces <= 0: - return - spans = self.spans - new_spaces = " " * spaces - if spans: - end_offset = len(self) - self._spans[:] = [ - span.extend(spaces) if span.end >= end_offset else span - for span in spans - ] - self._text.append(new_spaces) - self._length += spaces - else: - self.plain += new_spaces - def highlight_regex( self, - re_highlight: Union[Pattern[str], str], + re_highlight: str, style: Optional[Union[GetStyleCallable, StyleType]] = None, *, style_prefix: str = "", @@ -601,7 +560,7 @@ def highlight_regex( translated to styles. Args: - re_highlight (Union[re.Pattern, str]): A regular expression object or string. + re_highlight (str): A regular expression. style (Union[GetStyleCallable, StyleType]): Optional style to apply to whole match, or a callable which accepts the matched text and returns a style. Defaults to None. style_prefix (str, optional): Optional prefix to add to style group names. @@ -613,9 +572,7 @@ def highlight_regex( append_span = self._spans.append _Span = Span plain = self.plain - if isinstance(re_highlight, str): - re_highlight = re.compile(re_highlight) - for match in re_highlight.finditer(plain): + for match in re.finditer(re_highlight, plain): get_span = match.span if style: start, end = get_span() @@ -640,9 +597,9 @@ def highlight_words( """Highlight words with a style. Args: - words (Iterable[str]): Words to highlight. + words (Iterable[str]): Worlds to highlight. style (Union[str, Style]): Style to apply. - case_sensitive (bool, optional): Enable case sensitive matching. Defaults to True. + case_sensitive (bool, optional): Enable case sensitive matchings. Defaults to True. Returns: int: Number of words highlighted. @@ -689,7 +646,7 @@ def set_length(self, new_length: int) -> None: def __rich_console__( self, console: "Console", options: "ConsoleOptions" ) -> Iterable[Segment]: - tab_size: int = console.tab_size if self.tab_size is None else self.tab_size + tab_size: int = console.tab_size or self.tab_size or 8 justify = self.justify or options.justify or DEFAULT_JUSTIFY overflow = self.overflow or options.overflow or DEFAULT_OVERFLOW @@ -824,35 +781,27 @@ def expand_tabs(self, tab_size: Optional[int] = None) -> None: """ if "\t" not in self.plain: return + pos = 0 if tab_size is None: tab_size = self.tab_size - if tab_size is None: - tab_size = 8 - - new_text: List[Text] = [] - append = new_text.append + assert tab_size is not None + result = self.blank_copy() + append = result.append + _style = self.style for line in self.split("\n", include_separator=True): - if "\t" not in line.plain: - append(line) - else: - cell_position = 0 - parts = line.split("\t", include_separator=True) - for part in parts: - if part.plain.endswith("\t"): - part._text[-1] = part._text[-1][:-1] + " " - cell_position += part.cell_len - tab_remainder = cell_position % tab_size - if tab_remainder: - spaces = tab_size - tab_remainder - part.extend_style(spaces) - cell_position += spaces - else: - cell_position += part.cell_len + parts = line.split("\t", include_separator=True) + for part in parts: + if part.plain.endswith("\t"): + part._text = [part.plain[:-1] + " "] + append(part) + pos += len(part) + spaces = tab_size - ((pos - 1) % tab_size) - 1 + if spaces: + append(" " * spaces, _style) + pos += spaces + else: append(part) - - result = Text("").join(new_text) - self._text = [result.plain] self._length = len(self.plain) self._spans[:] = result._spans @@ -903,7 +852,6 @@ def pad(self, count: int, character: str = " ") -> None: Args: count (int): Width of padding. - character (str): The character to pad with. Must be a string of length 1. """ assert len(character) == 1, "Character must be a string of length 1" if count: @@ -984,7 +932,7 @@ def append( self._text.append(sanitized_text) offset = len(self) text_length = len(sanitized_text) - if style: + if style is not None: self._spans.append(Span(offset, offset + text_length, style)) self._length += text_length elif isinstance(text, Text): @@ -994,14 +942,14 @@ def append( "style must not be set when appending Text instance" ) text_length = self._length - if text.style: + if text.style is not None: self._spans.append( _Span(text_length, text_length + len(text), text.style) ) self._text.append(text.plain) self._spans.extend( _Span(start + text_length, end + text_length, style) - for start, end, style in text._spans.copy() + for start, end, style in text._spans ) self._length += len(text) return self @@ -1010,20 +958,17 @@ def append_text(self, text: "Text") -> "Text": """Append another Text instance. This method is more performant that Text.append, but only works for Text. - Args: - text (Text): The Text instance to append to this instance. - Returns: Text: Returns self for chaining. """ _Span = Span text_length = self._length - if text.style: + if text.style is not None: self._spans.append(_Span(text_length, text_length + len(text), text.style)) self._text.append(text.plain) self._spans.extend( _Span(start + text_length, end + text_length, style) - for start, end, style in text._spans.copy() + for start, end, style in text._spans ) self._length += len(text) return self @@ -1034,7 +979,7 @@ def append_tokens( """Append iterable of str and style. Style may be a Style instance or a str style definition. Args: - tokens (Iterable[Tuple[str, Optional[StyleType]]]): An iterable of tuples containing str content and style. + pairs (Iterable[Tuple[str, Optional[StyleType]]]): An iterable of tuples containing str content and style. Returns: Text: Returns self for chaining. @@ -1044,9 +989,8 @@ def append_tokens( _Span = Span offset = len(self) for content, style in tokens: - content = strip_control_codes(content) append_text(content) - if style: + if style is not None: append_span(_Span(offset, offset + len(content), style)) offset += len(content) self._length = offset @@ -1144,6 +1088,7 @@ def divide(self, offsets: Iterable[int]) -> Lines: _Span = Span for span_start, span_end, style in self._spans: + lower_bound = 0 upper_bound = line_count start_line_no = (lower_bound + upper_bound) // 2 @@ -1213,7 +1158,8 @@ def wrap( Args: console (Console): Console instance. - width (int): Number of cells available per line. + width (int): Number of characters per line. + emoji (bool, optional): Also render emoji code. Defaults to True. justify (str, optional): Justify method: "default", "left", "center", "full", "right". Defaults to "default". overflow (str, optional): Overflow method: "crop", "fold", or "ellipsis". Defaults to None. tab_size (int, optional): Default tab size. Defaults to 8. diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/theme.py b/venv1/Lib/site-packages/pip/_vendor/rich/theme.py index 227f1d86..471dfb2f 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/theme.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/theme.py @@ -1,5 +1,5 @@ import configparser -from typing import IO, Dict, List, Mapping, Optional +from typing import Dict, List, IO, Mapping, Optional from .default_styles import DEFAULT_STYLES from .style import Style, StyleType @@ -69,7 +69,7 @@ def read( Returns: Theme: A new theme instance. """ - with open(path, encoding=encoding) as config_file: + with open(path, "rt", encoding=encoding) as config_file: return cls.from_file(config_file, source=path, inherit=inherit) diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/traceback.py b/venv1/Lib/site-packages/pip/_vendor/rich/traceback.py index 01b2f502..c4ffe1f9 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/traceback.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/traceback.py @@ -1,9 +1,10 @@ -import inspect +from __future__ import absolute_import + import linecache import os +import platform import sys from dataclasses import dataclass, field -from itertools import islice from traceback import walk_tb from types import ModuleType, TracebackType from typing import ( @@ -14,7 +15,6 @@ List, Optional, Sequence, - Set, Tuple, Type, Union, @@ -27,64 +27,28 @@ from pip._vendor.pygments.util import ClassNotFound from . import pretty -from ._loop import loop_first_last, loop_last +from ._loop import loop_last from .columns import Columns -from .console import ( - Console, - ConsoleOptions, - ConsoleRenderable, - Group, - RenderResult, - group, -) +from .console import Console, ConsoleOptions, ConsoleRenderable, RenderResult, group from .constrain import Constrain from .highlighter import RegexHighlighter, ReprHighlighter from .panel import Panel from .scope import render_scope from .style import Style -from .syntax import Syntax, SyntaxPosition +from .syntax import Syntax from .text import Text from .theme import Theme -WINDOWS = sys.platform == "win32" +WINDOWS = platform.system() == "Windows" LOCALS_MAX_LENGTH = 10 LOCALS_MAX_STRING = 80 -def _iter_syntax_lines( - start: SyntaxPosition, end: SyntaxPosition -) -> Iterable[Tuple[int, int, int]]: - """Yield start and end positions per line. - - Args: - start: Start position. - end: End position. - - Returns: - Iterable of (LINE, COLUMN1, COLUMN2). - """ - - line1, column1 = start - line2, column2 = end - - if line1 == line2: - yield line1, column1, column2 - else: - for first, last, line_no in loop_first_last(range(line1, line2 + 1)): - if first: - yield line_no, column1, -1 - elif last: - yield line_no, 0, column2 - else: - yield line_no, 0, -1 - - def install( *, console: Optional[Console] = None, width: Optional[int] = 100, - code_width: Optional[int] = 88, extra_lines: int = 3, theme: Optional[str] = None, word_wrap: bool = False, @@ -105,7 +69,6 @@ def install( Args: console (Optional[Console], optional): Console to write exception to. Default uses internal Console instance. width (Optional[int], optional): Width (in characters) of traceback. Defaults to 100. - code_width (Optional[int], optional): Code width (in characters) of traceback. Defaults to 88. extra_lines (int, optional): Extra lines of code. Defaults to 3. theme (Optional[str], optional): Pygments theme to use in traceback. Defaults to ``None`` which will pick a theme appropriate for the platform. @@ -136,25 +99,25 @@ def excepthook( value: BaseException, traceback: Optional[TracebackType], ) -> None: - exception_traceback = Traceback.from_exception( - type_, - value, - traceback, - width=width, - code_width=code_width, - extra_lines=extra_lines, - theme=theme, - word_wrap=word_wrap, - show_locals=show_locals, - locals_max_length=locals_max_length, - locals_max_string=locals_max_string, - locals_hide_dunder=locals_hide_dunder, - locals_hide_sunder=bool(locals_hide_sunder), - indent_guides=indent_guides, - suppress=suppress, - max_frames=max_frames, + traceback_console.print( + Traceback.from_exception( + type_, + value, + traceback, + width=width, + extra_lines=extra_lines, + theme=theme, + word_wrap=word_wrap, + show_locals=show_locals, + locals_max_length=locals_max_length, + locals_max_string=locals_max_string, + locals_hide_dunder=locals_hide_dunder, + locals_hide_sunder=bool(locals_hide_sunder), + indent_guides=indent_guides, + suppress=suppress, + max_frames=max_frames, + ) ) - traceback_console.print(exception_traceback) def ipy_excepthook_closure(ip: Any) -> None: # pragma: no cover tb_data = {} # store information about showtraceback call @@ -178,9 +141,7 @@ def ipy_display_traceback( # determine correct tb_offset compiled = tb_data.get("running_compiled_code", False) - tb_offset = tb_data.get("tb_offset") - if tb_offset is None: - tb_offset = 1 if compiled else 0 + tb_offset = tb_data.get("tb_offset", 1 if compiled else 0) # remove ipython internal frames from trace with tb_offset for _ in range(tb_offset): if tb is None: @@ -218,7 +179,6 @@ class Frame: name: str line: str = "" locals: Optional[Dict[str, pretty.Node]] = None - last_instruction: Optional[Tuple[Tuple[int, int], Tuple[int, int]]] = None @dataclass @@ -228,7 +188,6 @@ class _SyntaxError: line: str lineno: int msg: str - notes: List[str] = field(default_factory=list) @dataclass @@ -238,9 +197,6 @@ class Stack: syntax_error: Optional[_SyntaxError] = None is_cause: bool = False frames: List[Frame] = field(default_factory=list) - notes: List[str] = field(default_factory=list) - is_group: bool = False - exceptions: List["Trace"] = field(default_factory=list) @dataclass @@ -259,7 +215,6 @@ class Traceback: trace (Trace, optional): A `Trace` object produced from `extract`. Defaults to None, which uses the last exception. width (Optional[int], optional): Number of characters used to traceback. Defaults to 100. - code_width (Optional[int], optional): Number of code characters used to traceback. Defaults to 88. extra_lines (int, optional): Additional lines of code to render. Defaults to 3. theme (str, optional): Override pygments theme used in traceback. word_wrap (bool, optional): Enable word wrapping of long lines. Defaults to False. @@ -288,7 +243,6 @@ def __init__( trace: Optional[Trace] = None, *, width: Optional[int] = 100, - code_width: Optional[int] = 88, extra_lines: int = 3, theme: Optional[str] = None, word_wrap: bool = False, @@ -312,7 +266,6 @@ def __init__( ) self.trace = trace self.width = width - self.code_width = code_width self.extra_lines = extra_lines self.theme = Syntax.get_theme(theme or "ansi_dark") self.word_wrap = word_wrap @@ -344,7 +297,6 @@ def from_exception( traceback: Optional[TracebackType], *, width: Optional[int] = 100, - code_width: Optional[int] = 88, extra_lines: int = 3, theme: Optional[str] = None, word_wrap: bool = False, @@ -364,7 +316,6 @@ def from_exception( exc_value (BaseException): Exception value. traceback (TracebackType): Python Traceback object. width (Optional[int], optional): Number of characters used to traceback. Defaults to 100. - code_width (Optional[int], optional): Number of code characters used to traceback. Defaults to 88. extra_lines (int, optional): Additional lines of code to render. Defaults to 3. theme (str, optional): Override pygments theme used in traceback. word_wrap (bool, optional): Enable word wrapping of long lines. Defaults to False. @@ -395,7 +346,6 @@ def from_exception( return cls( rich_traceback, width=width, - code_width=code_width, extra_lines=extra_lines, theme=theme, word_wrap=word_wrap, @@ -421,7 +371,6 @@ def extract( locals_max_string: int = LOCALS_MAX_STRING, locals_hide_dunder: bool = True, locals_hide_sunder: bool = False, - _visited_exceptions: Optional[Set[BaseException]] = None, ) -> Trace: """Extract traceback information. @@ -445,12 +394,6 @@ def extract( from pip._vendor.rich import _IMPORT_CWD - notes: List[str] = getattr(exc_value, "__notes__", None) or [] - - grouped_exceptions: Set[BaseException] = ( - set() if _visited_exceptions is None else _visited_exceptions - ) - def safe_str(_object: Any) -> str: """Don't allow exceptions from __str__ to propagate.""" try: @@ -463,29 +406,8 @@ def safe_str(_object: Any) -> str: exc_type=safe_str(exc_type.__name__), exc_value=safe_str(exc_value), is_cause=is_cause, - notes=notes, ) - if sys.version_info >= (3, 11): - if isinstance(exc_value, (BaseExceptionGroup, ExceptionGroup)): - stack.is_group = True - for exception in exc_value.exceptions: - if exception in grouped_exceptions: - continue - grouped_exceptions.add(exception) - stack.exceptions.append( - Traceback.extract( - type(exception), - exception, - exception.__traceback__, - show_locals=show_locals, - locals_max_length=locals_max_length, - locals_hide_dunder=locals_hide_dunder, - locals_hide_sunder=locals_hide_sunder, - _visited_exceptions=grouped_exceptions, - ) - ) - if isinstance(exc_value, SyntaxError): stack.syntax_error = _SyntaxError( offset=exc_value.offset or 0, @@ -493,14 +415,13 @@ def safe_str(_object: Any) -> str: lineno=exc_value.lineno or 0, line=exc_value.text or "", msg=exc_value.msg, - notes=notes, ) stacks.append(stack) append = stack.frames.append def get_locals( - iter_locals: Iterable[Tuple[str, object]], + iter_locals: Iterable[Tuple[str, object]] ) -> Iterable[Tuple[str, object]]: """Extract locals from an iterator of key pairs.""" if not (locals_hide_dunder or locals_hide_sunder): @@ -515,35 +436,6 @@ def get_locals( for frame_summary, line_no in walk_tb(traceback): filename = frame_summary.f_code.co_filename - - last_instruction: Optional[Tuple[Tuple[int, int], Tuple[int, int]]] - last_instruction = None - if sys.version_info >= (3, 11): - instruction_index = frame_summary.f_lasti // 2 - instruction_position = next( - islice( - frame_summary.f_code.co_positions(), - instruction_index, - instruction_index + 1, - ) - ) - ( - start_line, - end_line, - start_column, - end_column, - ) = instruction_position - if ( - start_line is not None - and end_line is not None - and start_column is not None - and end_column is not None - ): - last_instruction = ( - (start_line, start_column), - (end_line, end_column), - ) - if filename and not filename.startswith("<"): if not os.path.isabs(filename): filename = os.path.join(_IMPORT_CWD, filename) @@ -554,50 +446,42 @@ def get_locals( filename=filename or "?", lineno=line_no, name=frame_summary.f_code.co_name, - locals=( - { - key: pretty.traverse( - value, - max_length=locals_max_length, - max_string=locals_max_string, - ) - for key, value in get_locals(frame_summary.f_locals.items()) - if not (inspect.isfunction(value) or inspect.isclass(value)) - } - if show_locals - else None - ), - last_instruction=last_instruction, + locals={ + key: pretty.traverse( + value, + max_length=locals_max_length, + max_string=locals_max_string, + ) + for key, value in get_locals(frame_summary.f_locals.items()) + } + if show_locals + else None, ) append(frame) if frame_summary.f_locals.get("_rich_traceback_guard", False): del stack.frames[:] - if not grouped_exceptions: - cause = getattr(exc_value, "__cause__", None) - if cause is not None and cause is not exc_value: - exc_type = cause.__class__ - exc_value = cause - # __traceback__ can be None, e.g. for exceptions raised by the - # 'multiprocessing' module - traceback = cause.__traceback__ - is_cause = True - continue + cause = getattr(exc_value, "__cause__", None) + if cause: + exc_type = cause.__class__ + exc_value = cause + # __traceback__ can be None, e.g. for exceptions raised by the + # 'multiprocessing' module + traceback = cause.__traceback__ + is_cause = True + continue - cause = exc_value.__context__ - if cause is not None and not getattr( - exc_value, "__suppress_context__", False - ): - exc_type = cause.__class__ - exc_value = cause - traceback = cause.__traceback__ - is_cause = False - continue + cause = exc_value.__context__ + if cause and not getattr(exc_value, "__suppress_context__", False): + exc_type = cause.__class__ + exc_value = cause + traceback = cause.__traceback__ + is_cause = False + continue # No cover, code is reached but coverage doesn't recognize it. break # pragma: no cover trace = Trace(stacks=stacks) - return trace def __rich_console__( @@ -630,9 +514,7 @@ def __rich_console__( ) highlighter = ReprHighlighter() - - @group() - def render_stack(stack: Stack, last: bool) -> RenderResult: + for last, stack in loop_last(reversed(self.trace.stacks)): if stack.frames: stack_renderable: ConsoleRenderable = Panel( self._render_stack(stack), @@ -645,7 +527,6 @@ def render_stack(stack: Stack, last: bool) -> RenderResult: stack_renderable = Constrain(stack_renderable, self.width) with console.use_theme(traceback_theme): yield stack_renderable - if stack.syntax_error is not None: with console.use_theme(traceback_theme): yield Constrain( @@ -671,24 +552,6 @@ def render_stack(stack: Stack, last: bool) -> RenderResult: else: yield Text.assemble((f"{stack.exc_type}", "traceback.exc_type")) - for note in stack.notes: - yield Text.assemble(("[NOTE] ", "traceback.note"), highlighter(note)) - - if stack.is_group: - for group_no, group_exception in enumerate(stack.exceptions, 1): - grouped_exceptions: List[Group] = [] - for group_last, group_stack in loop_last(group_exception.stacks): - grouped_exceptions.append(render_stack(group_stack, group_last)) - yield "" - yield Constrain( - Panel( - Group(*grouped_exceptions), - title=f"Sub-exception #{group_no}", - border_style="traceback.group.border", - ), - self.width, - ) - if not last: if stack.is_cause: yield Text.from_markup( @@ -699,9 +562,6 @@ def render_stack(stack: Stack, last: bool) -> RenderResult: "\n[i]During handling of the above exception, another exception occurred:\n", ) - for last, stack in loop_last(reversed(self.trace.stacks)): - yield render_stack(stack, last) - @group() def _render_syntax_error(self, syntax_error: _SyntaxError) -> RenderResult: highlighter = ReprHighlighter() @@ -746,6 +606,17 @@ def _render_stack(self, stack: Stack) -> RenderResult: path_highlighter = PathHighlighter() theme = self.theme + def read_code(filename: str) -> str: + """Read files, and cache results on filename. + + Args: + filename (str): Filename to read + + Returns: + str: Contents of file + """ + return "".join(linecache.getlines(filename)) + def render_locals(frame: Frame) -> Iterable[ConsoleRenderable]: if frame.locals: yield render_scope( @@ -765,6 +636,7 @@ def render_locals(frame: Frame) -> Iterable[ConsoleRenderable]: excluded = False for frame_index, frame in enumerate(stack.frames): + if exclude_frames and frame_index in exclude_frames: excluded = True continue @@ -807,8 +679,7 @@ def render_locals(frame: Frame) -> Iterable[ConsoleRenderable]: continue if not suppressed: try: - code_lines = linecache.getlines(frame.filename) - code = "".join(code_lines) + code = read_code(frame.filename) if not code: # code may be an empty string if the file doesn't exist, OR # if the traceback filename is generated dynamically @@ -825,7 +696,7 @@ def render_locals(frame: Frame) -> Iterable[ConsoleRenderable]: ), highlight_lines={frame.lineno}, word_wrap=self.word_wrap, - code_width=self.code_width, + code_width=88, indent_guides=self.indent_guides, dedent=False, ) @@ -835,28 +706,6 @@ def render_locals(frame: Frame) -> Iterable[ConsoleRenderable]: (f"\n{error}", "traceback.error"), ) else: - if frame.last_instruction is not None: - start, end = frame.last_instruction - - # Stylize a line at a time - # So that indentation isn't underlined (which looks bad) - for line1, column1, column2 in _iter_syntax_lines(start, end): - try: - if column1 == 0: - line = code_lines[line1 - 1] - column1 = len(line) - len(line.lstrip()) - if column2 == -1: - column2 = len(code_lines[line1 - 1]) - except IndexError: - # Being defensive here - # If last_instruction reports a line out-of-bounds, we don't want to crash - continue - - syntax.stylize_range( - style="traceback.error_range", - start=(line1, column1), - end=(line1, column2), - ) yield ( Columns( [ @@ -871,12 +720,13 @@ def render_locals(frame: Frame) -> Iterable[ConsoleRenderable]: if __name__ == "__main__": # pragma: no cover - install(show_locals=True) + + from .console import Console + + console = Console() import sys - def bar( - a: Any, - ) -> None: # 这是对亚洲语言支持的测试。面对模棱两可的想法,拒绝猜测的诱惑 + def bar(a: Any) -> None: # 这是对亚洲语言支持的测试。面对模棱两可的想法,拒绝猜测的诱惑 one = 1 print(one / a) @@ -894,6 +744,13 @@ def foo(a: Any) -> None: bar(a) def error() -> None: - foo(0) + + try: + try: + foo(0) + except: + slfkjsldkfj # type: ignore[name-defined] + except: + console.print_exception(show_locals=True) error() diff --git a/venv1/Lib/site-packages/pip/_vendor/rich/tree.py b/venv1/Lib/site-packages/pip/_vendor/rich/tree.py index 27c5cf7b..afe8da1a 100644 --- a/venv1/Lib/site-packages/pip/_vendor/rich/tree.py +++ b/venv1/Lib/site-packages/pip/_vendor/rich/tree.py @@ -8,32 +8,18 @@ from .style import Style, StyleStack, StyleType from .styled import Styled -GuideType = Tuple[str, str, str, str] - class Tree(JupyterMixin): """A renderable for a tree structure. - Attributes: - ASCII_GUIDES (GuideType): Guide lines used when Console.ascii_only is True. - TREE_GUIDES (List[GuideType, GuideType, GuideType]): Default guide lines. - Args: label (RenderableType): The renderable or str for the tree label. style (StyleType, optional): Style of this tree. Defaults to "tree". guide_style (StyleType, optional): Style of the guide lines. Defaults to "tree.line". expanded (bool, optional): Also display children. Defaults to True. highlight (bool, optional): Highlight renderable (if str). Defaults to False. - hide_root (bool, optional): Hide the root node. Defaults to False. """ - ASCII_GUIDES = (" ", "| ", "+-- ", "`-- ") - TREE_GUIDES = [ - (" ", "│ ", "├── ", "└── "), - (" ", "┃ ", "┣━━ ", "┗━━ "), - (" ", "║ ", "╠══ ", "╚══ "), - ] - def __init__( self, label: RenderableType, @@ -86,6 +72,7 @@ def add( def __rich_console__( self, console: "Console", options: "ConsoleOptions" ) -> "RenderResult": + stack: List[Iterator[Tuple[bool, Tree]]] = [] pop = stack.pop push = stack.append @@ -96,15 +83,21 @@ def __rich_console__( guide_style = get_style(self.guide_style, default="") or null_style SPACE, CONTINUE, FORK, END = range(4) + ASCII_GUIDES = (" ", "| ", "+-- ", "`-- ") + TREE_GUIDES = [ + (" ", "│ ", "├── ", "└── "), + (" ", "┃ ", "┣━━ ", "┗━━ "), + (" ", "║ ", "╠══ ", "╚══ "), + ] _Segment = Segment def make_guide(index: int, style: Style) -> Segment: """Make a Segment for a level of the guide lines.""" if options.ascii_only: - line = self.ASCII_GUIDES[index] + line = ASCII_GUIDES[index] else: guide = 1 if style.bold else (2 if style.underline2 else 0) - line = self.TREE_GUIDES[0 if options.legacy_windows else guide][index] + line = TREE_GUIDES[0 if options.legacy_windows else guide][index] return _Segment(line, style) levels: List[Segment] = [make_guide(CONTINUE, guide_style)] @@ -202,6 +195,7 @@ def __rich_measure__( if __name__ == "__main__": # pragma: no cover + from pip._vendor.rich.console import Group from pip._vendor.rich.markdown import Markdown from pip._vendor.rich.panel import Panel diff --git a/venv1/Lib/site-packages/pip/_vendor/tomli/__init__.py b/venv1/Lib/site-packages/pip/_vendor/tomli/__init__.py index 9395b043..4c6ec97e 100644 --- a/venv1/Lib/site-packages/pip/_vendor/tomli/__init__.py +++ b/venv1/Lib/site-packages/pip/_vendor/tomli/__init__.py @@ -3,6 +3,9 @@ # Licensed to PSF under a Contributor Agreement. __all__ = ("loads", "load", "TOMLDecodeError") -__version__ = "2.3.0" # DO NOT EDIT THIS LINE MANUALLY. LET bump2version UTILITY DO IT +__version__ = "2.0.1" # DO NOT EDIT THIS LINE MANUALLY. LET bump2version UTILITY DO IT from ._parser import TOMLDecodeError, load, loads + +# Pretend this exception was created here. +TOMLDecodeError.__module__ = __name__ diff --git a/venv1/Lib/site-packages/pip/_vendor/tomli/_parser.py b/venv1/Lib/site-packages/pip/_vendor/tomli/_parser.py index 26170e8e..f1bb0aa1 100644 --- a/venv1/Lib/site-packages/pip/_vendor/tomli/_parser.py +++ b/venv1/Lib/site-packages/pip/_vendor/tomli/_parser.py @@ -4,8 +4,10 @@ from __future__ import annotations -import sys +from collections.abc import Iterable +import string from types import MappingProxyType +from typing import Any, BinaryIO, NamedTuple from ._re import ( RE_DATETIME, @@ -15,125 +17,44 @@ match_to_localtime, match_to_number, ) +from ._types import Key, ParseFloat, Pos -TYPE_CHECKING = False -if TYPE_CHECKING: - from collections.abc import Iterable - from typing import IO, Any, Final - - from ._types import Key, ParseFloat, Pos - -# Inline tables/arrays are implemented using recursion. Pathologically -# nested documents cause pure Python to raise RecursionError (which is OK), -# but mypyc binary wheels will crash unrecoverably (not OK). According to -# mypyc docs this will be fixed in the future: -# https://mypyc.readthedocs.io/en/latest/differences_from_python.html#stack-overflows -# Before mypyc's fix is in, recursion needs to be limited by this library. -# Choosing `sys.getrecursionlimit()` as maximum inline table/array nesting -# level, as it allows more nesting than pure Python, but still seems a far -# lower number than where mypyc binaries crash. -MAX_INLINE_NESTING: Final = sys.getrecursionlimit() - -ASCII_CTRL: Final = frozenset(chr(i) for i in range(32)) | frozenset(chr(127)) +ASCII_CTRL = frozenset(chr(i) for i in range(32)) | frozenset(chr(127)) # Neither of these sets include quotation mark or backslash. They are # currently handled as separate cases in the parser functions. -ILLEGAL_BASIC_STR_CHARS: Final = ASCII_CTRL - frozenset("\t") -ILLEGAL_MULTILINE_BASIC_STR_CHARS: Final = ASCII_CTRL - frozenset("\t\n") +ILLEGAL_BASIC_STR_CHARS = ASCII_CTRL - frozenset("\t") +ILLEGAL_MULTILINE_BASIC_STR_CHARS = ASCII_CTRL - frozenset("\t\n") -ILLEGAL_LITERAL_STR_CHARS: Final = ILLEGAL_BASIC_STR_CHARS -ILLEGAL_MULTILINE_LITERAL_STR_CHARS: Final = ILLEGAL_MULTILINE_BASIC_STR_CHARS +ILLEGAL_LITERAL_STR_CHARS = ILLEGAL_BASIC_STR_CHARS +ILLEGAL_MULTILINE_LITERAL_STR_CHARS = ILLEGAL_MULTILINE_BASIC_STR_CHARS -ILLEGAL_COMMENT_CHARS: Final = ILLEGAL_BASIC_STR_CHARS +ILLEGAL_COMMENT_CHARS = ILLEGAL_BASIC_STR_CHARS -TOML_WS: Final = frozenset(" \t") -TOML_WS_AND_NEWLINE: Final = TOML_WS | frozenset("\n") -BARE_KEY_CHARS: Final = frozenset( - "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789" "-_" -) -KEY_INITIAL_CHARS: Final = BARE_KEY_CHARS | frozenset("\"'") -HEXDIGIT_CHARS: Final = frozenset("abcdef" "ABCDEF" "0123456789") +TOML_WS = frozenset(" \t") +TOML_WS_AND_NEWLINE = TOML_WS | frozenset("\n") +BARE_KEY_CHARS = frozenset(string.ascii_letters + string.digits + "-_") +KEY_INITIAL_CHARS = BARE_KEY_CHARS | frozenset("\"'") +HEXDIGIT_CHARS = frozenset(string.hexdigits) -BASIC_STR_ESCAPE_REPLACEMENTS: Final = MappingProxyType( +BASIC_STR_ESCAPE_REPLACEMENTS = MappingProxyType( { "\\b": "\u0008", # backspace "\\t": "\u0009", # tab - "\\n": "\u000a", # linefeed - "\\f": "\u000c", # form feed - "\\r": "\u000d", # carriage return + "\\n": "\u000A", # linefeed + "\\f": "\u000C", # form feed + "\\r": "\u000D", # carriage return '\\"': "\u0022", # quote - "\\\\": "\u005c", # backslash + "\\\\": "\u005C", # backslash } ) -class DEPRECATED_DEFAULT: - """Sentinel to be used as default arg during deprecation - period of TOMLDecodeError's free-form arguments.""" - - class TOMLDecodeError(ValueError): - """An error raised if a document is not valid TOML. - - Adds the following attributes to ValueError: - msg: The unformatted error message - doc: The TOML document being parsed - pos: The index of doc where parsing failed - lineno: The line corresponding to pos - colno: The column corresponding to pos - """ - - def __init__( - self, - msg: str | type[DEPRECATED_DEFAULT] = DEPRECATED_DEFAULT, - doc: str | type[DEPRECATED_DEFAULT] = DEPRECATED_DEFAULT, - pos: Pos | type[DEPRECATED_DEFAULT] = DEPRECATED_DEFAULT, - *args: Any, - ): - if ( - args - or not isinstance(msg, str) - or not isinstance(doc, str) - or not isinstance(pos, int) - ): - import warnings - - warnings.warn( - "Free-form arguments for TOMLDecodeError are deprecated. " - "Please set 'msg' (str), 'doc' (str) and 'pos' (int) arguments only.", - DeprecationWarning, - stacklevel=2, - ) - if pos is not DEPRECATED_DEFAULT: - args = pos, *args - if doc is not DEPRECATED_DEFAULT: - args = doc, *args - if msg is not DEPRECATED_DEFAULT: - args = msg, *args - ValueError.__init__(self, *args) - return - - lineno = doc.count("\n", 0, pos) + 1 - if lineno == 1: - colno = pos + 1 - else: - colno = pos - doc.rindex("\n", 0, pos) - - if pos >= len(doc): - coord_repr = "end of document" - else: - coord_repr = f"line {lineno}, column {colno}" - errmsg = f"{msg} (at {coord_repr})" - ValueError.__init__(self, errmsg) - - self.msg = msg - self.doc = doc - self.pos = pos - self.lineno = lineno - self.colno = colno + """An error raised if a document is not valid TOML.""" -def load(__fp: IO[bytes], *, parse_float: ParseFloat = float) -> dict[str, Any]: +def load(__fp: BinaryIO, *, parse_float: ParseFloat = float) -> dict[str, Any]: """Parse TOML from a binary file object.""" b = __fp.read() try: @@ -150,14 +71,9 @@ def loads(__s: str, *, parse_float: ParseFloat = float) -> dict[str, Any]: # no # The spec allows converting "\r\n" to "\n", even in string # literals. Let's do so to simplify parsing. - try: - src = __s.replace("\r\n", "\n") - except (AttributeError, TypeError): - raise TypeError( - f"Expected str object, not '{type(__s).__qualname__}'" - ) from None + src = __s.replace("\r\n", "\n") pos = 0 - out = Output() + out = Output(NestedDict(), Flags()) header: Key = () parse_float = make_safe_parse_float(parse_float) @@ -197,7 +113,7 @@ def loads(__s: str, *, parse_float: ParseFloat = float) -> dict[str, Any]: # no pos, header = create_dict_rule(src, pos, out) pos = skip_chars(src, pos, TOML_WS) elif char != "#": - raise TOMLDecodeError("Invalid statement", src, pos) + raise suffixed_err(src, pos, "Invalid statement") # 3. Skip comment pos = skip_comment(src, pos) @@ -208,8 +124,8 @@ def loads(__s: str, *, parse_float: ParseFloat = float) -> dict[str, Any]: # no except IndexError: break if char != "\n": - raise TOMLDecodeError( - "Expected newline or end of document after a statement", src, pos + raise suffixed_err( + src, pos, "Expected newline or end of document after a statement" ) pos += 1 @@ -220,13 +136,13 @@ class Flags: """Flags that map to parsed keys/namespaces.""" # Marks an immutable namespace (inline array or inline table). - FROZEN: Final = 0 + FROZEN = 0 # Marks a nest that has been explicitly created and can no longer # be opened using the "[table]" syntax. - EXPLICIT_NEST: Final = 1 + EXPLICIT_NEST = 1 def __init__(self) -> None: - self._flags: dict[str, dict[Any, Any]] = {} + self._flags: dict[str, dict] = {} self._pending_flags: set[tuple[Key, int]] = set() def add_pending(self, key: Key, flag: int) -> None: @@ -269,8 +185,8 @@ def is_(self, key: Key, flag: int) -> bool: cont = inner_cont["nested"] key_stem = key[-1] if key_stem in cont: - inner_cont = cont[key_stem] - return flag in inner_cont["flags"] or flag in inner_cont["recursive_flags"] + cont = cont[key_stem] + return flag in cont["flags"] or flag in cont["recursive_flags"] return False @@ -284,7 +200,7 @@ def get_or_create_nest( key: Key, *, access_lists: bool = True, - ) -> dict[str, Any]: + ) -> dict: cont: Any = self.dict for k in key: if k not in cont: @@ -294,7 +210,7 @@ def get_or_create_nest( cont = cont[-1] if not isinstance(cont, dict): raise KeyError("There is no nest behind this key") - return cont # type: ignore[no-any-return] + return cont def append_nest_to_list(self, key: Key) -> None: cont = self.get_or_create_nest(key[:-1]) @@ -308,10 +224,9 @@ def append_nest_to_list(self, key: Key) -> None: cont[last_key] = [{}] -class Output: - def __init__(self) -> None: - self.data = NestedDict() - self.flags = Flags() +class Output(NamedTuple): + data: NestedDict + flags: Flags def skip_chars(src: str, pos: Pos, chars: Iterable[str]) -> Pos: @@ -336,12 +251,12 @@ def skip_until( except ValueError: new_pos = len(src) if error_on_eof: - raise TOMLDecodeError(f"Expected {expect!r}", src, new_pos) from None + raise suffixed_err(src, new_pos, f"Expected {expect!r}") from None if not error_on.isdisjoint(src[pos:new_pos]): while src[pos] not in error_on: pos += 1 - raise TOMLDecodeError(f"Found invalid character {src[pos]!r}", src, pos) + raise suffixed_err(src, pos, f"Found invalid character {src[pos]!r}") return new_pos @@ -372,17 +287,15 @@ def create_dict_rule(src: str, pos: Pos, out: Output) -> tuple[Pos, Key]: pos, key = parse_key(src, pos) if out.flags.is_(key, Flags.EXPLICIT_NEST) or out.flags.is_(key, Flags.FROZEN): - raise TOMLDecodeError(f"Cannot declare {key} twice", src, pos) + raise suffixed_err(src, pos, f"Cannot declare {key} twice") out.flags.set(key, Flags.EXPLICIT_NEST, recursive=False) try: out.data.get_or_create_nest(key) except KeyError: - raise TOMLDecodeError("Cannot overwrite a value", src, pos) from None + raise suffixed_err(src, pos, "Cannot overwrite a value") from None if not src.startswith("]", pos): - raise TOMLDecodeError( - "Expected ']' at the end of a table declaration", src, pos - ) + raise suffixed_err(src, pos, "Expected ']' at the end of a table declaration") return pos + 1, key @@ -392,7 +305,7 @@ def create_list_rule(src: str, pos: Pos, out: Output) -> tuple[Pos, Key]: pos, key = parse_key(src, pos) if out.flags.is_(key, Flags.FROZEN): - raise TOMLDecodeError(f"Cannot mutate immutable namespace {key}", src, pos) + raise suffixed_err(src, pos, f"Cannot mutate immutable namespace {key}") # Free the namespace now that it points to another empty list item... out.flags.unset_all(key) # ...but this key precisely is still prohibited from table declaration @@ -400,19 +313,17 @@ def create_list_rule(src: str, pos: Pos, out: Output) -> tuple[Pos, Key]: try: out.data.append_nest_to_list(key) except KeyError: - raise TOMLDecodeError("Cannot overwrite a value", src, pos) from None + raise suffixed_err(src, pos, "Cannot overwrite a value") from None if not src.startswith("]]", pos): - raise TOMLDecodeError( - "Expected ']]' at the end of an array declaration", src, pos - ) + raise suffixed_err(src, pos, "Expected ']]' at the end of an array declaration") return pos + 2, key def key_value_rule( src: str, pos: Pos, out: Output, header: Key, parse_float: ParseFloat ) -> Pos: - pos, key, value = parse_key_value_pair(src, pos, parse_float, nest_lvl=0) + pos, key, value = parse_key_value_pair(src, pos, parse_float) key_parent, key_stem = key[:-1], key[-1] abs_key_parent = header + key_parent @@ -420,22 +331,22 @@ def key_value_rule( for cont_key in relative_path_cont_keys: # Check that dotted key syntax does not redefine an existing table if out.flags.is_(cont_key, Flags.EXPLICIT_NEST): - raise TOMLDecodeError(f"Cannot redefine namespace {cont_key}", src, pos) + raise suffixed_err(src, pos, f"Cannot redefine namespace {cont_key}") # Containers in the relative path can't be opened with the table syntax or # dotted key/value syntax in following table sections. out.flags.add_pending(cont_key, Flags.EXPLICIT_NEST) if out.flags.is_(abs_key_parent, Flags.FROZEN): - raise TOMLDecodeError( - f"Cannot mutate immutable namespace {abs_key_parent}", src, pos + raise suffixed_err( + src, pos, f"Cannot mutate immutable namespace {abs_key_parent}" ) try: nest = out.data.get_or_create_nest(abs_key_parent) except KeyError: - raise TOMLDecodeError("Cannot overwrite a value", src, pos) from None + raise suffixed_err(src, pos, "Cannot overwrite a value") from None if key_stem in nest: - raise TOMLDecodeError("Cannot overwrite a value", src, pos) + raise suffixed_err(src, pos, "Cannot overwrite a value") # Mark inline table and array namespaces recursively immutable if isinstance(value, (dict, list)): out.flags.set(header + key, Flags.FROZEN, recursive=True) @@ -444,7 +355,7 @@ def key_value_rule( def parse_key_value_pair( - src: str, pos: Pos, parse_float: ParseFloat, nest_lvl: int + src: str, pos: Pos, parse_float: ParseFloat ) -> tuple[Pos, Key, Any]: pos, key = parse_key(src, pos) try: @@ -452,10 +363,10 @@ def parse_key_value_pair( except IndexError: char = None if char != "=": - raise TOMLDecodeError("Expected '=' after a key in a key/value pair", src, pos) + raise suffixed_err(src, pos, "Expected '=' after a key in a key/value pair") pos += 1 pos = skip_chars(src, pos, TOML_WS) - pos, value = parse_value(src, pos, parse_float, nest_lvl) + pos, value = parse_value(src, pos, parse_float) return pos, key, value @@ -490,7 +401,7 @@ def parse_key_part(src: str, pos: Pos) -> tuple[Pos, str]: return parse_literal_str(src, pos) if char == '"': return parse_one_line_basic_str(src, pos) - raise TOMLDecodeError("Invalid initial character for a key part", src, pos) + raise suffixed_err(src, pos, "Invalid initial character for a key part") def parse_one_line_basic_str(src: str, pos: Pos) -> tuple[Pos, str]: @@ -498,17 +409,15 @@ def parse_one_line_basic_str(src: str, pos: Pos) -> tuple[Pos, str]: return parse_basic_str(src, pos, multiline=False) -def parse_array( - src: str, pos: Pos, parse_float: ParseFloat, nest_lvl: int -) -> tuple[Pos, list[Any]]: +def parse_array(src: str, pos: Pos, parse_float: ParseFloat) -> tuple[Pos, list]: pos += 1 - array: list[Any] = [] + array: list = [] pos = skip_comments_and_array_ws(src, pos) if src.startswith("]", pos): return pos + 1, array while True: - pos, val = parse_value(src, pos, parse_float, nest_lvl) + pos, val = parse_value(src, pos, parse_float) array.append(val) pos = skip_comments_and_array_ws(src, pos) @@ -516,7 +425,7 @@ def parse_array( if c == "]": return pos + 1, array if c != ",": - raise TOMLDecodeError("Unclosed array", src, pos) + raise suffixed_err(src, pos, "Unclosed array") pos += 1 pos = skip_comments_and_array_ws(src, pos) @@ -524,9 +433,7 @@ def parse_array( return pos + 1, array -def parse_inline_table( - src: str, pos: Pos, parse_float: ParseFloat, nest_lvl: int -) -> tuple[Pos, dict[str, Any]]: +def parse_inline_table(src: str, pos: Pos, parse_float: ParseFloat) -> tuple[Pos, dict]: pos += 1 nested_dict = NestedDict() flags = Flags() @@ -535,23 +442,23 @@ def parse_inline_table( if src.startswith("}", pos): return pos + 1, nested_dict.dict while True: - pos, key, value = parse_key_value_pair(src, pos, parse_float, nest_lvl) + pos, key, value = parse_key_value_pair(src, pos, parse_float) key_parent, key_stem = key[:-1], key[-1] if flags.is_(key, Flags.FROZEN): - raise TOMLDecodeError(f"Cannot mutate immutable namespace {key}", src, pos) + raise suffixed_err(src, pos, f"Cannot mutate immutable namespace {key}") try: nest = nested_dict.get_or_create_nest(key_parent, access_lists=False) except KeyError: - raise TOMLDecodeError("Cannot overwrite a value", src, pos) from None + raise suffixed_err(src, pos, "Cannot overwrite a value") from None if key_stem in nest: - raise TOMLDecodeError(f"Duplicate inline table key {key_stem!r}", src, pos) + raise suffixed_err(src, pos, f"Duplicate inline table key {key_stem!r}") nest[key_stem] = value pos = skip_chars(src, pos, TOML_WS) c = src[pos : pos + 1] if c == "}": return pos + 1, nested_dict.dict if c != ",": - raise TOMLDecodeError("Unclosed inline table", src, pos) + raise suffixed_err(src, pos, "Unclosed inline table") if isinstance(value, (dict, list)): flags.set(key, Flags.FROZEN, recursive=True) pos += 1 @@ -573,7 +480,7 @@ def parse_basic_str_escape( except IndexError: return pos, "" if char != "\n": - raise TOMLDecodeError("Unescaped '\\' in a string", src, pos) + raise suffixed_err(src, pos, "Unescaped '\\' in a string") pos += 1 pos = skip_chars(src, pos, TOML_WS_AND_NEWLINE) return pos, "" @@ -584,7 +491,7 @@ def parse_basic_str_escape( try: return pos, BASIC_STR_ESCAPE_REPLACEMENTS[escape_id] except KeyError: - raise TOMLDecodeError("Unescaped '\\' in a string", src, pos) from None + raise suffixed_err(src, pos, "Unescaped '\\' in a string") from None def parse_basic_str_escape_multiline(src: str, pos: Pos) -> tuple[Pos, str]: @@ -594,13 +501,11 @@ def parse_basic_str_escape_multiline(src: str, pos: Pos) -> tuple[Pos, str]: def parse_hex_char(src: str, pos: Pos, hex_len: int) -> tuple[Pos, str]: hex_str = src[pos : pos + hex_len] if len(hex_str) != hex_len or not HEXDIGIT_CHARS.issuperset(hex_str): - raise TOMLDecodeError("Invalid hex value", src, pos) + raise suffixed_err(src, pos, "Invalid hex value") pos += hex_len hex_int = int(hex_str, 16) if not is_unicode_scalar_value(hex_int): - raise TOMLDecodeError( - "Escaped character is not a Unicode scalar value", src, pos - ) + raise suffixed_err(src, pos, "Escaped character is not a Unicode scalar value") return pos, chr(hex_int) @@ -657,7 +562,7 @@ def parse_basic_str(src: str, pos: Pos, *, multiline: bool) -> tuple[Pos, str]: try: char = src[pos] except IndexError: - raise TOMLDecodeError("Unterminated string", src, pos) from None + raise suffixed_err(src, pos, "Unterminated string") from None if char == '"': if not multiline: return pos + 1, result + src[start_pos:pos] @@ -672,21 +577,13 @@ def parse_basic_str(src: str, pos: Pos, *, multiline: bool) -> tuple[Pos, str]: start_pos = pos continue if char in error_on: - raise TOMLDecodeError(f"Illegal character {char!r}", src, pos) + raise suffixed_err(src, pos, f"Illegal character {char!r}") pos += 1 def parse_value( # noqa: C901 - src: str, pos: Pos, parse_float: ParseFloat, nest_lvl: int + src: str, pos: Pos, parse_float: ParseFloat ) -> tuple[Pos, Any]: - if nest_lvl > MAX_INLINE_NESTING: - # Pure Python should have raised RecursionError already. - # This ensures mypyc binaries eventually do the same. - raise RecursionError( # pragma: no cover - "TOML inline arrays/tables are nested more than the allowed" - f" {MAX_INLINE_NESTING} levels" - ) - try: char: str | None = src[pos] except IndexError: @@ -716,11 +613,11 @@ def parse_value( # noqa: C901 # Arrays if char == "[": - return parse_array(src, pos, parse_float, nest_lvl + 1) + return parse_array(src, pos, parse_float) # Inline tables if char == "{": - return parse_inline_table(src, pos, parse_float, nest_lvl + 1) + return parse_inline_table(src, pos, parse_float) # Dates and times datetime_match = RE_DATETIME.match(src, pos) @@ -728,7 +625,7 @@ def parse_value( # noqa: C901 try: datetime_obj = match_to_datetime(datetime_match) except ValueError as e: - raise TOMLDecodeError("Invalid date or datetime", src, pos) from e + raise suffixed_err(src, pos, "Invalid date or datetime") from e return datetime_match.end(), datetime_obj localtime_match = RE_LOCALTIME.match(src, pos) if localtime_match: @@ -749,7 +646,24 @@ def parse_value( # noqa: C901 if first_four in {"-inf", "+inf", "-nan", "+nan"}: return pos + 4, parse_float(first_four) - raise TOMLDecodeError("Invalid value", src, pos) + raise suffixed_err(src, pos, "Invalid value") + + +def suffixed_err(src: str, pos: Pos, msg: str) -> TOMLDecodeError: + """Return a `TOMLDecodeError` where error message is suffixed with + coordinates in source.""" + + def coord_repr(src: str, pos: Pos) -> str: + if pos >= len(src): + return "end of document" + line = src.count("\n", 0, pos) + 1 + if line == 1: + column = pos + 1 + else: + column = pos - src.rindex("\n", 0, pos) + return f"line {line}, column {column}" + + return TOMLDecodeError(f"{msg} (at {coord_repr(src, pos)})") def is_unicode_scalar_value(codepoint: int) -> bool: @@ -765,7 +679,7 @@ def make_safe_parse_float(parse_float: ParseFloat) -> ParseFloat: instead of returning illegal types. """ # The default `float` callable never returns illegal types. Optimize it. - if parse_float is float: + if parse_float is float: # type: ignore[comparison-overlap] return float def safe_parse_float(float_str: str) -> Any: diff --git a/venv1/Lib/site-packages/pip/_vendor/tomli/_re.py b/venv1/Lib/site-packages/pip/_vendor/tomli/_re.py index c159dcfa..994bb749 100644 --- a/venv1/Lib/site-packages/pip/_vendor/tomli/_re.py +++ b/venv1/Lib/site-packages/pip/_vendor/tomli/_re.py @@ -7,21 +7,16 @@ from datetime import date, datetime, time, timedelta, timezone, tzinfo from functools import lru_cache import re +from typing import Any -TYPE_CHECKING = False -if TYPE_CHECKING: - from typing import Any, Final - - from ._types import ParseFloat +from ._types import ParseFloat # E.g. # - 00:32:00.999999 # - 00:32:00 -_TIME_RE_STR: Final = ( - r"([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])(?:\.([0-9]{1,6})[0-9]*)?" -) +_TIME_RE_STR = r"([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])(?:\.([0-9]{1,6})[0-9]*)?" -RE_NUMBER: Final = re.compile( +RE_NUMBER = re.compile( r""" 0 (?: @@ -40,8 +35,8 @@ """, flags=re.VERBOSE, ) -RE_LOCALTIME: Final = re.compile(_TIME_RE_STR) -RE_DATETIME: Final = re.compile( +RE_LOCALTIME = re.compile(_TIME_RE_STR) +RE_DATETIME = re.compile( rf""" ([0-9]{{4}})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01]) # date, e.g. 1988-10-27 (?: @@ -54,7 +49,7 @@ ) -def match_to_datetime(match: re.Match[str]) -> datetime | date: +def match_to_datetime(match: re.Match) -> datetime | date: """Convert a `RE_DATETIME` match to `datetime.datetime` or `datetime.date`. Raises ValueError if the match does not correspond to a valid date @@ -89,9 +84,6 @@ def match_to_datetime(match: re.Match[str]) -> datetime | date: return datetime(year, month, day, hour, minute, sec, micros, tzinfo=tz) -# No need to limit cache size. This is only ever called on input -# that matched RE_DATETIME, so there is an implicit bound of -# 24 (hours) * 60 (minutes) * 2 (offset direction) = 2880. @lru_cache(maxsize=None) def cached_tz(hour_str: str, minute_str: str, sign_str: str) -> timezone: sign = 1 if sign_str == "+" else -1 @@ -103,13 +95,13 @@ def cached_tz(hour_str: str, minute_str: str, sign_str: str) -> timezone: ) -def match_to_localtime(match: re.Match[str]) -> time: +def match_to_localtime(match: re.Match) -> time: hour_str, minute_str, sec_str, micros_str = match.groups() micros = int(micros_str.ljust(6, "0")) if micros_str else 0 return time(int(hour_str), int(minute_str), int(sec_str), micros) -def match_to_number(match: re.Match[str], parse_float: ParseFloat) -> Any: +def match_to_number(match: re.Match, parse_float: ParseFloat) -> Any: if match.group("floatpart"): return parse_float(match.group()) return int(match.group(), 0) diff --git a/venv1/Lib/site-packages/pip/_vendor/tomli/py.typed b/venv1/Lib/site-packages/pip/_vendor/tomli/py.typed deleted file mode 100644 index 7632ecf7..00000000 --- a/venv1/Lib/site-packages/pip/_vendor/tomli/py.typed +++ /dev/null @@ -1 +0,0 @@ -# Marker file for PEP 561 diff --git a/venv1/Lib/site-packages/pip/_vendor/truststore/__init__.py b/venv1/Lib/site-packages/pip/_vendor/truststore/__init__.py deleted file mode 100644 index 0166459b..00000000 --- a/venv1/Lib/site-packages/pip/_vendor/truststore/__init__.py +++ /dev/null @@ -1,36 +0,0 @@ -"""Verify certificates using native system trust stores""" - -import sys as _sys - -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) and _sys.implementation.name not in ("cpython", "pypy"): - 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.10.4" diff --git a/venv1/Lib/site-packages/pip/_vendor/truststore/_api.py b/venv1/Lib/site-packages/pip/_vendor/truststore/_api.py deleted file mode 100644 index a54ff9f2..00000000 --- a/venv1/Lib/site-packages/pip/_vendor/truststore/_api.py +++ /dev/null @@ -1,341 +0,0 @@ -import contextlib -import os -import platform -import socket -import ssl -import sys -import threading -import typing - -import _ssl - -from ._ssl_constants import ( - _original_SSLContext, - _original_super_SSLContext, - _truststore_SSLContext_dunder_class, - _truststore_SSLContext_super_class, -) - -if platform.system() == "Windows": - from ._windows import _configure_context, _verify_peercerts_impl -elif platform.system() == "Darwin": - from ._macos import _configure_context, _verify_peercerts_impl -else: - from ._openssl import _configure_context, _verify_peercerts_impl - -if typing.TYPE_CHECKING: - from typing_extensions import Buffer - -# From typeshed/stdlib/ssl.pyi -_StrOrBytesPath: typing.TypeAlias = str | bytes | os.PathLike[str] | os.PathLike[bytes] -_PasswordType: typing.TypeAlias = str | bytes | typing.Callable[[], str | bytes] - - -def inject_into_ssl() -> None: - """Injects the :class:`truststore.SSLContext` into the ``ssl`` - module by replacing :class:`ssl.SSLContext`. - """ - setattr(ssl, "SSLContext", SSLContext) - # urllib3 holds on to its own reference of ssl.SSLContext - # so we need to replace that reference too. - try: - import pip._vendor.urllib3.util.ssl_ as urllib3_ssl - - setattr(urllib3_ssl, "SSLContext", SSLContext) - except ImportError: - pass - - # requests starting with 2.32.0 added a preloaded SSL context to improve concurrent performance; - # this unfortunately leads to a RecursionError, which can be avoided by patching the preloaded SSL context with - # the truststore patched instance - # also see https://github.com/psf/requests/pull/6667 - try: - from pip._vendor.requests import adapters as requests_adapters - - preloaded_context = getattr(requests_adapters, "_preloaded_ssl_context", None) - if preloaded_context is not None: - setattr( - requests_adapters, - "_preloaded_ssl_context", - SSLContext(ssl.PROTOCOL_TLS_CLIENT), - ) - except ImportError: - pass - - -def extract_from_ssl() -> None: - """Restores the :class:`ssl.SSLContext` class to its original state""" - setattr(ssl, "SSLContext", _original_SSLContext) - try: - import pip._vendor.urllib3.util.ssl_ as urllib3_ssl - - urllib3_ssl.SSLContext = _original_SSLContext - except ImportError: - pass - - -class SSLContext(_truststore_SSLContext_super_class): # type: ignore[misc] - """SSLContext API that uses system certificates on all platforms""" - - @property # type: ignore[misc] - def __class__(self) -> type: - # Dirty hack to get around isinstance() checks - # for ssl.SSLContext instances in aiohttp/trustme - # when using non-CPython implementations. - return _truststore_SSLContext_dunder_class or SSLContext - - def __init__(self, protocol: int = None) -> None: # type: ignore[assignment] - self._ctx = _original_SSLContext(protocol) - self._ctx_lock = threading.Lock() - - class TruststoreSSLObject(ssl.SSLObject): - # This object exists because wrap_bio() doesn't - # immediately do the handshake so we need to do - # certificate verifications after SSLObject.do_handshake() - - def do_handshake(self) -> None: - ret = super().do_handshake() - _verify_peercerts(self, server_hostname=self.server_hostname) - return ret - - self._ctx.sslobject_class = TruststoreSSLObject - - def wrap_socket( - self, - sock: socket.socket, - server_side: bool = False, - do_handshake_on_connect: bool = True, - suppress_ragged_eofs: bool = True, - server_hostname: str | None = None, - session: ssl.SSLSession | None = None, - ) -> ssl.SSLSocket: - - # We need to lock around the .__enter__() - # but we don't need to lock within the - # context manager, so we need to expand the - # syntactic sugar of the `with` statement. - with contextlib.ExitStack() as stack: - with self._ctx_lock: - stack.enter_context(_configure_context(self._ctx)) - - ssl_sock = self._ctx.wrap_socket( - sock, - server_side=server_side, - server_hostname=server_hostname, - do_handshake_on_connect=do_handshake_on_connect, - suppress_ragged_eofs=suppress_ragged_eofs, - session=session, - ) - try: - _verify_peercerts(ssl_sock, server_hostname=server_hostname) - except Exception: - ssl_sock.close() - raise - return ssl_sock - - def wrap_bio( - self, - incoming: ssl.MemoryBIO, - outgoing: ssl.MemoryBIO, - server_side: bool = False, - server_hostname: str | None = None, - session: ssl.SSLSession | None = None, - ) -> ssl.SSLObject: - with _configure_context(self._ctx): - ssl_obj = self._ctx.wrap_bio( - incoming, - outgoing, - server_hostname=server_hostname, - server_side=server_side, - session=session, - ) - return ssl_obj - - def load_verify_locations( - self, - cafile: str | bytes | os.PathLike[str] | os.PathLike[bytes] | None = None, - capath: str | bytes | os.PathLike[str] | os.PathLike[bytes] | None = None, - cadata: typing.Union[str, "Buffer", None] = None, - ) -> None: - return self._ctx.load_verify_locations( - cafile=cafile, capath=capath, cadata=cadata - ) - - def load_cert_chain( - self, - certfile: _StrOrBytesPath, - keyfile: _StrOrBytesPath | None = None, - password: _PasswordType | None = None, - ) -> None: - return self._ctx.load_cert_chain( - certfile=certfile, keyfile=keyfile, password=password - ) - - def load_default_certs( - self, purpose: ssl.Purpose = ssl.Purpose.SERVER_AUTH - ) -> None: - return self._ctx.load_default_certs(purpose) - - def set_alpn_protocols(self, alpn_protocols: typing.Iterable[str]) -> None: - return self._ctx.set_alpn_protocols(alpn_protocols) - - def set_npn_protocols(self, npn_protocols: typing.Iterable[str]) -> None: - return self._ctx.set_npn_protocols(npn_protocols) - - def set_ciphers(self, __cipherlist: str) -> None: - return self._ctx.set_ciphers(__cipherlist) - - def get_ciphers(self) -> typing.Any: - return self._ctx.get_ciphers() - - def session_stats(self) -> dict[str, int]: - return self._ctx.session_stats() - - 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] = ... - ) -> list[typing.Any]: ... - - @typing.overload - def get_ca_certs(self, binary_form: typing.Literal[True] = ...) -> list[bytes]: ... - - @typing.overload - def get_ca_certs(self, binary_form: bool = ...) -> typing.Any: ... - - def get_ca_certs(self, binary_form: bool = False) -> list[typing.Any] | list[bytes]: - raise NotImplementedError() - - @property - def check_hostname(self) -> bool: - return self._ctx.check_hostname - - @check_hostname.setter - def check_hostname(self, value: bool) -> None: - self._ctx.check_hostname = value - - @property - def hostname_checks_common_name(self) -> bool: - return self._ctx.hostname_checks_common_name - - @hostname_checks_common_name.setter - def hostname_checks_common_name(self, value: bool) -> None: - self._ctx.hostname_checks_common_name = value - - @property - def keylog_filename(self) -> str: - return self._ctx.keylog_filename - - @keylog_filename.setter - def keylog_filename(self, value: str) -> None: - self._ctx.keylog_filename = value - - @property - def maximum_version(self) -> ssl.TLSVersion: - return self._ctx.maximum_version - - @maximum_version.setter - def maximum_version(self, value: ssl.TLSVersion) -> None: - _original_super_SSLContext.maximum_version.__set__( # type: ignore[attr-defined] - self._ctx, value - ) - - @property - def minimum_version(self) -> ssl.TLSVersion: - return self._ctx.minimum_version - - @minimum_version.setter - def minimum_version(self, value: ssl.TLSVersion) -> None: - _original_super_SSLContext.minimum_version.__set__( # type: ignore[attr-defined] - self._ctx, value - ) - - @property - def options(self) -> ssl.Options: - return self._ctx.options - - @options.setter - def options(self, value: ssl.Options) -> None: - _original_super_SSLContext.options.__set__( # type: ignore[attr-defined] - self._ctx, value - ) - - @property - def post_handshake_auth(self) -> bool: - return self._ctx.post_handshake_auth - - @post_handshake_auth.setter - def post_handshake_auth(self, value: bool) -> None: - self._ctx.post_handshake_auth = value - - @property - def protocol(self) -> ssl._SSLMethod: - return self._ctx.protocol - - @property - def security_level(self) -> int: - return self._ctx.security_level - - @property - def verify_flags(self) -> ssl.VerifyFlags: - return self._ctx.verify_flags - - @verify_flags.setter - def verify_flags(self, value: ssl.VerifyFlags) -> None: - _original_super_SSLContext.verify_flags.__set__( # type: ignore[attr-defined] - self._ctx, value - ) - - @property - def verify_mode(self) -> ssl.VerifyMode: - return self._ctx.verify_mode - - @verify_mode.setter - def verify_mode(self, value: ssl.VerifyMode) -> None: - _original_super_SSLContext.verify_mode.__set__( # type: ignore[attr-defined] - self._ctx, value - ) - - -# Python 3.13+ makes get_unverified_chain() a public API that only returns DER -# encoded certificates. We detect whether we need to call public_bytes() for 3.10->3.12 -# Pre-3.13 returned None instead of an empty list from get_unverified_chain() -if sys.version_info >= (3, 13): - - def _get_unverified_chain_bytes(sslobj: ssl.SSLObject) -> list[bytes]: - unverified_chain = sslobj.get_unverified_chain() or () - return [ - cert if isinstance(cert, bytes) else cert.public_bytes(_ssl.ENCODING_DER) - for cert in unverified_chain - ] - -else: - - def _get_unverified_chain_bytes(sslobj: ssl.SSLObject) -> list[bytes]: - unverified_chain = sslobj.get_unverified_chain() or () # type: ignore[attr-defined] - return [cert.public_bytes(_ssl.ENCODING_DER) for cert in unverified_chain] - - -def _verify_peercerts( - sock_or_sslobj: ssl.SSLSocket | ssl.SSLObject, server_hostname: str | None -) -> None: - """ - Verifies the peer certificates from an SSLSocket or SSLObject - against the certificates in the OS trust store. - """ - sslobj: ssl.SSLObject = sock_or_sslobj # type: ignore[assignment] - try: - while not hasattr(sslobj, "get_unverified_chain"): - sslobj = sslobj._sslobj # type: ignore[attr-defined] - except AttributeError: - pass - - cert_bytes = _get_unverified_chain_bytes(sslobj) - _verify_peercerts_impl( - sock_or_sslobj.context, cert_bytes, server_hostname=server_hostname - ) diff --git a/venv1/Lib/site-packages/pip/_vendor/truststore/_macos.py b/venv1/Lib/site-packages/pip/_vendor/truststore/_macos.py deleted file mode 100644 index 34503077..00000000 --- a/venv1/Lib/site-packages/pip/_vendor/truststore/_macos.py +++ /dev/null @@ -1,571 +0,0 @@ -import contextlib -import ctypes -import platform -import ssl -import typing -from ctypes import ( - CDLL, - POINTER, - c_bool, - c_char_p, - c_int32, - c_long, - c_uint32, - c_ulong, - c_void_p, -) -from ctypes.util import find_library - -from ._ssl_constants import _set_ssl_context_verify_mode - -_mac_version = platform.mac_ver()[0] -_mac_version_info = tuple(map(int, _mac_version.split("."))) -if _mac_version_info < (10, 8): - raise ImportError( - 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+""" - try: - # Big Sur is technically 11 but we use 10.16 due to the Big Sur - # beta being labeled as 10.16. - path: str | None - if _mac_version_info >= (10, 16): - path = macos10_16_path - else: - path = find_library(name) - if not path: - raise OSError # Caught and reraised as 'ImportError' - return CDLL(path, use_errno=True) - except OSError: - raise ImportError(f"The library {name} failed to load") from None - - -Security = _load_cdll( - "Security", "/System/Library/Frameworks/Security.framework/Security" -) -CoreFoundation = _load_cdll( - "CoreFoundation", - "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", -) - -Boolean = c_bool -CFIndex = c_long -CFStringEncoding = c_uint32 -CFData = c_void_p -CFString = c_void_p -CFArray = c_void_p -CFMutableArray = c_void_p -CFError = c_void_p -CFType = c_void_p -CFTypeID = c_ulong -CFTypeRef = POINTER(CFType) -CFAllocatorRef = c_void_p - -OSStatus = c_int32 - -CFErrorRef = POINTER(CFError) -CFDataRef = POINTER(CFData) -CFStringRef = POINTER(CFString) -CFArrayRef = POINTER(CFArray) -CFMutableArrayRef = POINTER(CFMutableArray) -CFArrayCallBacks = c_void_p -CFOptionFlags = c_uint32 - -SecCertificateRef = POINTER(c_void_p) -SecPolicyRef = POINTER(c_void_p) -SecTrustRef = POINTER(c_void_p) -SecTrustResultType = c_uint32 -SecTrustOptionFlags = c_uint32 - -try: - Security.SecCertificateCreateWithData.argtypes = [CFAllocatorRef, CFDataRef] - Security.SecCertificateCreateWithData.restype = SecCertificateRef - - Security.SecCertificateCopyData.argtypes = [SecCertificateRef] - Security.SecCertificateCopyData.restype = CFDataRef - - Security.SecCopyErrorMessageString.argtypes = [OSStatus, c_void_p] - Security.SecCopyErrorMessageString.restype = CFStringRef - - Security.SecTrustSetAnchorCertificates.argtypes = [SecTrustRef, CFArrayRef] - Security.SecTrustSetAnchorCertificates.restype = OSStatus - - Security.SecTrustSetAnchorCertificatesOnly.argtypes = [SecTrustRef, Boolean] - Security.SecTrustSetAnchorCertificatesOnly.restype = OSStatus - - Security.SecPolicyCreateRevocation.argtypes = [CFOptionFlags] - Security.SecPolicyCreateRevocation.restype = SecPolicyRef - - Security.SecPolicyCreateSSL.argtypes = [Boolean, CFStringRef] - Security.SecPolicyCreateSSL.restype = SecPolicyRef - - Security.SecTrustCreateWithCertificates.argtypes = [ - CFTypeRef, - CFTypeRef, - POINTER(SecTrustRef), - ] - Security.SecTrustCreateWithCertificates.restype = OSStatus - - Security.SecTrustGetTrustResult.argtypes = [ - SecTrustRef, - POINTER(SecTrustResultType), - ] - 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] - - kSecRevocationUseAnyAvailableMethod = 3 - kSecRevocationRequirePositiveResponse = 8 - - CoreFoundation.CFRelease.argtypes = [CFTypeRef] - CoreFoundation.CFRelease.restype = None - - CoreFoundation.CFGetTypeID.argtypes = [CFTypeRef] - CoreFoundation.CFGetTypeID.restype = CFTypeID - - CoreFoundation.CFStringCreateWithCString.argtypes = [ - CFAllocatorRef, - c_char_p, - CFStringEncoding, - ] - CoreFoundation.CFStringCreateWithCString.restype = CFStringRef - - CoreFoundation.CFStringGetCStringPtr.argtypes = [CFStringRef, CFStringEncoding] - CoreFoundation.CFStringGetCStringPtr.restype = c_char_p - - CoreFoundation.CFStringGetCString.argtypes = [ - CFStringRef, - c_char_p, - CFIndex, - CFStringEncoding, - ] - CoreFoundation.CFStringGetCString.restype = c_bool - - CoreFoundation.CFDataCreate.argtypes = [CFAllocatorRef, c_char_p, CFIndex] - CoreFoundation.CFDataCreate.restype = CFDataRef - - CoreFoundation.CFDataGetLength.argtypes = [CFDataRef] - CoreFoundation.CFDataGetLength.restype = CFIndex - - CoreFoundation.CFDataGetBytePtr.argtypes = [CFDataRef] - CoreFoundation.CFDataGetBytePtr.restype = c_void_p - - CoreFoundation.CFArrayCreate.argtypes = [ - CFAllocatorRef, - POINTER(CFTypeRef), - CFIndex, - CFArrayCallBacks, - ] - CoreFoundation.CFArrayCreate.restype = CFArrayRef - - CoreFoundation.CFArrayCreateMutable.argtypes = [ - CFAllocatorRef, - CFIndex, - CFArrayCallBacks, - ] - CoreFoundation.CFArrayCreateMutable.restype = CFMutableArrayRef - - CoreFoundation.CFArrayAppendValue.argtypes = [CFMutableArrayRef, c_void_p] - CoreFoundation.CFArrayAppendValue.restype = None - - CoreFoundation.CFArrayGetCount.argtypes = [CFArrayRef] - CoreFoundation.CFArrayGetCount.restype = CFIndex - - CoreFoundation.CFArrayGetValueAtIndex.argtypes = [CFArrayRef, CFIndex] - CoreFoundation.CFArrayGetValueAtIndex.restype = c_void_p - - CoreFoundation.CFErrorGetCode.argtypes = [CFErrorRef] - CoreFoundation.CFErrorGetCode.restype = CFIndex - - CoreFoundation.CFErrorCopyDescription.argtypes = [CFErrorRef] - CoreFoundation.CFErrorCopyDescription.restype = CFStringRef - - CoreFoundation.kCFAllocatorDefault = CFAllocatorRef.in_dll( # type: ignore[attr-defined] - CoreFoundation, "kCFAllocatorDefault" - ) - CoreFoundation.kCFTypeArrayCallBacks = c_void_p.in_dll( # type: ignore[attr-defined] - CoreFoundation, "kCFTypeArrayCallBacks" - ) - - CoreFoundation.CFTypeRef = CFTypeRef # type: ignore[attr-defined] - CoreFoundation.CFArrayRef = CFArrayRef # type: ignore[attr-defined] - CoreFoundation.CFStringRef = CFStringRef # type: ignore[attr-defined] - CoreFoundation.CFErrorRef = CFErrorRef # type: ignore[attr-defined] - -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: - """ - Raises an error if the OSStatus value is non-zero. - """ - if int(result) == 0: - return args - - # Returns a CFString which we need to transform - # into a UTF-8 Python string. - error_message_cfstring = None - try: - error_message_cfstring = Security.SecCopyErrorMessageString(result, None) - - # First step is convert the CFString into a C string pointer. - # We try the fast no-copy way first. - error_message_cfstring_c_void_p = ctypes.cast( - error_message_cfstring, ctypes.POINTER(ctypes.c_void_p) - ) - message = CoreFoundation.CFStringGetCStringPtr( - error_message_cfstring_c_void_p, CFConst.kCFStringEncodingUTF8 - ) - - # Quoting the Apple dev docs: - # - # "A pointer to a C string or NULL if the internal - # storage of theString does not allow this to be - # returned efficiently." - # - # So we need to get our hands dirty. - if message is None: - buffer = ctypes.create_string_buffer(1024) - result = CoreFoundation.CFStringGetCString( - error_message_cfstring_c_void_p, - buffer, - 1024, - CFConst.kCFStringEncodingUTF8, - ) - if not result: - raise OSError("Error copying C string from CFStringRef") - message = buffer.value - - finally: - if error_message_cfstring is not None: - CoreFoundation.CFRelease(error_message_cfstring) - - # If no message can be found for this status we come - # up with a generic one that forwards the status code. - if message is None or message == "": - message = f"SecureTransport operation returned a non-zero OSStatus: {result}" - - raise ssl.SSLError(message) - - -Security.SecTrustCreateWithCertificates.errcheck = _handle_osstatus # type: ignore[assignment] -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: - """CoreFoundation constants""" - - kCFStringEncodingUTF8 = CFStringEncoding(0x08000100) - - errSecIncompleteCertRevocationCheck = -67635 - errSecHostNameMismatch = -67602 - errSecCertificateExpired = -67818 - errSecNotTrusted = -67843 - - -def _bytes_to_cf_data_ref(value: bytes) -> CFDataRef: # type: ignore[valid-type] - return CoreFoundation.CFDataCreate( # type: ignore[no-any-return] - CoreFoundation.kCFAllocatorDefault, value, len(value) - ) - - -def _bytes_to_cf_string(value: bytes) -> CFString: - """ - Given a Python binary data, create a CFString. - The string must be CFReleased by the caller. - """ - c_str = ctypes.c_char_p(value) - cf_str = CoreFoundation.CFStringCreateWithCString( - CoreFoundation.kCFAllocatorDefault, - c_str, - CFConst.kCFStringEncodingUTF8, - ) - return cf_str # type: ignore[no-any-return] - - -def _cf_string_ref_to_str(cf_string_ref: CFStringRef) -> str | None: # type: ignore[valid-type] - """ - Creates a Unicode string from a CFString object. Used entirely for error - reporting. - Yes, it annoys me quite a lot that this function is this complex. - """ - - string = CoreFoundation.CFStringGetCStringPtr( - cf_string_ref, CFConst.kCFStringEncodingUTF8 - ) - if string is None: - buffer = ctypes.create_string_buffer(1024) - result = CoreFoundation.CFStringGetCString( - cf_string_ref, buffer, 1024, CFConst.kCFStringEncodingUTF8 - ) - if not result: - raise OSError("Error copying C string from CFStringRef") - string = buffer.value - if string is not None: - string = string.decode("utf-8") - return string # type: ignore[no-any-return] - - -def _der_certs_to_cf_cert_array(certs: list[bytes]) -> CFMutableArrayRef: # type: ignore[valid-type] - """Builds a CFArray of SecCertificateRefs from a list of DER-encoded certificates. - Responsibility of the caller to call CoreFoundation.CFRelease on the CFArray. - """ - cf_array = CoreFoundation.CFArrayCreateMutable( - CoreFoundation.kCFAllocatorDefault, - 0, - ctypes.byref(CoreFoundation.kCFTypeArrayCallBacks), - ) - if not cf_array: - raise MemoryError("Unable to allocate memory!") - - for cert_data in certs: - cf_data = None - sec_cert_ref = None - try: - cf_data = _bytes_to_cf_data_ref(cert_data) - sec_cert_ref = Security.SecCertificateCreateWithData( - CoreFoundation.kCFAllocatorDefault, cf_data - ) - CoreFoundation.CFArrayAppendValue(cf_array, sec_cert_ref) - finally: - if cf_data: - CoreFoundation.CFRelease(cf_data) - if sec_cert_ref: - CoreFoundation.CFRelease(sec_cert_ref) - - return cf_array # type: ignore[no-any-return] - - -@contextlib.contextmanager -def _configure_context(ctx: ssl.SSLContext) -> typing.Iterator[None]: - check_hostname = ctx.check_hostname - verify_mode = ctx.verify_mode - ctx.check_hostname = False - _set_ssl_context_verify_mode(ctx, ssl.CERT_NONE) - try: - yield - finally: - ctx.check_hostname = check_hostname - _set_ssl_context_verify_mode(ctx, verify_mode) - - -def _verify_peercerts_impl( - ssl_context: ssl.SSLContext, - cert_chain: list[bytes], - server_hostname: str | None = None, -) -> None: - certs = None - policies = None - trust = None - try: - # 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")) - ssl_policy = Security.SecPolicyCreateSSL(True, cf_str_hostname) - finally: - if cf_str_hostname: - CoreFoundation.CFRelease(cf_str_hostname) - else: - ssl_policy = Security.SecPolicyCreateSSL(True, None) - - policies = ssl_policy - if ssl_context.verify_flags & ssl.VERIFY_CRL_CHECK_CHAIN: - # Add explicit policy requiring positive revocation checks - policies = CoreFoundation.CFArrayCreateMutable( - CoreFoundation.kCFAllocatorDefault, - 0, - ctypes.byref(CoreFoundation.kCFTypeArrayCallBacks), - ) - CoreFoundation.CFArrayAppendValue(policies, ssl_policy) - CoreFoundation.CFRelease(ssl_policy) - revocation_policy = Security.SecPolicyCreateRevocation( - kSecRevocationUseAnyAvailableMethod - | kSecRevocationRequirePositiveResponse - ) - CoreFoundation.CFArrayAppendValue(policies, revocation_policy) - CoreFoundation.CFRelease(revocation_policy) - elif ssl_context.verify_flags & ssl.VERIFY_CRL_CHECK_LEAF: - raise NotImplementedError("VERIFY_CRL_CHECK_LEAF not implemented for macOS") - - certs = None - try: - certs = _der_certs_to_cf_cert_array(cert_chain) - - # Now that we have certificates loaded and a SecPolicy - # we can finally create a SecTrust object! - trust = Security.SecTrustRef() - Security.SecTrustCreateWithCertificates( - certs, policies, ctypes.byref(trust) - ) - - finally: - # The certs are now being held by SecTrust so we can - # release our handles for the array. - if certs: - CoreFoundation.CFRelease(certs) - - # If there are additional trust anchors to load we need to transform - # the list of DER-encoded certificates into a CFArray. - ctx_ca_certs_der: list[bytes] | None = ssl_context.get_ca_certs( - binary_form=True - ) - if ctx_ca_certs_der: - ctx_ca_certs = None - try: - ctx_ca_certs = _der_certs_to_cf_cert_array(ctx_ca_certs_der) - Security.SecTrustSetAnchorCertificates(trust, ctx_ca_certs) - finally: - if ctx_ca_certs: - CoreFoundation.CFRelease(ctx_ca_certs) - - # We always want system certificates. - Security.SecTrustSetAnchorCertificatesOnly(trust, 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: - _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/venv1/Lib/site-packages/pip/_vendor/truststore/_openssl.py b/venv1/Lib/site-packages/pip/_vendor/truststore/_openssl.py deleted file mode 100644 index 3e25a567..00000000 --- a/venv1/Lib/site-packages/pip/_vendor/truststore/_openssl.py +++ /dev/null @@ -1,68 +0,0 @@ -import contextlib -import os -import re -import ssl -import typing - -# candidates based on https://github.com/tiran/certifi-system-store by Christian Heimes -_CA_FILE_CANDIDATES = [ - # Alpine, Arch, Fedora 34-42, OpenWRT, RHEL 9-10, BSD - "/etc/ssl/cert.pem", - # Fedora 43+, RHEL 11+ - "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", - # Fedora <= 34, RHEL <= 9, CentOS <= 9 - "/etc/pki/tls/cert.pem", - # Debian, Ubuntu (requires ca-certificates) - "/etc/ssl/certs/ca-certificates.crt", - # SUSE - "/etc/ssl/ca-bundle.pem", -] - -_HASHED_CERT_FILENAME_RE = re.compile(r"^[0-9a-fA-F]{8}\.[0-9]$") - - -@contextlib.contextmanager -def _configure_context(ctx: ssl.SSLContext) -> typing.Iterator[None]: - # First, check whether the default locations from OpenSSL - # seem like they will give us a usable set of CA certs. - # ssl.get_default_verify_paths already takes care of: - # - getting cafile from either the SSL_CERT_FILE env var - # or the path configured when OpenSSL was compiled, - # and verifying that that path exists - # - getting capath from either the SSL_CERT_DIR env var - # or the path configured when OpenSSL was compiled, - # and verifying that that path exists - # In addition we'll check whether capath appears to contain certs. - defaults = ssl.get_default_verify_paths() - if defaults.cafile or (defaults.capath and _capath_contains_certs(defaults.capath)): - ctx.set_default_verify_paths() - else: - # cafile from OpenSSL doesn't exist - # and capath from OpenSSL doesn't contain certs. - # Let's search other common locations instead. - for cafile in _CA_FILE_CANDIDATES: - if os.path.isfile(cafile): - ctx.load_verify_locations(cafile=cafile) - break - - yield - - -def _capath_contains_certs(capath: str) -> bool: - """Check whether capath exists and contains certs in the expected format.""" - if not os.path.isdir(capath): - return False - for name in os.listdir(capath): - if _HASHED_CERT_FILENAME_RE.match(name): - return True - return False - - -def _verify_peercerts_impl( - ssl_context: ssl.SSLContext, - cert_chain: list[bytes], - server_hostname: str | None = None, -) -> None: - # This is a no-op because we've enabled SSLContext's built-in - # verification via verify_mode=CERT_REQUIRED, and don't need to repeat it. - pass diff --git a/venv1/Lib/site-packages/pip/_vendor/truststore/_ssl_constants.py b/venv1/Lib/site-packages/pip/_vendor/truststore/_ssl_constants.py deleted file mode 100644 index b1ee7a3c..00000000 --- a/venv1/Lib/site-packages/pip/_vendor/truststore/_ssl_constants.py +++ /dev/null @@ -1,31 +0,0 @@ -import ssl -import sys -import typing - -# Hold on to the original class so we can create it consistently -# even if we inject our own SSLContext into the ssl module. -_original_SSLContext = ssl.SSLContext -_original_super_SSLContext = super(_original_SSLContext, _original_SSLContext) - -# CPython is known to be good, but non-CPython implementations -# may implement SSLContext differently so to be safe we don't -# subclass the SSLContext. - -# This is returned by truststore.SSLContext.__class__() -_truststore_SSLContext_dunder_class: typing.Optional[type] - -# This value is the superclass of truststore.SSLContext. -_truststore_SSLContext_super_class: type - -if sys.implementation.name == "cpython": - _truststore_SSLContext_super_class = _original_SSLContext - _truststore_SSLContext_dunder_class = None -else: - _truststore_SSLContext_super_class = object - _truststore_SSLContext_dunder_class = _original_SSLContext - - -def _set_ssl_context_verify_mode( - ssl_context: ssl.SSLContext, verify_mode: ssl.VerifyMode -) -> None: - _original_super_SSLContext.verify_mode.__set__(ssl_context, verify_mode) # type: ignore[attr-defined] diff --git a/venv1/Lib/site-packages/pip/_vendor/truststore/_windows.py b/venv1/Lib/site-packages/pip/_vendor/truststore/_windows.py deleted file mode 100644 index a9bf9abd..00000000 --- a/venv1/Lib/site-packages/pip/_vendor/truststore/_windows.py +++ /dev/null @@ -1,567 +0,0 @@ -import contextlib -import ssl -import typing -from ctypes import WinDLL # type: ignore -from ctypes import WinError # type: ignore -from ctypes import ( - POINTER, - Structure, - c_char_p, - c_ulong, - c_void_p, - c_wchar_p, - cast, - create_unicode_buffer, - pointer, - sizeof, -) -from ctypes.wintypes import ( - BOOL, - DWORD, - HANDLE, - LONG, - LPCSTR, - LPCVOID, - LPCWSTR, - LPFILETIME, - LPSTR, - LPWSTR, -) -from typing import TYPE_CHECKING, Any - -from ._ssl_constants import _set_ssl_context_verify_mode - -HCERTCHAINENGINE = HANDLE -HCERTSTORE = HANDLE -HCRYPTPROV_LEGACY = HANDLE - - -class CERT_CONTEXT(Structure): - _fields_ = ( - ("dwCertEncodingType", DWORD), - ("pbCertEncoded", c_void_p), - ("cbCertEncoded", DWORD), - ("pCertInfo", c_void_p), - ("hCertStore", HCERTSTORE), - ) - - -PCERT_CONTEXT = POINTER(CERT_CONTEXT) -PCCERT_CONTEXT = POINTER(PCERT_CONTEXT) - - -class CERT_ENHKEY_USAGE(Structure): - _fields_ = ( - ("cUsageIdentifier", DWORD), - ("rgpszUsageIdentifier", POINTER(LPSTR)), - ) - - -PCERT_ENHKEY_USAGE = POINTER(CERT_ENHKEY_USAGE) - - -class CERT_USAGE_MATCH(Structure): - _fields_ = ( - ("dwType", DWORD), - ("Usage", CERT_ENHKEY_USAGE), - ) - - -class CERT_CHAIN_PARA(Structure): - _fields_ = ( - ("cbSize", DWORD), - ("RequestedUsage", CERT_USAGE_MATCH), - ("RequestedIssuancePolicy", CERT_USAGE_MATCH), - ("dwUrlRetrievalTimeout", DWORD), - ("fCheckRevocationFreshnessTime", BOOL), - ("dwRevocationFreshnessTime", DWORD), - ("pftCacheResync", LPFILETIME), - ("pStrongSignPara", c_void_p), - ("dwStrongSignFlags", DWORD), - ) - - -if TYPE_CHECKING: - PCERT_CHAIN_PARA = pointer[CERT_CHAIN_PARA] # type: ignore[misc] -else: - PCERT_CHAIN_PARA = POINTER(CERT_CHAIN_PARA) - - -class CERT_TRUST_STATUS(Structure): - _fields_ = ( - ("dwErrorStatus", DWORD), - ("dwInfoStatus", DWORD), - ) - - -class CERT_CHAIN_ELEMENT(Structure): - _fields_ = ( - ("cbSize", DWORD), - ("pCertContext", PCERT_CONTEXT), - ("TrustStatus", CERT_TRUST_STATUS), - ("pRevocationInfo", c_void_p), - ("pIssuanceUsage", PCERT_ENHKEY_USAGE), - ("pApplicationUsage", PCERT_ENHKEY_USAGE), - ("pwszExtendedErrorInfo", LPCWSTR), - ) - - -PCERT_CHAIN_ELEMENT = POINTER(CERT_CHAIN_ELEMENT) - - -class CERT_SIMPLE_CHAIN(Structure): - _fields_ = ( - ("cbSize", DWORD), - ("TrustStatus", CERT_TRUST_STATUS), - ("cElement", DWORD), - ("rgpElement", POINTER(PCERT_CHAIN_ELEMENT)), - ("pTrustListInfo", c_void_p), - ("fHasRevocationFreshnessTime", BOOL), - ("dwRevocationFreshnessTime", DWORD), - ) - - -PCERT_SIMPLE_CHAIN = POINTER(CERT_SIMPLE_CHAIN) - - -class CERT_CHAIN_CONTEXT(Structure): - _fields_ = ( - ("cbSize", DWORD), - ("TrustStatus", CERT_TRUST_STATUS), - ("cChain", DWORD), - ("rgpChain", POINTER(PCERT_SIMPLE_CHAIN)), - ("cLowerQualityChainContext", DWORD), - ("rgpLowerQualityChainContext", c_void_p), - ("fHasRevocationFreshnessTime", BOOL), - ("dwRevocationFreshnessTime", DWORD), - ) - - -PCERT_CHAIN_CONTEXT = POINTER(CERT_CHAIN_CONTEXT) -PCCERT_CHAIN_CONTEXT = POINTER(PCERT_CHAIN_CONTEXT) - - -class SSL_EXTRA_CERT_CHAIN_POLICY_PARA(Structure): - _fields_ = ( - ("cbSize", DWORD), - ("dwAuthType", DWORD), - ("fdwChecks", DWORD), - ("pwszServerName", LPCWSTR), - ) - - -class CERT_CHAIN_POLICY_PARA(Structure): - _fields_ = ( - ("cbSize", DWORD), - ("dwFlags", DWORD), - ("pvExtraPolicyPara", c_void_p), - ) - - -PCERT_CHAIN_POLICY_PARA = POINTER(CERT_CHAIN_POLICY_PARA) - - -class CERT_CHAIN_POLICY_STATUS(Structure): - _fields_ = ( - ("cbSize", DWORD), - ("dwError", DWORD), - ("lChainIndex", LONG), - ("lElementIndex", LONG), - ("pvExtraPolicyStatus", c_void_p), - ) - - -PCERT_CHAIN_POLICY_STATUS = POINTER(CERT_CHAIN_POLICY_STATUS) - - -class CERT_CHAIN_ENGINE_CONFIG(Structure): - _fields_ = ( - ("cbSize", DWORD), - ("hRestrictedRoot", HCERTSTORE), - ("hRestrictedTrust", HCERTSTORE), - ("hRestrictedOther", HCERTSTORE), - ("cAdditionalStore", DWORD), - ("rghAdditionalStore", c_void_p), - ("dwFlags", DWORD), - ("dwUrlRetrievalTimeout", DWORD), - ("MaximumCachedCertificates", DWORD), - ("CycleDetectionModulus", DWORD), - ("hExclusiveRoot", HCERTSTORE), - ("hExclusiveTrustedPeople", HCERTSTORE), - ("dwExclusiveFlags", DWORD), - ) - - -PCERT_CHAIN_ENGINE_CONFIG = POINTER(CERT_CHAIN_ENGINE_CONFIG) -PHCERTCHAINENGINE = POINTER(HCERTCHAINENGINE) - -X509_ASN_ENCODING = 0x00000001 -PKCS_7_ASN_ENCODING = 0x00010000 -CERT_STORE_PROV_MEMORY = b"Memory" -CERT_STORE_ADD_USE_EXISTING = 2 -USAGE_MATCH_TYPE_OR = 1 -OID_PKIX_KP_SERVER_AUTH = c_char_p(b"1.3.6.1.5.5.7.3.1") -CERT_CHAIN_REVOCATION_CHECK_END_CERT = 0x10000000 -CERT_CHAIN_REVOCATION_CHECK_CHAIN = 0x20000000 -CERT_CHAIN_POLICY_IGNORE_ALL_NOT_TIME_VALID_FLAGS = 0x00000007 -CERT_CHAIN_POLICY_IGNORE_INVALID_BASIC_CONSTRAINTS_FLAG = 0x00000008 -CERT_CHAIN_POLICY_ALLOW_UNKNOWN_CA_FLAG = 0x00000010 -CERT_CHAIN_POLICY_IGNORE_INVALID_NAME_FLAG = 0x00000040 -CERT_CHAIN_POLICY_IGNORE_WRONG_USAGE_FLAG = 0x00000020 -CERT_CHAIN_POLICY_IGNORE_INVALID_POLICY_FLAG = 0x00000080 -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 -FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200 - -# Flags to set for SSLContext.verify_mode=CERT_NONE -CERT_CHAIN_POLICY_VERIFY_MODE_NONE_FLAGS = ( - CERT_CHAIN_POLICY_IGNORE_ALL_NOT_TIME_VALID_FLAGS - | CERT_CHAIN_POLICY_IGNORE_INVALID_BASIC_CONSTRAINTS_FLAG - | CERT_CHAIN_POLICY_ALLOW_UNKNOWN_CA_FLAG - | CERT_CHAIN_POLICY_IGNORE_INVALID_NAME_FLAG - | CERT_CHAIN_POLICY_IGNORE_WRONG_USAGE_FLAG - | CERT_CHAIN_POLICY_IGNORE_INVALID_POLICY_FLAG - | CERT_CHAIN_POLICY_IGNORE_ALL_REV_UNKNOWN_FLAGS - | CERT_CHAIN_POLICY_ALLOW_TESTROOT_FLAG - | CERT_CHAIN_POLICY_TRUST_TESTROOT_FLAG -) - -wincrypt = WinDLL("crypt32.dll") -kernel32 = WinDLL("kernel32.dll") - - -def _handle_win_error(result: bool, _: Any, args: Any) -> Any: - if not result: - # Note, actually raises OSError after calling GetLastError and FormatMessage - raise WinError() - return args - - -CertCreateCertificateChainEngine = wincrypt.CertCreateCertificateChainEngine -CertCreateCertificateChainEngine.argtypes = ( - PCERT_CHAIN_ENGINE_CONFIG, - PHCERTCHAINENGINE, -) -CertCreateCertificateChainEngine.errcheck = _handle_win_error - -CertOpenStore = wincrypt.CertOpenStore -CertOpenStore.argtypes = (LPCSTR, DWORD, HCRYPTPROV_LEGACY, DWORD, c_void_p) -CertOpenStore.restype = HCERTSTORE -CertOpenStore.errcheck = _handle_win_error - -CertAddEncodedCertificateToStore = wincrypt.CertAddEncodedCertificateToStore -CertAddEncodedCertificateToStore.argtypes = ( - HCERTSTORE, - DWORD, - c_char_p, - DWORD, - DWORD, - PCCERT_CONTEXT, -) -CertAddEncodedCertificateToStore.restype = BOOL - -CertCreateCertificateContext = wincrypt.CertCreateCertificateContext -CertCreateCertificateContext.argtypes = (DWORD, c_char_p, DWORD) -CertCreateCertificateContext.restype = PCERT_CONTEXT -CertCreateCertificateContext.errcheck = _handle_win_error - -CertGetCertificateChain = wincrypt.CertGetCertificateChain -CertGetCertificateChain.argtypes = ( - HCERTCHAINENGINE, - PCERT_CONTEXT, - LPFILETIME, - HCERTSTORE, - PCERT_CHAIN_PARA, - DWORD, - c_void_p, - PCCERT_CHAIN_CONTEXT, -) -CertGetCertificateChain.restype = BOOL -CertGetCertificateChain.errcheck = _handle_win_error - -CertVerifyCertificateChainPolicy = wincrypt.CertVerifyCertificateChainPolicy -CertVerifyCertificateChainPolicy.argtypes = ( - c_ulong, - PCERT_CHAIN_CONTEXT, - PCERT_CHAIN_POLICY_PARA, - PCERT_CHAIN_POLICY_STATUS, -) -CertVerifyCertificateChainPolicy.restype = BOOL - -CertCloseStore = wincrypt.CertCloseStore -CertCloseStore.argtypes = (HCERTSTORE, DWORD) -CertCloseStore.restype = BOOL -CertCloseStore.errcheck = _handle_win_error - -CertFreeCertificateChain = wincrypt.CertFreeCertificateChain -CertFreeCertificateChain.argtypes = (PCERT_CHAIN_CONTEXT,) - -CertFreeCertificateContext = wincrypt.CertFreeCertificateContext -CertFreeCertificateContext.argtypes = (PCERT_CONTEXT,) - -CertFreeCertificateChainEngine = wincrypt.CertFreeCertificateChainEngine -CertFreeCertificateChainEngine.argtypes = (HCERTCHAINENGINE,) - -FormatMessageW = kernel32.FormatMessageW -FormatMessageW.argtypes = ( - DWORD, - LPCVOID, - DWORD, - DWORD, - LPWSTR, - DWORD, - c_void_p, -) -FormatMessageW.restype = DWORD - - -def _verify_peercerts_impl( - ssl_context: ssl.SSLContext, - cert_chain: list[bytes], - server_hostname: str | None = None, -) -> None: - """Verify the cert_chain from the server using Windows APIs.""" - - # If the peer didn't send any certificates then - # we can't do verification. Raise an error. - if not cert_chain: - raise ssl.SSLCertVerificationError("Peer sent no certificates to verify") - - pCertContext = None - hIntermediateCertStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, None, 0, None) - try: - # Add intermediate certs to an in-memory cert store - for cert_bytes in cert_chain[1:]: - CertAddEncodedCertificateToStore( - hIntermediateCertStore, - X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, - cert_bytes, - len(cert_bytes), - CERT_STORE_ADD_USE_EXISTING, - None, - ) - - # Cert context for leaf cert - leaf_cert = cert_chain[0] - pCertContext = CertCreateCertificateContext( - X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, leaf_cert, len(leaf_cert) - ) - - # Chain params to match certs for serverAuth extended usage - cert_enhkey_usage = CERT_ENHKEY_USAGE() - cert_enhkey_usage.cUsageIdentifier = 1 - cert_enhkey_usage.rgpszUsageIdentifier = (c_char_p * 1)(OID_PKIX_KP_SERVER_AUTH) - cert_usage_match = CERT_USAGE_MATCH() - cert_usage_match.Usage = cert_enhkey_usage - chain_params = CERT_CHAIN_PARA() - chain_params.RequestedUsage = cert_usage_match - chain_params.cbSize = sizeof(chain_params) - pChainPara = pointer(chain_params) - - if ssl_context.verify_flags & ssl.VERIFY_CRL_CHECK_CHAIN: - chain_flags = CERT_CHAIN_REVOCATION_CHECK_CHAIN - elif ssl_context.verify_flags & ssl.VERIFY_CRL_CHECK_LEAF: - chain_flags = CERT_CHAIN_REVOCATION_CHECK_END_CERT - else: - chain_flags = 0 - - try: - # First attempt to verify using the default Windows system trust roots - # (default chain engine). - _get_and_verify_cert_chain( - ssl_context, - None, - hIntermediateCertStore, - pCertContext, - pChainPara, - server_hostname, - chain_flags=chain_flags, - ) - except ssl.SSLCertVerificationError as e: - # If that fails but custom CA certs have been added - # to the SSLContext using load_verify_locations, - # try verifying using a custom chain engine - # that trusts the custom CA certs. - custom_ca_certs: list[bytes] | None = ssl_context.get_ca_certs( - binary_form=True - ) - if custom_ca_certs: - try: - _verify_using_custom_ca_certs( - ssl_context, - custom_ca_certs, - hIntermediateCertStore, - pCertContext, - pChainPara, - server_hostname, - chain_flags=chain_flags, - ) - # Raise the original error, not the new error. - except ssl.SSLCertVerificationError: - raise e from None - else: - raise - finally: - CertCloseStore(hIntermediateCertStore, 0) - if pCertContext: - CertFreeCertificateContext(pCertContext) - - -def _get_and_verify_cert_chain( - ssl_context: ssl.SSLContext, - hChainEngine: HCERTCHAINENGINE | None, - hIntermediateCertStore: HCERTSTORE, - pPeerCertContext: c_void_p, - pChainPara: PCERT_CHAIN_PARA, # type: ignore[valid-type] - server_hostname: str | None, - chain_flags: int, -) -> None: - ppChainContext = None - try: - # Get cert chain - ppChainContext = pointer(PCERT_CHAIN_CONTEXT()) - CertGetCertificateChain( - hChainEngine, # chain engine - pPeerCertContext, # leaf cert context - None, # current system time - hIntermediateCertStore, # additional in-memory cert store - pChainPara, # chain-building parameters - chain_flags, - None, # reserved - ppChainContext, # the resulting chain context - ) - pChainContext = ppChainContext.contents - - # Verify cert chain - ssl_extra_cert_chain_policy_para = SSL_EXTRA_CERT_CHAIN_POLICY_PARA() - ssl_extra_cert_chain_policy_para.cbSize = sizeof( - ssl_extra_cert_chain_policy_para - ) - 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) - - chain_policy = CERT_CHAIN_POLICY_PARA() - chain_policy.pvExtraPolicyPara = cast( - pointer(ssl_extra_cert_chain_policy_para), c_void_p - ) - if ssl_context.verify_mode == ssl.CERT_NONE: - chain_policy.dwFlags |= CERT_CHAIN_POLICY_VERIFY_MODE_NONE_FLAGS - chain_policy.cbSize = sizeof(chain_policy) - - pPolicyPara = pointer(chain_policy) - policy_status = CERT_CHAIN_POLICY_STATUS() - policy_status.cbSize = sizeof(policy_status) - pPolicyStatus = pointer(policy_status) - CertVerifyCertificateChainPolicy( - CERT_CHAIN_POLICY_SSL, - pChainContext, - pPolicyPara, - pPolicyStatus, - ) - - # Check status - error_code = policy_status.dwError - if error_code: - # Try getting a human readable message for an error code. - error_message_buf = create_unicode_buffer(1024) - error_message_chars = FormatMessageW( - FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - None, - error_code, - 0, - error_message_buf, - sizeof(error_message_buf), - None, - ) - - # See if we received a message for the error, - # otherwise we use a generic error with the - # error code and hope that it's search-able. - if error_message_chars <= 0: - error_message = f"Certificate chain policy error {error_code:#x} [{policy_status.lElementIndex}]" - else: - error_message = error_message_buf.value.strip() - - err = ssl.SSLCertVerificationError(error_message) - err.verify_message = error_message - err.verify_code = error_code - raise err from None - finally: - if ppChainContext: - CertFreeCertificateChain(ppChainContext.contents) - - -def _verify_using_custom_ca_certs( - ssl_context: ssl.SSLContext, - custom_ca_certs: list[bytes], - hIntermediateCertStore: HCERTSTORE, - pPeerCertContext: c_void_p, - pChainPara: PCERT_CHAIN_PARA, # type: ignore[valid-type] - server_hostname: str | None, - chain_flags: int, -) -> None: - hChainEngine = None - hRootCertStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, None, 0, None) - try: - # Add custom CA certs to an in-memory cert store - for cert_bytes in custom_ca_certs: - CertAddEncodedCertificateToStore( - hRootCertStore, - X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, - cert_bytes, - len(cert_bytes), - CERT_STORE_ADD_USE_EXISTING, - None, - ) - - # Create a custom cert chain engine which exclusively trusts - # certs from our hRootCertStore - cert_chain_engine_config = CERT_CHAIN_ENGINE_CONFIG() - cert_chain_engine_config.cbSize = sizeof(cert_chain_engine_config) - cert_chain_engine_config.hExclusiveRoot = hRootCertStore - pConfig = pointer(cert_chain_engine_config) - phChainEngine = pointer(HCERTCHAINENGINE()) - CertCreateCertificateChainEngine( - pConfig, - phChainEngine, - ) - hChainEngine = phChainEngine.contents - - # Get and verify a cert chain using the custom chain engine - _get_and_verify_cert_chain( - ssl_context, - hChainEngine, - hIntermediateCertStore, - pPeerCertContext, - pChainPara, - server_hostname, - chain_flags, - ) - finally: - if hChainEngine: - CertFreeCertificateChainEngine(hChainEngine) - CertCloseStore(hRootCertStore, 0) - - -@contextlib.contextmanager -def _configure_context(ctx: ssl.SSLContext) -> typing.Iterator[None]: - check_hostname = ctx.check_hostname - verify_mode = ctx.verify_mode - ctx.check_hostname = False - _set_ssl_context_verify_mode(ctx, ssl.CERT_NONE) - try: - yield - finally: - ctx.check_hostname = check_hostname - _set_ssl_context_verify_mode(ctx, verify_mode) diff --git a/venv1/Lib/site-packages/pip/_vendor/truststore/py.typed b/venv1/Lib/site-packages/pip/_vendor/truststore/py.typed deleted file mode 100644 index e69de29b..00000000 diff --git a/venv1/Lib/site-packages/pip/_vendor/urllib3/_collections.py b/venv1/Lib/site-packages/pip/_vendor/urllib3/_collections.py index bceb8451..da9857e9 100644 --- a/venv1/Lib/site-packages/pip/_vendor/urllib3/_collections.py +++ b/venv1/Lib/site-packages/pip/_vendor/urllib3/_collections.py @@ -268,24 +268,6 @@ def getlist(self, key, default=__marker): else: return vals[1:] - def _prepare_for_method_change(self): - """ - Remove content-specific header fields before changing the request - method to GET or HEAD according to RFC 9110, Section 15.4. - """ - content_specific_headers = [ - "Content-Encoding", - "Content-Language", - "Content-Location", - "Content-Type", - "Content-Length", - "Digest", - "Last-Modified", - ] - for header in content_specific_headers: - self.discard(header) - return self - # Backwards compatibility for httplib getheaders = getlist getallmatchingheaders = getlist diff --git a/venv1/Lib/site-packages/pip/_vendor/urllib3/_version.py b/venv1/Lib/site-packages/pip/_vendor/urllib3/_version.py index d49df2a0..e12dd0e7 100644 --- a/venv1/Lib/site-packages/pip/_vendor/urllib3/_version.py +++ b/venv1/Lib/site-packages/pip/_vendor/urllib3/_version.py @@ -1,2 +1,2 @@ # This file is protected via CODEOWNERS -__version__ = "1.26.20" +__version__ = "1.26.15" diff --git a/venv1/Lib/site-packages/pip/_vendor/urllib3/connection.py b/venv1/Lib/site-packages/pip/_vendor/urllib3/connection.py index de35b63d..54b96b19 100644 --- a/venv1/Lib/site-packages/pip/_vendor/urllib3/connection.py +++ b/venv1/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(2024, 1, 1) +RECENT_DATE = datetime.date(2022, 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/venv1/Lib/site-packages/pip/_vendor/urllib3/connectionpool.py b/venv1/Lib/site-packages/pip/_vendor/urllib3/connectionpool.py index 0872ed77..c23d736b 100644 --- a/venv1/Lib/site-packages/pip/_vendor/urllib3/connectionpool.py +++ b/venv1/Lib/site-packages/pip/_vendor/urllib3/connectionpool.py @@ -9,7 +9,6 @@ from socket import error as SocketError from socket import timeout as SocketTimeout -from ._collections import HTTPHeaderDict from .connection import ( BaseSSLError, BrokenPipeError, @@ -51,13 +50,6 @@ from .util.url import _normalize_host as normalize_host from .util.url import get_host, parse_url -try: # Platform-specific: Python 3 - import weakref - - weakref_finalize = weakref.finalize -except AttributeError: # Platform-specific: Python 2 - from .packages.backports.weakref_finalize import weakref_finalize - xrange = six.moves.xrange log = logging.getLogger(__name__) @@ -228,16 +220,6 @@ def __init__( self.conn_kw["proxy"] = self.proxy self.conn_kw["proxy_config"] = self.proxy_config - # Do not pass 'self' as callback to 'finalize'. - # Then the 'finalize' would keep an endless living (leak) to self. - # By just passing a reference to the pool allows the garbage collector - # to free self if nobody else has a reference to it. - pool = self.pool - - # Close all the HTTPConnections in the pool before the - # HTTPConnectionPool object is garbage collected. - weakref_finalize(self, _close_pool_connections, pool) - def _new_conn(self): """ Return a fresh :class:`HTTPConnection`. @@ -423,13 +405,12 @@ def _make_request( pass except IOError as e: # Python 2 and macOS/Linux - # EPIPE and ESHUTDOWN are BrokenPipeError on Python 2, and EPROTOTYPE/ECONNRESET are needed on macOS + # EPIPE and ESHUTDOWN are BrokenPipeError on Python 2, and EPROTOTYPE is 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 @@ -508,8 +489,14 @@ def close(self): # Disable access to the pool old_pool, self.pool = self.pool, None - # Close all the HTTPConnections in the pool. - _close_pool_connections(old_pool) + try: + while True: + conn = old_pool.get(block=False) + if conn: + conn.close() + + except queue.Empty: + pass # Done. def is_same_host(self, url): """ @@ -769,9 +756,7 @@ 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 - or "record layer failure" in message + "wrong version number" in message or "unknown protocol" in message ) # Try to detect a common user error with proxies which is to @@ -847,11 +832,7 @@ def _is_ssl_error_message_from_http_proxy(ssl_error): redirect_location = redirect and response.get_redirect_location() if redirect_location: if response.status == 303: - # Change the method according to RFC 9110, Section 15.4.4. method = "GET" - # And lose the body not to transfer anything sensitive. - body = None - headers = HTTPHeaderDict(headers)._prepare_for_method_change() try: retries = retries.increment(method, url, response=response, _pool=self) @@ -1127,14 +1108,3 @@ def _normalize_host(host, scheme): if host.startswith("[") and host.endswith("]"): host = host[1:-1] return host - - -def _close_pool_connections(pool): - """Drains a queue of connections and closes each one.""" - try: - while True: - conn = pool.get(block=False) - if conn: - conn.close() - except queue.Empty: - pass # Done. diff --git a/venv1/Lib/site-packages/pip/_vendor/urllib3/contrib/securetransport.py b/venv1/Lib/site-packages/pip/_vendor/urllib3/contrib/securetransport.py index 722ee4e1..4a06bc69 100644 --- a/venv1/Lib/site-packages/pip/_vendor/urllib3/contrib/securetransport.py +++ b/venv1/Lib/site-packages/pip/_vendor/urllib3/contrib/securetransport.py @@ -64,8 +64,9 @@ import threading import weakref +from pip._vendor import six + from .. import util -from ..packages import six from ..util.ssl_ import PROTOCOL_TLS_CLIENT from ._securetransport.bindings import CoreFoundation, Security, SecurityConst from ._securetransport.low_level import ( diff --git a/venv1/Lib/site-packages/pip/_vendor/urllib3/packages/backports/weakref_finalize.py b/venv1/Lib/site-packages/pip/_vendor/urllib3/packages/backports/weakref_finalize.py deleted file mode 100644 index a2f2966e..00000000 --- a/venv1/Lib/site-packages/pip/_vendor/urllib3/packages/backports/weakref_finalize.py +++ /dev/null @@ -1,155 +0,0 @@ -# -*- coding: utf-8 -*- -""" -backports.weakref_finalize -~~~~~~~~~~~~~~~~~~ - -Backports the Python 3 ``weakref.finalize`` method. -""" -from __future__ import absolute_import - -import itertools -import sys -from weakref import ref - -__all__ = ["weakref_finalize"] - - -class weakref_finalize(object): - """Class for finalization of weakrefable objects - finalize(obj, func, *args, **kwargs) returns a callable finalizer - object which will be called when obj is garbage collected. The - first time the finalizer is called it evaluates func(*arg, **kwargs) - and returns the result. After this the finalizer is dead, and - calling it just returns None. - When the program exits any remaining finalizers for which the - atexit attribute is true will be run in reverse order of creation. - By default atexit is true. - """ - - # Finalizer objects don't have any state of their own. They are - # just used as keys to lookup _Info objects in the registry. This - # ensures that they cannot be part of a ref-cycle. - - __slots__ = () - _registry = {} - _shutdown = False - _index_iter = itertools.count() - _dirty = False - _registered_with_atexit = False - - class _Info(object): - __slots__ = ("weakref", "func", "args", "kwargs", "atexit", "index") - - def __init__(self, obj, func, *args, **kwargs): - if not self._registered_with_atexit: - # We may register the exit function more than once because - # of a thread race, but that is harmless - import atexit - - atexit.register(self._exitfunc) - weakref_finalize._registered_with_atexit = True - info = self._Info() - info.weakref = ref(obj, self) - info.func = func - info.args = args - info.kwargs = kwargs or None - info.atexit = True - info.index = next(self._index_iter) - self._registry[self] = info - weakref_finalize._dirty = True - - def __call__(self, _=None): - """If alive then mark as dead and return func(*args, **kwargs); - otherwise return None""" - info = self._registry.pop(self, None) - if info and not self._shutdown: - return info.func(*info.args, **(info.kwargs or {})) - - def detach(self): - """If alive then mark as dead and return (obj, func, args, kwargs); - otherwise return None""" - info = self._registry.get(self) - obj = info and info.weakref() - if obj is not None and self._registry.pop(self, None): - return (obj, info.func, info.args, info.kwargs or {}) - - def peek(self): - """If alive then return (obj, func, args, kwargs); - otherwise return None""" - info = self._registry.get(self) - obj = info and info.weakref() - if obj is not None: - return (obj, info.func, info.args, info.kwargs or {}) - - @property - def alive(self): - """Whether finalizer is alive""" - return self in self._registry - - @property - def atexit(self): - """Whether finalizer should be called at exit""" - info = self._registry.get(self) - return bool(info) and info.atexit - - @atexit.setter - def atexit(self, value): - info = self._registry.get(self) - if info: - info.atexit = bool(value) - - def __repr__(self): - info = self._registry.get(self) - obj = info and info.weakref() - if obj is None: - return "<%s object at %#x; dead>" % (type(self).__name__, id(self)) - else: - return "<%s object at %#x; for %r at %#x>" % ( - type(self).__name__, - id(self), - type(obj).__name__, - id(obj), - ) - - @classmethod - def _select_for_exit(cls): - # Return live finalizers marked for exit, oldest first - L = [(f, i) for (f, i) in cls._registry.items() if i.atexit] - L.sort(key=lambda item: item[1].index) - return [f for (f, i) in L] - - @classmethod - def _exitfunc(cls): - # At shutdown invoke finalizers for which atexit is true. - # This is called once all other non-daemonic threads have been - # joined. - reenable_gc = False - try: - if cls._registry: - import gc - - if gc.isenabled(): - reenable_gc = True - gc.disable() - pending = None - while True: - if pending is None or weakref_finalize._dirty: - pending = cls._select_for_exit() - weakref_finalize._dirty = False - if not pending: - break - f = pending.pop() - try: - # gc is disabled, so (assuming no daemonic - # threads) the following is the only line in - # this function which might trigger creation - # of a new finalizer - f() - except Exception: - sys.excepthook(*sys.exc_info()) - assert f not in cls._registry - finally: - # prevent any more finalizers from executing during shutdown - weakref_finalize._shutdown = True - if reenable_gc: - gc.enable() diff --git a/venv1/Lib/site-packages/pip/_vendor/urllib3/poolmanager.py b/venv1/Lib/site-packages/pip/_vendor/urllib3/poolmanager.py index fb51bf7d..ca4ec341 100644 --- a/venv1/Lib/site-packages/pip/_vendor/urllib3/poolmanager.py +++ b/venv1/Lib/site-packages/pip/_vendor/urllib3/poolmanager.py @@ -4,7 +4,7 @@ import functools import logging -from ._collections import HTTPHeaderDict, RecentlyUsedContainer +from ._collections import RecentlyUsedContainer from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool, port_by_scheme from .exceptions import ( LocationValueError, @@ -171,7 +171,7 @@ class PoolManager(RequestMethods): def __init__(self, num_pools=10, headers=None, **connection_pool_kw): RequestMethods.__init__(self, headers) self.connection_pool_kw = connection_pool_kw - self.pools = RecentlyUsedContainer(num_pools) + self.pools = RecentlyUsedContainer(num_pools, dispose_func=lambda p: p.close()) # Locally set the pool classes and keys so other PoolManagers can # override them. @@ -382,12 +382,9 @@ def urlopen(self, method, url, redirect=True, **kw): # Support relative URLs for redirecting. redirect_location = urljoin(url, redirect_location) + # RFC 7231, Section 6.4.4 if response.status == 303: - # Change the method according to RFC 9110, Section 15.4.4. method = "GET" - # And lose the body not to transfer anything sensitive. - kw["body"] = None - kw["headers"] = HTTPHeaderDict(kw["headers"])._prepare_for_method_change() retries = kw.get("retries") if not isinstance(retries, Retry): diff --git a/venv1/Lib/site-packages/pip/_vendor/urllib3/request.py b/venv1/Lib/site-packages/pip/_vendor/urllib3/request.py index 3b4cf999..398386a5 100644 --- a/venv1/Lib/site-packages/pip/_vendor/urllib3/request.py +++ b/venv1/Lib/site-packages/pip/_vendor/urllib3/request.py @@ -1,9 +1,6 @@ from __future__ import absolute_import -import sys - from .filepost import encode_multipart_formdata -from .packages import six from .packages.six.moves.urllib.parse import urlencode __all__ = ["RequestMethods"] @@ -171,21 +168,3 @@ def request_encode_body( extra_kw.update(urlopen_kw) return self.urlopen(method, url, **extra_kw) - - -if not six.PY2: - - class RequestModule(sys.modules[__name__].__class__): - def __call__(self, *args, **kwargs): - """ - If user tries to call this module directly urllib3 v2.x style raise an error to the user - suggesting they may need urllib3 v2 - """ - raise TypeError( - "'module' object is not callable\n" - "urllib3.request() method is not supported in this release, " - "upgrade to urllib3 v2 to use it\n" - "see https://urllib3.readthedocs.io/en/stable/v2-migration-guide.html" - ) - - sys.modules[__name__].__class__ = RequestModule diff --git a/venv1/Lib/site-packages/pip/_vendor/urllib3/util/retry.py b/venv1/Lib/site-packages/pip/_vendor/urllib3/util/retry.py index 9a1e90d0..2490d5e5 100644 --- a/venv1/Lib/site-packages/pip/_vendor/urllib3/util/retry.py +++ b/venv1/Lib/site-packages/pip/_vendor/urllib3/util/retry.py @@ -235,9 +235,7 @@ 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", "Proxy-Authorization"] - ) + DEFAULT_REMOVE_HEADERS_ON_REDIRECT = frozenset(["Authorization"]) #: Maximum backoff time. DEFAULT_BACKOFF_MAX = 120 diff --git a/venv1/Lib/site-packages/pip/_vendor/urllib3/util/ssl_.py b/venv1/Lib/site-packages/pip/_vendor/urllib3/util/ssl_.py index 0a6a0e06..2b45d391 100644 --- a/venv1/Lib/site-packages/pip/_vendor/urllib3/util/ssl_.py +++ b/venv1/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,10 +24,7 @@ ALPN_PROTOCOLS = ["http/1.1"] # Maps the length of a digest to a possible hash function producing this digest -HASHFUNC_MAP = { - length: getattr(hashlib, algorithm, None) - for length, algorithm in ((32, "md5"), (40, "sha1"), (64, "sha256")) -} +HASHFUNC_MAP = {32: md5, 40: sha1, 64: sha256} def _const_compare_digest_backport(a, b): @@ -194,15 +191,9 @@ def assert_fingerprint(cert, fingerprint): fingerprint = fingerprint.replace(":", "").lower() digest_length = len(fingerprint) - 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 - ) - ) + if not hashfunc: + raise SSLError("Fingerprint of invalid length: {0}".format(fingerprint)) # We need encode() here for py32; works on py2 and p33. fingerprint_bytes = unhexlify(fingerprint.encode()) diff --git a/venv1/Lib/site-packages/pip/_vendor/vendor.txt b/venv1/Lib/site-packages/pip/_vendor/vendor.txt index 0cdfda56..61063459 100644 --- a/venv1/Lib/site-packages/pip/_vendor/vendor.txt +++ b/venv1/Lib/site-packages/pip/_vendor/vendor.txt @@ -1,19 +1,23 @@ -CacheControl==0.14.3 -distlib==0.4.0 -distro==1.9.0 -msgpack==1.1.2 -packaging==25.0 -platformdirs==4.5.0 -pyproject-hooks==1.2.0 -requests==2.32.5 - certifi==2025.10.5 - idna==3.10 - urllib3==1.26.20 -rich==14.2.0 - pygments==2.19.2 -resolvelib==1.2.1 -setuptools==70.3.0 -tomli==2.3.0 -tomli-w==1.2.0 -truststore==0.10.4 -dependency-groups==1.3.1 +CacheControl==0.12.11 # Make sure to update the license in pyproject.toml for this. +colorama==0.4.6 +distlib==0.3.6 +distro==1.8.0 +msgpack==1.0.5 +packaging==21.3 +platformdirs==3.2.0 +pyparsing==3.0.9 +pyproject-hooks==1.0.0 +requests==2.28.2 + certifi==2022.12.7 + chardet==5.1.0 + idna==3.4 + urllib3==1.26.15 +rich==13.3.3 + pygments==2.14.0 + typing_extensions==4.5.0 +resolvelib==1.0.1 +setuptools==67.7.2 +six==1.16.0 +tenacity==8.2.2 +tomli==2.0.1 +webencodings==0.5.1 diff --git a/venv1/Scripts/Activate.ps1 b/venv1/Scripts/Activate.ps1 index b8e61edb..d746a8e6 100644 --- a/venv1/Scripts/Activate.ps1 +++ b/venv1/Scripts/Activate.ps1 @@ -219,8 +219,6 @@ deactivate -nondestructive # that there is an activated venv. $env:VIRTUAL_ENV = $VenvDir -$env:VIRTUAL_ENV_PROMPT = $Prompt - if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) { Write-Verbose "Setting prompt to '$Prompt'" @@ -235,6 +233,7 @@ if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) { Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) " _OLD_VIRTUAL_PROMPT } + $env:VIRTUAL_ENV_PROMPT = $Prompt } # Clear PYTHONHOME @@ -248,300 +247,256 @@ Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH $Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH" # SIG # Begin signature block -# MII3ZgYJKoZIhvcNAQcCoII3VzCCN1MCAQExDzANBglghkgBZQMEAgEFADB5Bgor +# MIIvIgYJKoZIhvcNAQcCoIIvEzCCLw8CAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG -# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBALKwKRFIhr2RY -# IW/WJLd9pc8a9sj/IoThKU92fTfKsKCCG9IwggXMMIIDtKADAgECAhBUmNLR1FsZ -# lUgTecgRwIeZMA0GCSqGSIb3DQEBDAUAMHcxCzAJBgNVBAYTAlVTMR4wHAYDVQQK -# ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xSDBGBgNVBAMTP01pY3Jvc29mdCBJZGVu -# dGl0eSBWZXJpZmljYXRpb24gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAy -# MDAeFw0yMDA0MTYxODM2MTZaFw00NTA0MTYxODQ0NDBaMHcxCzAJBgNVBAYTAlVT -# MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xSDBGBgNVBAMTP01pY3Jv -# c29mdCBJZGVudGl0eSBWZXJpZmljYXRpb24gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRo -# b3JpdHkgMjAyMDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALORKgeD -# Bmf9np3gx8C3pOZCBH8Ppttf+9Va10Wg+3cL8IDzpm1aTXlT2KCGhFdFIMeiVPvH -# or+Kx24186IVxC9O40qFlkkN/76Z2BT2vCcH7kKbK/ULkgbk/WkTZaiRcvKYhOuD -# PQ7k13ESSCHLDe32R0m3m/nJxxe2hE//uKya13NnSYXjhr03QNAlhtTetcJtYmrV -# qXi8LW9J+eVsFBT9FMfTZRY33stuvF4pjf1imxUs1gXmuYkyM6Nix9fWUmcIxC70 -# ViueC4fM7Ke0pqrrBc0ZV6U6CwQnHJFnni1iLS8evtrAIMsEGcoz+4m+mOJyoHI1 -# vnnhnINv5G0Xb5DzPQCGdTiO0OBJmrvb0/gwytVXiGhNctO/bX9x2P29Da6SZEi3 -# W295JrXNm5UhhNHvDzI9e1eM80UHTHzgXhgONXaLbZ7LNnSrBfjgc10yVpRnlyUK -# xjU9lJfnwUSLgP3B+PR0GeUw9gb7IVc+BhyLaxWGJ0l7gpPKWeh1R+g/OPTHU3mg -# trTiXFHvvV84wRPmeAyVWi7FQFkozA8kwOy6CXcjmTimthzax7ogttc32H83rwjj -# O3HbbnMbfZlysOSGM1l0tRYAe1BtxoYT2v3EOYI9JACaYNq6lMAFUSw0rFCZE4e7 -# swWAsk0wAly4JoNdtGNz764jlU9gKL431VulAgMBAAGjVDBSMA4GA1UdDwEB/wQE -# AwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTIftJqhSobyhmYBAcnz1AQ -# T2ioojAQBgkrBgEEAYI3FQEEAwIBADANBgkqhkiG9w0BAQwFAAOCAgEAr2rd5hnn -# LZRDGU7L6VCVZKUDkQKL4jaAOxWiUsIWGbZqWl10QzD0m/9gdAmxIR6QFm3FJI9c -# Zohj9E/MffISTEAQiwGf2qnIrvKVG8+dBetJPnSgaFvlVixlHIJ+U9pW2UYXeZJF -# xBA2CFIpF8svpvJ+1Gkkih6PsHMNzBxKq7Kq7aeRYwFkIqgyuH4yKLNncy2RtNwx -# AQv3Rwqm8ddK7VZgxCwIo3tAsLx0J1KH1r6I3TeKiW5niB31yV2g/rarOoDXGpc8 -# FzYiQR6sTdWD5jw4vU8w6VSp07YEwzJ2YbuwGMUrGLPAgNW3lbBeUU0i/OxYqujY -# lLSlLu2S3ucYfCFX3VVj979tzR/SpncocMfiWzpbCNJbTsgAlrPhgzavhgplXHT2 -# 6ux6anSg8Evu75SjrFDyh+3XOjCDyft9V77l4/hByuVkrrOj7FjshZrM77nq81YY -# uVxzmq/FdxeDWds3GhhyVKVB0rYjdaNDmuV3fJZ5t0GNv+zcgKCf0Xd1WF81E+Al -# GmcLfc4l+gcK5GEh2NQc5QfGNpn0ltDGFf5Ozdeui53bFv0ExpK91IjmqaOqu/dk -# ODtfzAzQNb50GQOmxapMomE2gj4d8yu8l13bS3g7LfU772Aj6PXsCyM2la+YZr9T -# 03u4aUoqlmZpxJTG9F9urJh4iIAGXKKy7aIwggb+MIIE5qADAgECAhMzAAbLVm/g -# dl/pQCFWAAAABstWMA0GCSqGSIb3DQEBDAUAMFoxCzAJBgNVBAYTAlVTMR4wHAYD -# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKzApBgNVBAMTIk1pY3Jvc29mdCBJ -# RCBWZXJpZmllZCBDUyBFT0MgQ0EgMDIwHhcNMjYwMjAzMDgyODQ3WhcNMjYwMjA2 -# MDgyODQ3WjB8MQswCQYDVQQGEwJVUzEPMA0GA1UECBMGT3JlZ29uMRIwEAYDVQQH -# EwlCZWF2ZXJ0b24xIzAhBgNVBAoTGlB5dGhvbiBTb2Z0d2FyZSBGb3VuZGF0aW9u -# MSMwIQYDVQQDExpQeXRob24gU29mdHdhcmUgRm91bmRhdGlvbjCCAaIwDQYJKoZI -# hvcNAQEBBQADggGPADCCAYoCggGBAJdXWv7CWGQoqghlPAZXtWrgRvUjGOdfnOno -# 12rtmBnlpfhf26jIPOqhlTm6TChkJCB5Fv99xXqVdT+tgryGQR4sZV5Ov2/gSkNs -# 72wV644+9TWUHbAiNrycsxIAuK5mZ61kY1Weody0MAmfryUVi1hsMTOPvn5P+2mG -# TE9Xz2rWI+iz4O7y0qeob022sImkfWQAkY1+fv7tlxKXNCEfU7lSxptGj/WaQbeV -# rh1bQisRWypNk+gNTyo5/cuiie0CmAlFj1hgqlMhuuilRgy44TABe6xtnr/m/q37 -# hrLrWkqIt9WfuxoOZ31g4G87kJpG9sQrDEAxKbxoxe2rZN7ryQVm/A+dA49KPh+7 -# PL8YDk70Cpu6YRuodlxopWhEFgrkiYDzO13emveUZO2B1ePk/LZczU+1eaIrkNIA -# 1jWBNQ067OQR5+TNq0iAa6e+WXsndc4Fph/5Y7qPiNygXOnGYchgTXv0J62n1JZ9 -# t6Uz+FJcgIXcvHB6jDW6i0GhpqLo7QIDAQABo4ICGTCCAhUwDAYDVR0TAQH/BAIw -# ADAOBgNVHQ8BAf8EBAMCB4AwPAYDVR0lBDUwMwYKKwYBBAGCN2EBAAYIKwYBBQUH -# AwMGGysGAQQBgjdhgqKNuwqmkohkgZH0oEWCk/3hbzAdBgNVHQ4EFgQU0otww7J0 -# 5gUeVUO9AseaqV7fclUwHwYDVR0jBBgwFoAUZZ9RzoVofy+KRYiq3acxux4NAF4w -# ZwYDVR0fBGAwXjBcoFqgWIZWaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9w -# cy9jcmwvTWljcm9zb2Z0JTIwSUQlMjBWZXJpZmllZCUyMENTJTIwRU9DJTIwQ0El -# MjAwMi5jcmwwgaUGCCsGAQUFBwEBBIGYMIGVMGQGCCsGAQUFBzAChlhodHRwOi8v -# d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMElEJTIw -# VmVyaWZpZWQlMjBDUyUyMEVPQyUyMENBJTIwMDIuY3J0MC0GCCsGAQUFBzABhiFo -# dHRwOi8vb25lb2NzcC5taWNyb3NvZnQuY29tL29jc3AwZgYDVR0gBF8wXTBRBgwr -# BgEEAYI3TIN9AQEwQTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQu -# Y29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRtMAgGBmeBDAEEATANBgkqhkiG -# 9w0BAQwFAAOCAgEAnasFEuVrXZqMkkmjnHMITmqw/GsXI83rSgItYpGhNcbx8DZ/ -# ENI072VQg1inVZDLh3hVH29XKMCg+3pBTK4CKpfLUWmIXiGwTXPDNsC1cZD1oMpe -# jalX6bsD45UxNhqmAnzWuZrrjGWIsDDvSmFsSJb4WJvhzTfbaKe149RkIMY5uJBO -# sr2UIVTmBug9S8JPxPX5ssXj8lxgSn01C3VPcRqiyzIgzijLj67Qc3IUmvGO/F8Z -# j+QRdisR6I5/9V8RszASTVEfHSNYhGRYY2OEIjdbKqjDSzmYf4mwN1ALdLM0PEsL -# /F+ZCYJXJLHJxptckK5PB7nLTd5yF6GV3lES0vINBQ/pUOjK2+G/7xwOeYw7zKbT -# RdBZTngrEFuzxZFNfid8Y9clqcnDAsqeOepRnhI+0hQdqa8P2aMWf8KYdCXsaE11 -# luELJHfURq8S7Mo0gDpI52xYm/+Osg2SeLrCsl2Ir1iH6IawL/qZfnQu0IWfpsFz -# /K+CJoHsphngB1/MMNpdXWQqVmsJDxnO+LTpWQuCw3azDJ20vr1wrmzgNLZBmOnf -# uYz76Emg5+JX0SSaqVIW1bWd5AcNxF7HDxLK7WuiNtMJYLhVJC5mPiE251ly5lfO -# Jjxdt60snj+F8HM1NjevHnzViscRpCW87d0GpcaJLCrJvVRjzvmL2B+UuDUwggda -# MIIFQqADAgECAhMzAAAABft6XDITYd9dAAAAAAAFMA0GCSqGSIb3DQEBDAUAMGMx -# CzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xNDAy -# BgNVBAMTK01pY3Jvc29mdCBJRCBWZXJpZmllZCBDb2RlIFNpZ25pbmcgUENBIDIw -# MjEwHhcNMjEwNDEzMTczMTUzWhcNMjYwNDEzMTczMTUzWjBaMQswCQYDVQQGEwJV -# UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSswKQYDVQQDEyJNaWNy -# b3NvZnQgSUQgVmVyaWZpZWQgQ1MgRU9DIENBIDAyMIICIjANBgkqhkiG9w0BAQEF -# AAOCAg8AMIICCgKCAgEA0hqZfD8ykKTA6CDbWvshmBpDoBf7Lv132RVuSqVwQO3a -# ALLkuRnnTIoRmMGo0fIMQrtwR6UHB06xdqOkAfqB6exubXTHu44+duHUCdE4ngjE -# LBQyluMuSOnHaEdveIbt31OhMEX/4nQkph4+Ah0eR4H2sTRrVKmKrlOoQlhia73Q -# g2dHoitcX1uT1vW3Knpt9Mt76H7ZHbLNspMZLkWBabKMl6BdaWZXYpPGdS+qY80g -# DaNCvFq0d10UMu7xHesIqXpTDT3Q3AeOxSylSTc/74P3og9j3OuemEFauFzL55t1 -# MvpadEhQmD8uFMxFv/iZOjwvcdY1zhanVLLyplz13/NzSoU3QjhPdqAGhRIwh/YD -# zo3jCdVJgWQRrW83P3qWFFkxNiME2iO4IuYgj7RwseGwv7I9cxOyaHihKMdT9Neo -# SjpSNzVnKKGcYMtOdMtKFqoV7Cim2m84GmIYZTBorR/Po9iwlasTYKFpGZqdWKyY -# nJO2FV8oMmWkIK1iagLLgEt6ZaR0rk/1jUYssyTiRqWr84Qs3XL/V5KUBEtUEQfQ -# /4RtnI09uFFUIGJZV9mD/xOUksWodGrCQSem6Hy261xMJAHqTqMuDKgwi8xk/mfl -# r7yhXPL73SOULmu1Aqu4I7Gpe6QwNW2TtQBxM3vtSTmdPW6rK5y0gED51RjsyK0C -# AwEAAaOCAg4wggIKMA4GA1UdDwEB/wQEAwIBhjAQBgkrBgEEAYI3FQEEAwIBADAd -# BgNVHQ4EFgQUZZ9RzoVofy+KRYiq3acxux4NAF4wVAYDVR0gBE0wSzBJBgRVHSAA -# MEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMv -# RG9jcy9SZXBvc2l0b3J5Lmh0bTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAS -# BgNVHRMBAf8ECDAGAQH/AgEAMB8GA1UdIwQYMBaAFNlBKbAPD2Ns72nX9c0pnqRI -# ajDmMHAGA1UdHwRpMGcwZaBjoGGGX2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9w -# a2lvcHMvY3JsL01pY3Jvc29mdCUyMElEJTIwVmVyaWZpZWQlMjBDb2RlJTIwU2ln -# bmluZyUyMFBDQSUyMDIwMjEuY3JsMIGuBggrBgEFBQcBAQSBoTCBnjBtBggrBgEF -# BQcwAoZhaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNy -# b3NvZnQlMjBJRCUyMFZlcmlmaWVkJTIwQ29kZSUyMFNpZ25pbmclMjBQQ0ElMjAy -# MDIxLmNydDAtBggrBgEFBQcwAYYhaHR0cDovL29uZW9jc3AubWljcm9zb2Z0LmNv -# bS9vY3NwMA0GCSqGSIb3DQEBDAUAA4ICAQBFSWDUd08X4g5HzvVfrB1SiV8pk6XP -# HT9jPkCmvU/uvBzmZRAjYk2gKYR3pXoStRJaJ/lhjC5Dq/2R7P1YRZHCDYyK0zvS -# RMdE6YQtgGjmsdhzD0nCS6hVVcgfmNQscPJ1WHxbvG5EQgYQ0ZED1FN0MOPQzWe1 -# zbH5Va0dSxtnodBVRjnyDYEm7sNEcvJHTG3eXzAyd00E5KDCsEl4z5O0mvXqwaH2 -# PS0200E6P4WqLwgs/NmUu5+Aa8Lw/2En2VkIW7Pkir4Un1jG6+tj/ehuqgFyUPPC -# h6kbnvk48bisi/zPjAVkj7qErr7fSYICCzJ4s4YUNVVHgdoFn2xbW7ZfBT3QA9zf -# hq9u4ExXbrVD5rxXSTFEUg2gzQq9JHxsdHyMfcCKLFQOXODSzcYeLpCd+r6GcoDB -# ToyPdKccjC6mAq6+/hiMDnpvKUIHpyYEzWUeattyKXtMf+QrJeQ+ny5jBL+xqdOO -# PEz3dg7qn8/oprUrUbGLBv9fWm18fWXdAv1PCtLL/acMLtHoyeSVMKQYqDHb3Qm0 -# uQ+NQ0YE4kUxSQa+W/cCzYAI32uN0nb9M4Mr1pj4bJZidNkM4JyYqezohILxYkgH -# bboJQISrQWrm5RYdyhKBpptJ9JJn0Z63LjdnzlOUxjlsAbQir2Wmz/OJE703BbHm -# QZRwzPx1vu7S5zCCB54wggWGoAMCAQICEzMAAAAHh6M0o3uljhwAAAAAAAcwDQYJ -# KoZIhvcNAQEMBQAwdzELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29mdCBD -# b3Jwb3JhdGlvbjFIMEYGA1UEAxM/TWljcm9zb2Z0IElkZW50aXR5IFZlcmlmaWNh -# dGlvbiBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDIwMB4XDTIxMDQwMTIw -# MDUyMFoXDTM2MDQwMTIwMTUyMFowYzELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1p -# Y3Jvc29mdCBDb3Jwb3JhdGlvbjE0MDIGA1UEAxMrTWljcm9zb2Z0IElEIFZlcmlm -# aWVkIENvZGUgU2lnbmluZyBQQ0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIP -# ADCCAgoCggIBALLwwK8ZiCji3VR6TElsaQhVCbRS/3pK+MHrJSj3Zxd3KU3rlfL3 -# qrZilYKJNqztA9OQacr1AwoNcHbKBLbsQAhBnIB34zxf52bDpIO3NJlfIaTE/xrw -# eLoQ71lzCHkD7A4As1Bs076Iu+mA6cQzsYYH/Cbl1icwQ6C65rU4V9NQhNUwgrx9 -# rGQ//h890Q8JdjLLw0nV+ayQ2Fbkd242o9kH82RZsH3HEyqjAB5a8+Ae2nPIPc8s -# ZU6ZE7iRrRZywRmrKDp5+TcmJX9MRff241UaOBs4NmHOyke8oU1TYrkxh+YeHgfW -# o5tTgkoSMoayqoDpHOLJs+qG8Tvh8SnifW2Jj3+ii11TS8/FGngEaNAWrbyfNrC6 -# 9oKpRQXY9bGH6jn9NEJv9weFxhTwyvx9OJLXmRGbAUXN1U9nf4lXezky6Uh/cgjk -# Vd6CGUAf0K+Jw+GE/5VpIVbcNr9rNE50Sbmy/4RTCEGvOq3GhjITbCa4crCzTTHg -# YYjHs1NbOc6brH+eKpWLtr+bGecy9CrwQyx7S/BfYJ+ozst7+yZtG2wR461uckFu -# 0t+gCwLdN0A6cFtSRtR8bvxVFyWwTtgMMFRuBa3vmUOTnfKLsLefRaQcVTgRnzeL -# zdpt32cdYKp+dhr2ogc+qM6K4CBI5/j4VFyC4QFeUP2YAidLtvpXRRo3AgMBAAGj -# ggI1MIICMTAOBgNVHQ8BAf8EBAMCAYYwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0O -# BBYEFNlBKbAPD2Ns72nX9c0pnqRIajDmMFQGA1UdIARNMEswSQYEVR0gADBBMD8G -# CCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3Mv -# UmVwb3NpdG9yeS5odG0wGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwDwYDVR0T -# AQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTIftJqhSobyhmYBAcnz1AQT2ioojCBhAYD -# VR0fBH0wezB5oHegdYZzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9j -# cmwvTWljcm9zb2Z0JTIwSWRlbnRpdHklMjBWZXJpZmljYXRpb24lMjBSb290JTIw -# Q2VydGlmaWNhdGUlMjBBdXRob3JpdHklMjAyMDIwLmNybDCBwwYIKwYBBQUHAQEE -# gbYwgbMwgYEGCCsGAQUFBzAChnVodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtp -# b3BzL2NlcnRzL01pY3Jvc29mdCUyMElkZW50aXR5JTIwVmVyaWZpY2F0aW9uJTIw -# Um9vdCUyMENlcnRpZmljYXRlJTIwQXV0aG9yaXR5JTIwMjAyMC5jcnQwLQYIKwYB -# BQUHMAGGIWh0dHA6Ly9vbmVvY3NwLm1pY3Jvc29mdC5jb20vb2NzcDANBgkqhkiG -# 9w0BAQwFAAOCAgEAfyUqnv7Uq+rdZgrbVyNMul5skONbhls5fccPlmIbzi+OwVdP -# Q4H55v7VOInnmezQEeW4LqK0wja+fBznANbXLB0KrdMCbHQpbLvG6UA/Xv2pfpVI -# E1CRFfNF4XKO8XYEa3oW8oVH+KZHgIQRIwAbyFKQ9iyj4aOWeAzwk+f9E5StNp5T -# 8FG7/VEURIVWArbAzPt9ThVN3w1fAZkF7+YU9kbq1bCR2YD+MtunSQ1Rft6XG7b4 -# e0ejRA7mB2IoX5hNh3UEauY0byxNRG+fT2MCEhQl9g2i2fs6VOG19CNep7SquKaB -# jhWmirYyANb0RJSLWjinMLXNOAga10n8i9jqeprzSMU5ODmrMCJE12xS/NWShg/t -# uLjAsKP6SzYZ+1Ry358ZTFcx0FS/mx2vSoU8s8HRvy+rnXqyUJ9HBqS0DErVLjQw -# K8VtsBdekBmdTbQVoCgPCqr+PDPB3xajYnzevs7eidBsM71PINK2BoE2UfMwxCCX -# 3mccFgx6UsQeRSdVVVNSyALQe6PT12418xon2iDGE81OGCreLzDcMAZnrUAx4XQL -# Uz6ZTl65yPUiOh3k7Yww94lDf+8oG2oZmDh5O1Qe38E+M3vhKwmzIeoB1dVLlz4i -# 3IpaDcR+iuGjH2TdaC1ZOmBXiCRKJLj4DT2uhJ04ji+tHD6n58vhavFIrmcxghrq -# MIIa5gIBATBxMFoxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y -# cG9yYXRpb24xKzApBgNVBAMTIk1pY3Jvc29mdCBJRCBWZXJpZmllZCBDUyBFT0Mg -# Q0EgMDICEzMABstWb+B2X+lAIVYAAAAGy1YwDQYJYIZIAWUDBAIBBQCggbQwGQYJ -# KoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQB -# gjcCARUwLwYJKoZIhvcNAQkEMSIEICpXe3RS3b2coD0CJveEHlglqtPUYZ2FqSrO -# UfP6C6Y4MEgGCisGAQQBgjcCAQwxOjA4oDKAMABQAHkAdABoAG8AbgAgADMALgAx -# ADMALgAxADIAIAAoADEAYwBiAGUANAA4ADEAKaECgAAwDQYJKoZIhvcNAQEBBQAE -# ggGATJCrsJUicLrCpF8N3j7QgLaRGpaeQI9ffGxThkfZFhsp7rn8a+TF4eQ5rtRc -# VJ4UWt3Q0T5O/gwHpuKcwvo7wd2SvR3+j9+Q2p5EmtZQQWOlrytRsFkyODun5GZZ -# P7Kp49m2pbR5T+cA+1rLHGPvgRdT7aCXg5ZxdHK1qfArZfM1tD0KsfPvA6ydk2MT -# 1MRA1cAyeF8k9nCD2jnebiMZOCyjyUcu0QULJei1A+DjPkLmdg3GdKgenemn65Dp -# ym/ZVb2WfJvqr4kQ5A56opS3wn8OXVGQp4lh1FUZzpM/+nUT/xjMEO6TSqdRK52u -# XOPUliPdliUg7kEq7t6seMFcRUcNG4q9C5rs0SbJ9f2SEkgGypsBxSf6lX7MjuDi -# 7BX4N8eMGjMeI+Qa4ERMflBM+R5wOkm5JcZ0d6/menoBNPpbzpXGWbBfMHPiWy86 -# +a+XYy1O5QWkJuaW4fo4ojNtA5zV6Q7zdJnUZTV6YwcXeDmGe1c17F9ysb4os9y4 -# EzWKoYIYEzCCGA8GCisGAQQBgjcDAwExghf/MIIX+wYJKoZIhvcNAQcCoIIX7DCC -# F+gCAQMxDzANBglghkgBZQMEAgEFADCCAWEGCyqGSIb3DQEJEAEEoIIBUASCAUww -# ggFIAgEBBgorBgEEAYRZCgMBMDEwDQYJYIZIAWUDBAIBBQAEID5IbVievRnShKjl -# YoBiKfpvanMshYl5yZ+wllrNo5y+AgZpb2FvBcUYEjIwMjYwMjAzMTk0MTA1LjM5 -# WjAEgAIB9KCB4aSB3jCB2zELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0 -# b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3Jh -# dGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEnMCUG -# A1UECxMeblNoaWVsZCBUU1MgRVNOOkE1MDAtMDVFMC1EOTQ3MTUwMwYDVQQDEyxN -# aWNyb3NvZnQgUHVibGljIFJTQSBUaW1lIFN0YW1waW5nIEF1dGhvcml0eaCCDyEw -# ggeCMIIFaqADAgECAhMzAAAABeXPD/9mLsmHAAAAAAAFMA0GCSqGSIb3DQEBDAUA -# MHcxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x -# SDBGBgNVBAMTP01pY3Jvc29mdCBJZGVudGl0eSBWZXJpZmljYXRpb24gUm9vdCBD -# ZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAyMDAeFw0yMDExMTkyMDMyMzFaFw0zNTEx -# MTkyMDQyMzFaMGExCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y -# cG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBQdWJsaWMgUlNBIFRpbWVzdGFt -# cGluZyBDQSAyMDIwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnnzn -# UmP94MWfBX1jtQYioxwe1+eXM9ETBb1lRkd3kcFdcG9/sqtDlwxKoVIcaqDb+omF -# io5DHC4RBcbyQHjXCwMk/l3TOYtgoBjxnG/eViS4sOx8y4gSq8Zg49REAf5huXhI -# kQRKe3Qxs8Sgp02KHAznEa/Ssah8nWo5hJM1xznkRsFPu6rfDHeZeG1Wa1wISvlk -# pOQooTULFm809Z0ZYlQ8Lp7i5F9YciFlyAKwn6yjN/kR4fkquUWfGmMopNq/B8U/ -# pdoZkZZQbxNlqJOiBGgCWpx69uKqKhTPVi3gVErnc/qi+dR8A2MiAz0kN0nh7SqI -# NGbmw5OIRC0EsZ31WF3Uxp3GgZwetEKxLms73KG/Z+MkeuaVDQQheangOEMGJ4pQ -# ZH55ngI0Tdy1bi69INBV5Kn2HVJo9XxRYR/JPGAaM6xGl57Ei95HUw9NV/uC3yFj -# rhc087qLJQawSC3xzY/EXzsT4I7sDbxOmM2rl4uKK6eEpurRduOQ2hTkmG1hSuWY -# BunFGNv21Kt4N20AKmbeuSnGnsBCd2cjRKG79+TX+sTehawOoxfeOO/jR7wo3liw -# kGdzPJYHgnJ54UxbckF914AqHOiEV7xTnD1a69w/UTxwjEugpIPMIIE67SFZ2PMo -# 27xjlLAHWW3l1CEAFjLNHd3EQ79PUr8FUXetXr0CAwEAAaOCAhswggIXMA4GA1Ud -# DwEB/wQEAwIBhjAQBgkrBgEEAYI3FQEEAwIBADAdBgNVHQ4EFgQUa2koOjUvSGNA -# z3vYr0npPtk92yEwVAYDVR0gBE0wSzBJBgRVHSAAMEEwPwYIKwYBBQUHAgEWM2h0 -# dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0 -# bTATBgNVHSUEDDAKBggrBgEFBQcDCDAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMA -# QTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFMh+0mqFKhvKGZgEByfPUBBP -# aKiiMIGEBgNVHR8EfTB7MHmgd6B1hnNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20v -# cGtpb3BzL2NybC9NaWNyb3NvZnQlMjBJZGVudGl0eSUyMFZlcmlmaWNhdGlvbiUy -# MFJvb3QlMjBDZXJ0aWZpY2F0ZSUyMEF1dGhvcml0eSUyMDIwMjAuY3JsMIGUBggr -# BgEFBQcBAQSBhzCBhDCBgQYIKwYBBQUHMAKGdWh0dHA6Ly93d3cubWljcm9zb2Z0 -# LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwSWRlbnRpdHklMjBWZXJpZmlj -# YXRpb24lMjBSb290JTIwQ2VydGlmaWNhdGUlMjBBdXRob3JpdHklMjAyMDIwLmNy -# dDANBgkqhkiG9w0BAQwFAAOCAgEAX4h2x35ttVoVdedMeGj6TuHYRJklFaW4sTQ5 -# r+k77iB79cSLNe+GzRjv4pVjJviceW6AF6ycWoEYR0LYhaa0ozJLU5Yi+LCmcrdo -# vkl53DNt4EXs87KDogYb9eGEndSpZ5ZM74LNvVzY0/nPISHz0Xva71QjD4h+8z2X -# MOZzY7YQ0Psw+etyNZ1CesufU211rLslLKsO8F2aBs2cIo1k+aHOhrw9xw6JCWON -# NboZ497mwYW5EfN0W3zL5s3ad4Xtm7yFM7Ujrhc0aqy3xL7D5FR2J7x9cLWMq7eb -# 0oYioXhqV2tgFqbKHeDick+P8tHYIFovIP7YG4ZkJWag1H91KlELGWi3SLv10o4K -# Gag42pswjybTi4toQcC/irAodDW8HNtX+cbz0sMptFJK+KObAnDFHEsukxD+7jFf -# EV9Hh/+CSxKRsmnuiovCWIOb+H7DRon9TlxydiFhvu88o0w35JkNbJxTk4MhF/Kg -# aXn0GxdH8elEa2Imq45gaa8D+mTm8LWVydt4ytxYP/bqjN49D9NZ81coE6aQWm88 -# TwIf4R4YZbOpMKN0CyejaPNN41LGXHeCUMYmBx3PkP8ADHD1J2Cr/6tjuOOCztfp -# +o9Nc+ZoIAkpUcA/X2gSMkgHAPUvIdtoSAHEUKiBhI6JQivRepyvWcl+JYbYbBh7 -# pmgAXVswggeXMIIFf6ADAgECAhMzAAAAVn6PnVgIjulgAAAAAABWMA0GCSqGSIb3 -# DQEBDAUAMGExCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9y -# YXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBQdWJsaWMgUlNBIFRpbWVzdGFtcGlu -# ZyBDQSAyMDIwMB4XDTI1MTAyMzIwNDY1MVoXDTI2MTAyMjIwNDY1MVowgdsxCzAJ -# BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k -# MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJTAjBgNVBAsTHE1pY3Jv -# c29mdCBBbWVyaWNhIE9wZXJhdGlvbnMxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVT -# TjpBNTAwLTA1RTAtRDk0NzE1MDMGA1UEAxMsTWljcm9zb2Z0IFB1YmxpYyBSU0Eg -# VGltZSBTdGFtcGluZyBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw -# ggIKAoICAQC0pZ+b+6XTbv93xGVvwyf+DRBS+8upjZWzLe0jxTa0VKylNmiZk4Pc -# EdPwuRH5GuEwmBvVWMAoU3Kxor1wtJeJ88ZIgGs8KCz0/jLbiWskSatXpDnPgGao -# yEg+tmES9mdakJLgc7uNhJ6L+fGYLv/USv6XkuDc+ZLFvx3YhVwBHFLDUHibEHpc -# jSeR6X3BrV1hvbB8amh+toWbFk7FP142G3gsfREFJW55trpk2mNL/SC1+buqIiLI -# /qno9HNNNsydWqwedX93+tbTMfH5D5A1nnBSoqZNkkH2FTznf7alfmsN8rfa41j3 -# 9YE4CbNuqCkR1CRuIxq9QzJQNKGbJwi+Ad1CdLbTuxOPwz6Qkve051qE+4+ozCxo -# IKB1/DBDHQ71Mp7sVK9sARizUCeV0KX8ocZkI5W9Q2qPIvXQkt7T/4YP3/KepcZY -# Wlc6Nq6e9n9wpE6GM3gzl7rHHRvaaKpw+KLj+KLZmF4pqWUkRPsIqWkVKGzfDKDo -# X9+iNDFC8+dtYPg3LHqWGNaPCagtzHrDUVIK1q8sKXLfcEtFKVNTiopTFprx3tg3 -# sSqmf1c7RJjS6Y68oVetYfuvGX72JqJyK12dNOSwCdGO96R0pPeWDuVEx+Z9lTy9 -# c2I3RRgnNP0SOqNGbS43+HShfE+E189ip4VvI9cYbHNphTPrPHepNwIDAQABo4IB -# yzCCAccwHQYDVR0OBBYEFL62M/K7q1n+HkazIu/LPUf4U0haMB8GA1UdIwQYMBaA -# FGtpKDo1L0hjQM972K9J6T7ZPdshMGwGA1UdHwRlMGMwYaBfoF2GW2h0dHA6Ly93 -# d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY3Jvc29mdCUyMFB1YmxpYyUy -# MFJTQSUyMFRpbWVzdGFtcGluZyUyMENBJTIwMjAyMC5jcmwweQYIKwYBBQUHAQEE -# bTBrMGkGCCsGAQUFBzAChl1odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3Bz -# L2NlcnRzL01pY3Jvc29mdCUyMFB1YmxpYyUyMFJTQSUyMFRpbWVzdGFtcGluZyUy -# MENBJTIwMjAyMC5jcnQwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEF -# BQcDCDAOBgNVHQ8BAf8EBAMCB4AwZgYDVR0gBF8wXTBRBgwrBgEEAYI3TIN9AQEw -# QTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9E -# b2NzL1JlcG9zaXRvcnkuaHRtMAgGBmeBDAEEAjANBgkqhkiG9w0BAQwFAAOCAgEA -# DgOoBcSw7bqP8trsWCf9CJ+K3zG5l6Spnnv5h76wf+FFNsQSMZitmCyrBH+VRR8o -# IWltkXyaxpk9Ak5HhhhQRTxfKMuufxjWMJKajGH2Xu1aJKhz8kUHDfnokCbMYbF4 -# EDYRZLFG5OvUC5l7qdho3z/C0WSIdyzyAxp3FcGzoPFWHK7lieEs9CR+6YqbeUV+ -# 3ATumJ5Xt/WWySaWCwLoB5IYLMY9lSAK9wflO/9B73PtsgiZIPdK7OE4jBo/54pB -# Nh/rtOJ/IkqRZBJ0Z9MDopy7jWTwsHqg8r4wuTWNvHErnA+otIvrbGMrThIFccQl -# ISewW3TPFaTE/+WB6PUPGpSeatgR2TG/MpIcgCoVZJm6X/mEj68nG8U+Gw1AESTh -# xK6UOQlClx1WL+CZ/+YcU5iEMGOxrXmzgv7awGKXddX9PxGJHrpDzFi9MtFbF3Z1 -# Wys6gLCexThYh6ILQmKcK/VYscSHtDLOv1FKviQoktZ2k1guGCOSiNOYSQCMU7vv -# i3fEHt6du8gXQY6xXX3GcJTOr0QYrK3SAy5qmEqU2Mn5pOmNYxkMaj4Y4qyen3ce -# Z+2aXRLKncX34zfL7LpYkZRmghkmrbbuMOOMSd22lSuH0F091Uh9UkP8C7zVHOHT -# lQcCK+itDc6zw8QsciCI531NbNt2CYbNwgu3911VARExggdGMIIHQgIBATB4MGEx -# CzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAw -# BgNVBAMTKU1pY3Jvc29mdCBQdWJsaWMgUlNBIFRpbWVzdGFtcGluZyBDQSAyMDIw -# AhMzAAAAVn6PnVgIjulgAAAAAABWMA0GCWCGSAFlAwQCAQUAoIIEnzARBgsqhkiG -# 9w0BCRACDzECBQAwGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEEMBwGCSqGSIb3 -# DQEJBTEPFw0yNjAyMDMxOTQxMDVaMC8GCSqGSIb3DQEJBDEiBCD9IoFZknpDXVCH -# tJ2isniuwcI6Yg0b6DuutG3YE3oT3zCBuQYLKoZIhvcNAQkQAi8xgakwgaYwgaMw -# gaAEILYMMyVNpOPwlXeJODleel7gJIfrTXjdn5f2jk0GAwyoMHwwZaRjMGExCzAJ -# BgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNV -# BAMTKU1pY3Jvc29mdCBQdWJsaWMgUlNBIFRpbWVzdGFtcGluZyBDQSAyMDIwAhMz -# AAAAVn6PnVgIjulgAAAAAABWMIIDYQYLKoZIhvcNAQkQAhIxggNQMIIDTKGCA0gw -# ggNEMIICLAIBATCCAQmhgeGkgd4wgdsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpX -# YXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQg -# Q29ycG9yYXRpb24xJTAjBgNVBAsTHE1pY3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlv -# bnMxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVTTjpBNTAwLTA1RTAtRDk0NzE1MDMG -# A1UEAxMsTWljcm9zb2Z0IFB1YmxpYyBSU0EgVGltZSBTdGFtcGluZyBBdXRob3Jp -# dHmiIwoBATAHBgUrDgMCGgMVAP9z9ykVKpBZgF5eCDJEnZlu9gQRoGcwZaRjMGEx -# CzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAw -# BgNVBAMTKU1pY3Jvc29mdCBQdWJsaWMgUlNBIFRpbWVzdGFtcGluZyBDQSAyMDIw -# MA0GCSqGSIb3DQEBCwUAAgUA7SxU1TAiGA8yMDI2MDIwMzExMDQ1M1oYDzIwMjYw -# MjA0MTEwNDUzWjB3MD0GCisGAQQBhFkKBAExLzAtMAoCBQDtLFTVAgEAMAoCAQAC -# AgzRAgH/MAcCAQACAhMKMAoCBQDtLaZVAgEAMDYGCisGAQQBhFkKBAIxKDAmMAwG -# CisGAQQBhFkKAwKgCjAIAgEAAgMHoSChCjAIAgEAAgMBhqAwDQYJKoZIhvcNAQEL -# BQADggEBALOYBKN41nk7fMBMOxSTfU+Fem0D6ycWllgixiAXAMjW87P/Et+FUyC9 -# 192uE3/ozxzTzjlBmyflkjUfXc0kDLSqVaw5E8A8p9iicwYRrqGXcsaH+PCSBYiS -# 7QRKZ0UL8+WuU8NsOth7M+ocnEI41KCAIrdtj3I3RmbJFTTu2huLY7Prz7vZ6f/e -# SZLqwFZwXKI5wnQjHcPQz19lwLKSxzt9fz07HnaCiqwgZhXw6KExhR5xPOLILndh -# TK6fDPey1LgryqwnBdZp67CaZlxwxkPJ9AlyGoX96ocVo6XYR9ViX9uFW8sUrVTf -# 6uguhf4WL3ZUZNVb7idiyqkzlLSaIoAwDQYJKoZIhvcNAQEBBQAEggIAQaukese3 -# UNfju7vCwoCftT+ckGKbWvW3UmFnigkIERpHF/VfNrMUbKIy2B3BxIX0CcBeu3tJ -# QRXjE/1P43wtSJYVUrCbCV3SFAovyN9G4REjTz7JXEa5iiUdA8fldyJ6y2kcC08a -# 64OqjdQuD+OtMr72I4eflABJ/99BUGvx+8oWBDBsJi+9J6rW4ks7ZR1LHKV6jqwu -# VzXzo1SRjkktNBvCIjetuyqvQBs4+AAiuCd3oKeeVFpBbVGrlWiCrEztOCeiru9G -# 89nPiwZl79y1iREZNqr6KwSi9/1xZ37Lzz+Zw+ZRYmEs5mCm5T/ayGuCwODLq/2T -# L38D9bzi1bOM54jFHdFOawhcLukLHr0qdtMKZqWJwJTFghcWt+DF3B+MdZT3Ny6E -# 0JXV1Jl/upIQ3QXHTYRQn0dS7qDNVLO8/GawaeKC2Of80FRswGXJbSuGBh0ioPJ3 -# 5smFuQ64Wlqp+nnIv1tL/1ZPrtApm7RJztIIhyo4Aqx0zY29eqUsb+WobnVbrTPz -# gZpuXsMoOwYRNjEomqISCUV1xgerhBa/bl4LFiJTWhitHXLjwqq9+ialwiw4amG5 -# Ht3sLKPxVK1FR4r/XxFdA/CF38SivpyJ6gWT+DpNAEmlyREWVh9vjuXnQDheXkNb -# VmGTiwa93gfMzXk5llDFS1z543lnBiUeZ7Q= +# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBnL745ElCYk8vk +# dBtMuQhLeWJ3ZGfzKW4DHCYzAn+QB6CCE8MwggWQMIIDeKADAgECAhAFmxtXno4h +# MuI5B72nd3VcMA0GCSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK +# EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNV +# BAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0xMzA4MDExMjAwMDBaFw0z +# ODAxMTUxMjAwMDBaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ +# bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0 +# IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB +# AL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3EMB/z +# G6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKyunWZ +# anMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsFxl7s +# Wxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU15zHL +# 2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJBMtfb +# BHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObURWBf3 +# JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6nj3c +# AORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxBYKqx +# YxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5SUUd0 +# viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+xq4aL +# T8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjQjBAMA8GA1Ud +# EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTs1+OC0nFdZEzf +# Lmc/57qYrhwPTzANBgkqhkiG9w0BAQwFAAOCAgEAu2HZfalsvhfEkRvDoaIAjeNk +# aA9Wz3eucPn9mkqZucl4XAwMX+TmFClWCzZJXURj4K2clhhmGyMNPXnpbWvWVPjS +# PMFDQK4dUPVS/JA7u5iZaWvHwaeoaKQn3J35J64whbn2Z006Po9ZOSJTROvIXQPK +# 7VB6fWIhCoDIc2bRoAVgX+iltKevqPdtNZx8WorWojiZ83iL9E3SIAveBO6Mm0eB +# cg3AFDLvMFkuruBx8lbkapdvklBtlo1oepqyNhR6BvIkuQkRUNcIsbiJeoQjYUIp +# 5aPNoiBB19GcZNnqJqGLFNdMGbJQQXE9P01wI4YMStyB0swylIQNCAmXHE/A7msg +# dDDS4Dk0EIUhFQEI6FUy3nFJ2SgXUE3mvk3RdazQyvtBuEOlqtPDBURPLDab4vri +# RbgjU2wGb2dVf0a1TD9uKFp5JtKkqGKX0h7i7UqLvBv9R0oN32dmfrJbQdA75PQ7 +# 9ARj6e/CVABRoIoqyc54zNXqhwQYs86vSYiv85KZtrPmYQ/ShQDnUBrkG5WdGaG5 +# nLGbsQAe79APT0JsyQq87kP6OnGlyE0mpTX9iV28hWIdMtKgK1TtmlfB2/oQzxm3 +# i0objwG2J5VT6LaJbVu8aNQj6ItRolb58KaAoNYes7wPD1N1KarqE3fk3oyBIa0H +# EEcRrYc9B9F1vM/zZn4wggawMIIEmKADAgECAhAIrUCyYNKcTJ9ezam9k67ZMA0G +# CSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ +# bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0 +# IFRydXN0ZWQgUm9vdCBHNDAeFw0yMTA0MjkwMDAwMDBaFw0zNjA0MjgyMzU5NTla +# MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UE +# AxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcgUlNBNDA5NiBTSEEz +# ODQgMjAyMSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDVtC9C +# 0CiteLdd1TlZG7GIQvUzjOs9gZdwxbvEhSYwn6SOaNhc9es0JAfhS0/TeEP0F9ce +# 2vnS1WcaUk8OoVf8iJnBkcyBAz5NcCRks43iCH00fUyAVxJrQ5qZ8sU7H/Lvy0da +# E6ZMswEgJfMQ04uy+wjwiuCdCcBlp/qYgEk1hz1RGeiQIXhFLqGfLOEYwhrMxe6T +# SXBCMo/7xuoc82VokaJNTIIRSFJo3hC9FFdd6BgTZcV/sk+FLEikVoQ11vkunKoA +# FdE3/hoGlMJ8yOobMubKwvSnowMOdKWvObarYBLj6Na59zHh3K3kGKDYwSNHR7Oh +# D26jq22YBoMbt2pnLdK9RBqSEIGPsDsJ18ebMlrC/2pgVItJwZPt4bRc4G/rJvmM +# 1bL5OBDm6s6R9b7T+2+TYTRcvJNFKIM2KmYoX7BzzosmJQayg9Rc9hUZTO1i4F4z +# 8ujo7AqnsAMrkbI2eb73rQgedaZlzLvjSFDzd5Ea/ttQokbIYViY9XwCFjyDKK05 +# huzUtw1T0PhH5nUwjewwk3YUpltLXXRhTT8SkXbev1jLchApQfDVxW0mdmgRQRNY +# mtwmKwH0iU1Z23jPgUo+QEdfyYFQc4UQIyFZYIpkVMHMIRroOBl8ZhzNeDhFMJlP +# /2NPTLuqDQhTQXxYPUez+rbsjDIJAsxsPAxWEQIDAQABo4IBWTCCAVUwEgYDVR0T +# AQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUaDfg67Y7+F8Rhvv+YXsIiGX0TkIwHwYD +# VR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMG +# A1UdJQQMMAoGCCsGAQUFBwMDMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYY +# aHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2Fj +# ZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNV +# HR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRU +# cnVzdGVkUm9vdEc0LmNybDAcBgNVHSAEFTATMAcGBWeBDAEDMAgGBmeBDAEEATAN +# BgkqhkiG9w0BAQwFAAOCAgEAOiNEPY0Idu6PvDqZ01bgAhql+Eg08yy25nRm95Ry +# sQDKr2wwJxMSnpBEn0v9nqN8JtU3vDpdSG2V1T9J9Ce7FoFFUP2cvbaF4HZ+N3HL +# IvdaqpDP9ZNq4+sg0dVQeYiaiorBtr2hSBh+3NiAGhEZGM1hmYFW9snjdufE5Btf +# Q/g+lP92OT2e1JnPSt0o618moZVYSNUa/tcnP/2Q0XaG3RywYFzzDaju4ImhvTnh +# OE7abrs2nfvlIVNaw8rpavGiPttDuDPITzgUkpn13c5UbdldAhQfQDN8A+KVssIh +# dXNSy0bYxDQcoqVLjc1vdjcshT8azibpGL6QB7BDf5WIIIJw8MzK7/0pNVwfiThV +# 9zeKiwmhywvpMRr/LhlcOXHhvpynCgbWJme3kuZOX956rEnPLqR0kq3bPKSchh/j +# wVYbKyP/j7XqiHtwa+aguv06P0WmxOgWkVKLQcBIhEuWTatEQOON8BUozu3xGFYH +# Ki8QxAwIZDwzj64ojDzLj4gLDb879M4ee47vtevLt/B3E+bnKD+sEq6lLyJsQfmC +# XBVmzGwOysWGw/YmMwwHS6DTBwJqakAwSEs0qFEgu60bhQjiWQ1tygVQK+pKHJ6l +# /aCnHwZ05/LWUpD9r4VIIflXO7ScA+2GRfS0YW6/aOImYIbqyK+p/pQd52MbOoZW +# eE4wggd3MIIFX6ADAgECAhAHHxQbizANJfMU6yMM0NHdMA0GCSqGSIb3DQEBCwUA +# MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UE +# AxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcgUlNBNDA5NiBTSEEz +# ODQgMjAyMSBDQTEwHhcNMjIwMTE3MDAwMDAwWhcNMjUwMTE1MjM1OTU5WjB8MQsw +# CQYDVQQGEwJVUzEPMA0GA1UECBMGT3JlZ29uMRIwEAYDVQQHEwlCZWF2ZXJ0b24x +# IzAhBgNVBAoTGlB5dGhvbiBTb2Z0d2FyZSBGb3VuZGF0aW9uMSMwIQYDVQQDExpQ +# eXRob24gU29mdHdhcmUgRm91bmRhdGlvbjCCAiIwDQYJKoZIhvcNAQEBBQADggIP +# ADCCAgoCggIBAKgc0BTT+iKbtK6f2mr9pNMUTcAJxKdsuOiSYgDFfwhjQy89koM7 +# uP+QV/gwx8MzEt3c9tLJvDccVWQ8H7mVsk/K+X+IufBLCgUi0GGAZUegEAeRlSXx +# xhYScr818ma8EvGIZdiSOhqjYc4KnfgfIS4RLtZSrDFG2tN16yS8skFa3IHyvWdb +# D9PvZ4iYNAS4pjYDRjT/9uzPZ4Pan+53xZIcDgjiTwOh8VGuppxcia6a7xCyKoOA +# GjvCyQsj5223v1/Ig7Dp9mGI+nh1E3IwmyTIIuVHyK6Lqu352diDY+iCMpk9Zanm +# SjmB+GMVs+H/gOiofjjtf6oz0ki3rb7sQ8fTnonIL9dyGTJ0ZFYKeb6BLA66d2GA +# LwxZhLe5WH4Np9HcyXHACkppsE6ynYjTOd7+jN1PRJahN1oERzTzEiV6nCO1M3U1 +# HbPTGyq52IMFSBM2/07WTJSbOeXjvYR7aUxK9/ZkJiacl2iZI7IWe7JKhHohqKuc +# eQNyOzxTakLcRkzynvIrk33R9YVqtB4L6wtFxhUjvDnQg16xot2KVPdfyPAWd81w +# tZADmrUtsZ9qG79x1hBdyOl4vUtVPECuyhCxaw+faVjumapPUnwo8ygflJJ74J+B +# Yxf6UuD7m8yzsfXWkdv52DjL74TxzuFTLHPyARWCSCAbzn3ZIly+qIqDAgMBAAGj +# ggIGMIICAjAfBgNVHSMEGDAWgBRoN+Drtjv4XxGG+/5hewiIZfROQjAdBgNVHQ4E +# FgQUt/1Teh2XDuUj2WW3siYWJgkZHA8wDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQM +# MAoGCCsGAQUFBwMDMIG1BgNVHR8Ega0wgaowU6BRoE+GTWh0dHA6Ly9jcmwzLmRp +# Z2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNENvZGVTaWduaW5nUlNBNDA5NlNI +# QTM4NDIwMjFDQTEuY3JsMFOgUaBPhk1odHRwOi8vY3JsNC5kaWdpY2VydC5jb20v +# RGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmluZ1JTQTQwOTZTSEEzODQyMDIxQ0Ex +# LmNybDA+BgNVHSAENzA1MDMGBmeBDAEEATApMCcGCCsGAQUFBwIBFhtodHRwOi8v +# d3d3LmRpZ2ljZXJ0LmNvbS9DUFMwgZQGCCsGAQUFBwEBBIGHMIGEMCQGCCsGAQUF +# BzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wXAYIKwYBBQUHMAKGUGh0dHA6 +# Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNENvZGVTaWdu +# aW5nUlNBNDA5NlNIQTM4NDIwMjFDQTEuY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZI +# hvcNAQELBQADggIBABxv4AeV/5ltkELHSC63fXAFYS5tadcWTiNc2rskrNLrfH1N +# s0vgSZFoQxYBFKI159E8oQQ1SKbTEubZ/B9kmHPhprHya08+VVzxC88pOEvz68nA +# 82oEM09584aILqYmj8Pj7h/kmZNzuEL7WiwFa/U1hX+XiWfLIJQsAHBla0i7QRF2 +# de8/VSF0XXFa2kBQ6aiTsiLyKPNbaNtbcucaUdn6vVUS5izWOXM95BSkFSKdE45O +# q3FForNJXjBvSCpwcP36WklaHL+aHu1upIhCTUkzTHMh8b86WmjRUqbrnvdyR2yd +# I5l1OqcMBjkpPpIV6wcc+KY/RH2xvVuuoHjlUjwq2bHiNoX+W1scCpnA8YTs2d50 +# jDHUgwUo+ciwpffH0Riq132NFmrH3r67VaN3TuBxjI8SIZM58WEDkbeoriDk3hxU +# 8ZWV7b8AW6oyVBGfM06UgkfMb58h+tJPrFx8VI/WLq1dTqMfZOm5cuclMnUHs2uq +# rRNtnV8UfidPBL4ZHkTcClQbCoz0UbLhkiDvIS00Dn+BBcxw/TKqVL4Oaz3bkMSs +# M46LciTeucHY9ExRVt3zy7i149sd+F4QozPqn7FrSVHXmem3r7bjyHTxOgqxRCVa +# 18Vtx7P/8bYSBeS+WHCKcliFCecspusCDSlnRUjZwyPdP0VHxaZg2unjHY3rMYIa +# tTCCGrECAQEwfTBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIElu +# Yy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgQ29kZSBTaWduaW5nIFJT +# QTQwOTYgU0hBMzg0IDIwMjEgQ0ExAhAHHxQbizANJfMU6yMM0NHdMA0GCWCGSAFl +# AwQCAQUAoIHIMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcC +# AQsxDjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJBDEiBCBnAZ6P7YvTwq0fbF62 +# o7E75R0LxsW5OtyYiFESQckLhjBcBgorBgEEAYI3AgEMMU4wTKBGgEQAQgB1AGkA +# bAB0ADoAIABSAGUAbABlAGEAcwBlAF8AdgAzAC4AMQAxAC4ANABfADIAMAAyADMA +# MAA2ADAANwAuADAAMaECgAAwDQYJKoZIhvcNAQEBBQAEggIAVdxtEr9NH8SoVTzT +# o/jdr3t1yqExSecge3YGCu9USfMqLtmCKzG5r2rf3xZkJ6CpvmHwji3FUY6Hl991 +# Ttd0eEEpjeEse9gotnojgHTQACJntGuPcK+65jIQYNvp3JIuczjTW0JjWkJf4lqI +# hVS6rEc00D/0NsUF9BbNkjNZ0AUQeOWe2WZJnqRRFN4U3pToN51NDjpEtRjlNTkc +# SzoNO7ZyEsSXkNenlgbgS1yXEQ8v4bbnbPyyL+2yWMG1QsLv6M3OV0kXx9aow1r5 +# gZ1mCjBkbtWKH58WVBoepUaPYTjFBWCT2pDrorbg6cguwBdyz7s8X+WlCD4ycFfW +# o95x7u1W9RwPPPppszr8Pd4jZSbEXEQ/G9Ke5NvTvNmK93b7/kySfNYfwW2meP6E +# JIc0R9DMSZlK+ChtU5mmvo4e6YQTLXIXQhPIz7jVNlUjXMJX7WALjE72EDdC5MpQ +# ygW7wue6EhjlUVXT4pEIySCGaXxUzRi1oh+Q+Jbe3rDvhSPZUWzCqEtOkJ35dLYh +# D9Rahi2BM1qaepfu1wVtSXbVbc0SDPjloojEmTyDnk61u5epo0E0oHqNAU8t1ZTN +# +Guptl/agMp52uRsaC5Bi276icqRtclfx9E4SfJEiw7xRlImCclMpw2dRsyzIrpb +# MKpWDAno4rClgYS3M9lqQ71RlXehghc+MIIXOgYKKwYBBAGCNwMDATGCFyowghcm +# BgkqhkiG9w0BBwKgghcXMIIXEwIBAzEPMA0GCWCGSAFlAwQCAQUAMHgGCyqGSIb3 +# DQEJEAEEoGkEZzBlAgEBBglghkgBhv1sBwEwMTANBglghkgBZQMEAgEFAAQgsPGH +# UIiYgGXi/94WNZrP+V1kV/B5SVJn3ck+XzTJ0aACEQCJ79BpOkCDCW06IgZOU3EQ +# GA8yMDIzMDYwNzA1NTc0NFqgghMHMIIGwDCCBKigAwIBAgIQDE1pckuU+jwqSj0p +# B4A9WjANBgkqhkiG9w0BAQsFADBjMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGln +# aUNlcnQsIEluYy4xOzA5BgNVBAMTMkRpZ2lDZXJ0IFRydXN0ZWQgRzQgUlNBNDA5 +# NiBTSEEyNTYgVGltZVN0YW1waW5nIENBMB4XDTIyMDkyMTAwMDAwMFoXDTMzMTEy +# MTIzNTk1OVowRjELMAkGA1UEBhMCVVMxETAPBgNVBAoTCERpZ2lDZXJ0MSQwIgYD +# VQQDExtEaWdpQ2VydCBUaW1lc3RhbXAgMjAyMiAtIDIwggIiMA0GCSqGSIb3DQEB +# AQUAA4ICDwAwggIKAoICAQDP7KUmOsap8mu7jcENmtuh6BSFdDMaJqzQHFUeHjZt +# vJJVDGH0nQl3PRWWCC9rZKT9BoMW15GSOBwxApb7crGXOlWvM+xhiummKNuQY1y9 +# iVPgOi2Mh0KuJqTku3h4uXoW4VbGwLpkU7sqFudQSLuIaQyIxvG+4C99O7HKU41A +# gx7ny3JJKB5MgB6FVueF7fJhvKo6B332q27lZt3iXPUv7Y3UTZWEaOOAy2p50dIQ +# kUYp6z4m8rSMzUy5Zsi7qlA4DeWMlF0ZWr/1e0BubxaompyVR4aFeT4MXmaMGgok +# vpyq0py2909ueMQoP6McD1AGN7oI2TWmtR7aeFgdOej4TJEQln5N4d3CraV++C0b +# H+wrRhijGfY59/XBT3EuiQMRoku7mL/6T+R7Nu8GRORV/zbq5Xwx5/PCUsTmFnta +# fqUlc9vAapkhLWPlWfVNL5AfJ7fSqxTlOGaHUQhr+1NDOdBk+lbP4PQK5hRtZHi7 +# mP2Uw3Mh8y/CLiDXgazT8QfU4b3ZXUtuMZQpi+ZBpGWUwFjl5S4pkKa3YWT62SBs +# GFFguqaBDwklU/G/O+mrBw5qBzliGcnWhX8T2Y15z2LF7OF7ucxnEweawXjtxojI +# sG4yeccLWYONxu71LHx7jstkifGxxLjnU15fVdJ9GSlZA076XepFcxyEftfO4tQ6 +# dwIDAQABo4IBizCCAYcwDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwFgYD +# VR0lAQH/BAwwCgYIKwYBBQUHAwgwIAYDVR0gBBkwFzAIBgZngQwBBAIwCwYJYIZI +# AYb9bAcBMB8GA1UdIwQYMBaAFLoW2W1NhS9zKXaaL3WMaiCPnshvMB0GA1UdDgQW +# BBRiit7QYfyPMRTtlwvNPSqUFN9SnDBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8v +# Y3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRSU0E0MDk2U0hBMjU2 +# VGltZVN0YW1waW5nQ0EuY3JsMIGQBggrBgEFBQcBAQSBgzCBgDAkBggrBgEFBQcw +# AYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMFgGCCsGAQUFBzAChkxodHRwOi8v +# Y2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRSU0E0MDk2U0hB +# MjU2VGltZVN0YW1waW5nQ0EuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQBVqioa80bz +# eFc3MPx140/WhSPx/PmVOZsl5vdyipjDd9Rk/BX7NsJJUSx4iGNVCUY5APxp1Mqb +# KfujP8DJAJsTHbCYidx48s18hc1Tna9i4mFmoxQqRYdKmEIrUPwbtZ4IMAn65C3X +# CYl5+QnmiM59G7hqopvBU2AJ6KO4ndetHxy47JhB8PYOgPvk/9+dEKfrALpfSo8a +# OlK06r8JSRU1NlmaD1TSsht/fl4JrXZUinRtytIFZyt26/+YsiaVOBmIRBTlClmi +# a+ciPkQh0j8cwJvtfEiy2JIMkU88ZpSvXQJT657inuTTH4YBZJwAwuladHUNPeF5 +# iL8cAZfJGSOA1zZaX5YWsWMMxkZAO85dNdRZPkOaGK7DycvD+5sTX2q1x+DzBcNZ +# 3ydiK95ByVO5/zQQZ/YmMph7/lxClIGUgp2sCovGSxVK05iQRWAzgOAj3vgDpPZF +# R+XOuANCR+hBNnF3rf2i6Jd0Ti7aHh2MWsgemtXC8MYiqE+bvdgcmlHEL5r2X6cn +# l7qWLoVXwGDneFZ/au/ClZpLEQLIgpzJGgV8unG1TnqZbPTontRamMifv427GFxD +# 9dAq6OJi7ngE273R+1sKqHB+8JeEeOMIA11HLGOoJTiXAdI/Otrl5fbmm9x+LMz/ +# F0xNAKLY1gEOuIvu5uByVYksJxlh9ncBjDCCBq4wggSWoAMCAQICEAc2N7ckVHzY +# R6z9KGYqXlswDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMCVVMxFTATBgNVBAoT +# DERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UE +# AxMYRGlnaUNlcnQgVHJ1c3RlZCBSb290IEc0MB4XDTIyMDMyMzAwMDAwMFoXDTM3 +# MDMyMjIzNTk1OVowYzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ +# bmMuMTswOQYDVQQDEzJEaWdpQ2VydCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hBMjU2 +# IFRpbWVTdGFtcGluZyBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB +# AMaGNQZJs8E9cklRVcclA8TykTepl1Gh1tKD0Z5Mom2gsMyD+Vr2EaFEFUJfpIjz +# aPp985yJC3+dH54PMx9QEwsmc5Zt+FeoAn39Q7SE2hHxc7Gz7iuAhIoiGN/r2j3E +# F3+rGSs+QtxnjupRPfDWVtTnKC3r07G1decfBmWNlCnT2exp39mQh0YAe9tEQYnc +# fGpXevA3eZ9drMvohGS0UvJ2R/dhgxndX7RUCyFobjchu0CsX7LeSn3O9TkSZ+8O +# pWNs5KbFHc02DVzV5huowWR0QKfAcsW6Th+xtVhNef7Xj3OTrCw54qVI1vCwMROp +# VymWJy71h6aPTnYVVSZwmCZ/oBpHIEPjQ2OAe3VuJyWQmDo4EbP29p7mO1vsgd4i +# FNmCKseSv6De4z6ic/rnH1pslPJSlRErWHRAKKtzQ87fSqEcazjFKfPKqpZzQmif +# tkaznTqj1QPgv/CiPMpC3BhIfxQ0z9JMq++bPf4OuGQq+nUoJEHtQr8FnGZJUlD0 +# UfM2SU2LINIsVzV5K6jzRWC8I41Y99xh3pP+OcD5sjClTNfpmEpYPtMDiP6zj9Ne +# S3YSUZPJjAw7W4oiqMEmCPkUEBIDfV8ju2TjY+Cm4T72wnSyPx4JduyrXUZ14mCj +# WAkBKAAOhFTuzuldyF4wEr1GnrXTdrnSDmuZDNIztM2xAgMBAAGjggFdMIIBWTAS +# BgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBS6FtltTYUvcyl2mi91jGogj57I +# bzAfBgNVHSMEGDAWgBTs1+OC0nFdZEzfLmc/57qYrhwPTzAOBgNVHQ8BAf8EBAMC +# AYYwEwYDVR0lBAwwCgYIKwYBBQUHAwgwdwYIKwYBBQUHAQEEazBpMCQGCCsGAQUF +# BzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQQYIKwYBBQUHMAKGNWh0dHA6 +# Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRSb290RzQuY3J0 +# MEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdp +# Q2VydFRydXN0ZWRSb290RzQuY3JsMCAGA1UdIAQZMBcwCAYGZ4EMAQQCMAsGCWCG +# SAGG/WwHATANBgkqhkiG9w0BAQsFAAOCAgEAfVmOwJO2b5ipRCIBfmbW2CFC4bAY +# LhBNE88wU86/GPvHUF3iSyn7cIoNqilp/GnBzx0H6T5gyNgL5Vxb122H+oQgJTQx +# Z822EpZvxFBMYh0MCIKoFr2pVs8Vc40BIiXOlWk/R3f7cnQU1/+rT4osequFzUNf +# 7WC2qk+RZp4snuCKrOX9jLxkJodskr2dfNBwCnzvqLx1T7pa96kQsl3p/yhUifDV +# inF2ZdrM8HKjI/rAJ4JErpknG6skHibBt94q6/aesXmZgaNWhqsKRcnfxI2g55j7 +# +6adcq/Ex8HBanHZxhOACcS2n82HhyS7T6NJuXdmkfFynOlLAlKnN36TU6w7HQhJ +# D5TNOXrd/yVjmScsPT9rp/Fmw0HNT7ZAmyEhQNC3EyTN3B14OuSereU0cZLXJmvk +# OHOrpgFPvT87eK1MrfvElXvtCl8zOYdBeHo46Zzh3SP9HSjTx/no8Zhf+yvYfvJG +# nXUsHicsJttvFXseGYs2uJPU5vIXmVnKcPA3v5gA3yAWTyf7YGcWoWa63VXAOimG +# sJigK+2VQbc61RWYMbRiCQ8KvYHZE/6/pNHzV9m8BPqC3jLfBInwAM1dwvnQI38A +# C+R2AibZ8GV2QqYphwlHK+Z/GqSFD/yYlvZVVCsfgPrA8g4r5db7qS9EFUrnEw4d +# 2zc4GqEr9u3WfPwwggWNMIIEdaADAgECAhAOmxiO+dAt5+/bUOIIQBhaMA0GCSqG +# SIb3DQEBDAUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMx +# GTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFz +# c3VyZWQgSUQgUm9vdCBDQTAeFw0yMjA4MDEwMDAwMDBaFw0zMTExMDkyMzU5NTla +# MGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsT +# EHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9v +# dCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL/mkHNo3rvkXUo8 +# MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3EMB/zG6Q4FutWxpdtHauy +# efLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKyunWZanMylNEQRBAu34Lz +# B4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsFxl7sWxq868nPzaw0QF+x +# embud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU15zHL2pNe3I6PgNq2kZhA +# kHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJBMtfbBHMqbpEBfCFM1Lyu +# GwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObURWBf3JFxGj2T3wWmIdph2 +# PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6nj3cAORFJYm2mkQZK37A +# lLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxBYKqxYxhElRp2Yn72gLD7 +# 6GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5SUUd0viastkF13nqsX40/ +# ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+xq4aLT8LWRV+dIPyhHsXA +# j6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjggE6MIIBNjAPBgNVHRMBAf8EBTAD +# AQH/MB0GA1UdDgQWBBTs1+OC0nFdZEzfLmc/57qYrhwPTzAfBgNVHSMEGDAWgBRF +# 66Kv9JLLgjEtUYunpyGd823IDzAOBgNVHQ8BAf8EBAMCAYYweQYIKwYBBQUHAQEE +# bTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQwYIKwYB +# BQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3Vy +# ZWRJRFJvb3RDQS5jcnQwRQYDVR0fBD4wPDA6oDigNoY0aHR0cDovL2NybDMuZGln +# aWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDARBgNVHSAECjAI +# MAYGBFUdIAAwDQYJKoZIhvcNAQEMBQADggEBAHCgv0NcVec4X6CjdBs9thbX979X +# B72arKGHLOyFXqkauyL4hxppVCLtpIh3bb0aFPQTSnovLbc47/T/gLn4offyct4k +# vFIDyE7QKt76LVbP+fT3rDB6mouyXtTP0UNEm0Mh65ZyoUi0mcudT6cGAxN3J0TU +# 53/oWajwvy8LpunyNDzs9wPHh6jSTEAZNUZqaVSwuKFWjuyk1T3osdz9HNj0d1pc +# VIxv76FQPfx2CWiEn2/K2yCNNWAcAgPLILCsWKAOQGPFmCLBsln1VWvPJ6tsds5v +# Iy30fnFqI2si/xK4VC0nftg62fC2h5b9W9FcrBjDTZ9ztwGpn1eqXijiuZQxggN2 +# MIIDcgIBATB3MGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5j +# LjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBHNCBSU0E0MDk2IFNIQTI1NiBU +# aW1lU3RhbXBpbmcgQ0ECEAxNaXJLlPo8Kko9KQeAPVowDQYJYIZIAWUDBAIBBQCg +# gdEwGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEEMBwGCSqGSIb3DQEJBTEPFw0y +# MzA2MDcwNTU3NDRaMCsGCyqGSIb3DQEJEAIMMRwwGjAYMBYEFPOHIk2GM4KSNamU +# vL2Plun+HHxzMC8GCSqGSIb3DQEJBDEiBCAZCWWaBjTHAZnsndSxyxCaZSOrTyqo +# O35hv3VOlS9KHDA3BgsqhkiG9w0BCRACLzEoMCYwJDAiBCDH9OG+MiiJIKviJjq+ +# GsT8T+Z4HC1k0EyAdVegI7W2+jANBgkqhkiG9w0BAQEFAASCAgBt92vHxbHXh4Z2 +# yl+aTo7PltgPhZhoQCWg+gDSyySEqkDN+kTuoW3ROuMjR1JR0htJOwVqnmI/enhW +# r8VJiDKfGOGupHEfzAlMaIIC+K+C3sSoeaRR1aiOWrUA/oPpJIgwXyfo65Hf07qf +# wdn//4y5zv6oMdHNtpSfFgibze5BjNRAgOUxl9rvKArEN7B+WTCnvLWw/EJe48MQ +# B0zUbVFIORQUHlLnCL07JGRSN5bHaMtnn5eEwZFC9522kJaHyLrmfeP4jZLMhjhn +# fGxv69HVzggM8CpjpQA8l8hh6Il48TDMZpdqkxwjoRmJVwt3hwTrfuE11NFrXEAD +# 8dAAta6N/M722c3BE6UxM2R4QXyV05BL6e4jVJm1aR1ebUVS4nZVZ/jbCexR/+vx +# mfSh1SezU3KlgRMDrLF+El883BFoe/99p4/QjjnELhn41lPPAYGefhMI9ioYZULQ +# xMyG6qIPA8s2tnYIL/AKvh7SUgFVtOsTKbTFXMMr20sipBQQFUOb8ZD+8u4Iyc4M +# UC4d2S6z9zwlPbSr1lk9m3R8rl+j2/VkB1S21nqda3xWFk/+n/2oEJe4gUkCiQxs +# qFaykkcAhWYdZVRRNM89ZF23DeYAEkUEaD2M1ld0CZNtvtPNmv/NZV/Xbb3H0RPR +# yDBB2JQI1BbEjl7HWy616MUsAqWA+Q== # SIG # End signature block diff --git a/venv1/Scripts/activate b/venv1/Scripts/activate index 2d13673f..e7de9788 100644 --- a/venv1/Scripts/activate +++ b/venv1/Scripts/activate @@ -1,5 +1,5 @@ # This file must be used with "source bin/activate" *from bash* -# You cannot run it directly +# you cannot run it directly deactivate () { # reset old environment variables @@ -14,10 +14,12 @@ deactivate () { unset _OLD_VIRTUAL_PYTHONHOME fi - # Call hash to forget past locations. Without forgetting - # past locations the $PATH changes we made may not be respected. - # See "man bash" for more details. hash is usually a builtin of your shell - hash -r 2> /dev/null + # This should detect bash and zsh, which have a hash command that must + # be called to get it to forget past commands. Without forgetting + # past commands the $PATH changes we made may not be respected + if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then + hash -r 2> /dev/null + fi if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then PS1="${_OLD_VIRTUAL_PS1:-}" @@ -36,27 +38,13 @@ deactivate () { # unset irrelevant variables deactivate nondestructive -# on Windows, a path can contain colons and backslashes and has to be converted: -case "$(uname)" in - CYGWIN*|MSYS*|MINGW*) - # transform D:\path\to\venv to /d/path/to/venv on MSYS and MINGW - # and to /cygdrive/d/path/to/venv on Cygwin - VIRTUAL_ENV=$(cygpath 'C:\Users\Pooja\Downloads\Achievement-Management-System\venv1') - export VIRTUAL_ENV - ;; - *) - # use the path as-is - export VIRTUAL_ENV='C:\Users\Pooja\Downloads\Achievement-Management-System\venv1' - ;; -esac +VIRTUAL_ENV="C:\Users\D S MOHANTO JULLIET\Achievement-Management-System\venv1" +export VIRTUAL_ENV _OLD_VIRTUAL_PATH="$PATH" -PATH="$VIRTUAL_ENV/"Scripts":$PATH" +PATH="$VIRTUAL_ENV/Scripts:$PATH" export PATH -VIRTUAL_ENV_PROMPT=venv1 -export VIRTUAL_ENV_PROMPT - # unset PYTHONHOME if set # this will fail if PYTHONHOME is set to the empty string (which is bad anyway) # could use `if (set -u; : $PYTHONHOME) ;` in bash @@ -67,10 +55,15 @@ fi if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then _OLD_VIRTUAL_PS1="${PS1:-}" - PS1="("venv1") ${PS1:-}" + PS1="(venv1) ${PS1:-}" export PS1 + VIRTUAL_ENV_PROMPT="(venv1) " + export VIRTUAL_ENV_PROMPT fi -# Call hash to forget past commands. Without forgetting +# This should detect bash and zsh, which have a hash command that must +# be called to get it to forget past commands. Without forgetting # past commands the $PATH changes we made may not be respected -hash -r 2> /dev/null +if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then + hash -r 2> /dev/null +fi diff --git a/venv1/Scripts/activate.bat b/venv1/Scripts/activate.bat index 0f3f36cd..b2f66537 100644 --- a/venv1/Scripts/activate.bat +++ b/venv1/Scripts/activate.bat @@ -8,15 +8,15 @@ if defined _OLD_CODEPAGE ( "%SystemRoot%\System32\chcp.com" 65001 > nul ) -set "VIRTUAL_ENV=C:\Users\Pooja\Downloads\Achievement-Management-System\venv1" +set VIRTUAL_ENV=C:\Users\D S MOHANTO JULLIET\Achievement-Management-System\venv1 if not defined PROMPT set PROMPT=$P$G if defined _OLD_VIRTUAL_PROMPT set PROMPT=%_OLD_VIRTUAL_PROMPT% if defined _OLD_VIRTUAL_PYTHONHOME set PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME% -set "_OLD_VIRTUAL_PROMPT=%PROMPT%" -set "PROMPT=(venv1) %PROMPT%" +set _OLD_VIRTUAL_PROMPT=%PROMPT% +set PROMPT=(venv1) %PROMPT% if defined PYTHONHOME set _OLD_VIRTUAL_PYTHONHOME=%PYTHONHOME% set PYTHONHOME= @@ -24,8 +24,8 @@ set PYTHONHOME= if defined _OLD_VIRTUAL_PATH set PATH=%_OLD_VIRTUAL_PATH% if not defined _OLD_VIRTUAL_PATH set _OLD_VIRTUAL_PATH=%PATH% -set "PATH=%VIRTUAL_ENV%\Scripts;%PATH%" -set "VIRTUAL_ENV_PROMPT=venv1" +set PATH=%VIRTUAL_ENV%\Scripts;%PATH% +set VIRTUAL_ENV_PROMPT=(venv1) :END if defined _OLD_CODEPAGE ( diff --git a/venv1/Scripts/pip.exe b/venv1/Scripts/pip.exe index 94514627..74156a66 100644 Binary files a/venv1/Scripts/pip.exe and b/venv1/Scripts/pip.exe differ diff --git a/venv1/Scripts/pip3.exe b/venv1/Scripts/pip3.exe index 94514627..74156a66 100644 Binary files a/venv1/Scripts/pip3.exe and b/venv1/Scripts/pip3.exe differ diff --git a/venv1/Scripts/python.exe b/venv1/Scripts/python.exe index 29c8442f..0c68b4c6 100644 Binary files a/venv1/Scripts/python.exe and b/venv1/Scripts/python.exe differ diff --git a/venv1/Scripts/pythonw.exe b/venv1/Scripts/pythonw.exe index f73174c1..01861b43 100644 Binary files a/venv1/Scripts/pythonw.exe and b/venv1/Scripts/pythonw.exe differ diff --git a/venv1/pyvenv.cfg b/venv1/pyvenv.cfg index 11f91eec..849037da 100644 --- a/venv1/pyvenv.cfg +++ b/venv1/pyvenv.cfg @@ -1,5 +1,5 @@ -home = C:\Users\Pooja\AppData\Local\Microsoft\WindowsApps\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0 +home = C:\Users\D S MOHANTO JULLIET\AppData\Local\Programs\Python\Python311 include-system-site-packages = false -version = 3.13.12 -executable = C:\Users\Pooja\AppData\Local\Microsoft\WindowsApps\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\python.exe -command = C:\Users\Pooja\AppData\Local\Microsoft\WindowsApps\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\python.exe -m venv C:\Users\Pooja\Downloads\Achievement-Management-System\venv1 +version = 3.11.4 +executable = C:\Users\D S MOHANTO JULLIET\AppData\Local\Programs\Python\Python311\python.exe +command = C:\Users\D S MOHANTO JULLIET\AppData\Local\Programs\Python\Python311\python.exe -m venv C:\Users\D S MOHANTO JULLIET\Achievement-Management-System\venv1