From e558a08fff299de2bfe69b411a11c3629d0cdb1c Mon Sep 17 00:00:00 2001 From: Marco Costa Date: Fri, 18 Sep 2026 21:32:56 -0300 Subject: [PATCH] ghgfbnvb --- .../util/__pycache__/timeout.cpython-311.pyc | Bin 12099 -> 0 bytes .../util/__pycache__/url.cpython-311.pyc | Bin 17849 -> 0 bytes .../util/__pycache__/util.cpython-311.pyc | Bin 2185 -> 0 bytes .../util/__pycache__/wait.cpython-311.pyc | Bin 3756 -> 0 bytes .../pip/_vendor/urllib3/util/connection.py | 137 - .../pip/_vendor/urllib3/util/proxy.py | 43 - .../pip/_vendor/urllib3/util/request.py | 254 - .../pip/_vendor/urllib3/util/response.py | 101 - .../pip/_vendor/urllib3/util/retry.py | 557 -- .../pip/_vendor/urllib3/util/ssl_.py | 477 -- .../urllib3/util/ssl_match_hostname.py | 153 - .../pip/_vendor/urllib3/util/ssltransport.py | 271 - .../pip/_vendor/urllib3/util/timeout.py | 275 - .../pip/_vendor/urllib3/util/url.py | 469 -- .../pip/_vendor/urllib3/util/util.py | 42 - .../pip/_vendor/urllib3/util/wait.py | 124 - .../site-packages/pip/_vendor/vendor.txt | 18 - .../lib/python3.11/site-packages/pip/py.typed | 4 - .../site-packages/pkg_resources/__init__.py | 3282 ---------- .../__pycache__/__init__.cpython-311.pyc | Bin 156112 -> 0 bytes .../pkg_resources/_vendor/__init__.py | 0 .../__pycache__/__init__.cpython-311.pyc | Bin 198 -> 0 bytes .../typing_extensions.cpython-311.pyc | Bin 97415 -> 0 bytes .../_vendor/__pycache__/zipp.cpython-311.pyc | Bin 15991 -> 0 bytes .../_vendor/importlib_resources/__init__.py | 36 - .../__pycache__/__init__.cpython-311.pyc | Bin 832 -> 0 bytes .../__pycache__/_adapters.cpython-311.pyc | Bin 10749 -> 0 bytes .../__pycache__/_common.cpython-311.pyc | Bin 4276 -> 0 bytes .../__pycache__/_compat.cpython-311.pyc | Bin 5561 -> 0 bytes .../__pycache__/_itertools.cpython-311.pyc | Bin 1394 -> 0 bytes .../__pycache__/_legacy.cpython-311.pyc | Bin 6492 -> 0 bytes .../__pycache__/abc.cpython-311.pyc | Bin 7493 -> 0 bytes .../__pycache__/readers.cpython-311.pyc | Bin 8367 -> 0 bytes .../__pycache__/simple.cpython-311.pyc | Bin 6389 -> 0 bytes .../_vendor/importlib_resources/_adapters.py | 170 - .../_vendor/importlib_resources/_common.py | 104 - .../_vendor/importlib_resources/_compat.py | 98 - .../_vendor/importlib_resources/_itertools.py | 35 - .../_vendor/importlib_resources/_legacy.py | 121 - .../_vendor/importlib_resources/abc.py | 137 - .../_vendor/importlib_resources/readers.py | 122 - .../_vendor/importlib_resources/simple.py | 116 - .../pkg_resources/_vendor/jaraco/__init__.py | 0 .../__pycache__/__init__.cpython-311.pyc | Bin 205 -> 0 bytes .../__pycache__/context.cpython-311.pyc | Bin 10980 -> 0 bytes .../__pycache__/functools.cpython-311.pyc | Bin 20291 -> 0 bytes .../pkg_resources/_vendor/jaraco/context.py | 253 - .../pkg_resources/_vendor/jaraco/functools.py | 525 -- .../_vendor/jaraco/text/__init__.py | 599 -- .../text/__pycache__/__init__.cpython-311.pyc | Bin 26608 -> 0 bytes .../_vendor/more_itertools/__init__.py | 6 - .../__pycache__/__init__.cpython-311.pyc | Bin 377 -> 0 bytes .../__pycache__/more.cpython-311.pyc | Bin 169499 -> 0 bytes .../__pycache__/recipes.cpython-311.pyc | Bin 33519 -> 0 bytes .../_vendor/more_itertools/more.py | 4346 ------------ .../_vendor/more_itertools/recipes.py | 841 --- .../_vendor/packaging/__about__.py | 26 - .../_vendor/packaging/__init__.py | 25 - .../__pycache__/__about__.cpython-311.pyc | Bin 649 -> 0 bytes .../__pycache__/__init__.cpython-311.pyc | Bin 570 -> 0 bytes .../__pycache__/_manylinux.cpython-311.pyc | Bin 13236 -> 0 bytes .../__pycache__/_musllinux.cpython-311.pyc | Bin 8004 -> 0 bytes .../__pycache__/_structures.cpython-311.pyc | Bin 3692 -> 0 bytes .../__pycache__/markers.cpython-311.pyc | Bin 16541 -> 0 bytes .../__pycache__/requirements.cpython-311.pyc | Bin 7656 -> 0 bytes .../__pycache__/specifiers.cpython-311.pyc | Bin 34370 -> 0 bytes .../__pycache__/tags.cpython-311.pyc | Bin 21355 -> 0 bytes .../__pycache__/utils.cpython-311.pyc | Bin 6690 -> 0 bytes .../__pycache__/version.cpython-311.pyc | Bin 21882 -> 0 bytes .../_vendor/packaging/_manylinux.py | 301 - .../_vendor/packaging/_musllinux.py | 136 - .../_vendor/packaging/_structures.py | 61 - .../_vendor/packaging/markers.py | 304 - .../_vendor/packaging/requirements.py | 146 - .../_vendor/packaging/specifiers.py | 802 --- .../pkg_resources/_vendor/packaging/tags.py | 487 -- .../pkg_resources/_vendor/packaging/utils.py | 136 - .../_vendor/packaging/version.py | 504 -- .../_vendor/platformdirs/__init__.py | 342 - .../_vendor/platformdirs/__main__.py | 46 - .../__pycache__/__init__.cpython-311.pyc | Bin 12830 -> 0 bytes .../__pycache__/__main__.cpython-311.pyc | Bin 2122 -> 0 bytes .../__pycache__/android.cpython-311.pyc | Bin 6364 -> 0 bytes .../__pycache__/api.cpython-311.pyc | Bin 7191 -> 0 bytes .../__pycache__/macos.cpython-311.pyc | Bin 4601 -> 0 bytes .../__pycache__/unix.cpython-311.pyc | Bin 11033 -> 0 bytes .../__pycache__/version.cpython-311.pyc | Bin 320 -> 0 bytes .../__pycache__/windows.cpython-311.pyc | Bin 9969 -> 0 bytes .../_vendor/platformdirs/android.py | 120 - .../pkg_resources/_vendor/platformdirs/api.py | 156 - .../_vendor/platformdirs/macos.py | 64 - .../_vendor/platformdirs/unix.py | 181 - .../_vendor/platformdirs/version.py | 4 - .../_vendor/platformdirs/windows.py | 184 - .../_vendor/pyparsing/__init__.py | 331 - .../__pycache__/__init__.cpython-311.pyc | Bin 8343 -> 0 bytes .../__pycache__/actions.cpython-311.pyc | Bin 8469 -> 0 bytes .../__pycache__/common.cpython-311.pyc | Bin 14791 -> 0 bytes .../__pycache__/core.cpython-311.pyc | Bin 277643 -> 0 bytes .../__pycache__/exceptions.cpython-311.pyc | Bin 12933 -> 0 bytes .../__pycache__/helpers.cpython-311.pyc | Bin 53634 -> 0 bytes .../__pycache__/results.cpython-311.pyc | Bin 36317 -> 0 bytes .../__pycache__/testing.cpython-311.pyc | Bin 19513 -> 0 bytes .../__pycache__/unicode.cpython-311.pyc | Bin 15371 -> 0 bytes .../__pycache__/util.cpython-311.pyc | Bin 14270 -> 0 bytes .../_vendor/pyparsing/actions.py | 207 - .../pkg_resources/_vendor/pyparsing/common.py | 424 -- .../pkg_resources/_vendor/pyparsing/core.py | 5814 ----------------- .../_vendor/pyparsing/diagram/__init__.py | 642 -- .../__pycache__/__init__.cpython-311.pyc | Bin 28006 -> 0 bytes .../_vendor/pyparsing/exceptions.py | 267 - .../_vendor/pyparsing/helpers.py | 1088 --- .../_vendor/pyparsing/results.py | 760 --- .../_vendor/pyparsing/testing.py | 331 - .../_vendor/pyparsing/unicode.py | 352 - .../pkg_resources/_vendor/pyparsing/util.py | 235 - .../_vendor/typing_extensions.py | 2209 ------- .../pkg_resources/_vendor/zipp.py | 329 - .../pkg_resources/extern/__init__.py | 81 - .../__pycache__/__init__.cpython-311.pyc | Bin 4321 -> 0 bytes .../python_dotenv-1.1.0.dist-info/INSTALLER | 1 - .../python_dotenv-1.1.0.dist-info/METADATA | 720 -- .../python_dotenv-1.1.0.dist-info/RECORD | 26 - .../python_dotenv-1.1.0.dist-info/REQUESTED | 0 .../python_dotenv-1.1.0.dist-info/WHEEL | 5 - .../entry_points.txt | 2 - .../licenses/LICENSE | 27 - .../top_level.txt | 1 - .../INSTALLER | 1 - .../METADATA | 299 - .../RECORD | 425 -- .../REQUESTED | 0 .../python_telegram_bot-21.10.dist-info/WHEEL | 4 - .../licenses/LICENSE | 619 -- .../licenses/LICENSE.dual | 792 --- .../licenses/LICENSE.lesser | 165 - .../setuptools-66.1.1.dist-info/INSTALLER | 1 - .../setuptools-66.1.1.dist-info/LICENSE | 19 - .../setuptools-66.1.1.dist-info/METADATA | 137 - .../setuptools-66.1.1.dist-info/RECORD | 484 -- .../setuptools-66.1.1.dist-info/REQUESTED | 0 .../setuptools-66.1.1.dist-info/WHEEL | 5 - .../entry_points.txt | 57 - .../setuptools-66.1.1.dist-info/top_level.txt | 4 - .../site-packages/setuptools/__init__.py | 268 - .../__pycache__/__init__.cpython-311.pyc | Bin 13926 -> 0 bytes .../_deprecation_warning.cpython-311.pyc | Bin 642 -> 0 bytes .../__pycache__/_entry_points.cpython-311.pyc | Bin 5199 -> 0 bytes .../__pycache__/_imp.cpython-311.pyc | Bin 3655 -> 0 bytes .../__pycache__/_importlib.cpython-311.pyc | Bin 1955 -> 0 bytes .../__pycache__/_itertools.cpython-311.pyc | Bin 1154 -> 0 bytes .../__pycache__/_path.cpython-311.pyc | Bin 1475 -> 0 bytes .../__pycache__/_reqs.cpython-311.pyc | Bin 1136 -> 0 bytes .../__pycache__/archive_util.cpython-311.pyc | Bin 10164 -> 0 bytes .../__pycache__/build_meta.cpython-311.pyc | Bin 28147 -> 0 bytes .../__pycache__/dep_util.cpython-311.pyc | Bin 1290 -> 0 bytes .../__pycache__/depends.cpython-311.pyc | Bin 7975 -> 0 bytes .../__pycache__/discovery.cpython-311.pyc | Bin 31128 -> 0 bytes .../__pycache__/dist.cpython-311.pyc | Bin 63795 -> 0 bytes .../__pycache__/errors.cpython-311.pyc | Bin 2951 -> 0 bytes .../__pycache__/extension.cpython-311.pyc | Bin 6807 -> 0 bytes .../__pycache__/glob.cpython-311.pyc | Bin 6564 -> 0 bytes .../__pycache__/installer.cpython-311.pyc | Bin 5614 -> 0 bytes .../__pycache__/launch.cpython-311.pyc | Bin 1530 -> 0 bytes .../__pycache__/logging.cpython-311.pyc | Bin 2097 -> 0 bytes .../__pycache__/monkey.cpython-311.pyc | Bin 7007 -> 0 bytes .../__pycache__/msvc.cpython-311.pyc | Bin 64180 -> 0 bytes .../__pycache__/namespaces.cpython-311.pyc | Bin 5662 -> 0 bytes .../__pycache__/package_index.cpython-311.pyc | Bin 62126 -> 0 bytes .../__pycache__/py34compat.cpython-311.pyc | Bin 717 -> 0 bytes .../__pycache__/sandbox.cpython-311.pyc | Bin 27333 -> 0 bytes .../__pycache__/unicode_utils.cpython-311.pyc | Bin 1819 -> 0 bytes .../__pycache__/version.cpython-311.pyc | Bin 437 -> 0 bytes .../__pycache__/wheel.cpython-311.pyc | Bin 15493 -> 0 bytes .../windows_support.cpython-311.pyc | Bin 1434 -> 0 bytes .../setuptools/_deprecation_warning.py | 7 - .../setuptools/_distutils/__init__.py | 14 - .../__pycache__/__init__.cpython-311.pyc | Bin 561 -> 0 bytes .../__pycache__/_collections.cpython-311.pyc | Bin 8531 -> 0 bytes .../__pycache__/_functools.cpython-311.pyc | Bin 863 -> 0 bytes .../__pycache__/_log.cpython-311.pyc | Bin 280 -> 0 bytes .../__pycache__/_macos_compat.cpython-311.pyc | Bin 572 -> 0 bytes .../__pycache__/_msvccompiler.cpython-311.pyc | Bin 25074 -> 0 bytes .../__pycache__/archive_util.cpython-311.pyc | Bin 10622 -> 0 bytes .../__pycache__/bcppcompiler.cpython-311.pyc | Bin 13448 -> 0 bytes .../__pycache__/ccompiler.cpython-311.pyc | Bin 46317 -> 0 bytes .../__pycache__/cmd.cpython-311.pyc | Bin 18841 -> 0 bytes .../__pycache__/config.cpython-311.pyc | Bin 6042 -> 0 bytes .../__pycache__/core.cpython-311.pyc | Bin 9932 -> 0 bytes .../cygwinccompiler.cpython-311.pyc | Bin 13626 -> 0 bytes .../__pycache__/debug.cpython-311.pyc | Bin 324 -> 0 bytes .../__pycache__/dep_util.cpython-311.pyc | Bin 3986 -> 0 bytes .../__pycache__/dir_util.cpython-311.pyc | Bin 10367 -> 0 bytes .../__pycache__/dist.cpython-311.pyc | Bin 55490 -> 0 bytes .../__pycache__/errors.cpython-311.pyc | Bin 6797 -> 0 bytes .../__pycache__/extension.cpython-311.pyc | Bin 10178 -> 0 bytes .../__pycache__/fancy_getopt.cpython-311.pyc | Bin 17237 -> 0 bytes .../__pycache__/file_util.cpython-311.pyc | Bin 10671 -> 0 bytes .../__pycache__/filelist.cpython-311.pyc | Bin 17611 -> 0 bytes .../__pycache__/log.cpython-311.pyc | Bin 2695 -> 0 bytes .../__pycache__/msvc9compiler.cpython-311.pyc | Bin 33560 -> 0 bytes .../__pycache__/msvccompiler.cpython-311.pyc | Bin 26972 -> 0 bytes .../__pycache__/py38compat.cpython-311.pyc | Bin 624 -> 0 bytes .../__pycache__/py39compat.cpython-311.pyc | Bin 992 -> 0 bytes .../__pycache__/spawn.cpython-311.pyc | Bin 4436 -> 0 bytes .../__pycache__/sysconfig.cpython-311.pyc | Bin 22073 -> 0 bytes .../__pycache__/text_file.cpython-311.pyc | Bin 11273 -> 0 bytes .../__pycache__/unixccompiler.cpython-311.pyc | Bin 16496 -> 0 bytes .../__pycache__/util.cpython-311.pyc | Bin 20847 -> 0 bytes .../__pycache__/version.cpython-311.pyc | Bin 11349 -> 0 bytes .../versionpredicate.cpython-311.pyc | Bin 7626 -> 0 bytes .../setuptools/_distutils/_collections.py | 194 - .../setuptools/_distutils/_functools.py | 20 - .../setuptools/_distutils/_log.py | 4 - .../setuptools/_distutils/_macos_compat.py | 12 - .../setuptools/_distutils/_msvccompiler.py | 572 -- .../setuptools/_distutils/archive_util.py | 280 - .../setuptools/_distutils/bcppcompiler.py | 408 -- .../setuptools/_distutils/ccompiler.py | 1220 ---- .../setuptools/_distutils/cmd.py | 435 -- .../setuptools/_distutils/command/__init__.py | 25 - .../__pycache__/__init__.cpython-311.pyc | Bin 544 -> 0 bytes .../_framework_compat.cpython-311.pyc | Bin 2785 -> 0 bytes .../command/__pycache__/bdist.cpython-311.pyc | Bin 6003 -> 0 bytes .../__pycache__/bdist_dumb.cpython-311.pyc | Bin 5723 -> 0 bytes .../__pycache__/bdist_rpm.cpython-311.pyc | Bin 23257 -> 0 bytes .../command/__pycache__/build.cpython-311.pyc | Bin 6058 -> 0 bytes .../__pycache__/build_clib.cpython-311.pyc | Bin 7766 -> 0 bytes .../__pycache__/build_ext.cpython-311.pyc | Bin 30276 -> 0 bytes .../__pycache__/build_py.cpython-311.pyc | Bin 17602 -> 0 bytes .../__pycache__/build_scripts.cpython-311.pyc | Bin 7856 -> 0 bytes .../command/__pycache__/check.cpython-311.pyc | Bin 7512 -> 0 bytes .../command/__pycache__/clean.cpython-311.pyc | Bin 3188 -> 0 bytes .../__pycache__/config.cpython-311.pyc | Bin 16225 -> 0 bytes .../__pycache__/install.cpython-311.pyc | Bin 29377 -> 0 bytes .../__pycache__/install_data.cpython-311.pyc | Bin 3765 -> 0 bytes .../install_egg_info.cpython-311.pyc | Bin 5220 -> 0 bytes .../install_headers.cpython-311.pyc | Bin 2353 -> 0 bytes .../__pycache__/install_lib.cpython-311.pyc | Bin 8674 -> 0 bytes .../install_scripts.cpython-311.pyc | Bin 3160 -> 0 bytes .../__pycache__/py37compat.cpython-311.pyc | Bin 1541 -> 0 bytes .../__pycache__/register.cpython-311.pyc | Bin 15559 -> 0 bytes .../command/__pycache__/sdist.cpython-311.pyc | Bin 23771 -> 0 bytes .../__pycache__/upload.cpython-311.pyc | Bin 10425 -> 0 bytes .../_distutils/command/_framework_compat.py | 55 - .../setuptools/_distutils/command/bdist.py | 157 - .../_distutils/command/bdist_dumb.py | 144 - .../_distutils/command/bdist_rpm.py | 615 -- .../setuptools/_distutils/command/build.py | 153 - .../_distutils/command/build_clib.py | 208 - .../_distutils/command/build_ext.py | 789 --- .../setuptools/_distutils/command/build_py.py | 407 -- .../_distutils/command/build_scripts.py | 173 - .../setuptools/_distutils/command/check.py | 151 - .../setuptools/_distutils/command/clean.py | 76 - .../setuptools/_distutils/command/config.py | 377 -- .../setuptools/_distutils/command/install.py | 814 --- .../_distutils/command/install_data.py | 84 - .../_distutils/command/install_egg_info.py | 92 - .../_distutils/command/install_headers.py | 45 - .../_distutils/command/install_lib.py | 238 - .../_distutils/command/install_scripts.py | 61 - .../_distutils/command/py37compat.py | 31 - .../setuptools/_distutils/command/register.py | 321 - .../setuptools/_distutils/command/sdist.py | 531 -- .../setuptools/_distutils/command/upload.py | 207 - .../setuptools/_distutils/config.py | 139 - .../setuptools/_distutils/core.py | 291 - .../setuptools/_distutils/cygwinccompiler.py | 358 - .../setuptools/_distutils/debug.py | 5 - .../setuptools/_distutils/dep_util.py | 96 - .../setuptools/_distutils/dir_util.py | 243 - .../setuptools/_distutils/dist.py | 1287 ---- .../setuptools/_distutils/errors.py | 127 - .../setuptools/_distutils/extension.py | 248 - .../setuptools/_distutils/fancy_getopt.py | 470 -- .../setuptools/_distutils/file_util.py | 249 - .../setuptools/_distutils/filelist.py | 371 -- .../setuptools/_distutils/log.py | 57 - .../setuptools/_distutils/msvc9compiler.py | 832 --- .../setuptools/_distutils/msvccompiler.py | 695 -- .../setuptools/_distutils/py38compat.py | 8 - .../setuptools/_distutils/py39compat.py | 22 - .../setuptools/_distutils/spawn.py | 109 - .../setuptools/_distutils/sysconfig.py | 552 -- .../setuptools/_distutils/text_file.py | 287 - .../setuptools/_distutils/unixccompiler.py | 401 -- .../setuptools/_distutils/util.py | 513 -- .../setuptools/_distutils/version.py | 358 - .../setuptools/_distutils/versionpredicate.py | 175 - .../site-packages/setuptools/_entry_points.py | 94 - .../site-packages/setuptools/_imp.py | 82 - .../site-packages/setuptools/_importlib.py | 47 - .../site-packages/setuptools/_itertools.py | 23 - .../site-packages/setuptools/_path.py | 29 - .../site-packages/setuptools/_reqs.py | 19 - .../setuptools/_vendor/__init__.py | 0 .../__pycache__/__init__.cpython-311.pyc | Bin 195 -> 0 bytes .../__pycache__/ordered_set.cpython-311.pyc | Bin 21781 -> 0 bytes .../typing_extensions.cpython-311.pyc | Bin 107612 -> 0 bytes .../_vendor/__pycache__/zipp.cpython-311.pyc | Bin 15988 -> 0 bytes .../_vendor/importlib_metadata/__init__.py | 1047 --- .../__pycache__/__init__.cpython-311.pyc | Bin 58234 -> 0 bytes .../__pycache__/_adapters.cpython-311.pyc | Bin 3847 -> 0 bytes .../__pycache__/_collections.cpython-311.pyc | Bin 2194 -> 0 bytes .../__pycache__/_compat.cpython-311.pyc | Bin 2716 -> 0 bytes .../__pycache__/_functools.cpython-311.pyc | Bin 3634 -> 0 bytes .../__pycache__/_itertools.cpython-311.pyc | Bin 2597 -> 0 bytes .../__pycache__/_meta.cpython-311.pyc | Bin 3001 -> 0 bytes .../__pycache__/_text.cpython-311.pyc | Bin 4392 -> 0 bytes .../_vendor/importlib_metadata/_adapters.py | 68 - .../importlib_metadata/_collections.py | 30 - .../_vendor/importlib_metadata/_compat.py | 71 - .../_vendor/importlib_metadata/_functools.py | 104 - .../_vendor/importlib_metadata/_itertools.py | 73 - .../_vendor/importlib_metadata/_meta.py | 48 - .../_vendor/importlib_metadata/_text.py | 99 - .../_vendor/importlib_resources/__init__.py | 36 - .../__pycache__/__init__.cpython-311.pyc | Bin 829 -> 0 bytes .../__pycache__/_adapters.cpython-311.pyc | Bin 10746 -> 0 bytes .../__pycache__/_common.cpython-311.pyc | Bin 4273 -> 0 bytes .../__pycache__/_compat.cpython-311.pyc | Bin 5558 -> 0 bytes .../__pycache__/_itertools.cpython-311.pyc | Bin 1391 -> 0 bytes .../__pycache__/_legacy.cpython-311.pyc | Bin 6489 -> 0 bytes .../__pycache__/abc.cpython-311.pyc | Bin 7490 -> 0 bytes .../__pycache__/readers.cpython-311.pyc | Bin 8364 -> 0 bytes .../__pycache__/simple.cpython-311.pyc | Bin 6386 -> 0 bytes .../_vendor/importlib_resources/_adapters.py | 170 - .../_vendor/importlib_resources/_common.py | 104 - .../_vendor/importlib_resources/_compat.py | 98 - .../_vendor/importlib_resources/_itertools.py | 35 - .../_vendor/importlib_resources/_legacy.py | 121 - .../_vendor/importlib_resources/abc.py | 137 - .../_vendor/importlib_resources/readers.py | 122 - .../_vendor/importlib_resources/simple.py | 116 - .../setuptools/_vendor/jaraco/__init__.py | 0 .../__pycache__/__init__.cpython-311.pyc | Bin 202 -> 0 bytes .../__pycache__/context.cpython-311.pyc | Bin 10977 -> 0 bytes .../__pycache__/functools.cpython-311.pyc | Bin 20282 -> 0 bytes .../setuptools/_vendor/jaraco/context.py | 253 - .../setuptools/_vendor/jaraco/functools.py | 525 -- .../_vendor/jaraco/text/__init__.py | 599 -- .../text/__pycache__/__init__.cpython-311.pyc | Bin 26596 -> 0 bytes .../_vendor/more_itertools/__init__.py | 4 - .../__pycache__/__init__.cpython-311.pyc | Bin 295 -> 0 bytes .../__pycache__/more.cpython-311.pyc | Bin 149182 -> 0 bytes .../__pycache__/recipes.cpython-311.pyc | Bin 23764 -> 0 bytes .../setuptools/_vendor/more_itertools/more.py | 3824 ----------- .../_vendor/more_itertools/recipes.py | 620 -- .../setuptools/_vendor/ordered_set.py | 488 -- .../setuptools/_vendor/packaging/__about__.py | 26 - .../setuptools/_vendor/packaging/__init__.py | 25 - .../__pycache__/__about__.cpython-311.pyc | Bin 646 -> 0 bytes 353 files changed, 60823 deletions(-) delete mode 100755 venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/__pycache__/timeout.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/__pycache__/url.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/__pycache__/util.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/__pycache__/wait.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/connection.py delete mode 100755 venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/proxy.py delete mode 100755 venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/request.py delete mode 100755 venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/response.py delete mode 100755 venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/retry.py delete mode 100755 venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/ssl_.py delete mode 100755 venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py delete mode 100755 venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/ssltransport.py delete mode 100755 venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/timeout.py delete mode 100755 venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/url.py delete mode 100755 venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/util.py delete mode 100755 venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/wait.py delete mode 100755 venv/lib/python3.11/site-packages/pip/_vendor/vendor.txt delete mode 100755 venv/lib/python3.11/site-packages/pip/py.typed delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/__init__.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/__pycache__/__init__.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/__init__.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/__pycache__/__init__.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/__pycache__/typing_extensions.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/__pycache__/zipp.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/__init__.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/__init__.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/_adapters.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/_common.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/_compat.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/_itertools.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/_legacy.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/abc.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/readers.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/simple.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/_adapters.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/_common.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/_compat.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/_itertools.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/_legacy.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/abc.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/readers.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/simple.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/jaraco/__init__.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/jaraco/__pycache__/__init__.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/jaraco/__pycache__/context.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/jaraco/__pycache__/functools.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/jaraco/context.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/jaraco/functools.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/jaraco/text/__init__.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/jaraco/text/__pycache__/__init__.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/more_itertools/__init__.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/more_itertools/__pycache__/__init__.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/more_itertools/__pycache__/more.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/more_itertools/__pycache__/recipes.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/more_itertools/more.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/more_itertools/recipes.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__about__.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__init__.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__pycache__/__about__.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__pycache__/__init__.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__pycache__/_manylinux.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__pycache__/_musllinux.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__pycache__/_structures.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__pycache__/markers.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__pycache__/requirements.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__pycache__/specifiers.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__pycache__/tags.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__pycache__/utils.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__pycache__/version.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/_manylinux.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/_musllinux.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/_structures.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/markers.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/requirements.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/specifiers.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/tags.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/utils.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/version.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/__init__.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/__main__.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/__pycache__/__init__.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/__pycache__/__main__.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/__pycache__/android.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/__pycache__/api.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/__pycache__/macos.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/__pycache__/unix.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/__pycache__/version.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/__pycache__/windows.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/android.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/api.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/macos.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/unix.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/version.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/windows.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/__init__.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/__init__.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/actions.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/common.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/core.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/exceptions.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/helpers.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/results.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/testing.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/unicode.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/util.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/actions.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/common.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/core.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/diagram/__init__.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/diagram/__pycache__/__init__.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/exceptions.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/helpers.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/results.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/testing.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/unicode.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/util.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/typing_extensions.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/_vendor/zipp.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/extern/__init__.py delete mode 100755 venv/lib/python3.11/site-packages/pkg_resources/extern/__pycache__/__init__.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/python_dotenv-1.1.0.dist-info/INSTALLER delete mode 100755 venv/lib/python3.11/site-packages/python_dotenv-1.1.0.dist-info/METADATA delete mode 100755 venv/lib/python3.11/site-packages/python_dotenv-1.1.0.dist-info/RECORD delete mode 100755 venv/lib/python3.11/site-packages/python_dotenv-1.1.0.dist-info/REQUESTED delete mode 100755 venv/lib/python3.11/site-packages/python_dotenv-1.1.0.dist-info/WHEEL delete mode 100755 venv/lib/python3.11/site-packages/python_dotenv-1.1.0.dist-info/entry_points.txt delete mode 100755 venv/lib/python3.11/site-packages/python_dotenv-1.1.0.dist-info/licenses/LICENSE delete mode 100755 venv/lib/python3.11/site-packages/python_dotenv-1.1.0.dist-info/top_level.txt delete mode 100755 venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/INSTALLER delete mode 100755 venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/METADATA delete mode 100755 venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/RECORD delete mode 100755 venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/REQUESTED delete mode 100755 venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/WHEEL delete mode 100755 venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/licenses/LICENSE delete mode 100755 venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/licenses/LICENSE.dual delete mode 100755 venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/licenses/LICENSE.lesser delete mode 100755 venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/INSTALLER delete mode 100755 venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/LICENSE delete mode 100755 venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/METADATA delete mode 100755 venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/RECORD delete mode 100755 venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/REQUESTED delete mode 100755 venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/WHEEL delete mode 100755 venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/entry_points.txt delete mode 100755 venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/top_level.txt delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__init__.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__pycache__/__init__.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__pycache__/_deprecation_warning.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__pycache__/_entry_points.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__pycache__/_imp.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__pycache__/_importlib.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__pycache__/_itertools.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__pycache__/_path.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__pycache__/_reqs.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__pycache__/archive_util.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__pycache__/build_meta.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__pycache__/dep_util.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__pycache__/depends.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__pycache__/discovery.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__pycache__/dist.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__pycache__/errors.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__pycache__/extension.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__pycache__/glob.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__pycache__/installer.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__pycache__/launch.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__pycache__/logging.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__pycache__/monkey.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__pycache__/msvc.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__pycache__/namespaces.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__pycache__/package_index.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__pycache__/py34compat.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__pycache__/sandbox.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__pycache__/unicode_utils.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__pycache__/version.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__pycache__/wheel.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/__pycache__/windows_support.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_deprecation_warning.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__init__.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/__init__.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/_collections.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/_functools.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/_log.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/_macos_compat.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/_msvccompiler.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/archive_util.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/bcppcompiler.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/ccompiler.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/cmd.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/config.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/core.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/cygwinccompiler.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/debug.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/dep_util.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/dir_util.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/dist.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/errors.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/extension.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/fancy_getopt.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/file_util.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/filelist.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/log.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/msvc9compiler.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/msvccompiler.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/py38compat.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/py39compat.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/spawn.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/sysconfig.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/text_file.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/unixccompiler.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/util.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/version.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/versionpredicate.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/_collections.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/_functools.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/_log.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/_macos_compat.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/_msvccompiler.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/archive_util.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/bcppcompiler.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/ccompiler.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/cmd.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/__init__.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/__init__.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/_framework_compat.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/bdist.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/bdist_dumb.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/bdist_rpm.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/build.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/build_clib.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/build_ext.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/build_py.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/build_scripts.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/check.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/clean.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/config.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/install.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/install_data.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/install_egg_info.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/install_headers.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/install_lib.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/install_scripts.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/py37compat.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/register.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/sdist.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/upload.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/_framework_compat.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/bdist.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/bdist_dumb.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/bdist_rpm.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/build.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/build_clib.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/build_ext.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/build_py.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/build_scripts.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/check.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/clean.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/config.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/install.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/install_data.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/install_egg_info.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/install_headers.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/install_lib.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/install_scripts.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/py37compat.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/register.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/sdist.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/command/upload.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/config.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/core.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/cygwinccompiler.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/debug.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/dep_util.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/dir_util.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/dist.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/errors.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/extension.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/fancy_getopt.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/file_util.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/filelist.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/log.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/msvc9compiler.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/msvccompiler.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/py38compat.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/py39compat.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/spawn.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/sysconfig.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/text_file.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/unixccompiler.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/util.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/version.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_distutils/versionpredicate.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_entry_points.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_imp.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_importlib.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_itertools.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_path.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_reqs.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/__init__.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/__pycache__/__init__.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/__pycache__/ordered_set.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/__pycache__/typing_extensions.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/__pycache__/zipp.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_metadata/__init__.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/__init__.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_adapters.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_collections.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_compat.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_functools.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_itertools.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_meta.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_text.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_metadata/_adapters.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_metadata/_collections.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_metadata/_compat.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_metadata/_functools.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_metadata/_itertools.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_metadata/_meta.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_metadata/_text.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/__init__.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/__pycache__/__init__.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/__pycache__/_adapters.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/__pycache__/_common.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/__pycache__/_compat.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/__pycache__/_itertools.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/__pycache__/_legacy.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/__pycache__/abc.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/__pycache__/readers.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/__pycache__/simple.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/_adapters.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/_common.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/_compat.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/_itertools.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/_legacy.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/abc.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/readers.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/simple.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/jaraco/__init__.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/jaraco/__pycache__/__init__.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/jaraco/__pycache__/context.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/jaraco/__pycache__/functools.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/jaraco/context.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/jaraco/functools.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/jaraco/text/__init__.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/jaraco/text/__pycache__/__init__.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/more_itertools/__init__.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/more_itertools/__pycache__/__init__.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/more_itertools/__pycache__/more.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/more_itertools/__pycache__/recipes.cpython-311.pyc delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/more_itertools/more.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/more_itertools/recipes.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/ordered_set.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/packaging/__about__.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/packaging/__init__.py delete mode 100755 venv/lib/python3.11/site-packages/setuptools/_vendor/packaging/__pycache__/__about__.cpython-311.pyc diff --git a/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/__pycache__/timeout.cpython-311.pyc b/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/__pycache__/timeout.cpython-311.pyc deleted file mode 100755 index ecfb2c0eb84aa698ad4a0952c97e1453e8a31b41..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12099 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 BLvjEB diff --git a/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/__pycache__/util.cpython-311.pyc b/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/__pycache__/util.cpython-311.pyc deleted file mode 100755 index 384d55c3fab2e48bcb23183851359586b743a8c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2185 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 pgApG=E_C6(Ch8=o+twxU bool: # Platform-specific - """ - Returns True if the connection is dropped and should be closed. - :param conn: :class:`urllib3.connection.HTTPConnection` object. - """ - return not conn.is_connected - - -# This function is copied from socket.py in the Python 2.7 standard -# library test suite. Added to its signature is only `socket_options`. -# One additional modification is that we avoid binding to IPv6 servers -# discovered in DNS if the system doesn't have IPv6 functionality. -def create_connection( - address: tuple[str, int], - timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, - source_address: tuple[str, int] | None = None, - socket_options: _TYPE_SOCKET_OPTIONS | None = None, -) -> socket.socket: - """Connect to *address* and return the socket object. - - Convenience function. Connect to *address* (a 2-tuple ``(host, - port)``) and return the socket object. Passing the optional - *timeout* parameter will set the timeout on the socket instance - before attempting to connect. If no *timeout* is supplied, the - global default timeout setting returned by :func:`socket.getdefaulttimeout` - is used. If *source_address* is set it must be a tuple of (host, port) - for the socket to bind as a source address before making the connection. - An host of '' or port 0 tells the OS to use the default. - """ - - host, port = address - if host.startswith("["): - host = host.strip("[]") - err = None - - # Using the value from allowed_gai_family() in the context of getaddrinfo lets - # us select whether to work with IPv4 DNS records, IPv6 records, or both. - # The original create_connection function always returns all records. - family = allowed_gai_family() - - try: - host.encode("idna") - except UnicodeError: - raise LocationParseError(f"'{host}', label empty or too long") from None - - for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): - af, socktype, proto, canonname, sa = res - sock = None - try: - sock = socket.socket(af, socktype, proto) - - # If provided, set socket level options before connecting. - _set_socket_options(sock, socket_options) - - if timeout is not _DEFAULT_TIMEOUT: - sock.settimeout(timeout) - if source_address: - sock.bind(source_address) - sock.connect(sa) - # Break explicitly a reference cycle - err = None - return sock - - except OSError as _: - err = _ - if sock is not None: - sock.close() - - if err is not None: - try: - raise err - finally: - # Break explicitly a reference cycle - err = None - else: - raise OSError("getaddrinfo returns an empty list") - - -def _set_socket_options( - sock: socket.socket, options: _TYPE_SOCKET_OPTIONS | None -) -> None: - if options is None: - return - - for opt in options: - sock.setsockopt(*opt) - - -def allowed_gai_family() -> socket.AddressFamily: - """This function is designed to work in the context of - getaddrinfo, where family=socket.AF_UNSPEC is the default and - will perform a DNS search for both IPv6 and IPv4 records.""" - - family = socket.AF_INET - if HAS_IPV6: - family = socket.AF_UNSPEC - return family - - -def _has_ipv6(host: str) -> bool: - """Returns True if the system can bind an IPv6 address.""" - sock = None - has_ipv6 = False - - if socket.has_ipv6: - # has_ipv6 returns true if cPython was compiled with IPv6 support. - # It does not tell us if the system has IPv6 support enabled. To - # determine that we must bind to an IPv6 address. - # https://github.com/urllib3/urllib3/pull/611 - # https://bugs.python.org/issue658327 - try: - sock = socket.socket(socket.AF_INET6) - sock.bind((host, 0)) - has_ipv6 = True - except Exception: - pass - - if sock: - sock.close() - return has_ipv6 - - -HAS_IPV6 = _has_ipv6("::1") diff --git a/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/proxy.py b/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/proxy.py deleted file mode 100755 index 908fc66..0000000 --- a/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/proxy.py +++ /dev/null @@ -1,43 +0,0 @@ -from __future__ import annotations - -import typing - -from .url import Url - -if typing.TYPE_CHECKING: - from ..connection import ProxyConfig - - -def connection_requires_http_tunnel( - proxy_url: Url | None = None, - proxy_config: ProxyConfig | None = None, - destination_scheme: str | None = None, -) -> bool: - """ - Returns True if the connection requires an HTTP CONNECT through the proxy. - - :param URL proxy_url: - URL of the proxy. - :param ProxyConfig proxy_config: - Proxy configuration from poolmanager.py - :param str destination_scheme: - The scheme of the destination. (i.e https, http, etc) - """ - # If we're not using a proxy, no way to use a tunnel. - if proxy_url is None: - return False - - # HTTP destinations never require tunneling, we always forward. - if destination_scheme == "http": - return False - - # Support for forwarding with HTTPS proxies and HTTPS destinations. - if ( - proxy_url.scheme == "https" - and proxy_config - and proxy_config.use_forwarding_for_https - ): - return False - - # Otherwise always use a tunnel. - return True diff --git a/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/request.py b/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/request.py deleted file mode 100755 index b0d2717..0000000 --- a/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/request.py +++ /dev/null @@ -1,254 +0,0 @@ -from __future__ import annotations - -import io -import sys -import typing -from base64 import b64encode -from enum import Enum - -from ..exceptions import UnrewindableBodyError -from .util import to_bytes - -if typing.TYPE_CHECKING: - from typing import Final - -# Pass as a value within ``headers`` to skip -# emitting some HTTP headers that are added automatically. -# The only headers that are supported are ``Accept-Encoding``, -# ``Host``, and ``User-Agent``. -SKIP_HEADER = "@@@SKIP_HEADER@@@" -SKIPPABLE_HEADERS = frozenset(["accept-encoding", "host", "user-agent"]) - -ACCEPT_ENCODING = "gzip,deflate" - -try: - if sys.version_info >= (3, 14): - from compression import zstd as _unused_module_zstd # noqa: F401 - else: - from backports import zstd as _unused_module_zstd # noqa: F401 -except ImportError: - pass -else: - ACCEPT_ENCODING += ",zstd" - - -class _TYPE_FAILEDTELL(Enum): - token = 0 - - -_FAILEDTELL: Final[_TYPE_FAILEDTELL] = _TYPE_FAILEDTELL.token - -_TYPE_BODY_POSITION = typing.Union[int, _TYPE_FAILEDTELL] - -# When sending a request with these methods we aren't expecting -# a body so don't need to set an explicit 'Content-Length: 0' -# The reason we do this in the negative instead of tracking methods -# which 'should' have a body is because unknown methods should be -# treated as if they were 'POST' which *does* expect a body. -_METHODS_NOT_EXPECTING_BODY = {"GET", "HEAD", "DELETE", "TRACE", "OPTIONS", "CONNECT"} - - -def make_headers( - keep_alive: bool | None = None, - accept_encoding: bool | list[str] | str | None = None, - user_agent: str | None = None, - basic_auth: str | None = None, - proxy_basic_auth: str | None = None, - disable_cache: bool | None = None, -) -> dict[str, str]: - """ - Shortcuts for generating request headers. - - :param keep_alive: - If ``True``, adds 'connection: keep-alive' header. - - :param accept_encoding: - Can be a boolean, list, or string. - ``True`` translates to 'gzip,deflate'. If the dependencies for - Brotli (either the ``brotli`` or ``brotlicffi`` package) and/or - Zstandard (the ``backports.zstd`` package for Python before 3.14) - algorithms are installed, then their encodings are - included in the string ('br' and 'zstd', respectively). - List will get joined by comma. - String will be used as provided. - - :param user_agent: - String representing the user-agent you want, such as - "python-urllib3/0.6" - - :param basic_auth: - Colon-separated username:password string for 'authorization: basic ...' - auth header. - - :param proxy_basic_auth: - Colon-separated username:password string for 'proxy-authorization: basic ...' - auth header. - - :param disable_cache: - If ``True``, adds 'cache-control: no-cache' header. - - Example: - - .. code-block:: python - - from pip._vendor import urllib3 - - print(urllib3.util.make_headers(keep_alive=True, user_agent="Batman/1.0")) - # {'connection': 'keep-alive', 'user-agent': 'Batman/1.0'} - print(urllib3.util.make_headers(accept_encoding=True)) - # {'accept-encoding': 'gzip,deflate'} - """ - headers: dict[str, str] = {} - if accept_encoding: - if isinstance(accept_encoding, str): - pass - elif isinstance(accept_encoding, list): - accept_encoding = ",".join(accept_encoding) - else: - accept_encoding = ACCEPT_ENCODING - headers["accept-encoding"] = accept_encoding - - if user_agent: - headers["user-agent"] = user_agent - - if keep_alive: - headers["connection"] = "keep-alive" - - if basic_auth: - headers["authorization"] = ( - f"Basic {b64encode(basic_auth.encode('latin-1')).decode()}" - ) - - if proxy_basic_auth: - headers["proxy-authorization"] = ( - f"Basic {b64encode(proxy_basic_auth.encode('latin-1')).decode()}" - ) - - if disable_cache: - headers["cache-control"] = "no-cache" - - return headers - - -def set_file_position( - body: typing.Any, pos: _TYPE_BODY_POSITION | None -) -> _TYPE_BODY_POSITION | None: - """ - If a position is provided, move file to that point. - Otherwise, we'll attempt to record a position for future use. - """ - if pos is not None: - rewind_body(body, pos) - elif getattr(body, "tell", None) is not None: - try: - pos = body.tell() - except OSError: - # This differentiates from None, allowing us to catch - # a failed `tell()` later when trying to rewind the body. - pos = _FAILEDTELL - - return pos - - -def rewind_body(body: typing.IO[typing.AnyStr], body_pos: _TYPE_BODY_POSITION) -> None: - """ - Attempt to rewind body to a certain position. - Primarily used for request redirects and retries. - - :param body: - File-like object that supports seek. - - :param int pos: - Position to seek to in file. - """ - body_seek = getattr(body, "seek", None) - if body_seek is not None and isinstance(body_pos, int): - try: - body_seek(body_pos) - except OSError as e: - raise UnrewindableBodyError( - "An error occurred when rewinding request body for redirect/retry." - ) from e - elif body_pos is _FAILEDTELL: - raise UnrewindableBodyError( - "Unable to record file position for rewinding " - "request body during a redirect/retry." - ) - else: - raise ValueError( - f"body_pos must be of type integer, instead it was {type(body_pos)}." - ) - - -class ChunksAndContentLength(typing.NamedTuple): - chunks: typing.Iterable[bytes] | None - content_length: int | None - - -def body_to_chunks( - body: typing.Any | None, method: str, blocksize: int -) -> ChunksAndContentLength: - """Takes the HTTP request method, body, and blocksize and - transforms them into an iterable of chunks to pass to - socket.sendall() and an optional 'Content-Length' header. - - A 'Content-Length' of 'None' indicates the length of the body - can't be determined so should use 'Transfer-Encoding: chunked' - for framing instead. - """ - - chunks: typing.Iterable[bytes] | None - content_length: int | None - - # No body, we need to make a recommendation on 'Content-Length' - # based on whether that request method is expected to have - # a body or not. - if body is None: - chunks = None - if method.upper() not in _METHODS_NOT_EXPECTING_BODY: - content_length = 0 - else: - content_length = None - - # Bytes or strings become bytes - elif isinstance(body, (str, bytes)): - chunks = (to_bytes(body),) - content_length = len(chunks[0]) - - # File-like object, TODO: use seek() and tell() for length? - elif hasattr(body, "read"): - - def chunk_readable() -> typing.Iterable[bytes]: - encode = isinstance(body, io.TextIOBase) - while True: - datablock = body.read(blocksize) - if not datablock: - break - if encode: - datablock = datablock.encode("utf-8") - yield datablock - - chunks = chunk_readable() - content_length = None - - # Otherwise we need to start checking via duck-typing. - else: - try: - # Check if the body implements the buffer API. - mv = memoryview(body) - except TypeError: - try: - # Check if the body is an iterable - chunks = iter(body) - content_length = None - except TypeError: - raise TypeError( - f"'body' must be a bytes-like object, file-like " - f"object, or iterable. Instead was {body!r}" - ) from None - else: - # Since it implements the buffer API can be passed directly to socket.sendall() - chunks = (body,) - content_length = mv.nbytes - - return ChunksAndContentLength(chunks=chunks, content_length=content_length) diff --git a/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/response.py b/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/response.py deleted file mode 100755 index 0f45786..0000000 --- a/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/response.py +++ /dev/null @@ -1,101 +0,0 @@ -from __future__ import annotations - -import http.client as httplib -from email.errors import MultipartInvariantViolationDefect, StartBoundaryNotFoundDefect - -from ..exceptions import HeaderParsingError - - -def is_fp_closed(obj: object) -> bool: - """ - Checks whether a given file-like object is closed. - - :param obj: - The file-like object to check. - """ - - try: - # Check `isclosed()` first, in case Python3 doesn't set `closed`. - # GH Issue #928 - return obj.isclosed() # type: ignore[no-any-return, attr-defined] - except AttributeError: - pass - - try: - # Check via the official file-like-object way. - return obj.closed # type: ignore[no-any-return, attr-defined] - except AttributeError: - pass - - try: - # Check if the object is a container for another file-like object that - # gets released on exhaustion (e.g. HTTPResponse). - return obj.fp is None # type: ignore[attr-defined] - except AttributeError: - pass - - raise ValueError("Unable to determine whether fp is closed.") - - -def assert_header_parsing(headers: httplib.HTTPMessage) -> None: - """ - Asserts whether all headers have been successfully parsed. - Extracts encountered errors from the result of parsing headers. - - Only works on Python 3. - - :param http.client.HTTPMessage headers: Headers to verify. - - :raises urllib3.exceptions.HeaderParsingError: - If parsing errors are found. - """ - - # This will fail silently if we pass in the wrong kind of parameter. - # To make debugging easier add an explicit check. - if not isinstance(headers, httplib.HTTPMessage): - raise TypeError(f"expected httplib.Message, got {type(headers)}.") - - unparsed_data = None - - # get_payload is actually email.message.Message.get_payload; - # we're only interested in the result if it's not a multipart message - if not headers.is_multipart(): - payload = headers.get_payload() - - if isinstance(payload, (bytes, str)): - unparsed_data = payload - - # httplib is assuming a response body is available - # when parsing headers even when httplib only sends - # header data to parse_headers() This results in - # defects on multipart responses in particular. - # See: https://github.com/urllib3/urllib3/issues/800 - - # So we ignore the following defects: - # - StartBoundaryNotFoundDefect: - # The claimed start boundary was never found. - # - MultipartInvariantViolationDefect: - # A message claimed to be a multipart but no subparts were found. - defects = [ - defect - for defect in headers.defects - if not isinstance( - defect, (StartBoundaryNotFoundDefect, MultipartInvariantViolationDefect) - ) - ] - - if defects or unparsed_data: - raise HeaderParsingError(defects=defects, unparsed_data=unparsed_data) - - -def is_response_to_head(response: httplib.HTTPResponse) -> bool: - """ - Checks whether the request of a response has been a HEAD-request. - - :param http.client.HTTPResponse response: - Response to check if the originating request - used 'HEAD' as a method. - """ - # FIXME: Can we do this somehow without accessing private httplib _method? - method_str = response._method # type: str # type: ignore[attr-defined] - return method_str.upper() == "HEAD" diff --git a/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/retry.py b/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/retry.py deleted file mode 100755 index 7649898..0000000 --- a/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/retry.py +++ /dev/null @@ -1,557 +0,0 @@ -from __future__ import annotations - -import email -import logging -import random -import re -import time -import typing -from itertools import takewhile -from types import TracebackType - -from ..exceptions import ( - ConnectTimeoutError, - InvalidHeader, - MaxRetryError, - ProtocolError, - ProxyError, - ReadTimeoutError, - ResponseError, -) -from .util import reraise - -if typing.TYPE_CHECKING: - from typing_extensions import Self - - from ..connectionpool import ConnectionPool - from ..response import BaseHTTPResponse - -log = logging.getLogger(__name__) - - -# Data structure for representing the metadata of requests that result in a retry. -class RequestHistory(typing.NamedTuple): - method: str | None - url: str | None - error: Exception | None - status: int | None - redirect_location: str | None - - -class Retry: - """Retry configuration. - - Each retry attempt will create a new Retry object with updated values, so - they can be safely reused. - - Retries can be defined as a default for a pool: - - .. code-block:: python - - retries = Retry(connect=5, read=2, redirect=5) - http = PoolManager(retries=retries) - response = http.request("GET", "https://example.com/") - - Or per-request (which overrides the default for the pool): - - .. code-block:: python - - response = http.request("GET", "https://example.com/", retries=Retry(10)) - - Retries can be disabled by passing ``False``: - - .. code-block:: python - - response = http.request("GET", "https://example.com/", retries=False) - - Errors will be wrapped in :class:`~urllib3.exceptions.MaxRetryError` unless - retries are disabled, in which case the causing exception will be raised. - - :param int total: - Total number of retries to allow. Takes precedence over other counts. - - Set to ``None`` to remove this constraint and fall back on other - counts. - - Set to ``0`` to fail on the first retry. - - Set to ``False`` to disable and imply ``raise_on_redirect=False``. - - :param int connect: - How many connection-related errors to retry on. - - These are errors raised before the request is sent to the remote server, - which we assume has not triggered the server to process the request. - - Set to ``0`` to fail on the first retry of this type. - - :param int read: - How many times to retry on read errors. - - These errors are raised after the request was sent to the server, so the - request may have side-effects. - - Set to ``0`` to fail on the first retry of this type. - - :param int redirect: - How many redirects to perform. Limit this to avoid infinite redirect - loops. - - A redirect is a HTTP response with a status code 301, 302, 303, 307 or - 308. - - Set to ``0`` to fail on the first retry of this type. - - Set to ``False`` to disable and imply ``raise_on_redirect=False``. - - :param int status: - How many times to retry on bad status codes. - - These are retries made on responses, where status code matches - ``status_forcelist``. - - Set to ``0`` to fail on the first retry of this type. - - :param int other: - How many times to retry on other errors. - - Other errors are errors that are not connect, read, redirect or status errors. - These errors might be raised after the request was sent to the server, so the - request might have side-effects. - - Set to ``0`` to fail on the first retry of this type. - - If ``total`` is not set, it's a good idea to set this to 0 to account - for unexpected edge cases and avoid infinite retry loops. - - :param Collection allowed_methods: - Set of uppercased HTTP method verbs that we should retry on. - - By default, we only retry on methods which are considered to be - idempotent (multiple requests with the same parameters end with the - same state). See :attr:`Retry.DEFAULT_ALLOWED_METHODS`. - - Set to a ``None`` value to retry on any verb. - - :param Collection status_forcelist: - A set of integer HTTP status codes that we should force a retry on. - A retry is initiated if the request method is in ``allowed_methods`` - and the response status code is in ``status_forcelist``. - - By default, this is disabled with ``None``. - - :param float backoff_factor: - A backoff factor to apply between attempts after the second try - (most errors are resolved immediately by a second try without a - delay). urllib3 will sleep for:: - - {backoff factor} * (2 ** ({number of previous retries})) - - seconds. If `backoff_jitter` is non-zero, this sleep is extended by:: - - random.uniform(0, {backoff jitter}) - - seconds. For example, if the backoff_factor is 0.1, then :func:`Retry.sleep` will - sleep for [0.0s, 0.2s, 0.4s, 0.8s, ...] between retries. No backoff will ever - be longer than `backoff_max`. - - By default, backoff is disabled (factor set to 0). - - :param float backoff_max: - The maximum backoff time (in seconds) between retry attempts. - This value caps the computed backoff from `backoff_factor`. - - :param float backoff_jitter: - Random jitter amount (in seconds) added to the computed backoff. - Jitter is sampled uniformly from `0` to `backoff_jitter`. - - :param bool raise_on_redirect: Whether, if the number of redirects is - exhausted, to raise a MaxRetryError, or to return a response with a - response code in the 3xx range. - - :param bool raise_on_status: Similar meaning to ``raise_on_redirect``: - whether we should raise an exception, or return a response, - if status falls in ``status_forcelist`` range and retries have - been exhausted. - - :param tuple history: The history of the request encountered during - each call to :meth:`~Retry.increment`. The list is in the order - the requests occurred. Each list item is of class :class:`RequestHistory`. - - :param bool respect_retry_after_header: - Whether to respect Retry-After header on status codes defined as - :attr:`Retry.RETRY_AFTER_STATUS_CODES` or not. - - :param Collection remove_headers_on_redirect: - Sequence of headers to remove from the request when a response - indicating a redirect is returned before firing off the redirected - request. - - :param int retry_after_max: Number of seconds to allow as the maximum for - Retry-After headers. Defaults to :attr:`Retry.DEFAULT_RETRY_AFTER_MAX`. - Any Retry-After headers larger than this value will be limited to this - value. - """ - - #: Default methods to be used for ``allowed_methods`` - DEFAULT_ALLOWED_METHODS = frozenset( - ["HEAD", "GET", "PUT", "DELETE", "OPTIONS", "TRACE"] - ) - - #: Default status codes to be used for ``status_forcelist`` - 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 maximum backoff time. - DEFAULT_BACKOFF_MAX = 120 - - # This is undocumented in the RFC. Setting to 6 hours matches other popular libraries. - #: Default maximum allowed value for Retry-After headers in seconds - DEFAULT_RETRY_AFTER_MAX: typing.Final[int] = 21600 - - # Backward compatibility; assigned outside of the class. - DEFAULT: typing.ClassVar[Retry] - - def __init__( - self, - total: bool | int | None = 10, - connect: int | None = None, - read: int | None = None, - redirect: bool | int | None = None, - status: int | None = None, - other: int | None = None, - allowed_methods: typing.Collection[str] | None = DEFAULT_ALLOWED_METHODS, - status_forcelist: typing.Collection[int] | None = None, - backoff_factor: float = 0, - backoff_max: float = DEFAULT_BACKOFF_MAX, - raise_on_redirect: bool = True, - raise_on_status: bool = True, - history: tuple[RequestHistory, ...] | None = None, - respect_retry_after_header: bool = True, - remove_headers_on_redirect: typing.Collection[ - str - ] = DEFAULT_REMOVE_HEADERS_ON_REDIRECT, - backoff_jitter: float = 0.0, - retry_after_max: int = DEFAULT_RETRY_AFTER_MAX, - ) -> None: - self.total = total - self.connect = connect - self.read = read - self.status = status - self.other = other - - if redirect is False or total is False: - redirect = 0 - raise_on_redirect = False - - self.redirect = redirect - self.status_forcelist = status_forcelist or set() - self.allowed_methods = allowed_methods - self.backoff_factor = backoff_factor - self.backoff_max = backoff_max - self.retry_after_max = retry_after_max - self.raise_on_redirect = raise_on_redirect - self.raise_on_status = raise_on_status - self.history = history or () - self.respect_retry_after_header = respect_retry_after_header - self.remove_headers_on_redirect = frozenset( - h.lower() for h in remove_headers_on_redirect - ) - self.backoff_jitter = backoff_jitter - - def new(self, **kw: typing.Any) -> Self: - params = dict( - total=self.total, - connect=self.connect, - read=self.read, - redirect=self.redirect, - status=self.status, - other=self.other, - allowed_methods=self.allowed_methods, - status_forcelist=self.status_forcelist, - backoff_factor=self.backoff_factor, - backoff_max=self.backoff_max, - retry_after_max=self.retry_after_max, - raise_on_redirect=self.raise_on_redirect, - raise_on_status=self.raise_on_status, - history=self.history, - remove_headers_on_redirect=self.remove_headers_on_redirect, - respect_retry_after_header=self.respect_retry_after_header, - backoff_jitter=self.backoff_jitter, - ) - - params.update(kw) - return type(self)(**params) # type: ignore[arg-type] - - @classmethod - def from_int( - cls, - retries: Retry | bool | int | None, - redirect: bool | int | None = True, - default: Retry | bool | int | None = None, - ) -> Retry: - """Backwards-compatibility for the old retries format.""" - if retries is None: - retries = default if default is not None else cls.DEFAULT - - if isinstance(retries, Retry): - return retries - - redirect = bool(redirect) and None - new_retries = cls(retries, redirect=redirect) - log.debug("Converted retries value: %r -> %r", retries, new_retries) - return new_retries - - def get_backoff_time(self) -> float: - """Formula for computing the current backoff - - :rtype: float - """ - # We want to consider only the last consecutive errors sequence (Ignore redirects). - consecutive_errors_len = len( - list( - takewhile(lambda x: x.redirect_location is None, reversed(self.history)) - ) - ) - if consecutive_errors_len <= 1: - return 0 - - backoff_value = self.backoff_factor * (2 ** (consecutive_errors_len - 1)) - if self.backoff_jitter != 0.0: - backoff_value += random.random() * self.backoff_jitter - return float(max(0, min(self.backoff_max, backoff_value))) - - def parse_retry_after(self, retry_after: str) -> float: - seconds: float - # Whitespace: https://tools.ietf.org/html/rfc7230#section-3.2.4 - if re.match(r"^\s*[0-9]+\s*$", retry_after): - seconds = int(retry_after) - else: - retry_date_tuple = email.utils.parsedate_tz(retry_after) - if retry_date_tuple is None: - raise InvalidHeader(f"Invalid Retry-After header: {retry_after}") - - retry_date = email.utils.mktime_tz(retry_date_tuple) - seconds = retry_date - time.time() - - seconds = max(seconds, 0) - - # Check the seconds do not exceed the specified maximum - if seconds > self.retry_after_max: - seconds = self.retry_after_max - - return seconds - - def get_retry_after(self, response: BaseHTTPResponse) -> float | None: - """Get the value of Retry-After in seconds.""" - - retry_after = response.headers.get("Retry-After") - - if retry_after is None: - return None - - return self.parse_retry_after(retry_after) - - def sleep_for_retry(self, response: BaseHTTPResponse) -> bool: - retry_after = self.get_retry_after(response) - if retry_after: - time.sleep(retry_after) - return True - - return False - - def _sleep_backoff(self) -> None: - backoff = self.get_backoff_time() - if backoff <= 0: - return - time.sleep(backoff) - - def sleep(self, response: BaseHTTPResponse | None = None) -> None: - """Sleep between retry attempts. - - This method will respect a server's ``Retry-After`` response header - and sleep the duration of the time requested. If that is not present, it - will use an exponential backoff. By default, the backoff factor is 0 and - this method will return immediately. - """ - - if self.respect_retry_after_header and response: - slept = self.sleep_for_retry(response) - if slept: - return - - self._sleep_backoff() - - def _is_connection_error(self, err: Exception) -> bool: - """Errors when we're fairly sure that the server did not receive the - request, so it should be safe to retry. - """ - if isinstance(err, ProxyError): - err = err.original_error - return isinstance(err, ConnectTimeoutError) - - def _is_read_error(self, err: Exception) -> bool: - """Errors that occur after the request has been started, so we should - assume that the server began processing it. - """ - return isinstance(err, (ReadTimeoutError, ProtocolError)) - - def _is_method_retryable(self, method: str) -> bool: - """Checks if a given HTTP method should be retried upon, depending if - it is included in the allowed_methods - """ - if self.allowed_methods and method.upper() not in self.allowed_methods: - return False - return True - - def is_retry( - self, method: str, status_code: int, has_retry_after: bool = False - ) -> bool: - """Is this method/status code retryable? (Based on allowlists and control - variables such as the number of total retries to allow, whether to - respect the Retry-After header, whether this header is present, and - whether the returned status code is on the list of status codes to - be retried upon on the presence of the aforementioned header) - """ - if not self._is_method_retryable(method): - return False - - if self.status_forcelist and status_code in self.status_forcelist: - return True - - return bool( - self.total - and self.respect_retry_after_header - and has_retry_after - and (status_code in self.RETRY_AFTER_STATUS_CODES) - ) - - def is_exhausted(self) -> bool: - """Are we out of retries?""" - retry_counts = [ - x - for x in ( - self.total, - self.connect, - self.read, - self.redirect, - self.status, - self.other, - ) - if x - ] - if not retry_counts: - return False - - return min(retry_counts) < 0 - - def increment( - self, - method: str | None = None, - url: str | None = None, - response: BaseHTTPResponse | None = None, - error: Exception | None = None, - _pool: ConnectionPool | None = None, - _stacktrace: TracebackType | None = None, - ) -> Self: - """Return a new Retry object with incremented retry counters. - - :param response: A response object, or None, if the server did not - return a response. - :type response: :class:`~urllib3.response.BaseHTTPResponse` - :param Exception error: An error encountered during the request, or - None if the response was received successfully. - - :return: A new ``Retry`` object. - """ - if self.total is False and error: - # Disabled, indicate to re-raise the error. - raise reraise(type(error), error, _stacktrace) - - total = self.total - if total is not None: - total -= 1 - - connect = self.connect - read = self.read - redirect = self.redirect - status_count = self.status - other = self.other - cause = "unknown" - status = None - redirect_location = None - - if error and self._is_connection_error(error): - # Connect retry? - if connect is False: - raise reraise(type(error), error, _stacktrace) - elif connect is not None: - connect -= 1 - - elif error and self._is_read_error(error): - # Read retry? - if read is False or method is None or not self._is_method_retryable(method): - raise reraise(type(error), error, _stacktrace) - elif read is not None: - read -= 1 - - elif error: - # Other retry? - if other is not None: - other -= 1 - - elif response and response.get_redirect_location(): - # Redirect retry? - if redirect is not None: - redirect -= 1 - cause = "too many redirects" - response_redirect_location = response.get_redirect_location() - if response_redirect_location: - redirect_location = response_redirect_location - status = response.status - - else: - # Incrementing because of a server error like a 500 in - # status_forcelist and the given method is in the allowed_methods - cause = ResponseError.GENERIC_ERROR - if response and response.status: - if status_count is not None: - status_count -= 1 - cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) - status = response.status - - history = self.history + ( - RequestHistory(method, url, error, status, redirect_location), - ) - - new_retry = self.new( - total=total, - connect=connect, - read=read, - redirect=redirect, - status=status_count, - other=other, - history=history, - ) - - if new_retry.is_exhausted(): - reason = error or ResponseError(cause) - raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] - - log.debug("Incremented Retry for (url='%s'): %r", url, new_retry) - - return new_retry - - def __repr__(self) -> str: - return ( - f"{type(self).__name__}(total={self.total}, connect={self.connect}, " - f"read={self.read}, redirect={self.redirect}, status={self.status})" - ) - - -# For backwards compatibility (equivalent to pre-v1.9): -Retry.DEFAULT = Retry(3) diff --git a/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/ssl_.py b/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/ssl_.py deleted file mode 100755 index e66549a..0000000 --- a/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/ssl_.py +++ /dev/null @@ -1,477 +0,0 @@ -from __future__ import annotations - -import hashlib -import hmac -import os -import socket -import sys -import typing -import warnings -from binascii import unhexlify - -from ..exceptions import ProxySchemeUnsupported, SSLError -from .url import _BRACELESS_IPV6_ADDRZ_RE, _IPV4_RE - -SSLContext = None -SSLTransport = None -HAS_NEVER_CHECK_COMMON_NAME = False -IS_PYOPENSSL = False -ALPN_PROTOCOLS = ["http/1.1"] - -_TYPE_VERSION_INFO = tuple[int, int, int, str, int] - -# 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")) -} - - -def _is_has_never_check_common_name_reliable( - openssl_version: str, -) -> bool: - # As of May 2023, all released versions of LibreSSL fail to reject certificates with - # only common names, see https://github.com/urllib3/urllib3/pull/3024 - is_openssl = openssl_version.startswith("OpenSSL ") - - return is_openssl - - -if typing.TYPE_CHECKING: - from ssl import VerifyMode - from typing import TypedDict - - from .ssltransport import SSLTransport as SSLTransportType - - class _TYPE_PEER_CERT_RET_DICT(TypedDict, total=False): - subjectAltName: tuple[tuple[str, str], ...] - subject: tuple[tuple[tuple[str, str], ...], ...] - serialNumber: str - - -# Mapping from 'ssl.PROTOCOL_TLSX' to 'TLSVersion.X' -_SSL_VERSION_TO_TLS_VERSION: dict[int, int] = {} - -try: # Do we have ssl at all? - import ssl - from ssl import ( # type: ignore[assignment] - CERT_REQUIRED, - HAS_NEVER_CHECK_COMMON_NAME, - OP_NO_COMPRESSION, - OP_NO_TICKET, - OPENSSL_VERSION, - PROTOCOL_TLS, - PROTOCOL_TLS_CLIENT, - VERIFY_X509_PARTIAL_CHAIN, - VERIFY_X509_STRICT, - OP_NO_SSLv2, - OP_NO_SSLv3, - SSLContext, - TLSVersion, - ) - - PROTOCOL_SSLv23 = PROTOCOL_TLS - - # Setting SSLContext.hostname_checks_common_name = False didn't work with - # LibreSSL, check details in the used function. - if HAS_NEVER_CHECK_COMMON_NAME and not _is_has_never_check_common_name_reliable( - OPENSSL_VERSION, - ): # Defensive: - HAS_NEVER_CHECK_COMMON_NAME = False - - # Need to be careful here in case old TLS versions get - # removed in future 'ssl' module implementations. - for attr in ("TLSv1", "TLSv1_1", "TLSv1_2"): - try: - _SSL_VERSION_TO_TLS_VERSION[getattr(ssl, f"PROTOCOL_{attr}")] = getattr( - TLSVersion, attr - ) - except AttributeError: # Defensive: - continue - - from .ssltransport import SSLTransport # type: ignore[assignment] -except ImportError: - OP_NO_COMPRESSION = 0x20000 # type: ignore[assignment, misc] - OP_NO_TICKET = 0x4000 # type: ignore[assignment, misc] - OP_NO_SSLv2 = 0x1000000 # type: ignore[assignment, misc] - OP_NO_SSLv3 = 0x2000000 # type: ignore[assignment, misc] - PROTOCOL_SSLv23 = PROTOCOL_TLS = 2 # type: ignore[assignment, misc] - PROTOCOL_TLS_CLIENT = 16 # type: ignore[assignment, misc] - VERIFY_X509_PARTIAL_CHAIN = 0x80000 # type: ignore[assignment,misc] - VERIFY_X509_STRICT = 0x20 # type: ignore[assignment, misc] - - -_TYPE_PEER_CERT_RET = typing.Union["_TYPE_PEER_CERT_RET_DICT", bytes, None] - - -def assert_fingerprint(cert: bytes | None, fingerprint: str) -> None: - """ - Checks if given fingerprint matches the supplied certificate. - - :param cert: - Certificate as bytes object. - :param fingerprint: - Fingerprint as string of hexdigits, can be interspersed by colons. - """ - - if cert is None: - raise SSLError("No certificate for the peer.") - - fingerprint = fingerprint.replace(":", "").lower() - digest_length = len(fingerprint) - if digest_length not in HASHFUNC_MAP: - raise SSLError(f"Fingerprint of invalid length: {fingerprint}") - hashfunc = HASHFUNC_MAP.get(digest_length) - if hashfunc is None: - raise SSLError( - f"Hash function implementation unavailable for fingerprint length: {digest_length}" - ) - - # We need encode() here for py32; works on py2 and p33. - fingerprint_bytes = unhexlify(fingerprint.encode()) - - cert_digest = hashfunc(cert).digest() - - if not hmac.compare_digest(cert_digest, fingerprint_bytes): - raise SSLError( - f'Fingerprints did not match. Expected "{fingerprint}", got "{cert_digest.hex()}"' - ) - - -def resolve_cert_reqs(candidate: None | int | str) -> VerifyMode: - """ - Resolves the argument to a numeric constant, which can be passed to - the wrap_socket function/method from the ssl module. - Defaults to :data:`ssl.CERT_REQUIRED`. - If given a string it is assumed to be the name of the constant in the - :mod:`ssl` module or its abbreviation. - (So you can specify `REQUIRED` instead of `CERT_REQUIRED`. - If it's neither `None` nor a string we assume it is already the numeric - constant which can directly be passed to wrap_socket. - """ - if candidate is None: - return CERT_REQUIRED - - if isinstance(candidate, str): - res = getattr(ssl, candidate, None) - if res is None: - res = getattr(ssl, "CERT_" + candidate) - return res # type: ignore[no-any-return] - - return candidate # type: ignore[return-value] - - -def resolve_ssl_version(candidate: None | int | str) -> int: - """ - like resolve_cert_reqs - """ - if candidate is None: - return PROTOCOL_TLS - - if isinstance(candidate, str): - res = getattr(ssl, candidate, None) - if res is None: - res = getattr(ssl, "PROTOCOL_" + candidate) - return typing.cast(int, res) - - return candidate - - -def create_urllib3_context( - ssl_version: int | None = None, - cert_reqs: int | None = None, - options: int | None = None, - ciphers: str | None = None, - ssl_minimum_version: int | None = None, - ssl_maximum_version: int | None = None, - verify_flags: int | None = None, -) -> ssl.SSLContext: - """Creates and configures an :class:`ssl.SSLContext` instance for use with urllib3. - - :param ssl_version: - The desired protocol version to use. This will default to - PROTOCOL_SSLv23 which will negotiate the highest protocol that both - the server and your installation of OpenSSL support. - - This parameter is deprecated instead use 'ssl_minimum_version'. - :param ssl_minimum_version: - The minimum version of TLS to be used. Use the 'ssl.TLSVersion' enum for specifying the value. - :param ssl_maximum_version: - The maximum version of TLS to be used. Use the 'ssl.TLSVersion' enum for specifying the value. - Not recommended to set to anything other than 'ssl.TLSVersion.MAXIMUM_SUPPORTED' which is the - default value. - :param cert_reqs: - Whether to require the certificate verification. This defaults to - ``ssl.CERT_REQUIRED``. - :param options: - Specific OpenSSL options. These default to ``ssl.OP_NO_SSLv2``, - ``ssl.OP_NO_SSLv3``, ``ssl.OP_NO_COMPRESSION``, and ``ssl.OP_NO_TICKET``. - :param ciphers: - Which cipher suites to allow the server to select. Defaults to either system configured - ciphers if OpenSSL 1.1.1+, otherwise uses a secure default set of ciphers. - :param verify_flags: - The flags for certificate verification operations. These default to - ``ssl.VERIFY_X509_PARTIAL_CHAIN`` and ``ssl.VERIFY_X509_STRICT`` for Python 3.13+. - :returns: - Constructed SSLContext object with specified options - :rtype: SSLContext - """ - if SSLContext is None: - raise TypeError("Can't create an SSLContext object without an ssl module") - - # This means 'ssl_version' was specified as an exact value. - if ssl_version not in (None, PROTOCOL_TLS, PROTOCOL_TLS_CLIENT): - # Disallow setting 'ssl_version' and 'ssl_minimum|maximum_version' - # to avoid conflicts. - if ssl_minimum_version is not None or ssl_maximum_version is not None: - raise ValueError( - "Can't specify both 'ssl_version' and either " - "'ssl_minimum_version' or 'ssl_maximum_version'" - ) - - # 'ssl_version' is deprecated and will be removed in the future. - else: - # Use 'ssl_minimum_version' and 'ssl_maximum_version' instead. - ssl_minimum_version = _SSL_VERSION_TO_TLS_VERSION.get( - ssl_version, TLSVersion.MINIMUM_SUPPORTED - ) - ssl_maximum_version = _SSL_VERSION_TO_TLS_VERSION.get( - ssl_version, TLSVersion.MAXIMUM_SUPPORTED - ) - - # This warning message is pushing users to use 'ssl_minimum_version' - # instead of both min/max. Best practice is to only set the minimum version and - # keep the maximum version to be it's default value: 'TLSVersion.MAXIMUM_SUPPORTED' - warnings.warn( - "'ssl_version' option is deprecated and will be " - "removed in urllib3 v3.0. Instead use 'ssl_minimum_version'", - category=FutureWarning, - stacklevel=2, - ) - - context = SSLContext(PROTOCOL_TLS_CLIENT) - if ssl_minimum_version is not None: - context.minimum_version = ssl_minimum_version - else: # pyOpenSSL defaults to 'MINIMUM_SUPPORTED' so explicitly set TLSv1.2 here - context.minimum_version = TLSVersion.TLSv1_2 - - if ssl_maximum_version is not None: - context.maximum_version = ssl_maximum_version - - # Unless we're given ciphers defer to either system ciphers in - # the case of OpenSSL 1.1.1+ or use our own secure default ciphers. - if ciphers: - context.set_ciphers(ciphers) - - # Setting the default here, as we may have no ssl module on import - cert_reqs = ssl.CERT_REQUIRED if cert_reqs is None else cert_reqs - - if options is None: - options = 0 - # SSLv2 is easily broken and is considered harmful and dangerous - options |= OP_NO_SSLv2 - # SSLv3 has several problems and is now dangerous - options |= OP_NO_SSLv3 - # Disable compression to prevent CRIME attacks for OpenSSL 1.0+ - # (issue #309) - options |= OP_NO_COMPRESSION - # TLSv1.2 only. Unless set explicitly, do not request tickets. - # This may save some bandwidth on wire, and although the ticket is encrypted, - # there is a risk associated with it being on wire, - # if the server is not rotating its ticketing keys properly. - options |= OP_NO_TICKET - - context.options |= options - - if verify_flags is None: - verify_flags = 0 - # In Python 3.13+ ssl.create_default_context() sets VERIFY_X509_PARTIAL_CHAIN - # and VERIFY_X509_STRICT so we do the same - if sys.version_info >= (3, 13): - verify_flags |= VERIFY_X509_PARTIAL_CHAIN - verify_flags |= VERIFY_X509_STRICT - - context.verify_flags |= verify_flags - - # Enable post-handshake authentication for TLS 1.3, see GH #1634. PHA is - # necessary for conditional client cert authentication with TLS 1.3. - # The attribute is None for OpenSSL <= 1.1.0 or does not exist when using - # an SSLContext created by pyOpenSSL. - if getattr(context, "post_handshake_auth", None) is not None: - context.post_handshake_auth = True - - # The order of the below lines setting verify_mode and check_hostname - # matter due to safe-guards SSLContext has to prevent an SSLContext with - # check_hostname=True, verify_mode=NONE/OPTIONAL. - # We always set 'check_hostname=False' for pyOpenSSL so we rely on our own - # 'ssl.match_hostname()' implementation. - if cert_reqs == ssl.CERT_REQUIRED and not IS_PYOPENSSL: - context.verify_mode = cert_reqs - context.check_hostname = True - else: - context.check_hostname = False - context.verify_mode = cert_reqs - - context.hostname_checks_common_name = False - - if "SSLKEYLOGFILE" in os.environ: - sslkeylogfile = os.path.expandvars(os.environ.get("SSLKEYLOGFILE")) - else: - sslkeylogfile = None - if sslkeylogfile: - context.keylog_filename = sslkeylogfile - - return context - - -@typing.overload -def ssl_wrap_socket( - sock: socket.socket, - keyfile: str | None = ..., - certfile: str | None = ..., - cert_reqs: int | None = ..., - ca_certs: str | None = ..., - server_hostname: str | None = ..., - ssl_version: int | None = ..., - ciphers: str | None = ..., - ssl_context: ssl.SSLContext | None = ..., - ca_cert_dir: str | None = ..., - key_password: str | None = ..., - ca_cert_data: None | str | bytes = ..., - tls_in_tls: typing.Literal[False] = ..., -) -> ssl.SSLSocket: ... - - -@typing.overload -def ssl_wrap_socket( - sock: socket.socket, - keyfile: str | None = ..., - certfile: str | None = ..., - cert_reqs: int | None = ..., - ca_certs: str | None = ..., - server_hostname: str | None = ..., - ssl_version: int | None = ..., - ciphers: str | None = ..., - ssl_context: ssl.SSLContext | None = ..., - ca_cert_dir: str | None = ..., - key_password: str | None = ..., - ca_cert_data: None | str | bytes = ..., - tls_in_tls: bool = ..., -) -> ssl.SSLSocket | SSLTransportType: ... - - -def ssl_wrap_socket( - sock: socket.socket, - keyfile: str | None = None, - certfile: str | None = None, - cert_reqs: int | None = None, - ca_certs: str | None = None, - server_hostname: str | None = None, - ssl_version: int | None = None, - ciphers: str | None = None, - ssl_context: ssl.SSLContext | None = None, - ca_cert_dir: str | None = None, - key_password: str | None = None, - ca_cert_data: None | str | bytes = None, - tls_in_tls: bool = False, -) -> ssl.SSLSocket | SSLTransportType: - """ - All arguments except for server_hostname, ssl_context, tls_in_tls, ca_cert_data and - ca_cert_dir have the same meaning as they do when using - :func:`ssl.create_default_context`, :meth:`ssl.SSLContext.load_cert_chain`, - :meth:`ssl.SSLContext.set_ciphers` and :meth:`ssl.SSLContext.wrap_socket`. - - :param server_hostname: - When SNI is supported, the expected hostname of the certificate - :param ssl_context: - A pre-made :class:`SSLContext` object. If none is provided, one will - be created using :func:`create_urllib3_context`. - :param ciphers: - A string of ciphers we wish the client to support. - :param ca_cert_dir: - A directory containing CA certificates in multiple separate files, as - supported by OpenSSL's -CApath flag or the capath argument to - SSLContext.load_verify_locations(). - :param key_password: - Optional password if the keyfile is encrypted. - :param ca_cert_data: - Optional string containing CA certificates in PEM format suitable for - passing as the cadata parameter to SSLContext.load_verify_locations() - :param tls_in_tls: - Use SSLTransport to wrap the existing socket. - """ - context = ssl_context - if context is None: - # Note: This branch of code and all the variables in it are only used in tests. - # We should consider deprecating and removing this code. - context = create_urllib3_context(ssl_version, cert_reqs, ciphers=ciphers) - - if ca_certs or ca_cert_dir or ca_cert_data: - try: - context.load_verify_locations(ca_certs, ca_cert_dir, ca_cert_data) - except OSError as e: - raise SSLError(e) from e - - elif ssl_context is None and hasattr(context, "load_default_certs"): - # try to load OS default certs; works well on Windows. - context.load_default_certs() - - # Attempt to detect if we get the goofy behavior of the - # keyfile being encrypted and OpenSSL asking for the - # passphrase via the terminal and instead error out. - if keyfile and key_password is None and _is_key_file_encrypted(keyfile): - raise SSLError("Client private key is encrypted, password is required") - - if certfile: - if key_password is None: - context.load_cert_chain(certfile, keyfile) - else: - context.load_cert_chain(certfile, keyfile, key_password) - - context.set_alpn_protocols(ALPN_PROTOCOLS) - - ssl_sock = _ssl_wrap_socket_impl(sock, context, tls_in_tls, server_hostname) - return ssl_sock - - -def is_ipaddress(hostname: str | bytes) -> bool: - """Detects whether the hostname given is an IPv4 or IPv6 address. - Also detects IPv6 addresses with Zone IDs. - - :param str hostname: Hostname to examine. - :return: True if the hostname is an IP address, False otherwise. - """ - if isinstance(hostname, bytes): - # IDN A-label bytes are ASCII compatible. - hostname = hostname.decode("ascii") - return bool(_IPV4_RE.match(hostname) or _BRACELESS_IPV6_ADDRZ_RE.match(hostname)) - - -def _is_key_file_encrypted(key_file: str) -> bool: - """Detects if a key file is encrypted or not.""" - with open(key_file) as f: - for line in f: - # Look for Proc-Type: 4,ENCRYPTED - if "ENCRYPTED" in line: - return True - - return False - - -def _ssl_wrap_socket_impl( - sock: socket.socket, - ssl_context: ssl.SSLContext, - tls_in_tls: bool, - server_hostname: str | None = None, -) -> ssl.SSLSocket | SSLTransportType: - if tls_in_tls: - if not SSLTransport: - # Import error, ssl is not available. - raise ProxySchemeUnsupported( - "TLS in TLS requires support for the 'ssl' module" - ) - - SSLTransport._validate_ssl_context_for_tls_in_tls(ssl_context) - return SSLTransport(sock, ssl_context, server_hostname) - - return ssl_context.wrap_socket(sock, server_hostname=server_hostname) diff --git a/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py b/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py deleted file mode 100755 index 94994f2..0000000 --- a/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py +++ /dev/null @@ -1,153 +0,0 @@ -"""The match_hostname() function from Python 3.5, essential when using SSL.""" - -# Note: This file is under the PSF license as the code comes from the python -# stdlib. http://docs.python.org/3/license.html -# It is modified to remove commonName support. - -from __future__ import annotations - -import ipaddress -import re -import typing -from ipaddress import IPv4Address, IPv6Address - -if typing.TYPE_CHECKING: - from .ssl_ import _TYPE_PEER_CERT_RET_DICT - -__version__ = "3.5.0.1" - - -class CertificateError(ValueError): - pass - - -def _dnsname_match( - dn: typing.Any, hostname: str, max_wildcards: int = 1 -) -> typing.Match[str] | None | bool: - """Matching according to RFC 6125, section 6.4.3 - - http://tools.ietf.org/html/rfc6125#section-6.4.3 - """ - pats = [] - if not dn: - return False - - # Ported from python3-syntax: - # leftmost, *remainder = dn.split(r'.') - parts = dn.split(r".") - leftmost = parts[0] - remainder = parts[1:] - - wildcards = leftmost.count("*") - if wildcards > max_wildcards: - # Issue #17980: avoid denials of service by refusing more - # than one wildcard per fragment. A survey of established - # policy among SSL implementations showed it to be a - # reasonable choice. - raise CertificateError( - "too many wildcards in certificate DNS name: " + repr(dn) - ) - - # speed up common case w/o wildcards - if not wildcards: - return bool(dn.lower() == hostname.lower()) - - # RFC 6125, section 6.4.3, subitem 1. - # The client SHOULD NOT attempt to match a presented identifier in which - # the wildcard character comprises a label other than the left-most label. - if leftmost == "*": - # When '*' is a fragment by itself, it matches a non-empty dotless - # fragment. - pats.append("[^.]+") - elif leftmost.startswith("xn--") or hostname.startswith("xn--"): - # RFC 6125, section 6.4.3, subitem 3. - # The client SHOULD NOT attempt to match a presented identifier - # where the wildcard character is embedded within an A-label or - # U-label of an internationalized domain name. - pats.append(re.escape(leftmost)) - else: - # Otherwise, '*' matches any dotless string, e.g. www* - pats.append(re.escape(leftmost).replace(r"\*", "[^.]*")) - - # add the remaining fragments, ignore any wildcards - for frag in remainder: - pats.append(re.escape(frag)) - - pat = re.compile(r"\A" + r"\.".join(pats) + r"\Z", re.IGNORECASE) - return pat.match(hostname) - - -def _ipaddress_match(ipname: str, host_ip: IPv4Address | IPv6Address) -> bool: - """Exact matching of IP addresses. - - RFC 9110 section 4.3.5: "A reference identity of IP-ID contains the decoded - bytes of the IP address. An IP version 4 address is 4 octets, and an IP - version 6 address is 16 octets. [...] A reference identity of type IP-ID - matches if the address is identical to an iPAddress value of the - subjectAltName extension of the certificate." - """ - # OpenSSL may add a trailing newline to a subjectAltName's IP address - # Divergence from upstream: ipaddress can't handle byte str - ip = ipaddress.ip_address(ipname.rstrip()) - return bool(ip.packed == host_ip.packed) - - -def match_hostname( - cert: _TYPE_PEER_CERT_RET_DICT | None, - hostname: str, - hostname_checks_common_name: bool = False, -) -> None: - """Verify that *cert* (in decoded format as returned by - SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125 - rules are followed, but IP addresses are not accepted for *hostname*. - - CertificateError is raised on failure. On success, the function - returns nothing. - """ - if not cert: - raise ValueError( - "empty or no certificate, match_hostname needs a " - "SSL socket or SSL context with either " - "CERT_OPTIONAL or CERT_REQUIRED" - ) - - try: - host_ip = ipaddress.ip_address(hostname) - except ValueError: - # Not an IP address (common case) - host_ip = None - dnsnames = [] - san: tuple[tuple[str, str], ...] = cert.get("subjectAltName", ()) - key: str - value: str - for key, value in san: - if key == "DNS": - if host_ip is None and _dnsname_match(value, hostname): - return - dnsnames.append(value) - elif key == "IP Address": - if host_ip is not None and _ipaddress_match(value, host_ip): - return - dnsnames.append(value) - - # We only check 'commonName' if it's enabled and we're not verifying - # an IP address. IP addresses aren't valid within 'commonName'. - if hostname_checks_common_name and host_ip is None and not dnsnames: - for sub in cert.get("subject", ()): - for key, value in sub: - if key == "commonName": - if _dnsname_match(value, hostname): - return - dnsnames.append( - value - ) # Defensive: for older PyPy and OpenSSL versions - - if len(dnsnames) > 1: - raise CertificateError( - "hostname %r " - "doesn't match either of %s" % (hostname, ", ".join(map(repr, dnsnames))) - ) - elif len(dnsnames) == 1: - raise CertificateError(f"hostname {hostname!r} doesn't match {dnsnames[0]!r}") - else: - raise CertificateError("no appropriate subjectAltName fields were found") diff --git a/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/ssltransport.py b/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/ssltransport.py deleted file mode 100755 index 6d59bc3..0000000 --- a/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/ssltransport.py +++ /dev/null @@ -1,271 +0,0 @@ -from __future__ import annotations - -import io -import socket -import ssl -import typing - -from ..exceptions import ProxySchemeUnsupported - -if typing.TYPE_CHECKING: - from typing_extensions import Self - - from .ssl_ import _TYPE_PEER_CERT_RET, _TYPE_PEER_CERT_RET_DICT - - -_WriteBuffer = typing.Union[bytearray, memoryview] -_ReturnValue = typing.TypeVar("_ReturnValue") - -SSL_BLOCKSIZE = 16384 - - -class SSLTransport: - """ - The SSLTransport wraps an existing socket and establishes an SSL connection. - - Contrary to Python's implementation of SSLSocket, it allows you to chain - multiple TLS connections together. It's particularly useful if you need to - implement TLS within TLS. - - The class supports most of the socket API operations. - """ - - @staticmethod - def _validate_ssl_context_for_tls_in_tls(ssl_context: ssl.SSLContext) -> None: - """ - Raises a ProxySchemeUnsupported if the provided ssl_context can't be used - for TLS in TLS. - - The only requirement is that the ssl_context provides the 'wrap_bio' - methods. - """ - - if not hasattr(ssl_context, "wrap_bio"): - raise ProxySchemeUnsupported( - "TLS in TLS requires SSLContext.wrap_bio() which isn't " - "available on non-native SSLContext" - ) - - def __init__( - self, - socket: socket.socket, - ssl_context: ssl.SSLContext, - server_hostname: str | None = None, - suppress_ragged_eofs: bool = True, - ) -> None: - """ - Create an SSLTransport around socket using the provided ssl_context. - """ - self.incoming = ssl.MemoryBIO() - self.outgoing = ssl.MemoryBIO() - - self.suppress_ragged_eofs = suppress_ragged_eofs - self.socket = socket - - self.sslobj = ssl_context.wrap_bio( - self.incoming, self.outgoing, server_hostname=server_hostname - ) - - # Perform initial handshake. - self._ssl_io_loop(self.sslobj.do_handshake) - - def __enter__(self) -> Self: - return self - - def __exit__(self, *_: typing.Any) -> None: - self.close() - - def fileno(self) -> int: - return self.socket.fileno() - - def read(self, len: int = 1024, buffer: typing.Any | None = None) -> int | bytes: - return self._wrap_ssl_read(len, buffer) - - def recv(self, buflen: int = 1024, flags: int = 0) -> int | bytes: - if flags != 0: - raise ValueError("non-zero flags not allowed in calls to recv") - return self._wrap_ssl_read(buflen) - - def recv_into( - self, - buffer: _WriteBuffer, - nbytes: int | None = None, - flags: int = 0, - ) -> None | int | bytes: - if flags != 0: - raise ValueError("non-zero flags not allowed in calls to recv_into") - if nbytes is None: - nbytes = len(buffer) - return self.read(nbytes, buffer) - - def sendall(self, data: bytes, flags: int = 0) -> None: - if flags != 0: - raise ValueError("non-zero flags not allowed in calls to sendall") - count = 0 - with memoryview(data) as view, view.cast("B") as byte_view: - amount = len(byte_view) - while count < amount: - v = self.send(byte_view[count:]) - count += v - - def send(self, data: bytes, flags: int = 0) -> int: - if flags != 0: - raise ValueError("non-zero flags not allowed in calls to send") - return self._ssl_io_loop(self.sslobj.write, data) - - def makefile( - self, - mode: str, - buffering: int | None = None, - *, - encoding: str | None = None, - errors: str | None = None, - newline: str | None = None, - ) -> typing.BinaryIO | typing.TextIO | socket.SocketIO: - """ - Python's httpclient uses makefile and buffered io when reading HTTP - messages and we need to support it. - - This is unfortunately a copy and paste of socket.py makefile with small - changes to point to the socket directly. - """ - if not set(mode) <= {"r", "w", "b"}: - raise ValueError(f"invalid mode {mode!r} (only r, w, b allowed)") - - writing = "w" in mode - reading = "r" in mode or not writing - assert reading or writing - binary = "b" in mode - rawmode = "" - if reading: - rawmode += "r" - if writing: - rawmode += "w" - raw = socket.SocketIO(self, rawmode) # type: ignore[arg-type] - self.socket._io_refs += 1 # type: ignore[attr-defined] - if buffering is None: - buffering = -1 - if buffering < 0: - buffering = io.DEFAULT_BUFFER_SIZE - if buffering == 0: - if not binary: - raise ValueError("unbuffered streams must be binary") - return raw - buffer: typing.BinaryIO - if reading and writing: - buffer = io.BufferedRWPair(raw, raw, buffering) # type: ignore[assignment] - elif reading: - buffer = io.BufferedReader(raw, buffering) - else: - assert writing - buffer = io.BufferedWriter(raw, buffering) - if binary: - return buffer - text = io.TextIOWrapper(buffer, encoding, errors, newline) - text.mode = mode # type: ignore[misc] - return text - - def unwrap(self) -> None: - self._ssl_io_loop(self.sslobj.unwrap) - - def close(self) -> None: - self.socket.close() - - @typing.overload - def getpeercert( - self, binary_form: typing.Literal[False] = ... - ) -> _TYPE_PEER_CERT_RET_DICT | None: ... - - @typing.overload - def getpeercert(self, binary_form: typing.Literal[True]) -> bytes | None: ... - - def getpeercert(self, binary_form: bool = False) -> _TYPE_PEER_CERT_RET: - return self.sslobj.getpeercert(binary_form) # type: ignore[return-value] - - def version(self) -> str | None: - return self.sslobj.version() - - def cipher(self) -> tuple[str, str, int] | None: - return self.sslobj.cipher() - - def selected_alpn_protocol(self) -> str | None: - return self.sslobj.selected_alpn_protocol() - - def shared_ciphers(self) -> list[tuple[str, str, int]] | None: - return self.sslobj.shared_ciphers() - - def compression(self) -> str | None: - return self.sslobj.compression() - - def settimeout(self, value: float | None) -> None: - self.socket.settimeout(value) - - def gettimeout(self) -> float | None: - return self.socket.gettimeout() - - def _decref_socketios(self) -> None: - self.socket._decref_socketios() # type: ignore[attr-defined] - - def _wrap_ssl_read(self, len: int, buffer: bytearray | None = None) -> int | bytes: - try: - return self._ssl_io_loop(self.sslobj.read, len, buffer) - except ssl.SSLError as e: - if e.errno == ssl.SSL_ERROR_EOF and self.suppress_ragged_eofs: - return 0 # eof, return 0. - else: - raise - - # func is sslobj.do_handshake or sslobj.unwrap - @typing.overload - def _ssl_io_loop(self, func: typing.Callable[[], None]) -> None: ... - - # func is sslobj.write, arg1 is data - @typing.overload - def _ssl_io_loop(self, func: typing.Callable[[bytes], int], arg1: bytes) -> int: ... - - # func is sslobj.read, arg1 is len, arg2 is buffer - @typing.overload - def _ssl_io_loop( - self, - func: typing.Callable[[int, bytearray | None], bytes], - arg1: int, - arg2: bytearray | None, - ) -> bytes: ... - - def _ssl_io_loop( - self, - func: typing.Callable[..., _ReturnValue], - arg1: None | bytes | int = None, - arg2: bytearray | None = None, - ) -> _ReturnValue: - """Performs an I/O loop between incoming/outgoing and the socket.""" - should_loop = True - ret = None - - while should_loop: - errno = None - try: - if arg1 is None and arg2 is None: - ret = func() - elif arg2 is None: - ret = func(arg1) - else: - ret = func(arg1, arg2) - except ssl.SSLError as e: - if e.errno not in (ssl.SSL_ERROR_WANT_READ, ssl.SSL_ERROR_WANT_WRITE): - # WANT_READ, and WANT_WRITE are expected, others are not. - raise e - errno = e.errno - - buf = self.outgoing.read() - self.socket.sendall(buf) - - if errno is None: - should_loop = False - elif errno == ssl.SSL_ERROR_WANT_READ: - buf = self.socket.recv(SSL_BLOCKSIZE) - if buf: - self.incoming.write(buf) - else: - self.incoming.write_eof() - return typing.cast(_ReturnValue, ret) diff --git a/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/timeout.py b/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/timeout.py deleted file mode 100755 index c6cdb35..0000000 --- a/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/timeout.py +++ /dev/null @@ -1,275 +0,0 @@ -from __future__ import annotations - -import time -import typing -from enum import Enum -from socket import getdefaulttimeout - -from ..exceptions import TimeoutStateError - -if typing.TYPE_CHECKING: - from typing import Final - - -class _TYPE_DEFAULT(Enum): - # This value should never be passed to socket.settimeout() so for safety we use a -1. - # socket.settimout() raises a ValueError for negative values. - token = -1 - - -_DEFAULT_TIMEOUT: Final[_TYPE_DEFAULT] = _TYPE_DEFAULT.token - -_TYPE_TIMEOUT = typing.Optional[typing.Union[float, _TYPE_DEFAULT]] - - -class Timeout: - """Timeout configuration. - - Timeouts can be defined as a default for a pool: - - .. code-block:: python - - from pip._vendor import urllib3 - - timeout = urllib3.util.Timeout(connect=2.0, read=7.0) - - http = urllib3.PoolManager(timeout=timeout) - - resp = http.request("GET", "https://example.com/") - - print(resp.status) - - Or per-request (which overrides the default for the pool): - - .. code-block:: python - - response = http.request("GET", "https://example.com/", timeout=Timeout(10)) - - Timeouts can be disabled by setting all the parameters to ``None``: - - .. code-block:: python - - no_timeout = Timeout(connect=None, read=None) - response = http.request("GET", "https://example.com/", timeout=no_timeout) - - - :param total: - This combines the connect and read timeouts into one; the read timeout - will be set to the time leftover from the connect attempt. In the - event that both a connect timeout and a total are specified, or a read - timeout and a total are specified, the shorter timeout will be applied. - - Defaults to None. - - :type total: int, float, or None - - :param connect: - The maximum amount of time (in seconds) to wait for a connection - attempt to a server to succeed. Omitting the parameter will default the - connect timeout to the system default, probably `the global default - timeout in socket.py - `_. - None will set an infinite timeout for connection attempts. - - :type connect: int, float, or None - - :param read: - The maximum amount of time (in seconds) to wait between consecutive - read operations for a response from the server. Omitting the parameter - will default the read timeout to the system default, probably `the - global default timeout in socket.py - `_. - None will set an infinite timeout. - - :type read: int, float, or None - - .. note:: - - Many factors can affect the total amount of time for urllib3 to return - an HTTP response. - - For example, Python's DNS resolver does not obey the timeout specified - on the socket. Other factors that can affect total request time include - high CPU load, high swap, the program running at a low priority level, - or other behaviors. - - In addition, the read and total timeouts only measure the time between - read operations on the socket connecting the client and the server, - not the total amount of time for the request to return a complete - response. For most requests, the timeout is raised because the server - has not sent the first byte in the specified time. This is not always - the case; if a server streams one byte every fifteen seconds, a timeout - of 20 seconds will not trigger, even though the request will take - several minutes to complete. - """ - - #: A sentinel object representing the default timeout value - DEFAULT_TIMEOUT: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT - - def __init__( - self, - total: _TYPE_TIMEOUT = None, - connect: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, - read: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT, - ) -> None: - self._connect = self._validate_timeout(connect, "connect") - self._read = self._validate_timeout(read, "read") - self.total = self._validate_timeout(total, "total") - self._start_connect: float | None = None - - def __repr__(self) -> str: - return f"{type(self).__name__}(connect={self._connect!r}, read={self._read!r}, total={self.total!r})" - - # __str__ provided for backwards compatibility - __str__ = __repr__ - - @staticmethod - def resolve_default_timeout(timeout: _TYPE_TIMEOUT) -> float | None: - return getdefaulttimeout() if timeout is _DEFAULT_TIMEOUT else timeout - - @classmethod - def _validate_timeout(cls, value: _TYPE_TIMEOUT, name: str) -> _TYPE_TIMEOUT: - """Check that a timeout attribute is valid. - - :param value: The timeout value to validate - :param name: The name of the timeout attribute to validate. This is - used to specify in error messages. - :return: The validated and casted version of the given value. - :raises ValueError: If it is a numeric value less than or equal to - zero, or the type is not an integer, float, or None. - """ - if value is None or value is _DEFAULT_TIMEOUT: - return value - - if isinstance(value, bool): - raise ValueError( - "Timeout cannot be a boolean value. It must " - "be an int, float or None." - ) - try: - float(value) - except (TypeError, ValueError): - raise ValueError( - "Timeout value %s was %s, but it must be an " - "int, float or None." % (name, value) - ) from None - - try: - if value <= 0: - raise ValueError( - "Attempted to set %s timeout to %s, but the " - "timeout cannot be set to a value less " - "than or equal to 0." % (name, value) - ) - except TypeError: - raise ValueError( - "Timeout value %s was %s, but it must be an " - "int, float or None." % (name, value) - ) from None - - return value - - @classmethod - def from_float(cls, timeout: _TYPE_TIMEOUT) -> Timeout: - """Create a new Timeout from a legacy timeout value. - - The timeout value used by httplib.py sets the same timeout on the - connect(), and recv() socket requests. This creates a :class:`Timeout` - object that sets the individual timeouts to the ``timeout`` value - passed to this function. - - :param timeout: The legacy timeout value. - :type timeout: integer, float, :attr:`urllib3.util.Timeout.DEFAULT_TIMEOUT`, or None - :return: Timeout object - :rtype: :class:`Timeout` - """ - return Timeout(read=timeout, connect=timeout) - - def clone(self) -> Timeout: - """Create a copy of the timeout object - - Timeout properties are stored per-pool but each request needs a fresh - Timeout object to ensure each one has its own start/stop configured. - - :return: a copy of the timeout object - :rtype: :class:`Timeout` - """ - # We can't use copy.deepcopy because that will also create a new object - # for _GLOBAL_DEFAULT_TIMEOUT, which socket.py uses as a sentinel to - # detect the user default. - return Timeout(connect=self._connect, read=self._read, total=self.total) - - def start_connect(self) -> float: - """Start the timeout clock, used during a connect() attempt - - :raises urllib3.exceptions.TimeoutStateError: if you attempt - to start a timer that has been started already. - """ - if self._start_connect is not None: - raise TimeoutStateError("Timeout timer has already been started.") - self._start_connect = time.monotonic() - return self._start_connect - - def get_connect_duration(self) -> float: - """Gets the time elapsed since the call to :meth:`start_connect`. - - :return: Elapsed time in seconds. - :rtype: float - :raises urllib3.exceptions.TimeoutStateError: if you attempt - to get duration for a timer that hasn't been started. - """ - if self._start_connect is None: - raise TimeoutStateError( - "Can't get connect duration for timer that has not started." - ) - return time.monotonic() - self._start_connect - - @property - def connect_timeout(self) -> _TYPE_TIMEOUT: - """Get the value to use when setting a connection timeout. - - This will be a positive float or integer, the value None - (never timeout), or the default system timeout. - - :return: Connect timeout. - :rtype: int, float, :attr:`Timeout.DEFAULT_TIMEOUT` or None - """ - if self.total is None: - return self._connect - - if self._connect is None or self._connect is _DEFAULT_TIMEOUT: - return self.total - - return min(self._connect, self.total) # type: ignore[type-var] - - @property - def read_timeout(self) -> float | None: - """Get the value for the read timeout. - - This assumes some time has elapsed in the connection timeout and - computes the read timeout appropriately. - - If self.total is set, the read timeout is dependent on the amount of - time taken by the connect timeout. If the connection time has not been - established, a :exc:`~urllib3.exceptions.TimeoutStateError` will be - raised. - - :return: Value to use for the read timeout. - :rtype: int, float or None - :raises urllib3.exceptions.TimeoutStateError: If :meth:`start_connect` - has not yet been called on this object. - """ - if ( - self.total is not None - and self.total is not _DEFAULT_TIMEOUT - and self._read is not None - and self._read is not _DEFAULT_TIMEOUT - ): - # In case the connect timeout has not yet been established. - if self._start_connect is None: - return self._read - return max(0, min(self.total - self.get_connect_duration(), self._read)) - elif self.total is not None and self.total is not _DEFAULT_TIMEOUT: - return max(0, self.total - self.get_connect_duration()) - else: - return self.resolve_default_timeout(self._read) diff --git a/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/url.py b/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/url.py deleted file mode 100755 index 82b174c..0000000 --- a/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/url.py +++ /dev/null @@ -1,469 +0,0 @@ -from __future__ import annotations - -import re -import typing - -from ..exceptions import LocationParseError -from .util import to_str - -# We only want to normalize urls with an HTTP(S) scheme. -# urllib3 infers URLs without a scheme (None) to be http. -_NORMALIZABLE_SCHEMES = ("http", "https", None) - -# Almost all of these patterns were derived from the -# 'rfc3986' module: https://github.com/python-hyper/rfc3986 -_PERCENT_RE = re.compile(r"%[a-fA-F0-9]{2}") -_SCHEME_RE = re.compile(r"^(?:[a-zA-Z][a-zA-Z0-9+-]*:|/)") -_URI_RE = re.compile( - r"^(?:([a-zA-Z][a-zA-Z0-9+.-]*):)?" - r"(?://([^\\/?#]*))?" - r"([^?#]*)" - r"(?:\?([^#]*))?" - r"(?:#(.*))?$", - re.UNICODE | re.DOTALL, -) - -_IPV4_PAT = r"(?:[0-9]{1,3}\.){3}[0-9]{1,3}" -_HEX_PAT = "[0-9A-Fa-f]{1,4}" -_LS32_PAT = "(?:{hex}:{hex}|{ipv4})".format(hex=_HEX_PAT, ipv4=_IPV4_PAT) -_subs = {"hex": _HEX_PAT, "ls32": _LS32_PAT} -_variations = [ - # 6( h16 ":" ) ls32 - "(?:%(hex)s:){6}%(ls32)s", - # "::" 5( h16 ":" ) ls32 - "::(?:%(hex)s:){5}%(ls32)s", - # [ h16 ] "::" 4( h16 ":" ) ls32 - "(?:%(hex)s)?::(?:%(hex)s:){4}%(ls32)s", - # [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32 - "(?:(?:%(hex)s:)?%(hex)s)?::(?:%(hex)s:){3}%(ls32)s", - # [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32 - "(?:(?:%(hex)s:){0,2}%(hex)s)?::(?:%(hex)s:){2}%(ls32)s", - # [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32 - "(?:(?:%(hex)s:){0,3}%(hex)s)?::%(hex)s:%(ls32)s", - # [ *4( h16 ":" ) h16 ] "::" ls32 - "(?:(?:%(hex)s:){0,4}%(hex)s)?::%(ls32)s", - # [ *5( h16 ":" ) h16 ] "::" h16 - "(?:(?:%(hex)s:){0,5}%(hex)s)?::%(hex)s", - # [ *6( h16 ":" ) h16 ] "::" - "(?:(?:%(hex)s:){0,6}%(hex)s)?::", -] - -_UNRESERVED_PAT = r"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._\-~" -_IPV6_PAT = "(?:" + "|".join([x % _subs for x in _variations]) + ")" -_ZONE_ID_PAT = "(?:%25|%)(?:[" + _UNRESERVED_PAT + "]|%[a-fA-F0-9]{2})+" -_IPV6_ADDRZ_PAT = r"\[" + _IPV6_PAT + r"(?:" + _ZONE_ID_PAT + r")?\]" -_REG_NAME_PAT = r"(?:[^\[\]%:/?#]|%[a-fA-F0-9]{2})*" -_TARGET_RE = re.compile(r"^(/[^?#]*)(?:\?([^#]*))?(?:#.*)?$") - -_IPV4_RE = re.compile("^" + _IPV4_PAT + "$") -_IPV6_RE = re.compile("^" + _IPV6_PAT + "$") -_IPV6_ADDRZ_RE = re.compile("^" + _IPV6_ADDRZ_PAT + "$") -_BRACELESS_IPV6_ADDRZ_RE = re.compile("^" + _IPV6_ADDRZ_PAT[2:-2] + "$") -_ZONE_ID_RE = re.compile("(" + _ZONE_ID_PAT + r")\]$") - -_HOST_PORT_PAT = ("^(%s|%s|%s)(?::0*?(|0|[1-9][0-9]{0,4}))?$") % ( - _REG_NAME_PAT, - _IPV4_PAT, - _IPV6_ADDRZ_PAT, -) -_HOST_PORT_RE = re.compile(_HOST_PORT_PAT, re.UNICODE | re.DOTALL) - -_UNRESERVED_CHARS = set( - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._-~" -) -_SUB_DELIM_CHARS = set("!$&'()*+,;=") -_USERINFO_CHARS = _UNRESERVED_CHARS | _SUB_DELIM_CHARS | {":"} -_PATH_CHARS = _USERINFO_CHARS | {"@", "/"} -_QUERY_CHARS = _FRAGMENT_CHARS = _PATH_CHARS | {"?"} - - -class Url( - typing.NamedTuple( - "Url", - [ - ("scheme", typing.Optional[str]), - ("auth", typing.Optional[str]), - ("host", typing.Optional[str]), - ("port", typing.Optional[int]), - ("path", typing.Optional[str]), - ("query", typing.Optional[str]), - ("fragment", typing.Optional[str]), - ], - ) -): - """ - Data structure for representing an HTTP URL. Used as a return value for - :func:`parse_url`. Both the scheme and host are normalized as they are - both case-insensitive according to RFC 3986. - """ - - def __new__( # type: ignore[no-untyped-def] - cls, - scheme: str | None = None, - auth: str | None = None, - host: str | None = None, - port: int | None = None, - path: str | None = None, - query: str | None = None, - fragment: str | None = None, - ): - if path and not path.startswith("/"): - path = "/" + path - if scheme is not None: - scheme = scheme.lower() - return super().__new__(cls, scheme, auth, host, port, path, query, fragment) - - @property - def hostname(self) -> str | None: - """For backwards-compatibility with urlparse. We're nice like that.""" - return self.host - - @property - def request_uri(self) -> str: - """Absolute path including the query string.""" - uri = self.path or "/" - - if self.query is not None: - uri += "?" + self.query - - return uri - - @property - def authority(self) -> str | None: - """ - Authority component as defined in RFC 3986 3.2. - This includes userinfo (auth), host and port. - - i.e. - userinfo@host:port - """ - userinfo = self.auth - netloc = self.netloc - if netloc is None or userinfo is None: - return netloc - else: - return f"{userinfo}@{netloc}" - - @property - def netloc(self) -> str | None: - """ - Network location including host and port. - - If you need the equivalent of urllib.parse's ``netloc``, - use the ``authority`` property instead. - """ - if self.host is None: - return None - if self.port: - return f"{self.host}:{self.port}" - return self.host - - @property - def url(self) -> str: - """ - Convert self into a url - - This function should more or less round-trip with :func:`.parse_url`. The - returned url may not be exactly the same as the url inputted to - :func:`.parse_url`, but it should be equivalent by the RFC (e.g., urls - with a blank port will have : removed). - - Example: - - .. code-block:: python - - from pip._vendor import urllib3 - - U = urllib3.util.parse_url("https://google.com/mail/") - - print(U.url) - # "https://google.com/mail/" - - print( urllib3.util.Url("https", "username:password", - "host.com", 80, "/path", "query", "fragment" - ).url - ) - # "https://username:password@host.com:80/path?query#fragment" - """ - scheme, auth, host, port, path, query, fragment = self - url = "" - - # We use "is not None" we want things to happen with empty strings (or 0 port) - if scheme is not None: - url += scheme + "://" - if auth is not None: - url += auth + "@" - if host is not None: - url += host - if port is not None: - url += ":" + str(port) - if path is not None: - url += path - if query is not None: - url += "?" + query - if fragment is not None: - url += "#" + fragment - - return url - - def __str__(self) -> str: - return self.url - - -@typing.overload -def _encode_invalid_chars( - component: str, allowed_chars: typing.Container[str] -) -> str: # Abstract - ... - - -@typing.overload -def _encode_invalid_chars( - component: None, allowed_chars: typing.Container[str] -) -> None: # Abstract - ... - - -def _encode_invalid_chars( - component: str | None, allowed_chars: typing.Container[str] -) -> str | None: - """Percent-encodes a URI component without reapplying - onto an already percent-encoded component. - """ - if component is None: - return component - - component = to_str(component) - - # Normalize existing percent-encoded bytes. - # Try to see if the component we're encoding is already percent-encoded - # so we can skip all '%' characters but still encode all others. - component, percent_encodings = _PERCENT_RE.subn( - lambda match: match.group(0).upper(), component - ) - - uri_bytes = component.encode("utf-8", "surrogatepass") - is_percent_encoded = percent_encodings == uri_bytes.count(b"%") - encoded_component = bytearray() - - for i in range(0, len(uri_bytes)): - # Will return a single character bytestring - byte = uri_bytes[i : i + 1] - byte_ord = ord(byte) - if (is_percent_encoded and byte == b"%") or ( - byte_ord < 128 and byte.decode() in allowed_chars - ): - encoded_component += byte - continue - encoded_component.extend(b"%" + (hex(byte_ord)[2:].encode().zfill(2).upper())) - - return encoded_component.decode() - - -def _remove_path_dot_segments(path: str) -> str: - # See http://tools.ietf.org/html/rfc3986#section-5.2.4 for pseudo-code - segments = path.split("/") # Turn the path into a list of segments - output = [] # Initialize the variable to use to store output - - for segment in segments: - # '.' is the current directory, so ignore it, it is superfluous - if segment == ".": - continue - # Anything other than '..', should be appended to the output - if segment != "..": - output.append(segment) - # In this case segment == '..', if we can, we should pop the last - # element - elif output: - output.pop() - - # If the path starts with '/' and the output is empty or the first string - # is non-empty - if path.startswith("/") and (not output or output[0]): - output.insert(0, "") - - # If the path starts with '/.' or '/..' ensure we add one more empty - # string to add a trailing '/' - if path.endswith(("/.", "/..")): - output.append("") - - return "/".join(output) - - -@typing.overload -def _normalize_host(host: None, scheme: str | None) -> None: ... - - -@typing.overload -def _normalize_host(host: str, scheme: str | None) -> str: ... - - -def _normalize_host(host: str | None, scheme: str | None) -> str | None: - if host: - if scheme in _NORMALIZABLE_SCHEMES: - is_ipv6 = _IPV6_ADDRZ_RE.match(host) - if is_ipv6: - # IPv6 hosts of the form 'a::b%zone' are encoded in a URL as - # such per RFC 6874: 'a::b%25zone'. Unquote the ZoneID - # separator as necessary to return a valid RFC 4007 scoped IP. - match = _ZONE_ID_RE.search(host) - if match: - start, end = match.span(1) - zone_id = host[start:end] - - if zone_id.startswith("%25") and zone_id != "%25": - zone_id = zone_id[3:] - else: - zone_id = zone_id[1:] - zone_id = _encode_invalid_chars(zone_id, _UNRESERVED_CHARS) - return f"{host[:start].lower()}%{zone_id}{host[end:]}" - else: - return host.lower() - elif not _IPV4_RE.match(host): - return to_str( - b".".join([_idna_encode(label) for label in host.split(".")]), - "ascii", - ) - return host - - -def _idna_encode(name: str) -> bytes: - if not name.isascii(): - try: - from pip._vendor import idna - except ImportError: - raise LocationParseError( - "Unable to parse URL without the 'idna' module" - ) from None - - try: - return idna.encode(name.lower(), strict=True, std3_rules=True) - except idna.IDNAError: - raise LocationParseError( - f"Name '{name}' is not a valid IDNA label" - ) from None - - return name.lower().encode("ascii") - - -def _encode_target(target: str) -> str: - """Percent-encodes a request target so that there are no invalid characters - - Pre-condition for this function is that 'target' must start with '/'. - If that is the case then _TARGET_RE will always produce a match. - """ - match = _TARGET_RE.match(target) - if not match: # Defensive: - raise LocationParseError(f"{target!r} is not a valid request URI") - - path, query = match.groups() - encoded_target = _encode_invalid_chars(path, _PATH_CHARS) - if query is not None: - query = _encode_invalid_chars(query, _QUERY_CHARS) - encoded_target += "?" + query - return encoded_target - - -def parse_url(url: str) -> Url: - """ - Given a url, return a parsed :class:`.Url` namedtuple. Best-effort is - performed to parse incomplete urls. Fields not provided will be None. - This parser is RFC 3986 and RFC 6874 compliant. - - The parser logic and helper functions are based heavily on - work done in the ``rfc3986`` module. - - :param str url: URL to parse into a :class:`.Url` namedtuple. - - Partly backwards-compatible with :mod:`urllib.parse`. - - Example: - - .. code-block:: python - - from pip._vendor import urllib3 - - print( urllib3.util.parse_url('http://google.com/mail/')) - # Url(scheme='http', host='google.com', port=None, path='/mail/', ...) - - print( urllib3.util.parse_url('google.com:80')) - # Url(scheme=None, host='google.com', port=80, path=None, ...) - - print( urllib3.util.parse_url('/foo?bar')) - # Url(scheme=None, host=None, port=None, path='/foo', query='bar', ...) - """ - if not url: - # Empty - return Url() - - source_url = url - if not _SCHEME_RE.search(url): - url = "//" + url - - scheme: str | None - authority: str | None - auth: str | None - host: str | None - port: str | None - port_int: int | None - path: str | None - query: str | None - fragment: str | None - - try: - scheme, authority, path, query, fragment = _URI_RE.match(url).groups() # type: ignore[union-attr] - normalize_uri = scheme is None or scheme.lower() in _NORMALIZABLE_SCHEMES - - if scheme: - scheme = scheme.lower() - - if authority: - auth, _, host_port = authority.rpartition("@") - auth = auth or None - host, port = _HOST_PORT_RE.match(host_port).groups() # type: ignore[union-attr] - if auth and normalize_uri: - auth = _encode_invalid_chars(auth, _USERINFO_CHARS) - if port == "": - port = None - else: - auth, host, port = None, None, None - - if port is not None: - port_int = int(port) - if not (0 <= port_int <= 65535): - raise LocationParseError(url) - else: - port_int = None - - host = _normalize_host(host, scheme) - - if normalize_uri and path: - path = _remove_path_dot_segments(path) - path = _encode_invalid_chars(path, _PATH_CHARS) - if normalize_uri and query: - query = _encode_invalid_chars(query, _QUERY_CHARS) - if normalize_uri and fragment: - fragment = _encode_invalid_chars(fragment, _FRAGMENT_CHARS) - - except (ValueError, AttributeError) as e: - raise LocationParseError(source_url) from e - - # For the sake of backwards compatibility we put empty - # string values for path if there are any defined values - # beyond the path in the URL. - # TODO: Remove this when we break backwards compatibility. - if not path: - if query is not None or fragment is not None: - path = "" - else: - path = None - - return Url( - scheme=scheme, - auth=auth, - host=host, - port=port_int, - path=path, - query=query, - fragment=fragment, - ) diff --git a/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/util.py b/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/util.py deleted file mode 100755 index 35c77e4..0000000 --- a/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/util.py +++ /dev/null @@ -1,42 +0,0 @@ -from __future__ import annotations - -import typing -from types import TracebackType - - -def to_bytes( - x: str | bytes, encoding: str | None = None, errors: str | None = None -) -> bytes: - if isinstance(x, bytes): - return x - elif not isinstance(x, str): - raise TypeError(f"not expecting type {type(x).__name__}") - if encoding or errors: - return x.encode(encoding or "utf-8", errors=errors or "strict") - return x.encode() - - -def to_str( - x: str | bytes, encoding: str | None = None, errors: str | None = None -) -> str: - if isinstance(x, str): - return x - elif not isinstance(x, bytes): - raise TypeError(f"not expecting type {type(x).__name__}") - if encoding or errors: - return x.decode(encoding or "utf-8", errors=errors or "strict") - return x.decode() - - -def reraise( - tp: type[BaseException] | None, - value: BaseException, - tb: TracebackType | None = None, -) -> typing.NoReturn: - try: - if value.__traceback__ is not tb: - raise value.with_traceback(tb) - raise value - finally: - value = None # type: ignore[assignment] - tb = None diff --git a/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/wait.py b/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/wait.py deleted file mode 100755 index aeca0c7..0000000 --- a/venv/lib/python3.11/site-packages/pip/_vendor/urllib3/util/wait.py +++ /dev/null @@ -1,124 +0,0 @@ -from __future__ import annotations - -import select -import socket -from functools import partial - -__all__ = ["wait_for_read", "wait_for_write"] - - -# How should we wait on sockets? -# -# There are two types of APIs you can use for waiting on sockets: the fancy -# modern stateful APIs like epoll/kqueue, and the older stateless APIs like -# select/poll. The stateful APIs are more efficient when you have a lots of -# sockets to keep track of, because you can set them up once and then use them -# lots of times. But we only ever want to wait on a single socket at a time -# and don't want to keep track of state, so the stateless APIs are actually -# more efficient. So we want to use select() or poll(). -# -# Now, how do we choose between select() and poll()? On traditional Unixes, -# select() has a strange calling convention that makes it slow, or fail -# altogether, for high-numbered file descriptors. The point of poll() is to fix -# that, so on Unixes, we prefer poll(). -# -# On Windows, there is no poll() (or at least Python doesn't provide a wrapper -# for it), but that's OK, because on Windows, select() doesn't have this -# strange calling convention; plain select() works fine. -# -# So: on Windows we use select(), and everywhere else we use poll(). We also -# fall back to select() in case poll() is somehow broken or missing. - - -def select_wait_for_socket( - sock: socket.socket, - read: bool = False, - write: bool = False, - timeout: float | None = None, -) -> bool: - if not read and not write: - raise RuntimeError("must specify at least one of read=True, write=True") - rcheck = [] - wcheck = [] - if read: - rcheck.append(sock) - if write: - wcheck.append(sock) - # When doing a non-blocking connect, most systems signal success by - # marking the socket writable. Windows, though, signals success by marked - # it as "exceptional". We paper over the difference by checking the write - # sockets for both conditions. (The stdlib selectors module does the same - # thing.) - fn = partial(select.select, rcheck, wcheck, wcheck) - rready, wready, xready = fn(timeout) - return bool(rready or wready or xready) - - -def poll_wait_for_socket( - sock: socket.socket, - read: bool = False, - write: bool = False, - timeout: float | None = None, -) -> bool: - if not read and not write: - raise RuntimeError("must specify at least one of read=True, write=True") - mask = 0 - if read: - mask |= select.POLLIN - if write: - mask |= select.POLLOUT - poll_obj = select.poll() - poll_obj.register(sock, mask) - - # For some reason, poll() takes timeout in milliseconds - def do_poll(t: float | None) -> list[tuple[int, int]]: - if t is not None: - t *= 1000 - return poll_obj.poll(t) - - return bool(do_poll(timeout)) - - -def _have_working_poll() -> bool: - # Apparently some systems have a select.poll that fails as soon as you try - # to use it, either due to strange configuration or broken monkeypatching - # from libraries like eventlet/greenlet. - try: - poll_obj = select.poll() - poll_obj.poll(0) - except (AttributeError, OSError): - return False - else: - return True - - -def wait_for_socket( - sock: socket.socket, - read: bool = False, - write: bool = False, - timeout: float | None = None, -) -> bool: - # We delay choosing which implementation to use until the first time we're - # called. We could do it at import time, but then we might make the wrong - # decision if someone goes wild with monkeypatching select.poll after - # we're imported. - global wait_for_socket - if _have_working_poll(): - wait_for_socket = poll_wait_for_socket - elif hasattr(select, "select"): - wait_for_socket = select_wait_for_socket - return wait_for_socket(sock, read, write, timeout) - - -def wait_for_read(sock: socket.socket, timeout: float | None = None) -> bool: - """Waits for reading to be available on a given socket. - Returns True if the socket is readable, or False if the timeout expired. - """ - return wait_for_socket(sock, read=True, timeout=timeout) - - -def wait_for_write(sock: socket.socket, timeout: float | None = None) -> bool: - """Waits for writing to be available on a given socket. - Returns True if the socket is readable, or False if the timeout expired. - """ - return wait_for_socket(sock, write=True, timeout=timeout) diff --git a/venv/lib/python3.11/site-packages/pip/_vendor/vendor.txt b/venv/lib/python3.11/site-packages/pip/_vendor/vendor.txt deleted file mode 100755 index 75f337a..0000000 --- a/venv/lib/python3.11/site-packages/pip/_vendor/vendor.txt +++ /dev/null @@ -1,18 +0,0 @@ -CacheControl==0.14.4 -distlib==0.4.2 -distro==1.9.0 -msgpack==1.1.2 -packaging==26.2 -platformdirs==4.10.0 -pyproject-hooks==1.2.0 -requests==2.34.2 - certifi==2026.6.17 - idna==3.18 - urllib3==2.7.0 -rich==14.2.0 - pygments==2.20.0 -resolvelib==1.2.1 -setuptools==70.3.0 -tomli==2.4.1 -tomli-w==1.2.0 -truststore==0.10.4 diff --git a/venv/lib/python3.11/site-packages/pip/py.typed b/venv/lib/python3.11/site-packages/pip/py.typed deleted file mode 100755 index 493b53e..0000000 --- a/venv/lib/python3.11/site-packages/pip/py.typed +++ /dev/null @@ -1,4 +0,0 @@ -pip is a command line program. While it is implemented in Python, and so is -available for import, you must not use pip's internal APIs in this way. Typing -information is provided as a convenience only and is not a guarantee. Expect -unannounced changes to the API and types in releases. diff --git a/venv/lib/python3.11/site-packages/pkg_resources/__init__.py b/venv/lib/python3.11/site-packages/pkg_resources/__init__.py deleted file mode 100755 index 0ae951b..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/__init__.py +++ /dev/null @@ -1,3282 +0,0 @@ -""" -Package resource API --------------------- - -A resource is a logical file contained within a package, or a logical -subdirectory thereof. The package resource API expects resource names -to have their path parts separated with ``/``, *not* whatever the local -path separator is. Do not use os.path operations to manipulate resource -names being passed into the API. - -The package resource API is designed to work with normal filesystem packages, -.egg files, and unpacked .egg files. It can also work in a limited way with -.zip files and with custom PEP 302 loaders that support the ``get_data()`` -method. -""" - -import sys -import os -import io -import time -import re -import types -import zipfile -import zipimport -import warnings -import stat -import functools -import pkgutil -import operator -import platform -import collections -import plistlib -import email.parser -import errno -import tempfile -import textwrap -import inspect -import ntpath -import posixpath -import importlib -from pkgutil import get_importer - -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 - -try: - from os import mkdir, rename, unlink - - WRITE_SUPPORT = True -except ImportError: - # 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 pkg_resources.extern.jaraco.text import ( - yield_lines, - drop_comment, - join_continuation, -) - -from pkg_resources.extern import platformdirs -from pkg_resources.extern import packaging - -__import__('pkg_resources.extern.packaging.version') -__import__('pkg_resources.extern.packaging.specifiers') -__import__('pkg_resources.extern.packaging.requirements') -__import__('pkg_resources.extern.packaging.markers') -__import__('pkg_resources.extern.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 - - -class PEP440Warning(RuntimeWarning): - """ - Used when there is an issue with a version or specifier not complying with - PEP 440. - """ - - -parse_version = packaging.version.Version - - -_state_vars = {} - - -def _declare_state(vartype, **kw): - globals().update(kw) - _state_vars.update(dict.fromkeys(kw, vartype)) - - -def __getstate__(): - state = {} - g = globals() - for k, v in _state_vars.items(): - state[k] = g['_sget_' + v](g[k]) - return state - - -def __setstate__(state): - g = globals() - for k, v in state.items(): - g['_sset_' + _state_vars[k]](k, g[k], v) - return state - - -def _sget_dict(val): - return val.copy() - - -def _sset_dict(key, ob, state): - ob.clear() - ob.update(state) - - -def _sget_object(val): - return val.__getstate__() - - -def _sset_object(key, ob, state): - ob.__setstate__(state) - - -_sget_none = _sset_none = lambda *args: None - - -def get_supported_platform(): - """Return this platform's maximum compatible version. - - distutils.util.get_platform() normally reports the minimum version - of macOS that would be required to *use* extensions produced by - distutils. But what we want when checking compatibility is to know the - version of macOS that we are *running*. To allow usage of packages that - explicitly require a newer version of macOS, we must also know the - current version of the OS. - - If this condition occurs for any other platform with a version in its - platform strings, this function should be extended accordingly. - """ - plat = get_build_platform() - m = macosVersionString.match(plat) - if m is not None and sys.platform == "darwin": - try: - plat = 'macosx-%s-%s' % ('.'.join(_macos_vers()[:2]), m.group(3)) - except ValueError: - # not macOS - pass - return plat - - -__all__ = [ - # Basic resource access and distribution/entry point discovery - 'require', - 'run_script', - 'get_provider', - 'get_distribution', - 'load_entry_point', - 'get_entry_map', - 'get_entry_info', - 'iter_entry_points', - 'resource_string', - 'resource_stream', - 'resource_filename', - 'resource_listdir', - 'resource_exists', - 'resource_isdir', - # Environmental control - 'declare_namespace', - 'working_set', - 'add_activation_listener', - 'find_distributions', - 'set_extraction_path', - 'cleanup_resources', - 'get_default_cache', - # Primary implementation classes - 'Environment', - 'WorkingSet', - 'ResourceManager', - 'Distribution', - 'Requirement', - 'EntryPoint', - # Exceptions - 'ResolutionError', - 'VersionConflict', - 'DistributionNotFound', - 'UnknownExtra', - 'ExtractionError', - # Warnings - 'PEP440Warning', - # Parsing functions and string utilities - 'parse_requirements', - 'parse_version', - 'safe_name', - 'safe_version', - 'get_platform', - 'compatible_platforms', - 'yield_lines', - 'split_sections', - 'safe_extra', - 'to_filename', - 'invalid_marker', - 'evaluate_marker', - # filesystem utilities - 'ensure_directory', - 'normalize_path', - # Distribution "precedence" constants - 'EGG_DIST', - 'BINARY_DIST', - 'SOURCE_DIST', - 'CHECKOUT_DIST', - 'DEVELOP_DIST', - # "Provider" interfaces, implementations, and registration/lookup APIs - 'IMetadataProvider', - 'IResourceProvider', - 'FileMetadata', - 'PathMetadata', - 'EggMetadata', - 'EmptyProvider', - 'empty_provider', - 'NullProvider', - 'EggProvider', - 'DefaultProvider', - 'ZipProvider', - 'register_finder', - 'register_namespace_handler', - 'register_loader_type', - 'fixup_namespace_packages', - 'get_importer', - # Warnings - 'PkgResourcesDeprecationWarning', - # Deprecated/backward compatibility only - 'run_main', - 'AvailableDistributions', -] - - -class ResolutionError(Exception): - """Abstract base for dependency resolution errors""" - - def __repr__(self): - return self.__class__.__name__ + repr(self.args) - - -class VersionConflict(ResolutionError): - """ - An already-installed version conflicts with the requested version. - - Should be initialized with the installed Distribution and the requested - Requirement. - """ - - _template = "{self.dist} is installed but {self.req} is required" - - @property - def dist(self): - return self.args[0] - - @property - def req(self): - return self.args[1] - - def report(self): - return self._template.format(**locals()) - - def with_context(self, required_by): - """ - If required_by is non-empty, return a version of self that is a - ContextualVersionConflict. - """ - if not required_by: - return self - args = self.args + (required_by,) - return ContextualVersionConflict(*args) - - -class ContextualVersionConflict(VersionConflict): - """ - A VersionConflict that accepts a third parameter, the set of the - requirements that required the installed Distribution. - """ - - _template = VersionConflict._template + ' by {self.required_by}' - - @property - def required_by(self): - return self.args[2] - - -class DistributionNotFound(ResolutionError): - """A requested distribution was not found""" - - _template = ( - "The '{self.req}' distribution was not found " - "and is required by {self.requirers_str}" - ) - - @property - def req(self): - return self.args[0] - - @property - def requirers(self): - return self.args[1] - - @property - def requirers_str(self): - if not self.requirers: - return 'the application' - return ', '.join(self.requirers) - - def report(self): - return self._template.format(**locals()) - - def __str__(self): - return self.report() - - -class UnknownExtra(ResolutionError): - """Distribution doesn't have an "extra feature" of the given name""" - - -_provider_factories = {} - -PY_MAJOR = '{}.{}'.format(*sys.version_info) -EGG_DIST = 3 -BINARY_DIST = 2 -SOURCE_DIST = 1 -CHECKOUT_DIST = 0 -DEVELOP_DIST = -1 - - -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__``, - and `provider_factory` is a function that, passed a *module* object, - returns an ``IResourceProvider`` for that module. - """ - _provider_factories[loader_type] = provider_factory - - -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] - try: - module = sys.modules[moduleOrReq] - except KeyError: - __import__(moduleOrReq) - module = sys.modules[moduleOrReq] - loader = getattr(module, '__loader__', None) - return _find_adapter(_provider_factories, loader)(module) - - -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): - return {'PowerPC': 'ppc', 'Power_Macintosh': 'ppc'}.get(machine, machine) - - -def get_build_platform(): - """Return this platform's string for platform-specific distributions - - XXX Currently this is the same as ``distutils.util.get_platform()``, but it - needs some hacks for Linux and macOS. - """ - from sysconfig import get_platform - - plat = get_platform() - if sys.platform == "darwin" and not plat.startswith('macosx-'): - try: - version = _macos_vers() - machine = os.uname()[4].replace(" ", "_") - return "macosx-%d.%d-%s" % ( - int(version[0]), - int(version[1]), - _macos_arch(machine), - ) - except ValueError: - # if someone is running a non-Mac darwin system, this will fall - # through to the default implementation - pass - return plat - - -macosVersionString = re.compile(r"macosx-(\d+)\.(\d+)-(.*)") -darwinVersionString = re.compile(r"darwin-(\d+)\.(\d+)\.(\d+)-(.*)") -# XXX backward compat -get_platform = get_build_platform - - -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. - - XXX Needs compatibility checks for Linux and other unixy OSes. - """ - if provided is None or required is None or provided == required: - # easy case - return True - - # macOS special cases - reqMac = macosVersionString.match(required) - if reqMac: - provMac = macosVersionString.match(provided) - - # is this a Mac package? - if not provMac: - # this is backwards compatibility for packages built before - # setuptools 0.6. All packages built after this point will - # use the new macOS designation. - provDarwin = darwinVersionString.match(provided) - if provDarwin: - dversion = int(provDarwin.group(1)) - macosversion = "%s.%s" % (reqMac.group(1), reqMac.group(2)) - if ( - dversion == 7 - and macosversion >= "10.3" - or dversion == 8 - and macosversion >= "10.4" - ): - return True - # egg isn't macOS or legacy darwin - return False - - # are they the same major version and machine type? - if provMac.group(1) != reqMac.group(1) or provMac.group(3) != reqMac.group(3): - return False - - # is the required OS major update >= the provided one? - if int(provMac.group(2)) > int(reqMac.group(2)): - return False - - return True - - # XXX Linux and other platforms' special cases should go here - return False - - -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): - dist = get_provider(dist) - if not isinstance(dist, Distribution): - raise TypeError("Expected string, Requirement, or Distribution", dist) - return dist - - -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) - - -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, group, name): - """Return the EntryPoint object for `group`+`name`, or ``None``""" - return get_distribution(dist).get_entry_info(group, name) - - -class IMetadataProvider: - def has_metadata(name): - """Does the package's distribution contain the named metadata?""" - - def get_metadata(name): - """The named metadata resource as a string""" - - 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(name): - """Is the named metadata a directory? (like ``os.path.isdir()``)""" - - def metadata_listdir(name): - """List of metadata names in the directory (like ``os.listdir()``)""" - - def run_script(script_name, namespace): - """Execute the named script in the supplied namespace dictionary""" - - -class IResourceProvider(IMetadataProvider): - """An object that provides access to package resources""" - - def get_resource_filename(manager, resource_name): - """Return a true filesystem path for `resource_name` - - `manager` must be an ``IResourceManager``""" - - def get_resource_stream(manager, resource_name): - """Return a readable file-like object for `resource_name` - - `manager` must be an ``IResourceManager``""" - - def get_resource_string(manager, resource_name): - """Return a string containing the contents of `resource_name` - - `manager` must be an ``IResourceManager``""" - - def has_resource(resource_name): - """Does the package contain the named resource?""" - - def resource_isdir(resource_name): - """Is the named resource a directory? (like ``os.path.isdir()``)""" - - 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=None): - """Create working set from list of path entries (default=sys.path)""" - self.entries = [] - self.entry_keys = {} - self.by_key = {} - self.normalized_to_canonical_keys = {} - self.callbacks = [] - - if entries is None: - entries = sys.path - - for entry in entries: - self.add_entry(entry) - - @classmethod - def _build_master(cls): - """ - Prepare the master working set. - """ - ws = cls() - try: - from __main__ import __requires__ - except ImportError: - # The main program does not list any requirements - return ws - - # ensure the requirements are met - try: - ws.require(__requires__) - except VersionConflict: - return cls._build_from_requirements(__requires__) - - return ws - - @classmethod - def _build_from_requirements(cls, req_spec): - """ - Build a working set from a requirement spec. Rewrites sys.path. - """ - # try it without defaults already on sys.path - # by starting with an empty path - ws = cls([]) - reqs = parse_requirements(req_spec) - dists = ws.resolve(reqs, Environment()) - for dist in dists: - ws.add(dist) - - # add any missing entries from sys.path - for entry in sys.path: - if entry not in ws.entries: - ws.add_entry(entry) - - # then copy back to sys.path - sys.path[:] = ws.entries - return ws - - 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 - corresponding to the path entry, and they are added. `entry` is - always appended to ``.entries``, even if it is already present. - (This is because ``sys.path`` can contain the same value more than - once, and the ``.entries`` of the ``sys.path`` WorkingSet should always - equal ``sys.path``.) - """ - self.entry_keys.setdefault(entry, []) - self.entries.append(entry) - for dist in find_distributions(entry, True): - self.add(dist, entry, False) - - 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): - """Find a distribution matching requirement `req` - - If there is an active distribution for the requested project, this - returns it as long as it meets the version requirement specified by - `req`. But, if there is an active distribution for the project and it - does *not* meet the `req` requirement, ``VersionConflict`` is raised. - If there is no active distribution for the requested project, ``None`` - is returned. - """ - dist = self.by_key.get(req.key) - - if dist is None: - canonical_key = self.normalized_to_canonical_keys.get(req.key) - - if canonical_key is not None: - req.key = canonical_key - dist = self.by_key.get(canonical_key) - - if dist is not None and dist not in req: - # XXX add more info - raise VersionConflict(dist, req) - return dist - - 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 - distributions in the working set, otherwise only ones matching - both `group` and `name` are yielded (in distribution order). - """ - return ( - entry - for dist in self - for entry in dist.get_entry_map(group).values() - if name is None or name == entry.name - ) - - 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__'] - ns.clear() - ns['__name__'] = name - self.require(requires)[0].run_script(script_name, ns) - - 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 = {} - for item in self.entries: - if item not in self.entry_keys: - # workaround a cache issue - continue - - for key in self.entry_keys[item]: - if key not in seen: - seen[key] = 1 - yield self.by_key[key] - - 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`. - On exit from this routine, `entry` is added to the end of the working - set's ``.entries`` (if it wasn't already present). - - `dist` is only added to the working set if it's for a project that - doesn't already have a distribution in the set, unless `replace=True`. - If it's added, any callbacks registered with the ``subscribe()`` method - will be called. - """ - if insert: - dist.insert_on(self.entries, entry, replace=replace) - - if entry is None: - entry = dist.location - keys = self.entry_keys.setdefault(entry, []) - keys2 = self.entry_keys.setdefault(dist.location, []) - if not replace and dist.key in self.by_key: - # ignore hidden distros - return - - self.by_key[dist.key] = dist - 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) - if dist.key not in keys2: - keys2.append(dist.key) - self._added_new(dist) - - def resolve( - self, - 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`, - if supplied, should be an ``Environment`` instance. If - not supplied, it defaults to all distributions available within any - entry or distribution in the working set. `installer`, if supplied, - will be invoked with each requirement that cannot be met by an - already-installed distribution; it should return a ``Distribution`` or - ``None``. - - Unless `replace_conflicting=True`, raises a VersionConflict exception - if - any requirements are found on the path that have the correct name but - the wrong version. Otherwise, if an `installer` is supplied it will be - invoked to obtain the correct version of the requirement and activate - it. - - `extras` is a list of the extras to be used with these requirements. - This is important because extra requirements may look like `my_req; - extra = "my_extra"`, which would otherwise be interpreted as a purely - optional requirement. Instead, we want to be able to assert that these - requirements are truly required. - """ - - # set up the stack - requirements = list(requirements)[::-1] - # set of processed requirements - processed = {} - # key -> dist - best = {} - to_activate = [] - - req_extras = _ReqExtras() - - # Mapping of requirement to set of distributions that required it; - # useful for reporting info about conflicts. - required_by = collections.defaultdict(set) - - while requirements: - # process dependencies breadth-first - req = requirements.pop(0) - if req in processed: - # Ignore cyclic or redundant dependencies - continue - - if not req_extras.markers_pass(req, extras): - continue - - dist = self._resolve_dist( - req, best, replace_conflicting, env, installer, required_by, to_activate - ) - - # push the new requirements onto the stack - new_requirements = dist.requires(req.extras)[::-1] - requirements.extend(new_requirements) - - # Register the new requirements needed by req - for new_requirement in new_requirements: - required_by[new_requirement].add(req.project_name) - req_extras[new_requirement] = req.extras - - 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 - ): - dist = best.get(req.key) - if dist is None: - # Find the best distribution and add it to the map - dist = self.by_key.get(req.key) - if dist is None or (dist not in req and replace_conflicting): - ws = self - if env is None: - if dist is None: - env = Environment(self.entries) - else: - # Use an empty environment and workingset to avoid - # any further conflicts with the conflicting - # distribution - env = Environment([]) - ws = WorkingSet([]) - dist = best[req.key] = env.best_match( - req, ws, installer, replace_conflicting=replace_conflicting - ) - if dist is None: - requirers = required_by.get(req, None) - raise DistributionNotFound(req, requirers) - to_activate.append(dist) - if dist not in req: - # Oops, the "best" so far conflicts with a dependency - dependent_req = required_by[req] - raise VersionConflict(dist, req).with_context(dependent_req) - return dist - - def find_plugins(self, plugin_env, full_env=None, installer=None, fallback=True): - """Find all activatable distributions in `plugin_env` - - Example usage:: - - distributions, errors = working_set.find_plugins( - Environment(plugin_dirlist) - ) - # add plugins+libs to sys.path - map(working_set.add, distributions) - # display errors - print('Could not load', errors) - - The `plugin_env` should be an ``Environment`` instance that contains - only distributions that are in the project's "plugin directory" or - directories. The `full_env`, if supplied, should be an ``Environment`` - contains all currently-available distributions. If `full_env` is not - supplied, one is created automatically from the ``WorkingSet`` this - method is called on, which will typically mean that every directory on - ``sys.path`` will be scanned for distributions. - - `installer` is a standard installer callback as used by the - ``resolve()`` method. The `fallback` flag indicates whether we should - attempt to resolve older versions of a plugin if the newest version - cannot be resolved. - - This method returns a 2-tuple: (`distributions`, `error_info`), where - `distributions` is a list of the distributions found in `plugin_env` - that were loadable, along with any other distributions that are needed - to resolve their dependencies. `error_info` is a dictionary mapping - unloadable plugin distributions to an exception instance describing the - error that occurred. Usually this will be a ``DistributionNotFound`` or - ``VersionConflict`` instance. - """ - - plugin_projects = list(plugin_env) - # scan project names in alphabetic order - plugin_projects.sort() - - error_info = {} - distributions = {} - - if full_env is None: - env = Environment(self.entries) - env += plugin_env - else: - env = full_env + plugin_env - - shadow_set = self.__class__([]) - # put all our entries in shadow_set - list(map(shadow_set.add, self)) - - for project_name in plugin_projects: - - for dist in plugin_env[project_name]: - - req = [dist.as_requirement()] - - try: - resolvees = shadow_set.resolve(req, env, installer) - - except ResolutionError as v: - # save error info - error_info[dist] = v - if fallback: - # try the next older version of project - continue - else: - # give up on this project, keep going - break - - else: - list(map(shadow_set.add, resolvees)) - distributions.update(dict.fromkeys(resolvees)) - - # success, no need to try any more versions of this project - break - - distributions = list(distributions) - distributions.sort() - - return distributions, error_info - - def require(self, *requirements): - """Ensure that distributions matching `requirements` are activated - - `requirements` must be a string or a (possibly-nested) sequence - thereof, specifying the distributions and versions required. The - return value is a sequence of the distributions that needed to be - activated to fulfill the requirements; all relevant distributions are - included, even if they were already activated in this working set. - """ - needed = self.resolve(parse_requirements(requirements)) - - for dist in needed: - self.add(dist) - - return needed - - def subscribe(self, callback, existing=True): - """Invoke `callback` for all distributions - - If `existing=True` (default), - call on all existing ones, as well. - """ - if callback in self.callbacks: - return - self.callbacks.append(callback) - if not existing: - return - for dist in self: - callback(dist) - - def _added_new(self, dist): - for callback in self.callbacks: - callback(dist) - - def __getstate__(self): - return ( - self.entries[:], - self.entry_keys.copy(), - self.by_key.copy(), - self.normalized_to_canonical_keys.copy(), - self.callbacks[:], - ) - - def __setstate__(self, e_k_b_n_c): - entries, keys, by_key, normalized_to_canonical_keys, callbacks = e_k_b_n_c - self.entries = entries[:] - self.entry_keys = keys.copy() - self.by_key = by_key.copy() - self.normalized_to_canonical_keys = normalized_to_canonical_keys.copy() - self.callbacks = callbacks[:] - - -class _ReqExtras(dict): - """ - Map each requirement to the extras that demanded it. - """ - - def markers_pass(self, req, extras=None): - """ - Evaluate markers for req against each extra that - demanded it. - - Return False if the req has a marker and fails - evaluation. Otherwise, return True. - """ - extra_evals = ( - req.marker.evaluate({'extra': extra}) - for extra in self.get(req, ()) + (extras or (None,)) - ) - return not req.marker or any(extra_evals) - - -class Environment: - """Searchable snapshot of distributions on a search path""" - - def __init__( - self, search_path=None, platform=get_supported_platform(), python=PY_MAJOR - ): - """Snapshot distributions available on a search path - - Any distributions found on `search_path` are added to the environment. - `search_path` should be a sequence of ``sys.path`` items. If not - supplied, ``sys.path`` is used. - - `platform` is an optional string specifying the name of the platform - that platform-specific distributions must be compatible with. If - unspecified, it defaults to the current platform. `python` is an - optional string naming the desired version of Python (e.g. ``'3.6'``); - it defaults to the current version. - - You may explicitly set `platform` (and/or `python`) to ``None`` if you - wish to map *all* distributions, not just those compatible with the - running platform or Python version. - """ - self._distmap = {} - self.platform = platform - self.python = python - self.scan(search_path) - - def can_add(self, dist): - """Is distribution `dist` acceptable for this environment? - - The distribution must match the platform and python version - requirements specified when this environment was created, or False - is returned. - """ - py_compat = ( - self.python is None - or dist.py_version is None - or dist.py_version == self.python - ) - return py_compat and compatible_platforms(dist.platform, self.platform) - - def remove(self, dist): - """Remove `dist` from the environment""" - self._distmap[dist.key].remove(dist) - - def scan(self, search_path=None): - """Scan `search_path` for distributions usable in this environment - - Any distributions found are added to the environment. - `search_path` should be a sequence of ``sys.path`` items. If not - supplied, ``sys.path`` is used. Only distributions conforming to - the platform/python version defined at initialization are added. - """ - if search_path is None: - search_path = sys.path - - for item in search_path: - for dist in find_distributions(item): - self.add(dist) - - 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 - project's distributions use their project's name converted to all - lowercase as their key. - - """ - distribution_key = project_name.lower() - return self._distmap.get(distribution_key, []) - - 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, []) - if dist not in dists: - dists.append(dist) - dists.sort(key=operator.attrgetter('hashcmp'), reverse=True) - - 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 - suitable distribution is already active. (This may raise - ``VersionConflict`` if an unsuitable version of the project is already - active in the specified `working_set`.) If a suitable distribution - isn't active, this method returns the newest distribution in the - environment that meets the ``Requirement`` in `req`. If no suitable - distribution is found, and `installer` is supplied, then the result of - calling the environment's ``obtain(req, installer)`` method will be - returned. - """ - try: - dist = working_set.find(req) - except VersionConflict: - if not replace_conflicting: - raise - dist = None - if dist is not None: - return dist - for dist in self[req.key]: - if dist in req: - return dist - # try to download/install - return self.obtain(req, installer) - - 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 - base ``Environment`` class, this routine just returns - ``installer(requirement)``, unless `installer` is None, in which case - 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.""" - if installer is not None: - return installer(requirement) - - 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): - """In-place addition of a distribution or environment""" - if isinstance(other, Distribution): - self.add(other) - elif isinstance(other, Environment): - for project in other: - for dist in other[project]: - self.add(dist) - else: - raise TypeError("Can't add %r to environment" % (other,)) - return self - - def __add__(self, other): - """Add an environment or distribution to an environment""" - new = self.__class__([], platform=None, python=None) - for env in self, other: - new += env - return new - - -# XXX backward compatibility -AvailableDistributions = Environment - - -class ExtractionError(RuntimeError): - """An error occurred extracting a resource - - The following attributes are available from instances of this exception: - - manager - The resource manager that raised this exception - - cache_path - The base directory for resource extraction - - original_error - The exception instance that caused extraction to fail - """ - - -class ResourceManager: - """Manage resource extraction and packages""" - - extraction_path = None - - def __init__(self): - self.cached_files = {} - - 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, 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, 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, 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, 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, resource_name): - """List the contents of the named resource directory""" - return get_provider(package_or_requirement).resource_listdir(resource_name) - - def extraction_error(self): - """Give an error message for problems extracting file(s)""" - - old_exc = sys.exc_info()[1] - cache_path = self.extraction_path or get_default_cache() - - tmpl = textwrap.dedent( - """ - Can't extract file(s) to egg cache - - The following error occurred while trying to extract file(s) - to the Python egg cache: - - {old_exc} - - The Python egg cache directory is currently set to: - - {cache_path} - - Perhaps your account does not have write access to this directory? - You can change the cache directory by setting the PYTHON_EGG_CACHE - environment variable to point to an accessible directory. - """ - ).lstrip() - err = ExtractionError(tmpl.format(**locals())) - err.manager = self - err.cache_path = cache_path - err.original_error = old_exc - raise err - - 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 - not already exist. `archive_name` should be the base filename of the - enclosing egg (which may not be the name of the enclosing zipfile!), - including its ".egg" extension. `names`, if provided, should be a - sequence of path name parts "under" the egg's extraction location. - - This method should only be called by resource providers that need to - obtain an extraction location, and only for names they intend to - extract, as it tracks the generated names for possible cleanup later. - """ - extract_path = self.extraction_path or get_default_cache() - target_path = os.path.join(extract_path, archive_name + '-tmp', *names) - try: - _bypass_ensure_directory(target_path) - except Exception: - self.extraction_error() - - self._warn_unsafe_extraction_path(extract_path) - - self.cached_files[target_path] = 1 - return target_path - - @staticmethod - def _warn_unsafe_extraction_path(path): - """ - If the default extraction path is overridden and set to an insecure - location, such as /tmp, it opens up an opportunity for an attacker to - replace an extracted file with an unauthorized payload. Warn the user - if a known insecure location is used. - - See Distribute #375 for more details. - """ - if os.name == 'nt' and not path.startswith(os.environ['windir']): - # On Windows, permissions are generally restrictive by default - # and temp directories are not writable by other users, so - # bypass the warning. - return - mode = os.stat(path).st_mode - if mode & stat.S_IWOTH or mode & stat.S_IWGRP: - msg = ( - "Extraction path is writable by group/others " - "and vulnerable to attack when " - "used with get_resource_filename ({path}). " - "Consider a more secure " - "location (set with .set_extraction_path or the " - "PYTHON_EGG_CACHE environment variable)." - ).format(**locals()) - warnings.warn(msg, UserWarning) - - 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 - have anything special they should do. - - Resource providers should call this method ONLY after successfully - extracting a compressed resource. They must NOT call it on resources - that are already in the filesystem. - - `tempname` is the current (temporary) name of the file, and `filename` - is the name it will be renamed to by the caller after this routine - returns. - """ - - if os.name == 'posix': - # Make the resource executable - mode = ((os.stat(tempname).st_mode) | 0o555) & 0o7777 - os.chmod(tempname, mode) - - 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 - path defaults to the return value of ``get_default_cache()``. (Which - is based on the ``PYTHON_EGG_CACHE`` environment variable, with various - platform-specific fallbacks. See that routine's documentation for more - details.) - - Resources are extracted to subdirectories of this path based upon - information given by the ``IResourceProvider``. You may set this to a - temporary directory, but then you must call ``cleanup_resources()`` to - delete the extracted files when done. There is no guarantee that - ``cleanup_resources()`` will be able to remove all extracted files. - - (Note: you may not change the extraction path for a given resource - manager once resources have been extracted, unless you first call - ``cleanup_resources()``.) - """ - if self.cached_files: - raise ValueError("Can't change extraction path, files already extracted") - - self.extraction_path = path - - 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. - This function does not have any concurrency protection, so it should - generally only be called when the extraction path is a temporary - directory exclusive to a single process. This method is not - automatically called; you must call it explicitly or register it as an - ``atexit`` function if you wish to ensure cleanup of a temporary - directory used for extractions. - """ - # XXX - - -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 platformdirs.user_cache_dir( - appname='Python-Eggs' - ) - - -def safe_name(name): - """Convert an arbitrary string to a standard distribution name - - Any runs of non-alphanumeric/. characters are replaced with a single '-'. - """ - return re.sub('[^A-Za-z0-9.]+', '-', name) - - -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: - version = version.replace(' ', '.') - return re.sub('[^A-Za-z0-9.]+', '-', version) - - -def safe_extra(extra): - """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. - """ - return re.sub('[^A-Za-z0-9.-]+', '_', extra).lower() - - -def to_filename(name): - """Convert a project or version name to its filename-escaped form - - Any '-' characters are currently replaced with '_'. - """ - return name.replace('-', '_') - - -def invalid_marker(text): - """ - Validate text as a PEP 508 environment marker; return an exception - if invalid or False otherwise. - """ - try: - evaluate_marker(text) - except SyntaxError as e: - e.filename = None - e.lineno = None - return e - return False - - -def evaluate_marker(text, extra=None): - """ - Evaluate a PEP 508 environment marker. - Return a boolean indicating the marker result in this environment. - Raise SyntaxError if marker is invalid. - - This implementation uses the 'pyparsing' module. - """ - try: - marker = packaging.markers.Marker(text) - return marker.evaluate() - 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 = None - egg_info = None - loader = None - - 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, resource_name): - return self._fn(self.module_path, resource_name) - - def get_resource_stream(self, manager, resource_name): - return io.BytesIO(self.get_resource_string(manager, resource_name)) - - def get_resource_string(self, manager, resource_name): - return self._get(self._fn(self.module_path, resource_name)) - - 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): - if not self.egg_info: - return self.egg_info - - path = self._get_metadata_path(name) - return self._has(path) - - def get_metadata(self, name): - if not self.egg_info: - return "" - path = self._get_metadata_path(name) - value = self._get(path) - try: - return value.decode('utf-8') - except UnicodeDecodeError as exc: - # Include the path in the error message to simplify - # troubleshooting, and without changing the exception type. - exc.reason += ' in {} file at path: {}'.format(name, path) - raise - - def get_metadata_lines(self, name): - return yield_lines(self.get_metadata(name)) - - def resource_isdir(self, resource_name): - return self._isdir(self._fn(self.module_path, resource_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): - return self._listdir(self._fn(self.module_path, resource_name)) - - 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, namespace): - script = 'scripts/' + script_name - if not self.has_metadata(script): - raise ResolutionError( - "Script {script!r} not found in metadata at {self.egg_info!r}".format( - **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): - with open(script_filename) as fid: - source = fid.read() - code = compile(source, script_filename, 'exec') - exec(code, namespace, namespace) - else: - from linecache import cache - - cache[script_filename] = ( - len(script_text), - 0, - script_text.split('\n'), - script_filename, - ) - script_code = compile(script_text, script_filename, 'exec') - exec(script_code, namespace, namespace) - - def _has(self, path): - raise NotImplementedError( - "Can't perform this operation for unregistered loader type" - ) - - def _isdir(self, path): - raise NotImplementedError( - "Can't perform this operation for unregistered loader type" - ) - - def _listdir(self, path): - raise NotImplementedError( - "Can't perform this operation for unregistered loader type" - ) - - def _fn(self, base, resource_name): - self._validate_resource_path(resource_name) - if resource_name: - return os.path.join(base, *resource_name.split('/')) - return base - - @staticmethod - def _validate_resource_path(path): - """ - Validate the resource paths according to the docs. - https://setuptools.pypa.io/en/latest/pkg_resources.html#basic-resource-access - - >>> warned = getfixture('recwarn') - >>> warnings.simplefilter('always') - >>> vrp = NullProvider._validate_resource_path - >>> vrp('foo/bar.txt') - >>> bool(warned) - False - >>> vrp('../foo/bar.txt') - >>> bool(warned) - True - >>> warned.clear() - >>> vrp('/foo/bar.txt') - >>> bool(warned) - True - >>> vrp('foo/../../bar.txt') - >>> bool(warned) - True - >>> warned.clear() - >>> vrp('foo/f../bar.txt') - >>> bool(warned) - False - - Windows path separators are straight-up disallowed. - >>> vrp(r'\\foo/bar.txt') - Traceback (most recent call last): - ... - ValueError: Use of .. or absolute path in a resource path \ -is not allowed. - - >>> vrp(r'C:\\foo/bar.txt') - Traceback (most recent call last): - ... - ValueError: Use of .. or absolute path in a resource path \ -is not allowed. - - Blank values are allowed - - >>> vrp('') - >>> bool(warned) - False - - Non-string values are not. - - >>> vrp(None) - Traceback (most recent call last): - ... - AttributeError: ... - """ - invalid = ( - os.path.pardir in path.split(posixpath.sep) - or posixpath.isabs(path) - or ntpath.isabs(path) - ) - if not invalid: - return - - msg = "Use of .. or absolute path in a resource path is not allowed." - - # Aggressively disallow Windows absolute paths - if ntpath.isabs(path) and not posixpath.isabs(path): - raise ValueError(msg) - - # for compatibility, warn; in future - # raise ValueError(msg) - warnings.warn( - msg[:-1] + " and will raise exceptions in a future release.", - DeprecationWarning, - stacklevel=4, - ) - - 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()'" - ) - - -register_loader_type(object, NullProvider) - - -def _parents(path): - """ - yield all parents of path including path - """ - last = None - while path != last: - yield path - last = path - path, _ = os.path.split(path) - - -class EggProvider(NullProvider): - """Provider based on a virtual filesystem""" - - def __init__(self, module): - super().__init__(module) - self._setup_prefix() - - def _setup_prefix(self): - # Assume that metadata may be nested inside a "basket" - # of multiple eggs and use module_path instead of .archive. - eggs = filter(_is_egg_path, _parents(self.module_path)) - egg = next(eggs, None) - egg and self._set_egg(egg) - - 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 - - -class DefaultProvider(EggProvider): - """Provides access to package resources in the filesystem""" - - def _has(self, path): - return os.path.exists(path) - - def _isdir(self, path): - return os.path.isdir(path) - - def _listdir(self, path): - return os.listdir(path) - - def get_resource_stream(self, manager, resource_name): - return open(self._fn(self.module_path, resource_name), 'rb') - - def _get(self, path): - with open(path, 'rb') as stream: - return stream.read() - - @classmethod - def _register(cls): - loader_names = ( - 'SourceFileLoader', - 'SourcelessFileLoader', - ) - for name in loader_names: - loader_cls = getattr(importlib_machinery, name, type(None)) - register_loader_type(loader_cls, cls) - - -DefaultProvider._register() - - -class EmptyProvider(NullProvider): - """Provider that returns nothing for all requests""" - - module_path = None - - _isdir = _has = lambda self, path: False - - def _get(self, path): - return '' - - def _listdir(self, path): - return [] - - def __init__(self): - pass - - -empty_provider = EmptyProvider() - - -class ZipManifests(dict): - """ - zip manifest builder - """ - - @classmethod - def build(cls, path): - """ - Build a dictionary similar to the zipimport directory - caches, except instead of tuples, store ZipInfo objects. - - Use a platform-specific path separator (os.sep) for the path keys - for compatibility with pypy on Windows. - """ - with zipfile.ZipFile(path) as zfile: - items = ( - ( - name.replace('/', os.sep), - zfile.getinfo(name), - ) - for name in zfile.namelist() - ) - return dict(items) - - load = build - - -class MemoizedZipManifests(ZipManifests): - """ - Memoized zipfile manifests. - """ - - manifest_mod = collections.namedtuple('manifest_mod', 'manifest mtime') - - def load(self, path): - """ - Load a manifest at path or return a suitable manifest already loaded. - """ - path = os.path.normpath(path) - mtime = os.stat(path).st_mtime - - if path not in self or self[path].mtime != mtime: - manifest = self.build(path) - self[path] = self.manifest_mod(manifest, mtime) - - return self[path].manifest - - -class ZipProvider(EggProvider): - """Resource support for zips and eggs""" - - eagers = None - _zip_manifests = MemoizedZipManifests() - - def __init__(self, module): - super().__init__(module) - self.zip_pre = self.loader.archive + os.sep - - def _zipinfo_name(self, fspath): - # Convert a virtual filename (full path to file) into a zipfile subpath - # usable with the zipimport directory cache for our target archive - fspath = fspath.rstrip(os.sep) - if fspath == self.loader.archive: - return '' - if fspath.startswith(self.zip_pre): - return fspath[len(self.zip_pre) :] - raise AssertionError("%s is not a subpath of %s" % (fspath, self.zip_pre)) - - def _parts(self, zip_path): - # Convert a zipfile subpath into an egg-relative path part list. - # pseudo-fs path - fspath = self.zip_pre + zip_path - if fspath.startswith(self.egg_root + os.sep): - return fspath[len(self.egg_root) + 1 :].split(os.sep) - raise AssertionError("%s is not a subpath of %s" % (fspath, self.egg_root)) - - @property - def zipinfo(self): - return self._zip_manifests.load(self.loader.archive) - - def get_resource_filename(self, manager, resource_name): - if not self.egg_name: - raise NotImplementedError( - "resource_filename() only supported for .egg, not .zip" - ) - # no need to lock for extraction, since we use temp names - zip_path = self._resource_to_zip(resource_name) - eagers = self._get_eager_resources() - if '/'.join(self._parts(zip_path)) in eagers: - for name in eagers: - self._extract_resource(manager, self._eager_to_zip(name)) - return self._extract_resource(manager, zip_path) - - @staticmethod - def _get_date_and_size(zip_stat): - size = zip_stat.file_size - # ymdhms+wday, yday, dst - date_time = zip_stat.date_time + (0, 0, -1) - # 1980 offset already done - timestamp = time.mktime(date_time) - return timestamp, size - - # FIXME: 'ZipProvider._extract_resource' is too complex (12) - 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)) - # return the extracted directory name - return os.path.dirname(last) - - timestamp, size = self._get_date_and_size(self.zipinfo[zip_path]) - - if not WRITE_SUPPORT: - raise IOError( - '"os.rename" and "os.unlink" are not supported ' 'on this platform' - ) - try: - - real_path = manager.get_cache_path(self.egg_name, self._parts(zip_path)) - - if self._is_current(real_path, zip_path): - return real_path - - outf, tmpnam = _mkstemp( - ".$extract", - dir=os.path.dirname(real_path), - ) - os.write(outf, self.loader.get_data(zip_path)) - os.close(outf) - utime(tmpnam, (timestamp, timestamp)) - manager.postprocess(tmpnam, real_path) - - try: - rename(tmpnam, real_path) - - 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, - # so proceed. - return real_path - # Windows, del old file and retry - elif os.name == 'nt': - unlink(real_path) - rename(tmpnam, real_path) - return real_path - raise - - except os.error: - # report a user-friendly error - manager.extraction_error() - - return real_path - - def _is_current(self, file_path, zip_path): - """ - Return True if the file_path is current for this zip_path - """ - timestamp, size = self._get_date_and_size(self.zipinfo[zip_path]) - if not os.path.isfile(file_path): - return False - stat = os.stat(file_path) - if stat.st_size != size or stat.st_mtime != timestamp: - return False - # check that the contents match - zip_contents = self.loader.get_data(zip_path) - with open(file_path, 'rb') as f: - file_contents = f.read() - return zip_contents == file_contents - - def _get_eager_resources(self): - if self.eagers is None: - eagers = [] - for name in ('native_libs.txt', 'eager_resources.txt'): - if self.has_metadata(name): - eagers.extend(self.get_metadata_lines(name)) - self.eagers = eagers - return self.eagers - - def _index(self): - try: - return self._dirindex - except AttributeError: - ind = {} - for path in self.zipinfo: - parts = path.split(os.sep) - while parts: - parent = os.sep.join(parts[:-1]) - if parent in ind: - ind[parent].append(parts[-1]) - break - else: - ind[parent] = [parts.pop()] - self._dirindex = ind - return ind - - 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): - 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): - return self._zipinfo_name(self._fn(self.egg_root, resource_name)) - - def _resource_to_zip(self, resource_name): - return self._zipinfo_name(self._fn(self.module_path, resource_name)) - - -register_loader_type(zipimport.zipimporter, ZipProvider) - - -class FileMetadata(EmptyProvider): - """Metadata handler for standalone PKG-INFO files - - Usage:: - - metadata = FileMetadata("/path/to/PKG-INFO") - - This provider rejects all data and metadata requests except for PKG-INFO, - which is treated as existing, and will be the contents of the file at - the provided location. - """ - - def __init__(self, path): - self.path = path - - def _get_metadata_path(self, name): - return self.path - - def has_metadata(self, name): - return name == 'PKG-INFO' and os.path.isfile(self.path) - - def get_metadata(self, name): - if name != 'PKG-INFO': - raise KeyError("No metadata except PKG-INFO is available") - - with io.open(self.path, encoding='utf-8', errors="replace") as f: - metadata = f.read() - self._warn_on_replacement(metadata) - return metadata - - def _warn_on_replacement(self, metadata): - replacement_char = '�' - if replacement_char in metadata: - tmpl = "{self.path} could not be properly decoded in UTF-8" - msg = tmpl.format(**locals()) - warnings.warn(msg) - - def get_metadata_lines(self, name): - return yield_lines(self.get_metadata(name)) - - -class PathMetadata(DefaultProvider): - """Metadata provider for egg directories - - Usage:: - - # Development eggs: - - egg_info = "/path/to/PackageName.egg-info" - base_dir = os.path.dirname(egg_info) - metadata = PathMetadata(base_dir, egg_info) - dist_name = os.path.splitext(os.path.basename(egg_info))[0] - dist = Distribution(basedir, project_name=dist_name, metadata=metadata) - - # Unpacked egg directories: - - egg_path = "/path/to/PackageName-ver-pyver-etc.egg" - metadata = PathMetadata(egg_path, os.path.join(egg_path,'EGG-INFO')) - dist = Distribution.from_filename(egg_path, metadata=metadata) - """ - - def __init__(self, path, egg_info): - self.module_path = path - self.egg_info = egg_info - - -class EggMetadata(ZipProvider): - """Metadata provider for .egg files""" - - def __init__(self, importer): - """Create a metadata provider from a zipimporter""" - - self.zip_pre = importer.archive + os.sep - self.loader = importer - if importer.prefix: - self.module_path = os.path.join(importer.archive, importer.prefix) - else: - self.module_path = importer.archive - self._setup_prefix() - - -_declare_state('dict', _distribution_finders={}) - - -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 - handler), and `distribution_finder` is a callable that, passed a path - item and the importer instance, yields ``Distribution`` instances found on - that path item. See ``pkg_resources.find_on_path`` for an example.""" - _distribution_finders[importer_type] = distribution_finder - - -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, path_item, only=False): - """ - Find eggs in zip files; possibly multiple nested eggs. - """ - if importer.archive.endswith('.whl'): - # wheels are not supported with this finder - # they don't have PKG-INFO metadata, and won't ever contain eggs - return - metadata = EggMetadata(importer) - if metadata.has_metadata('PKG-INFO'): - yield Distribution.from_filename(path_item, metadata=metadata) - if only: - # don't yield nested distros - return - for subitem in metadata.resource_listdir(''): - if _is_egg_path(subitem): - subpath = os.path.join(path_item, subitem) - dists = find_eggs_in_zip(zipimport.zipimporter(subpath), subpath) - 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)) - submeta.egg_info = subpath - yield Distribution.from_location(path_item, subitem, submeta) - - -register_finder(zipimport.zipimporter, find_eggs_in_zip) - - -def find_nothing(importer, path_item, only=False): - return () - - -register_finder(object, find_nothing) - - -def find_on_path(importer, path_item, only=False): - """Yield distributions accessible on a sys.path directory""" - path_item = _normalize_cached(path_item) - - if _is_unpacked_egg(path_item): - yield Distribution.from_filename( - path_item, - metadata=PathMetadata(path_item, os.path.join(path_item, 'EGG-INFO')), - ) - return - - entries = (os.path.join(path_item, child) for child in safe_listdir(path_item)) - - # scan for .egg and .egg-info in directory - for entry in sorted(entries): - fullpath = os.path.join(path_item, entry) - factory = dist_factory(path_item, entry, only) - for dist in factory(fullpath): - yield dist - - -def dist_factory(path_item, entry, only): - """Return a dist_factory for the given entry.""" - lower = entry.lower() - is_egg_info = lower.endswith('.egg-info') - is_dist_info = lower.endswith('.dist-info') and os.path.isdir( - os.path.join(path_item, entry) - ) - is_meta = is_egg_info or is_dist_info - return ( - distributions_from_metadata - if is_meta - else find_distributions - if not only and _is_egg_path(entry) - else resolve_egg_link - if not only and lower.endswith('.egg-link') - else NoDists() - ) - - -class NoDists: - """ - >>> bool(NoDists()) - False - - >>> list(NoDists()('anything')) - [] - """ - - def __bool__(self): - return False - - def __call__(self, fullpath): - return iter(()) - - -def safe_listdir(path): - """ - Attempt to list contents of path, but suppress some exceptions. - """ - try: - return os.listdir(path) - except (PermissionError, NotADirectoryError): - pass - except OSError as e: - # Ignore the directory if does not exist, not a directory or - # permission denied - if e.errno not in (errno.ENOTDIR, errno.EACCES, errno.ENOENT): - raise - return () - - -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 = PathMetadata(root, path) - else: - metadata = FileMetadata(path) - entry = os.path.basename(path) - yield Distribution.from_location( - root, - entry, - metadata, - precedence=DEVELOP_DIST, - ) - - -def non_empty_lines(path): - """ - Yield non-empty lines from file at path - """ - with open(path) as f: - for line in f: - line = line.strip() - if line: - yield line - - -def resolve_egg_link(path): - """ - Given a path to an .egg-link, resolve distributions - present in the referenced path. - """ - referenced_paths = non_empty_lines(path) - resolved_paths = ( - os.path.join(os.path.dirname(path), ref) for ref in referenced_paths - ) - dist_groups = map(find_distributions, resolved_paths) - return next(dist_groups, ()) - - -if hasattr(pkgutil, 'ImpImporter'): - register_finder(pkgutil.ImpImporter, find_on_path) - -register_finder(importlib_machinery.FileFinder, find_on_path) - -_declare_state('dict', _namespace_handlers={}) -_declare_state('dict', _namespace_packages={}) - - -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 - handler), and `namespace_handler` is a callable like this:: - - def namespace_handler(importer, path_entry, moduleName, module): - # return a path_entry to use for child packages - - Namespace handlers are only called if the importer object has already - agreed that it can handle the relevant path item, and they should only - return a subpath if the module __path__ does not already contain an - equivalent subpath. For an example namespace handler, see - ``pkg_resources.file_ns_handler``. - """ - _namespace_handlers[importer_type] = namespace_handler - - -def _handle_ns(packageName, path_item): - """Ensure that named package includes a subpath of path_item (if needed)""" - - importer = get_importer(path_item) - if importer is None: - return None - - # use find_spec (PEP 451) and fall-back to find_module (PEP 302) - try: - spec = importer.find_spec(packageName) - except AttributeError: - # capture warnings due to #1111 - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - loader = importer.find_module(packageName) - else: - loader = spec.loader if spec else None - - if loader is None: - return None - module = sys.modules.get(packageName) - if module is None: - module = sys.modules[packageName] = types.ModuleType(packageName) - module.__path__ = [] - _set_parent_ns(packageName) - elif not hasattr(module, '__path__'): - raise TypeError("Not a package:", packageName) - handler = _find_adapter(_namespace_handlers, importer) - subpath = handler(importer, path_item, packageName, module) - if subpath is not None: - path = module.__path__ - path.append(subpath) - importlib.import_module(packageName) - _rebuild_mod_path(path, packageName, module) - return subpath - - -def _rebuild_mod_path(orig_path, package_name, module): - """ - Rebuild module.__path__ ensuring that all entries are ordered - corresponding to their sys.path order - """ - sys_path = [_normalize_cached(p) for p in sys.path] - - def safe_sys_path_index(entry): - """ - Workaround for #520 and #513. - """ - try: - return sys_path.index(entry) - except ValueError: - return float('inf') - - def position_in_sys_path(path): - """ - Return the ordinal of the path based on its position in sys.path - """ - path_parts = path.split(os.sep) - module_parts = package_name.count('.') + 1 - parts = path_parts[:-module_parts] - return safe_sys_path_index(_normalize_cached(os.sep.join(parts))) - - new_path = sorted(orig_path, key=position_in_sys_path) - new_path = [_normalize_cached(p) for p in new_path] - - if isinstance(module.__path__, list): - module.__path__[:] = new_path - else: - module.__path__ = new_path - - -def declare_namespace(packageName): - """Declare that package 'packageName' is a namespace package""" - - _imp.acquire_lock() - try: - if packageName in _namespace_packages: - return - - path = sys.path - parent, _, _ = packageName.rpartition('.') - - if parent: - declare_namespace(parent) - if parent not in _namespace_packages: - __import__(parent) - try: - path = sys.modules[parent].__path__ - except AttributeError as e: - raise TypeError("Not a package:", parent) from e - - # Track what packages are namespaces, so when new path items are added, - # they can be updated - _namespace_packages.setdefault(parent or None, []).append(packageName) - _namespace_packages.setdefault(packageName, []) - - for path_item in path: - # Ensure all the parent's path items are reflected in the child, - # if they apply - _handle_ns(packageName, path_item) - - finally: - _imp.release_lock() - - -def fixup_namespace_packages(path_item, parent=None): - """Ensure that previously-declared namespace packages include path_item""" - _imp.acquire_lock() - try: - for package in _namespace_packages.get(parent, ()): - subpath = _handle_ns(package, path_item) - if subpath: - fixup_namespace_packages(subpath, package) - finally: - _imp.release_lock() - - -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]) - normalized = _normalize_cached(subpath) - for item in module.__path__: - if _normalize_cached(item) == normalized: - break - else: - # Only return the path if it's not already there - return subpath - - -if hasattr(pkgutil, 'ImpImporter'): - 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) - - -def null_ns_handler(importer, path_item, packageName, module): - return None - - -register_namespace_handler(object, null_ns_handler) - - -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): # pragma: nocover - """ - Contrary to POSIX 2008, on Cygwin, getcwd (3) contains - symlink components. Using - os.path.abspath() works around this limitation. A fix in os.getcwd() - would probably better, in Cygwin even more so, except - that this seems to be by design... - """ - return os.path.abspath(filename) if sys.platform == 'cygwin' else 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): - """ - Determine if given path appears to be an egg. - """ - return _is_zip_egg(path) or _is_unpacked_egg(path) - - -def _is_zip_egg(path): - return ( - path.lower().endswith('.egg') - and os.path.isfile(path) - and zipfile.is_zipfile(path) - ) - - -def _is_unpacked_egg(path): - """ - Determine if given path appears to be an unpacked egg. - """ - return path.lower().endswith('.egg') and os.path.isfile( - os.path.join(path, 'EGG-INFO', 'PKG-INFO') - ) - - -def _set_parent_ns(packageName): - parts = packageName.split('.') - name = parts.pop() - if parts: - parent = '.'.join(parts) - setattr(sys.modules[parent], name, sys.modules[packageName]) - - -MODULE = re.compile(r"\w+(\.\w+)*$").match -EGG_NAME = re.compile( - r""" - (?P[^-]+) ( - -(?P[^-]+) ( - -py(?P[^-]+) ( - -(?P.+) - )? - )? - )? - """, - re.VERBOSE | re.IGNORECASE, -).match - - -class EntryPoint: - """Object representing an advertised importable object""" - - 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 - self.module_name = module_name - self.attrs = tuple(attrs) - self.extras = tuple(extras) - self.dist = dist - - def __str__(self): - s = "%s = %s" % (self.name, self.module_name) - if self.attrs: - s += ':' + '.'.join(self.attrs) - if self.extras: - s += ' [%s]' % ','.join(self.extras) - return s - - def __repr__(self): - return "EntryPoint.parse(%r)" % str(self) - - def load(self, require=True, *args, **kwargs): - """ - Require packages for this EntryPoint, then resolve it. - """ - if not require or args or kwargs: - warnings.warn( - "Parameters to load are deprecated. Call .resolve and " - ".require separately.", - PkgResourcesDeprecationWarning, - stacklevel=2, - ) - if require: - self.require(*args, **kwargs) - return self.resolve() - - def resolve(self): - """ - Resolve the entry point from its module and attrs. - """ - module = __import__(self.module_name, fromlist=['__name__'], level=0) - try: - return functools.reduce(getattr, self.attrs, module) - except AttributeError as exc: - raise ImportError(str(exc)) from exc - - 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 - # that the working set knows what extras we want. Otherwise, for - # dist-info distributions, the working set will assume that the - # requirements for that extra are purely optional and skip over them. - reqs = self.dist.requires(self.extras) - items = working_set.resolve(reqs, env, installer, extras=self.extras) - list(map(working_set.add, items)) - - pattern = re.compile( - r'\s*' - r'(?P.+?)\s*' - r'=\s*' - r'(?P[\w.]+)\s*' - r'(:\s*(?P[\w.]+))?\s*' - r'(?P\[.*\])?\s*$' - ) - - @classmethod - def parse(cls, src, dist=None): - """Parse a single entry point from string `src` - - Entry point syntax follows the form:: - - name = some.module:some.attr [extra1, extra2] - - The entry name and module name are required, but the ``:attrs`` and - ``[extras]`` parts are optional - """ - m = cls.pattern.match(src) - if not m: - msg = "EntryPoint must be in 'name=module:attrs [extras]' format" - raise ValueError(msg, src) - res = m.groupdict() - extras = cls._parse_extras(res['extras']) - attrs = res['attr'].split('.') if res['attr'] else () - return cls(res['name'], res['module'], attrs, extras, dist) - - @classmethod - def _parse_extras(cls, extras_spec): - if not extras_spec: - return () - req = Requirement.parse('x' + extras_spec) - if req.specs: - raise ValueError() - return req.extras - - @classmethod - def parse_group(cls, group, lines, dist=None): - """Parse an entry point group""" - if not MODULE(group): - raise ValueError("Invalid group name", group) - this = {} - for line in yield_lines(lines): - ep = cls.parse(line, dist) - if ep.name in this: - raise ValueError("Duplicate entry point", group, ep.name) - this[ep.name] = ep - return this - - @classmethod - def parse_map(cls, data, dist=None): - """Parse a map of entry point groups""" - if isinstance(data, dict): - data = data.items() - else: - data = split_sections(data) - maps = {} - for group, lines in data: - if group is None: - if not lines: - continue - raise ValueError("Entry points must be listed in groups") - group = group.strip() - if group in maps: - raise ValueError("Duplicate group name", group) - maps[group] = cls.parse_group(group, lines, dist) - return maps - - -def _version_from_file(lines): - """ - Given an iterable of lines from a Metadata file, return - the value of the Version field, if present, or None otherwise. - """ - - def is_version_line(line): - return line.lower().startswith('version:') - - version_lines = filter(is_version_line, lines) - line = next(iter(version_lines), '') - _, _, value = line.partition(':') - return safe_version(value.strip()) or None - - -class Distribution: - """Wrap an actual or potential sys.path entry w/metadata""" - - PKG_INFO = 'PKG-INFO' - - def __init__( - self, - 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: - self._version = safe_version(version) - self.py_version = py_version - self.platform = platform - self.location = location - self.precedence = precedence - self._provider = metadata or empty_provider - - @classmethod - 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: - cls = _distributionImpl[ext.lower()] - - match = EGG_NAME(basename) - if match: - project_name, version, py_version, platform = match.group( - 'name', 'ver', 'pyver', 'plat' - ) - return cls( - location, - metadata, - project_name=project_name, - version=version, - py_version=py_version, - platform=platform, - **kw, - )._reload_version() - - def _reload_version(self): - return self - - @property - def hashcmp(self): - return ( - self.parsed_version, - self.precedence, - self.key, - self.location, - self.py_version or '', - self.platform or '', - ) - - def __hash__(self): - return hash(self.hashcmp) - - def __lt__(self, other): - return self.hashcmp < other.hashcmp - - def __le__(self, other): - return self.hashcmp <= other.hashcmp - - def __gt__(self, other): - return self.hashcmp > other.hashcmp - - def __ge__(self, other): - return self.hashcmp >= other.hashcmp - - 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): - return not self == other - - # These properties have to be lazy so that we don't have to load any - # metadata until/unless it's actually needed. (i.e., some distributions - # may not know their name or version without loading PKG-INFO) - - @property - def key(self): - try: - return self._key - except AttributeError: - self._key = key = self.project_name.lower() - return key - - @property - def parsed_version(self): - if not hasattr(self, "_parsed_version"): - try: - self._parsed_version = parse_version(self.version) - 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 - - return self._parsed_version - - @property - def version(self): - try: - return self._version - except AttributeError as e: - version = self._get_version() - if version is None: - path = self._get_metadata_path_for_display(self.PKG_INFO) - msg = ("Missing 'Version:' header and/or {} file at path: {}").format( - self.PKG_INFO, path - ) - raise ValueError(msg, self) from e - - return version - - @property - def _dep_map(self): - """ - A map of extra to its list of (direct) requirements - for this distribution, including the null extra. - """ - try: - return self.__dep_map - except AttributeError: - self.__dep_map = self._filter_extras(self._build_dep_map()) - return self.__dep_map - - @staticmethod - 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 = extra - reqs = dm.pop(extra) - new_extra, _, marker = extra.partition(':') - fails_marker = marker and ( - invalid_marker(marker) or not evaluate_marker(marker) - ) - if fails_marker: - reqs = [] - new_extra = safe_extra(new_extra) or None - - dm.setdefault(new_extra, []).extend(reqs) - return dm - - def _build_dep_map(self): - dm = {} - for name in 'requires.txt', 'depends.txt': - for extra, reqs in split_sections(self._get_metadata(name)): - dm.setdefault(extra, []).extend(parse_requirements(reqs)) - return dm - - def requires(self, extras=()): - """List of Requirements needed for this distro if `extras` are used""" - dm = self._dep_map - deps = [] - deps.extend(dm.get(None, ())) - for ext in extras: - try: - deps.extend(dm[safe_extra(ext)]) - except KeyError as e: - raise UnknownExtra( - "%s has no such extra feature %r" % (self, ext) - ) from e - return deps - - def _get_metadata_path_for_display(self, name): - """ - Return the path to the given metadata file, if available. - """ - try: - # We need to access _get_metadata_path() on the provider object - # directly rather than through this class's __getattr__() - # since _get_metadata_path() is marked private. - path = self._provider._get_metadata_path(name) - - # Handle exceptions e.g. in case the distribution's metadata - # provider doesn't support _get_metadata_path(). - except Exception: - return '[could not detect]' - - return path - - def _get_metadata(self, name): - if self.has_metadata(name): - for line in self.get_metadata_lines(name): - yield line - - def _get_version(self): - lines = self._get_metadata(self.PKG_INFO) - version = _version_from_file(lines) - - 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: - fixup_namespace_packages(self.location) - for pkg in self._get_metadata('namespace_packages.txt'): - if pkg in sys.modules: - declare_namespace(pkg) - - def egg_name(self): - """Return what this distribution's standard .egg filename should be""" - filename = "%s-%s-py%s" % ( - to_filename(self.project_name), - to_filename(self.version), - self.py_version or PY_MAJOR, - ) - - if self.platform: - filename += '-' + self.platform - return filename - - def __repr__(self): - if self.location: - return "%s (%s)" % (self, self.location) - else: - return str(self) - - def __str__(self): - try: - version = getattr(self, 'version', None) - except ValueError: - version = None - version = version or "[unknown version]" - return "%s %s" % (self.project_name, version) - - def __getattr__(self, attr): - """Delegate all unrecognized public attributes to .metadata provider""" - if attr.startswith('_'): - raise AttributeError(attr) - return getattr(self._provider, attr) - - def __dir__(self): - return list( - set(super(Distribution, self).__dir__()) - | set(attr for attr in self._provider.__dir__() if not attr.startswith('_')) - ) - - @classmethod - 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): - 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, 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() - - def get_entry_map(self, group=None): - """Return the entry point map for `group`, or the full entry 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 ep_map.get(group, {}) - return ep_map - - 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(self, path, loc=None, replace=False): # noqa: C901 - """Ensure self.location is on path - - If replace=False (default): - - If location is already in path anywhere, do nothing. - - Else: - - If it's an egg and its parent directory is on path, - insert just ahead of the parent. - - Else: add to the end of path. - If replace=True: - - If location is already on path anywhere (not eggs) - or higher priority than its parent (eggs) - do nothing. - - Else: - - If it's an egg and its parent directory is on path, - insert just ahead of the parent, - removing any lower-priority entries. - - Else: add it to the front of path. - """ - - loc = loc or self.location - if not loc: - return - - nloc = _normalize_cached(loc) - bdir = os.path.dirname(nloc) - npath = [(p and _normalize_cached(p) or p) for p in path] - - for p, item in enumerate(npath): - if item == nloc: - if replace: - break - else: - # don't modify path (even removing duplicates) if - # found and not replace - return - elif item == bdir and self.precedence == EGG_DIST: - # if it's an .egg, give it precedence over its directory - # UNLESS it's already been added to sys.path and replace=False - if (not replace) and nloc in npath[p:]: - return - if path is sys.path: - self.check_version_conflict() - path.insert(p, loc) - npath.insert(p, nloc) - break - else: - if path is sys.path: - self.check_version_conflict() - if replace: - path.insert(0, loc) - else: - path.append(loc) - return - - # p is the spot where we found or inserted loc; now remove duplicates - while True: - try: - np = npath.index(nloc, p + 1) - except ValueError: - break - else: - del npath[np], path[np] - # ha! - p = np - - return - - def check_version_conflict(self): - if self.key == 'setuptools': - # ignore the inevitable setuptools self-conflicts :( - return - - nsp = dict.fromkeys(self._get_metadata('namespace_packages.txt')) - loc = normalize_path(self.location) - for modname in self._get_metadata('top_level.txt'): - if ( - modname not in sys.modules - or modname in nsp - or modname in _namespace_packages - ): - continue - if modname in ('pkg_resources', 'setuptools', 'site'): - continue - fn = getattr(sys.modules[modname], '__file__', None) - if fn and ( - normalize_path(fn).startswith(loc) or fn.startswith(self.location) - ): - continue - issue_warning( - "Module %s was already imported from %s, but %s is being added" - " to sys.path" % (modname, fn, self.location), - ) - - def has_version(self): - try: - self.version - except ValueError: - issue_warning("Unbuilt egg for " + repr(self)) - return False - return True - - 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) - return self.__class__(**kw) - - @property - def extras(self): - return [dep for dep in self._dep_map if dep] - - -class EggInfoDistribution(Distribution): - def _reload_version(self): - """ - Packages installed by distutils (e.g. numpy or scipy), - which uses an old safe_version, and so - their version numbers can get mangled when - converted to filenames (e.g., 1.11.0.dev0+2329eae to - 1.11.0.dev0_2329eae). These distributions will not be - parsed properly - downstream by Distribution and safe_version, so - take an extra step and try to get the version number from - the metadata file itself instead of the filename. - """ - md_version = self._get_version() - if md_version: - self._version = md_version - return self - - -class DistInfoDistribution(Distribution): - """ - Wrap an actual or potential sys.path entry - w/metadata, .dist-info style. - """ - - PKG_INFO = 'METADATA' - EQEQ = re.compile(r"([\(,])\s*(\d.*?)\s*([,\)])") - - @property - def _parsed_pkg_info(self): - """Parse and cache metadata""" - try: - return self._pkg_info - except AttributeError: - metadata = self.get_metadata(self.PKG_INFO) - self._pkg_info = email.parser.Parser().parsestr(metadata) - return self._pkg_info - - @property - def _dep_map(self): - try: - return self.__dep_map - except AttributeError: - self.__dep_map = self._compute_dependencies() - return self.__dep_map - - def _compute_dependencies(self): - """Recompute this distribution's dependencies.""" - dm = self.__dep_map = {None: []} - - reqs = [] - # Including any condition expressions - for req in self._parsed_pkg_info.get_all('Requires-Dist') or []: - reqs.extend(parse_requirements(req)) - - def reqs_for_extra(extra): - for req in reqs: - if not req.marker or req.marker.evaluate({'extra': extra}): - yield req - - common = types.MappingProxyType(dict.fromkeys(reqs_for_extra(None))) - dm[None].extend(common) - - for extra in self._parsed_pkg_info.get_all('Provides-Extra') or []: - s_extra = safe_extra(extra.strip()) - dm[s_extra] = [r for r in reqs_for_extra(extra) if r not in common] - - return dm - - -_distributionImpl = { - '.egg': Distribution, - '.egg-info': EggInfoDistribution, - '.dist-info': DistInfoDistribution, -} - - -def issue_warning(*args, **kw): - level = 1 - g = globals() - try: - # find the first stack frame that is *not* code in - # the pkg_resources module, to use for the warning - while sys._getframe(level).f_globals is g: - level += 1 - except ValueError: - pass - warnings.warn(stacklevel=level + 1, *args, **kw) - - -def parse_requirements(strs): - """ - Yield ``Requirement`` objects for each specification in `strs`. - - `strs` must be a string, or a (possibly-nested) iterable thereof. - """ - return map(Requirement, join_continuation(map(drop_comment, yield_lines(strs)))) - - -class RequirementParseError(packaging.requirements.InvalidRequirement): - "Compatibility wrapper for InvalidRequirement" - - -class Requirement(packaging.requirements.Requirement): - def __init__(self, requirement_string): - """DO NOT CALL THIS UNDOCUMENTED METHOD; use Requirement.parse()!""" - 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] - self.extras = tuple(map(safe_extra, self.extras)) - self.hashCmp = ( - self.key, - self.url, - self.specifier, - frozenset(self.extras), - str(self.marker) if self.marker else None, - ) - self.__hash = hash(self.hashCmp) - - 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): - if isinstance(item, Distribution): - if item.key != self.key: - return False - - item = item.version - - # Allow prereleases always in order to match the previous behavior of - # this method. In the future this should be smarter and follow PEP 440 - # more accurately. - return self.specifier.contains(item, prereleases=True) - - def __hash__(self): - return self.__hash - - def __repr__(self): - return "Requirement.parse(%r)" % str(self) - - @staticmethod - def parse(s): - (req,) = parse_requirements(s) - return req - - -def _always_object(classes): - """ - Ensure object appears in the mro even - for old-style classes. - """ - if object not in classes: - return classes + (object,) - return classes - - -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] - - -def ensure_directory(path): - """Ensure that the parent directory of `path` exists""" - dirname = os.path.dirname(path) - os.makedirs(dirname, exist_ok=True) - - -def _bypass_ensure_directory(path): - """Sandbox-bypassing version of ensure_directory()""" - if not WRITE_SUPPORT: - 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) - try: - mkdir(dirname, 0o755) - except FileExistsError: - pass - - -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]") - and each ``content`` is a list of stripped lines excluding blank lines and - comment-only lines. If there are any such lines before the first section - header, they're returned in a first ``section`` of ``None``. - """ - section = None - content = [] - for line in yield_lines(s): - if line.startswith("["): - if line.endswith("]"): - if section or content: - yield section, content - section = line[1:-1].strip() - content = [] - else: - raise ValueError("Invalid section heading", line) - else: - content.append(line) - - # wrap up last segment - yield section, content - - -def _mkstemp(*args, **kw): - old_open = os.open - try: - # temporarily bypass sandboxing - os.open = os_open - return tempfile.mkstemp(*args, **kw) - finally: - # and then put it back - os.open = old_open - - -# Silence the PEP440Warning by default, so that end users don't get hit by it -# randomly just because they use pkg_resources. We want to append the rule -# because we want earlier uses of filterwarnings to take precedence over this -# one. -warnings.filterwarnings("ignore", category=PEP440Warning, append=True) - - -# from jaraco.functools 1.3 -def _call_aside(f, *args, **kwargs): - f(*args, **kwargs) - return f - - -@_call_aside -def _initialize(g=globals()): - "Set up global resource manager (deliberately not state-saved)" - manager = ResourceManager() - g['_manager'] = manager - g.update( - (name, getattr(manager, name)) - for name in dir(manager) - if not name.startswith('_') - ) - - -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(): - """ - Prepare the master working set and make the ``require()`` - API available. - - This function has explicit effects on the global state - of pkg_resources. It is intended to be invoked once at - the initialization of this module. - - Invocation by other packages is unsupported and done - at their own risk. - """ - working_set = WorkingSet._build_master() - _declare_state('object', working_set=working_set) - - require = working_set.require - iter_entry_points = working_set.iter_entry_points - add_activation_listener = working_set.subscribe - run_script = working_set.run_script - # backward compatibility - run_main = run_script - # Activate all distributions already on sys.path with replace=False and - # ensure that all distributions added to the working set in the future - # (e.g. by calling ``require()``) will get activated as well, - # with higher priority (replace=True). - tuple(dist.activate(replace=False) for dist in working_set) - add_activation_listener( - lambda dist: dist.activate(replace=True), - existing=False, - ) - working_set.entries = [] - # match order - list(map(working_set.add_entry, sys.path)) - globals().update(locals()) diff --git a/venv/lib/python3.11/site-packages/pkg_resources/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/__pycache__/__init__.cpython-311.pyc deleted file mode 100755 index 773800192d68c6fa535a981cb66210e26fcdbaf9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 156112 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 i)uQ~grDRvP=cipN;m(TP70Mr0l`2PXzMY%!% diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/__init__.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/__init__.py deleted file mode 100755 index e69de29..0000000 diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/__pycache__/__init__.cpython-311.pyc deleted file mode 100755 index 4e35e5cd5f90b207503f519e569862f6b2c38747..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 198 zcmZ3^%ge<81Xrfa$^y}kK?DpiLK&agfQ;!3DGb33nv8xc8H$*I{LdiCUy=G5`MIh3 zxrs%|`TAb@>G{U`i3J7vWvO{(`Z<|N`URCG8Tom}dWMGj#hE3kx&?{J*@@|?#rg%= z>G4IW#rdU0$v|E_P(w<7k$!x9W?p7Ve7s&kUp~fFOY?=v9FW z1Xz?z+n_?*kWEE!Om(1yav)pkz>YP|oY)!JlXRTvPP&SDZec2oG<(vTY4@3#!yLxv z=y*<_p6~zf+Y4M|cjwH^WAWlGcm40Z|NXc7-#;iU%y-~YZvD=Mzuw_={5?HrS3tda zxGm^#yy=h}l5@z>EB-oro&4-l|GInK{OsxV@ZX%?9R8czo5z2>z1{(b9J-f1Qtov}Z%J&4=i3ftFZfI+n$w;J_X9`#C<);h>lmO414WnXetYKa_Dm0Bk+ z@>-$2?p+aE#U)pxWaN3FM*D&`uK11zb;N&h^@dPxNUD@--V0ev?piMqs?%fD;i+DKs>f4<{?rg_Mjp-!joKSLxi75Mp3GmO>#U{NMqiWE09e#XjR@YqTs{-tV%ux_28&*`dYm-GQf_`qNH4?b4ri;c2)2 zv>Q)*^rt;|YSo`wfuEXypY}@4fZIN)1>t^aJ;FA%6&tLz;8q;a(;tYfkv1ZBJCFZO z7-5^Ejtd>yciRl?jqGkc&u%;&)}IdJ=^6d$nb-@`F4XXdv>V}3 zX;1WM_?Y%pa!akZozmXxuHNI)zUXn|3)gTzYS@;A*AAmjhouA2b^Xpkhqd;--O&@# z?(j)H|8_i`(w@||wAtE{Z?1jxaKEefbj*#v&fe2f2kQKcny%B9j_^v4mUnLtdZG)l zdmaHXiv6q}``K7PqP0|8Gjn@$rGrTQob*RhH&(1?)m#qS$_yZv=k;8k$J1x@r_ZRE z?HNGr2)=w)`?3h${S3qRC}P@5=zZRTckLKoTZO3}y;}agy?8pKKb?u~@)3n_46D@V zdOwF%YRPIx^lYs|&UezvtJkadbDwp@JeM6;+@Ez^c5<5INb~vL@MF@1&1s|)fLX6} z65$yYVyA2nBe=hy*X@PabB}GGMn|k<_?!lOdXWBcD_A5Nk)FNou+5tn)V_G`X>vf# zBho49`K(pu1+K+skjH1Ot?E6;UwZN74C<%TGSPF~*PxWX$J7$FySG$@%;&6m$kc~@ zI%N9rBP1hUcFJXN7Tr_H%e|`Mz1$>KSeUsFBoU`U9gI)p+(}y(Y zP=|i44vV&>KNjHF62~5hp0m*t{c0IeYZ-|mPSuZ81JMCnozJ7xL9JBjd{$pxSUgXL z-$gB5??vQtUVl0tYkR73=10#DW|eqR9X%INU&{A!<8KJH83H65u!fgkBttj!F|*bxYvw7qZ?aW9vEJmyz$aC**qx zt-B=clwQf|+XR1kRr+Gqm!t}j>x;nivJQjGu`fRr40du|zl6Ge`3ZHs!ZE*sn3IU9 zuUm_ZwyV)A(v2**T$WzL$}|?+#rgc!)8xZ3ZzASbpHR1#0F#%b>(bYz>{THQk$wr2B%N?h8ma9hH$zM!Ihy-51n!zq3fXm-Tcn$D*Jr58>aprQ5eX z(p%AM(m%uh-^KqK)a(^4ChlJ~-Rm3@-Y?VMS86vzw|r51klr@O={Ir2=6mUF%hT_f z)1XzR{Gv+-oPdrwAHVeb*K>PcR$F{$krrRqYSVi?hFOjLbSgl4$DI44Yx~}JtoinS z2@wAh>h>i-{0{)}>uUM7F_b8ZLZT90qSYV@%oNrnMGngx)cAHEYV>6-e(#qh=V^yD zi&6R&>4(z0pm%A0-O#_khH`)FyhHl#?>lYW?MOcBrgA<4r%zRBN&HOj|Rq3Bg-v(C!357{Y@pVg^{!o|1%pp&Mm-#;0GZme}yVtcm zshy1<{DK~jHSWl`+hSKU-u9tLBJo^A&J?uAV||fiG=~3~oUXxGWGGX3WH1?(BSWW? z@?dNr<2w^jsZ@X7VVcBK+!2&*;cd zG?V*mY$VcmG2?5y92rbT&f!&ITjFZ0ubawD#%1#(ef71+<@jiFFc!@eam0hsm>M(4 z&uBq1dL?-@5{nE(Wwh;lWH5F#GLk8>eaUN&k0Pp^$?1r`I2z3qbVU0jqeID#!MIBSUd^9Nf|%D8I_aaSo9L| zFHoP71cyN1P&6WkLiYebfQrq#TJQ`s4C&rf?vdG{wp3=brG=TZU{t zf0qXb24k5bx~IIu=LciSL?*X8mSjK=B1fvML=DPQdoh!DEP9#Rknw7D5O?yRgm)+8 zcrxA>AIcQSsC#6HbI9b$fYjh{G*hD9g!|4%`z~^Kd3pft41=X@XfToxw+BZfvXm+8 z`Rs|#aQmUo_Gh|}9n9n$V|aLv#ZN_(qjD_cJq5@Q0<@WeWAUW+(9`GEMl1f3B$%Eb zeh7K!n~rf;Vo6e$j5-|Sj&Fl&eamH?m9IL-U09;^Yt$jPCUyRUQb{)Hjhr{`xS*H& zbY&!cdI8AMNNuglgv%1ohCe3UvK;M8;xC3)2!lQ}LU<*L37H7R`$Lh?08Q+{zEIy# zBGiD99hHHNLg%AHBT>1rB|n6#=lozIG%$E6nn3*6U|%#8m1Sf#98DxJ`$L1VP+uew zrTj!W!-I+8NV4y|NIq5`LV8SEOKF&inWAvms7^TCXBu!08b&0#e@Jr4Hys1$kh4Jm z-V|rt*2!}v0A6k;?1`o(){k5q2+Pq# zd{pkkQy2-PxV#<+07yHGDH@F>2IH|r%gEJV50cf8P9M8YpJ_GdU>qaJeX;0kNI|oB7MnG4B)YXrVwg|u^*K}jky9{cG9rTkBQ+;^=5`A#NZ9ltidP=Gk8iiUJSqf*fLz~S+g z&+~YjIjyYOjvvbW!in?o(IF`eB4G%FINUGChfT;*jvy{cK@yD!t~nM0 zmGl0>H*%HY+IRYux}87XrtE$u6*%$_ZdY;sKROURaJYQ=47zt+GD(tuLCdNIbks-& z9g()b3Fz!P8x2S~3?!N4$1;hH<69Bk<9FV9Zu^a(6a(d-k{mP0>A9N{O z4yKkLN(Z`?KzGX9%?-0OhWe2k(}kO-YmBvL;}%lI540$H+GA@(#v4um&kRO}9^D9% zRU}AJsx{&{W%af$ePm(*c!e8mlL58`oQX*GF4J|i}yKcBIIpx}9o|c~CS&50n(i`p> zf@9WYkLh%n2_pMfxeoc5=9rP)q`TiKxvqQ1T^ICvJf4uk5;c-6F><)!w$>TMk9+K& zw~JX5iVO{fFe9U(OA&dH=x7iqu_QPZEDE4n=u?7j;>3D@eqnN_e^5?EoSnjyrF-E;;`&mx&x7hT~pD;Goeh zx6%Cz2r@ZIDldp#iofB3JI7aj-(NWO?Bub@V++O0rZ>J`c&qS%+fi8cAlFg2 zCibJzDN`r+;lF-qxZ@#N7<>hIFX|v8onF_Z12fHe-P`NtJIuLW&!ppuvp0uk3~(4E z6i1_Ak+mEsOUj=9KfHv1h9Xu_+-Vosy+D$_tCwV>$6s}tvCwxA>w8*M$BZeR{u0Ug>v)3-_1BN@Tl#9aM zMFJ)>>}}9B_agETmo*Oh9k5-xC~SdHsC=2`7sduSo)I}5#^59Iu1qpl!3U`5U3}oXx5Z}jle0nRALNFYB&rYE<7BUMu+I$ z9}d3=(q4R#sYhfg7_^q?v%cuiP&oXqQ`C>vMS(r!s}z-j-^KsLNd%~n_V0nq?c4Og zu}F~b_SMmcrwO>`Tt*+V*DtLb9Dk->?NLJAj3#zW^L zm!iCALPBspE+s5cv6fzn42_Z$z(|4Fr%fmpD4=vB5u{DgQ1W~Pt0^tS=aKh0h{Hl) zDwEOSD8y)?h>RHWXf#9wE=L)OLkdB%giC|b%i5YuO`}v;eyP17p1hD@w1nD{Ayrz| z#7!4;Gm9Inm_cP_^>v!FFtyOK2ov>0g6)Sf1dGnVCtyC8XhXmgb;%ojlVg)(jJ@`x%UYGP)>Lupd~nqpTM2*N+BdT~72Gjf zia`A4%G6u`4s{00uOc(~ixgZ(0G2x}#ruFqsA&016nq&06a4BVWqd;cE$4{?2rQE{ z&*y*OprF|8+ex$XX#z1TDN|ZsF{XtCSkA?pU(nptmQx}=`|w}C2z$`=kTgQZDvA}< z0b^GeLXYG|UwMF`Sbh&;aM&_}D0?dTVHxKjIU%~low&yE2VxfV^pb4+3uZ8f@gGnb z;af9X^a`HGf<}?(L4j-kCwzEFBNppVuzt4oy|wA!mXv=BgTS(=)6nLMkh^|zp938rY|~zNgt05T@6J-SgQwso*03> z>tRYVQ^1shc^C^kG35@|GmM4~NIfEa1`K|4XEO zxEld@uwW$?oS6&rjm_^ZOVynezkhH$OHVr?Za_HM@iE1zpY_ZpX9v>3ZAx%k%D;`F zdFFa%b=v>Xfu%e-~cg5 zU~fow0gZ(ejS-iG9veN!B3mSSJlgh|@agW}&Rrp%KB3mo&J7zj zJgS1`6rpvkp^c%?>JUrwLKyx~4xzf|#OkIk4Ua9I8xd-c!+4@E2^q|;#}!P4_jDia zJpOEtTH7;Nq0XYp8y{O?QAk%LkyHzc%MC`6jZa%9mGc`kx92>RYC-_7EtCR8G-9yI zVpWFdengIgJWdWq6D=5IZXjz5GV@^YG0y11&6^Hb>;XT7aWAe|`D%-3ElKg!tKS9t zKerPyP{ZPH9LTTH75M~%m~{(M6nY9$LlRA|6ZDor9Jj9fOjYQeMwEq`2L^(mT}3T3onF7Gcb5=lqlFZ zKJ|b|#oIWfMn*1#CC^;|4$(71T+q7l%lcdcs*vM^s0q&)9ohrF6U?Ss9F*)@X^hpF zXT?Nx_L~>~HJDN|1^4kkLDC;AB2BrzlKEvTCfja4Gx^LX3&ktm@udQ5NvvOD3cQZO zlF5z-KD_%CQDO2D84Ut%azgUzDN^b6*u1y!zCrg+9kD` z)L8{6NzEa@XEvOOA+tJ;36QZ0Tg7zxr-(qk6lqlYhiID%>EKQ!xHIM7DJUEHZG5-W zFz?Yj3Vf8q6KEKxZx@j?_CRzdWfF-q>B3wbvxZNL^7ScZM^t#`jA&l6zB@4z2fvKv zjoDQ&wWPNe_d}o&VPpgHlT0G;4ov7{Gse1uY_U9Eg5ib~(p7?wTNf6oAjEgOAOhyX z&uk&uVT*yt7Kz`3LK#FVqYIuN5^7S$N`$MxQP(5OdRo^lO(KCo{ILx}#sU;ucrA>@ zLvgfF7B5ZMb&*PG^#>L{Yg%5-izVu9r#2o}8*Ux<6l@UsuhN~~l{%=YkwUA>Tm#qs zahVdg4C`tlZX$xYkZUpUEXXYfFBrKIw`rY?Fj@g|V>Nl4z$OK&_Hf*3ut$cmAl_20 zd|BSo?C0wOmCV;3gt1}}PJZ5{L#mqz_~huhQ2*div?(+)6zRhtyNm$&>0iS>FiC}Z(hGeeBP3DcRDXbZ-h932=PipU`tfH0gJn?Ua|4j~|h zKu_qo^g~GnLSZl|1azQ$2T7MiaxnC^HR8gnC#k#Hj1Cgi3W=(R z?8Y*=j3^UO*Zd3mLj9ldLSYgnV^oWXjF&(To~5BMfS4ExP;%Oa!hC`M=ANI|Y)lo< zZ$7wmvU?%8W+rlHNC|G9^wQ_OGZm?VM*PIrKyd2N^vTwxzs6X4Z%D^a})_SbS+4FFIZS;Bd_7oojk&1F#bdG%bZ=we4i&%TP6-2{{!l zS=y{>fhC(vV9VsNNwA%`U4>6F1uqa-NZNbN@v(Q=N8ZpqZz%0urFd7Rw4Weis}ZNM z5EjoMBgv#dF2;+Dx0`4?GMyH85N60r@Ifx&uZJRu^ZYgE^xzl_abaIA>=5KkzG|!h zjGxIrMQWM^X>H_kN=@{-Wx|l?8WaE&6R59s!h8p>4FxOg1x&^v5@2TD!4D&m-^N66 z8AOcay5x|ZH~m(F5Xo)dX*=Pz*x9-af@X0O4{NQglf#nJBTPgdm!8DvXvu~NSl7;w z3_t6VJk}Bum1KvDDZg~wIpfWWju+#$6fij1c=OG18gaSDe(_&%VL+`%#7v%Q%msWL zW>qw=+6iFooN(k^U$}8;CWtTRNK@CBR0%T3>;IAxLt=e78o4M(`&qLIOI7d~!X~_w z>{c}kaQ!XT1e(-{jXTot;0^+W#85m*x2OXwF_X}4hlk}jN+I%+)TePaUq_50aUVVh z;gOmc3FHVqL4%rdmPF`px@G7s{4TOR3teb8@dnrE?cQ+SYY%TUUD9A!Xa4^u}&w zV|Ti=`+>vfLjedTJLXF(-aP(|<1+`-rA@$`uumxr&6PsMwYLk#DtVjqu-H*j_NMO} zzUkW61GfTGflnR;DVI`*zvS8xA!ab+OdUV;psA#BHfw1#BM`IUzzv%O=kexOgmlEbDdUB~v_QBtel(M(zsEff z6sx^PH(rl5(L~Zxg@>cV=YU(oq1AO>gUBP%5TXGDFAszB!M z(0syj*IdBQ_nu6hdN#fHIc4v2c%LqMUO`y!yi)Ld%JY2oFd$lnmx;qzY`@|qBeDtD z|Cn`mBzX^o{2s%zrD-+LyF_2eXunYt_qce+4Cv4l~Jx$zL$`cZYau zh|cK<<10{IC)D)|!cbl&wACXVWi^{qgQ;KQE~GNQU__;A(H)T*Pik-KdlKA+li1iyDS&%F5d zwmaLzlNxfYY<#3Qd<$~a*N7+V=TVzmsyA2uzmOW_R~!ChoC6kC_ft3Ur_{g(CRpC5lmgfOrW)noKYu5Vkj&ibstL`Ts`bw+T=$ zA;7ZqpvX}e0O6E}y(_o(r1I+1dG!m$We^X{u2$CWNf);&#jTS$u*EG|I+-(HTCSAB ze9q?sfrDVOgN$sqyi=yE+?p=lrW9`@x~B=W(5>U|=e}3;V{fXyEmcat`&Bi!_bFAI zr@ZsQid3+6VcF^jE@$O_C&Um{ZLrdy5YmUG2y-2k%aw|CQ#qf^7Zgvn&X-nBc20JF zTvj=~=JgA=E=(R=FmC6A%cckJ!P+pmX1;Ry?^ga!B}TRWo7;-p^s1u@Lf!>4m8-|1 zfk5APrdRD$5LWI~DtBV5OIZyR9xD$z@8*iXBAnl}3;S5`T77J7H$RG(*xpiphzw2; z;!VjR=Y6XBLgk9-(Qj4XuD;f;c*;`zb>bD`;;a7QvQ7a9$t!1 z0=poceu2i}>mhBiFq>Iw1TPs|!q(YC4Fk8MA#GZTEJ`|^dag#@-f(`!@f8?7n=$eY zzzcg?0e8dSp4AB2PEX6_W@z6qiJlM>6*nxZWEYu~-EbINkmPmdZ55M_NoT(cyG^}G z6PaNz@9{)}C?iQ@M!l^3_2NA74ciz27;}zsuXpuW#-q**{0?$|!=)qoPAfBT1B92g z?ePs}Lev7WCo&6u$4H4KMON;TW7MfGCSCesf<^NfYAOHk6fjHS5xXeUV#I;umz%yU%K zOkbHTO_#SQvueNu!JxRPCN(g^3*6bwiOkV`9I+kb1`gU%Es1!7Xd}~ zpb^5Vl(5eWFQ_mX$HQ376JYXh2>^Ey6Eb2JKZ2`1J<~F`CcSirvUCSPQCPiDvUYZJ zx@5glvi^Y^&mWhrn7*RaY@CB&al2Bw9Stn32F|ajo=VOKmM8(>-<-nGLa@vPPQAhW z4sy=g?Q@Cr>fOrf-4F5rpnsqU|40GuO6jf?9pNbnJ@BF1?b28LI&xL=!B> z_#%PhItA4D#m!os1T6~whMG=K80AWN(@ z!IXFfyD@#a(B3dXq=~yD3G*JQ5H67wqv8e)A={KW6pge!Bs()KreIN%ZEi$SE!IJ& zN1>DCGRR;Z9K?t`h<(3<&>u7Pp~oek5k!&tXtXG2%79p=hAX>7SFrkW zQDCVVTxnszHd^!HJle5+hU~LWpt}LTEI1iSPDi7m6P+hQTeocCc1u`O2Zt6L4pt4N z4%htxZ061Ls_>Jv{-hEC+XtSic^D?GpsTfy`T*qq64v~BrfgwMdVmpZ)+c2Oah2r4 z07`Jp(kjsuf}tzqqe7=QC=05dtY0GlFov|zN^OAZBTBVeA?XpkCp3}H0Vd5DW=|UM zU?Qz!{tR{mKFx6G$&N(bPJ^EQ(#6UR>xxV`nkmG8vMpRTx>L}S-95Bx!+_$V^yF^R zg%e=8_dsm&L}i^ANq+_GvCDyIMkY7K;&cO#>fQ&L2u}!ZhR=#YN5#>yg;Fe zRwM*w#)9(3`N@|jUslQbE+-M`2boA`TE66<^JB4(>&<=Nz)pyCupVaODSy47N;PbZ z+#DpuBJe-_AMlp;?wSe7ai>}0WhI6ZAYl5PBoau}!Rmx)5A`yna-&YU!mK`F*`7|; zL)zndD@y_P|i&f!?aw*6S%~mSd_xC4e5|Y-DC*^@1db!pu1K46Ni)*Zm zl{u9?rs|j`V5wEUHT|p3*yjDR2Zqnb=NXL@K{5JA#x(yZhmU9unkln z7Km#>q;%_y1VkNZAw-1Y-BE&uG*?pZN)p=PoN19ar&h<{xDwY z9McLb$7DqphM;~?Ak>(7oI}XfFvgYl<1t%q_URg5NsVtoMq1muQ_H&Vo_uT9OyvEt z_g18dG`{Y(#yIOgiE`WrCpO<`bzk5IigZueprVfy{ub7Sl+Fa zL!X&jvUk3sa;j}%S?$bovu$@i`$6sxi_**XDa-buwo7a9ar)%9a;KfYbUUinEE?rw zA=qo3udAP3`F50?zkm}%Fu!s8UFQ!gjTa>O+e?B!u)eOPd%@I|mcNmh-uC)Sw_ZvI zS1ZBQ?<8ioz5UXim+l2OrGlFvGMukC1OQYWCIBF$Iw5pBN;m&9-%(OCotWu*zkSZF zY&ei^YFC=t)5RT1aYw4SgLjD4&$?%y!!|m_w3E&}b7_HR+UoP@GGe_XC!{xcDK4n1 zO3jPBF>4Wv2m`(@IVRk(;3MPdi$BF1cSF{sD`X(Mv#F!7H0kKv0ZEc|8E}$pNh{Xz z2zv=P6tifJA(cw3HoMy(UuR|s)#Ig2HymM-HuJ?SD3o9mILE_W57=Vlje8I?UyF&a zda8traGABlvll0F#&eRiuTs4hhaM>m6FuWO#djdp7R?poWO4b@F01utWV0oxYwxZC&MZ?(s{9P4BnJ zy1AK#N^YggVfbq2gbC349oY;Kh1m?hb0?(U!7leNPpw09I#tZsfgZ-B~xlAw8aiK`N zx3*SZg}S*>qZO94jwERy)XSE_2crqyoIytIV)-`{_FA8I-2Adcf;YdAugiap%(~>S zA!L~&88j{UR3)67B1SK)HM>ywatu`gCoU7FCip>b@L`3XXh0c=>+sQrlG+U37Q3wjz$SQDCY!$vDp z1n&^tnr(YjVv#ho*)Rq35$WAeZYt5v@W4>~99$&|;_N>YAef~6FLd`GDfo935Urod zQ?1Zg;L3OqzWj1{e~bM06ze}w@V`>Pra44=PJJaO{ zl=1^4dEUK%L=!V7)8+LF{Wi|6MWR&Ov#E0WEz~rpDw;_P>Ts^v1))UMZlY<(Y2MP^ zAD3?c$5FmjDaTfFPf5G;Q{;7kBpg-kOd+*1h1Bl+xP0Zzn)eMgM9E<%$h1`LAwm76 zO1l@T*U!1r)mxP6Es$TAKv#ias$)L1=1$=Qhkq$vAei>dSJljHxzn1e+JN7D&Fb3| zvpq`9rc}+Yh5D_jkmWaDy>hy9p{{vWN^R-eO%HN#3pK&=RnwiHe9X`T z0P*`|zPxHGDVULuFaX8^s*gP~Dr|w_=Ga!P>sj$Bq)`?_5V2#52Mf|djyM3de`6^R zZozB)jK&z5l8}ui39n#rDMm19)McFD1x7RyyDGFTREti)M4^BUz&iq}jIcJ9Llc_kwAuuqU~^92lc z%~2)0LV`J`Hj&{u!OWG|*761#-sG2thIgQ5X7imrsla;t*xeQ@|5FuvrgEloJ|_QL zv#Z|&thZ0)%m-l9=q&7XvOAIXbXkW|#ss#%cII^2->CQ-Q~pNuQ)&6FJs$B-raHUNsv8e-zk? z-+cWhieJm6fnA{N%h_Kg-c(lK#>mY@O+`56nXjmRr;HfdRA@)4f_`{&JCItp=U&Ag zG?tzUe-2)&f_@7Xt7f*mzdT*BU8&fPaag%)e$Reo&r!Z5CI|Dj!@011_uY=~kNt2A zYz-d8OPYY4JOQb2=h9B+Cm&a>o@~E)WD@^)q&E5){fohIojUm@1!)TYiUJaX3MA+Y zCr4oQh$TP{Qs*~N@Fn{EWdv-FDELw#M~JhCpY&nc zO!^;qJiZ1@!R)~A$S+oWl@DCy>8Mz6yun?~vydVPh z;Rpho4AtUvz_#3y_eP9aalz5FiNqsW>9<|kB)9~-#xRw~7dt6%N45YqN8v9v6ro+9 zY@w|xaab^IUrU=p3EJ)j4bq^o(~D%SF;mk#NUlf24{$GriSlbX)5o!%)Kja;tX_#cmeO z;U1}9qaG8l;ELwLdc%F)W3{-z8JT33lEWFZ0wZj6m8#y6`zch2swen_s{ucGti%1VMKUbcw1kR*y zPE4On2Wntrp#&Od*D3*^cGq6AR&y0=;V-?8@=z-DT)OOerR@1s@$(OS^zjpxu)UL? z3am4Fk?-btryvZvXs6))KN%PV-={%+ATVdjV?df{cgu>7bhpTFj|=lN87b)04OIzyeyvxx0=##x#NNNPb>W2Vn+=_zFOY z+zvkx;;@S|LEM=IaVO-LPC1CJA5V(si5-?;&=2l<`?za{YLj)@B`=UFLQ**7BFW&4 zsb7tRQjU4rO1balS!F!n$E{;3OA>BX+9cOwsVdra-Rq*{}W*aXiwyh z=VA+m3$Q2|cL8yl+ip7>8CIo5X8F)~u2nuX=$yy{@-8v@%aE+vw{l$2p*~}hg&QfQ zfK+TH2FLTHl0AsP$h*RbY3{$pkax1mh>LxLOU6M|z8AEf5d`#JdQ9Gmwi}oL6P&c1 zH1ohrl0!9^nAGd<>WN~)rnk%RB&{P7Qe;Ws>7sNnki-%nc+R0+aeWtuuq$+E?BF6e zDTJdoIQNaPSQ3Z4ght{xvI5L343#u2waZ-k*uKRwN=7bX?cse6n}`D3yjVU7a$tb7 z6+)NE%?I1lU~iv5En}OFmWnq|(ay2`dR;=I22pGPggcT*h)^WCrmzDFc#SGSxcD3x zah5Fc%1Rp)X+H-z?JuI=1XZ#V9RqzIBWCwVd?e$ATg({x1N#T*F0-UV1v()1y!a$< zqTW1Cd2FLQ+d50kyV!_dWZl#P;%OIs(-FVC9gi@~SI2_fMvu7yI2l(gksv|>3^`v+ z$6}Wz#pc6=Xork^2ua?f^??|0V!c1b`hZQ0WOl!Ge)-ComA9Xtk!Cl}ZkpY6=lqm3 zd1&&`d|}0OSE_Ioe)Hwa-yHkK*vz^#Tb|;ZziJXruP2XV>*LptzIHUV?Bv3-rn@EJ zW(${rNG_yf84BrG1~q^-E(jjnxqJ(e&|8Uw2Cd*M+|9$>d(-Hc8siLiB@)iLmhvND&CVQ##ZCcJ-a=RAI}c>wycdw?3{} z1p(N}bj^B&emg&^X}wp|diTQ5)~0KoRcfA{JTN()_E)F;)$GXYNwgDSUc6%Z{H$yC zz+5yH*pm+IQ388X-aQGTz<-+SIZ)vEX+g_@o$f!|vY~U0WJWH<$c9UdoW98QAuL+97|BmMC8pMD&Wx-!^LyAT3Ie@RYtozFAt>|(iQ-RC$AercUE8~E5@ zrS%qK85f%pnV6b>=r*jY9JWE4)>=Lv%k_BOuUv0788eP|FjE%&uJN3(Uam!xV$+y9 zL7#)(aL?##zfpVW!9CFF0O*F+dLmECc`Yy*!1&9Bfm`0yr9sfz45cT$ zkNM`Kt(s?VPUMg0F1{gjJm1hOJ#CAu^pevt?)|m%&Xc@WXl3Q?`?d4-Jt^;-UwtH0 zYsr}y5~)BxO8b^s?rjm2(ZWI5 zJv@v+H+J}MW=@ww>jH^w#paGUDMJ#U3ZS9gE-V{GhW$#LMTS6RTE9$P=5@3M}1T1rTz`O zLdgx-j<6AbH#U)}_(bDw;jJxc($EscX@MavKs0C{9zZ~gFN7nGvsFCFuwx!(BY=W- z8B#VnQ^?wN-*nxq)()yEKpNP~wIN-`8OykmBNkgZv9RLMJfi!>p?Pbc2tPgUKN0|U zB5N$UAk1otjNpISykl|8*t*iX6D>1&YNgaf*>9((HNF=K8VIgg~=@m9!a=K z@8ctasnXt4caxx%DI|FJs$yE51v-XZx?mtyTLz81iXII;U=H~$Pl$cKxuYXEs5B}x ziS;N!CSxSIjsj|){O>8)MFDj?^y6}T3}+6)TiI#KwTA*CndE122YovW|A?@WpP^4W zS%Xc&BP@ktb$BKazZ^3=vB?x#z>q1lw4TR1EJad=BI znM(>&ed7I@#4>{YDz$Y3pWxQLhd84S3=i73smbO3J@x$WBcL5+*q*$8^W4RIEp4fm zwzrN=AN%vGpsBCkI0|88dG+f9w+7yfeVc2D+3$7sgTHriC@@?tK1(9%$^R@|5D03&jny<>}&$O7X^2@y7ehswbbBUlID< z{@>|Ot=V?hm0q!1S+N_e(~{GZ?GId*QO3h^e$O)>?KydG&&l+j)5@OHJP^Uz)D(fU zsVSN~4!VAM=v$q)J139g3_fvlzk>OtlMubS3r{+soh+{UsCd=AVrU)jw0^XD%e~cG zQd_%z=1Q-AMp^w#y7-7vd?ZzT1PAqfR9t(nxOS%J&e@OFY`eE+TWb5^pB+fAIj*cZ zo-RJ26rV^HpLoh>h%{*iyhJ^za7m(%|Bihq5|zkYu6fsZyHy0`gIdh=mr^Wg`M zKp}Q^BS;sopDLOOEY!BlzMQVzr_}Dlfr0bE+V_1a9DNhqxKKwQ>h>vh`=*Z1mt(8A zYw029{Mwy&S7JB$bYP)r+uY0Prh`h;!Bj=#eI)dzf*bIgFJ1Xj>6&|`Yi44?-B_x0 zD}M7!>)v0NTDld#N5)tN2$pPn#OM2q=X<|y7i|{*jUeO!lLK-0jfAI35+qPRGVp@RKQTWvaT_{1Yn= zmrToWKYvJt9QanL6|!(JTwyatmAU3sbR;H7fJ@irlxXG&+l!OeZJZ9TSr%d(kR zpA)zd;OZJ28h-4g$GJE-p^~SuIW^s1h5t-3_jORvYq(9L!Ov3Y2FjoJ0=MoBksR>R zG5I*#GvxjTRxnBVtd^<^=9@+`XhshKu< zWjHrr%ecu}C_0Pnl`&0sLf-LVby^ z2PbJP`7ji~G%RxzFP-!=Nn=3-plQUAkq|ix5rEjzF6(s1t{)OYsF&GQo)t-8-vL!X zj|VFT-#HQP(V^gSJFI$cFo432N z6xd-%cJ1<0Yk9QW1ntplrb@G6a(5b&adG*qU1x5ESW=fCkp$RQ)38}Yf!3Mg8asb% zX*w;f%fY5*Q+OOI)1k=DDmG>0wi%=>TFPSd`r z3;JkEuF`6OakWId&u%dzWbat(Y4}|qN#H0);5nkZn?k2F#WtaWWAUW^%*yJB857HY zg92C&pEZ$LCP*qOT_*Txz0bi=rZ5boI5M%OH5_W@wesNHi|;hgIn%2)DXTW&(e@Ke*IA_b@6bA#0;8 zky=#o^Zzfb;#Er(8-q-Qz-_WV(AtIuBMJE;HG)SGOVL>7#^SaV+9U+OXXtJS0Ug;q zay3khp*&14scU3vJX`mX9Vh(4z#}-FtwzV2;f!IKPSJefyG4$&ff}xp`JJmv(new+R6fBwAI5m_mSgjP0xw&t{ ztn)qpk1PIscWTG+R0I7)l4aPbyF49SuLMbWv%ndbk^AC;7Nr2f0*|j{p?akle0SS^ zbQpK(l?N4s)d!X8gOf++1JyImJNfqlYjM=ne0c>q=_`G6_cwM=Po#s*N|2PBsLdN& zr(3l8dVKB9_b=Qn`EjSR=UBSsxYBZ*3c^;EPgxQ?Gm#h<4(aEPrh^BR;DMC?fGBKT zx}Z)efDp;!YjeK8YcBHRr9Y}kuj^LUVXHE|`}Ad1)2`w}caA{n6Wp%^_ow{(?+1z} zy*$pl`iMf%E}dpOV$J^i(Ptpll?8<_-Ab4qv~Vj>Tu7symFSwyOey(=b4m_;EZ z*yx9Rgeg2e{{)6lh-zn;g+&h}L!kL2_|w$MJmd}|9r*l-_QT)^ZhRnK0WnQ(fRGbS zAQ)Du2OvR)1NJu&I z>IY+eL!&tEL#!%nY*F86fhA-Q8f6R*uC$jRf+KtATx>X)C6`=H>ZylKR5b4mgpiB` zQi!QDng(3SQIVj&1tiUKHF2^P=Sr6NrsQD2xuTG>C5%I+)SXetNZl%Et~uBeHbW)= z1a-Vd)ADJa#-{mI_iqJW54TIN!>Y z3}7^P2;myaEO0!~`Fz`{&QNnR57={2$O{JnPjVf_n-F8fmPznC3?>fuC`x7QFcn52 zc)4U`u66F!_$U<`>W{#6@nA$2V#M<}_a_P#1t-Q(hS4k0KHQS1qEVdsqqjK$4jnQ{ zSPH@@4h3@An09m~411l5sdY1Zt7;B)_XDWHgiZrA>W+Gh5T6I43ZR1{EP@{8I*ik! zh$+Pm6>7R(dPvJ$7zSeMh8h46V%Xpxiw`xt6jeuJeZq*0IO+guY%*m=ZADrXLRFzr zq`P>cEJfP@0MwqI1yV7L;<5Jy&@knviFDO1qTH&*1_W)qF^x(F5A2|=@F6&8&=Epv z-mgOlj_eHe#-S0WDyVffm|V`BWKtw)L_1Y8aSQO#I5@Lr=Kbnp^KCML8D8u4a#<@# zM@V|LftkruM`fnSicUaoTp^m~Dgq1HNb40Vd5I`iRlG|VSMiS9Y>uJUEz{JxL^eXC z(}qkk&WlXiSe(Afrx0Om6`jgJvpdYohKU{~FtNIKmS~+iWOL1t3bcyfyPjF+>_(_= zTW3myix2%1ufWhJGnvK;c`}`lpQGyJ$X}p)z1{K{-ex>pG_mF+?+~W=GAE+o8WlfI zH;!NKcRKvRH?~dhP8ZZG1@-VR={x0Qmmm!|GGhAtT;9(-(At$2L2Fk^TD#Js$&Sem z?1U&?rUV;igL7AYR-Ou;Ob1UY!IL=bp#a`moW6?rU^!HU+_*W3-B8#Mqi?R9- z4PL}6;5K=fR&R0cHAgY=q*4=RVKZf*VaAEk1fnO+H zI%7Y2YVqT#Ku6jnOR%h>t&Vy*hE-&)kj>Hn!44sunURdZ9sy^>2%g9=ne^}(q}a5~ z$IIZ*DK+L|ZudyJiE~NYwDH887HB|mn#`X7P>EBB0++@}P|v$lW{O3*J7(edE@GH%GJky*rKvi32z8R@^L=Rw{FCD-DN zhAK3qe&EZ_YFLGa$jS2-nS13N8><$x-Rvh+A5mxI{{y*MmNzQlH<$S|I^{aF>k)F1 zb@o0X>!A^OQQyyhNxei1jVkX6b)-TavnOFB9(lX`PB|WIKd~14BT`^JqXiD9InmhQ zBE)q3CEoHVTKtUSMW&pn-d|8%K8M7#)6WTuix0Lbn>#-2`Ll3(^Rvq4XR%n}r3kU@ z`^~H0xGE|)SF3Dl$89>)p&%^pP|7>7c~+0CCoJrCW)Cdt5*}EGaD&N*P`iv_Wmc-0 zWu&l4HhD%Tyx8yRcWK81<;XNh`FusPrV>_DEXJWpW(NytM0Sm>I(;c^ur>dIgJj#Z)bX6P3fI2cZE2W^Y=rI_FND@27F$)H)cq3tR z7-R;8c{xx$N4n@pJTrh0hrrF35Vd0#xsG*dd#V`$RS|4-C_$Xbs3?TDW^q&|Hyn<> z2uPJ>LyF#~2uk}=5)YN5aQ_FGuSIum#vUWF|L8ODNO0YHM7bIL`f!)C8CKAcC5Xywj@US=HA1i3 zhvBOS`8huLmC=JDr;nV?KPC{UifY-13hI~ECu~Ogro+55UN|NPS(+2gy`bxah;${2 z$&f^WcqKv>Zpkrx^LScE-p0UglO%Cq&=u^J7Fy6g5`i$a!s=B!(b{<>Le7SE8JdMN zY>!}ZQqb}&EP4iFQ3;|W5P^McbR_h`Iyrd$>Ims0llVHM=`+P%YLyWNy$J&!)^HNO zCJGcJ@Ti(IGKR>37!bNT`CKE`Z&G^_*i+2%1|v23j$k*{#F-PTt~HXGX|jvbGcyu_ z*ydvNPdy-XZ7NnYOJ6@t#=wwD3<`a6sDX;OJSd!Sn&dD<{2B)fB46w*h6DzAIUUEy?vVL6N^H)|44rYkLQAkW6sN73JG9`>6BAghv^v+6x6BKqD5$EJge87CWH1~ zqM2y}qIs@bGFUu^BQQd-6i+W8hW!+k;1t;v(O*A4D>g;25TwB0Vn=-lH`cW*+kXL_ zzf;#k*h7aPbp;7ZA^bH40OVS*n4#UR@2bahyoUSiqj%W0bgV?r4BQv*MffkYs+1rJ z)^0j+rz5?jQ(4lP@^@xaG9)>nMm+2RqPI5Su`F%SVw_;#2JgIxEKy~v-woR$4)=jx zj>du66rvxe5n8s#!|{NzUB}8z@Md}+I5|@cIA2{Zc_uvO&FRJo8P>Qs8Wu~MVW0uW zfdmirLfjmylL>3-*g_Z7;*y&|I0d!jh6N6OLcWG5W6$dSB%C3uXTGE7c^(Q&R2(!G zjbM~pkQ;EeIx~T~f%$mIuq|q13+u(lYK^=hupuE0Hiww-KP_1;!kLr`$?3LO~=Lzaq-4zJ)FZ~c&8#htOWQkBRB z@p7z6uO&t*i;@j@+z!+r@h*zZ@{jB;-0*>WuIu{+KP9(7s_9 zWxGl?z`(w)<^53{=bG}bWSPTE$?e8;pjLqsjRsZr2w}sF^EP}fPvzb(+cV`}AmPKh z*{->b?{(uWnabTtDD9E6?36jxV)Binitsr8Tg8feRNcOw+dwIa*obuSpV~loj*VLnT4u`_i@S? z{HVf#gP(j__~FySAQf`JAQt0&!3k zI1BMrtM%DOWT&C{GiOkf9upR6pclxJ-^Gj*ld8w$zrYKeo@?L^T~=wb#QQb| z06UMC*+h?UL8idur&74v`%`-D?Hn3{ap_<}{$t7+uJMpIQHKL4}J^fRnzS_ zjDE?C`}U#Nzi{gdGYPo!xtuCnKjoeemQ5a>50p&Gf}SF+ejonpmxe?hmg1FJ8VC6r z{DxpMx#4}N2h)gAFlNQD1-%hn!&DC)yg+IppbI^7fv9AXPs+C_uz93pfv4&)Mb93j zz0gN|4se#=q+~=29(&hgrzBsYZ#G)-ZR&Rl&LH)})reuH6`e%?Wd{N_lxlIcAoaQ( zb%O+VW;=^*bVcfr&1n)oLJ)|f1uv3?j*uFXAcv)Z#Dc*=*FcPX1%?D4r>~3P=k#L+ z*`SSG%mPK3ge&4aIo{NzZ41=Xi|vH6+46^Q*&|LKJOPadOEh=!UL)=Wh)DDa3RV#K z4=&};8q`}iN!kWuLMC{bHn#{tQ0yump#6_t=~D%J*qcR!p;~q*axQ)e8)Ja;`1;jS zqEJYBq0@~-_sQR+KKw(#+%o@Y=*kq3Gu}iMZZQ8U9D$1IEvbra;+HPkt`u!gdADs2&}> zG8h}H;XlmJ5K;#FbA*gvR4dj*i;ysyxJ`#nfD)x_!(x`>2F*IwEMhTa7HUb(Cm-zx zOA=Za_##UZ_{pp`+o%{sDhN3nX=+a^fkU3caIb5fjSW5e~6 z;+U=dRhbHOn+WWfT!5(u5}^%cWt@@)L3QIDyt|mYOE+gRnYIn6-d(;-XsiQigz6vb zQXP&uMlip29S+8-Z&vDd+$~A%=}Ff;tJIP9UH!h;omj!%r^>0uIzz~r2^t(=5mtu> zR#s-QZsQvoL3-Uxo;Gx7%xIDzw#_M9yeZeI-d{ju2!X&j4ZM@{P7)UW17F|BPXeKmnfJ+9muK^Ch*wSi1>8IxHj);I^?PUACfa+ zvNm&BSjO+*v!PMFfH>kBcMdqm^M22Himbuh@Neq8?f#k*K5PLn?V8bJYj5Z;_9ocm zOt2`+HP2l5awYCvy$lRsKe5a>F=>Wck#!Lqt<3C%H&zMHyZZhz$iMVmWvUBqY_*1W zTJL8aF^}d+cN}_T)l|Ya?nO;?$roWP`u}e3G1y}L0PQt_UiaE9@56^oi7KjqvJyUb zh&6;{L$`_J(Uw_4c5UXa!c=^e15x2<^owXUgr{tK@m<{8D?$A){}GiBwg$RF*wJI> z1yAQNHUS8WJ8F-%4u!6noD>$Ti-(S&Zqa=BYea`30sK_@D!-a@BkyLO;;opbqdI)s zW(xQZ2Xk9L?4GaRf{E>eM;A-*v3Kc5-WB(}E2fh(&!@f3inlrCZJuAXVbY^`YaZmf zeN_u(mA8gx+R|lp3jH>GRJP?_*_OH950|COjwoeECJ#;?w0OECkNo721i?I9ZsPOg zK`Oh7JcSo5NtHF;D`-p=G|sPBGud&I9h5$BJN#?$DnX;*C!XfEO^%;z3Lfyff12k+ z`0nCpgE7XJ2-sgnzyhWH0%$Zjd4_(S;6zB&WNsYrP$?w3?vJA8lR*7>T?T+V#u z^4aKvoT41;JNmSNz%g7R%@zxyL4Wi0a25VMnsNaB09#+u9l@xndw6&>Nrd&-WQ#l3s!oI@A@-1~1cg>E6;AiGv_B-QC-%(q*{XtiwXt~QewS?$!(&0C zCZxWhO>*Hs1UMhk9ETHIGK1!}>u3z`A77fbhMn}}5%PmD4AAW%1 z<^K^4Qdg6_N3SM-O0j-Qfo)0o5xt|}do(m!xh?vV;%!TL+aM8`^pRSkg2u2KB+Tdm4@MFuu`f%Ulu9gW_6Dtk;xP2AD4`Qg zAtA*jmJR%?P&W7R3F>^#D&^OPGE7z)miKB|3C-P(zIhAMwZ4mNOMO0y)7JGwCgToK zG6s#1$;0~zDsjSKNLif#EX-Cl!_f$s>VB}is$~JmljJyQ8%b`5%1fvN@twj(h}d)_ zVdmV}zm#>hJ^VBnoU3Jo(xS`rp_IFZHnfLvCobKH8VY%mQ@yL2)4hUjF%MX_0vjvS zThE}>jG=#mk@b)e0%pmIS`EjExq^K3ORq@?uV`i(q8MX=7lI265Ev8WuwWi_ViDS_ zNVT|#CaYdTLi1-d;z{s>dX+7^6<5kyQjmCwpMPuiWJY`eD#Dh&2)FS^mxa;O&i#8T4rkZe=zyUk#@Yp}RE zw}o4GJA+GEj;-YJ7=alei2B92F2cxe<6{mBdOHhi(~r?T?5kKkC@ z8~nKEJ*U;L`LE0Eg1yv^mh{whleFJ={(Jv>@9qMW{Ae=0Se(6k@BcXe`~2se|D2Mn?dnI^ntmg4 zm#yhnwZqBUO-yXH3*eQ4ujh-f)hu5vPN^D_ExjL9_9iQ_ zq3xazy-_)jKcH0Ahev9w8SLHDANY2E?cSo`?-d$==I^i~{t+tzHvxM;$+2J({27b< zByPO>$;hT;WYf+1_PLUqJ$={Ledhvvb!38N#ZX%KxFC1oclzFK;*>p*y}s$5E*vWw zEy&fq$5R|B^^Y&;;)An=KlpLChkp_HTP33r>`h8Xivi061pEoBUxSN2b2ks&$z&Z(@ z?Kn<+LYGNx3^dbUb{$&65#{03OCtXlkr;N`NJ5NNFq!isbYIN5kI`rb113IQH6bdj zi$g?28^JD|9&emyIK__W&_Fk70pZ*^F%3FSo*=e2(K8dL8CdKAXw)2o58SVf^7!qP zn45vxlZ&M!lP$;eoA_eBqR%rf?GR=Y02 z(oG8mRCOhXXIBWfWp0_!-R57J9|2JD|TYcu@Gsi3Q41#<0)iX>BNa( z+4W)LN5;FOqs~g$GpVb}5m2(dMSl{Jcv``&wJde^L3A^lg%*SL4p&_P+_sgvAYP+X zG)XdacIxzLWD*@H*fv=^?Rff^~OiWDgLn=R}Q)06pWp? zI`iUmgg(T|PKek{Orm09JtVVXf>pMJu3HyAQPiE_HJF16F|xDkV~xkg*MD{#Q##EB z4h>z7Uc_FTy?AWYUrlyNAncyLfKENG5O6d0)hPqp0R>xk62Obyp6c|LtXLdRg^ zcKqzr2=riJ)>iJMIC7U$B-Sn}kvi0q7nGy(=_%;kV2tIfLmROdqZ^`^T*U4^+c^DO zG`CMpDK7rBSbD)w)+M3A6LZA(mdAe_y>E;>H2+!Z9O*P@@5L8QCzd@32F36Oj2rvh zj$x=FIhhxf6&@5FyqS?x(=?A0$8jE52sq`p9CL|Upi@K(=uE&E4~7^A=dlCFqFej# zkzqNi&h2FLh*ls6m9uRm>N0Vd@>t*LJ`aNko#2@6a#Tk0TGX*$iU0+yBfQO4&SYF& zcPfbAI;ow6uS&h)boCBQP4h$+CMua(-3g!UC#^fCiCsE(Q*#{VJY}>a8VAo3O*!Ju zPAL8P3Hp13xe{O^mv6&HB3KCFC~mUYDp@*u4s*m%dX(9FwbzlrOoen^GW29F*bIsx zPRR;2>!XWxsoE~9wkuiImAiBNkr0tBO*SGwM?|VzMAQ_t#fu8)y;N-smNk-PF+pYE zpqT=V<=Z20pCDE9AMxf#+9L!`XB|#~REsP=y(jh3{P2*3eBLFcCl|sI1G#+RvRud_ zoI{sE?q;@n53jftc~ixiel+g zQfK}a0K8wgvbmR$|5AwRP0+LOP60HtpEcTD(K-El*t3a9_dddQ$+VF5$JhyNXGi~Q zV3)HK8eM>0i?vqS+GN?)-6tab@e-|DIQ;SV_o;v-qgD7*1GNd-I=bW zXdMj8j`dc@z1I#T??0aEIAL|1zy_vbzT#%bI^Nv)2egU$z1rS=M&S32+I@||-)}Gg zeY2frPwhqh__^F>aMZYLOqPN3t%o3G$8=fh26=r?iJ?Mtx{xa0XWxkBila@+0#Ba{cBmYd4lXImk<5r zQODaKM|ng&lx*M1W)d;TdL4{3UDA`OlxRoYo=_ zC&&5v-{GO}c$G*(K?lQRg0It%HXa({^zR5l=?Po1!(7Eqn62F+Iy@pDCVyoqa^9pV z(dkPb7o)DIL7H0339z{4UlRN*6J3@i@po9U;@?9M4@)9bu#o}?g6D9|s`ZTl`fIPI z9}#qB0G_C-xzeN_;Jj50@5CZ$x93$iR0}q2(j1K%ax_*1u_6Z1pvFm)c_J~R7=ufL zte+A166f3HfmE`In)kChoeARhQ+VU$kc=J~)*C-b21SMmo zG_;k)Cn*!2M>%*NMN3UX``k^oy?a$^(5FbUIF}}>#_{AwB4M)5&1MrYV)jYrs3n#V zpt&oh2ndrv08d3H<@4-FBo~*p?bNYc@i5Sok*7&ieY_WGpr`q*Hw~uBINN`2I1w8qV(2wu`wK@L z8aw7^7T3PBDb;w7)d(YDM*X8a0}7aKYWtPqUn=%udVTO)&*FEg=bi`^p0w%AH zp<|aHTghG#m-y_>mfP99-E3LwGv?286zQ>*e@R}cM$`)ZB5QvO*Y}I z@eZqYN3v{3?wCQw>Z~yb&)ruqSvXc~9JP+k0u}SGSgHd^*GIQuSy7{uA}xQ#i9)f5 zW?Ok=iSB|gX_nz${NMf*fF4Kdaa@hXv@gFo0(TPdo^Z|9d;X0zvxYtHVtU*;ng#AU z%sm%K#Xa~^j!L9kN0siF48ff%3_;B$fR~^=1M%~0-A9nLqbOX^%oEnl6*wpaGS+4 zRE^Lw|DAn}xaOy7{+h1|#);t@2!~n2`2#gl-)hyxpq*71sB4~!WI{nw6nQ{Nu=p4z z6b~#hiYb3`Ko+&3NFe86xh8>}2TaLhTuIHFMAJt~>k(6iH?J0exOE*qS9-g4_U0Ux zG4y&4#azRyyql$36P(4$hJoS>@3n>D9UfV6{WxT?G+s8~Y`MT|9yv(#SPc-H$Bjw!sBbuvO9Q_wrA zQg(3mk38%Cdh#$FDUM?*BhL);1&)o)92@ph-*7P5aPZp5mtL?MyRUX!J&|hcw;KEL zEbF6Yk+8BV@h}ol^9iRz8FU~{gjhVz2jwo3YQe`T?>zXKKV)YoM!!Ui5`mjV)$_+c zC~8a=HQuObOg8OKRqU}Us94GK2hV?PU8*!@mBug@!)wwF(fMcRO60|2%^QBfJT*5vaKj^5e=)kRMl4p4Z3Up4@7pGR!x^1Gov$$pW0ERcgr zws2ozm#M=qITl#8RvN4FKCAM+WW;VPywn#Glk0X1zP$Qx*ua5f1PGN{%rqf*BlDC7 zW&epEfNjpsKsXV!82T>Ca=28C_8adg%pwzeFoM?JmrzEz42O6 z&(Gn;Ke>1|9oXI42a}Pc$0k*Qms)U1Urb9_lXF(rg6|b$3a0>whnTU1QW(x@LLKzQ z%wr45#V>#(nB`K-Rd>WEy)Ur^RuVNsC#>+Gd~I= z6POG|j;T~WdZbvBBXC-G5$N>L4+O*uW2eqcPJHHqZF>t=AXd@~VR{gKj+y76&w$vX zoq(zP6kK1ZdSSJ}bRoRH!|DLF)VTscCg{$?VDg>D42_f5^mIZI_C-|R<8cUNp{U|V zlIroJGcUxgzomG4@`bU< z3Gu9}yi)kPn$xzrH)sTvjY;-T$qMM7xWM&Lhjh9L^iI58QVgwe@x^&}kNaS|GYRgj z9GqFl8Frew$PSFr0r#Fz0TPU)$mj&( zi_#vE8UrLvtR)Q2hd>9wTbED@a+M=64KG7NP$CW_=_oA*jCU&YD#|R1Xlp#1$Aj^j zXy*iK6ZM5tke!~XM&stpLK95f3CRq^5=x#V8DWjI3p@SrFoL2ZponT*s6ISA3^a#_ zb8=y1SWd`!J_eVkIoc)+jI0je9V*$LM3>D_>VS1A(Xs&Z)GtoJ5fYq@NQ&-YW(i<% zL3@?PbfzZ2y(r$~7|Laz|AIdSne;p^bY%&U+86|ydk`Up@kwQrG4wV-`%>Mvo|gAXQKGYwNXWM z(c^bGeu!&7LqqX_AUb_!>cZ(W(pkl-tN74Cv2}`AdM=!Fnu2|r z!p_*9G0HMxWr%&X#S_ z7`7i~?|xegWstp37UMWvO*x&*I~C*cy}Ou)Y(!ADXJwD?m- zpsE2<(8Zo>b;-UH>XWJ*v?>SZLN_YwtxE2zwp?AW{5vEg_Xy2*3bFO2iM+cJ>xyo2 zf-^qoAVoJd;O56MP$SiXian?4yZ_~*@A6Y?XCzl2^`)_+8i`AbeFVBKh{WVtj&2*6 zX@!!OBA*m3<)xv_uOPCS+iXJrx8xA9n)?46w&wkaOX|Owe)gVEclW;6lI%LBKDUBK z-EjjuYQVYuA2JL#3DZ|kr)sxao`X?&w+WgA{-3PRUnPzQ2nx}3zFxqlz<_wt_0kh0>IY7}fW z1@ko|>eEr69C)VQi@6rQ-3z99Jc{>_aW}1=3tcHs*SA^q>u^_+Zd~=o=WtUthd(tO zoyunsh!+2ED|G~NC0_`LQAxg)>x9oIdbTL*Wdo-VcQHv-kXLYrGDvxTP2CIM=$CQt zEe~y3pst|@jm}5fSFV{B`2! zWb7vfwoV2dN6aK6&ABR7Ot<6SOgdvTtgC?OFs&Ci~Oc8WP@W8*|{Us63 zt}rDCdnl{*wq700YojXfxavVM(DCd#U4^4-?l~%|)&V zsyBjNT^4ro^k_DE2Nt(1kKPKSS2IV@Z13VvnmUHXQLte!J(mJD9CL+qG`8mull4a_E{DCl97EMYcl##iUYb9y5jM8 z%wL?xvWqjqo}FDBC$e3f6DW?^&IaXr?dv1D5vbZgrL0AK=U(~P;_C3WVahW18;Ikp zW}#K`O#F&Z`2>3kr#?sxDrVKH4ztg^YEr3_54nMhfJR04?cFI}~nMuvi6Y63c-Bou~& zW(~@WFd3u{C^W+T{AmOHY~fEE;3v;^IsiYZd*y)KpZlpC5!Mg^^u2ms7$_{W!u8PN z3R6lF-UJb5VT139JeDezVwybqn7_^oecLWsV6}|JsfkzJP8;tfu4<3K?XjE*lbar#EKlN!(ek$;I zR_M=8OrF0m9qYcVVsK_cEFDctPqy7B`{LY_6(+TZ)FNgp+*IR%Z!odNq}iTh7j2a; z`u)z8Oe&hx2mkRKdFFp$+bLYY_<3-SqxOEj( zDMgRVNuxMlX15=iPLP1b$70MK&MM*Fa3|QO(_=7O4gOrdIP5X`m^}KV5|eVVaNEP| zz^veF2-d1p?FCOmtXi=lw*5pJV&pxbG6;SHoY_uKofA$1j~WVRLRgKqsgyikoXKG) z?+2V&SunwCQKwlD-(g0gWx=j=3=4tz0=Ky?6M~cy-3|*k(;sD0!YXEDj(PTRQ=yuF zU=J{=TkmWpHm{^OB*fXdu^7Y&JK^XDA*FqJA}G60MA0MS@!W*K%Oxp=IY^~~-_co4 zNh_q3letU-Qp+~4Sotl|JB434uRK&RNZM04Rs zXU^F=hEs{LSRXYp7J8+$hVmoLyz*Db)Thz;phbb6g_%IAN7~43gq21ShlEM+x@Qz^ zUTGAaLSTJic9d%+Nn*p$0d3{YLr0%-;xYk@D7E{^w+EZS%e(KvR_D(~bDqA50=jbH z{F23Wz{4c?1_Qg2MLzP);NZF_eE;9_s=oIZsI)!W29sK+DdRz>xZL@>cKYD7d{xdO6A8=+UVcCdOie;CD(Q zV7$9&=jr~CgVRggaXWpndag5Os=O}25BW}xFMo#Ta8_7lmlH#hePBH&;G-iTL|$CK zk>mk8zHeHHLTtfW;J7$9fm7gKXX9?>5A^TYvBN!I%@>~I@5qIRqQ&x+V;W0x!8EGo z=@DIlPHyVNCj^WTKfb_2ow^8O_u1VqGYv)uKOGCZuGcIk@^T!=9q584!LM`VlB)#9 zai_~S{>_$T-zU{4Rr$14`SgmMV{~wR{e5-r;g8+9b)7-lsB0Nc1t~Wa8Sl9Xh=xJ+ z3U~iw^zG%lGe(-uN%bP96Aw&H>%NW-?NQrdxWDHf?Vu`hiRHS~PILj2;M<-q)%K%y zDczrNCG>*B~}tWG-nq?OCG+;>V^EYK9)4JP)geKSc_m zH8%_00}Slz?nWJKX5k2EC)h(B@KOHqwjr!5bjdyn1yi{N5Rs^I?>Rd$5+BGlvidZV z5G$%mr<>;h6#rl!@3s&nf)G%;U5`hKSt1ORx)vTeb?1MJ@|#tFo%EGC{WpATGNoMpX z!!GUw-YHvQowQ8NFySRFE+S)*?MM^n3LrViWTX|L?&Cbjp>#MMv2otzzZG2SEsKyE z_gIxZ$w-g%3*Q_YLPA0O-`)t2&3~Fk2Xd}#1vp_rexpFyk0j2}J{5*9r+)iX$Ah>v z2^!d2m1Kn8TGqTho2uMsRc=g1HY${yT==cmj=PN}^Il|Y-bb+9Flj-?=2nK_Ls%_JJ6L(S-BEbV zjeg|ylGMR2%A;R7!tlqEUHniOenN!dCqx*&dNH&(y$DHopHHau?k*J|1`|m6DA7A*ktmgU;n`N!9+h> z7{t&u#0E*}ntO&hcoieyF~WRZFT?@k!Y1Yx_^iu9p60v|7iHdfba)s95LH!e2DYOT z7wws*&&nP$KXMYZ-)Yh%D@End4(W=bC{zeN;)p!;<7bHj>)~PhWdHCmh%wsf5`%Oe zW8yenLS0#9X>fdss*dEQI6HiwNXrpr2qhM?Q+}prFb=I)KLtjf60`>6$W}_E>q4p` zD!ibRV`oNq5{TNA2rO@&8HC&V!Fy0pmyx90dLgxbq()4xg3gYKQ;H#Vq0^$u_c#$b1GQCg{dg%#4NmZ5kf_Me71gX; z!LB&f5MB*kba}8fA;F|yZYrcY?dDc>^vu*n3L`dp-u5Uuob}8;;WC9Th)%4oJUK*w z(kYxoZ2@e4nDeuxraiV1JIzwpF}=q62Xhx#e_tMP+`H+)s+3YO$pb|Qf?QtTAVova zls$W46unE~C88nmScfBMs9eZ|E<&_Rk8tw)BISU1?udbOL+D1MEEsNuZQnTf0hy>8 zOIgMl?Hu!s5qI|Dg2js)BxiZDg@18w#NZE4{M@RsrLj?w6r_BwZzv};CO~otS#8(w2srjQ^!po79@z{$ZwK_ycHgbrAT?Q>J@t*M~=c}+8#HV${7g29(oEn7a zl(!!x{)>HXtqBT@=*Cy`R#yHRfm5Ukos0Kt@PC{8FUL^8^Um9VI$rB4TN?BuqUInt ztRKogBTth))JT9@RXxWKhJv&u=^c4|iSz*F>grr=x~9RZS(7aDePn$fFb`l=&rirU z0qJc0QSa_`(V+))F?d7Pg`aHv2ThU|!Pk_BB=x!yo()iCN?iy;S-D)QnNaxdGDWd| z6BVUw1du&rwiB!(Xd(DDL~>m#3A@2O%-FU;8$V?m=RShn?5;HJEZg`O5gMePZIA8m z&z9PU(XPemcgkq^tsR=K_{2%azSFy>Ch+Z=+C8!0x7QnhIfEjIP`8&?*Zgm+K^D@x z_4_=2=X89fF8Vqu#r$(d65a%E^u?ScH;Q@uN{)-(a5}kkRw9<>s%FEG< z{e_jQTC`ym0}RT`1uqz;-)cjaZ75i6fP5P670rJNWVL+-NAoX7TuWi2i&QPz_)48nsz8^9ZoXwix2tK_h0_oHf0TJ4}?mhBVaXzb;OQYR+OH!Ovr)NlGDYpi*g<|8u>GzaU4`F_jRC8 zajxG(H;6#rA?7@LswYW|kC2SdK23=;Yo}o46ALSMaa80{)U+vC3{7JJj&*ytEj&9q zfly-*ndirVXgLRqvx!L1N!ay)a_QHkgscai++OrB+mBzE6dzLgQIFAJF^T(gm(E`r z9`43TXJ7={$KK`XECgW)+ea^)!Y<{)G;{#D`U)>XW*2Hu2SY^1{SfoGXjN z`1W+?dQVMy&quSM4rQ$rg49_}M-MCeB+ zamZf~2SfwK70HSnU#nXj`)cbutyaf<_=V3O2LGTW899=Q9I+xta07Fv_K_7cikKV{ zD2Q(~a0=%CZ3f654b+-^m&nLP-SClq;I{|U9F#`U1guJ_E=NPd=3t!V*=|&!9H~aj zUYNuYM%0wwcE*8ximGZCg7*8^dS(B=s)un^F{g(_ON?4}o`H5qG=bRrod$pf?NN4T zXd1fnf-i+`Y%_FU)y)EVnRkZ3rWyTl%6sh6KZMYz(`R4?fE!T^TpqKNqxzh&lq#cl zM65pWBD8p@4I@1QJ%@^tZl}NisZhNNi5y_YU}ry>H58)gh0>4zC5M7KqVfG$pt3#L zzAIJnpjGi;GV-8W0M;-lWkoPqQUXE*8`}{as$D7*-0hAZc%2%aT)4xrEcIi!3F|8j)@$@L{IF0LqFh1tbd3tkPr8hSG@7nlpq z70iWTG7&a1Ux{1}&(alT!AKp9O6+$%6|lW%t%0+-GdFEidv{R@h0%Z!#XA67KKSn8zqQ}SBp4rS?w=5d_n9lG4dB(WQNAoq` zPpS$I(CC>W8bI0jvKR(OP;Cv!U=uGc;DviB9z~i>PF>XXr8uw-wL_yOv^%25h&>MM zgIQdKhlkxxf@AMGq{kowIPS{pjZg6c+Md~qxX@kkOOtpJpO^tvNG`9#7xW~ET0b-8 zrF;gFl0zv8UsejK^Ce@{t08|%#u0OnaL%mdjwqUAaA$ASBNn#_+Hk{J|1;u(M3847 zywt2*5pBfdFp(q2Dm+T|(I^dgP{&>=&Vs9rWe;natw~BFF{}<*!Lax_!v|CTG0@3cx>i8Q4*AnZDSPomj?PNTbXL0{!2m?lc_jA)#xBMxNQ!%W zQYAn_N0B@vc7y_o6P;*+moNgCighi{bmgfX*SMk%R}ZQu-i>4+^S-$%mhR|Fuem3^ zc1yY?nkg;phZRtOxkFZ2Z>Azp2bNu%qUVH^D_pi{CYi;8-Y_qlPq~JO6Z{9#iw`hY zUf^FmQV=O_&jdaqs0maxCnL5q>OLg1R4{Z9TQ$05^fecoE{OlztSBDz1f^$;{2XvQ zWY1gZR6>}mnUfO_HacUI&?V;t5Aly_Li&lZ;shY&iMeo8{E@Ur~tp6kqD zB%V~FuB=54`Ydy7E8l@1n}RqqadtGuT=EbNyPYz8bOdrj5@k#daKqKzXQS+)D}^VL zwXUEZX|4+{+SNL#VlA_>>HJ{DXae1qs}C9l>wtqhCo8)Flt~$^2qL2=1*fQ4Z<{z( zJV+kKnX$9yNuh%?0*1-S3$V{4$V5T}Mu{h0p6oa-Vt|!`0P-E|p*nt0!TkLCocv zEyM&E9`MbP%u<%LCfvLkIE`8I*&^<*FB_L(<^Kx>S0a#UNShGA=ENR+na9wJ%wgR5 zdFuP|1cunp!Q%1IY8TgKs<;52rwlP*l+~Mmq2NlCd;gh2AyJ|;Eg0U8+&;@#vRTRk zbHw-yd>oILFEEH>Rp3vuzz<1*(E}TyY2|=FXIO>f5u1?`Un)EYwk&M@okS+xMdsVUYpI0uz*nxn+NWHLf7U&rrvorhUcl*r?Qz^Ms% zKX}%F2fTy|V^-AWitGOV|!k5CeN?~>_ zz7`xUb7lYUm1j-h5jd`ixcUJ3+mn64?8*P``7#H?=P5Uo>vHjQyK@gMiei5~AwM1G zwIJH);N_Cp60aXSMd1)Kn(6U`WdjY|u53+YLZIlzPbrn5Nr<2#S1oh;_u4 zh&tNY`|)FD!`&-M6B3_gEpbR-7ny9{rap^%7CILmduyG3psM6&nDJT6t6Fh@`wOZ~ zj(Piy%RcC?H(x|>CAHMN6T zY9E5Q;0#P~Li!?ph}8nER^Yg30xh*DiO0yde z_}pk&lWsbSV=AqWa*+oFy#wb*Klre&S#|X9JdW>F^9c*E?u1o$V(vh?uHnstUp$y> z-FWq6s;=Lv>&LUURdYwvt6;RKsC*w1A)GHs*S0U#Bx~2;ldkLdZe8qyy4cm0RNWS< zZc9==>H1FCIjY`g02AQ4Zm;qFVfC%xhkgCmdQ*M7t-jsw_kYm0KiRi`F}@i8PG=^} zz;@8WKy2f$UHa8a*VMlEib4%=SOai}VD4b1BoJLkYNw5s(q3Au zPgZu}b0gaIPK6cSZAA~wm*3d1_1fjsh6C1y1M`JeRqSSCGs;^IuT%i@!E|lIAGd5v z*79?sC6?@dEIIgOs{6@Q%Trd%Q^~rg()CS$9Nn3$=jVF-J6->-FZtk8_}r*#T{yV7 z?`qA}eeX4@Mo8B6|G}3?%}zI)8(~P2zuDKQPYa?+x`&A z_S%Ozq5<)w{9)t6%C?24uQvVe`rq#UR(G;;f2wl7Rk=SIQQjpb8`!FR5}Eutatq9? z72y+cghhQyh2sy9U$!y2$>WyYx5%S#iVTn8CW{CUI7GO2c^@}y^*v-PW##mb%Hy2s zVa|YUOEm0x+hZ2fd>!H6X5BD0?G-jJJg!v6Y{jvv*14CGk#^M~xgSJB50H1sZr=Sx zlj^i;?^byVhb_RY#vU!+H*)fn+00km;wtuu?9M)gSh75UOELtVqoJXtA{b8|x^L@d z(P&vJwTU0j)5^Q*QAT-!;5?8uM|d|yz+;2z{PTISZDBSN@DR4yLO@OeY)FEAI1)F>$1ocRNK%>`3GOA>O0bSO{3-ALg5ZA>Y$EtS z082%C_U@CaG8pV0KJO=3ML;scqyadyhj;h#ZactI4TjIyi_n~RPH;dO`(eI)nc-wU zyTUtmPP2n|?2zWC`ExbzKEu0bct@Jr>>~Iwo-LIg5_52(fMGt%$6sO4Exh|G??kJ( zm_NCHF~7xU94+Q=6Z|!QiVeUY@{XH4ae1O_VF%IvsI`L=aKa#l*2Kt{*eDWnC(6)( zSn3fo2Hc^^seE-9{z3kfL!lM&f*?x3N!k1pW>`hg#BTPl_^gj$ls{!~aqNB@Nkab8 zftsZANe3E|&L<!@q^&1WN;O@n&A>q1wIf76c)p};X=a) z;nm6TYT7-d#$^tKrNo2sT*F9>0hXs9^aRRkt~{8CWFmoZZQ|f71M~N$LXB3aF=3?f z;E7kBo8O-bH(TN6L_zL@qWZ)Oue>xrel?UV>P;2(T1CByP`b2vZtIm@3q9BNCrfvv zN_SYLJCH%4zijDHOETw^DJ%|mWdgZie#X9$wOVu0atP zuWk|CaRXHaDqH8yF6_t@lt%kA!LrJGP=%HEpb9JRL6WNiu$5jDOH{HQRRunn3a+t& zpok?psF1ucc}wb)Xa3^imTUFgpN4UQSbtZ)q)3TSpzgR(%R;+4-PLYcBac`eA? zL^0Y+eZ!1@)!IZkNKEw|skl;>2&bzX!DviW2zHy3fm+mz&t6UT;d(?6qq4CXU=Jsk+jKVP0CzaisIG zpB9x9MF){gVX*E23}_o*n#q(^8E9z@x(wqfj#?K+))^QQ8i2=a*Z%_+$#p!k`2-hz3gAFd0Ui^636lVpKaFDRC54U)Y!_ z2y;B-f`!N}KD|RgyRVH_xIqQ3a+1~6bh*ITmZ=J$6I4YLhtlw;S>KZwz^22h?Mgh7 zcq9`lh8bCOHybpB!t2lx98eZmd)!DIvO>|DYvIDLCya*71D-OBo`;RZfE8MoDSUu| za=}8~Ek3>DzIw?BRIi?|SorMK!K)8lJD#fAZdGjulC5i)V^b#73U&TqAY5Ug9zPL? zR3B{KK4ciXocc=)+zizvoliPc#i~SQ7B;ZOG}s&q@5%)H0PDKlmG4gl zS6e}h{c*#9M_7znv=Capv0YCi>li;5EI>-qcWqQ&-QxQ@ZlD2Udl*U!x!@L`-Em*c z01;Vt_s%~yzt;*jE^PZC*qID=%4qIP9Ck-nVJO^xGeVOoS)U)IOB=Wf_q#w^1a{}4 zpTG~Ok8nSPiW&! zK!eRW6}!&paq2a3=w>(q3S$1`{AcD*Vr5@=;)C#-B<9wFg7AHuIkLe*gVnt8+J1Qj z@3`UnFk?G`K#tU5&7eJJ0FJ@BSDtepWZHB{HxBPsPE!qrOhNJ5?o6J@I|S$# zEoBC#s9b;r%UFvA%Xu5E<;F9oAn=>7G*R@C( z#8fUI70^T~z-m-cd~-@oisRH^TYZ53%$4G-5qa;M}qb|G=Di&w9YERWVza?$b{NC=yJg# zNH{#bIwf0Kgpr5DFS+ zJ*Ay9fV4fO{WON&#_+wF0Dvx_^C0t_kxQ@&rK-ms-se)S9DC^qs;-*_+)#}I0^A|M z;Cs%98L;G&3+A`J@xaxPyt&2Kcib>wG-cC_b;fpQP$iDuMBgi@;uHeFa@4%?DfOVs ziMTZtY_Wo1=+z)1NUi%5`xE;mUIpU;=y-h4>BRF;`P(%)FYy`~4?xG`gDp-xz1BU> z=Ci3=O%J9&<^;OfV0CP{zU&0rmMN%aD*_OkHY?n!o^;_yrl5lF0Ni)ZlT2q3XO~>C zP-r!6;0%XXw+QaIfuJ$hK6g1CsX@wY;i@XMFaW5)s&WvJouqYprHhyHeL1^00Cp|X z#Wg*!Jr!)Tf^C_=Hlr6zzAMir4kiwM+^Si4!fM}q9sLGtLeAP^kl@b++{Z}i@Cv-d z@EWiZosb|Go3P^wL&FDvRn}yMK|u0Jn-Ru|M?Z+@m~I-pTQQF!x*Es@^W#=S_cbiZ zc*R=B7|?-g0u{}3&!i(&&cso{iKBuOM@4z!V5TJtEvF;yN(DQuAjA+OhJk&4VL9jc zTp(M!t4H5Q=6H$r;vDY}79CJLg5|&FFW(Bt+dJwjV}G42aIn!7W1Wv;3{`_60m=to zi&#eRl?`G}3c5Uv#%{w)eAi*yvT%Sz%x+_GOnv8p&ib6JjirL!RuD&1j~hlabX2XD zEy++LKG;&UMIr4;N7v!DyfRb$s1b%>!-Y5NnlfSeSr}+)%M{6NB+#-dQ!KY7f!2<< zHp+al(C}94;uG&YjUDW@uHW4B{+jn+_=B1EH(B=_Pc|R7%1)%qDnXQ$SKSE)TT3#f z61@hSVg%M1=#nB8TSblVD)W8kP-rBXIn$_f!c=%><<6Og) zRSTiTgYP_gZQu2VZ?#-|)LOegS$rT>e84I`kl33EHJ~BDh~k$iU)f-{;jG#(rHZ<& zB2Y*L#)fqCp2R^b)ShnZ;de9k)ILs>LkK4hCk~T-1#zQ6St<5hSYo}PC9rOTwRUSV z)RFG!S!_;jcuIXz9iOy1KA8-y%7oU?BSHz^XZbCAlOJDYc3k7q)&-)R8ReNXG`|O03Ab zOsF7?&9erPK<5sovkKVZBL}^c4TZ DhY$O= diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/__pycache__/zipp.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/__pycache__/zipp.cpython-311.pyc deleted file mode 100755 index 373b7aa77db5383735f569095d613ddc34e791ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15991 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 Kc+4aBIe!2dQ`y`A diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/_adapters.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/_adapters.cpython-311.pyc deleted file mode 100755 index dfc95d650acbeec91124d08137713c0b53a389de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10749 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 diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/_common.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/_common.cpython-311.pyc deleted file mode 100755 index 57b2f7f852d61fca86cb9125bac4b194b1686bdb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4276 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 BT!sJu diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/_legacy.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/_legacy.cpython-311.pyc deleted file mode 100755 index 5880da66dce4eceba76a5d8528a5d403f13d3833..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6492 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 d%Uj#hmhPPAd)z)$`D zGvtsnl7nDhdS>RIGv|K(`+w%Q9UW~9sk;1EH~y!CvHzlvdJ5Mv8{Z(a!c?Y8I-7Fd z(v&2=15*Jtpa%6|E;JRA81f-KoQq6FL_VyyoQxFCX*pMl(jT&$1;YlYZ)tR)}NV-rMnbq>MBYO7gNMX*pZsd;) zkByC(=y$k~&fH92)69{=&1)&HnZ^vy;46g=s=-IHxq`thbZn~QS{e&6hYNFd7uRye ztd>$|3VJq^wltH=SVjzw`3k@Sdm58}6|2S%Jc*A!j*ouTTZtd5#*bBE$E&g9<9#0{5t^DO0#tFp_CM=>Bs)KUP405f)oSj7&}ryVJzxt6z*0Xt-B z`m`O<4S_5gK~Z=oUUoE<%I33HDpl-mtbMp%7)KLxHvn+gvupXCQs2W}m7c>@x{oe~ z?zJxB;?&BsU6(sApvKFc^Q^JqlDic&bJM)!-MsgUc(V9$n^H@cG;4{O2xH4O5eY$)794yGjOZWM%W$l(d5G;IcHIb30{>!rZX? zwHma8rp0+57Hmgv7}-3Hv>M>sMS(j(Gm<;%r73D#+}?y~Pfa(5*w_oO!2Y+L#k-e| zE}wYPJ@B}Dpme>`JyPu+smP;Md9)lIb&&4z4*F1D@EDO}1)_ZeZzt9GWK|NY#*5bK z$f&~wVM3l+j5jSzl2s7ZXpeMu>Cr>715I*=?y*&QND`%D1Od zAI+q7r-tuDS56z^2LM)?=q#q>2`VK(GHRXzSa7fPfE0dhow*E)gpwt6$-c})2!s%Ya-3s#o&I5Y&;rn9&07OoZabVjpVpsKHDXSHNl@Ce_5dF+To zU0X`oAtJ0v@+}0=Ath0{m~gS=Y7YhF=6L{cPw%cLz55^c?k|~@-oa|`;GeZEN{eHQ z>RR9K<=m6L!N+}rk4}HJuhRE=weR(>dn$b=|20_YdmB0?wzlo1<-5qVFX9q3-dfp| zFw?K371ru8hhL!dOFT|0xfrXL(A%$aF0*~iBKp=+KjVAu1gw_&H+lqaxb><;SaOnA zS$zU)aVKy$a7((yZU_H_-I7)VlbnbNTM;&A3NWi3MnTKF2F;G1*XGV}Zg9JcgmKca zCXAW9>J)|2{F<2zIiz_7!`MOXcE)Z^r80WjG*c;)76r;IID{F;S8-c|FrKLfP-$KU z_-=u%2ZF6*PrJ8&c5M0BlkS6$yAM9vUg>_d+Wl&|{nhWD%G)4rtq{RFc$(N(di&vz zA6D$7&XtxIw{tD6P-J`$TG}mHGeug`j%c^Dre!9B4q=34 zh*+SNW|=fL2;!*O7<$wdezCVfm!{%Dv^U=b08t_=(YLbm^PQjVUf%trYyab}{Uxi? zHB{{yT8ym8y?=T4&+k^`Jym&6Sw2#l`0cxY`|jVo_wc=P^oS!Q&8$v*AyEA~GB38s zFd8n>yo#refFO@x1b&RbYXtTKG?@~CpQ7B@o3JBe)QIo`KSJ(XvXSR-+d&T zqlN)nMC=k(5w}dWs!_l;t!*l%B0`yJ*E-a;Pnnm6r#e-{B~!B64prY_%kR$UR<@vP zw>9+wc^m&OT$i&@>Ukxtm>SP&reaJhS9qF&jPzBwO~%z5@a)YY1unL(<=`@*X-)$N ztD-kGguS3{XqGb-g~uu<{dAo1W2?X@iTt!eYR)*Wi^o?!9vB zdNy-i$))F%tD2Id^-`RmDruV5gde7BZdb?i@&rHR^O7#!2!O@C%xnc+)O$2|!#Y~6 zjTU~r?`3(fE{9bmvnLY7#Lb&sss!8MhJ<7rygfgWEb?(`iK2$){-=H9^!7DntE=9V z?7p{_?2EAP#bF=SfmPE|GDhA?XF+yL(X})Rj66}n7fTY#j^NoKQ9I8hp^87;en*;@ zN+{W!y!`h*TahGoZ$~2>k?aUGnwsUS0Xr}}Dx6M}B%!7UpSQkwP0MSy3w*pd=v%n! zJPg078=16jjt{$y{|G~vq$B8DSQeAMNq`4^ zPJ#WUc+ym`QgFXPf{|>sLpqeX9n7T*oU9n{B|rqUBf@<*`CIf61kc+E*ymHHYuz2Y zU9$pqnDA`cEpV4iifIYUbweODTXDN@RqobLqN%w60BzZ~^TCk^w|+hUpNGf4o~ax@ zQ$2j9vTLHcYogM3w%T`A_($-}KVD~n*28Ok6N_ibHlM8|hN_97a{JIzIpN^r(Usr* z47p0;L={jzQI$`SJ-;M9P4t%sE>sd1tBH%{_KRe~FG)_-W;;U4pLViA!3EA}5C}I1 z8h&QJBQ*=;ykxmzgR==&R8^nA{Lbg}3KsWh0GDOSFt{xH(hp_X)9k|tc?dPuZMpYy zGxN64aR+z;l)Q-Hok%Yv?3jm$mrz+e7~)4!ue-8uB#AV(cS)w!p1w5%L+?n>wJYUlBC^!U~bC&}OV z;S1+v=y?WUwdM|_r)S8yu?3cZV?_!^S8b?o4ok#2x;wqP#DTPCS-=jvIU zapofHP*1cav8_BZKQt_WNOzG)H$v)p>82Q!hvowrcnX)9oS4A60kp*Px&?f ze(Vqhip3s3vxx8!jbFfygl$1LM_QWgLNl%#6sqGp;HWWyZ$H~o;pUZ)Pf3Dil5+&K zk_99bRpq_q=-#anB$oC*+LNS|@ZOwizL^_1`OTTv`?@2k!FdV#EA$`;$qP>w14D{O zK#4BGv)YS{Yo^-J5l0T_$Q}f1CMf0z?{n$Eq$5)o(8Hs#g|*qjTf)f=Po=gnH-fB9 z-qMco@{aLG{r3m&t9WqX({~HR72`g-AABw)=?t0p*^!5uRr#rJjdUdFEN8PY)N7`x zPu;fkth9dK>a5|b{(qnaRd$S50psJ<`1oRYO+Hi_D9eXxcl3~0;AArHixlmaR7y26 zm}4h~ccfRPT$TW7H%>aq3EN|-l*MN>H9L#;28!)yfs^sH<{XiqrKUoMlE!tSN}+`b z(9+HS09bIZ^*}frU1tP3BVqELnqWK-K8unj7?r~0dDTJ0&51I6_E2pN;Io%LYXAqK z2wz0;KhCn z)ol6af)7wfzil{x!eXy~R^h16QTu}gXv|5Tq^wV-Kc+GQH}P!x0}%|rK?g-O(B}Sp z5WgY5{|^L>2_4l&|BNv36N21}W0-|#c4_;!n0!8iX0H)Q{a diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/simple.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/simple.cpython-311.pyc deleted file mode 100755 index 7d757a0a8b09591fba1456835150c42ddf8b62ea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6389 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 diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/_adapters.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/_adapters.py deleted file mode 100755 index ea363d8..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/_adapters.py +++ /dev/null @@ -1,170 +0,0 @@ -from contextlib import suppress -from io import TextIOWrapper - -from . import abc - - -class SpecLoaderAdapter: - """ - Adapt a package spec to adapt the underlying loader. - """ - - def __init__(self, spec, adapter=lambda spec: spec.loader): - self.spec = spec - self.loader = adapter(spec) - - def __getattr__(self, name): - return getattr(self.spec, name) - - -class TraversableResourcesLoader: - """ - Adapt a loader to provide TraversableResources. - """ - - def __init__(self, spec): - self.spec = spec - - def get_resource_reader(self, name): - return CompatibilityFiles(self.spec)._native() - - -def _io_wrapper(file, mode='r', *args, **kwargs): - if mode == 'r': - return TextIOWrapper(file, *args, **kwargs) - elif mode == 'rb': - return file - raise ValueError( - "Invalid mode value '{}', only 'r' and 'rb' are supported".format(mode) - ) - - -class CompatibilityFiles: - """ - Adapter for an existing or non-existent resource reader - to provide a compatibility .files(). - """ - - class SpecPath(abc.Traversable): - """ - Path tied to a module spec. - Can be read and exposes the resource reader children. - """ - - def __init__(self, spec, reader): - self._spec = spec - self._reader = reader - - def iterdir(self): - if not self._reader: - return iter(()) - return iter( - CompatibilityFiles.ChildPath(self._reader, path) - for path in self._reader.contents() - ) - - def is_file(self): - return False - - is_dir = is_file - - def joinpath(self, other): - if not self._reader: - return CompatibilityFiles.OrphanPath(other) - return CompatibilityFiles.ChildPath(self._reader, other) - - @property - def name(self): - return self._spec.name - - def open(self, mode='r', *args, **kwargs): - return _io_wrapper(self._reader.open_resource(None), mode, *args, **kwargs) - - class ChildPath(abc.Traversable): - """ - Path tied to a resource reader child. - Can be read but doesn't expose any meaningful children. - """ - - def __init__(self, reader, name): - self._reader = reader - self._name = name - - def iterdir(self): - return iter(()) - - def is_file(self): - return self._reader.is_resource(self.name) - - def is_dir(self): - return not self.is_file() - - def joinpath(self, other): - return CompatibilityFiles.OrphanPath(self.name, other) - - @property - def name(self): - return self._name - - def open(self, mode='r', *args, **kwargs): - return _io_wrapper( - self._reader.open_resource(self.name), mode, *args, **kwargs - ) - - class OrphanPath(abc.Traversable): - """ - Orphan path, not tied to a module spec or resource reader. - Can't be read and doesn't expose any meaningful children. - """ - - def __init__(self, *path_parts): - if len(path_parts) < 1: - raise ValueError('Need at least one path part to construct a path') - self._path = path_parts - - def iterdir(self): - return iter(()) - - def is_file(self): - return False - - is_dir = is_file - - def joinpath(self, other): - return CompatibilityFiles.OrphanPath(*self._path, other) - - @property - def name(self): - return self._path[-1] - - def open(self, mode='r', *args, **kwargs): - raise FileNotFoundError("Can't open orphan path") - - def __init__(self, spec): - self.spec = spec - - @property - def _reader(self): - with suppress(AttributeError): - return self.spec.loader.get_resource_reader(self.spec.name) - - def _native(self): - """ - Return the native reader if it supports files(). - """ - reader = self._reader - return reader if hasattr(reader, 'files') else self - - def __getattr__(self, attr): - return getattr(self._reader, attr) - - def files(self): - return CompatibilityFiles.SpecPath(self.spec, self._reader) - - -def wrap_spec(package): - """ - Construct a package spec with traversable compatibility - on the spec/loader/reader. - """ - return SpecLoaderAdapter(package.__spec__, TraversableResourcesLoader) diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/_common.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/_common.py deleted file mode 100755 index a12e2c7..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/_common.py +++ /dev/null @@ -1,104 +0,0 @@ -import os -import pathlib -import tempfile -import functools -import contextlib -import types -import importlib - -from typing import Union, Optional -from .abc import ResourceReader, Traversable - -from ._compat import wrap_spec - -Package = Union[types.ModuleType, str] - - -def files(package): - # type: (Package) -> Traversable - """ - Get a Traversable resource from a package - """ - return from_package(get_package(package)) - - -def get_resource_reader(package): - # type: (types.ModuleType) -> Optional[ResourceReader] - """ - Return the package's loader if it's a ResourceReader. - """ - # We can't use - # a issubclass() check here because apparently abc.'s __subclasscheck__() - # hook wants to create a weak reference to the object, but - # zipimport.zipimporter does not support weak references, resulting in a - # TypeError. That seems terrible. - spec = package.__spec__ - reader = getattr(spec.loader, 'get_resource_reader', None) # type: ignore - if reader is None: - return None - return reader(spec.name) # type: ignore - - -def resolve(cand): - # type: (Package) -> types.ModuleType - return cand if isinstance(cand, types.ModuleType) else importlib.import_module(cand) - - -def get_package(package): - # type: (Package) -> types.ModuleType - """Take a package name or module object and return the module. - - Raise an exception if the resolved module is not a package. - """ - resolved = resolve(package) - if wrap_spec(resolved).submodule_search_locations is None: - raise TypeError(f'{package!r} is not a package') - return resolved - - -def from_package(package): - """ - Return a Traversable object for the given package. - - """ - spec = wrap_spec(package) - reader = spec.loader.get_resource_reader(spec.name) - return reader.files() - - -@contextlib.contextmanager -def _tempfile(reader, suffix=''): - # Not using tempfile.NamedTemporaryFile as it leads to deeper 'try' - # blocks due to the need to close the temporary file to work on Windows - # properly. - fd, raw_path = tempfile.mkstemp(suffix=suffix) - try: - try: - os.write(fd, reader()) - finally: - os.close(fd) - del reader - yield pathlib.Path(raw_path) - finally: - try: - os.remove(raw_path) - except FileNotFoundError: - pass - - -@functools.singledispatch -def as_file(path): - """ - Given a Traversable object, return that object as a - path on the local file system in a context manager. - """ - return _tempfile(path.read_bytes, suffix=path.name) - - -@as_file.register(pathlib.Path) -@contextlib.contextmanager -def _(path): - """ - Degenerate behavior for pathlib.Path objects. - """ - yield path diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/_compat.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/_compat.py deleted file mode 100755 index cb9fc82..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/_compat.py +++ /dev/null @@ -1,98 +0,0 @@ -# flake8: noqa - -import abc -import sys -import pathlib -from contextlib import suppress - -if sys.version_info >= (3, 10): - from zipfile import Path as ZipPath # type: ignore -else: - from ..zipp import Path as ZipPath # type: ignore - - -try: - from typing import runtime_checkable # type: ignore -except ImportError: - - def runtime_checkable(cls): # type: ignore - return cls - - -try: - from typing import Protocol # type: ignore -except ImportError: - Protocol = abc.ABC # type: ignore - - -class TraversableResourcesLoader: - """ - Adapt loaders to provide TraversableResources and other - compatibility. - - Used primarily for Python 3.9 and earlier where the native - loaders do not yet implement TraversableResources. - """ - - def __init__(self, spec): - self.spec = spec - - @property - def path(self): - return self.spec.origin - - def get_resource_reader(self, name): - from . import readers, _adapters - - def _zip_reader(spec): - with suppress(AttributeError): - return readers.ZipReader(spec.loader, spec.name) - - def _namespace_reader(spec): - with suppress(AttributeError, ValueError): - return readers.NamespaceReader(spec.submodule_search_locations) - - def _available_reader(spec): - with suppress(AttributeError): - return spec.loader.get_resource_reader(spec.name) - - def _native_reader(spec): - reader = _available_reader(spec) - return reader if hasattr(reader, 'files') else None - - def _file_reader(spec): - try: - path = pathlib.Path(self.path) - except TypeError: - return None - if path.exists(): - return readers.FileReader(self) - - return ( - # native reader if it supplies 'files' - _native_reader(self.spec) - or - # local ZipReader if a zip module - _zip_reader(self.spec) - or - # local NamespaceReader if a namespace module - _namespace_reader(self.spec) - or - # local FileReader - _file_reader(self.spec) - # fallback - adapt the spec ResourceReader to TraversableReader - or _adapters.CompatibilityFiles(self.spec) - ) - - -def wrap_spec(package): - """ - Construct a package spec with traversable compatibility - on the spec/loader/reader. - - Supersedes _adapters.wrap_spec to use TraversableResourcesLoader - from above for older Python compatibility (<3.10). - """ - from . import _adapters - - return _adapters.SpecLoaderAdapter(package.__spec__, TraversableResourcesLoader) diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/_itertools.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/_itertools.py deleted file mode 100755 index cce0558..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/_itertools.py +++ /dev/null @@ -1,35 +0,0 @@ -from itertools import filterfalse - -from typing import ( - Callable, - Iterable, - Iterator, - Optional, - Set, - TypeVar, - Union, -) - -# Type and type variable definitions -_T = TypeVar('_T') -_U = TypeVar('_U') - - -def unique_everseen( - iterable: Iterable[_T], key: Optional[Callable[[_T], _U]] = None -) -> Iterator[_T]: - "List unique elements, preserving order. Remember all elements ever seen." - # unique_everseen('AAAABBBCCDAABBB') --> A B C D - # unique_everseen('ABBCcAD', str.lower) --> A B C D - seen: Set[Union[_T, _U]] = set() - seen_add = seen.add - if key is None: - for element in filterfalse(seen.__contains__, iterable): - seen_add(element) - yield element - else: - for element in iterable: - k = key(element) - if k not in seen: - seen_add(k) - yield element diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/_legacy.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/_legacy.py deleted file mode 100755 index 1d5d3f1..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/_legacy.py +++ /dev/null @@ -1,121 +0,0 @@ -import functools -import os -import pathlib -import types -import warnings - -from typing import Union, Iterable, ContextManager, BinaryIO, TextIO, Any - -from . import _common - -Package = Union[types.ModuleType, str] -Resource = str - - -def deprecated(func): - @functools.wraps(func) - def wrapper(*args, **kwargs): - warnings.warn( - f"{func.__name__} is deprecated. Use files() instead. " - "Refer to https://importlib-resources.readthedocs.io" - "/en/latest/using.html#migrating-from-legacy for migration advice.", - DeprecationWarning, - stacklevel=2, - ) - return func(*args, **kwargs) - - return wrapper - - -def normalize_path(path): - # type: (Any) -> str - """Normalize a path by ensuring it is a string. - - If the resulting string contains path separators, an exception is raised. - """ - str_path = str(path) - parent, file_name = os.path.split(str_path) - if parent: - raise ValueError(f'{path!r} must be only a file name') - return file_name - - -@deprecated -def open_binary(package: Package, resource: Resource) -> BinaryIO: - """Return a file-like object opened for binary reading of the resource.""" - return (_common.files(package) / normalize_path(resource)).open('rb') - - -@deprecated -def read_binary(package: Package, resource: Resource) -> bytes: - """Return the binary contents of the resource.""" - return (_common.files(package) / normalize_path(resource)).read_bytes() - - -@deprecated -def open_text( - package: Package, - resource: Resource, - encoding: str = 'utf-8', - errors: str = 'strict', -) -> TextIO: - """Return a file-like object opened for text reading of the resource.""" - return (_common.files(package) / normalize_path(resource)).open( - 'r', encoding=encoding, errors=errors - ) - - -@deprecated -def read_text( - package: Package, - resource: Resource, - encoding: str = 'utf-8', - errors: str = 'strict', -) -> str: - """Return the decoded string of the resource. - - The decoding-related arguments have the same semantics as those of - bytes.decode(). - """ - with open_text(package, resource, encoding, errors) as fp: - return fp.read() - - -@deprecated -def contents(package: Package) -> Iterable[str]: - """Return an iterable of entries in `package`. - - Note that not all entries are resources. Specifically, directories are - not considered resources. Use `is_resource()` on each entry returned here - to check if it is a resource or not. - """ - return [path.name for path in _common.files(package).iterdir()] - - -@deprecated -def is_resource(package: Package, name: str) -> bool: - """True if `name` is a resource inside `package`. - - Directories are *not* resources. - """ - resource = normalize_path(name) - return any( - traversable.name == resource and traversable.is_file() - for traversable in _common.files(package).iterdir() - ) - - -@deprecated -def path( - package: Package, - resource: Resource, -) -> ContextManager[pathlib.Path]: - """A context manager providing a file path object to the resource. - - If the resource does not already exist on its own on the file system, - a temporary file will be created. If the file was created, the file - will be deleted upon exiting the context manager (no exception is - raised if the file was deleted prior to the context manager - exiting). - """ - return _common.as_file(_common.files(package) / normalize_path(resource)) diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/abc.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/abc.py deleted file mode 100755 index d39dc1a..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/abc.py +++ /dev/null @@ -1,137 +0,0 @@ -import abc -from typing import BinaryIO, Iterable, Text - -from ._compat import runtime_checkable, Protocol - - -class ResourceReader(metaclass=abc.ABCMeta): - """Abstract base class for loaders to provide resource reading support.""" - - @abc.abstractmethod - def open_resource(self, resource: Text) -> BinaryIO: - """Return an opened, file-like object for binary reading. - - The 'resource' argument is expected to represent only a file name. - If the resource cannot be found, FileNotFoundError is raised. - """ - # This deliberately raises FileNotFoundError instead of - # NotImplementedError so that if this method is accidentally called, - # it'll still do the right thing. - raise FileNotFoundError - - @abc.abstractmethod - def resource_path(self, resource: Text) -> Text: - """Return the file system path to the specified resource. - - The 'resource' argument is expected to represent only a file name. - If the resource does not exist on the file system, raise - FileNotFoundError. - """ - # This deliberately raises FileNotFoundError instead of - # NotImplementedError so that if this method is accidentally called, - # it'll still do the right thing. - raise FileNotFoundError - - @abc.abstractmethod - def is_resource(self, path: Text) -> bool: - """Return True if the named 'path' is a resource. - - Files are resources, directories are not. - """ - raise FileNotFoundError - - @abc.abstractmethod - def contents(self) -> Iterable[str]: - """Return an iterable of entries in `package`.""" - raise FileNotFoundError - - -@runtime_checkable -class Traversable(Protocol): - """ - An object with a subset of pathlib.Path methods suitable for - traversing directories and opening files. - """ - - @abc.abstractmethod - def iterdir(self): - """ - Yield Traversable objects in self - """ - - def read_bytes(self): - """ - Read contents of self as bytes - """ - with self.open('rb') as strm: - return strm.read() - - def read_text(self, encoding=None): - """ - Read contents of self as text - """ - with self.open(encoding=encoding) as strm: - return strm.read() - - @abc.abstractmethod - def is_dir(self) -> bool: - """ - Return True if self is a directory - """ - - @abc.abstractmethod - def is_file(self) -> bool: - """ - Return True if self is a file - """ - - @abc.abstractmethod - def joinpath(self, child): - """ - Return Traversable child in self - """ - - def __truediv__(self, child): - """ - Return Traversable child in self - """ - return self.joinpath(child) - - @abc.abstractmethod - def open(self, mode='r', *args, **kwargs): - """ - mode may be 'r' or 'rb' to open as text or binary. Return a handle - suitable for reading (same as pathlib.Path.open). - - When opening as text, accepts encoding parameters such as those - accepted by io.TextIOWrapper. - """ - - @abc.abstractproperty - def name(self) -> str: - """ - The base name of this object without any parent references. - """ - - -class TraversableResources(ResourceReader): - """ - The required interface for providing traversable - resources. - """ - - @abc.abstractmethod - def files(self): - """Return a Traversable object for the loaded package.""" - - def open_resource(self, resource): - return self.files().joinpath(resource).open('rb') - - def resource_path(self, resource): - raise FileNotFoundError(resource) - - def is_resource(self, path): - return self.files().joinpath(path).is_file() - - def contents(self): - return (item.name for item in self.files().iterdir()) diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/readers.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/readers.py deleted file mode 100755 index f1190ca..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/readers.py +++ /dev/null @@ -1,122 +0,0 @@ -import collections -import pathlib -import operator - -from . import abc - -from ._itertools import unique_everseen -from ._compat import ZipPath - - -def remove_duplicates(items): - return iter(collections.OrderedDict.fromkeys(items)) - - -class FileReader(abc.TraversableResources): - def __init__(self, loader): - self.path = pathlib.Path(loader.path).parent - - def resource_path(self, resource): - """ - Return the file system path to prevent - `resources.path()` from creating a temporary - copy. - """ - return str(self.path.joinpath(resource)) - - def files(self): - return self.path - - -class ZipReader(abc.TraversableResources): - def __init__(self, loader, module): - _, _, name = module.rpartition('.') - self.prefix = loader.prefix.replace('\\', '/') + name + '/' - self.archive = loader.archive - - def open_resource(self, resource): - try: - return super().open_resource(resource) - except KeyError as exc: - raise FileNotFoundError(exc.args[0]) - - def is_resource(self, path): - # workaround for `zipfile.Path.is_file` returning true - # for non-existent paths. - target = self.files().joinpath(path) - return target.is_file() and target.exists() - - def files(self): - return ZipPath(self.archive, self.prefix) - - -class MultiplexedPath(abc.Traversable): - """ - Given a series of Traversable objects, implement a merged - version of the interface across all objects. Useful for - namespace packages which may be multihomed at a single - name. - """ - - def __init__(self, *paths): - self._paths = list(map(pathlib.Path, remove_duplicates(paths))) - if not self._paths: - message = 'MultiplexedPath must contain at least one path' - raise FileNotFoundError(message) - if not all(path.is_dir() for path in self._paths): - raise NotADirectoryError('MultiplexedPath only supports directories') - - def iterdir(self): - files = (file for path in self._paths for file in path.iterdir()) - return unique_everseen(files, key=operator.attrgetter('name')) - - def read_bytes(self): - raise FileNotFoundError(f'{self} is not a file') - - def read_text(self, *args, **kwargs): - raise FileNotFoundError(f'{self} is not a file') - - def is_dir(self): - return True - - def is_file(self): - return False - - def joinpath(self, child): - # first try to find child in current paths - for file in self.iterdir(): - if file.name == child: - return file - # if it does not exist, construct it with the first path - return self._paths[0] / child - - __truediv__ = joinpath - - def open(self, *args, **kwargs): - raise FileNotFoundError(f'{self} is not a file') - - @property - def name(self): - return self._paths[0].name - - def __repr__(self): - paths = ', '.join(f"'{path}'" for path in self._paths) - return f'MultiplexedPath({paths})' - - -class NamespaceReader(abc.TraversableResources): - def __init__(self, namespace_path): - if 'NamespacePath' not in str(namespace_path): - raise ValueError('Invalid path') - self.path = MultiplexedPath(*list(namespace_path)) - - def resource_path(self, resource): - """ - Return the file system path to prevent - `resources.path()` from creating a temporary - copy. - """ - return str(self.path.joinpath(resource)) - - def files(self): - return self.path diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/simple.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/simple.py deleted file mode 100755 index da073cb..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/importlib_resources/simple.py +++ /dev/null @@ -1,116 +0,0 @@ -""" -Interface adapters for low-level readers. -""" - -import abc -import io -import itertools -from typing import BinaryIO, List - -from .abc import Traversable, TraversableResources - - -class SimpleReader(abc.ABC): - """ - The minimum, low-level interface required from a resource - provider. - """ - - @abc.abstractproperty - def package(self): - # type: () -> str - """ - The name of the package for which this reader loads resources. - """ - - @abc.abstractmethod - def children(self): - # type: () -> List['SimpleReader'] - """ - Obtain an iterable of SimpleReader for available - child containers (e.g. directories). - """ - - @abc.abstractmethod - def resources(self): - # type: () -> List[str] - """ - Obtain available named resources for this virtual package. - """ - - @abc.abstractmethod - def open_binary(self, resource): - # type: (str) -> BinaryIO - """ - Obtain a File-like for a named resource. - """ - - @property - def name(self): - return self.package.split('.')[-1] - - -class ResourceHandle(Traversable): - """ - Handle to a named resource in a ResourceReader. - """ - - def __init__(self, parent, name): - # type: (ResourceContainer, str) -> None - self.parent = parent - self.name = name # type: ignore - - def is_file(self): - return True - - def is_dir(self): - return False - - def open(self, mode='r', *args, **kwargs): - stream = self.parent.reader.open_binary(self.name) - if 'b' not in mode: - stream = io.TextIOWrapper(*args, **kwargs) - return stream - - def joinpath(self, name): - raise RuntimeError("Cannot traverse into a resource") - - -class ResourceContainer(Traversable): - """ - Traversable container for a package's resources via its reader. - """ - - def __init__(self, reader): - # type: (SimpleReader) -> None - self.reader = reader - - def is_dir(self): - return True - - def is_file(self): - return False - - def iterdir(self): - files = (ResourceHandle(self, name) for name in self.reader.resources) - dirs = map(ResourceContainer, self.reader.children()) - return itertools.chain(files, dirs) - - def open(self, *args, **kwargs): - raise IsADirectoryError() - - def joinpath(self, name): - return next( - traversable for traversable in self.iterdir() if traversable.name == name - ) - - -class TraversableReader(TraversableResources, SimpleReader): - """ - A TraversableResources based on SimpleReader. Resource providers - may derive from this class to provide the TraversableResources - interface by supplying the SimpleReader interface. - """ - - def files(self): - return ResourceContainer(self) diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/jaraco/__init__.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/jaraco/__init__.py deleted file mode 100755 index e69de29..0000000 diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/jaraco/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/jaraco/__pycache__/__init__.cpython-311.pyc deleted file mode 100755 index 259e6c44d3b5d406d0ed7a1ff00ccdd180fef7a5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 205 zcmZ3^%ge<81Xrfa$^y}kK?DpiLK&agfQ;!3DGb33nv8xc8H$*I{LdiCUkUmd`MIh3 zxrs%|`TAb@>G{U`i3J7vWvO{(`Z<|N`URCG8Tom}dWMGj#hE3kx&?{J*@@|?#rg%= z>G4IW#rdU0$v|E_P(w<7k$zTUQ6kWw`1s7c%#!$cy@JYL95%W6DWy57c15f}3qejQ U<_8iVm>C%vKQO?EB4(f%0DEsXAOHXW diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/jaraco/__pycache__/context.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/jaraco/__pycache__/context.cpython-311.pyc deleted file mode 100755 index c8e3c36cc95517cf3a2bbf0ebbab6681f3e9b935..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10980 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 bI?B48Ja}m>SU6DW8oWytU)-mbaoYa_F|;h& diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/jaraco/__pycache__/functools.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/jaraco/__pycache__/functools.cpython-311.pyc deleted file mode 100755 index ef340bbf79228230b30862c5f44908a3f5e0dda2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20291 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 TJaG8o@iplXwfU@s<*@$;w0s9H diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/jaraco/context.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/jaraco/context.py deleted file mode 100755 index 818f16f..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/jaraco/context.py +++ /dev/null @@ -1,253 +0,0 @@ -import os -import subprocess -import contextlib -import functools -import tempfile -import shutil -import operator - - -@contextlib.contextmanager -def pushd(dir): - orig = os.getcwd() - os.chdir(dir) - try: - yield dir - finally: - os.chdir(orig) - - -@contextlib.contextmanager -def tarball_context(url, target_dir=None, runner=None, pushd=pushd): - """ - Get a tarball, extract it, change to that directory, yield, then - clean up. - `runner` is the function to invoke commands. - `pushd` is a context manager for changing the directory. - """ - if target_dir is None: - target_dir = os.path.basename(url).replace('.tar.gz', '').replace('.tgz', '') - if runner is None: - runner = functools.partial(subprocess.check_call, shell=True) - # In the tar command, use --strip-components=1 to strip the first path and - # then - # use -C to cause the files to be extracted to {target_dir}. This ensures - # that we always know where the files were extracted. - runner('mkdir {target_dir}'.format(**vars())) - try: - getter = 'wget {url} -O -' - extract = 'tar x{compression} --strip-components=1 -C {target_dir}' - cmd = ' | '.join((getter, extract)) - runner(cmd.format(compression=infer_compression(url), **vars())) - with pushd(target_dir): - yield target_dir - finally: - runner('rm -Rf {target_dir}'.format(**vars())) - - -def infer_compression(url): - """ - Given a URL or filename, infer the compression code for tar. - """ - # cheat and just assume it's the last two characters - compression_indicator = url[-2:] - mapping = dict(gz='z', bz='j', xz='J') - # Assume 'z' (gzip) if no match - return mapping.get(compression_indicator, 'z') - - -@contextlib.contextmanager -def temp_dir(remover=shutil.rmtree): - """ - Create a temporary directory context. Pass a custom remover - to override the removal behavior. - """ - temp_dir = tempfile.mkdtemp() - try: - yield temp_dir - finally: - remover(temp_dir) - - -@contextlib.contextmanager -def repo_context(url, branch=None, quiet=True, dest_ctx=temp_dir): - """ - Check out the repo indicated by url. - - If dest_ctx is supplied, it should be a context manager - to yield the target directory for the check out. - """ - exe = 'git' if 'git' in url else 'hg' - with dest_ctx() as repo_dir: - cmd = [exe, 'clone', url, repo_dir] - if branch: - cmd.extend(['--branch', branch]) - devnull = open(os.path.devnull, 'w') - stdout = devnull if quiet else None - subprocess.check_call(cmd, stdout=stdout) - yield repo_dir - - -@contextlib.contextmanager -def null(): - yield - - -class ExceptionTrap: - """ - A context manager that will catch certain exceptions and provide an - indication they occurred. - - >>> with ExceptionTrap() as trap: - ... raise Exception() - >>> bool(trap) - True - - >>> with ExceptionTrap() as trap: - ... pass - >>> bool(trap) - False - - >>> with ExceptionTrap(ValueError) as trap: - ... raise ValueError("1 + 1 is not 3") - >>> bool(trap) - True - - >>> with ExceptionTrap(ValueError) as trap: - ... raise Exception() - Traceback (most recent call last): - ... - Exception - - >>> bool(trap) - False - """ - - exc_info = None, None, None - - def __init__(self, exceptions=(Exception,)): - self.exceptions = exceptions - - def __enter__(self): - return self - - @property - def type(self): - return self.exc_info[0] - - @property - def value(self): - return self.exc_info[1] - - @property - def tb(self): - return self.exc_info[2] - - def __exit__(self, *exc_info): - type = exc_info[0] - matches = type and issubclass(type, self.exceptions) - if matches: - self.exc_info = exc_info - return matches - - def __bool__(self): - return bool(self.type) - - def raises(self, func, *, _test=bool): - """ - Wrap func and replace the result with the truth - value of the trap (True if an exception occurred). - - First, give the decorator an alias to support Python 3.8 - Syntax. - - >>> raises = ExceptionTrap(ValueError).raises - - Now decorate a function that always fails. - - >>> @raises - ... def fail(): - ... raise ValueError('failed') - >>> fail() - True - """ - - @functools.wraps(func) - def wrapper(*args, **kwargs): - with ExceptionTrap(self.exceptions) as trap: - func(*args, **kwargs) - return _test(trap) - - return wrapper - - def passes(self, func): - """ - Wrap func and replace the result with the truth - value of the trap (True if no exception). - - First, give the decorator an alias to support Python 3.8 - Syntax. - - >>> passes = ExceptionTrap(ValueError).passes - - Now decorate a function that always fails. - - >>> @passes - ... def fail(): - ... raise ValueError('failed') - - >>> fail() - False - """ - return self.raises(func, _test=operator.not_) - - -class suppress(contextlib.suppress, contextlib.ContextDecorator): - """ - A version of contextlib.suppress with decorator support. - - >>> @suppress(KeyError) - ... def key_error(): - ... {}[''] - >>> key_error() - """ - - -class on_interrupt(contextlib.ContextDecorator): - """ - Replace a KeyboardInterrupt with SystemExit(1) - - >>> def do_interrupt(): - ... raise KeyboardInterrupt() - >>> on_interrupt('error')(do_interrupt)() - Traceback (most recent call last): - ... - SystemExit: 1 - >>> on_interrupt('error', code=255)(do_interrupt)() - Traceback (most recent call last): - ... - SystemExit: 255 - >>> on_interrupt('suppress')(do_interrupt)() - >>> with __import__('pytest').raises(KeyboardInterrupt): - ... on_interrupt('ignore')(do_interrupt)() - """ - - def __init__( - self, - action='error', - # py3.7 compat - # /, - code=1, - ): - self.action = action - self.code = code - - def __enter__(self): - return self - - def __exit__(self, exctype, excinst, exctb): - if exctype is not KeyboardInterrupt or self.action == 'ignore': - return - elif self.action == 'error': - raise SystemExit(self.code) from excinst - return self.action == 'suppress' diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/jaraco/functools.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/jaraco/functools.py deleted file mode 100755 index a3fea3a..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/jaraco/functools.py +++ /dev/null @@ -1,525 +0,0 @@ -import functools -import time -import inspect -import collections -import types -import itertools - -import pkg_resources.extern.more_itertools - -from typing import Callable, TypeVar - - -CallableT = TypeVar("CallableT", bound=Callable[..., object]) - - -def compose(*funcs): - """ - Compose any number of unary functions into a single unary function. - - >>> import textwrap - >>> expected = str.strip(textwrap.dedent(compose.__doc__)) - >>> strip_and_dedent = compose(str.strip, textwrap.dedent) - >>> strip_and_dedent(compose.__doc__) == expected - True - - Compose also allows the innermost function to take arbitrary arguments. - - >>> round_three = lambda x: round(x, ndigits=3) - >>> f = compose(round_three, int.__truediv__) - >>> [f(3*x, x+1) for x in range(1,10)] - [1.5, 2.0, 2.25, 2.4, 2.5, 2.571, 2.625, 2.667, 2.7] - """ - - def compose_two(f1, f2): - return lambda *args, **kwargs: f1(f2(*args, **kwargs)) - - return functools.reduce(compose_two, funcs) - - -def method_caller(method_name, *args, **kwargs): - """ - Return a function that will call a named method on the - target object with optional positional and keyword - arguments. - - >>> lower = method_caller('lower') - >>> lower('MyString') - 'mystring' - """ - - def call_method(target): - func = getattr(target, method_name) - return func(*args, **kwargs) - - return call_method - - -def once(func): - """ - Decorate func so it's only ever called the first time. - - This decorator can ensure that an expensive or non-idempotent function - will not be expensive on subsequent calls and is idempotent. - - >>> add_three = once(lambda a: a+3) - >>> add_three(3) - 6 - >>> add_three(9) - 6 - >>> add_three('12') - 6 - - To reset the stored value, simply clear the property ``saved_result``. - - >>> del add_three.saved_result - >>> add_three(9) - 12 - >>> add_three(8) - 12 - - Or invoke 'reset()' on it. - - >>> add_three.reset() - >>> add_three(-3) - 0 - >>> add_three(0) - 0 - """ - - @functools.wraps(func) - def wrapper(*args, **kwargs): - if not hasattr(wrapper, 'saved_result'): - wrapper.saved_result = func(*args, **kwargs) - return wrapper.saved_result - - wrapper.reset = lambda: vars(wrapper).__delitem__('saved_result') - return wrapper - - -def method_cache( - method: CallableT, - cache_wrapper: Callable[ - [CallableT], CallableT - ] = functools.lru_cache(), # type: ignore[assignment] -) -> CallableT: - """ - Wrap lru_cache to support storing the cache data in the object instances. - - Abstracts the common paradigm where the method explicitly saves an - underscore-prefixed protected property on first call and returns that - subsequently. - - >>> class MyClass: - ... calls = 0 - ... - ... @method_cache - ... def method(self, value): - ... self.calls += 1 - ... return value - - >>> a = MyClass() - >>> a.method(3) - 3 - >>> for x in range(75): - ... res = a.method(x) - >>> a.calls - 75 - - Note that the apparent behavior will be exactly like that of lru_cache - except that the cache is stored on each instance, so values in one - instance will not flush values from another, and when an instance is - deleted, so are the cached values for that instance. - - >>> b = MyClass() - >>> for x in range(35): - ... res = b.method(x) - >>> b.calls - 35 - >>> a.method(0) - 0 - >>> a.calls - 75 - - Note that if method had been decorated with ``functools.lru_cache()``, - a.calls would have been 76 (due to the cached value of 0 having been - flushed by the 'b' instance). - - Clear the cache with ``.cache_clear()`` - - >>> a.method.cache_clear() - - Same for a method that hasn't yet been called. - - >>> c = MyClass() - >>> c.method.cache_clear() - - Another cache wrapper may be supplied: - - >>> cache = functools.lru_cache(maxsize=2) - >>> MyClass.method2 = method_cache(lambda self: 3, cache_wrapper=cache) - >>> a = MyClass() - >>> a.method2() - 3 - - Caution - do not subsequently wrap the method with another decorator, such - as ``@property``, which changes the semantics of the function. - - See also - http://code.activestate.com/recipes/577452-a-memoize-decorator-for-instance-methods/ - for another implementation and additional justification. - """ - - def wrapper(self: object, *args: object, **kwargs: object) -> object: - # it's the first call, replace the method with a cached, bound method - bound_method: CallableT = types.MethodType( # type: ignore[assignment] - method, self - ) - cached_method = cache_wrapper(bound_method) - setattr(self, method.__name__, cached_method) - return cached_method(*args, **kwargs) - - # Support cache clear even before cache has been created. - wrapper.cache_clear = lambda: None # type: ignore[attr-defined] - - return ( # type: ignore[return-value] - _special_method_cache(method, cache_wrapper) or wrapper - ) - - -def _special_method_cache(method, cache_wrapper): - """ - Because Python treats special methods differently, it's not - possible to use instance attributes to implement the cached - methods. - - Instead, install the wrapper method under a different name - and return a simple proxy to that wrapper. - - https://github.com/jaraco/jaraco.functools/issues/5 - """ - name = method.__name__ - special_names = '__getattr__', '__getitem__' - if name not in special_names: - return - - wrapper_name = '__cached' + name - - def proxy(self, *args, **kwargs): - if wrapper_name not in vars(self): - bound = types.MethodType(method, self) - cache = cache_wrapper(bound) - setattr(self, wrapper_name, cache) - else: - cache = getattr(self, wrapper_name) - return cache(*args, **kwargs) - - return proxy - - -def apply(transform): - """ - Decorate a function with a transform function that is - invoked on results returned from the decorated function. - - >>> @apply(reversed) - ... def get_numbers(start): - ... "doc for get_numbers" - ... return range(start, start+3) - >>> list(get_numbers(4)) - [6, 5, 4] - >>> get_numbers.__doc__ - 'doc for get_numbers' - """ - - def wrap(func): - return functools.wraps(func)(compose(transform, func)) - - return wrap - - -def result_invoke(action): - r""" - Decorate a function with an action function that is - invoked on the results returned from the decorated - function (for its side-effect), then return the original - result. - - >>> @result_invoke(print) - ... def add_two(a, b): - ... return a + b - >>> x = add_two(2, 3) - 5 - >>> x - 5 - """ - - def wrap(func): - @functools.wraps(func) - def wrapper(*args, **kwargs): - result = func(*args, **kwargs) - action(result) - return result - - return wrapper - - return wrap - - -def call_aside(f, *args, **kwargs): - """ - Call a function for its side effect after initialization. - - >>> @call_aside - ... def func(): print("called") - called - >>> func() - called - - Use functools.partial to pass parameters to the initial call - - >>> @functools.partial(call_aside, name='bingo') - ... def func(name): print("called with", name) - called with bingo - """ - f(*args, **kwargs) - return f - - -class Throttler: - """ - Rate-limit a function (or other callable) - """ - - def __init__(self, func, max_rate=float('Inf')): - if isinstance(func, Throttler): - func = func.func - self.func = func - self.max_rate = max_rate - self.reset() - - def reset(self): - self.last_called = 0 - - def __call__(self, *args, **kwargs): - self._wait() - return self.func(*args, **kwargs) - - def _wait(self): - "ensure at least 1/max_rate seconds from last call" - elapsed = time.time() - self.last_called - must_wait = 1 / self.max_rate - elapsed - time.sleep(max(0, must_wait)) - self.last_called = time.time() - - def __get__(self, obj, type=None): - return first_invoke(self._wait, functools.partial(self.func, obj)) - - -def first_invoke(func1, func2): - """ - Return a function that when invoked will invoke func1 without - any parameters (for its side-effect) and then invoke func2 - with whatever parameters were passed, returning its result. - """ - - def wrapper(*args, **kwargs): - func1() - return func2(*args, **kwargs) - - return wrapper - - -def retry_call(func, cleanup=lambda: None, retries=0, trap=()): - """ - Given a callable func, trap the indicated exceptions - for up to 'retries' times, invoking cleanup on the - exception. On the final attempt, allow any exceptions - to propagate. - """ - attempts = itertools.count() if retries == float('inf') else range(retries) - for attempt in attempts: - try: - return func() - except trap: - cleanup() - - return func() - - -def retry(*r_args, **r_kwargs): - """ - Decorator wrapper for retry_call. Accepts arguments to retry_call - except func and then returns a decorator for the decorated function. - - Ex: - - >>> @retry(retries=3) - ... def my_func(a, b): - ... "this is my funk" - ... print(a, b) - >>> my_func.__doc__ - 'this is my funk' - """ - - def decorate(func): - @functools.wraps(func) - def wrapper(*f_args, **f_kwargs): - bound = functools.partial(func, *f_args, **f_kwargs) - return retry_call(bound, *r_args, **r_kwargs) - - return wrapper - - return decorate - - -def print_yielded(func): - """ - Convert a generator into a function that prints all yielded elements - - >>> @print_yielded - ... def x(): - ... yield 3; yield None - >>> x() - 3 - None - """ - print_all = functools.partial(map, print) - print_results = compose(more_itertools.consume, print_all, func) - return functools.wraps(func)(print_results) - - -def pass_none(func): - """ - Wrap func so it's not called if its first param is None - - >>> print_text = pass_none(print) - >>> print_text('text') - text - >>> print_text(None) - """ - - @functools.wraps(func) - def wrapper(param, *args, **kwargs): - if param is not None: - return func(param, *args, **kwargs) - - return wrapper - - -def assign_params(func, namespace): - """ - Assign parameters from namespace where func solicits. - - >>> def func(x, y=3): - ... print(x, y) - >>> assigned = assign_params(func, dict(x=2, z=4)) - >>> assigned() - 2 3 - - The usual errors are raised if a function doesn't receive - its required parameters: - - >>> assigned = assign_params(func, dict(y=3, z=4)) - >>> assigned() - Traceback (most recent call last): - TypeError: func() ...argument... - - It even works on methods: - - >>> class Handler: - ... def meth(self, arg): - ... print(arg) - >>> assign_params(Handler().meth, dict(arg='crystal', foo='clear'))() - crystal - """ - sig = inspect.signature(func) - params = sig.parameters.keys() - call_ns = {k: namespace[k] for k in params if k in namespace} - return functools.partial(func, **call_ns) - - -def save_method_args(method): - """ - Wrap a method such that when it is called, the args and kwargs are - saved on the method. - - >>> class MyClass: - ... @save_method_args - ... def method(self, a, b): - ... print(a, b) - >>> my_ob = MyClass() - >>> my_ob.method(1, 2) - 1 2 - >>> my_ob._saved_method.args - (1, 2) - >>> my_ob._saved_method.kwargs - {} - >>> my_ob.method(a=3, b='foo') - 3 foo - >>> my_ob._saved_method.args - () - >>> my_ob._saved_method.kwargs == dict(a=3, b='foo') - True - - The arguments are stored on the instance, allowing for - different instance to save different args. - - >>> your_ob = MyClass() - >>> your_ob.method({str('x'): 3}, b=[4]) - {'x': 3} [4] - >>> your_ob._saved_method.args - ({'x': 3},) - >>> my_ob._saved_method.args - () - """ - args_and_kwargs = collections.namedtuple('args_and_kwargs', 'args kwargs') - - @functools.wraps(method) - def wrapper(self, *args, **kwargs): - attr_name = '_saved_' + method.__name__ - attr = args_and_kwargs(args, kwargs) - setattr(self, attr_name, attr) - return method(self, *args, **kwargs) - - return wrapper - - -def except_(*exceptions, replace=None, use=None): - """ - Replace the indicated exceptions, if raised, with the indicated - literal replacement or evaluated expression (if present). - - >>> safe_int = except_(ValueError)(int) - >>> safe_int('five') - >>> safe_int('5') - 5 - - Specify a literal replacement with ``replace``. - - >>> safe_int_r = except_(ValueError, replace=0)(int) - >>> safe_int_r('five') - 0 - - Provide an expression to ``use`` to pass through particular parameters. - - >>> safe_int_pt = except_(ValueError, use='args[0]')(int) - >>> safe_int_pt('five') - 'five' - - """ - - def decorate(func): - @functools.wraps(func) - def wrapper(*args, **kwargs): - try: - return func(*args, **kwargs) - except exceptions: - try: - return eval(use) - except TypeError: - return replace - - return wrapper - - return decorate diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/jaraco/text/__init__.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/jaraco/text/__init__.py deleted file mode 100755 index c466378..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/jaraco/text/__init__.py +++ /dev/null @@ -1,599 +0,0 @@ -import re -import itertools -import textwrap -import functools - -try: - from importlib.resources import files # type: ignore -except ImportError: # pragma: nocover - from pkg_resources.extern.importlib_resources import files # type: ignore - -from pkg_resources.extern.jaraco.functools import compose, method_cache -from pkg_resources.extern.jaraco.context import ExceptionTrap - - -def substitution(old, new): - """ - Return a function that will perform a substitution on a string - """ - return lambda s: s.replace(old, new) - - -def multi_substitution(*substitutions): - """ - Take a sequence of pairs specifying substitutions, and create - a function that performs those substitutions. - - >>> multi_substitution(('foo', 'bar'), ('bar', 'baz'))('foo') - 'baz' - """ - substitutions = itertools.starmap(substitution, substitutions) - # compose function applies last function first, so reverse the - # substitutions to get the expected order. - substitutions = reversed(tuple(substitutions)) - return compose(*substitutions) - - -class FoldedCase(str): - """ - A case insensitive string class; behaves just like str - except compares equal when the only variation is case. - - >>> s = FoldedCase('hello world') - - >>> s == 'Hello World' - True - - >>> 'Hello World' == s - True - - >>> s != 'Hello World' - False - - >>> s.index('O') - 4 - - >>> s.split('O') - ['hell', ' w', 'rld'] - - >>> sorted(map(FoldedCase, ['GAMMA', 'alpha', 'Beta'])) - ['alpha', 'Beta', 'GAMMA'] - - Sequence membership is straightforward. - - >>> "Hello World" in [s] - True - >>> s in ["Hello World"] - True - - You may test for set inclusion, but candidate and elements - must both be folded. - - >>> FoldedCase("Hello World") in {s} - True - >>> s in {FoldedCase("Hello World")} - True - - String inclusion works as long as the FoldedCase object - is on the right. - - >>> "hello" in FoldedCase("Hello World") - True - - But not if the FoldedCase object is on the left: - - >>> FoldedCase('hello') in 'Hello World' - False - - In that case, use ``in_``: - - >>> FoldedCase('hello').in_('Hello World') - True - - >>> FoldedCase('hello') > FoldedCase('Hello') - False - """ - - def __lt__(self, other): - return self.lower() < other.lower() - - def __gt__(self, other): - return self.lower() > other.lower() - - def __eq__(self, other): - return self.lower() == other.lower() - - def __ne__(self, other): - return self.lower() != other.lower() - - def __hash__(self): - return hash(self.lower()) - - def __contains__(self, other): - return super().lower().__contains__(other.lower()) - - def in_(self, other): - "Does self appear in other?" - return self in FoldedCase(other) - - # cache lower since it's likely to be called frequently. - @method_cache - def lower(self): - return super().lower() - - def index(self, sub): - return self.lower().index(sub.lower()) - - def split(self, splitter=' ', maxsplit=0): - pattern = re.compile(re.escape(splitter), re.I) - return pattern.split(self, maxsplit) - - -# Python 3.8 compatibility -_unicode_trap = ExceptionTrap(UnicodeDecodeError) - - -@_unicode_trap.passes -def is_decodable(value): - r""" - Return True if the supplied value is decodable (using the default - encoding). - - >>> is_decodable(b'\xff') - False - >>> is_decodable(b'\x32') - True - """ - value.decode() - - -def is_binary(value): - r""" - Return True if the value appears to be binary (that is, it's a byte - string and isn't decodable). - - >>> is_binary(b'\xff') - True - >>> is_binary('\xff') - False - """ - return isinstance(value, bytes) and not is_decodable(value) - - -def trim(s): - r""" - Trim something like a docstring to remove the whitespace that - is common due to indentation and formatting. - - >>> trim("\n\tfoo = bar\n\t\tbar = baz\n") - 'foo = bar\n\tbar = baz' - """ - return textwrap.dedent(s).strip() - - -def wrap(s): - """ - Wrap lines of text, retaining existing newlines as - paragraph markers. - - >>> print(wrap(lorem_ipsum)) - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do - eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad - minim veniam, quis nostrud exercitation ullamco laboris nisi ut - aliquip ex ea commodo consequat. Duis aute irure dolor in - reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla - pariatur. Excepteur sint occaecat cupidatat non proident, sunt in - culpa qui officia deserunt mollit anim id est laborum. - - Curabitur pretium tincidunt lacus. Nulla gravida orci a odio. Nullam - varius, turpis et commodo pharetra, est eros bibendum elit, nec luctus - magna felis sollicitudin mauris. Integer in mauris eu nibh euismod - gravida. Duis ac tellus et risus vulputate vehicula. Donec lobortis - risus a elit. Etiam tempor. Ut ullamcorper, ligula eu tempor congue, - eros est euismod turpis, id tincidunt sapien risus a quam. Maecenas - fermentum consequat mi. Donec fermentum. Pellentesque malesuada nulla - a mi. Duis sapien sem, aliquet nec, commodo eget, consequat quis, - neque. Aliquam faucibus, elit ut dictum aliquet, felis nisl adipiscing - sapien, sed malesuada diam lacus eget erat. Cras mollis scelerisque - nunc. Nullam arcu. Aliquam consequat. Curabitur augue lorem, dapibus - quis, laoreet et, pretium ac, nisi. Aenean magna nisl, mollis quis, - molestie eu, feugiat in, orci. In hac habitasse platea dictumst. - """ - paragraphs = s.splitlines() - wrapped = ('\n'.join(textwrap.wrap(para)) for para in paragraphs) - return '\n\n'.join(wrapped) - - -def unwrap(s): - r""" - Given a multi-line string, return an unwrapped version. - - >>> wrapped = wrap(lorem_ipsum) - >>> wrapped.count('\n') - 20 - >>> unwrapped = unwrap(wrapped) - >>> unwrapped.count('\n') - 1 - >>> print(unwrapped) - Lorem ipsum dolor sit amet, consectetur adipiscing ... - Curabitur pretium tincidunt lacus. Nulla gravida orci ... - - """ - paragraphs = re.split(r'\n\n+', s) - cleaned = (para.replace('\n', ' ') for para in paragraphs) - return '\n'.join(cleaned) - - - - -class Splitter(object): - """object that will split a string with the given arguments for each call - - >>> s = Splitter(',') - >>> s('hello, world, this is your, master calling') - ['hello', ' world', ' this is your', ' master calling'] - """ - - def __init__(self, *args): - self.args = args - - def __call__(self, s): - return s.split(*self.args) - - -def indent(string, prefix=' ' * 4): - """ - >>> indent('foo') - ' foo' - """ - return prefix + string - - -class WordSet(tuple): - """ - Given an identifier, return the words that identifier represents, - whether in camel case, underscore-separated, etc. - - >>> WordSet.parse("camelCase") - ('camel', 'Case') - - >>> WordSet.parse("under_sep") - ('under', 'sep') - - Acronyms should be retained - - >>> WordSet.parse("firstSNL") - ('first', 'SNL') - - >>> WordSet.parse("you_and_I") - ('you', 'and', 'I') - - >>> WordSet.parse("A simple test") - ('A', 'simple', 'test') - - Multiple caps should not interfere with the first cap of another word. - - >>> WordSet.parse("myABCClass") - ('my', 'ABC', 'Class') - - The result is a WordSet, so you can get the form you need. - - >>> WordSet.parse("myABCClass").underscore_separated() - 'my_ABC_Class' - - >>> WordSet.parse('a-command').camel_case() - 'ACommand' - - >>> WordSet.parse('someIdentifier').lowered().space_separated() - 'some identifier' - - Slices of the result should return another WordSet. - - >>> WordSet.parse('taken-out-of-context')[1:].underscore_separated() - 'out_of_context' - - >>> WordSet.from_class_name(WordSet()).lowered().space_separated() - 'word set' - - >>> example = WordSet.parse('figured it out') - >>> example.headless_camel_case() - 'figuredItOut' - >>> example.dash_separated() - 'figured-it-out' - - """ - - _pattern = re.compile('([A-Z]?[a-z]+)|([A-Z]+(?![a-z]))') - - def capitalized(self): - return WordSet(word.capitalize() for word in self) - - def lowered(self): - return WordSet(word.lower() for word in self) - - def camel_case(self): - return ''.join(self.capitalized()) - - def headless_camel_case(self): - words = iter(self) - first = next(words).lower() - new_words = itertools.chain((first,), WordSet(words).camel_case()) - return ''.join(new_words) - - def underscore_separated(self): - return '_'.join(self) - - def dash_separated(self): - return '-'.join(self) - - def space_separated(self): - return ' '.join(self) - - def trim_right(self, item): - """ - Remove the item from the end of the set. - - >>> WordSet.parse('foo bar').trim_right('foo') - ('foo', 'bar') - >>> WordSet.parse('foo bar').trim_right('bar') - ('foo',) - >>> WordSet.parse('').trim_right('bar') - () - """ - return self[:-1] if self and self[-1] == item else self - - def trim_left(self, item): - """ - Remove the item from the beginning of the set. - - >>> WordSet.parse('foo bar').trim_left('foo') - ('bar',) - >>> WordSet.parse('foo bar').trim_left('bar') - ('foo', 'bar') - >>> WordSet.parse('').trim_left('bar') - () - """ - return self[1:] if self and self[0] == item else self - - def trim(self, item): - """ - >>> WordSet.parse('foo bar').trim('foo') - ('bar',) - """ - return self.trim_left(item).trim_right(item) - - def __getitem__(self, item): - result = super(WordSet, self).__getitem__(item) - if isinstance(item, slice): - result = WordSet(result) - return result - - @classmethod - def parse(cls, identifier): - matches = cls._pattern.finditer(identifier) - return WordSet(match.group(0) for match in matches) - - @classmethod - def from_class_name(cls, subject): - return cls.parse(subject.__class__.__name__) - - -# for backward compatibility -words = WordSet.parse - - -def simple_html_strip(s): - r""" - Remove HTML from the string `s`. - - >>> str(simple_html_strip('')) - '' - - >>> print(simple_html_strip('A stormy day in paradise')) - A stormy day in paradise - - >>> print(simple_html_strip('Somebody tell the truth.')) - Somebody tell the truth. - - >>> print(simple_html_strip('What about
\nmultiple lines?')) - What about - multiple lines? - """ - html_stripper = re.compile('()|(<[^>]*>)|([^<]+)', re.DOTALL) - texts = (match.group(3) or '' for match in html_stripper.finditer(s)) - return ''.join(texts) - - -class SeparatedValues(str): - """ - A string separated by a separator. Overrides __iter__ for getting - the values. - - >>> list(SeparatedValues('a,b,c')) - ['a', 'b', 'c'] - - Whitespace is stripped and empty values are discarded. - - >>> list(SeparatedValues(' a, b , c, ')) - ['a', 'b', 'c'] - """ - - separator = ',' - - def __iter__(self): - parts = self.split(self.separator) - return filter(None, (part.strip() for part in parts)) - - -class Stripper: - r""" - Given a series of lines, find the common prefix and strip it from them. - - >>> lines = [ - ... 'abcdefg\n', - ... 'abc\n', - ... 'abcde\n', - ... ] - >>> res = Stripper.strip_prefix(lines) - >>> res.prefix - 'abc' - >>> list(res.lines) - ['defg\n', '\n', 'de\n'] - - If no prefix is common, nothing should be stripped. - - >>> lines = [ - ... 'abcd\n', - ... '1234\n', - ... ] - >>> res = Stripper.strip_prefix(lines) - >>> res.prefix = '' - >>> list(res.lines) - ['abcd\n', '1234\n'] - """ - - def __init__(self, prefix, lines): - self.prefix = prefix - self.lines = map(self, lines) - - @classmethod - def strip_prefix(cls, lines): - prefix_lines, lines = itertools.tee(lines) - prefix = functools.reduce(cls.common_prefix, prefix_lines) - return cls(prefix, lines) - - def __call__(self, line): - if not self.prefix: - return line - null, prefix, rest = line.partition(self.prefix) - return rest - - @staticmethod - def common_prefix(s1, s2): - """ - Return the common prefix of two lines. - """ - index = min(len(s1), len(s2)) - while s1[:index] != s2[:index]: - index -= 1 - return s1[:index] - - -def remove_prefix(text, prefix): - """ - Remove the prefix from the text if it exists. - - >>> remove_prefix('underwhelming performance', 'underwhelming ') - 'performance' - - >>> remove_prefix('something special', 'sample') - 'something special' - """ - null, prefix, rest = text.rpartition(prefix) - return rest - - -def remove_suffix(text, suffix): - """ - Remove the suffix from the text if it exists. - - >>> remove_suffix('name.git', '.git') - 'name' - - >>> remove_suffix('something special', 'sample') - 'something special' - """ - rest, suffix, null = text.partition(suffix) - return rest - - -def normalize_newlines(text): - r""" - Replace alternate newlines with the canonical newline. - - >>> normalize_newlines('Lorem Ipsum\u2029') - 'Lorem Ipsum\n' - >>> normalize_newlines('Lorem Ipsum\r\n') - 'Lorem Ipsum\n' - >>> normalize_newlines('Lorem Ipsum\x85') - 'Lorem Ipsum\n' - """ - newlines = ['\r\n', '\r', '\n', '\u0085', '\u2028', '\u2029'] - pattern = '|'.join(newlines) - return re.sub(pattern, '\n', text) - - -def _nonblank(str): - return str and not str.startswith('#') - - -@functools.singledispatch -def yield_lines(iterable): - r""" - Yield valid lines of a string or iterable. - - >>> list(yield_lines('')) - [] - >>> list(yield_lines(['foo', 'bar'])) - ['foo', 'bar'] - >>> list(yield_lines('foo\nbar')) - ['foo', 'bar'] - >>> list(yield_lines('\nfoo\n#bar\nbaz #comment')) - ['foo', 'baz #comment'] - >>> list(yield_lines(['foo\nbar', 'baz', 'bing\n\n\n'])) - ['foo', 'bar', 'baz', 'bing'] - """ - return itertools.chain.from_iterable(map(yield_lines, iterable)) - - -@yield_lines.register(str) -def _(text): - return filter(_nonblank, map(str.strip, text.splitlines())) - - -def drop_comment(line): - """ - Drop comments. - - >>> drop_comment('foo # bar') - 'foo' - - A hash without a space may be in a URL. - - >>> drop_comment('http://example.com/foo#bar') - 'http://example.com/foo#bar' - """ - return line.partition(' #')[0] - - -def join_continuation(lines): - r""" - Join lines continued by a trailing backslash. - - >>> list(join_continuation(['foo \\', 'bar', 'baz'])) - ['foobar', 'baz'] - >>> list(join_continuation(['foo \\', 'bar', 'baz'])) - ['foobar', 'baz'] - >>> list(join_continuation(['foo \\', 'bar \\', 'baz'])) - ['foobarbaz'] - - Not sure why, but... - The character preceeding the backslash is also elided. - - >>> list(join_continuation(['goo\\', 'dly'])) - ['godly'] - - A terrible idea, but... - If no line is available to continue, suppress the lines. - - >>> list(join_continuation(['foo', 'bar\\', 'baz\\'])) - ['foo'] - """ - lines = iter(lines) - for item in lines: - while item.endswith('\\'): - try: - item = item[:-2].strip() + next(lines) - except StopIteration: - return - yield item diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/jaraco/text/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/jaraco/text/__pycache__/__init__.cpython-311.pyc deleted file mode 100755 index 63d9788ba9a21536331ff8dfd658a4033f25176e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26608 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⪼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 diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/more_itertools/__pycache__/recipes.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/more_itertools/__pycache__/recipes.cpython-311.pyc deleted file mode 100755 index cef0c789bc661413e63fc6e9aa56e53e0e058a1f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33519 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 list(chunked([1, 2, 3, 4, 5, 6], 3)) - [[1, 2, 3], [4, 5, 6]] - - By the default, the last yielded list will have fewer than *n* elements - if the length of *iterable* is not divisible by *n*: - - >>> list(chunked([1, 2, 3, 4, 5, 6, 7, 8], 3)) - [[1, 2, 3], [4, 5, 6], [7, 8]] - - To use a fill-in value instead, see the :func:`grouper` recipe. - - If the length of *iterable* is not divisible by *n* and *strict* is - ``True``, then ``ValueError`` will be raised before the last - list is yielded. - - """ - iterator = iter(partial(take, n, iter(iterable)), []) - if strict: - if n is None: - raise ValueError('n must not be None when using strict mode.') - - def ret(): - for chunk in iterator: - if len(chunk) != n: - raise ValueError('iterable is not divisible by n.') - yield chunk - - return iter(ret()) - else: - return iterator - - -def first(iterable, default=_marker): - """Return the first item of *iterable*, or *default* if *iterable* is - empty. - - >>> first([0, 1, 2, 3]) - 0 - >>> first([], 'some default') - 'some default' - - If *default* is not provided and there are no items in the iterable, - raise ``ValueError``. - - :func:`first` is useful when you have a generator of expensive-to-retrieve - values and want any arbitrary one. It is marginally shorter than - ``next(iter(iterable), default)``. - - """ - try: - return next(iter(iterable)) - except StopIteration as e: - if default is _marker: - raise ValueError( - 'first() was called on an empty iterable, and no ' - 'default value was provided.' - ) from e - return default - - -def last(iterable, default=_marker): - """Return the last item of *iterable*, or *default* if *iterable* is - empty. - - >>> last([0, 1, 2, 3]) - 3 - >>> last([], 'some default') - 'some default' - - If *default* is not provided and there are no items in the iterable, - raise ``ValueError``. - """ - try: - if isinstance(iterable, Sequence): - return iterable[-1] - # Work around https://bugs.python.org/issue38525 - elif hasattr(iterable, '__reversed__') and (hexversion != 0x030800F0): - return next(reversed(iterable)) - else: - return deque(iterable, maxlen=1)[-1] - except (IndexError, TypeError, StopIteration): - if default is _marker: - raise ValueError( - 'last() was called on an empty iterable, and no default was ' - 'provided.' - ) - return default - - -def nth_or_last(iterable, n, default=_marker): - """Return the nth or the last item of *iterable*, - or *default* if *iterable* is empty. - - >>> nth_or_last([0, 1, 2, 3], 2) - 2 - >>> nth_or_last([0, 1], 2) - 1 - >>> nth_or_last([], 0, 'some default') - 'some default' - - If *default* is not provided and there are no items in the iterable, - raise ``ValueError``. - """ - return last(islice(iterable, n + 1), default=default) - - -class peekable: - """Wrap an iterator to allow lookahead and prepending elements. - - Call :meth:`peek` on the result to get the value that will be returned - by :func:`next`. This won't advance the iterator: - - >>> p = peekable(['a', 'b']) - >>> p.peek() - 'a' - >>> next(p) - 'a' - - Pass :meth:`peek` a default value to return that instead of raising - ``StopIteration`` when the iterator is exhausted. - - >>> p = peekable([]) - >>> p.peek('hi') - 'hi' - - peekables also offer a :meth:`prepend` method, which "inserts" items - at the head of the iterable: - - >>> p = peekable([1, 2, 3]) - >>> p.prepend(10, 11, 12) - >>> next(p) - 10 - >>> p.peek() - 11 - >>> list(p) - [11, 12, 1, 2, 3] - - peekables can be indexed. Index 0 is the item that will be returned by - :func:`next`, index 1 is the item after that, and so on: - The values up to the given index will be cached. - - >>> p = peekable(['a', 'b', 'c', 'd']) - >>> p[0] - 'a' - >>> p[1] - 'b' - >>> next(p) - 'a' - - Negative indexes are supported, but be aware that they will cache the - remaining items in the source iterator, which may require significant - storage. - - To check whether a peekable is exhausted, check its truth value: - - >>> p = peekable(['a', 'b']) - >>> if p: # peekable has items - ... list(p) - ['a', 'b'] - >>> if not p: # peekable is exhausted - ... list(p) - [] - - """ - - def __init__(self, iterable): - self._it = iter(iterable) - self._cache = deque() - - def __iter__(self): - return self - - def __bool__(self): - try: - self.peek() - except StopIteration: - return False - return True - - def peek(self, default=_marker): - """Return the item that will be next returned from ``next()``. - - Return ``default`` if there are no items left. If ``default`` is not - provided, raise ``StopIteration``. - - """ - if not self._cache: - try: - self._cache.append(next(self._it)) - except StopIteration: - if default is _marker: - raise - return default - return self._cache[0] - - def prepend(self, *items): - """Stack up items to be the next ones returned from ``next()`` or - ``self.peek()``. The items will be returned in - first in, first out order:: - - >>> p = peekable([1, 2, 3]) - >>> p.prepend(10, 11, 12) - >>> next(p) - 10 - >>> list(p) - [11, 12, 1, 2, 3] - - It is possible, by prepending items, to "resurrect" a peekable that - previously raised ``StopIteration``. - - >>> p = peekable([]) - >>> next(p) - Traceback (most recent call last): - ... - StopIteration - >>> p.prepend(1) - >>> next(p) - 1 - >>> next(p) - Traceback (most recent call last): - ... - StopIteration - - """ - self._cache.extendleft(reversed(items)) - - def __next__(self): - if self._cache: - return self._cache.popleft() - - return next(self._it) - - def _get_slice(self, index): - # Normalize the slice's arguments - step = 1 if (index.step is None) else index.step - if step > 0: - start = 0 if (index.start is None) else index.start - stop = maxsize if (index.stop is None) else index.stop - elif step < 0: - start = -1 if (index.start is None) else index.start - stop = (-maxsize - 1) if (index.stop is None) else index.stop - else: - raise ValueError('slice step cannot be zero') - - # If either the start or stop index is negative, we'll need to cache - # the rest of the iterable in order to slice from the right side. - if (start < 0) or (stop < 0): - self._cache.extend(self._it) - # Otherwise we'll need to find the rightmost index and cache to that - # point. - else: - n = min(max(start, stop) + 1, maxsize) - cache_len = len(self._cache) - if n >= cache_len: - self._cache.extend(islice(self._it, n - cache_len)) - - return list(self._cache)[index] - - def __getitem__(self, index): - if isinstance(index, slice): - return self._get_slice(index) - - cache_len = len(self._cache) - if index < 0: - self._cache.extend(self._it) - elif index >= cache_len: - self._cache.extend(islice(self._it, index + 1 - cache_len)) - - return self._cache[index] - - -def consumer(func): - """Decorator that automatically advances a PEP-342-style "reverse iterator" - to its first yield point so you don't have to call ``next()`` on it - manually. - - >>> @consumer - ... def tally(): - ... i = 0 - ... while True: - ... print('Thing number %s is %s.' % (i, (yield))) - ... i += 1 - ... - >>> t = tally() - >>> t.send('red') - Thing number 0 is red. - >>> t.send('fish') - Thing number 1 is fish. - - Without the decorator, you would have to call ``next(t)`` before - ``t.send()`` could be used. - - """ - - @wraps(func) - def wrapper(*args, **kwargs): - gen = func(*args, **kwargs) - next(gen) - return gen - - return wrapper - - -def ilen(iterable): - """Return the number of items in *iterable*. - - >>> ilen(x for x in range(1000000) if x % 3 == 0) - 333334 - - This consumes the iterable, so handle with care. - - """ - # This approach was selected because benchmarks showed it's likely the - # fastest of the known implementations at the time of writing. - # See GitHub tracker: #236, #230. - counter = count() - deque(zip(iterable, counter), maxlen=0) - return next(counter) - - -def iterate(func, start): - """Return ``start``, ``func(start)``, ``func(func(start))``, ... - - >>> from itertools import islice - >>> list(islice(iterate(lambda x: 2*x, 1), 10)) - [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] - - """ - while True: - yield start - start = func(start) - - -def with_iter(context_manager): - """Wrap an iterable in a ``with`` statement, so it closes once exhausted. - - For example, this will close the file when the iterator is exhausted:: - - upper_lines = (line.upper() for line in with_iter(open('foo'))) - - Any context manager which returns an iterable is a candidate for - ``with_iter``. - - """ - with context_manager as iterable: - yield from iterable - - -def one(iterable, too_short=None, too_long=None): - """Return the first item from *iterable*, which is expected to contain only - that item. Raise an exception if *iterable* is empty or has more than one - item. - - :func:`one` is useful for ensuring that an iterable contains only one item. - For example, it can be used to retrieve the result of a database query - that is expected to return a single row. - - If *iterable* is empty, ``ValueError`` will be raised. You may specify a - different exception with the *too_short* keyword: - - >>> it = [] - >>> one(it) # doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ... - ValueError: too many items in iterable (expected 1)' - >>> too_short = IndexError('too few items') - >>> one(it, too_short=too_short) # doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ... - IndexError: too few items - - Similarly, if *iterable* contains more than one item, ``ValueError`` will - be raised. You may specify a different exception with the *too_long* - keyword: - - >>> it = ['too', 'many'] - >>> one(it) # doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ... - ValueError: Expected exactly one item in iterable, but got 'too', - 'many', and perhaps more. - >>> too_long = RuntimeError - >>> one(it, too_long=too_long) # doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ... - RuntimeError - - Note that :func:`one` attempts to advance *iterable* twice to ensure there - is only one item. See :func:`spy` or :func:`peekable` to check iterable - contents less destructively. - - """ - it = iter(iterable) - - try: - first_value = next(it) - except StopIteration as e: - raise ( - too_short or ValueError('too few items in iterable (expected 1)') - ) from e - - try: - second_value = next(it) - except StopIteration: - pass - else: - msg = ( - 'Expected exactly one item in iterable, but got {!r}, {!r}, ' - 'and perhaps more.'.format(first_value, second_value) - ) - raise too_long or ValueError(msg) - - return first_value - - -def raise_(exception, *args): - raise exception(*args) - - -def strictly_n(iterable, n, too_short=None, too_long=None): - """Validate that *iterable* has exactly *n* items and return them if - it does. If it has fewer than *n* items, call function *too_short* - with those items. If it has more than *n* items, call function - *too_long* with the first ``n + 1`` items. - - >>> iterable = ['a', 'b', 'c', 'd'] - >>> n = 4 - >>> list(strictly_n(iterable, n)) - ['a', 'b', 'c', 'd'] - - By default, *too_short* and *too_long* are functions that raise - ``ValueError``. - - >>> list(strictly_n('ab', 3)) # doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ... - ValueError: too few items in iterable (got 2) - - >>> list(strictly_n('abc', 2)) # doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ... - ValueError: too many items in iterable (got at least 3) - - You can instead supply functions that do something else. - *too_short* will be called with the number of items in *iterable*. - *too_long* will be called with `n + 1`. - - >>> def too_short(item_count): - ... raise RuntimeError - >>> it = strictly_n('abcd', 6, too_short=too_short) - >>> list(it) # doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ... - RuntimeError - - >>> def too_long(item_count): - ... print('The boss is going to hear about this') - >>> it = strictly_n('abcdef', 4, too_long=too_long) - >>> list(it) - The boss is going to hear about this - ['a', 'b', 'c', 'd'] - - """ - if too_short is None: - too_short = lambda item_count: raise_( - ValueError, - 'Too few items in iterable (got {})'.format(item_count), - ) - - if too_long is None: - too_long = lambda item_count: raise_( - ValueError, - 'Too many items in iterable (got at least {})'.format(item_count), - ) - - it = iter(iterable) - for i in range(n): - try: - item = next(it) - except StopIteration: - too_short(i) - return - else: - yield item - - try: - next(it) - except StopIteration: - pass - else: - too_long(n + 1) - - -def distinct_permutations(iterable, r=None): - """Yield successive distinct permutations of the elements in *iterable*. - - >>> sorted(distinct_permutations([1, 0, 1])) - [(0, 1, 1), (1, 0, 1), (1, 1, 0)] - - Equivalent to ``set(permutations(iterable))``, except duplicates are not - generated and thrown away. For larger input sequences this is much more - efficient. - - Duplicate permutations arise when there are duplicated elements in the - input iterable. The number of items returned is - `n! / (x_1! * x_2! * ... * x_n!)`, where `n` is the total number of - items input, and each `x_i` is the count of a distinct item in the input - sequence. - - If *r* is given, only the *r*-length permutations are yielded. - - >>> sorted(distinct_permutations([1, 0, 1], r=2)) - [(0, 1), (1, 0), (1, 1)] - >>> sorted(distinct_permutations(range(3), r=2)) - [(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)] - - """ - # Algorithm: https://w.wiki/Qai - def _full(A): - while True: - # Yield the permutation we have - yield tuple(A) - - # Find the largest index i such that A[i] < A[i + 1] - for i in range(size - 2, -1, -1): - if A[i] < A[i + 1]: - break - # If no such index exists, this permutation is the last one - else: - return - - # Find the largest index j greater than j such that A[i] < A[j] - for j in range(size - 1, i, -1): - if A[i] < A[j]: - break - - # Swap the value of A[i] with that of A[j], then reverse the - # sequence from A[i + 1] to form the new permutation - A[i], A[j] = A[j], A[i] - A[i + 1 :] = A[: i - size : -1] # A[i + 1:][::-1] - - # Algorithm: modified from the above - def _partial(A, r): - # Split A into the first r items and the last r items - head, tail = A[:r], A[r:] - right_head_indexes = range(r - 1, -1, -1) - left_tail_indexes = range(len(tail)) - - while True: - # Yield the permutation we have - yield tuple(head) - - # Starting from the right, find the first index of the head with - # value smaller than the maximum value of the tail - call it i. - pivot = tail[-1] - for i in right_head_indexes: - if head[i] < pivot: - break - pivot = head[i] - else: - return - - # Starting from the left, find the first value of the tail - # with a value greater than head[i] and swap. - for j in left_tail_indexes: - if tail[j] > head[i]: - head[i], tail[j] = tail[j], head[i] - break - # If we didn't find one, start from the right and find the first - # index of the head with a value greater than head[i] and swap. - else: - for j in right_head_indexes: - if head[j] > head[i]: - head[i], head[j] = head[j], head[i] - break - - # Reverse head[i + 1:] and swap it with tail[:r - (i + 1)] - tail += head[: i - r : -1] # head[i + 1:][::-1] - i += 1 - head[i:], tail[:] = tail[: r - i], tail[r - i :] - - items = sorted(iterable) - - size = len(items) - if r is None: - r = size - - if 0 < r <= size: - return _full(items) if (r == size) else _partial(items, r) - - return iter(() if r else ((),)) - - -def intersperse(e, iterable, n=1): - """Intersperse filler element *e* among the items in *iterable*, leaving - *n* items between each filler element. - - >>> list(intersperse('!', [1, 2, 3, 4, 5])) - [1, '!', 2, '!', 3, '!', 4, '!', 5] - - >>> list(intersperse(None, [1, 2, 3, 4, 5], n=2)) - [1, 2, None, 3, 4, None, 5] - - """ - if n == 0: - raise ValueError('n must be > 0') - elif n == 1: - # interleave(repeat(e), iterable) -> e, x_0, e, x_1, e, x_2... - # islice(..., 1, None) -> x_0, e, x_1, e, x_2... - return islice(interleave(repeat(e), iterable), 1, None) - else: - # interleave(filler, chunks) -> [e], [x_0, x_1], [e], [x_2, x_3]... - # islice(..., 1, None) -> [x_0, x_1], [e], [x_2, x_3]... - # flatten(...) -> x_0, x_1, e, x_2, x_3... - filler = repeat([e]) - chunks = chunked(iterable, n) - return flatten(islice(interleave(filler, chunks), 1, None)) - - -def unique_to_each(*iterables): - """Return the elements from each of the input iterables that aren't in the - other input iterables. - - For example, suppose you have a set of packages, each with a set of - dependencies:: - - {'pkg_1': {'A', 'B'}, 'pkg_2': {'B', 'C'}, 'pkg_3': {'B', 'D'}} - - If you remove one package, which dependencies can also be removed? - - If ``pkg_1`` is removed, then ``A`` is no longer necessary - it is not - associated with ``pkg_2`` or ``pkg_3``. Similarly, ``C`` is only needed for - ``pkg_2``, and ``D`` is only needed for ``pkg_3``:: - - >>> unique_to_each({'A', 'B'}, {'B', 'C'}, {'B', 'D'}) - [['A'], ['C'], ['D']] - - If there are duplicates in one input iterable that aren't in the others - they will be duplicated in the output. Input order is preserved:: - - >>> unique_to_each("mississippi", "missouri") - [['p', 'p'], ['o', 'u', 'r']] - - It is assumed that the elements of each iterable are hashable. - - """ - pool = [list(it) for it in iterables] - counts = Counter(chain.from_iterable(map(set, pool))) - uniques = {element for element in counts if counts[element] == 1} - return [list(filter(uniques.__contains__, it)) for it in pool] - - -def windowed(seq, n, fillvalue=None, step=1): - """Return a sliding window of width *n* over the given iterable. - - >>> all_windows = windowed([1, 2, 3, 4, 5], 3) - >>> list(all_windows) - [(1, 2, 3), (2, 3, 4), (3, 4, 5)] - - When the window is larger than the iterable, *fillvalue* is used in place - of missing values: - - >>> list(windowed([1, 2, 3], 4)) - [(1, 2, 3, None)] - - Each window will advance in increments of *step*: - - >>> list(windowed([1, 2, 3, 4, 5, 6], 3, fillvalue='!', step=2)) - [(1, 2, 3), (3, 4, 5), (5, 6, '!')] - - To slide into the iterable's items, use :func:`chain` to add filler items - to the left: - - >>> iterable = [1, 2, 3, 4] - >>> n = 3 - >>> padding = [None] * (n - 1) - >>> list(windowed(chain(padding, iterable), 3)) - [(None, None, 1), (None, 1, 2), (1, 2, 3), (2, 3, 4)] - """ - if n < 0: - raise ValueError('n must be >= 0') - if n == 0: - yield tuple() - return - if step < 1: - raise ValueError('step must be >= 1') - - window = deque(maxlen=n) - i = n - for _ in map(window.append, seq): - i -= 1 - if not i: - i = step - yield tuple(window) - - size = len(window) - if size == 0: - return - elif size < n: - yield tuple(chain(window, repeat(fillvalue, n - size))) - elif 0 < i < min(step, n): - window += (fillvalue,) * i - yield tuple(window) - - -def substrings(iterable): - """Yield all of the substrings of *iterable*. - - >>> [''.join(s) for s in substrings('more')] - ['m', 'o', 'r', 'e', 'mo', 'or', 're', 'mor', 'ore', 'more'] - - Note that non-string iterables can also be subdivided. - - >>> list(substrings([0, 1, 2])) - [(0,), (1,), (2,), (0, 1), (1, 2), (0, 1, 2)] - - """ - # The length-1 substrings - seq = [] - for item in iter(iterable): - seq.append(item) - yield (item,) - seq = tuple(seq) - item_count = len(seq) - - # And the rest - for n in range(2, item_count + 1): - for i in range(item_count - n + 1): - yield seq[i : i + n] - - -def substrings_indexes(seq, reverse=False): - """Yield all substrings and their positions in *seq* - - The items yielded will be a tuple of the form ``(substr, i, j)``, where - ``substr == seq[i:j]``. - - This function only works for iterables that support slicing, such as - ``str`` objects. - - >>> for item in substrings_indexes('more'): - ... print(item) - ('m', 0, 1) - ('o', 1, 2) - ('r', 2, 3) - ('e', 3, 4) - ('mo', 0, 2) - ('or', 1, 3) - ('re', 2, 4) - ('mor', 0, 3) - ('ore', 1, 4) - ('more', 0, 4) - - Set *reverse* to ``True`` to yield the same items in the opposite order. - - - """ - r = range(1, len(seq) + 1) - if reverse: - r = reversed(r) - return ( - (seq[i : i + L], i, i + L) for L in r for i in range(len(seq) - L + 1) - ) - - -class bucket: - """Wrap *iterable* and return an object that buckets it iterable into - child iterables based on a *key* function. - - >>> iterable = ['a1', 'b1', 'c1', 'a2', 'b2', 'c2', 'b3'] - >>> s = bucket(iterable, key=lambda x: x[0]) # Bucket by 1st character - >>> sorted(list(s)) # Get the keys - ['a', 'b', 'c'] - >>> a_iterable = s['a'] - >>> next(a_iterable) - 'a1' - >>> next(a_iterable) - 'a2' - >>> list(s['b']) - ['b1', 'b2', 'b3'] - - The original iterable will be advanced and its items will be cached until - they are used by the child iterables. This may require significant storage. - - By default, attempting to select a bucket to which no items belong will - exhaust the iterable and cache all values. - If you specify a *validator* function, selected buckets will instead be - checked against it. - - >>> from itertools import count - >>> it = count(1, 2) # Infinite sequence of odd numbers - >>> key = lambda x: x % 10 # Bucket by last digit - >>> validator = lambda x: x in {1, 3, 5, 7, 9} # Odd digits only - >>> s = bucket(it, key=key, validator=validator) - >>> 2 in s - False - >>> list(s[2]) - [] - - """ - - def __init__(self, iterable, key, validator=None): - self._it = iter(iterable) - self._key = key - self._cache = defaultdict(deque) - self._validator = validator or (lambda x: True) - - def __contains__(self, value): - if not self._validator(value): - return False - - try: - item = next(self[value]) - except StopIteration: - return False - else: - self._cache[value].appendleft(item) - - return True - - def _get_values(self, value): - """ - Helper to yield items from the parent iterator that match *value*. - Items that don't match are stored in the local cache as they - are encountered. - """ - while True: - # If we've cached some items that match the target value, emit - # the first one and evict it from the cache. - if self._cache[value]: - yield self._cache[value].popleft() - # Otherwise we need to advance the parent iterator to search for - # a matching item, caching the rest. - else: - while True: - try: - item = next(self._it) - except StopIteration: - return - item_value = self._key(item) - if item_value == value: - yield item - break - elif self._validator(item_value): - self._cache[item_value].append(item) - - def __iter__(self): - for item in self._it: - item_value = self._key(item) - if self._validator(item_value): - self._cache[item_value].append(item) - - yield from self._cache.keys() - - def __getitem__(self, value): - if not self._validator(value): - return iter(()) - - return self._get_values(value) - - -def spy(iterable, n=1): - """Return a 2-tuple with a list containing the first *n* elements of - *iterable*, and an iterator with the same items as *iterable*. - This allows you to "look ahead" at the items in the iterable without - advancing it. - - There is one item in the list by default: - - >>> iterable = 'abcdefg' - >>> head, iterable = spy(iterable) - >>> head - ['a'] - >>> list(iterable) - ['a', 'b', 'c', 'd', 'e', 'f', 'g'] - - You may use unpacking to retrieve items instead of lists: - - >>> (head,), iterable = spy('abcdefg') - >>> head - 'a' - >>> (first, second), iterable = spy('abcdefg', 2) - >>> first - 'a' - >>> second - 'b' - - The number of items requested can be larger than the number of items in - the iterable: - - >>> iterable = [1, 2, 3, 4, 5] - >>> head, iterable = spy(iterable, 10) - >>> head - [1, 2, 3, 4, 5] - >>> list(iterable) - [1, 2, 3, 4, 5] - - """ - it = iter(iterable) - head = take(n, it) - - return head.copy(), chain(head, it) - - -def interleave(*iterables): - """Return a new iterable yielding from each iterable in turn, - until the shortest is exhausted. - - >>> list(interleave([1, 2, 3], [4, 5], [6, 7, 8])) - [1, 4, 6, 2, 5, 7] - - For a version that doesn't terminate after the shortest iterable is - exhausted, see :func:`interleave_longest`. - - """ - return chain.from_iterable(zip(*iterables)) - - -def interleave_longest(*iterables): - """Return a new iterable yielding from each iterable in turn, - skipping any that are exhausted. - - >>> list(interleave_longest([1, 2, 3], [4, 5], [6, 7, 8])) - [1, 4, 6, 2, 5, 7, 3, 8] - - This function produces the same output as :func:`roundrobin`, but may - perform better for some inputs (in particular when the number of iterables - is large). - - """ - i = chain.from_iterable(zip_longest(*iterables, fillvalue=_marker)) - return (x for x in i if x is not _marker) - - -def interleave_evenly(iterables, lengths=None): - """ - Interleave multiple iterables so that their elements are evenly distributed - throughout the output sequence. - - >>> iterables = [1, 2, 3, 4, 5], ['a', 'b'] - >>> list(interleave_evenly(iterables)) - [1, 2, 'a', 3, 4, 'b', 5] - - >>> iterables = [[1, 2, 3], [4, 5], [6, 7, 8]] - >>> list(interleave_evenly(iterables)) - [1, 6, 4, 2, 7, 3, 8, 5] - - This function requires iterables of known length. Iterables without - ``__len__()`` can be used by manually specifying lengths with *lengths*: - - >>> from itertools import combinations, repeat - >>> iterables = [combinations(range(4), 2), ['a', 'b', 'c']] - >>> lengths = [4 * (4 - 1) // 2, 3] - >>> list(interleave_evenly(iterables, lengths=lengths)) - [(0, 1), (0, 2), 'a', (0, 3), (1, 2), 'b', (1, 3), (2, 3), 'c'] - - Based on Bresenham's algorithm. - """ - if lengths is None: - try: - lengths = [len(it) for it in iterables] - except TypeError: - raise ValueError( - 'Iterable lengths could not be determined automatically. ' - 'Specify them with the lengths keyword.' - ) - elif len(iterables) != len(lengths): - raise ValueError('Mismatching number of iterables and lengths.') - - dims = len(lengths) - - # sort iterables by length, descending - lengths_permute = sorted( - range(dims), key=lambda i: lengths[i], reverse=True - ) - lengths_desc = [lengths[i] for i in lengths_permute] - iters_desc = [iter(iterables[i]) for i in lengths_permute] - - # the longest iterable is the primary one (Bresenham: the longest - # distance along an axis) - delta_primary, deltas_secondary = lengths_desc[0], lengths_desc[1:] - iter_primary, iters_secondary = iters_desc[0], iters_desc[1:] - errors = [delta_primary // dims] * len(deltas_secondary) - - to_yield = sum(lengths) - while to_yield: - yield next(iter_primary) - to_yield -= 1 - # update errors for each secondary iterable - errors = [e - delta for e, delta in zip(errors, deltas_secondary)] - - # those iterables for which the error is negative are yielded - # ("diagonal step" in Bresenham) - for i, e in enumerate(errors): - if e < 0: - yield next(iters_secondary[i]) - to_yield -= 1 - errors[i] += delta_primary - - -def collapse(iterable, base_type=None, levels=None): - """Flatten an iterable with multiple levels of nesting (e.g., a list of - lists of tuples) into non-iterable types. - - >>> iterable = [(1, 2), ([3, 4], [[5], [6]])] - >>> list(collapse(iterable)) - [1, 2, 3, 4, 5, 6] - - Binary and text strings are not considered iterable and - will not be collapsed. - - To avoid collapsing other types, specify *base_type*: - - >>> iterable = ['ab', ('cd', 'ef'), ['gh', 'ij']] - >>> list(collapse(iterable, base_type=tuple)) - ['ab', ('cd', 'ef'), 'gh', 'ij'] - - Specify *levels* to stop flattening after a certain level: - - >>> iterable = [('a', ['b']), ('c', ['d'])] - >>> list(collapse(iterable)) # Fully flattened - ['a', 'b', 'c', 'd'] - >>> list(collapse(iterable, levels=1)) # Only one level flattened - ['a', ['b'], 'c', ['d']] - - """ - - def walk(node, level): - if ( - ((levels is not None) and (level > levels)) - or isinstance(node, (str, bytes)) - or ((base_type is not None) and isinstance(node, base_type)) - ): - yield node - return - - try: - tree = iter(node) - except TypeError: - yield node - return - else: - for child in tree: - yield from walk(child, level + 1) - - yield from walk(iterable, 0) - - -def side_effect(func, iterable, chunk_size=None, before=None, after=None): - """Invoke *func* on each item in *iterable* (or on each *chunk_size* group - of items) before yielding the item. - - `func` must be a function that takes a single argument. Its return value - will be discarded. - - *before* and *after* are optional functions that take no arguments. They - will be executed before iteration starts and after it ends, respectively. - - `side_effect` can be used for logging, updating progress bars, or anything - that is not functionally "pure." - - Emitting a status message: - - >>> from more_itertools import consume - >>> func = lambda item: print('Received {}'.format(item)) - >>> consume(side_effect(func, range(2))) - Received 0 - Received 1 - - Operating on chunks of items: - - >>> pair_sums = [] - >>> func = lambda chunk: pair_sums.append(sum(chunk)) - >>> list(side_effect(func, [0, 1, 2, 3, 4, 5], 2)) - [0, 1, 2, 3, 4, 5] - >>> list(pair_sums) - [1, 5, 9] - - Writing to a file-like object: - - >>> from io import StringIO - >>> from more_itertools import consume - >>> f = StringIO() - >>> func = lambda x: print(x, file=f) - >>> before = lambda: print(u'HEADER', file=f) - >>> after = f.close - >>> it = [u'a', u'b', u'c'] - >>> consume(side_effect(func, it, before=before, after=after)) - >>> f.closed - True - - """ - try: - if before is not None: - before() - - if chunk_size is None: - for item in iterable: - func(item) - yield item - else: - for chunk in chunked(iterable, chunk_size): - func(chunk) - yield from chunk - finally: - if after is not None: - after() - - -def sliced(seq, n, strict=False): - """Yield slices of length *n* from the sequence *seq*. - - >>> list(sliced((1, 2, 3, 4, 5, 6), 3)) - [(1, 2, 3), (4, 5, 6)] - - By the default, the last yielded slice will have fewer than *n* elements - if the length of *seq* is not divisible by *n*: - - >>> list(sliced((1, 2, 3, 4, 5, 6, 7, 8), 3)) - [(1, 2, 3), (4, 5, 6), (7, 8)] - - If the length of *seq* is not divisible by *n* and *strict* is - ``True``, then ``ValueError`` will be raised before the last - slice is yielded. - - This function will only work for iterables that support slicing. - For non-sliceable iterables, see :func:`chunked`. - - """ - iterator = takewhile(len, (seq[i : i + n] for i in count(0, n))) - if strict: - - def ret(): - for _slice in iterator: - if len(_slice) != n: - raise ValueError("seq is not divisible by n.") - yield _slice - - return iter(ret()) - else: - return iterator - - -def split_at(iterable, pred, maxsplit=-1, keep_separator=False): - """Yield lists of items from *iterable*, where each list is delimited by - an item where callable *pred* returns ``True``. - - >>> list(split_at('abcdcba', lambda x: x == 'b')) - [['a'], ['c', 'd', 'c'], ['a']] - - >>> list(split_at(range(10), lambda n: n % 2 == 1)) - [[0], [2], [4], [6], [8], []] - - At most *maxsplit* splits are done. If *maxsplit* is not specified or -1, - then there is no limit on the number of splits: - - >>> list(split_at(range(10), lambda n: n % 2 == 1, maxsplit=2)) - [[0], [2], [4, 5, 6, 7, 8, 9]] - - By default, the delimiting items are not included in the output. - The include them, set *keep_separator* to ``True``. - - >>> list(split_at('abcdcba', lambda x: x == 'b', keep_separator=True)) - [['a'], ['b'], ['c', 'd', 'c'], ['b'], ['a']] - - """ - if maxsplit == 0: - yield list(iterable) - return - - buf = [] - it = iter(iterable) - for item in it: - if pred(item): - yield buf - if keep_separator: - yield [item] - if maxsplit == 1: - yield list(it) - return - buf = [] - maxsplit -= 1 - else: - buf.append(item) - yield buf - - -def split_before(iterable, pred, maxsplit=-1): - """Yield lists of items from *iterable*, where each list ends just before - an item for which callable *pred* returns ``True``: - - >>> list(split_before('OneTwo', lambda s: s.isupper())) - [['O', 'n', 'e'], ['T', 'w', 'o']] - - >>> list(split_before(range(10), lambda n: n % 3 == 0)) - [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]] - - At most *maxsplit* splits are done. If *maxsplit* is not specified or -1, - then there is no limit on the number of splits: - - >>> list(split_before(range(10), lambda n: n % 3 == 0, maxsplit=2)) - [[0, 1, 2], [3, 4, 5], [6, 7, 8, 9]] - """ - if maxsplit == 0: - yield list(iterable) - return - - buf = [] - it = iter(iterable) - for item in it: - if pred(item) and buf: - yield buf - if maxsplit == 1: - yield [item] + list(it) - return - buf = [] - maxsplit -= 1 - buf.append(item) - if buf: - yield buf - - -def split_after(iterable, pred, maxsplit=-1): - """Yield lists of items from *iterable*, where each list ends with an - item where callable *pred* returns ``True``: - - >>> list(split_after('one1two2', lambda s: s.isdigit())) - [['o', 'n', 'e', '1'], ['t', 'w', 'o', '2']] - - >>> list(split_after(range(10), lambda n: n % 3 == 0)) - [[0], [1, 2, 3], [4, 5, 6], [7, 8, 9]] - - At most *maxsplit* splits are done. If *maxsplit* is not specified or -1, - then there is no limit on the number of splits: - - >>> list(split_after(range(10), lambda n: n % 3 == 0, maxsplit=2)) - [[0], [1, 2, 3], [4, 5, 6, 7, 8, 9]] - - """ - if maxsplit == 0: - yield list(iterable) - return - - buf = [] - it = iter(iterable) - for item in it: - buf.append(item) - if pred(item) and buf: - yield buf - if maxsplit == 1: - yield list(it) - return - buf = [] - maxsplit -= 1 - if buf: - yield buf - - -def split_when(iterable, pred, maxsplit=-1): - """Split *iterable* into pieces based on the output of *pred*. - *pred* should be a function that takes successive pairs of items and - returns ``True`` if the iterable should be split in between them. - - For example, to find runs of increasing numbers, split the iterable when - element ``i`` is larger than element ``i + 1``: - - >>> list(split_when([1, 2, 3, 3, 2, 5, 2, 4, 2], lambda x, y: x > y)) - [[1, 2, 3, 3], [2, 5], [2, 4], [2]] - - At most *maxsplit* splits are done. If *maxsplit* is not specified or -1, - then there is no limit on the number of splits: - - >>> list(split_when([1, 2, 3, 3, 2, 5, 2, 4, 2], - ... lambda x, y: x > y, maxsplit=2)) - [[1, 2, 3, 3], [2, 5], [2, 4, 2]] - - """ - if maxsplit == 0: - yield list(iterable) - return - - it = iter(iterable) - try: - cur_item = next(it) - except StopIteration: - return - - buf = [cur_item] - for next_item in it: - if pred(cur_item, next_item): - yield buf - if maxsplit == 1: - yield [next_item] + list(it) - return - buf = [] - maxsplit -= 1 - - buf.append(next_item) - cur_item = next_item - - yield buf - - -def split_into(iterable, sizes): - """Yield a list of sequential items from *iterable* of length 'n' for each - integer 'n' in *sizes*. - - >>> list(split_into([1,2,3,4,5,6], [1,2,3])) - [[1], [2, 3], [4, 5, 6]] - - If the sum of *sizes* is smaller than the length of *iterable*, then the - remaining items of *iterable* will not be returned. - - >>> list(split_into([1,2,3,4,5,6], [2,3])) - [[1, 2], [3, 4, 5]] - - If the sum of *sizes* is larger than the length of *iterable*, fewer items - will be returned in the iteration that overruns *iterable* and further - lists will be empty: - - >>> list(split_into([1,2,3,4], [1,2,3,4])) - [[1], [2, 3], [4], []] - - When a ``None`` object is encountered in *sizes*, the returned list will - contain items up to the end of *iterable* the same way that itertools.slice - does: - - >>> list(split_into([1,2,3,4,5,6,7,8,9,0], [2,3,None])) - [[1, 2], [3, 4, 5], [6, 7, 8, 9, 0]] - - :func:`split_into` can be useful for grouping a series of items where the - sizes of the groups are not uniform. An example would be where in a row - from a table, multiple columns represent elements of the same feature - (e.g. a point represented by x,y,z) but, the format is not the same for - all columns. - """ - # convert the iterable argument into an iterator so its contents can - # be consumed by islice in case it is a generator - it = iter(iterable) - - for size in sizes: - if size is None: - yield list(it) - return - else: - yield list(islice(it, size)) - - -def padded(iterable, fillvalue=None, n=None, next_multiple=False): - """Yield the elements from *iterable*, followed by *fillvalue*, such that - at least *n* items are emitted. - - >>> list(padded([1, 2, 3], '?', 5)) - [1, 2, 3, '?', '?'] - - If *next_multiple* is ``True``, *fillvalue* will be emitted until the - number of items emitted is a multiple of *n*:: - - >>> list(padded([1, 2, 3, 4], n=3, next_multiple=True)) - [1, 2, 3, 4, None, None] - - If *n* is ``None``, *fillvalue* will be emitted indefinitely. - - """ - it = iter(iterable) - if n is None: - yield from chain(it, repeat(fillvalue)) - elif n < 1: - raise ValueError('n must be at least 1') - else: - item_count = 0 - for item in it: - yield item - item_count += 1 - - remaining = (n - item_count) % n if next_multiple else n - item_count - for _ in range(remaining): - yield fillvalue - - -def repeat_each(iterable, n=2): - """Repeat each element in *iterable* *n* times. - - >>> list(repeat_each('ABC', 3)) - ['A', 'A', 'A', 'B', 'B', 'B', 'C', 'C', 'C'] - """ - return chain.from_iterable(map(repeat, iterable, repeat(n))) - - -def repeat_last(iterable, default=None): - """After the *iterable* is exhausted, keep yielding its last element. - - >>> list(islice(repeat_last(range(3)), 5)) - [0, 1, 2, 2, 2] - - If the iterable is empty, yield *default* forever:: - - >>> list(islice(repeat_last(range(0), 42), 5)) - [42, 42, 42, 42, 42] - - """ - item = _marker - for item in iterable: - yield item - final = default if item is _marker else item - yield from repeat(final) - - -def distribute(n, iterable): - """Distribute the items from *iterable* among *n* smaller iterables. - - >>> group_1, group_2 = distribute(2, [1, 2, 3, 4, 5, 6]) - >>> list(group_1) - [1, 3, 5] - >>> list(group_2) - [2, 4, 6] - - If the length of *iterable* is not evenly divisible by *n*, then the - length of the returned iterables will not be identical: - - >>> children = distribute(3, [1, 2, 3, 4, 5, 6, 7]) - >>> [list(c) for c in children] - [[1, 4, 7], [2, 5], [3, 6]] - - If the length of *iterable* is smaller than *n*, then the last returned - iterables will be empty: - - >>> children = distribute(5, [1, 2, 3]) - >>> [list(c) for c in children] - [[1], [2], [3], [], []] - - This function uses :func:`itertools.tee` and may require significant - storage. If you need the order items in the smaller iterables to match the - original iterable, see :func:`divide`. - - """ - if n < 1: - raise ValueError('n must be at least 1') - - children = tee(iterable, n) - return [islice(it, index, None, n) for index, it in enumerate(children)] - - -def stagger(iterable, offsets=(-1, 0, 1), longest=False, fillvalue=None): - """Yield tuples whose elements are offset from *iterable*. - The amount by which the `i`-th item in each tuple is offset is given by - the `i`-th item in *offsets*. - - >>> list(stagger([0, 1, 2, 3])) - [(None, 0, 1), (0, 1, 2), (1, 2, 3)] - >>> list(stagger(range(8), offsets=(0, 2, 4))) - [(0, 2, 4), (1, 3, 5), (2, 4, 6), (3, 5, 7)] - - By default, the sequence will end when the final element of a tuple is the - last item in the iterable. To continue until the first element of a tuple - is the last item in the iterable, set *longest* to ``True``:: - - >>> list(stagger([0, 1, 2, 3], longest=True)) - [(None, 0, 1), (0, 1, 2), (1, 2, 3), (2, 3, None), (3, None, None)] - - By default, ``None`` will be used to replace offsets beyond the end of the - sequence. Specify *fillvalue* to use some other value. - - """ - children = tee(iterable, len(offsets)) - - return zip_offset( - *children, offsets=offsets, longest=longest, fillvalue=fillvalue - ) - - -def zip_equal(*iterables): - """``zip`` the input *iterables* together, but raise - ``UnequalIterablesError`` if they aren't all the same length. - - >>> it_1 = range(3) - >>> it_2 = iter('abc') - >>> list(zip_equal(it_1, it_2)) - [(0, 'a'), (1, 'b'), (2, 'c')] - - >>> it_1 = range(3) - >>> it_2 = iter('abcd') - >>> list(zip_equal(it_1, it_2)) # doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ... - more_itertools.more.UnequalIterablesError: Iterables have different - lengths - - """ - if hexversion >= 0x30A00A6: - warnings.warn( - ( - 'zip_equal will be removed in a future version of ' - 'more-itertools. Use the builtin zip function with ' - 'strict=True instead.' - ), - DeprecationWarning, - ) - - return _zip_equal(*iterables) - - -def zip_offset(*iterables, offsets, longest=False, fillvalue=None): - """``zip`` the input *iterables* together, but offset the `i`-th iterable - by the `i`-th item in *offsets*. - - >>> list(zip_offset('0123', 'abcdef', offsets=(0, 1))) - [('0', 'b'), ('1', 'c'), ('2', 'd'), ('3', 'e')] - - This can be used as a lightweight alternative to SciPy or pandas to analyze - data sets in which some series have a lead or lag relationship. - - By default, the sequence will end when the shortest iterable is exhausted. - To continue until the longest iterable is exhausted, set *longest* to - ``True``. - - >>> list(zip_offset('0123', 'abcdef', offsets=(0, 1), longest=True)) - [('0', 'b'), ('1', 'c'), ('2', 'd'), ('3', 'e'), (None, 'f')] - - By default, ``None`` will be used to replace offsets beyond the end of the - sequence. Specify *fillvalue* to use some other value. - - """ - if len(iterables) != len(offsets): - raise ValueError("Number of iterables and offsets didn't match") - - staggered = [] - for it, n in zip(iterables, offsets): - if n < 0: - staggered.append(chain(repeat(fillvalue, -n), it)) - elif n > 0: - staggered.append(islice(it, n, None)) - else: - staggered.append(it) - - if longest: - return zip_longest(*staggered, fillvalue=fillvalue) - - return zip(*staggered) - - -def sort_together(iterables, key_list=(0,), key=None, reverse=False): - """Return the input iterables sorted together, with *key_list* as the - priority for sorting. All iterables are trimmed to the length of the - shortest one. - - This can be used like the sorting function in a spreadsheet. If each - iterable represents a column of data, the key list determines which - columns are used for sorting. - - By default, all iterables are sorted using the ``0``-th iterable:: - - >>> iterables = [(4, 3, 2, 1), ('a', 'b', 'c', 'd')] - >>> sort_together(iterables) - [(1, 2, 3, 4), ('d', 'c', 'b', 'a')] - - Set a different key list to sort according to another iterable. - Specifying multiple keys dictates how ties are broken:: - - >>> iterables = [(3, 1, 2), (0, 1, 0), ('c', 'b', 'a')] - >>> sort_together(iterables, key_list=(1, 2)) - [(2, 3, 1), (0, 0, 1), ('a', 'c', 'b')] - - To sort by a function of the elements of the iterable, pass a *key* - function. Its arguments are the elements of the iterables corresponding to - the key list:: - - >>> names = ('a', 'b', 'c') - >>> lengths = (1, 2, 3) - >>> widths = (5, 2, 1) - >>> def area(length, width): - ... return length * width - >>> sort_together([names, lengths, widths], key_list=(1, 2), key=area) - [('c', 'b', 'a'), (3, 2, 1), (1, 2, 5)] - - Set *reverse* to ``True`` to sort in descending order. - - >>> sort_together([(1, 2, 3), ('c', 'b', 'a')], reverse=True) - [(3, 2, 1), ('a', 'b', 'c')] - - """ - if key is None: - # if there is no key function, the key argument to sorted is an - # itemgetter - key_argument = itemgetter(*key_list) - else: - # if there is a key function, call it with the items at the offsets - # specified by the key function as arguments - key_list = list(key_list) - if len(key_list) == 1: - # if key_list contains a single item, pass the item at that offset - # as the only argument to the key function - key_offset = key_list[0] - key_argument = lambda zipped_items: key(zipped_items[key_offset]) - else: - # if key_list contains multiple items, use itemgetter to return a - # tuple of items, which we pass as *args to the key function - get_key_items = itemgetter(*key_list) - key_argument = lambda zipped_items: key( - *get_key_items(zipped_items) - ) - - return list( - zip(*sorted(zip(*iterables), key=key_argument, reverse=reverse)) - ) - - -def unzip(iterable): - """The inverse of :func:`zip`, this function disaggregates the elements - of the zipped *iterable*. - - The ``i``-th iterable contains the ``i``-th element from each element - of the zipped iterable. The first element is used to determine the - length of the remaining elements. - - >>> iterable = [('a', 1), ('b', 2), ('c', 3), ('d', 4)] - >>> letters, numbers = unzip(iterable) - >>> list(letters) - ['a', 'b', 'c', 'd'] - >>> list(numbers) - [1, 2, 3, 4] - - This is similar to using ``zip(*iterable)``, but it avoids reading - *iterable* into memory. Note, however, that this function uses - :func:`itertools.tee` and thus may require significant storage. - - """ - head, iterable = spy(iter(iterable)) - if not head: - # empty iterable, e.g. zip([], [], []) - return () - # spy returns a one-length iterable as head - head = head[0] - iterables = tee(iterable, len(head)) - - def itemgetter(i): - def getter(obj): - try: - return obj[i] - except IndexError: - # basically if we have an iterable like - # iter([(1, 2, 3), (4, 5), (6,)]) - # the second unzipped iterable would fail at the third tuple - # since it would try to access tup[1] - # same with the third unzipped iterable and the second tuple - # to support these "improperly zipped" iterables, - # we create a custom itemgetter - # which just stops the unzipped iterables - # at first length mismatch - raise StopIteration - - return getter - - return tuple(map(itemgetter(i), it) for i, it in enumerate(iterables)) - - -def divide(n, iterable): - """Divide the elements from *iterable* into *n* parts, maintaining - order. - - >>> group_1, group_2 = divide(2, [1, 2, 3, 4, 5, 6]) - >>> list(group_1) - [1, 2, 3] - >>> list(group_2) - [4, 5, 6] - - If the length of *iterable* is not evenly divisible by *n*, then the - length of the returned iterables will not be identical: - - >>> children = divide(3, [1, 2, 3, 4, 5, 6, 7]) - >>> [list(c) for c in children] - [[1, 2, 3], [4, 5], [6, 7]] - - If the length of the iterable is smaller than n, then the last returned - iterables will be empty: - - >>> children = divide(5, [1, 2, 3]) - >>> [list(c) for c in children] - [[1], [2], [3], [], []] - - This function will exhaust the iterable before returning and may require - significant storage. If order is not important, see :func:`distribute`, - which does not first pull the iterable into memory. - - """ - if n < 1: - raise ValueError('n must be at least 1') - - try: - iterable[:0] - except TypeError: - seq = tuple(iterable) - else: - seq = iterable - - q, r = divmod(len(seq), n) - - ret = [] - stop = 0 - for i in range(1, n + 1): - start = stop - stop += q + 1 if i <= r else q - ret.append(iter(seq[start:stop])) - - return ret - - -def always_iterable(obj, base_type=(str, bytes)): - """If *obj* is iterable, return an iterator over its items:: - - >>> obj = (1, 2, 3) - >>> list(always_iterable(obj)) - [1, 2, 3] - - If *obj* is not iterable, return a one-item iterable containing *obj*:: - - >>> obj = 1 - >>> list(always_iterable(obj)) - [1] - - If *obj* is ``None``, return an empty iterable: - - >>> obj = None - >>> list(always_iterable(None)) - [] - - By default, binary and text strings are not considered iterable:: - - >>> obj = 'foo' - >>> list(always_iterable(obj)) - ['foo'] - - If *base_type* is set, objects for which ``isinstance(obj, base_type)`` - returns ``True`` won't be considered iterable. - - >>> obj = {'a': 1} - >>> list(always_iterable(obj)) # Iterate over the dict's keys - ['a'] - >>> list(always_iterable(obj, base_type=dict)) # Treat dicts as a unit - [{'a': 1}] - - Set *base_type* to ``None`` to avoid any special handling and treat objects - Python considers iterable as iterable: - - >>> obj = 'foo' - >>> list(always_iterable(obj, base_type=None)) - ['f', 'o', 'o'] - """ - if obj is None: - return iter(()) - - if (base_type is not None) and isinstance(obj, base_type): - return iter((obj,)) - - try: - return iter(obj) - except TypeError: - return iter((obj,)) - - -def adjacent(predicate, iterable, distance=1): - """Return an iterable over `(bool, item)` tuples where the `item` is - drawn from *iterable* and the `bool` indicates whether - that item satisfies the *predicate* or is adjacent to an item that does. - - For example, to find whether items are adjacent to a ``3``:: - - >>> list(adjacent(lambda x: x == 3, range(6))) - [(False, 0), (False, 1), (True, 2), (True, 3), (True, 4), (False, 5)] - - Set *distance* to change what counts as adjacent. For example, to find - whether items are two places away from a ``3``: - - >>> list(adjacent(lambda x: x == 3, range(6), distance=2)) - [(False, 0), (True, 1), (True, 2), (True, 3), (True, 4), (True, 5)] - - This is useful for contextualizing the results of a search function. - For example, a code comparison tool might want to identify lines that - have changed, but also surrounding lines to give the viewer of the diff - context. - - The predicate function will only be called once for each item in the - iterable. - - See also :func:`groupby_transform`, which can be used with this function - to group ranges of items with the same `bool` value. - - """ - # Allow distance=0 mainly for testing that it reproduces results with map() - if distance < 0: - raise ValueError('distance must be at least 0') - - i1, i2 = tee(iterable) - padding = [False] * distance - selected = chain(padding, map(predicate, i1), padding) - adjacent_to_selected = map(any, windowed(selected, 2 * distance + 1)) - return zip(adjacent_to_selected, i2) - - -def groupby_transform(iterable, keyfunc=None, valuefunc=None, reducefunc=None): - """An extension of :func:`itertools.groupby` that can apply transformations - to the grouped data. - - * *keyfunc* is a function computing a key value for each item in *iterable* - * *valuefunc* is a function that transforms the individual items from - *iterable* after grouping - * *reducefunc* is a function that transforms each group of items - - >>> iterable = 'aAAbBBcCC' - >>> keyfunc = lambda k: k.upper() - >>> valuefunc = lambda v: v.lower() - >>> reducefunc = lambda g: ''.join(g) - >>> list(groupby_transform(iterable, keyfunc, valuefunc, reducefunc)) - [('A', 'aaa'), ('B', 'bbb'), ('C', 'ccc')] - - Each optional argument defaults to an identity function if not specified. - - :func:`groupby_transform` is useful when grouping elements of an iterable - using a separate iterable as the key. To do this, :func:`zip` the iterables - and pass a *keyfunc* that extracts the first element and a *valuefunc* - that extracts the second element:: - - >>> from operator import itemgetter - >>> keys = [0, 0, 1, 1, 1, 2, 2, 2, 3] - >>> values = 'abcdefghi' - >>> iterable = zip(keys, values) - >>> grouper = groupby_transform(iterable, itemgetter(0), itemgetter(1)) - >>> [(k, ''.join(g)) for k, g in grouper] - [(0, 'ab'), (1, 'cde'), (2, 'fgh'), (3, 'i')] - - Note that the order of items in the iterable is significant. - Only adjacent items are grouped together, so if you don't want any - duplicate groups, you should sort the iterable by the key function. - - """ - ret = groupby(iterable, keyfunc) - if valuefunc: - ret = ((k, map(valuefunc, g)) for k, g in ret) - if reducefunc: - ret = ((k, reducefunc(g)) for k, g in ret) - - return ret - - -class numeric_range(abc.Sequence, abc.Hashable): - """An extension of the built-in ``range()`` function whose arguments can - be any orderable numeric type. - - With only *stop* specified, *start* defaults to ``0`` and *step* - defaults to ``1``. The output items will match the type of *stop*: - - >>> list(numeric_range(3.5)) - [0.0, 1.0, 2.0, 3.0] - - With only *start* and *stop* specified, *step* defaults to ``1``. The - output items will match the type of *start*: - - >>> from decimal import Decimal - >>> start = Decimal('2.1') - >>> stop = Decimal('5.1') - >>> list(numeric_range(start, stop)) - [Decimal('2.1'), Decimal('3.1'), Decimal('4.1')] - - With *start*, *stop*, and *step* specified the output items will match - the type of ``start + step``: - - >>> from fractions import Fraction - >>> start = Fraction(1, 2) # Start at 1/2 - >>> stop = Fraction(5, 2) # End at 5/2 - >>> step = Fraction(1, 2) # Count by 1/2 - >>> list(numeric_range(start, stop, step)) - [Fraction(1, 2), Fraction(1, 1), Fraction(3, 2), Fraction(2, 1)] - - If *step* is zero, ``ValueError`` is raised. Negative steps are supported: - - >>> list(numeric_range(3, -1, -1.0)) - [3.0, 2.0, 1.0, 0.0] - - Be aware of the limitations of floating point numbers; the representation - of the yielded numbers may be surprising. - - ``datetime.datetime`` objects can be used for *start* and *stop*, if *step* - is a ``datetime.timedelta`` object: - - >>> import datetime - >>> start = datetime.datetime(2019, 1, 1) - >>> stop = datetime.datetime(2019, 1, 3) - >>> step = datetime.timedelta(days=1) - >>> items = iter(numeric_range(start, stop, step)) - >>> next(items) - datetime.datetime(2019, 1, 1, 0, 0) - >>> next(items) - datetime.datetime(2019, 1, 2, 0, 0) - - """ - - _EMPTY_HASH = hash(range(0, 0)) - - def __init__(self, *args): - argc = len(args) - if argc == 1: - (self._stop,) = args - self._start = type(self._stop)(0) - self._step = type(self._stop - self._start)(1) - elif argc == 2: - self._start, self._stop = args - self._step = type(self._stop - self._start)(1) - elif argc == 3: - self._start, self._stop, self._step = args - elif argc == 0: - raise TypeError( - 'numeric_range expected at least ' - '1 argument, got {}'.format(argc) - ) - else: - raise TypeError( - 'numeric_range expected at most ' - '3 arguments, got {}'.format(argc) - ) - - self._zero = type(self._step)(0) - if self._step == self._zero: - raise ValueError('numeric_range() arg 3 must not be zero') - self._growing = self._step > self._zero - self._init_len() - - def __bool__(self): - if self._growing: - return self._start < self._stop - else: - return self._start > self._stop - - def __contains__(self, elem): - if self._growing: - if self._start <= elem < self._stop: - return (elem - self._start) % self._step == self._zero - else: - if self._start >= elem > self._stop: - return (self._start - elem) % (-self._step) == self._zero - - return False - - def __eq__(self, other): - if isinstance(other, numeric_range): - empty_self = not bool(self) - empty_other = not bool(other) - if empty_self or empty_other: - return empty_self and empty_other # True if both empty - else: - return ( - self._start == other._start - and self._step == other._step - and self._get_by_index(-1) == other._get_by_index(-1) - ) - else: - return False - - def __getitem__(self, key): - if isinstance(key, int): - return self._get_by_index(key) - elif isinstance(key, slice): - step = self._step if key.step is None else key.step * self._step - - if key.start is None or key.start <= -self._len: - start = self._start - elif key.start >= self._len: - start = self._stop - else: # -self._len < key.start < self._len - start = self._get_by_index(key.start) - - if key.stop is None or key.stop >= self._len: - stop = self._stop - elif key.stop <= -self._len: - stop = self._start - else: # -self._len < key.stop < self._len - stop = self._get_by_index(key.stop) - - return numeric_range(start, stop, step) - else: - raise TypeError( - 'numeric range indices must be ' - 'integers or slices, not {}'.format(type(key).__name__) - ) - - def __hash__(self): - if self: - return hash((self._start, self._get_by_index(-1), self._step)) - else: - return self._EMPTY_HASH - - def __iter__(self): - values = (self._start + (n * self._step) for n in count()) - if self._growing: - return takewhile(partial(gt, self._stop), values) - else: - return takewhile(partial(lt, self._stop), values) - - def __len__(self): - return self._len - - def _init_len(self): - if self._growing: - start = self._start - stop = self._stop - step = self._step - else: - start = self._stop - stop = self._start - step = -self._step - distance = stop - start - if distance <= self._zero: - self._len = 0 - else: # distance > 0 and step > 0: regular euclidean division - q, r = divmod(distance, step) - self._len = int(q) + int(r != self._zero) - - def __reduce__(self): - return numeric_range, (self._start, self._stop, self._step) - - def __repr__(self): - if self._step == 1: - return "numeric_range({}, {})".format( - repr(self._start), repr(self._stop) - ) - else: - return "numeric_range({}, {}, {})".format( - repr(self._start), repr(self._stop), repr(self._step) - ) - - def __reversed__(self): - return iter( - numeric_range( - self._get_by_index(-1), self._start - self._step, -self._step - ) - ) - - def count(self, value): - return int(value in self) - - def index(self, value): - if self._growing: - if self._start <= value < self._stop: - q, r = divmod(value - self._start, self._step) - if r == self._zero: - return int(q) - else: - if self._start >= value > self._stop: - q, r = divmod(self._start - value, -self._step) - if r == self._zero: - return int(q) - - raise ValueError("{} is not in numeric range".format(value)) - - def _get_by_index(self, i): - if i < 0: - i += self._len - if i < 0 or i >= self._len: - raise IndexError("numeric range object index out of range") - return self._start + i * self._step - - -def count_cycle(iterable, n=None): - """Cycle through the items from *iterable* up to *n* times, yielding - the number of completed cycles along with each item. If *n* is omitted the - process repeats indefinitely. - - >>> list(count_cycle('AB', 3)) - [(0, 'A'), (0, 'B'), (1, 'A'), (1, 'B'), (2, 'A'), (2, 'B')] - - """ - iterable = tuple(iterable) - if not iterable: - return iter(()) - counter = count() if n is None else range(n) - return ((i, item) for i in counter for item in iterable) - - -def mark_ends(iterable): - """Yield 3-tuples of the form ``(is_first, is_last, item)``. - - >>> list(mark_ends('ABC')) - [(True, False, 'A'), (False, False, 'B'), (False, True, 'C')] - - Use this when looping over an iterable to take special action on its first - and/or last items: - - >>> iterable = ['Header', 100, 200, 'Footer'] - >>> total = 0 - >>> for is_first, is_last, item in mark_ends(iterable): - ... if is_first: - ... continue # Skip the header - ... if is_last: - ... continue # Skip the footer - ... total += item - >>> print(total) - 300 - """ - it = iter(iterable) - - try: - b = next(it) - except StopIteration: - return - - try: - for i in count(): - a = b - b = next(it) - yield i == 0, False, a - - except StopIteration: - yield i == 0, True, a - - -def locate(iterable, pred=bool, window_size=None): - """Yield the index of each item in *iterable* for which *pred* returns - ``True``. - - *pred* defaults to :func:`bool`, which will select truthy items: - - >>> list(locate([0, 1, 1, 0, 1, 0, 0])) - [1, 2, 4] - - Set *pred* to a custom function to, e.g., find the indexes for a particular - item. - - >>> list(locate(['a', 'b', 'c', 'b'], lambda x: x == 'b')) - [1, 3] - - If *window_size* is given, then the *pred* function will be called with - that many items. This enables searching for sub-sequences: - - >>> iterable = [0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3] - >>> pred = lambda *args: args == (1, 2, 3) - >>> list(locate(iterable, pred=pred, window_size=3)) - [1, 5, 9] - - Use with :func:`seekable` to find indexes and then retrieve the associated - items: - - >>> from itertools import count - >>> from more_itertools import seekable - >>> source = (3 * n + 1 if (n % 2) else n // 2 for n in count()) - >>> it = seekable(source) - >>> pred = lambda x: x > 100 - >>> indexes = locate(it, pred=pred) - >>> i = next(indexes) - >>> it.seek(i) - >>> next(it) - 106 - - """ - if window_size is None: - return compress(count(), map(pred, iterable)) - - if window_size < 1: - raise ValueError('window size must be at least 1') - - it = windowed(iterable, window_size, fillvalue=_marker) - return compress(count(), starmap(pred, it)) - - -def longest_common_prefix(iterables): - """Yield elements of the longest common prefix amongst given *iterables*. - - >>> ''.join(longest_common_prefix(['abcd', 'abc', 'abf'])) - 'ab' - - """ - return (c[0] for c in takewhile(all_equal, zip(*iterables))) - - -def lstrip(iterable, pred): - """Yield the items from *iterable*, but strip any from the beginning - for which *pred* returns ``True``. - - For example, to remove a set of items from the start of an iterable: - - >>> iterable = (None, False, None, 1, 2, None, 3, False, None) - >>> pred = lambda x: x in {None, False, ''} - >>> list(lstrip(iterable, pred)) - [1, 2, None, 3, False, None] - - This function is analogous to to :func:`str.lstrip`, and is essentially - an wrapper for :func:`itertools.dropwhile`. - - """ - return dropwhile(pred, iterable) - - -def rstrip(iterable, pred): - """Yield the items from *iterable*, but strip any from the end - for which *pred* returns ``True``. - - For example, to remove a set of items from the end of an iterable: - - >>> iterable = (None, False, None, 1, 2, None, 3, False, None) - >>> pred = lambda x: x in {None, False, ''} - >>> list(rstrip(iterable, pred)) - [None, False, None, 1, 2, None, 3] - - This function is analogous to :func:`str.rstrip`. - - """ - cache = [] - cache_append = cache.append - cache_clear = cache.clear - for x in iterable: - if pred(x): - cache_append(x) - else: - yield from cache - cache_clear() - yield x - - -def strip(iterable, pred): - """Yield the items from *iterable*, but strip any from the - beginning and end for which *pred* returns ``True``. - - For example, to remove a set of items from both ends of an iterable: - - >>> iterable = (None, False, None, 1, 2, None, 3, False, None) - >>> pred = lambda x: x in {None, False, ''} - >>> list(strip(iterable, pred)) - [1, 2, None, 3] - - This function is analogous to :func:`str.strip`. - - """ - return rstrip(lstrip(iterable, pred), pred) - - -class islice_extended: - """An extension of :func:`itertools.islice` that supports negative values - for *stop*, *start*, and *step*. - - >>> iterable = iter('abcdefgh') - >>> list(islice_extended(iterable, -4, -1)) - ['e', 'f', 'g'] - - Slices with negative values require some caching of *iterable*, but this - function takes care to minimize the amount of memory required. - - For example, you can use a negative step with an infinite iterator: - - >>> from itertools import count - >>> list(islice_extended(count(), 110, 99, -2)) - [110, 108, 106, 104, 102, 100] - - You can also use slice notation directly: - - >>> iterable = map(str, count()) - >>> it = islice_extended(iterable)[10:20:2] - >>> list(it) - ['10', '12', '14', '16', '18'] - - """ - - def __init__(self, iterable, *args): - it = iter(iterable) - if args: - self._iterable = _islice_helper(it, slice(*args)) - else: - self._iterable = it - - def __iter__(self): - return self - - def __next__(self): - return next(self._iterable) - - def __getitem__(self, key): - if isinstance(key, slice): - return islice_extended(_islice_helper(self._iterable, key)) - - raise TypeError('islice_extended.__getitem__ argument must be a slice') - - -def _islice_helper(it, s): - start = s.start - stop = s.stop - if s.step == 0: - raise ValueError('step argument must be a non-zero integer or None.') - step = s.step or 1 - - if step > 0: - start = 0 if (start is None) else start - - if start < 0: - # Consume all but the last -start items - cache = deque(enumerate(it, 1), maxlen=-start) - len_iter = cache[-1][0] if cache else 0 - - # Adjust start to be positive - i = max(len_iter + start, 0) - - # Adjust stop to be positive - if stop is None: - j = len_iter - elif stop >= 0: - j = min(stop, len_iter) - else: - j = max(len_iter + stop, 0) - - # Slice the cache - n = j - i - if n <= 0: - return - - for index, item in islice(cache, 0, n, step): - yield item - elif (stop is not None) and (stop < 0): - # Advance to the start position - next(islice(it, start, start), None) - - # When stop is negative, we have to carry -stop items while - # iterating - cache = deque(islice(it, -stop), maxlen=-stop) - - for index, item in enumerate(it): - cached_item = cache.popleft() - if index % step == 0: - yield cached_item - cache.append(item) - else: - # When both start and stop are positive we have the normal case - yield from islice(it, start, stop, step) - else: - start = -1 if (start is None) else start - - if (stop is not None) and (stop < 0): - # Consume all but the last items - n = -stop - 1 - cache = deque(enumerate(it, 1), maxlen=n) - len_iter = cache[-1][0] if cache else 0 - - # If start and stop are both negative they are comparable and - # we can just slice. Otherwise we can adjust start to be negative - # and then slice. - if start < 0: - i, j = start, stop - else: - i, j = min(start - len_iter, -1), None - - for index, item in list(cache)[i:j:step]: - yield item - else: - # Advance to the stop position - if stop is not None: - m = stop + 1 - next(islice(it, m, m), None) - - # stop is positive, so if start is negative they are not comparable - # and we need the rest of the items. - if start < 0: - i = start - n = None - # stop is None and start is positive, so we just need items up to - # the start index. - elif stop is None: - i = None - n = start + 1 - # Both stop and start are positive, so they are comparable. - else: - i = None - n = start - stop - if n <= 0: - return - - cache = list(islice(it, n)) - - yield from cache[i::step] - - -def always_reversible(iterable): - """An extension of :func:`reversed` that supports all iterables, not - just those which implement the ``Reversible`` or ``Sequence`` protocols. - - >>> print(*always_reversible(x for x in range(3))) - 2 1 0 - - If the iterable is already reversible, this function returns the - result of :func:`reversed()`. If the iterable is not reversible, - this function will cache the remaining items in the iterable and - yield them in reverse order, which may require significant storage. - """ - try: - return reversed(iterable) - except TypeError: - return reversed(list(iterable)) - - -def consecutive_groups(iterable, ordering=lambda x: x): - """Yield groups of consecutive items using :func:`itertools.groupby`. - The *ordering* function determines whether two items are adjacent by - returning their position. - - By default, the ordering function is the identity function. This is - suitable for finding runs of numbers: - - >>> iterable = [1, 10, 11, 12, 20, 30, 31, 32, 33, 40] - >>> for group in consecutive_groups(iterable): - ... print(list(group)) - [1] - [10, 11, 12] - [20] - [30, 31, 32, 33] - [40] - - For finding runs of adjacent letters, try using the :meth:`index` method - of a string of letters: - - >>> from string import ascii_lowercase - >>> iterable = 'abcdfgilmnop' - >>> ordering = ascii_lowercase.index - >>> for group in consecutive_groups(iterable, ordering): - ... print(list(group)) - ['a', 'b', 'c', 'd'] - ['f', 'g'] - ['i'] - ['l', 'm', 'n', 'o', 'p'] - - Each group of consecutive items is an iterator that shares it source with - *iterable*. When an an output group is advanced, the previous group is - no longer available unless its elements are copied (e.g., into a ``list``). - - >>> iterable = [1, 2, 11, 12, 21, 22] - >>> saved_groups = [] - >>> for group in consecutive_groups(iterable): - ... saved_groups.append(list(group)) # Copy group elements - >>> saved_groups - [[1, 2], [11, 12], [21, 22]] - - """ - for k, g in groupby( - enumerate(iterable), key=lambda x: x[0] - ordering(x[1]) - ): - yield map(itemgetter(1), g) - - -def difference(iterable, func=sub, *, initial=None): - """This function is the inverse of :func:`itertools.accumulate`. By default - it will compute the first difference of *iterable* using - :func:`operator.sub`: - - >>> from itertools import accumulate - >>> iterable = accumulate([0, 1, 2, 3, 4]) # produces 0, 1, 3, 6, 10 - >>> list(difference(iterable)) - [0, 1, 2, 3, 4] - - *func* defaults to :func:`operator.sub`, but other functions can be - specified. They will be applied as follows:: - - A, B, C, D, ... --> A, func(B, A), func(C, B), func(D, C), ... - - For example, to do progressive division: - - >>> iterable = [1, 2, 6, 24, 120] - >>> func = lambda x, y: x // y - >>> list(difference(iterable, func)) - [1, 2, 3, 4, 5] - - If the *initial* keyword is set, the first element will be skipped when - computing successive differences. - - >>> it = [10, 11, 13, 16] # from accumulate([1, 2, 3], initial=10) - >>> list(difference(it, initial=10)) - [1, 2, 3] - - """ - a, b = tee(iterable) - try: - first = [next(b)] - except StopIteration: - return iter([]) - - if initial is not None: - first = [] - - return chain(first, map(func, b, a)) - - -class SequenceView(Sequence): - """Return a read-only view of the sequence object *target*. - - :class:`SequenceView` objects are analogous to Python's built-in - "dictionary view" types. They provide a dynamic view of a sequence's items, - meaning that when the sequence updates, so does the view. - - >>> seq = ['0', '1', '2'] - >>> view = SequenceView(seq) - >>> view - SequenceView(['0', '1', '2']) - >>> seq.append('3') - >>> view - SequenceView(['0', '1', '2', '3']) - - Sequence views support indexing, slicing, and length queries. They act - like the underlying sequence, except they don't allow assignment: - - >>> view[1] - '1' - >>> view[1:-1] - ['1', '2'] - >>> len(view) - 4 - - Sequence views are useful as an alternative to copying, as they don't - require (much) extra storage. - - """ - - def __init__(self, target): - if not isinstance(target, Sequence): - raise TypeError - self._target = target - - def __getitem__(self, index): - return self._target[index] - - def __len__(self): - return len(self._target) - - def __repr__(self): - return '{}({})'.format(self.__class__.__name__, repr(self._target)) - - -class seekable: - """Wrap an iterator to allow for seeking backward and forward. This - progressively caches the items in the source iterable so they can be - re-visited. - - Call :meth:`seek` with an index to seek to that position in the source - iterable. - - To "reset" an iterator, seek to ``0``: - - >>> from itertools import count - >>> it = seekable((str(n) for n in count())) - >>> next(it), next(it), next(it) - ('0', '1', '2') - >>> it.seek(0) - >>> next(it), next(it), next(it) - ('0', '1', '2') - >>> next(it) - '3' - - You can also seek forward: - - >>> it = seekable((str(n) for n in range(20))) - >>> it.seek(10) - >>> next(it) - '10' - >>> it.seek(20) # Seeking past the end of the source isn't a problem - >>> list(it) - [] - >>> it.seek(0) # Resetting works even after hitting the end - >>> next(it), next(it), next(it) - ('0', '1', '2') - - Call :meth:`peek` to look ahead one item without advancing the iterator: - - >>> it = seekable('1234') - >>> it.peek() - '1' - >>> list(it) - ['1', '2', '3', '4'] - >>> it.peek(default='empty') - 'empty' - - Before the iterator is at its end, calling :func:`bool` on it will return - ``True``. After it will return ``False``: - - >>> it = seekable('5678') - >>> bool(it) - True - >>> list(it) - ['5', '6', '7', '8'] - >>> bool(it) - False - - You may view the contents of the cache with the :meth:`elements` method. - That returns a :class:`SequenceView`, a view that updates automatically: - - >>> it = seekable((str(n) for n in range(10))) - >>> next(it), next(it), next(it) - ('0', '1', '2') - >>> elements = it.elements() - >>> elements - SequenceView(['0', '1', '2']) - >>> next(it) - '3' - >>> elements - SequenceView(['0', '1', '2', '3']) - - By default, the cache grows as the source iterable progresses, so beware of - wrapping very large or infinite iterables. Supply *maxlen* to limit the - size of the cache (this of course limits how far back you can seek). - - >>> from itertools import count - >>> it = seekable((str(n) for n in count()), maxlen=2) - >>> next(it), next(it), next(it), next(it) - ('0', '1', '2', '3') - >>> list(it.elements()) - ['2', '3'] - >>> it.seek(0) - >>> next(it), next(it), next(it), next(it) - ('2', '3', '4', '5') - >>> next(it) - '6' - - """ - - def __init__(self, iterable, maxlen=None): - self._source = iter(iterable) - if maxlen is None: - self._cache = [] - else: - self._cache = deque([], maxlen) - self._index = None - - def __iter__(self): - return self - - def __next__(self): - if self._index is not None: - try: - item = self._cache[self._index] - except IndexError: - self._index = None - else: - self._index += 1 - return item - - item = next(self._source) - self._cache.append(item) - return item - - def __bool__(self): - try: - self.peek() - except StopIteration: - return False - return True - - def peek(self, default=_marker): - try: - peeked = next(self) - except StopIteration: - if default is _marker: - raise - return default - if self._index is None: - self._index = len(self._cache) - self._index -= 1 - return peeked - - def elements(self): - return SequenceView(self._cache) - - def seek(self, index): - self._index = index - remainder = index - len(self._cache) - if remainder > 0: - consume(self, remainder) - - -class run_length: - """ - :func:`run_length.encode` compresses an iterable with run-length encoding. - It yields groups of repeated items with the count of how many times they - were repeated: - - >>> uncompressed = 'abbcccdddd' - >>> list(run_length.encode(uncompressed)) - [('a', 1), ('b', 2), ('c', 3), ('d', 4)] - - :func:`run_length.decode` decompresses an iterable that was previously - compressed with run-length encoding. It yields the items of the - decompressed iterable: - - >>> compressed = [('a', 1), ('b', 2), ('c', 3), ('d', 4)] - >>> list(run_length.decode(compressed)) - ['a', 'b', 'b', 'c', 'c', 'c', 'd', 'd', 'd', 'd'] - - """ - - @staticmethod - def encode(iterable): - return ((k, ilen(g)) for k, g in groupby(iterable)) - - @staticmethod - def decode(iterable): - return chain.from_iterable(repeat(k, n) for k, n in iterable) - - -def exactly_n(iterable, n, predicate=bool): - """Return ``True`` if exactly ``n`` items in the iterable are ``True`` - according to the *predicate* function. - - >>> exactly_n([True, True, False], 2) - True - >>> exactly_n([True, True, False], 1) - False - >>> exactly_n([0, 1, 2, 3, 4, 5], 3, lambda x: x < 3) - True - - The iterable will be advanced until ``n + 1`` truthy items are encountered, - so avoid calling it on infinite iterables. - - """ - return len(take(n + 1, filter(predicate, iterable))) == n - - -def circular_shifts(iterable): - """Return a list of circular shifts of *iterable*. - - >>> circular_shifts(range(4)) - [(0, 1, 2, 3), (1, 2, 3, 0), (2, 3, 0, 1), (3, 0, 1, 2)] - """ - lst = list(iterable) - return take(len(lst), windowed(cycle(lst), len(lst))) - - -def make_decorator(wrapping_func, result_index=0): - """Return a decorator version of *wrapping_func*, which is a function that - modifies an iterable. *result_index* is the position in that function's - signature where the iterable goes. - - This lets you use itertools on the "production end," i.e. at function - definition. This can augment what the function returns without changing the - function's code. - - For example, to produce a decorator version of :func:`chunked`: - - >>> from more_itertools import chunked - >>> chunker = make_decorator(chunked, result_index=0) - >>> @chunker(3) - ... def iter_range(n): - ... return iter(range(n)) - ... - >>> list(iter_range(9)) - [[0, 1, 2], [3, 4, 5], [6, 7, 8]] - - To only allow truthy items to be returned: - - >>> truth_serum = make_decorator(filter, result_index=1) - >>> @truth_serum(bool) - ... def boolean_test(): - ... return [0, 1, '', ' ', False, True] - ... - >>> list(boolean_test()) - [1, ' ', True] - - The :func:`peekable` and :func:`seekable` wrappers make for practical - decorators: - - >>> from more_itertools import peekable - >>> peekable_function = make_decorator(peekable) - >>> @peekable_function() - ... def str_range(*args): - ... return (str(x) for x in range(*args)) - ... - >>> it = str_range(1, 20, 2) - >>> next(it), next(it), next(it) - ('1', '3', '5') - >>> it.peek() - '7' - >>> next(it) - '7' - - """ - # See https://sites.google.com/site/bbayles/index/decorator_factory for - # notes on how this works. - def decorator(*wrapping_args, **wrapping_kwargs): - def outer_wrapper(f): - def inner_wrapper(*args, **kwargs): - result = f(*args, **kwargs) - wrapping_args_ = list(wrapping_args) - wrapping_args_.insert(result_index, result) - return wrapping_func(*wrapping_args_, **wrapping_kwargs) - - return inner_wrapper - - return outer_wrapper - - return decorator - - -def map_reduce(iterable, keyfunc, valuefunc=None, reducefunc=None): - """Return a dictionary that maps the items in *iterable* to categories - defined by *keyfunc*, transforms them with *valuefunc*, and - then summarizes them by category with *reducefunc*. - - *valuefunc* defaults to the identity function if it is unspecified. - If *reducefunc* is unspecified, no summarization takes place: - - >>> keyfunc = lambda x: x.upper() - >>> result = map_reduce('abbccc', keyfunc) - >>> sorted(result.items()) - [('A', ['a']), ('B', ['b', 'b']), ('C', ['c', 'c', 'c'])] - - Specifying *valuefunc* transforms the categorized items: - - >>> keyfunc = lambda x: x.upper() - >>> valuefunc = lambda x: 1 - >>> result = map_reduce('abbccc', keyfunc, valuefunc) - >>> sorted(result.items()) - [('A', [1]), ('B', [1, 1]), ('C', [1, 1, 1])] - - Specifying *reducefunc* summarizes the categorized items: - - >>> keyfunc = lambda x: x.upper() - >>> valuefunc = lambda x: 1 - >>> reducefunc = sum - >>> result = map_reduce('abbccc', keyfunc, valuefunc, reducefunc) - >>> sorted(result.items()) - [('A', 1), ('B', 2), ('C', 3)] - - You may want to filter the input iterable before applying the map/reduce - procedure: - - >>> all_items = range(30) - >>> items = [x for x in all_items if 10 <= x <= 20] # Filter - >>> keyfunc = lambda x: x % 2 # Evens map to 0; odds to 1 - >>> categories = map_reduce(items, keyfunc=keyfunc) - >>> sorted(categories.items()) - [(0, [10, 12, 14, 16, 18, 20]), (1, [11, 13, 15, 17, 19])] - >>> summaries = map_reduce(items, keyfunc=keyfunc, reducefunc=sum) - >>> sorted(summaries.items()) - [(0, 90), (1, 75)] - - Note that all items in the iterable are gathered into a list before the - summarization step, which may require significant storage. - - The returned object is a :obj:`collections.defaultdict` with the - ``default_factory`` set to ``None``, such that it behaves like a normal - dictionary. - - """ - valuefunc = (lambda x: x) if (valuefunc is None) else valuefunc - - ret = defaultdict(list) - for item in iterable: - key = keyfunc(item) - value = valuefunc(item) - ret[key].append(value) - - if reducefunc is not None: - for key, value_list in ret.items(): - ret[key] = reducefunc(value_list) - - ret.default_factory = None - return ret - - -def rlocate(iterable, pred=bool, window_size=None): - """Yield the index of each item in *iterable* for which *pred* returns - ``True``, starting from the right and moving left. - - *pred* defaults to :func:`bool`, which will select truthy items: - - >>> list(rlocate([0, 1, 1, 0, 1, 0, 0])) # Truthy at 1, 2, and 4 - [4, 2, 1] - - Set *pred* to a custom function to, e.g., find the indexes for a particular - item: - - >>> iterable = iter('abcb') - >>> pred = lambda x: x == 'b' - >>> list(rlocate(iterable, pred)) - [3, 1] - - If *window_size* is given, then the *pred* function will be called with - that many items. This enables searching for sub-sequences: - - >>> iterable = [0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3] - >>> pred = lambda *args: args == (1, 2, 3) - >>> list(rlocate(iterable, pred=pred, window_size=3)) - [9, 5, 1] - - Beware, this function won't return anything for infinite iterables. - If *iterable* is reversible, ``rlocate`` will reverse it and search from - the right. Otherwise, it will search from the left and return the results - in reverse order. - - See :func:`locate` to for other example applications. - - """ - if window_size is None: - try: - len_iter = len(iterable) - return (len_iter - i - 1 for i in locate(reversed(iterable), pred)) - except TypeError: - pass - - return reversed(list(locate(iterable, pred, window_size))) - - -def replace(iterable, pred, substitutes, count=None, window_size=1): - """Yield the items from *iterable*, replacing the items for which *pred* - returns ``True`` with the items from the iterable *substitutes*. - - >>> iterable = [1, 1, 0, 1, 1, 0, 1, 1] - >>> pred = lambda x: x == 0 - >>> substitutes = (2, 3) - >>> list(replace(iterable, pred, substitutes)) - [1, 1, 2, 3, 1, 1, 2, 3, 1, 1] - - If *count* is given, the number of replacements will be limited: - - >>> iterable = [1, 1, 0, 1, 1, 0, 1, 1, 0] - >>> pred = lambda x: x == 0 - >>> substitutes = [None] - >>> list(replace(iterable, pred, substitutes, count=2)) - [1, 1, None, 1, 1, None, 1, 1, 0] - - Use *window_size* to control the number of items passed as arguments to - *pred*. This allows for locating and replacing subsequences. - - >>> iterable = [0, 1, 2, 5, 0, 1, 2, 5] - >>> window_size = 3 - >>> pred = lambda *args: args == (0, 1, 2) # 3 items passed to pred - >>> substitutes = [3, 4] # Splice in these items - >>> list(replace(iterable, pred, substitutes, window_size=window_size)) - [3, 4, 5, 3, 4, 5] - - """ - if window_size < 1: - raise ValueError('window_size must be at least 1') - - # Save the substitutes iterable, since it's used more than once - substitutes = tuple(substitutes) - - # Add padding such that the number of windows matches the length of the - # iterable - it = chain(iterable, [_marker] * (window_size - 1)) - windows = windowed(it, window_size) - - n = 0 - for w in windows: - # If the current window matches our predicate (and we haven't hit - # our maximum number of replacements), splice in the substitutes - # and then consume the following windows that overlap with this one. - # For example, if the iterable is (0, 1, 2, 3, 4...) - # and the window size is 2, we have (0, 1), (1, 2), (2, 3)... - # If the predicate matches on (0, 1), we need to zap (0, 1) and (1, 2) - if pred(*w): - if (count is None) or (n < count): - n += 1 - yield from substitutes - consume(windows, window_size - 1) - continue - - # If there was no match (or we've reached the replacement limit), - # yield the first item from the window. - if w and (w[0] is not _marker): - yield w[0] - - -def partitions(iterable): - """Yield all possible order-preserving partitions of *iterable*. - - >>> iterable = 'abc' - >>> for part in partitions(iterable): - ... print([''.join(p) for p in part]) - ['abc'] - ['a', 'bc'] - ['ab', 'c'] - ['a', 'b', 'c'] - - This is unrelated to :func:`partition`. - - """ - sequence = list(iterable) - n = len(sequence) - for i in powerset(range(1, n)): - yield [sequence[i:j] for i, j in zip((0,) + i, i + (n,))] - - -def set_partitions(iterable, k=None): - """ - Yield the set partitions of *iterable* into *k* parts. Set partitions are - not order-preserving. - - >>> iterable = 'abc' - >>> for part in set_partitions(iterable, 2): - ... print([''.join(p) for p in part]) - ['a', 'bc'] - ['ab', 'c'] - ['b', 'ac'] - - - If *k* is not given, every set partition is generated. - - >>> iterable = 'abc' - >>> for part in set_partitions(iterable): - ... print([''.join(p) for p in part]) - ['abc'] - ['a', 'bc'] - ['ab', 'c'] - ['b', 'ac'] - ['a', 'b', 'c'] - - """ - L = list(iterable) - n = len(L) - if k is not None: - if k < 1: - raise ValueError( - "Can't partition in a negative or zero number of groups" - ) - elif k > n: - return - - def set_partitions_helper(L, k): - n = len(L) - if k == 1: - yield [L] - elif n == k: - yield [[s] for s in L] - else: - e, *M = L - for p in set_partitions_helper(M, k - 1): - yield [[e], *p] - for p in set_partitions_helper(M, k): - for i in range(len(p)): - yield p[:i] + [[e] + p[i]] + p[i + 1 :] - - if k is None: - for k in range(1, n + 1): - yield from set_partitions_helper(L, k) - else: - yield from set_partitions_helper(L, k) - - -class time_limited: - """ - Yield items from *iterable* until *limit_seconds* have passed. - If the time limit expires before all items have been yielded, the - ``timed_out`` parameter will be set to ``True``. - - >>> from time import sleep - >>> def generator(): - ... yield 1 - ... yield 2 - ... sleep(0.2) - ... yield 3 - >>> iterable = time_limited(0.1, generator()) - >>> list(iterable) - [1, 2] - >>> iterable.timed_out - True - - Note that the time is checked before each item is yielded, and iteration - stops if the time elapsed is greater than *limit_seconds*. If your time - limit is 1 second, but it takes 2 seconds to generate the first item from - the iterable, the function will run for 2 seconds and not yield anything. - - """ - - def __init__(self, limit_seconds, iterable): - if limit_seconds < 0: - raise ValueError('limit_seconds must be positive') - self.limit_seconds = limit_seconds - self._iterable = iter(iterable) - self._start_time = monotonic() - self.timed_out = False - - def __iter__(self): - return self - - def __next__(self): - item = next(self._iterable) - if monotonic() - self._start_time > self.limit_seconds: - self.timed_out = True - raise StopIteration - - return item - - -def only(iterable, default=None, too_long=None): - """If *iterable* has only one item, return it. - If it has zero items, return *default*. - If it has more than one item, raise the exception given by *too_long*, - which is ``ValueError`` by default. - - >>> only([], default='missing') - 'missing' - >>> only([1]) - 1 - >>> only([1, 2]) # doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ... - ValueError: Expected exactly one item in iterable, but got 1, 2, - and perhaps more.' - >>> only([1, 2], too_long=TypeError) # doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ... - TypeError - - Note that :func:`only` attempts to advance *iterable* twice to ensure there - is only one item. See :func:`spy` or :func:`peekable` to check - iterable contents less destructively. - """ - it = iter(iterable) - first_value = next(it, default) - - try: - second_value = next(it) - except StopIteration: - pass - else: - msg = ( - 'Expected exactly one item in iterable, but got {!r}, {!r}, ' - 'and perhaps more.'.format(first_value, second_value) - ) - raise too_long or ValueError(msg) - - return first_value - - -class _IChunk: - def __init__(self, iterable, n): - self._it = islice(iterable, n) - self._cache = deque() - - def fill_cache(self): - self._cache.extend(self._it) - - def __iter__(self): - return self - - def __next__(self): - try: - return next(self._it) - except StopIteration: - if self._cache: - return self._cache.popleft() - else: - raise - - -def ichunked(iterable, n): - """Break *iterable* into sub-iterables with *n* elements each. - :func:`ichunked` is like :func:`chunked`, but it yields iterables - instead of lists. - - If the sub-iterables are read in order, the elements of *iterable* - won't be stored in memory. - If they are read out of order, :func:`itertools.tee` is used to cache - elements as necessary. - - >>> from itertools import count - >>> all_chunks = ichunked(count(), 4) - >>> c_1, c_2, c_3 = next(all_chunks), next(all_chunks), next(all_chunks) - >>> list(c_2) # c_1's elements have been cached; c_3's haven't been - [4, 5, 6, 7] - >>> list(c_1) - [0, 1, 2, 3] - >>> list(c_3) - [8, 9, 10, 11] - - """ - source = peekable(iter(iterable)) - ichunk_marker = object() - while True: - # Check to see whether we're at the end of the source iterable - item = source.peek(ichunk_marker) - if item is ichunk_marker: - return - - chunk = _IChunk(source, n) - yield chunk - - # Advance the source iterable and fill previous chunk's cache - chunk.fill_cache() - - -def iequals(*iterables): - """Return ``True`` if all given *iterables* are equal to each other, - which means that they contain the same elements in the same order. - - The function is useful for comparing iterables of different data types - or iterables that do not support equality checks. - - >>> iequals("abc", ['a', 'b', 'c'], ('a', 'b', 'c'), iter("abc")) - True - - >>> iequals("abc", "acb") - False - - Not to be confused with :func:`all_equals`, which checks whether all - elements of iterable are equal to each other. - - """ - return all(map(all_equal, zip_longest(*iterables, fillvalue=object()))) - - -def distinct_combinations(iterable, r): - """Yield the distinct combinations of *r* items taken from *iterable*. - - >>> list(distinct_combinations([0, 0, 1], 2)) - [(0, 0), (0, 1)] - - Equivalent to ``set(combinations(iterable))``, except duplicates are not - generated and thrown away. For larger input sequences this is much more - efficient. - - """ - if r < 0: - raise ValueError('r must be non-negative') - elif r == 0: - yield () - return - pool = tuple(iterable) - generators = [unique_everseen(enumerate(pool), key=itemgetter(1))] - current_combo = [None] * r - level = 0 - while generators: - try: - cur_idx, p = next(generators[-1]) - except StopIteration: - generators.pop() - level -= 1 - continue - current_combo[level] = p - if level + 1 == r: - yield tuple(current_combo) - else: - generators.append( - unique_everseen( - enumerate(pool[cur_idx + 1 :], cur_idx + 1), - key=itemgetter(1), - ) - ) - level += 1 - - -def filter_except(validator, iterable, *exceptions): - """Yield the items from *iterable* for which the *validator* function does - not raise one of the specified *exceptions*. - - *validator* is called for each item in *iterable*. - It should be a function that accepts one argument and raises an exception - if that item is not valid. - - >>> iterable = ['1', '2', 'three', '4', None] - >>> list(filter_except(int, iterable, ValueError, TypeError)) - ['1', '2', '4'] - - If an exception other than one given by *exceptions* is raised by - *validator*, it is raised like normal. - """ - for item in iterable: - try: - validator(item) - except exceptions: - pass - else: - yield item - - -def map_except(function, iterable, *exceptions): - """Transform each item from *iterable* with *function* and yield the - result, unless *function* raises one of the specified *exceptions*. - - *function* is called to transform each item in *iterable*. - It should accept one argument. - - >>> iterable = ['1', '2', 'three', '4', None] - >>> list(map_except(int, iterable, ValueError, TypeError)) - [1, 2, 4] - - If an exception other than one given by *exceptions* is raised by - *function*, it is raised like normal. - """ - for item in iterable: - try: - yield function(item) - except exceptions: - pass - - -def map_if(iterable, pred, func, func_else=lambda x: x): - """Evaluate each item from *iterable* using *pred*. If the result is - equivalent to ``True``, transform the item with *func* and yield it. - Otherwise, transform the item with *func_else* and yield it. - - *pred*, *func*, and *func_else* should each be functions that accept - one argument. By default, *func_else* is the identity function. - - >>> from math import sqrt - >>> iterable = list(range(-5, 5)) - >>> iterable - [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4] - >>> list(map_if(iterable, lambda x: x > 3, lambda x: 'toobig')) - [-5, -4, -3, -2, -1, 0, 1, 2, 3, 'toobig'] - >>> list(map_if(iterable, lambda x: x >= 0, - ... lambda x: f'{sqrt(x):.2f}', lambda x: None)) - [None, None, None, None, None, '0.00', '1.00', '1.41', '1.73', '2.00'] - """ - for item in iterable: - yield func(item) if pred(item) else func_else(item) - - -def _sample_unweighted(iterable, k): - # Implementation of "Algorithm L" from the 1994 paper by Kim-Hung Li: - # "Reservoir-Sampling Algorithms of Time Complexity O(n(1+log(N/n)))". - - # Fill up the reservoir (collection of samples) with the first `k` samples - reservoir = take(k, iterable) - - # Generate random number that's the largest in a sample of k U(0,1) numbers - # Largest order statistic: https://en.wikipedia.org/wiki/Order_statistic - W = exp(log(random()) / k) - - # The number of elements to skip before changing the reservoir is a random - # number with a geometric distribution. Sample it using random() and logs. - next_index = k + floor(log(random()) / log(1 - W)) - - for index, element in enumerate(iterable, k): - - if index == next_index: - reservoir[randrange(k)] = element - # The new W is the largest in a sample of k U(0, `old_W`) numbers - W *= exp(log(random()) / k) - next_index += floor(log(random()) / log(1 - W)) + 1 - - return reservoir - - -def _sample_weighted(iterable, k, weights): - # Implementation of "A-ExpJ" from the 2006 paper by Efraimidis et al. : - # "Weighted random sampling with a reservoir". - - # Log-transform for numerical stability for weights that are small/large - weight_keys = (log(random()) / weight for weight in weights) - - # Fill up the reservoir (collection of samples) with the first `k` - # weight-keys and elements, then heapify the list. - reservoir = take(k, zip(weight_keys, iterable)) - heapify(reservoir) - - # The number of jumps before changing the reservoir is a random variable - # with an exponential distribution. Sample it using random() and logs. - smallest_weight_key, _ = reservoir[0] - weights_to_skip = log(random()) / smallest_weight_key - - for weight, element in zip(weights, iterable): - if weight >= weights_to_skip: - # The notation here is consistent with the paper, but we store - # the weight-keys in log-space for better numerical stability. - smallest_weight_key, _ = reservoir[0] - t_w = exp(weight * smallest_weight_key) - r_2 = uniform(t_w, 1) # generate U(t_w, 1) - weight_key = log(r_2) / weight - heapreplace(reservoir, (weight_key, element)) - smallest_weight_key, _ = reservoir[0] - weights_to_skip = log(random()) / smallest_weight_key - else: - weights_to_skip -= weight - - # Equivalent to [element for weight_key, element in sorted(reservoir)] - return [heappop(reservoir)[1] for _ in range(k)] - - -def sample(iterable, k, weights=None): - """Return a *k*-length list of elements chosen (without replacement) - from the *iterable*. Like :func:`random.sample`, but works on iterables - of unknown length. - - >>> iterable = range(100) - >>> sample(iterable, 5) # doctest: +SKIP - [81, 60, 96, 16, 4] - - An iterable with *weights* may also be given: - - >>> iterable = range(100) - >>> weights = (i * i + 1 for i in range(100)) - >>> sampled = sample(iterable, 5, weights=weights) # doctest: +SKIP - [79, 67, 74, 66, 78] - - The algorithm can also be used to generate weighted random permutations. - The relative weight of each item determines the probability that it - appears late in the permutation. - - >>> data = "abcdefgh" - >>> weights = range(1, len(data) + 1) - >>> sample(data, k=len(data), weights=weights) # doctest: +SKIP - ['c', 'a', 'b', 'e', 'g', 'd', 'h', 'f'] - """ - if k == 0: - return [] - - iterable = iter(iterable) - if weights is None: - return _sample_unweighted(iterable, k) - else: - weights = iter(weights) - return _sample_weighted(iterable, k, weights) - - -def is_sorted(iterable, key=None, reverse=False, strict=False): - """Returns ``True`` if the items of iterable are in sorted order, and - ``False`` otherwise. *key* and *reverse* have the same meaning that they do - in the built-in :func:`sorted` function. - - >>> is_sorted(['1', '2', '3', '4', '5'], key=int) - True - >>> is_sorted([5, 4, 3, 1, 2], reverse=True) - False - - If *strict*, tests for strict sorting, that is, returns ``False`` if equal - elements are found: - - >>> is_sorted([1, 2, 2]) - True - >>> is_sorted([1, 2, 2], strict=True) - False - - The function returns ``False`` after encountering the first out-of-order - item. If there are no out-of-order items, the iterable is exhausted. - """ - - compare = (le if reverse else ge) if strict else (lt if reverse else gt) - it = iterable if key is None else map(key, iterable) - return not any(starmap(compare, pairwise(it))) - - -class AbortThread(BaseException): - pass - - -class callback_iter: - """Convert a function that uses callbacks to an iterator. - - Let *func* be a function that takes a `callback` keyword argument. - For example: - - >>> def func(callback=None): - ... for i, c in [(1, 'a'), (2, 'b'), (3, 'c')]: - ... if callback: - ... callback(i, c) - ... return 4 - - - Use ``with callback_iter(func)`` to get an iterator over the parameters - that are delivered to the callback. - - >>> with callback_iter(func) as it: - ... for args, kwargs in it: - ... print(args) - (1, 'a') - (2, 'b') - (3, 'c') - - The function will be called in a background thread. The ``done`` property - indicates whether it has completed execution. - - >>> it.done - True - - If it completes successfully, its return value will be available - in the ``result`` property. - - >>> it.result - 4 - - Notes: - - * If the function uses some keyword argument besides ``callback``, supply - *callback_kwd*. - * If it finished executing, but raised an exception, accessing the - ``result`` property will raise the same exception. - * If it hasn't finished executing, accessing the ``result`` - property from within the ``with`` block will raise ``RuntimeError``. - * If it hasn't finished executing, accessing the ``result`` property from - outside the ``with`` block will raise a - ``more_itertools.AbortThread`` exception. - * Provide *wait_seconds* to adjust how frequently the it is polled for - output. - - """ - - def __init__(self, func, callback_kwd='callback', wait_seconds=0.1): - self._func = func - self._callback_kwd = callback_kwd - self._aborted = False - self._future = None - self._wait_seconds = wait_seconds - # Lazily import concurrent.future - self._executor = __import__( - ).futures.__import__("concurrent.futures").futures.ThreadPoolExecutor(max_workers=1) - self._iterator = self._reader() - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, traceback): - self._aborted = True - self._executor.shutdown() - - def __iter__(self): - return self - - def __next__(self): - return next(self._iterator) - - @property - def done(self): - if self._future is None: - return False - return self._future.done() - - @property - def result(self): - if not self.done: - raise RuntimeError('Function has not yet completed') - - return self._future.result() - - def _reader(self): - q = Queue() - - def callback(*args, **kwargs): - if self._aborted: - raise AbortThread('canceled by user') - - q.put((args, kwargs)) - - self._future = self._executor.submit( - self._func, **{self._callback_kwd: callback} - ) - - while True: - try: - item = q.get(timeout=self._wait_seconds) - except Empty: - pass - else: - q.task_done() - yield item - - if self._future.done(): - break - - remaining = [] - while True: - try: - item = q.get_nowait() - except Empty: - break - else: - q.task_done() - remaining.append(item) - q.join() - yield from remaining - - -def windowed_complete(iterable, n): - """ - Yield ``(beginning, middle, end)`` tuples, where: - - * Each ``middle`` has *n* items from *iterable* - * Each ``beginning`` has the items before the ones in ``middle`` - * Each ``end`` has the items after the ones in ``middle`` - - >>> iterable = range(7) - >>> n = 3 - >>> for beginning, middle, end in windowed_complete(iterable, n): - ... print(beginning, middle, end) - () (0, 1, 2) (3, 4, 5, 6) - (0,) (1, 2, 3) (4, 5, 6) - (0, 1) (2, 3, 4) (5, 6) - (0, 1, 2) (3, 4, 5) (6,) - (0, 1, 2, 3) (4, 5, 6) () - - Note that *n* must be at least 0 and most equal to the length of - *iterable*. - - This function will exhaust the iterable and may require significant - storage. - """ - if n < 0: - raise ValueError('n must be >= 0') - - seq = tuple(iterable) - size = len(seq) - - if n > size: - raise ValueError('n must be <= len(seq)') - - for i in range(size - n + 1): - beginning = seq[:i] - middle = seq[i : i + n] - end = seq[i + n :] - yield beginning, middle, end - - -def all_unique(iterable, key=None): - """ - Returns ``True`` if all the elements of *iterable* are unique (no two - elements are equal). - - >>> all_unique('ABCB') - False - - If a *key* function is specified, it will be used to make comparisons. - - >>> all_unique('ABCb') - True - >>> all_unique('ABCb', str.lower) - False - - The function returns as soon as the first non-unique element is - encountered. Iterables with a mix of hashable and unhashable items can - be used, but the function will be slower for unhashable items. - """ - seenset = set() - seenset_add = seenset.add - seenlist = [] - seenlist_add = seenlist.append - for element in map(key, iterable) if key else iterable: - try: - if element in seenset: - return False - seenset_add(element) - except TypeError: - if element in seenlist: - return False - seenlist_add(element) - return True - - -def nth_product(index, *args): - """Equivalent to ``list(product(*args))[index]``. - - The products of *args* can be ordered lexicographically. - :func:`nth_product` computes the product at sort position *index* without - computing the previous products. - - >>> nth_product(8, range(2), range(2), range(2), range(2)) - (1, 0, 0, 0) - - ``IndexError`` will be raised if the given *index* is invalid. - """ - pools = list(map(tuple, reversed(args))) - ns = list(map(len, pools)) - - c = reduce(mul, ns) - - if index < 0: - index += c - - if not 0 <= index < c: - raise IndexError - - result = [] - for pool, n in zip(pools, ns): - result.append(pool[index % n]) - index //= n - - return tuple(reversed(result)) - - -def nth_permutation(iterable, r, index): - """Equivalent to ``list(permutations(iterable, r))[index]``` - - The subsequences of *iterable* that are of length *r* where order is - important can be ordered lexicographically. :func:`nth_permutation` - computes the subsequence at sort position *index* directly, without - computing the previous subsequences. - - >>> nth_permutation('ghijk', 2, 5) - ('h', 'i') - - ``ValueError`` will be raised If *r* is negative or greater than the length - of *iterable*. - ``IndexError`` will be raised if the given *index* is invalid. - """ - pool = list(iterable) - n = len(pool) - - if r is None or r == n: - r, c = n, factorial(n) - elif not 0 <= r < n: - raise ValueError - else: - c = factorial(n) // factorial(n - r) - - if index < 0: - index += c - - if not 0 <= index < c: - raise IndexError - - if c == 0: - return tuple() - - result = [0] * r - q = index * factorial(n) // c if r < n else index - for d in range(1, n + 1): - q, i = divmod(q, d) - if 0 <= n - d < r: - result[n - d] = i - if q == 0: - break - - return tuple(map(pool.pop, result)) - - -def value_chain(*args): - """Yield all arguments passed to the function in the same order in which - they were passed. If an argument itself is iterable then iterate over its - values. - - >>> list(value_chain(1, 2, 3, [4, 5, 6])) - [1, 2, 3, 4, 5, 6] - - Binary and text strings are not considered iterable and are emitted - as-is: - - >>> list(value_chain('12', '34', ['56', '78'])) - ['12', '34', '56', '78'] - - - Multiple levels of nesting are not flattened. - - """ - for value in args: - if isinstance(value, (str, bytes)): - yield value - continue - try: - yield from value - except TypeError: - yield value - - -def product_index(element, *args): - """Equivalent to ``list(product(*args)).index(element)`` - - The products of *args* can be ordered lexicographically. - :func:`product_index` computes the first index of *element* without - computing the previous products. - - >>> product_index([8, 2], range(10), range(5)) - 42 - - ``ValueError`` will be raised if the given *element* isn't in the product - of *args*. - """ - index = 0 - - for x, pool in zip_longest(element, args, fillvalue=_marker): - if x is _marker or pool is _marker: - raise ValueError('element is not a product of args') - - pool = tuple(pool) - index = index * len(pool) + pool.index(x) - - return index - - -def combination_index(element, iterable): - """Equivalent to ``list(combinations(iterable, r)).index(element)`` - - The subsequences of *iterable* that are of length *r* can be ordered - lexicographically. :func:`combination_index` computes the index of the - first *element*, without computing the previous combinations. - - >>> combination_index('adf', 'abcdefg') - 10 - - ``ValueError`` will be raised if the given *element* isn't one of the - combinations of *iterable*. - """ - element = enumerate(element) - k, y = next(element, (None, None)) - if k is None: - return 0 - - indexes = [] - pool = enumerate(iterable) - for n, x in pool: - if x == y: - indexes.append(n) - tmp, y = next(element, (None, None)) - if tmp is None: - break - else: - k = tmp - else: - raise ValueError('element is not a combination of iterable') - - n, _ = last(pool, default=(n, None)) - - # Python versions below 3.8 don't have math.comb - index = 1 - for i, j in enumerate(reversed(indexes), start=1): - j = n - j - if i <= j: - index += factorial(j) // (factorial(i) * factorial(j - i)) - - return factorial(n + 1) // (factorial(k + 1) * factorial(n - k)) - index - - -def permutation_index(element, iterable): - """Equivalent to ``list(permutations(iterable, r)).index(element)``` - - The subsequences of *iterable* that are of length *r* where order is - important can be ordered lexicographically. :func:`permutation_index` - computes the index of the first *element* directly, without computing - the previous permutations. - - >>> permutation_index([1, 3, 2], range(5)) - 19 - - ``ValueError`` will be raised if the given *element* isn't one of the - permutations of *iterable*. - """ - index = 0 - pool = list(iterable) - for i, x in zip(range(len(pool), -1, -1), element): - r = pool.index(x) - index = index * i + r - del pool[r] - - return index - - -class countable: - """Wrap *iterable* and keep a count of how many items have been consumed. - - The ``items_seen`` attribute starts at ``0`` and increments as the iterable - is consumed: - - >>> iterable = map(str, range(10)) - >>> it = countable(iterable) - >>> it.items_seen - 0 - >>> next(it), next(it) - ('0', '1') - >>> list(it) - ['2', '3', '4', '5', '6', '7', '8', '9'] - >>> it.items_seen - 10 - """ - - def __init__(self, iterable): - self._it = iter(iterable) - self.items_seen = 0 - - def __iter__(self): - return self - - def __next__(self): - item = next(self._it) - self.items_seen += 1 - - return item - - -def chunked_even(iterable, n): - """Break *iterable* into lists of approximately length *n*. - Items are distributed such the lengths of the lists differ by at most - 1 item. - - >>> iterable = [1, 2, 3, 4, 5, 6, 7] - >>> n = 3 - >>> list(chunked_even(iterable, n)) # List lengths: 3, 2, 2 - [[1, 2, 3], [4, 5], [6, 7]] - >>> list(chunked(iterable, n)) # List lengths: 3, 3, 1 - [[1, 2, 3], [4, 5, 6], [7]] - - """ - - len_method = getattr(iterable, '__len__', None) - - if len_method is None: - return _chunked_even_online(iterable, n) - else: - return _chunked_even_finite(iterable, len_method(), n) - - -def _chunked_even_online(iterable, n): - buffer = [] - maxbuf = n + (n - 2) * (n - 1) - for x in iterable: - buffer.append(x) - if len(buffer) == maxbuf: - yield buffer[:n] - buffer = buffer[n:] - yield from _chunked_even_finite(buffer, len(buffer), n) - - -def _chunked_even_finite(iterable, N, n): - if N < 1: - return - - # Lists are either size `full_size <= n` or `partial_size = full_size - 1` - q, r = divmod(N, n) - num_lists = q + (1 if r > 0 else 0) - q, r = divmod(N, num_lists) - full_size = q + (1 if r > 0 else 0) - partial_size = full_size - 1 - num_full = N - partial_size * num_lists - num_partial = num_lists - num_full - - buffer = [] - iterator = iter(iterable) - - # Yield num_full lists of full_size - for x in iterator: - buffer.append(x) - if len(buffer) == full_size: - yield buffer - buffer = [] - num_full -= 1 - if num_full <= 0: - break - - # Yield num_partial lists of partial_size - for x in iterator: - buffer.append(x) - if len(buffer) == partial_size: - yield buffer - buffer = [] - num_partial -= 1 - - -def zip_broadcast(*objects, scalar_types=(str, bytes), strict=False): - """A version of :func:`zip` that "broadcasts" any scalar - (i.e., non-iterable) items into output tuples. - - >>> iterable_1 = [1, 2, 3] - >>> iterable_2 = ['a', 'b', 'c'] - >>> scalar = '_' - >>> list(zip_broadcast(iterable_1, iterable_2, scalar)) - [(1, 'a', '_'), (2, 'b', '_'), (3, 'c', '_')] - - The *scalar_types* keyword argument determines what types are considered - scalar. It is set to ``(str, bytes)`` by default. Set it to ``None`` to - treat strings and byte strings as iterable: - - >>> list(zip_broadcast('abc', 0, 'xyz', scalar_types=None)) - [('a', 0, 'x'), ('b', 0, 'y'), ('c', 0, 'z')] - - If the *strict* keyword argument is ``True``, then - ``UnequalIterablesError`` will be raised if any of the iterables have - different lengths. - """ - - def is_scalar(obj): - if scalar_types and isinstance(obj, scalar_types): - return True - try: - iter(obj) - except TypeError: - return True - else: - return False - - size = len(objects) - if not size: - return - - iterables, iterable_positions = [], [] - scalars, scalar_positions = [], [] - for i, obj in enumerate(objects): - if is_scalar(obj): - scalars.append(obj) - scalar_positions.append(i) - else: - iterables.append(iter(obj)) - iterable_positions.append(i) - - if len(scalars) == size: - yield tuple(objects) - return - - zipper = _zip_equal if strict else zip - for item in zipper(*iterables): - new_item = [None] * size - - for i, elem in zip(iterable_positions, item): - new_item[i] = elem - - for i, elem in zip(scalar_positions, scalars): - new_item[i] = elem - - yield tuple(new_item) - - -def unique_in_window(iterable, n, key=None): - """Yield the items from *iterable* that haven't been seen recently. - *n* is the size of the lookback window. - - >>> iterable = [0, 1, 0, 2, 3, 0] - >>> n = 3 - >>> list(unique_in_window(iterable, n)) - [0, 1, 2, 3, 0] - - The *key* function, if provided, will be used to determine uniqueness: - - >>> list(unique_in_window('abAcda', 3, key=lambda x: x.lower())) - ['a', 'b', 'c', 'd', 'a'] - - The items in *iterable* must be hashable. - - """ - if n <= 0: - raise ValueError('n must be greater than 0') - - window = deque(maxlen=n) - uniques = set() - use_key = key is not None - - for item in iterable: - k = key(item) if use_key else item - if k in uniques: - continue - - if len(uniques) == n: - uniques.discard(window[0]) - - uniques.add(k) - window.append(k) - - yield item - - -def duplicates_everseen(iterable, key=None): - """Yield duplicate elements after their first appearance. - - >>> list(duplicates_everseen('mississippi')) - ['s', 'i', 's', 's', 'i', 'p', 'i'] - >>> list(duplicates_everseen('AaaBbbCccAaa', str.lower)) - ['a', 'a', 'b', 'b', 'c', 'c', 'A', 'a', 'a'] - - This function is analagous to :func:`unique_everseen` and is subject to - the same performance considerations. - - """ - seen_set = set() - seen_list = [] - use_key = key is not None - - for element in iterable: - k = key(element) if use_key else element - try: - if k not in seen_set: - seen_set.add(k) - else: - yield element - except TypeError: - if k not in seen_list: - seen_list.append(k) - else: - yield element - - -def duplicates_justseen(iterable, key=None): - """Yields serially-duplicate elements after their first appearance. - - >>> list(duplicates_justseen('mississippi')) - ['s', 's', 'p'] - >>> list(duplicates_justseen('AaaBbbCccAaa', str.lower)) - ['a', 'a', 'b', 'b', 'c', 'c', 'a', 'a'] - - This function is analagous to :func:`unique_justseen`. - - """ - return flatten( - map( - lambda group_tuple: islice_extended(group_tuple[1])[1:], - groupby(iterable, key), - ) - ) - - -def minmax(iterable_or_value, *others, key=None, default=_marker): - """Returns both the smallest and largest items in an iterable - or the largest of two or more arguments. - - >>> minmax([3, 1, 5]) - (1, 5) - - >>> minmax(4, 2, 6) - (2, 6) - - If a *key* function is provided, it will be used to transform the input - items for comparison. - - >>> minmax([5, 30], key=str) # '30' sorts before '5' - (30, 5) - - If a *default* value is provided, it will be returned if there are no - input items. - - >>> minmax([], default=(0, 0)) - (0, 0) - - Otherwise ``ValueError`` is raised. - - This function is based on the - `recipe `__ by - Raymond Hettinger and takes care to minimize the number of comparisons - performed. - """ - iterable = (iterable_or_value, *others) if others else iterable_or_value - - it = iter(iterable) - - try: - lo = hi = next(it) - except StopIteration as e: - if default is _marker: - raise ValueError( - '`minmax()` argument is an empty iterable. ' - 'Provide a `default` value to suppress this error.' - ) from e - return default - - # Different branches depending on the presence of key. This saves a lot - # of unimportant copies which would slow the "key=None" branch - # significantly down. - if key is None: - for x, y in zip_longest(it, it, fillvalue=lo): - if y < x: - x, y = y, x - if x < lo: - lo = x - if hi < y: - hi = y - - else: - lo_key = hi_key = key(lo) - - for x, y in zip_longest(it, it, fillvalue=lo): - - x_key, y_key = key(x), key(y) - - if y_key < x_key: - x, y, x_key, y_key = y, x, y_key, x_key - if x_key < lo_key: - lo, lo_key = x, x_key - if hi_key < y_key: - hi, hi_key = y, y_key - - return lo, hi - - -def constrained_batches( - iterable, max_size, max_count=None, get_len=len, strict=True -): - """Yield batches of items from *iterable* with a combined size limited by - *max_size*. - - >>> iterable = [b'12345', b'123', b'12345678', b'1', b'1', b'12', b'1'] - >>> list(constrained_batches(iterable, 10)) - [(b'12345', b'123'), (b'12345678', b'1', b'1'), (b'12', b'1')] - - If a *max_count* is supplied, the number of items per batch is also - limited: - - >>> iterable = [b'12345', b'123', b'12345678', b'1', b'1', b'12', b'1'] - >>> list(constrained_batches(iterable, 10, max_count = 2)) - [(b'12345', b'123'), (b'12345678', b'1'), (b'1', b'12'), (b'1',)] - - If a *get_len* function is supplied, use that instead of :func:`len` to - determine item size. - - If *strict* is ``True``, raise ``ValueError`` if any single item is bigger - than *max_size*. Otherwise, allow single items to exceed *max_size*. - """ - if max_size <= 0: - raise ValueError('maximum size must be greater than zero') - - batch = [] - batch_size = 0 - batch_count = 0 - for item in iterable: - item_len = get_len(item) - if strict and item_len > max_size: - raise ValueError('item size exceeds maximum size') - - reached_count = batch_count == max_count - reached_size = item_len + batch_size > max_size - if batch_count and (reached_size or reached_count): - yield tuple(batch) - batch.clear() - batch_size = 0 - batch_count = 0 - - batch.append(item) - batch_size += item_len - batch_count += 1 - - if batch: - yield tuple(batch) diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/more_itertools/recipes.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/more_itertools/recipes.py deleted file mode 100755 index 8579620..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/more_itertools/recipes.py +++ /dev/null @@ -1,841 +0,0 @@ -"""Imported from the recipes section of the itertools documentation. - -All functions taken from the recipes section of the itertools library docs -[1]_. -Some backward-compatible usability improvements have been made. - -.. [1] http://docs.python.org/library/itertools.html#recipes - -""" -import math -import operator - -from collections import deque -from collections.abc import Sized -from functools import reduce -from itertools import ( - chain, - combinations, - compress, - count, - cycle, - groupby, - islice, - repeat, - starmap, - tee, - zip_longest, -) -from random import randrange, sample, choice - -__all__ = [ - 'all_equal', - 'batched', - 'before_and_after', - 'consume', - 'convolve', - 'dotproduct', - 'first_true', - 'flatten', - 'grouper', - 'iter_except', - 'ncycles', - 'nth', - 'nth_combination', - 'padnone', - 'pad_none', - 'pairwise', - 'partition', - 'polynomial_from_roots', - 'powerset', - 'prepend', - 'quantify', - 'random_combination_with_replacement', - 'random_combination', - 'random_permutation', - 'random_product', - 'repeatfunc', - 'roundrobin', - 'sieve', - 'sliding_window', - 'subslices', - 'tabulate', - 'tail', - 'take', - 'triplewise', - 'unique_everseen', - 'unique_justseen', -] - -_marker = object() - - -def take(n, iterable): - """Return first *n* items of the iterable as a list. - - >>> take(3, range(10)) - [0, 1, 2] - - If there are fewer than *n* items in the iterable, all of them are - returned. - - >>> take(10, range(3)) - [0, 1, 2] - - """ - return list(islice(iterable, n)) - - -def tabulate(function, start=0): - """Return an iterator over the results of ``func(start)``, - ``func(start + 1)``, ``func(start + 2)``... - - *func* should be a function that accepts one integer argument. - - If *start* is not specified it defaults to 0. It will be incremented each - time the iterator is advanced. - - >>> square = lambda x: x ** 2 - >>> iterator = tabulate(square, -3) - >>> take(4, iterator) - [9, 4, 1, 0] - - """ - return map(function, count(start)) - - -def tail(n, iterable): - """Return an iterator over the last *n* items of *iterable*. - - >>> t = tail(3, 'ABCDEFG') - >>> list(t) - ['E', 'F', 'G'] - - """ - # If the given iterable has a length, then we can use islice to get its - # final elements. Note that if the iterable is not actually Iterable, - # either islice or deque will throw a TypeError. This is why we don't - # check if it is Iterable. - if isinstance(iterable, Sized): - yield from islice(iterable, max(0, len(iterable) - n), None) - else: - yield from iter(deque(iterable, maxlen=n)) - - -def consume(iterator, n=None): - """Advance *iterable* by *n* steps. If *n* is ``None``, consume it - entirely. - - Efficiently exhausts an iterator without returning values. Defaults to - consuming the whole iterator, but an optional second argument may be - provided to limit consumption. - - >>> i = (x for x in range(10)) - >>> next(i) - 0 - >>> consume(i, 3) - >>> next(i) - 4 - >>> consume(i) - >>> next(i) - Traceback (most recent call last): - File "", line 1, in - StopIteration - - If the iterator has fewer items remaining than the provided limit, the - whole iterator will be consumed. - - >>> i = (x for x in range(3)) - >>> consume(i, 5) - >>> next(i) - Traceback (most recent call last): - File "", line 1, in - StopIteration - - """ - # Use functions that consume iterators at C speed. - if n is None: - # feed the entire iterator into a zero-length deque - deque(iterator, maxlen=0) - else: - # advance to the empty slice starting at position n - next(islice(iterator, n, n), None) - - -def nth(iterable, n, default=None): - """Returns the nth item or a default value. - - >>> l = range(10) - >>> nth(l, 3) - 3 - >>> nth(l, 20, "zebra") - 'zebra' - - """ - return next(islice(iterable, n, None), default) - - -def all_equal(iterable): - """ - Returns ``True`` if all the elements are equal to each other. - - >>> all_equal('aaaa') - True - >>> all_equal('aaab') - False - - """ - g = groupby(iterable) - return next(g, True) and not next(g, False) - - -def quantify(iterable, pred=bool): - """Return the how many times the predicate is true. - - >>> quantify([True, False, True]) - 2 - - """ - return sum(map(pred, iterable)) - - -def pad_none(iterable): - """Returns the sequence of elements and then returns ``None`` indefinitely. - - >>> take(5, pad_none(range(3))) - [0, 1, 2, None, None] - - Useful for emulating the behavior of the built-in :func:`map` function. - - See also :func:`padded`. - - """ - return chain(iterable, repeat(None)) - - -padnone = pad_none - - -def ncycles(iterable, n): - """Returns the sequence elements *n* times - - >>> list(ncycles(["a", "b"], 3)) - ['a', 'b', 'a', 'b', 'a', 'b'] - - """ - return chain.from_iterable(repeat(tuple(iterable), n)) - - -def dotproduct(vec1, vec2): - """Returns the dot product of the two iterables. - - >>> dotproduct([10, 10], [20, 20]) - 400 - - """ - return sum(map(operator.mul, vec1, vec2)) - - -def flatten(listOfLists): - """Return an iterator flattening one level of nesting in a list of lists. - - >>> list(flatten([[0, 1], [2, 3]])) - [0, 1, 2, 3] - - See also :func:`collapse`, which can flatten multiple levels of nesting. - - """ - return chain.from_iterable(listOfLists) - - -def repeatfunc(func, times=None, *args): - """Call *func* with *args* repeatedly, returning an iterable over the - results. - - If *times* is specified, the iterable will terminate after that many - repetitions: - - >>> from operator import add - >>> times = 4 - >>> args = 3, 5 - >>> list(repeatfunc(add, times, *args)) - [8, 8, 8, 8] - - If *times* is ``None`` the iterable will not terminate: - - >>> from random import randrange - >>> times = None - >>> args = 1, 11 - >>> take(6, repeatfunc(randrange, times, *args)) # doctest:+SKIP - [2, 4, 8, 1, 8, 4] - - """ - if times is None: - return starmap(func, repeat(args)) - return starmap(func, repeat(args, times)) - - -def _pairwise(iterable): - """Returns an iterator of paired items, overlapping, from the original - - >>> take(4, pairwise(count())) - [(0, 1), (1, 2), (2, 3), (3, 4)] - - On Python 3.10 and above, this is an alias for :func:`itertools.pairwise`. - - """ - a, b = tee(iterable) - next(b, None) - yield from zip(a, b) - - -try: - from itertools import pairwise as itertools_pairwise -except ImportError: - pairwise = _pairwise -else: - - def pairwise(iterable): - yield from itertools_pairwise(iterable) - - pairwise.__doc__ = _pairwise.__doc__ - - -class UnequalIterablesError(ValueError): - def __init__(self, details=None): - msg = 'Iterables have different lengths' - if details is not None: - msg += (': index 0 has length {}; index {} has length {}').format( - *details - ) - - super().__init__(msg) - - -def _zip_equal_generator(iterables): - for combo in zip_longest(*iterables, fillvalue=_marker): - for val in combo: - if val is _marker: - raise UnequalIterablesError() - yield combo - - -def _zip_equal(*iterables): - # Check whether the iterables are all the same size. - try: - first_size = len(iterables[0]) - for i, it in enumerate(iterables[1:], 1): - size = len(it) - if size != first_size: - break - else: - # If we didn't break out, we can use the built-in zip. - return zip(*iterables) - - # If we did break out, there was a mismatch. - raise UnequalIterablesError(details=(first_size, i, size)) - # If any one of the iterables didn't have a length, start reading - # them until one runs out. - except TypeError: - return _zip_equal_generator(iterables) - - -def grouper(iterable, n, incomplete='fill', fillvalue=None): - """Group elements from *iterable* into fixed-length groups of length *n*. - - >>> list(grouper('ABCDEF', 3)) - [('A', 'B', 'C'), ('D', 'E', 'F')] - - The keyword arguments *incomplete* and *fillvalue* control what happens for - iterables whose length is not a multiple of *n*. - - When *incomplete* is `'fill'`, the last group will contain instances of - *fillvalue*. - - >>> list(grouper('ABCDEFG', 3, incomplete='fill', fillvalue='x')) - [('A', 'B', 'C'), ('D', 'E', 'F'), ('G', 'x', 'x')] - - When *incomplete* is `'ignore'`, the last group will not be emitted. - - >>> list(grouper('ABCDEFG', 3, incomplete='ignore', fillvalue='x')) - [('A', 'B', 'C'), ('D', 'E', 'F')] - - When *incomplete* is `'strict'`, a subclass of `ValueError` will be raised. - - >>> it = grouper('ABCDEFG', 3, incomplete='strict') - >>> list(it) # doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ... - UnequalIterablesError - - """ - args = [iter(iterable)] * n - if incomplete == 'fill': - return zip_longest(*args, fillvalue=fillvalue) - if incomplete == 'strict': - return _zip_equal(*args) - if incomplete == 'ignore': - return zip(*args) - else: - raise ValueError('Expected fill, strict, or ignore') - - -def roundrobin(*iterables): - """Yields an item from each iterable, alternating between them. - - >>> list(roundrobin('ABC', 'D', 'EF')) - ['A', 'D', 'E', 'B', 'F', 'C'] - - This function produces the same output as :func:`interleave_longest`, but - may perform better for some inputs (in particular when the number of - iterables is small). - - """ - # Recipe credited to George Sakkis - pending = len(iterables) - nexts = cycle(iter(it).__next__ for it in iterables) - while pending: - try: - for next in nexts: - yield next() - except StopIteration: - pending -= 1 - nexts = cycle(islice(nexts, pending)) - - -def partition(pred, iterable): - """ - Returns a 2-tuple of iterables derived from the input iterable. - The first yields the items that have ``pred(item) == False``. - The second yields the items that have ``pred(item) == True``. - - >>> is_odd = lambda x: x % 2 != 0 - >>> iterable = range(10) - >>> even_items, odd_items = partition(is_odd, iterable) - >>> list(even_items), list(odd_items) - ([0, 2, 4, 6, 8], [1, 3, 5, 7, 9]) - - If *pred* is None, :func:`bool` is used. - - >>> iterable = [0, 1, False, True, '', ' '] - >>> false_items, true_items = partition(None, iterable) - >>> list(false_items), list(true_items) - ([0, False, ''], [1, True, ' ']) - - """ - if pred is None: - pred = bool - - evaluations = ((pred(x), x) for x in iterable) - t1, t2 = tee(evaluations) - return ( - (x for (cond, x) in t1 if not cond), - (x for (cond, x) in t2 if cond), - ) - - -def powerset(iterable): - """Yields all possible subsets of the iterable. - - >>> list(powerset([1, 2, 3])) - [(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)] - - :func:`powerset` will operate on iterables that aren't :class:`set` - instances, so repeated elements in the input will produce repeated elements - in the output. Use :func:`unique_everseen` on the input to avoid generating - duplicates: - - >>> seq = [1, 1, 0] - >>> list(powerset(seq)) - [(), (1,), (1,), (0,), (1, 1), (1, 0), (1, 0), (1, 1, 0)] - >>> from more_itertools import unique_everseen - >>> list(powerset(unique_everseen(seq))) - [(), (1,), (0,), (1, 0)] - - """ - s = list(iterable) - return chain.from_iterable(combinations(s, r) for r in range(len(s) + 1)) - - -def unique_everseen(iterable, key=None): - """ - Yield unique elements, preserving order. - - >>> list(unique_everseen('AAAABBBCCDAABBB')) - ['A', 'B', 'C', 'D'] - >>> list(unique_everseen('ABBCcAD', str.lower)) - ['A', 'B', 'C', 'D'] - - Sequences with a mix of hashable and unhashable items can be used. - The function will be slower (i.e., `O(n^2)`) for unhashable items. - - Remember that ``list`` objects are unhashable - you can use the *key* - parameter to transform the list to a tuple (which is hashable) to - avoid a slowdown. - - >>> iterable = ([1, 2], [2, 3], [1, 2]) - >>> list(unique_everseen(iterable)) # Slow - [[1, 2], [2, 3]] - >>> list(unique_everseen(iterable, key=tuple)) # Faster - [[1, 2], [2, 3]] - - Similary, you may want to convert unhashable ``set`` objects with - ``key=frozenset``. For ``dict`` objects, - ``key=lambda x: frozenset(x.items())`` can be used. - - """ - seenset = set() - seenset_add = seenset.add - seenlist = [] - seenlist_add = seenlist.append - use_key = key is not None - - for element in iterable: - k = key(element) if use_key else element - try: - if k not in seenset: - seenset_add(k) - yield element - except TypeError: - if k not in seenlist: - seenlist_add(k) - yield element - - -def unique_justseen(iterable, key=None): - """Yields elements in order, ignoring serial duplicates - - >>> list(unique_justseen('AAAABBBCCDAABBB')) - ['A', 'B', 'C', 'D', 'A', 'B'] - >>> list(unique_justseen('ABBCcAD', str.lower)) - ['A', 'B', 'C', 'A', 'D'] - - """ - return map(next, map(operator.itemgetter(1), groupby(iterable, key))) - - -def iter_except(func, exception, first=None): - """Yields results from a function repeatedly until an exception is raised. - - Converts a call-until-exception interface to an iterator interface. - Like ``iter(func, sentinel)``, but uses an exception instead of a sentinel - to end the loop. - - >>> l = [0, 1, 2] - >>> list(iter_except(l.pop, IndexError)) - [2, 1, 0] - - Multiple exceptions can be specified as a stopping condition: - - >>> l = [1, 2, 3, '...', 4, 5, 6] - >>> list(iter_except(lambda: 1 + l.pop(), (IndexError, TypeError))) - [7, 6, 5] - >>> list(iter_except(lambda: 1 + l.pop(), (IndexError, TypeError))) - [4, 3, 2] - >>> list(iter_except(lambda: 1 + l.pop(), (IndexError, TypeError))) - [] - - """ - try: - if first is not None: - yield first() - while 1: - yield func() - except exception: - pass - - -def first_true(iterable, default=None, pred=None): - """ - Returns the first true value in the iterable. - - If no true value is found, returns *default* - - If *pred* is not None, returns the first item for which - ``pred(item) == True`` . - - >>> first_true(range(10)) - 1 - >>> first_true(range(10), pred=lambda x: x > 5) - 6 - >>> first_true(range(10), default='missing', pred=lambda x: x > 9) - 'missing' - - """ - return next(filter(pred, iterable), default) - - -def random_product(*args, repeat=1): - """Draw an item at random from each of the input iterables. - - >>> random_product('abc', range(4), 'XYZ') # doctest:+SKIP - ('c', 3, 'Z') - - If *repeat* is provided as a keyword argument, that many items will be - drawn from each iterable. - - >>> random_product('abcd', range(4), repeat=2) # doctest:+SKIP - ('a', 2, 'd', 3) - - This equivalent to taking a random selection from - ``itertools.product(*args, **kwarg)``. - - """ - pools = [tuple(pool) for pool in args] * repeat - return tuple(choice(pool) for pool in pools) - - -def random_permutation(iterable, r=None): - """Return a random *r* length permutation of the elements in *iterable*. - - If *r* is not specified or is ``None``, then *r* defaults to the length of - *iterable*. - - >>> random_permutation(range(5)) # doctest:+SKIP - (3, 4, 0, 1, 2) - - This equivalent to taking a random selection from - ``itertools.permutations(iterable, r)``. - - """ - pool = tuple(iterable) - r = len(pool) if r is None else r - return tuple(sample(pool, r)) - - -def random_combination(iterable, r): - """Return a random *r* length subsequence of the elements in *iterable*. - - >>> random_combination(range(5), 3) # doctest:+SKIP - (2, 3, 4) - - This equivalent to taking a random selection from - ``itertools.combinations(iterable, r)``. - - """ - pool = tuple(iterable) - n = len(pool) - indices = sorted(sample(range(n), r)) - return tuple(pool[i] for i in indices) - - -def random_combination_with_replacement(iterable, r): - """Return a random *r* length subsequence of elements in *iterable*, - allowing individual elements to be repeated. - - >>> random_combination_with_replacement(range(3), 5) # doctest:+SKIP - (0, 0, 1, 2, 2) - - This equivalent to taking a random selection from - ``itertools.combinations_with_replacement(iterable, r)``. - - """ - pool = tuple(iterable) - n = len(pool) - indices = sorted(randrange(n) for i in range(r)) - return tuple(pool[i] for i in indices) - - -def nth_combination(iterable, r, index): - """Equivalent to ``list(combinations(iterable, r))[index]``. - - The subsequences of *iterable* that are of length *r* can be ordered - lexicographically. :func:`nth_combination` computes the subsequence at - sort position *index* directly, without computing the previous - subsequences. - - >>> nth_combination(range(5), 3, 5) - (0, 3, 4) - - ``ValueError`` will be raised If *r* is negative or greater than the length - of *iterable*. - ``IndexError`` will be raised if the given *index* is invalid. - """ - pool = tuple(iterable) - n = len(pool) - if (r < 0) or (r > n): - raise ValueError - - c = 1 - k = min(r, n - r) - for i in range(1, k + 1): - c = c * (n - k + i) // i - - if index < 0: - index += c - - if (index < 0) or (index >= c): - raise IndexError - - result = [] - while r: - c, n, r = c * r // n, n - 1, r - 1 - while index >= c: - index -= c - c, n = c * (n - r) // n, n - 1 - result.append(pool[-1 - n]) - - return tuple(result) - - -def prepend(value, iterator): - """Yield *value*, followed by the elements in *iterator*. - - >>> value = '0' - >>> iterator = ['1', '2', '3'] - >>> list(prepend(value, iterator)) - ['0', '1', '2', '3'] - - To prepend multiple values, see :func:`itertools.chain` - or :func:`value_chain`. - - """ - return chain([value], iterator) - - -def convolve(signal, kernel): - """Convolve the iterable *signal* with the iterable *kernel*. - - >>> signal = (1, 2, 3, 4, 5) - >>> kernel = [3, 2, 1] - >>> list(convolve(signal, kernel)) - [3, 8, 14, 20, 26, 14, 5] - - Note: the input arguments are not interchangeable, as the *kernel* - is immediately consumed and stored. - - """ - kernel = tuple(kernel)[::-1] - n = len(kernel) - window = deque([0], maxlen=n) * n - for x in chain(signal, repeat(0, n - 1)): - window.append(x) - yield sum(map(operator.mul, kernel, window)) - - -def before_and_after(predicate, it): - """A variant of :func:`takewhile` that allows complete access to the - remainder of the iterator. - - >>> it = iter('ABCdEfGhI') - >>> all_upper, remainder = before_and_after(str.isupper, it) - >>> ''.join(all_upper) - 'ABC' - >>> ''.join(remainder) # takewhile() would lose the 'd' - 'dEfGhI' - - Note that the first iterator must be fully consumed before the second - iterator can generate valid results. - """ - it = iter(it) - transition = [] - - def true_iterator(): - for elem in it: - if predicate(elem): - yield elem - else: - transition.append(elem) - return - - # Note: this is different from itertools recipes to allow nesting - # before_and_after remainders into before_and_after again. See tests - # for an example. - remainder_iterator = chain(transition, it) - - return true_iterator(), remainder_iterator - - -def triplewise(iterable): - """Return overlapping triplets from *iterable*. - - >>> list(triplewise('ABCDE')) - [('A', 'B', 'C'), ('B', 'C', 'D'), ('C', 'D', 'E')] - - """ - for (a, _), (b, c) in pairwise(pairwise(iterable)): - yield a, b, c - - -def sliding_window(iterable, n): - """Return a sliding window of width *n* over *iterable*. - - >>> list(sliding_window(range(6), 4)) - [(0, 1, 2, 3), (1, 2, 3, 4), (2, 3, 4, 5)] - - If *iterable* has fewer than *n* items, then nothing is yielded: - - >>> list(sliding_window(range(3), 4)) - [] - - For a variant with more features, see :func:`windowed`. - """ - it = iter(iterable) - window = deque(islice(it, n), maxlen=n) - if len(window) == n: - yield tuple(window) - for x in it: - window.append(x) - yield tuple(window) - - -def subslices(iterable): - """Return all contiguous non-empty subslices of *iterable*. - - >>> list(subslices('ABC')) - [['A'], ['A', 'B'], ['A', 'B', 'C'], ['B'], ['B', 'C'], ['C']] - - This is similar to :func:`substrings`, but emits items in a different - order. - """ - seq = list(iterable) - slices = starmap(slice, combinations(range(len(seq) + 1), 2)) - return map(operator.getitem, repeat(seq), slices) - - -def polynomial_from_roots(roots): - """Compute a polynomial's coefficients from its roots. - - >>> roots = [5, -4, 3] # (x - 5) * (x + 4) * (x - 3) - >>> polynomial_from_roots(roots) # x^3 - 4 * x^2 - 17 * x + 60 - [1, -4, -17, 60] - """ - # Use math.prod for Python 3.8+, - prod = getattr(math, 'prod', lambda x: reduce(operator.mul, x, 1)) - roots = list(map(operator.neg, roots)) - return [ - sum(map(prod, combinations(roots, k))) for k in range(len(roots) + 1) - ] - - -def sieve(n): - """Yield the primes less than n. - - >>> list(sieve(30)) - [2, 3, 5, 7, 11, 13, 17, 19, 23, 29] - """ - isqrt = getattr(math, 'isqrt', lambda x: int(math.sqrt(x))) - limit = isqrt(n) + 1 - data = bytearray([1]) * n - data[:2] = 0, 0 - for p in compress(range(limit), data): - data[p + p : n : p] = bytearray(len(range(p + p, n, p))) - - return compress(count(), data) - - -def batched(iterable, n): - """Batch data into lists of length *n*. The last batch may be shorter. - - >>> list(batched('ABCDEFG', 3)) - [['A', 'B', 'C'], ['D', 'E', 'F'], ['G']] - - This recipe is from the ``itertools`` docs. This library also provides - :func:`chunked`, which has a different implementation. - """ - it = iter(iterable) - while True: - batch = list(islice(it, n)) - if not batch: - break - yield batch diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__about__.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__about__.py deleted file mode 100755 index 3551bc2..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__about__.py +++ /dev/null @@ -1,26 +0,0 @@ -# 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. - -__all__ = [ - "__title__", - "__summary__", - "__uri__", - "__version__", - "__author__", - "__email__", - "__license__", - "__copyright__", -] - -__title__ = "packaging" -__summary__ = "Core utilities for Python packages" -__uri__ = "https://github.com/pypa/packaging" - -__version__ = "21.3" - -__author__ = "Donald Stufft and individual contributors" -__email__ = "donald@stufft.io" - -__license__ = "BSD-2-Clause or Apache-2.0" -__copyright__ = "2014-2019 %s" % __author__ diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__init__.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__init__.py deleted file mode 100755 index 3c50c5d..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__init__.py +++ /dev/null @@ -1,25 +0,0 @@ -# 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 .__about__ import ( - __author__, - __copyright__, - __email__, - __license__, - __summary__, - __title__, - __uri__, - __version__, -) - -__all__ = [ - "__title__", - "__summary__", - "__uri__", - "__version__", - "__author__", - "__email__", - "__license__", - "__copyright__", -] diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__pycache__/__about__.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__pycache__/__about__.cpython-311.pyc deleted file mode 100755 index 0ba4f28bacf8c4340fa313b08b0005dbfd1709b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 649 zcmYL_Pm9w)7{(|4mnPk;J&4F2mMD0rlFYW>Kh+-pMmh=6!xSj*X!He)<0SYYU-&O>-#dcXe|P zk8dbO6#X;;M2*0pt)NBQL7R4h4($eA+6#Kr3{2W*-KvLB(5Kc6jqFkX+9E`AoiakM z2ZX3H%R;$=#w4Vae80M6QgM+(V-pgVIuR1yVJFK%p6)d%k65l68;6ic6f4Q&L^rY` zjIP3%=W+G;LP+M8nx|ZIrrd>)?xz*lITOOb~ub!WO*gOQdL8`lfF?qsn11q@@{tNO}vXV zEERL%7;nKoVcx_)tBxjT<8u%2!hNDXj;tn%FoiK?lela*=rrgyfHaXb8}u7kfZyl_ zh;AuPM8+@#8VUSC#A1rWqQFa*FLBD}Fjh1A)E|$r;+lDf3~+H36Ume)WyBOFuz?DB z7XXIy%tZ;|`o-$D|0)x-OxbIB4}NOEt=qbXr@R3ey&+u98G?#S1?LV)G#i;-Q diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__pycache__/__init__.cpython-311.pyc deleted file mode 100755 index 60758eaeaf0f92915bf3ccf8705e86f06aa8c536..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 570 zcmcJLzfQw25XS8!ZT?h6OuRz|YE_k(5D&n>!sg}VCRS=1$B~m%>VkL(BqT-_#QQLH zWnwGp)`@dd5HEl&{d8x4zVFVj<8eZ8y+1zReNjR_T=KKLW3aox;ECiUrzO#pQ|)n2 z``p(75A=W!^pFpA$U`0Rh?0Wj-V5b%?%$F$_{6FtjW!8@=-P#`0GlyDX6m(7#iGSD z29R2)62lQdsWMqLvQL^$Yhl;Ds8wz0&O?CCs$Q^?wo#@6NFy7elMNkW2RE4Y9R?0V zhX8StCeBjKO^5Ei!kzz-9f};v{Z?|WqQoBG$PUG1pRt9}l3{z9Vb`WGGbZYqtz@-g zrJA#Pjnh`M$#lvZ)ynf)WJ^)VhSkdgtZYnYGt2-V-L@y#!Z#;nk)Z$p diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__pycache__/_manylinux.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__pycache__/_manylinux.cpython-311.pyc deleted file mode 100755 index 1da1e5bc08f162e63bc7c4bb552e36589234398d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13236 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 BwKo6& diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__pycache__/_musllinux.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__pycache__/_musllinux.cpython-311.pyc deleted file mode 100755 index 8dd4ac4007c4781bb203bde1750cc194138e76a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8004 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 KQtwNo!2bcr`+xKR diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__pycache__/_structures.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__pycache__/_structures.cpython-311.pyc deleted file mode 100755 index 8d0dd4dbc30da2558a97be1bd4db8f4ce6090d8d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3692 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 diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__pycache__/specifiers.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__pycache__/specifiers.cpython-311.pyc deleted file mode 100755 index 7de07846fd8f7e8ed68c7478905c2585442c5061..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34370 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 Tg5MN|3#fhy`N=Bbtjql$7bWif diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__pycache__/tags.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__pycache__/tags.cpython-311.pyc deleted file mode 100755 index 6ad45ff2761c40e63d520da14232fa93647239d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21355 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 diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__pycache__/version.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/__pycache__/version.cpython-311.pyc deleted file mode 100755 index 22c2d91ecabc18fc65f6769598740d169598dde5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21882 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 diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/_manylinux.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/_manylinux.py deleted file mode 100755 index 4c379aa..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/_manylinux.py +++ /dev/null @@ -1,301 +0,0 @@ -import collections -import functools -import os -import re -import struct -import sys -import warnings -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(sys.executable, "rb") as f: - elf_header = _ELFFileHeader(f) - except (OSError, TypeError, _ELFFileHeader._InvalidELFFileHeader): - return None - return elf_header - - -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 - 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(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 -# minor version was, so we can build the complete list of all versions. -# For now, guess what the highest minor version might be, assume it will -# be 50 for testing. Once this actually happens, update the dictionary -# with the actual value. -_LAST_GLIBC_MINOR: Dict[int, int] = collections.defaultdict(lambda: 50) - - -class _GLibCVersion(NamedTuple): - major: int - minor: int - - -def _glibc_version_string_confstr() -> 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 - # platform module. - # https://github.com/python/cpython/blob/fcf1d003bf4f0100c/Lib/platform.py#L175-L183 - try: - # 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.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() -> Optional[str]: - """ - Fallback implementation of glibc_version_string using ctypes. - """ - try: - import ctypes - except ImportError: - return None - - # ctypes.CDLL(None) internally calls dlopen(NULL), and as the dlopen - # manpage says, "If filename is NULL, then the returned handle is for the - # main program". This way we can let the linker do the work to figure out - # which libc our process is actually using. - # - # We must also handle the special case where the executable is not a - # dynamically linked executable. This can occur when using musl libc, - # for example. In this situation, dlopen() will error, leading to an - # OSError. Interestingly, at least in the case of musl, there is no - # errno set on the OSError. The single string argument used to construct - # OSError comes from libc itself and is therefore not portable to - # hard code here. In any case, failure to call dlopen() means we - # can proceed, so we bail on our attempt. - try: - process_namespace = ctypes.CDLL(None) - except OSError: - return None - - try: - gnu_get_libc_version = process_namespace.gnu_get_libc_version - except AttributeError: - # Symbol doesn't exist -> therefore, we are not linked to - # glibc. - return None - - # Call gnu_get_libc_version, which returns a string like "2.5" - gnu_get_libc_version.restype = ctypes.c_char_p - version_str: str = gnu_get_libc_version() - # py2 / py3 compatibility: - if not isinstance(version_str, str): - version_str = version_str.decode("ascii") - - return version_str - - -def _glibc_version_string() -> 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]: - """Parse glibc version. - - We use a regexp instead of str.split because we want to discard any - random junk that might come after the minor version -- this might happen - in patched/forked versions of glibc (e.g. Linaro's version of glibc - uses version strings like "2.20-2014.11"). See gh-3588. - """ - m = re.match(r"(?P[0-9]+)\.(?P[0-9]+)", version_str) - if not m: - warnings.warn( - "Expected glibc version with 2 components major.minor," - " got: %s" % version_str, - RuntimeWarning, - ) - return -1, -1 - return int(m.group("major")), int(m.group("minor")) - - -@functools.lru_cache() -def _get_glibc_version() -> Tuple[int, int]: - version_str = _glibc_version_string() - if version_str is None: - return (-1, -1) - return _parse_glibc_version(version_str) - - -# From PEP 513, PEP 600 -def _is_compatible(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 # noqa - except ImportError: - return True - if hasattr(_manylinux, "manylinux_compatible"): - result = _manylinux.manylinux_compatible(version[0], version[1], arch) - if result is not None: - return bool(result) - return True - if version == _GLibCVersion(2, 5): - if hasattr(_manylinux, "manylinux1_compatible"): - return bool(_manylinux.manylinux1_compatible) - if version == _GLibCVersion(2, 12): - if hasattr(_manylinux, "manylinux2010_compatible"): - return bool(_manylinux.manylinux2010_compatible) - if version == _GLibCVersion(2, 17): - if hasattr(_manylinux, "manylinux2014_compatible"): - return bool(_manylinux.manylinux2014_compatible) - return True - - -_LEGACY_MANYLINUX_MAP = { - # CentOS 7 w/ glibc 2.17 (PEP 599) - (2, 17): "manylinux2014", - # CentOS 6 w/ glibc 2.12 (PEP 571) - (2, 12): "manylinux2010", - # CentOS 5 w/ glibc 2.5 (PEP 513) - (2, 5): "manylinux1", -} - - -def platform_tags(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 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()) - glibc_max_list = [current_glibc] - # We can assume compatibility across glibc major versions. - # https://sourceware.org/bugzilla/show_bug.cgi?id=24636 - # - # Build a list of maximum glibc versions so that we can - # output the canonical list of all glibc from current_glibc - # down to too_old_glibc2, including all intermediary versions. - for glibc_major in range(current_glibc.major - 1, 1, -1): - glibc_minor = _LAST_GLIBC_MINOR[glibc_major] - glibc_max_list.append(_GLibCVersion(glibc_major, glibc_minor)) - for 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/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/_musllinux.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/_musllinux.py deleted file mode 100755 index 8ac3059..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/_musllinux.py +++ /dev/null @@ -1,136 +0,0 @@ -"""PEP 656 support. - -This module implements logic to detect if the currently running Python is -linked against musl, and what musl version is used. -""" - -import contextlib -import functools -import operator -import os -import re -import struct -import subprocess -import sys -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))) - - -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): - major: int - minor: int - - -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 - m = re.match(r"Version (\d+)\.(\d+)", lines[1]) - if not m: - return None - return _MuslVersion(major=int(m.group(1)), minor=int(m.group(2))) - - -@functools.lru_cache() -def _get_musl_version(executable: str) -> Optional[_MuslVersion]: - """Detect currently-running musl runtime version. - - This is done by checking the specified executable's dynamic linking - information, and invoking the loader to parse its output for a version - string. If the loader is musl, the output would be something like:: - - musl libc (x86_64) - Version 1.2.2 - Dynamic Program Loader - """ - 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, universal_newlines=True) - return _parse_musl_version(proc.stderr) - - -def platform_tags(arch: str) -> Iterator[str]: - """Generate musllinux tags compatible to the current platform. - - :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 minor in range(sys_musl.minor, -1, -1): - yield f"musllinux_{sys_musl.major}_{minor}_{arch}" - - -if __name__ == "__main__": # pragma: no cover - import sysconfig - - plat = sysconfig.get_platform() - assert plat.startswith("linux-"), "not linux" - - print("plat:", plat) - print("musl:", _get_musl_version(sys.executable)) - print("tags:", end=" ") - for t in platform_tags(re.sub(r"[.-]", "_", plat.split("-", 1)[-1])): - print(t, end="\n ") diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/_structures.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/_structures.py deleted file mode 100755 index 90a6465..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/_structures.py +++ /dev/null @@ -1,61 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - - -class InfinityType: - def __repr__(self) -> str: - return "Infinity" - - def __hash__(self) -> int: - return hash(repr(self)) - - def __lt__(self, other: object) -> bool: - return False - - def __le__(self, other: object) -> bool: - return False - - def __eq__(self, other: object) -> bool: - return isinstance(other, self.__class__) - - def __gt__(self, other: object) -> bool: - return True - - def __ge__(self, other: object) -> bool: - return True - - def __neg__(self: object) -> "NegativeInfinityType": - return NegativeInfinity - - -Infinity = InfinityType() - - -class NegativeInfinityType: - def __repr__(self) -> str: - return "-Infinity" - - def __hash__(self) -> int: - return hash(repr(self)) - - def __lt__(self, other: object) -> bool: - return True - - def __le__(self, other: object) -> bool: - return True - - def __eq__(self, other: object) -> bool: - return isinstance(other, self.__class__) - - def __gt__(self, other: object) -> bool: - return False - - def __ge__(self, other: object) -> bool: - return False - - def __neg__(self: object) -> InfinityType: - return Infinity - - -NegativeInfinity = NegativeInfinityType() diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/markers.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/markers.py deleted file mode 100755 index 18769b0..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/markers.py +++ /dev/null @@ -1,304 +0,0 @@ -# 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. - -import operator -import os -import platform -import sys -from typing import Any, Callable, Dict, List, Optional, Tuple, Union - -from pkg_resources.extern.pyparsing import ( # noqa: N817 - Forward, - Group, - Literal as L, - ParseException, - ParseResults, - QuotedString, - ZeroOrMore, - stringEnd, - stringStart, -) - -from .specifiers import InvalidSpecifier, Specifier - -__all__ = [ - "InvalidMarker", - "UndefinedComparison", - "UndefinedEnvironmentName", - "Marker", - "default_environment", -] - -Operator = Callable[[str, str], bool] - - -class InvalidMarker(ValueError): - """ - An invalid marker was found, users should refer to PEP 508. - """ - - -class UndefinedComparison(ValueError): - """ - An invalid operation was attempted on a value that doesn't support it. - """ - - -class UndefinedEnvironmentName(ValueError): - """ - A name was attempted to be used that does not exist inside of the - environment. - """ - - -class Node: - def __init__(self, value: Any) -> None: - self.value = value - - def __str__(self) -> str: - return str(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) - - -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]))) - -VERSION_CMP = ( - L("===") | L("==") | L(">=") | L("<=") | L("!=") | L("~=") | L(">") | L("<") -) - -MARKER_OP = VERSION_CMP | L("not in") | L("in") -MARKER_OP.setParseAction(lambda s, l, t: Op(t[0])) - -MARKER_VALUE = QuotedString("'") | QuotedString('"') -MARKER_VALUE.setParseAction(lambda s, l, t: Value(t[0])) - -BOOLOP = L("and") | L("or") - -MARKER_VAR = VARIABLE | MARKER_VALUE - -MARKER_ITEM = Group(MARKER_VAR + MARKER_OP + MARKER_VAR) -MARKER_ITEM.setParseAction(lambda s, l, t: tuple(t[0])) - -LPAREN = L("(").suppress() -RPAREN = L(")").suppress() - -MARKER_EXPR = Forward() -MARKER_ATOM = MARKER_ITEM | Group(LPAREN + MARKER_EXPR + RPAREN) -MARKER_EXPR << MARKER_ATOM + ZeroOrMore(BOOLOP + MARKER_EXPR) - -MARKER = stringStart + MARKER_EXPR + stringEnd - - -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: 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 - # where the single item is itself it's own list. In that case we want skip - # the rest of this function so that we don't get extraneous () on the - # outside. - if ( - isinstance(marker, list) - and len(marker) == 1 - and isinstance(marker[0], (list, tuple)) - ): - return _format_marker(marker[0]) - - if isinstance(marker, list): - inner = (_format_marker(m, first=False) for m in marker) - if first: - return " ".join(inner) - else: - return "(" + " ".join(inner) + ")" - elif isinstance(marker, tuple): - return " ".join([m.serialize() for m in marker]) - else: - return marker - - -_operators: Dict[str, Operator] = { - "in": lambda lhs, rhs: lhs in rhs, - "not in": lambda lhs, rhs: lhs not in rhs, - "<": operator.lt, - "<=": operator.le, - "==": operator.eq, - "!=": operator.ne, - ">=": operator.ge, - ">": operator.gt, -} - - -def _eval_op(lhs: str, op: Op, rhs: str) -> bool: - try: - spec = Specifier("".join([op.serialize(), rhs])) - except InvalidSpecifier: - pass - else: - return spec.contains(lhs) - - 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) - - -class Undefined: - pass - - -_undefined = Undefined() - - -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: List[Any], environment: Dict[str, str]) -> bool: - groups: List[List[bool]] = [[]] - - for marker in markers: - assert isinstance(marker, (list, tuple, str)) - - if isinstance(marker, list): - groups[-1].append(_evaluate_markers(marker, environment)) - elif isinstance(marker, tuple): - lhs, op, rhs = marker - - if isinstance(lhs, Variable): - lhs_value = _get_env(environment, lhs.value) - rhs_value = rhs.value - else: - lhs_value = lhs.value - rhs_value = _get_env(environment, rhs.value) - - groups[-1].append(_eval_op(lhs_value, op, rhs_value)) - else: - assert marker in ["and", "or"] - if marker == "or": - groups.append([]) - - return any(all(item) for item in groups) - - -def format_full_version(info: "sys._version_info") -> str: - version = "{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() -> Dict[str, str]: - iver = format_full_version(sys.implementation.version) - implementation_name = sys.implementation.name - return { - "implementation_name": implementation_name, - "implementation_version": iver, - "os_name": os.name, - "platform_machine": platform.machine(), - "platform_release": platform.release(), - "platform_system": platform.system(), - "platform_version": platform.version(), - "python_full_version": platform.python_version(), - "platform_python_implementation": platform.python_implementation(), - "python_version": ".".join(platform.python_version_tuple()[:2]), - "sys_platform": sys.platform, - } - - -class Marker: - def __init__(self, marker: str) -> None: - try: - 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) - - def __repr__(self) -> str: - return f"" - - 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 environment is determined from the current Python process. - """ - current_environment = default_environment() - if environment is not None: - current_environment.update(environment) - - return _evaluate_markers(self._markers, current_environment) diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/requirements.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/requirements.py deleted file mode 100755 index 6af14ec..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/requirements.py +++ /dev/null @@ -1,146 +0,0 @@ -# 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. - -import re -import string -import urllib.parse -from typing import List, Optional as TOptional, Set - -from pkg_resources.extern.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): - """ - An invalid requirement was found, users should refer to PEP 508. - """ - - -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 -# pkg_resources.extern.pyparsing isn't thread safe during initialization, so we do it eagerly, see -# issue #104 -REQUIREMENT.parseString("x[]") - - -class Requirement: - """Parse a requirement. - - Parse a given requirement string into its parts, such as name, specifier, - URL, and extras. Raises InvalidRequirement on a badly-formed requirement - string. - """ - - # TODO: Can we test whether something is contained within a requirement? - # If so how do we do that? Do we need to test against the _name_ of - # the thing as well as the version? What about the markers? - # TODO: Can we normalize the name and extra name? - - def __init__(self, requirement_string: str) -> None: - try: - 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)) - parts.append(f"[{formatted_extras}]") - - if self.specifier: - parts.append(str(self.specifier)) - - if self.url: - parts.append(f"@ {self.url}") - if self.marker: - parts.append(" ") - - if self.marker: - parts.append(f"; {self.marker}") - - return "".join(parts) - - def __repr__(self) -> str: - return f"" diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/specifiers.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/specifiers.py deleted file mode 100755 index 0e218a6..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/specifiers.py +++ /dev/null @@ -1,802 +0,0 @@ -# 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. - -import abc -import functools -import itertools -import re -import warnings -from typing import ( - Callable, - Dict, - Iterable, - Iterator, - List, - Optional, - Pattern, - Set, - Tuple, - TypeVar, - Union, -) - -from .utils import canonicalize_version -from .version import LegacyVersion, Version, parse - -ParsedVersion = Union[Version, LegacyVersion] -UnparsedVersion = Union[Version, LegacyVersion, str] -VersionTypeVar = TypeVar("VersionTypeVar", bound=UnparsedVersion) -CallableOperator = Callable[[ParsedVersion, str], bool] - - -class InvalidSpecifier(ValueError): - """ - An invalid specifier was found, users should refer to PEP 440. - """ - - -class BaseSpecifier(metaclass=abc.ABCMeta): - @abc.abstractmethod - def __str__(self) -> str: - """ - Returns the str representation of this Specifier like object. This - should be representative of the Specifier itself. - """ - - @abc.abstractmethod - def __hash__(self) -> int: - """ - Returns a hash value for this Specifier like object. - """ - - @abc.abstractmethod - def __eq__(self, other: object) -> bool: - """ - Returns a boolean representing whether or not the two Specifier like - objects are equal. - """ - - @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: - """ - Sets whether or not pre-releases as a whole are allowed by this - specifier. - """ - - @abc.abstractmethod - 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[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 _IndividualSpecifier(BaseSpecifier): - - _operators: Dict[str, str] = {} - _regex: Pattern[str] - - def __init__(self, spec: str = "", prereleases: Optional[bool] = None) -> None: - match = self._regex.search(spec) - if not match: - raise InvalidSpecifier(f"Invalid specifier: '{spec}'") - - 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. - ) - """ - - _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 - # do an exact string match of the version you wish to install. - # This will not be parsed by PEP 440 and we cannot determine - # any semantic meaning from it. This operator is discouraged - # but included entirely as an escape hatch. - (?<====) # Only match for the identity operator - \s* - [^\s]* # We just match everything, except for whitespace - # since we are only testing for strict identity. - ) - | - (?: - # The (non)equality operators allow for wild card and local - # versions to be specified so we have to define these two - # operators separately to enable that. - (?<===|!=) # Only match for equals and not equals - - \s* - v? - (?:[0-9]+!)? # epoch - [0-9]+(?:\.[0-9]+)* # release - (?: # 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 dev or local version - # together so group them with a | and make them optional. - (?: - (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release - (?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local - | - \.\* # Wild card syntax of .* - )? - ) - | - (?: - # The compatible operator requires at least two digits in the - # release segment. - (?<=~=) # Only match for the compatible operator - - \s* - v? - (?:[0-9]+!)? # epoch - [0-9]+(?:\.[0-9]+)+ # release (We have a + instead of a *) - (?: # pre release - [-_\.]? - (a|b|c|rc|alpha|beta|pre|preview) - [-_\.]? - [0-9]* - )? - (?: # post release - (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) - )? - (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release - ) - | - (?: - # All other operators only allow a sub set of what the - # (non)equality operators do. Specifically they do not allow - # local versions to be specified nor do they allow the prefix - # matching wild cards. - (?=": "greater_than_equal", - "<": "less_than", - ">": "greater_than", - "===": "arbitrary", - } - - @_require_version_compare - def _compare_compatible(self, prospective: ParsedVersion, spec: str) -> bool: - - # Compatible releases have an equivalent combination of >= and ==. That - # is that ~=2.2 is equivalent to >=2.2,==2.*. This allows us to - # implement this in terms of the other specifiers instead of - # implementing it ourselves. The only thing we need to do is construct - # the other specifiers. - - # We want everything but the last item in the version, but we want to - # ignore suffix segments. - prefix = ".".join( - list(itertools.takewhile(_is_not_suffix, _version_split(spec)))[:-1] - ) - - # Add the prefix notation to the end of our string - prefix += ".*" - - return self._get_operator(">=")(prospective, spec) and self._get_operator("==")( - prospective, prefix - ) - - @_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. - 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 .* - - # 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 = split_prospective[: len(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) - - # If the specifier does not have a local segment, then we want to - # act as if the prospective version also does not have a local - # segment. - if not spec_version.local: - prospective = Version(prospective.public) - - return prospective == spec_version - - @_require_version_compare - def _compare_not_equal(self, prospective: ParsedVersion, spec: str) -> bool: - return not self._compare_equal(prospective, spec) - - @_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) - - @_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) - - @_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) - - # Check to see if the prospective version is less than the spec - # version. If it's not we can short circuit and just return False now - # instead of doing extra unneeded work. - if not prospective < spec: - return False - - # This special case is here so that, unless the specifier itself - # includes is a pre-release version, that we do not accept pre-release - # versions for the version mentioned in the specifier (e.g. <3.1 should - # not match 3.1.dev0, but should match 3.0.dev0). - if not spec.is_prerelease and prospective.is_prerelease: - if Version(prospective.base_version) == Version(spec.base_version): - return False - - # If we've gotten to here, it means that prospective version is both - # less than the spec version *and* it's not a pre-release of the same - # version in the spec. - return True - - @_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) - - # Check to see if the prospective version is greater than the spec - # version. If it's not we can short circuit and just return False now - # instead of doing extra unneeded work. - if not prospective > spec: - return False - - # This special case is here so that, unless the specifier itself - # includes is a post-release version, that we do not accept - # post-release versions for the version mentioned in the specifier - # (e.g. >3.1 should not match 3.0.post0, but should match 3.2.post0). - if not spec.is_postrelease and prospective.is_postrelease: - if Version(prospective.base_version) == Version(spec.base_version): - return False - - # Ensure that we do not allow a local version of the version mentioned - # in the specifier, which is technically greater than, to match. - if prospective.local is not None: - if Version(prospective.base_version) == Version(spec.base_version): - return False - - # If we've gotten to here, it means that prospective version is both - # greater than the spec version *and* it's not a pre-release of the - # same version in the spec. - return True - - def _compare_arbitrary(self, prospective: Version, spec: str) -> bool: - return str(prospective).lower() == str(spec).lower() - - @property - 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 parse(version).is_prerelease: - return True - - return False - - @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]: - result: List[str] = [] - for item in version.split("."): - match = _prefix_regex.search(item) - if match: - result.extend(match.groups()) - else: - result.append(item) - return result - - -def _is_not_suffix(segment: str) -> bool: - return not any( - segment.startswith(prefix) for prefix in ("dev", "a", "b", "rc", "post") - ) - - -def _pad_version(left: List[str], right: List[str]) -> Tuple[List[str], List[str]]: - left_split, right_split = [], [] - - # Get the release segment of our versions - left_split.append(list(itertools.takewhile(lambda x: x.isdigit(), left))) - right_split.append(list(itertools.takewhile(lambda x: x.isdigit(), right))) - - # Get the rest of our versions - left_split.append(left[len(left_split[0]) :]) - right_split.append(right[len(right_split[0]) :]) - - # Insert our padding - left_split.insert(1, ["0"] * max(0, len(right_split[0]) - len(left_split[0]))) - right_split.insert(1, ["0"] * max(0, len(left_split[0]) - len(right_split[0]))) - - return (list(itertools.chain(*left_split)), list(itertools.chain(*right_split))) - - -class SpecifierSet(BaseSpecifier): - def __init__( - self, specifiers: str = "", prereleases: Optional[bool] = None - ) -> None: - - # 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()] - - # 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 - - def __repr__(self) -> str: - pre = ( - f", prereleases={self.prereleases!r}" - if self._prereleases is not None - else "" - ) - - return f"" - - def __str__(self) -> str: - return ",".join(sorted(str(s) for s in self._specs)) - - def __hash__(self) -> int: - return hash(self._specs) - - def __and__(self, other: Union["SpecifierSet", str]) -> "SpecifierSet": - if isinstance(other, str): - other = SpecifierSet(other) - elif not isinstance(other, SpecifierSet): - return NotImplemented - - specifier = SpecifierSet() - specifier._specs = frozenset(self._specs | other._specs) - - if self._prereleases is None and other._prereleases is not None: - specifier._prereleases = other._prereleases - elif self._prereleases is not None and other._prereleases is None: - specifier._prereleases = self._prereleases - elif self._prereleases == other._prereleases: - specifier._prereleases = self._prereleases - else: - raise ValueError( - "Cannot combine SpecifierSets with True and False prerelease " - "overrides." - ) - - return specifier - - def __eq__(self, other: object) -> bool: - if isinstance(other, (str, _IndividualSpecifier)): - other = SpecifierSet(str(other)) - elif not isinstance(other, SpecifierSet): - return NotImplemented - - return self._specs == other._specs - - def __len__(self) -> int: - return len(self._specs) - - 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 self.contains(item) - - def contains( - self, item: UnparsedVersion, prereleases: Optional[bool] = None - ) -> bool: - - # 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 - # SpecifierSet thinks for whether or not we should support prereleases. - if prereleases is None: - prereleases = self.prereleases - - # We can determine if we're going to allow pre-releases by looking to - # see if any of the underlying items supports them. If none of them do - # and this item is a pre-release then we do not allow it and we can - # short circuit that here. - # Note: This means that 1.0.dev1 would not be contained in something - # like >=1.0.devabc however it would be in >=1.0.debabc,>0.0.dev0 - if not prereleases and item.is_prerelease: - return False - - # We simply dispatch to the underlying specs here to make sure that the - # given version is contained within all of them. - # Note: This use of all() here means that an empty set of specifiers - # will always return True, this is an explicit design decision. - return all(s.contains(item, prereleases=prereleases) for s in self._specs) - - def filter( - self, iterable: Iterable[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. - if prereleases is None: - prereleases = self.prereleases - - # If we have any specifiers, then we want to wrap our iterable in the - # filter method for each one, this will act as a logical AND amongst - # each specifier. - if self._specs: - for spec in self._specs: - iterable = spec.filter(iterable, prereleases=bool(prereleases)) - return 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, and which will filter out LegacyVersion in general. - else: - filtered: List[VersionTypeVar] = [] - found_prereleases: List[VersionTypeVar] = [] - - item: UnparsedVersion - parsed_version: Union[Version, LegacyVersion] - - for item in iterable: - # 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 - if parsed_version.is_prerelease and not prereleases: - if not filtered: - found_prereleases.append(item) - else: - filtered.append(item) - - # If we've found no items except for pre-releases, then we'll go - # ahead and use the pre-releases - if not filtered and found_prereleases and prereleases is None: - return found_prereleases - - return filtered diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/tags.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/tags.py deleted file mode 100755 index 9a3d25a..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/tags.py +++ /dev/null @@ -1,487 +0,0 @@ -# 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. - -import logging -import platform -import sys -import sysconfig -from importlib.machinery import EXTENSION_SUFFIXES -from typing import ( - Dict, - FrozenSet, - Iterable, - Iterator, - List, - Optional, - Sequence, - Tuple, - Union, - cast, -) - -from . import _manylinux, _musllinux - -logger = logging.getLogger(__name__) - -PythonVersion = Sequence[int] -MacVersion = Tuple[int, int] - -INTERPRETER_SHORT_NAMES: Dict[str, str] = { - "python": "py", # Generic. - "cpython": "cp", - "pypy": "pp", - "ironpython": "ip", - "jython": "jy", -} - - -_32_BIT_INTERPRETER = sys.maxsize <= 2 ** 32 - - -class Tag: - """ - A representation of the tag triple for a wheel. - - Instances are considered immutable and thus are hashable. Equality checking - is also supported. - """ - - __slots__ = ["_interpreter", "_abi", "_platform", "_hash"] - - def __init__(self, interpreter: str, abi: str, platform: str) -> None: - self._interpreter = interpreter.lower() - self._abi = abi.lower() - self._platform = platform.lower() - # The __hash__ of every single element in a Set[Tag] will be evaluated each time - # that a set calls its `.disjoint()` method, which may be called hundreds of - # times when scanning a page of links for packages with tags matching that - # Set[Tag]. Pre-computing the value here produces significant speedups for - # downstream consumers. - self._hash = hash((self._interpreter, self._abi, self._platform)) - - @property - def interpreter(self) -> str: - return self._interpreter - - @property - def abi(self) -> str: - return self._abi - - @property - def platform(self) -> str: - return self._platform - - def __eq__(self, other: object) -> bool: - if not isinstance(other, Tag): - return NotImplemented - - return ( - (self._hash == other._hash) # Short-circuit ASAP for perf reasons. - and (self._platform == other._platform) - and (self._abi == other._abi) - and (self._interpreter == other._interpreter) - ) - - def __hash__(self) -> int: - return self._hash - - def __str__(self) -> str: - return f"{self._interpreter}-{self._abi}-{self._platform}" - - def __repr__(self) -> str: - return f"<{self} @ {id(self)}>" - - -def parse_tag(tag: str) -> FrozenSet[Tag]: - """ - Parses the provided tag (e.g. `py3-none-any`) into a frozenset of Tag instances. - - Returning a set is required due to the possibility that the tag is a - compressed tag set. - """ - tags = set() - interpreters, abis, platforms = tag.split("-") - for interpreter in interpreters.split("."): - for abi in abis.split("."): - for platform_ in platforms.split("."): - tags.add(Tag(interpreter, abi, platform_)) - return frozenset(tags) - - -def _get_config_var(name: str, warn: bool = False) -> 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 - ) - return value - - -def _normalize_string(string: str) -> str: - return string.replace(".", "_").replace("-", "_") - - -def _abi3_applies(python_version: PythonVersion) -> bool: - """ - Determine if the Python version supports abi3. - - PEP 384 was first implemented in Python 3.2. - """ - return len(python_version) > 1 and tuple(python_version) >= (3, 2) - - -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]) - debug = pymalloc = ucs4 = "" - with_debug = _get_config_var("Py_DEBUG", warn) - has_refcount = hasattr(sys, "gettotalrefcount") - # Windows doesn't set Py_DEBUG, so checking for support of debug-compiled - # extension modules is the best option. - # https://github.com/pypa/pip/issues/3383#issuecomment-173267692 - has_ext = "_d.pyd" in EXTENSION_SUFFIXES - if with_debug or (with_debug is None and (has_refcount or has_ext)): - debug = "d" - if py_version < (3, 8): - with_pymalloc = _get_config_var("WITH_PYMALLOC", warn) - if with_pymalloc or with_pymalloc is None: - pymalloc = "m" - if py_version < (3, 3): - unicode_size = _get_config_var("Py_UNICODE_SIZE", warn) - if unicode_size == 4 or ( - unicode_size is None and sys.maxunicode == 0x10FFFF - ): - ucs4 = "u" - elif debug: - # Debug builds can also load "normal" extension modules. - # We can also assume no UCS-4 or pymalloc requirement. - abis.append(f"cp{version}") - abis.insert( - 0, - "cp{version}{debug}{pymalloc}{ucs4}".format( - version=version, debug=debug, pymalloc=pymalloc, ucs4=ucs4 - ), - ) - return abis - - -def cpython_tags( - python_version: Optional[PythonVersion] = None, - abis: Optional[Iterable[str]] = None, - platforms: Optional[Iterable[str]] = None, - *, - warn: bool = False, -) -> Iterator[Tag]: - """ - Yields the tags for a CPython interpreter. - - The tags consist of: - - cp-- - - cp-abi3- - - cp-none- - - cp-abi3- # Older Python versions down to 3.2. - - If python_version only specifies a major version then user-provided ABIs and - the 'none' ABItag will be used. - - If 'abi3' or 'none' are specified in 'abis' then they will be yielded at - their normal position and not at the beginning. - """ - if not python_version: - python_version = sys.version_info[:2] - - interpreter = f"cp{_version_nodot(python_version[:2])}" - - if abis is None: - if len(python_version) > 1: - abis = _cpython_abis(python_version, warn) - else: - abis = [] - abis = list(abis) - # 'abi3' and 'none' are explicitly handled later. - for explicit_abi in ("abi3", "none"): - try: - abis.remove(explicit_abi) - except ValueError: - pass - - platforms = list(platforms or platform_tags()) - for abi in abis: - for platform_ in platforms: - yield Tag(interpreter, abi, platform_) - 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 _abi3_applies(python_version): - for minor_version in range(python_version[1] - 1, 1, -1): - for platform_ in platforms: - interpreter = "cp{version}".format( - version=_version_nodot((python_version[0], minor_version)) - ) - yield Tag(interpreter, "abi3", platform_) - - -def _generic_abi() -> Iterator[str]: - abi = sysconfig.get_config_var("SOABI") - if abi: - yield _normalize_string(abi) - - -def generic_tags( - interpreter: Optional[str] = None, - abis: Optional[Iterable[str]] = None, - platforms: Optional[Iterable[str]] = None, - *, - warn: bool = False, -) -> Iterator[Tag]: - """ - Yields the tags for a generic interpreter. - - The tags consist of: - - -- - - The "none" ABI will be added if it was not explicitly provided. - """ - if not interpreter: - interp_name = interpreter_name() - interp_version = interpreter_version(warn=warn) - interpreter = "".join([interp_name, interp_version]) - if abis is None: - abis = _generic_abi() - platforms = list(platforms or platform_tags()) - abis = list(abis) - if "none" not in abis: - abis.append("none") - for abi in abis: - for platform_ in platforms: - yield Tag(interpreter, abi, platform_) - - -def _py_interpreter_range(py_version: PythonVersion) -> Iterator[str]: - """ - Yields Python versions in descending order. - - After the latest version, the major-only version will be yielded, and then - all previous versions of that major version. - """ - if len(py_version) > 1: - yield f"py{_version_nodot(py_version[:2])}" - yield f"py{py_version[0]}" - if len(py_version) > 1: - for minor in range(py_version[1] - 1, -1, -1): - yield f"py{_version_nodot((py_version[0], minor))}" - - -def compatible_tags( - python_version: 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. - - The tags consist of: - - py*-none- - - -none-any # ... if `interpreter` is provided. - - py*-none-any - """ - if not python_version: - python_version = sys.version_info[:2] - platforms = list(platforms or platform_tags()) - for version in _py_interpreter_range(python_version): - for platform_ in platforms: - yield Tag(version, "none", platform_) - if interpreter: - yield Tag(interpreter, "none", "any") - for version in _py_interpreter_range(python_version): - yield Tag(version, "none", "any") - - -def _mac_arch(arch: str, is_32bit: bool = _32_BIT_INTERPRETER) -> str: - if not is_32bit: - return arch - - if arch.startswith("ppc"): - return "ppc" - - return "i386" - - -def _mac_binary_formats(version: MacVersion, cpu_arch: str) -> List[str]: - formats = [cpu_arch] - if cpu_arch == "x86_64": - if version < (10, 4): - return [] - formats.extend(["intel", "fat64", "fat32"]) - - elif cpu_arch == "i386": - if version < (10, 4): - return [] - formats.extend(["intel", "fat32", "fat"]) - - elif cpu_arch == "ppc64": - # TODO: Need to care about 32-bit PPC for ppc64 through 10.2? - if version > (10, 5) or version < (10, 4): - return [] - formats.append("fat64") - - elif cpu_arch == "ppc": - if version > (10, 6): - return [] - formats.extend(["fat32", "fat"]) - - if cpu_arch in {"arm64", "x86_64"}: - formats.append("universal2") - - if cpu_arch in {"x86_64", "i386", "ppc64", "ppc", "intel"}: - formats.append("universal") - - return formats - - -def mac_platforms( - version: Optional[MacVersion] = None, arch: Optional[str] = None -) -> Iterator[str]: - """ - Yields the platform tags for a macOS system. - - The `version` parameter is a two-item tuple specifying the macOS version to - generate platform tags for. The `arch` parameter is the CPU architecture to - generate platform tags for. Both parameters default to the appropriate value - for the current system. - """ - version_str, _, cpu_arch = platform.mac_ver() - if version is None: - version = cast("MacVersion", tuple(map(int, version_str.split(".")[:2]))) - else: - version = version - if arch is None: - arch = _mac_arch(cpu_arch) - else: - arch = arch - - if (10, 0) <= version and version < (11, 0): - # Prior to Mac OS 11, each yearly release of Mac OS bumped the - # "minor" version number. The major version was always 10. - for minor_version in range(version[1], -1, -1): - compat_version = 10, minor_version - binary_formats = _mac_binary_formats(compat_version, arch) - for binary_format in binary_formats: - 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. - for major_version in range(version[0], 10, -1): - compat_version = major_version, 0 - binary_formats = _mac_binary_formats(compat_version, arch) - for binary_format in binary_formats: - 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. - # Arm64 support was introduced in 11.0, so no Arm binaries from previous - # releases exist. - # - # However, the "universal2" binary format can have a - # macOS version earlier than 11.0 when the x86_64 part of the binary supports - # that version of macOS. - if arch == "x86_64": - for minor_version in range(16, 3, -1): - compat_version = 10, minor_version - binary_formats = _mac_binary_formats(compat_version, arch) - for binary_format in binary_formats: - 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 = 10, minor_version - binary_format = "universal2" - 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 is_32bit: - if linux == "linux_x86_64": - linux = "linux_i686" - elif linux == "linux_aarch64": - linux = "linux_armv7l" - _, arch = linux.split("_", 1) - yield from _manylinux.platform_tags(linux, arch) - yield from _musllinux.platform_tags(arch) - yield linux - - -def _generic_platforms() -> Iterator[str]: - yield _normalize_string(sysconfig.get_platform()) - - -def platform_tags() -> Iterator[str]: - """ - Provides the platform tags for this installation. - """ - if platform.system() == "Darwin": - return mac_platforms() - elif platform.system() == "Linux": - return _linux_platforms() - else: - return _generic_platforms() - - -def interpreter_name() -> str: - """ - Returns the name of the running interpreter. - """ - name = sys.implementation.name - return INTERPRETER_SHORT_NAMES.get(name) or name - - -def interpreter_version(*, warn: bool = False) -> str: - """ - Returns the version of the running interpreter. - """ - version = _get_config_var("py_version_nodot", warn=warn) - if version: - version = str(version) - else: - version = _version_nodot(sys.version_info[:2]) - return version - - -def _version_nodot(version: PythonVersion) -> str: - return "".join(map(str, version)) - - -def sys_tags(*, warn: bool = False) -> Iterator[Tag]: - """ - Returns the sequence of tag triples for the running interpreter. - - The order of the sequence corresponds to priority order for the - interpreter, from most to least important. - """ - - interp_name = interpreter_name() - if interp_name == "cp": - yield from cpython_tags(warn=warn) - else: - yield from generic_tags() - - if interp_name == "pp": - yield from compatible_tags(interpreter="pp3") - else: - yield from compatible_tags() diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/utils.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/utils.py deleted file mode 100755 index bab11b8..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/utils.py +++ /dev/null @@ -1,136 +0,0 @@ -# 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. - -import re -from typing import FrozenSet, NewType, Tuple, Union, cast - -from .tags import Tag, parse_tag -from .version import InvalidVersion, Version - -BuildTag = Union[Tuple[()], Tuple[int, str]] -NormalizedName = NewType("NormalizedName", str) - - -class InvalidWheelFilename(ValueError): - """ - An invalid wheel filename was found, users should refer to PEP 427. - """ - - -class InvalidSdistFilename(ValueError): - """ - An invalid sdist filename was found, users should refer to the packaging user guide. - """ - - -_canonicalize_regex = re.compile(r"[-_.]+") -# PEP 427: The build number must start with a digit. -_build_tag_regex = re.compile(r"(\d+)(.*)") - - -def canonicalize_name(name: str) -> NormalizedName: - # This is taken from PEP 503. - value = _canonicalize_regex.sub("-", name).lower() - return cast(NormalizedName, value) - - -def canonicalize_version(version: Union[Version, str]) -> str: - """ - 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 - - parts = [] - - # Epoch - if parsed.epoch != 0: - parts.append(f"{parsed.epoch}!") - - # Release segment - # NB: This strips trailing '.0's to normalize - parts.append(re.sub(r"(\.0)+$", "", ".".join(str(x) for x in parsed.release))) - - # Pre-release - if parsed.pre is not None: - parts.append("".join(str(x) for x in parsed.pre)) - - # 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}") - - return "".join(parts) - - -def parse_wheel_filename( - filename: str, -) -> Tuple[NormalizedName, Version, BuildTag, FrozenSet[Tag]]: - if not filename.endswith(".whl"): - raise InvalidWheelFilename( - f"Invalid wheel filename (extension must be '.whl'): {filename}" - ) - - filename = filename[:-4] - dashes = filename.count("-") - if dashes not in (4, 5): - raise InvalidWheelFilename( - 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 - if "__" in name_part or re.match(r"^[\w\d._]*$", name_part, re.UNICODE) is None: - raise InvalidWheelFilename(f"Invalid project name: {filename}") - name = canonicalize_name(name_part) - 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}'" - ) - build = cast(BuildTag, (int(build_match.group(1)), build_match.group(2))) - else: - build = () - tags = parse_tag(parts[-1]) - return (name, version, build, tags) - - -def parse_sdist_filename(filename: str) -> Tuple[NormalizedName, Version]: - if filename.endswith(".tar.gz"): - file_stem = filename[: -len(".tar.gz")] - elif filename.endswith(".zip"): - file_stem = filename[: -len(".zip")] - else: - raise InvalidSdistFilename( - f"Invalid sdist filename (extension must be '.tar.gz' or '.zip'):" - f" {filename}" - ) - - # 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}") - - name = canonicalize_name(name_part) - version = Version(version_part) - return (name, version) diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/version.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/version.py deleted file mode 100755 index de9a09a..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/packaging/version.py +++ /dev/null @@ -1,504 +0,0 @@ -# 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. - -import collections -import itertools -import re -import warnings -from typing import Callable, Iterator, List, Optional, SupportsInt, Tuple, Union - -from ._structures import Infinity, InfinityType, NegativeInfinity, NegativeInfinityType - -__all__ = ["parse", "Version", "LegacyVersion", "InvalidVersion", "VERSION_PATTERN"] - -InfiniteTypes = Union[InfinityType, NegativeInfinityType] -PrePostDevType = Union[InfiniteTypes, Tuple[str, int]] -SubLocalType = Union[InfiniteTypes, int, str] -LocalType = Union[ - NegativeInfinityType, - Tuple[ - Union[ - SubLocalType, - Tuple[SubLocalType, str], - Tuple[NegativeInfinityType, SubLocalType], - ], - ..., - ], -] -CmpKey = Tuple[ - int, Tuple[int, ...], PrePostDevType, PrePostDevType, PrePostDevType, LocalType -] -LegacyCmpKey = Tuple[int, Tuple[str, ...]] -VersionComparisonMethod = Callable[ - [Union[CmpKey, LegacyCmpKey], Union[CmpKey, LegacyCmpKey]], bool -] - -_Version = collections.namedtuple( - "_Version", ["epoch", "release", "dev", "pre", "post", "local"] -) - - -def parse(version: str) -> Union["LegacyVersion", "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): - """ - An invalid version was found, users should refer to PEP 440. - """ - - -class _BaseVersion: - _key: Union[CmpKey, LegacyCmpKey] - - def __hash__(self) -> int: - return hash(self._key) - - # Please keep the duplicated `isinstance` check - # in the six comparisons hereunder - # unless you find a way to avoid adding overhead function calls. - def __lt__(self, other: "_BaseVersion") -> bool: - if not isinstance(other, _BaseVersion): - return NotImplemented - - return self._key < other._key - - def __le__(self, other: "_BaseVersion") -> bool: - if not isinstance(other, _BaseVersion): - return NotImplemented - - return self._key <= other._key - - def __eq__(self, other: object) -> bool: - if not isinstance(other, _BaseVersion): - return NotImplemented - - return self._key == other._key - - def __ge__(self, other: "_BaseVersion") -> bool: - if not isinstance(other, _BaseVersion): - return NotImplemented - - return self._key >= other._key - - def __gt__(self, other: "_BaseVersion") -> bool: - if not isinstance(other, _BaseVersion): - return NotImplemented - - return self._key > other._key - - def __ne__(self, other: object) -> bool: - if not isinstance(other, _BaseVersion): - return NotImplemented - - return self._key != other._key - - -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""" - v? - (?: - (?:(?P[0-9]+)!)? # epoch - (?P[0-9]+(?:\.[0-9]+)*) # release segment - (?P
                                          # pre-release
-            [-_\.]?
-            (?P(a|b|c|rc|alpha|beta|pre|preview))
-            [-_\.]?
-            (?P[0-9]+)?
-        )?
-        (?P                                         # post release
-            (?:-(?P[0-9]+))
-            |
-            (?:
-                [-_\.]?
-                (?Ppost|rev|r)
-                [-_\.]?
-                (?P[0-9]+)?
-            )
-        )?
-        (?P                                          # dev release
-            [-_\.]?
-            (?Pdev)
-            [-_\.]?
-            (?P[0-9]+)?
-        )?
-    )
-    (?:\+(?P[a-z0-9]+(?:[-_\.][a-z0-9]+)*))?       # local version
-"""
-
-
-class Version(_BaseVersion):
-
-    _regex = re.compile(r"^\s*" + VERSION_PATTERN + r"\s*$", re.VERBOSE | re.IGNORECASE)
-
-    def __init__(self, version: str) -> None:
-
-        # Validate the version and parse it into pieces
-        match = self._regex.search(version)
-        if not match:
-            raise InvalidVersion(f"Invalid version: '{version}'")
-
-        # Store the parsed out pieces of the version
-        self._version = _Version(
-            epoch=int(match.group("epoch")) if match.group("epoch") else 0,
-            release=tuple(int(i) for i in match.group("release").split(".")),
-            pre=_parse_letter_version(match.group("pre_l"), match.group("pre_n")),
-            post=_parse_letter_version(
-                match.group("post_l"), match.group("post_n1") or match.group("post_n2")
-            ),
-            dev=_parse_letter_version(match.group("dev_l"), match.group("dev_n")),
-            local=_parse_local_version(match.group("local")),
-        )
-
-        # Generate a key which will be used for sorting
-        self._key = _cmpkey(
-            self._version.epoch,
-            self._version.release,
-            self._version.pre,
-            self._version.post,
-            self._version.dev,
-            self._version.local,
-        )
-
-    def __repr__(self) -> str:
-        return f""
-
-    def __str__(self) -> str:
-        parts = []
-
-        # Epoch
-        if self.epoch != 0:
-            parts.append(f"{self.epoch}!")
-
-        # Release segment
-        parts.append(".".join(str(x) for x in self.release))
-
-        # Pre-release
-        if self.pre is not None:
-            parts.append("".join(str(x) for x in self.pre))
-
-        # Post-release
-        if self.post is not None:
-            parts.append(f".post{self.post}")
-
-        # Development release
-        if self.dev is not None:
-            parts.append(f".dev{self.dev}")
-
-        # Local version segment
-        if self.local is not None:
-            parts.append(f"+{self.local}")
-
-        return "".join(parts)
-
-    @property
-    def epoch(self) -> int:
-        _epoch: int = self._version.epoch
-        return _epoch
-
-    @property
-    def release(self) -> Tuple[int, ...]:
-        _release: Tuple[int, ...] = self._version.release
-        return _release
-
-    @property
-    def pre(self) -> Optional[Tuple[str, int]]:
-        _pre: Optional[Tuple[str, int]] = self._version.pre
-        return _pre
-
-    @property
-    def post(self) -> Optional[int]:
-        return self._version.post[1] if self._version.post else None
-
-    @property
-    def dev(self) -> Optional[int]:
-        return self._version.dev[1] if self._version.dev else None
-
-    @property
-    def local(self) -> Optional[str]:
-        if self._version.local:
-            return ".".join(str(x) for x in self._version.local)
-        else:
-            return None
-
-    @property
-    def public(self) -> str:
-        return str(self).split("+", 1)[0]
-
-    @property
-    def base_version(self) -> str:
-        parts = []
-
-        # Epoch
-        if self.epoch != 0:
-            parts.append(f"{self.epoch}!")
-
-        # Release segment
-        parts.append(".".join(str(x) for x in self.release))
-
-        return "".join(parts)
-
-    @property
-    def is_prerelease(self) -> bool:
-        return self.dev is not None or self.pre is not None
-
-    @property
-    def is_postrelease(self) -> bool:
-        return self.post is not None
-
-    @property
-    def is_devrelease(self) -> bool:
-        return self.dev is not None
-
-    @property
-    def major(self) -> int:
-        return self.release[0] if len(self.release) >= 1 else 0
-
-    @property
-    def minor(self) -> int:
-        return self.release[1] if len(self.release) >= 2 else 0
-
-    @property
-    def micro(self) -> int:
-        return self.release[2] if len(self.release) >= 3 else 0
-
-
-def _parse_letter_version(
-    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.
-        if number is None:
-            number = 0
-
-        # We normalize any letters to their lower case form
-        letter = letter.lower()
-
-        # We consider some words to be alternate spellings of other words and
-        # in those cases we want to normalize the spellings to our preferred
-        # spelling.
-        if letter == "alpha":
-            letter = "a"
-        elif letter == "beta":
-            letter = "b"
-        elif letter in ["c", "pre", "preview"]:
-            letter = "rc"
-        elif letter in ["rev", "r"]:
-            letter = "post"
-
-        return letter, int(number)
-    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"
-
-        return letter, int(number)
-
-    return None
-
-
-_local_version_separators = re.compile(r"[\._-]")
-
-
-def _parse_local_version(local: str) -> Optional[LocalType]:
-    """
-    Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").
-    """
-    if local is not None:
-        return tuple(
-            part.lower() if not part.isdigit() else int(part)
-            for part in _local_version_separators.split(local)
-        )
-    return None
-
-
-def _cmpkey(
-    epoch: int,
-    release: Tuple[int, ...],
-    pre: 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
-    # re-reverse it back into the correct order and make it a tuple and use
-    # that for our sorting key.
-    _release = tuple(
-        reversed(list(itertools.dropwhile(lambda x: x == 0, reversed(release))))
-    )
-
-    # We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0.
-    # We'll do this by abusing the pre segment, but we _only_ want to do this
-    # if there is not a pre or a post segment. If we have one of those then
-    # the normal sorting rules will handle this case correctly.
-    if pre is None and post is None and dev is not None:
-        _pre: PrePostDevType = NegativeInfinity
-    # Versions without a pre-release (except as noted above) should sort after
-    # those with one.
-    elif pre is None:
-        _pre = Infinity
-    else:
-        _pre = pre
-
-    # Versions without a post segment should sort before those with one.
-    if post is None:
-        _post: PrePostDevType = NegativeInfinity
-
-    else:
-        _post = post
-
-    # Versions without a development segment should sort after those with one.
-    if dev is None:
-        _dev: PrePostDevType = Infinity
-
-    else:
-        _dev = dev
-
-    if local is None:
-        # Versions without a local segment should sort before those with one.
-        _local: LocalType = NegativeInfinity
-    else:
-        # Versions with a local segment need that segment parsed to implement
-        # the sorting rules in PEP440.
-        # - Alpha numeric segments sort before numeric segments
-        # - Alpha numeric segments sort lexicographically
-        # - Numeric segments sort numerically
-        # - Shorter versions sort before longer versions when the prefixes
-        #   match exactly
-        _local = tuple(
-            (i, "") if isinstance(i, int) else (NegativeInfinity, i) for i in local
-        )
-
-    return epoch, _release, _pre, _post, _dev, _local
diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/__init__.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/__init__.py
deleted file mode 100755
index aef2821..0000000
--- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/__init__.py
+++ /dev/null
@@ -1,342 +0,0 @@
-"""
-Utilities for determining application-specific dirs. See  for details and
-usage.
-"""
-from __future__ import annotations
-
-import os
-import sys
-from pathlib import Path
-
-if sys.version_info >= (3, 8):  # pragma: no cover (py38+)
-    from typing import Literal
-else:  # pragma: no cover (py38+)
-    from ..typing_extensions import Literal
-
-from .api import PlatformDirsABC
-from .version import __version__
-from .version import __version_tuple__ as __version_info__
-
-
-def _set_platform_dir_class() -> type[PlatformDirsABC]:
-    if sys.platform == "win32":
-        from .windows import Windows as Result
-    elif sys.platform == "darwin":
-        from .macos import MacOS as Result
-    else:
-        from .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
-
-        from .android import _android_folder
-
-        if _android_folder() is not None:
-            from .android import Android
-
-            return Android  # return to avoid redefinition of result
-
-    return Result
-
-
-PlatformDirs = _set_platform_dir_class()  #: Currently active platform
-AppDirs = PlatformDirs  #: Backwards compatibility with appdirs
-
-
-def user_data_dir(
-    appname: str | None = None,
-    appauthor: str | None | Literal[False] = None,
-    version: str | None = None,
-    roaming: bool = False,
-) -> str:
-    """
-    :param appname: See `appname `.
-    :param appauthor: See `appauthor `.
-    :param version: See `version `.
-    :param roaming: See `roaming `.
-    :returns: data directory tied to the user
-    """
-    return PlatformDirs(appname=appname, appauthor=appauthor, version=version, roaming=roaming).user_data_dir
-
-
-def site_data_dir(
-    appname: str | None = None,
-    appauthor: str | None | Literal[False] = None,
-    version: str | None = None,
-    multipath: bool = False,
-) -> str:
-    """
-    :param appname: See `appname `.
-    :param appauthor: See `appauthor `.
-    :param version: See `version `.
-    :param multipath: See `roaming `.
-    :returns: data directory shared by users
-    """
-    return PlatformDirs(appname=appname, appauthor=appauthor, version=version, multipath=multipath).site_data_dir
-
-
-def user_config_dir(
-    appname: str | None = None,
-    appauthor: str | None | Literal[False] = None,
-    version: str | None = None,
-    roaming: bool = False,
-) -> str:
-    """
-    :param appname: See `appname `.
-    :param appauthor: See `appauthor `.
-    :param version: See `version `.
-    :param roaming: See `roaming `.
-    :returns: config directory tied to the user
-    """
-    return PlatformDirs(appname=appname, appauthor=appauthor, version=version, roaming=roaming).user_config_dir
-
-
-def site_config_dir(
-    appname: str | None = None,
-    appauthor: str | None | Literal[False] = None,
-    version: str | None = None,
-    multipath: bool = False,
-) -> str:
-    """
-    :param appname: See `appname `.
-    :param appauthor: See `appauthor `.
-    :param version: See `version `.
-    :param multipath: See `roaming `.
-    :returns: config directory shared by the users
-    """
-    return PlatformDirs(appname=appname, appauthor=appauthor, version=version, multipath=multipath).site_config_dir
-
-
-def user_cache_dir(
-    appname: str | None = None,
-    appauthor: str | None | Literal[False] = None,
-    version: str | None = None,
-    opinion: bool = True,
-) -> str:
-    """
-    :param appname: See `appname `.
-    :param appauthor: See `appauthor `.
-    :param version: See `version `.
-    :param opinion: See `roaming `.
-    :returns: cache directory tied to the user
-    """
-    return PlatformDirs(appname=appname, appauthor=appauthor, version=version, opinion=opinion).user_cache_dir
-
-
-def user_state_dir(
-    appname: str | None = None,
-    appauthor: str | None | Literal[False] = None,
-    version: str | None = None,
-    roaming: bool = False,
-) -> str:
-    """
-    :param appname: See `appname `.
-    :param appauthor: See `appauthor `.
-    :param version: See `version `.
-    :param roaming: See `roaming `.
-    :returns: state directory tied to the user
-    """
-    return PlatformDirs(appname=appname, appauthor=appauthor, version=version, roaming=roaming).user_state_dir
-
-
-def user_log_dir(
-    appname: str | None = None,
-    appauthor: str | None | Literal[False] = None,
-    version: str | None = None,
-    opinion: bool = True,
-) -> str:
-    """
-    :param appname: See `appname `.
-    :param appauthor: See `appauthor `.
-    :param version: See `version `.
-    :param opinion: See `roaming `.
-    :returns: log directory tied to the user
-    """
-    return PlatformDirs(appname=appname, appauthor=appauthor, version=version, opinion=opinion).user_log_dir
-
-
-def user_documents_dir() -> str:
-    """
-    :returns: documents directory tied to the user
-    """
-    return PlatformDirs().user_documents_dir
-
-
-def user_runtime_dir(
-    appname: str | None = None,
-    appauthor: str | None | Literal[False] = None,
-    version: str | None = None,
-    opinion: bool = True,
-) -> str:
-    """
-    :param appname: See `appname `.
-    :param appauthor: See `appauthor `.
-    :param version: See `version `.
-    :param opinion: See `opinion `.
-    :returns: runtime directory tied to the user
-    """
-    return PlatformDirs(appname=appname, appauthor=appauthor, version=version, opinion=opinion).user_runtime_dir
-
-
-def user_data_path(
-    appname: str | None = None,
-    appauthor: str | None | Literal[False] = None,
-    version: str | None = None,
-    roaming: bool = False,
-) -> Path:
-    """
-    :param appname: See `appname `.
-    :param appauthor: See `appauthor `.
-    :param version: See `version `.
-    :param roaming: See `roaming `.
-    :returns: data path tied to the user
-    """
-    return PlatformDirs(appname=appname, appauthor=appauthor, version=version, roaming=roaming).user_data_path
-
-
-def site_data_path(
-    appname: str | None = None,
-    appauthor: str | None | Literal[False] = None,
-    version: str | None = None,
-    multipath: bool = False,
-) -> Path:
-    """
-    :param appname: See `appname `.
-    :param appauthor: See `appauthor `.
-    :param version: See `version `.
-    :param multipath: See `multipath `.
-    :returns: data path shared by users
-    """
-    return PlatformDirs(appname=appname, appauthor=appauthor, version=version, multipath=multipath).site_data_path
-
-
-def user_config_path(
-    appname: str | None = None,
-    appauthor: str | None | Literal[False] = None,
-    version: str | None = None,
-    roaming: bool = False,
-) -> Path:
-    """
-    :param appname: See `appname `.
-    :param appauthor: See `appauthor `.
-    :param version: See `version `.
-    :param roaming: See `roaming `.
-    :returns: config path tied to the user
-    """
-    return PlatformDirs(appname=appname, appauthor=appauthor, version=version, roaming=roaming).user_config_path
-
-
-def site_config_path(
-    appname: str | None = None,
-    appauthor: str | None | Literal[False] = None,
-    version: str | None = None,
-    multipath: bool = False,
-) -> Path:
-    """
-    :param appname: See `appname `.
-    :param appauthor: See `appauthor `.
-    :param version: See `version `.
-    :param multipath: See `roaming `.
-    :returns: config path shared by the users
-    """
-    return PlatformDirs(appname=appname, appauthor=appauthor, version=version, multipath=multipath).site_config_path
-
-
-def user_cache_path(
-    appname: str | None = None,
-    appauthor: str | None | Literal[False] = None,
-    version: str | None = None,
-    opinion: bool = True,
-) -> Path:
-    """
-    :param appname: See `appname `.
-    :param appauthor: See `appauthor `.
-    :param version: See `version `.
-    :param opinion: See `roaming `.
-    :returns: cache path tied to the user
-    """
-    return PlatformDirs(appname=appname, appauthor=appauthor, version=version, opinion=opinion).user_cache_path
-
-
-def user_state_path(
-    appname: str | None = None,
-    appauthor: str | None | Literal[False] = None,
-    version: str | None = None,
-    roaming: bool = False,
-) -> Path:
-    """
-    :param appname: See `appname `.
-    :param appauthor: See `appauthor `.
-    :param version: See `version `.
-    :param roaming: See `roaming `.
-    :returns: state path tied to the user
-    """
-    return PlatformDirs(appname=appname, appauthor=appauthor, version=version, roaming=roaming).user_state_path
-
-
-def user_log_path(
-    appname: str | None = None,
-    appauthor: str | None | Literal[False] = None,
-    version: str | None = None,
-    opinion: bool = True,
-) -> Path:
-    """
-    :param appname: See `appname `.
-    :param appauthor: See `appauthor `.
-    :param version: See `version `.
-    :param opinion: See `roaming `.
-    :returns: log path tied to the user
-    """
-    return PlatformDirs(appname=appname, appauthor=appauthor, version=version, opinion=opinion).user_log_path
-
-
-def user_documents_path() -> Path:
-    """
-    :returns: documents path tied to the user
-    """
-    return PlatformDirs().user_documents_path
-
-
-def user_runtime_path(
-    appname: str | None = None,
-    appauthor: str | None | Literal[False] = None,
-    version: str | None = None,
-    opinion: bool = True,
-) -> Path:
-    """
-    :param appname: See `appname `.
-    :param appauthor: See `appauthor `.
-    :param version: See `version `.
-    :param opinion: See `opinion `.
-    :returns: runtime path tied to the user
-    """
-    return PlatformDirs(appname=appname, appauthor=appauthor, version=version, opinion=opinion).user_runtime_path
-
-
-__all__ = [
-    "__version__",
-    "__version_info__",
-    "PlatformDirs",
-    "AppDirs",
-    "PlatformDirsABC",
-    "user_data_dir",
-    "user_config_dir",
-    "user_cache_dir",
-    "user_state_dir",
-    "user_log_dir",
-    "user_documents_dir",
-    "user_runtime_dir",
-    "site_data_dir",
-    "site_config_dir",
-    "user_data_path",
-    "user_config_path",
-    "user_cache_path",
-    "user_state_path",
-    "user_log_path",
-    "user_documents_path",
-    "user_runtime_path",
-    "site_data_path",
-    "site_config_path",
-]
diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/__main__.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/__main__.py
deleted file mode 100755
index 0fc1edd..0000000
--- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/__main__.py
+++ /dev/null
@@ -1,46 +0,0 @@
-from __future__ import annotations
-
-from platformdirs import PlatformDirs, __version__
-
-PROPS = (
-    "user_data_dir",
-    "user_config_dir",
-    "user_cache_dir",
-    "user_state_dir",
-    "user_log_dir",
-    "user_documents_dir",
-    "user_runtime_dir",
-    "site_data_dir",
-    "site_config_dir",
-)
-
-
-def main() -> None:
-    app_name = "MyApp"
-    app_author = "MyCompany"
-
-    print(f"-- platformdirs {__version__} --")
-
-    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)}")
-
-    print("\n-- app dirs (without optional 'version')")
-    dirs = PlatformDirs(app_name, app_author)
-    for prop in PROPS:
-        print(f"{prop}: {getattr(dirs, prop)}")
-
-    print("\n-- app dirs (without optional 'appauthor')")
-    dirs = PlatformDirs(app_name)
-    for prop in PROPS:
-        print(f"{prop}: {getattr(dirs, prop)}")
-
-    print("\n-- app dirs (with disabled 'appauthor')")
-    dirs = PlatformDirs(app_name, appauthor=False)
-    for prop in PROPS:
-        print(f"{prop}: {getattr(dirs, prop)}")
-
-
-if __name__ == "__main__":
-    main()
diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/__pycache__/__init__.cpython-311.pyc
deleted file mode 100755
index cf2942f33d23b799b4182a34a56afde3aeb7a111..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 12830
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
Qjs=#Ol9=Q1k4}gF52IJVng9R*

diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/__pycache__/__main__.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/__pycache__/__main__.cpython-311.pyc
deleted file mode 100755
index 89fcb1fed6c9477aabe94e1075e1cde3b0b922f1..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2122
zcmcgt-D}%c6u*+LZP~Juth7s0_TiR=R9kH|E_Id>24h(mg=V37^B6+46i1DvE3V`W
z8wWh-Lm$f6!(gK&kf&@Teb}EO4Lt-wpfL8ZH$&d~)N>`j2R9-A-L0fK>UJqq;pMVaW#%(G~eVcp(a?khJhDqDLt#F
zAL3ft$mp4!*p}vbWTX$l`e=xWKv&$1mz?{TNo6jQG}|Vg=9$EHWj@MpG&OIFP;1qs
zZX~Jdu0dTmQ&l+|6}Z<&o)FqH_j`nEB~yMUhX`S`p^6735K
z8mYG|!}i?RVkVZ+mhG8VVpDKUW2PR5KXv9b^$M+vx}2VVmN^8kN3fEy$9w4^
zjnFFk?xQ_n9J4EcU(sXH4n~*n3WpHa(I~d3=xkh%=f_d>?3*H+L_DXca{nFGe+z}SbH{ot)29gf{S+OJM&e)Qc_geE$-lPg4
zXf1D>Q1EsAtTKe>YWJIlUR)T{T!V{;oR(WwzVLhbeX!RYfVYrI3(@?45k`}E42My2G3020Euc)e}na~5vPCLSkq#uCW
z3$WZDp;h$I@$|dBuaDn(uXpDkob_|1{cmAQW`N5fF8jC~pDYHr65@)FD<{(Iuj0YS
ze;U5D5=bkdw9;EWnYq+QTR9NtrtIi0pTkkj^lX=$o~+S

diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/__pycache__/android.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/__pycache__/android.cpython-311.pyc
deleted file mode 100755
index 61e71965eca0248e9c1d764b25c60d23c636c189..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 6364
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

diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/__pycache__/macos.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/__pycache__/macos.cpython-311.pyc
deleted file mode 100755
index af7f4ba0fcf2e6c2adb96ed8c5d14131eb624c6b..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 4601
zcmc&%OK;Rx6t?FT=jkW}=!3QnrHfHv94ng&p{Ni9q2iG?5YiFgG2=Ur;K%gZ6Pl<(
zS+MA$%c_yO%8ClHZU4s%8i~p)q^{^{P}&Wvo^$;e51ypZF5*d!?eCs@eeQR@dwl)N
z`1lA1N9V_%*HpOr18>43>tFD@i*T{c>733RoXHn?9avn<=y+`4T!S6}cxC@vYATd}Em
zzD}L9=N8KT2)+#lvm8GS;}Jj^_TmM2l4VwU0A1P&pBe=dO!
zF?=Y23k(+$_%OqV6ZilI&mbRO>%2QGSOGE8-xP6R#kE~9G92{>4I$-_I-!>RGW2Ov&uxOP}`JBXB!QJ
zNV;8an#A&R!k%-c=DH2%v@GjnoftS|K||L<**0aPewS)=L)K`yR$nJ_Uw8RJ-5^&q
zOREwbQeLp(X$`lj8LVZQ#k552D%DIAqPz$J5t&VM6>=X=Dv1CTPr-zp$(JoD5^h>%>||{mG3Dw`N;&1x1max=T(qwDLWWoFg~x
zRaHtHyGhG%2hX&0o62!bz@TN@DKs{`aeT0fM5!Q_%|lFug+6c+qH*$IwzzJNo1A_o
z&OQ}qf1CRC=rd*Esj|>IueTM_QAk^?bi_(asO)0K`jmjVWJ)**7kew=_3W~ImiEf0
zQ`0D9^zH^O0_sHReCuo;+pouCo{mA#l+nO4L#N>08%NR;%=LkX!OwXYOdoSCWE7%VTn#dYadewvu18Z9G7jYQm?+LMVYM=L}peM|!Iz?n*~t@(Er=CO$t5
zrpd!GP4?jTklTG#d8@75?kKn0;+>9orzPA;a{Yf)d1G(Jdb-3{(jMB36A@MzC@j;F
z6k`tb$Uvf))_RO=21LCEe}qI05aGqPxY!XFTf$>l49r16V(-E?s@x0M
zWw87vd-C(W1`BV(7aoqobT=K>U5K9eSJ|z!m75*qW?NkCh^sAOHOVd(5mpSbq+l^z
zgR_4?!Q(g2MLamLAK9M=2jBOaBb8Y2VI42!d3p#&Oe`*cj%?V(93vE0l`{?|C|ezI
zrX|cI=W#G9`6^<^u-~#yUAC)(6*AFN2>J}x#~7m+9?F=Tim4;O3dq~OCFy!wxzSN>
zw8fQ2nxtn{&a2$6B=M*@-quVH=(YzC0Hqw!$r{^JeSne6S&QpeT(#
zkfYmtnxZu51R4>|>o3MBUy5OW#@0JAwxU3=We!Ggu$FIef5YZt>WBN!#F?k!%+9H{
zINK3tTf%ITq=OM&HKLL>Ew>Kq?!OeM>%@dzC44(vf)A6yYW%3D#-OV8cN#3uNk)4R
z8YBHkjPw}(8B)HlOi5d*bd*Y4taij|OQ^C8T+OGbfcYKFG!tBIqMJ%(t9+O1*_Ua6AFc)sLg4cy^9gOt2cXbL
zWj>*e`2ZC9Tw*?aJ~pLnD@KZFUcG~p8u5=^l`u?pa&;lq;RQe;`dTx*5_9-ktF`&yQ_
zSHc-z9P?BL3~QLv1k+9PJpVg)yw(5roEzR^zvrCP>i_HJ=6DQpu>JnpOV;vNyxrot
Q>{vIQ8cl5t;g5y&4{Ml%NB{r;

diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/__pycache__/unix.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/__pycache__/unix.cpython-311.pyc
deleted file mode 100755
index d903ad67de7cb4eb748c26470b10217ba0e21fa4..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 11033
zcmds7U2GdycD^(Gl|*VJQF7!&R>rZkF=d&IWyeY!*?}y1Z8^4_T5>nhVoQ!SBWYxk
z!`>NL79lG_;KeF|i}eQH+Q=r23MAQhlWqO5Es8!A-F@m)K?(#U3}8S&u@C#kz`JPR
zm-d`H)R05cii{eIBA3HEGiT2I|L!^Go_l{84Av6}`P(1P{?D_7{1?7#1&{T>J^WXA
zxI<(ja|x2)&I*DNaw
zb6st)@^;3u?{kijFX3+m>Vtg!2|gK^2yi6jmRsb88}5k!Pfim#aD&J}rS5YVq=3H_
zCW3NEZU&x4IXKNt2r@rL!mWS6k73SikWwklkPKBz>7(!-7}8Qx>hzlu)fEcw?l&c4
z<_}mrya;b5Bx6dW$zhf1gC~bfPeM)2U4t*)X~mdRWz$RHPE)2!O&OC``Bse8fj{?9
zgoiuCup3063!P1TmkaZwnGStMn@h-|mP#y$mlbhNSMWtVS1d7baV}-3N#zu!8ofsz
zVlj^{M`yI85=}~UQj4C|rnSRSDV>g9RZ>@@3H5R`y(+8mvPw-_XlH5yG9n=3!2VOHNu154AC-q(D-cjxmR?|w$FtD@I2dVLkWp3wnA73DWDdZ3CPVDw-WJ;>;dRrE%nKO;9)(FH~a
zTvn9ZB)7{UXkWA33OL=#27_L4UJ<9XL_(VvjTwb8#NQe|
zEuNGBEh-hq(#oVbFk={L{a7@r!<#y#PFiS>Oi@LV75$2#r6U@hj$XDB9Yi+A%RzvF
zq8pJJBbhi6k441s8AU`cQNp5iR<3qcp;VRC)U*gCE0cysRYe!)Rbxg3_^DJ&C6$yR
zUX`dST}~*vm5p*uN~YmW1h~(O5>>DvqO43wa|vWl%qe;=l%u7lbyc>$rlh1IYE!IO
z5!Gh^pV6)&2%=rZF^$JXjoR5mf-abXvEjk-!PuD#=TFs2U~`*62d_yojn3lk
z`AlBZO4EW6)218oW7aFz(o#ysDw`cKs2s>{yu}dHG57+~oT2m{Z@P6Q
zF-1F|pL859QKU_9GlQ5ohW!zPxtnQ02@`S9Ix)!@M9bt)0n*fRGxO7>_m}Q!U(lS;
zmlyh0+#5pZrN_IpQjq5gcRe`OfB)`geWgqQBO
z=7ghp;b_)>)Y29<%%Bh(j=zDIKN}pIWLIrK{({Kvk6jFKHKADpa31MxXplY3wK0eC
zkzq;}FE5}}qPn^!qeDw{UYpfS1&aFS`NEGAQ5$}a4s?Z8BLV+2+$q0d2N`mothW3wrSnkvTnB8Eiz
zJbZV~5;U1AXNiLr#v~UYf?3kElUZ_nBQ)^Yg*buh|O&Dzfu@|1s%%-T|0uU`b?Oy+;gV~1Jc
zI=@1uIN5c>zsL_0r!2qD*Dhlfr*c(TF^Ur1p_+U^2%+VObMxoi9WqT8
z$&Zd)=icL2fl?hFQxUsquCrP{<8Qt^Mkw03VK+q)XkiHDC*6Zom&r$7GPyJr
z;Z4UPL~)tP)JOFL2~{^HwPgB4Cd>qCCBh;DY)a@S;9-mP80PZ|MBglvY^zkfE{@$A
zUvE3Q)^_xt=x^rN`$yLLNB(1PuK!%V|6H!^e7^0x&C8$?_JE2=Csf0#Zx`fe*4aYE
zbkAyPD(qsFW~egj5b-gr1#3jSs2FHBq|CI{to>1}=?|@%ZnU=FIs3uckLgF5Tx(Ch
zwP&Rc1pUn=R0J<>wC`QryE?eK@1w?*kqx^|@bH5;R6Exyi_?h4WSs5(QEQ_Eo9r3
zHp^jJvJCvuV&br;mKDInTn+3p-Cjaz#=>p|^$cQn2qK5h-wwN-8=*bh=y`|sL$rWe
z;U0cx<=t(2@JjMdnnWK!(TlMC%4`yOYhj{7+AT%ds%&U*=*+1dh`UB6?rdgD+WAr1
zVR?@cc8!*>Lk=eELS?dUi+Bm)QbW{5?(;d}a9%iECF=UhMcr&JbSNJ>^u(g>I}4w?
z)$q~5ox4-`6c;6!Vh12%5E>gF9N#g7O3W67%2xMS=C(j$?WhEjO^hRu#vyX7$g`b~
z2h!77l3#`*VWmN4;cf+77?-?6R5Z#|Txmt|n3Vtr-fuAco!%o@5Ad0V>XA)oCFf!-
zv7n=4P}0RXn~0^Z5@AsdUVgFY3}eezB>_v^cpS3C^>9j54ZA$k1yoQKuR;4vUolac
z=^p`lwYmtfLLns^vgXpBgoq19D0xSooR*PE%tca&dY3OK9CDTm(HIW9UqHtLZe;#
zRarbZ7v8C6xOi!FeB}HogjTI2cC9QcwT#=sVSTCO+TJQ_>y7y#s+?0z3|_@%GH_YT
z_Db@*(8*gas*)pjJ9G8GMyTgA@8A1B^=CspaBX9IP@M7(`xRXx%zj080jiBvxL1dA
z1>%$nAQ8BXY>y-J*)vyVh2t~=J7cg>YWeoXDVTf)h;$_hK1kTiL-{aV1*U@8Lbf7nu+YaGaOD1Y{^ip-;Y?mQll7meo{>+d1840HEG{1_x)2??h!p*4
zbR!*sM$(rtI*V;C>!+sj#S`l(3#FCh4=`QLz8c91XY<0@tp6@c_4&t
zjlB2H&3Cf?PS%5?PzBr+q#>-1+tO+HTt+Q&unN0bT^YB#mxFxEUC$J
z2_+UY1F_g&&q)ck6%{jmu^8w%Ap6r)ODoh^pnI_-oK@B$ybqrkbY8(Hw7}@=7!6}|
z8lyKbI*$><8G2_~Lzvr@w%{v9_}Bjd#(CNP75F-jzd$hBMZAp#-tXxzkge!z7tn6J
zWl>w%_j=EP0@;e}??`C(czO!N88!Z2^W0JTt?IIh+jT;!RcD{4wLrEa`#Ta^if!71
zZL%W!I}+M=R6g$+;Q(QFY-hnpewGLCd4ut6#brD|^1D6H7sz8GYbbH>OxG1<7E^$vk-m?kg07)8LqOZ_%rlCXW3_BW*tmx20?Q42rGZ(6AdLbJ{N;2WEqd*riSQ7Olyi$z*4*q&Klc>Lk^~dQ?
z&V6|9*RA(Z7SyO(Y!vkm*;+6X;!>&T|i
zc1yW={q9&^*t;&gxF)>#g)1lY=7ruB_a+>1SbTr+?&;4ie)@y;?*6sz{(o`hx(D*z
z13BS%UO3KtcPkB>4Z_M19S85Xkpm~YUBBygpA7qc*ULe?rET%BBWPP3oHAYdmq=|w
z4LUUk=LkWAQZxV=F5uM8f^G(^;j_lgf&<&bhSPn_pfFu)Zc?}l1
sj>td4bD&*n$1AUY&A$Ax{QFz(7Ots4oKY|FG!$HX1HbIUAJakBzyxJ{76US-Go&z7Fh(&%F{UsAX{IRV6sBMXP39_A
zBRw-cBTeR)AmuOFfJ709<)_JVi#tBPEVZaOGe0jr{uVowc}ox>T2fk&lM0mMg((9I
ztYr8MG=Sk(s(wa(ZmNE6Vo`FwzE^&FzOjB{L4kf*YF?RsPG*vRL1jrsex9+Op`m_p
zW=X1UL1J=tVtQ(^enED6d{Js~erZuMkOy=_UP^wEenC!RNm_nUZc1iRG0+gOyYvbw
ze{tC4=BJeAq}mm618rpl;$j6L@qw9cP<##bvLnTf$FXILu}oQZ;vkMJN6{+}S#~Tt4@C(@b4C&^lEd5?
zT9!ZuO5g>Qz`Jo5Ti8gwg}O+yHsS^Hr+^Fe$Np&1qQ8d5044?y5TGqk|I@+^Ht?VJ
zoIB)@LrJOAV$nrE?T^ZMui#^>_Zuay{dEn{Jc(cAKA1mX@@LB(qAL3rgmubodrUD#skuf6i
zSBd1817Eud`38PgmO+UE~qX0B-h>MuQ{j*KPy10
z@HIrgsU{F-{!~=*&v8@Dl53L0+8$!57-t5PxtyXUwX~8`C*Zv)Lko#iGBq#5i+?DY
z$s{ji$YhF>2&@k`<(54#de2pl
zb9_@?T$5Xz)FuV4!g{e%!A+%jmJVyuP}|SaVT~Hnn^-!mSwnh&r3;(VgDf4^wxN88
zr8jR%53}@^P3aNI3oF}h^6#W`lCr2K{}EPg=G5fygs9}i#d(>^qNa$dra&Z_&x=x0
zONz7UjI0Jk2>tV#mOtLxs}}Nkg=+C^Iz<&#nbqPcCEF{>v&lk6izn6m<&$bEEuC1n
z@UomcR8U_&+IRTKOV96pcXIsPYe)NDdcN;SU*D0VeMb(n2++d=Gl@9s<5Y4%R>guU
zi^{C1&C4ut1_qN$W@WKIUtzBV?2RY$>39RbA&r$BnCY==CJWlULZ7UzRo1S3Nv0|Y
z-V@ZVl(cJ7C7Dg<=ANKtrKDX`$)|Hq)@P;Uz)alqQCTa{oat6InzA(x#2oPf}o_C%LY0nyZ>d$VEH8X6t+{mk_O~_EzMa8ti<#;wqB03O?29V65nJ
zmISGEFF#-mLpeKcP3E{If52)v1tPg5YH3+Q0R^!@386ir9G|nq2CIoPGhOE=N6wx(
zdwTTs@sY0S!F+xgBzSsUNhLGW`#>}-_Od9-)69(64d5bHSP&BxY7b)D*3Md--LAcA
zTXsWccxdwV;qk=anKQ$K=LXGI>vjC}(4d_d^O=05qUlmp)00nX^QJ!sK*nN`Iay0A
zrgMo|B_qky3@2bRa!yL*lT=ewS_gDRT^o{GnbwPjO
zjaBcu(0pz2fw23&u={T!w+kil1w(wHBpfq@W2>IB(E32wb6?oAwyz`{FoXlT|G*z#%y2~$5|@&hg3RVmpN7200ay*OC{8FjIaQTw)D92)m{yF#+YK^DuDBhV@iTa{
zwMgO$9Nk-=lK0h@zTzpm*Q%{U!?jTKIOUup+m@`;%T0A$pX`GEY;C0N+qTl6SI{51
zh;wCuc5Yj*u2f_1TCiFlu)$Z2U*xN?A~(ks-M`_^l3x(eW7ouJ%y04_VyIwdldW{7
z&k|XauQ1ExE0{^6&=zBw>A9$+b1^S%uck0Inm!QoWLAYH7?i6BDj?gUNOxkvHXt>L
zbEw81$WreBSs~@-)>U6QC|v8`ApWKv5U6V(ubtP0=ipoJ__JHj=p8TKe*SL%bzeEU
z<3{+G;hVFiXqOS~(xYAFP|FvmK0kGH->sff=ztMApob2WgOTMM9Ovx$IV=wz+)?Ft8AZHr2^eS9{8JTiIt+;$kP&L=6L^o1pc(5eN|fTcsn
zr_WGj4%o;bc}p-h+bn1tI(_QY>4_>}-tpE1gtowdXe$zA`W;tIQdHEyibR-Ugt9Hr
z$dMd}3hFT+E9840iMG_hNADdeiKB)%S`x+#VQg#k*~}!7xVc%=Cei4eQfvtk80lNzYlVp^L=
z#lm`E$XJ#EOHJn>9W~6dabo{hGijRjF}<&X*E2Kr=xGGj)%3D_+KDXaMiK+!(8q`+
zn>bV^nme4LSxq0ndM^V3jSMwt+4vqYFP8ar+gaJbs(ES6Oh2Vcu
z%U5k4sBq5wF&@;(uv05(4^F#Lf~{GzMz@%?oj!(jx0YW7WQHggAmT(61ne68Q&GdR
zl~A)4wu5xo3>;Dkt#J(4mu%kJtCCUvS4bs-yrOYkFSBw64t6s$0A`5bw*6jXF
z4<^IrkN8G$e*H^)L_syMP6DAUu{8z%|9!Tibv2
z;*I`a_OE%?W=pMyjMhV|!(bY$1~ejlp$2JOdizW5d2HC22I#%5tCg#13Ymb}*
zb%wQfY_KOw;wy&uN=X2Jtt@LTc1nqzAeP|V9A)Tk?Bm!
zZ0l;XzC{`TE2C!If6BrAx||PSrBy_>MksfE#s4<+o6zq*)cfBm9Xe|qI;)?XDv9qK
z;`=3G+7PB4*lwTon0&-sGyqLfJd(iZ@tn)z?36%v;cG2lF#U-H?tqDe8Av3uid4v8
zJd{X$R7hqjIea1kG7HK6JXP{C)s`&$LG#kGOVCWDeMr!7qG&KuW^(jn>?DvomgQj`
zM$kP%k%Zu<&cWuhVt+PVy!XTgLDE8ekqwvM+YN`23i*Q@(yqR1rM8hV?oDok1ic5h
zC!MSjH`cEbyAezXuzZ*I*$q-9c0MNfpD5qwJ-I=u#IBDC(I=|Ud)si%7P0GNg0%=9
z@2fD;8nuhCq!8=FhjXkFyFfL8Wibh1D{lr;YFf%L=3DZCQsFpL;X#&xO9mK(8>_@E
zFcXcQ(jcoE>cGP`;Hr7}+@|c-KvP$-b|{xzXtY|v2`|zn!%^~}J6hszxwmnvH8|99
zQ(tM((A2L4si{c*lKi^CP4Fq_n1`oYdYfJvzzy7du7+L$MQ*EJis;x6F7F?cwW_%~
zOO>n$uBbFsa=5*Tmy$G%4t+IF(GWC)bsjyl$==IMzUodB2FJ&-%w)ywXNH((t&$yc
zQ=C3MfCP=ziN|f{a|=0TF(wy#y{uqEbzzlhDc>{M5e%
zvO>P&oAvgt`+S$qcQFsb7sbzuzkc=B*n?d?_jmRD?(E&Edtu|yXld7&v1{y~pDqdK
z4dJ}*KM&`;&b?)^ue|%v2JdO}fx5N%{^%!s;M3IVbDtyfAQ
zj{a{0K;T=7oG>CMbpMIhCrJqbL}k{d<)mS+uSxj7WK7VA1CllX1K+7@N-UD@R&{{o9s
zUh~&_`;?QK;Qq^t;=E@2xoY|7wXS)+q=3^h0RN$Dt**6Ny`mc&C=OeD8s4sWu6Q-v
zX)B@8Q^*wM?-~^a57ShhOM_Q)DIQ>Z`nmbED#91;Y2YgC0yu9)O-{|{(jOJTeV~aK
zWL1lcuOG-VTU;%`%?{Y*1r_fms@E&kCP69T9Dxna6~N(^(`0rP!~E?jg`yi?Oy<-@
znX;15pQS^I=h#qClT^zc59(?8-j^doN;V5ODAo5cbH-O+P5&9VVNr6)%pFgIqB8ZL
zpr>GgOz&bkck~EF2wr|=5-yw;!O1jzs(Sr2T`@wYhYB#roc6YLYcoA^IiG>6EIK_o
zFT+?zneSYU1?XvLh@Qcg-RhDGTYu$N$!wiawAZuwjEq<$OH7$fAM_4OWb&uM<^HC;
zWH!I{=E!@Aq4Q_Yj!c|OAo!S}x4`ebWFf%is(r#RpjpMvD~@|>OPXdqFF;F8w&iDX
z2^FOdy_!`o)|S{%Wfqm7^b-8kuYkbmCdyR&aCvvU+_`U~$=d;14&;x4dMytU?~aWS
z@ptIFxSf{sfvd&qi}(3wbpDz32>OP~9?)d`d>4p*5&t}XbBEE;^iBju;(K_(S_{!_6AFT%?t4p5^TpQ3m9h;%RHu1mw(?da>p_KU_szv|(rs&CpE&U<}P67K$Fp@4VipuA&DauvP}3D73t@4vLuL
zDWxstLE9gq)92w{Bxrs=#8J|BfLNNFCV;?9fuu}^>94~IgG_Q1FDKEIev@#_68m5$
zTu6dER70cxSt1KqkGxH8a2&bzl*Akt5C032@c#jBg-S7(>53mVxm3Lq>Ty&5oSc&{
z=jp(5Ps6TzDVnKkYMobtbx`B8IxyQ)R0cOwqL53c6iH58D9p~nl^zd6N@^NJR0NEpN6hHtYq07T
zYMp`mz;{e{GPh*<7i5}~u|P9qPr}u|})0clzhX<9cUO%#!)Rp&dm
zL7IOLM2*1yHLVorF#q5IB9K1bT68a3G51l^E*G@hN
z_S_Hl+@8Gq-aXGfsT3SCfa=iyvZj0oy`#rMA#oQB&y-dwwyvffeRTL=t5fo=Uq`2|0eZvgGE(e0c
zHaKQwf)^fh>mBfIiF`V>kZ{Tc{S->w!IJL*St09uJUoP>Y!Hckx-q^a(t^2z-
zTwZTa+26hz#?SYD0+(X`gFk%Flh95q)>9+v!a>Ngz8h}H`r(HkRGj8td1B;F^9lFg
zb0^%O*?cy6Sxqm?;H*OFuAS_x{kGy8_!zQcEqLOeEx=zQ;KWaXMZ{VKcGHLhH=AY)
zIrvwBl2Ix0!t?>2flWjaz(CLPX^NW@J5I9oVasN%BCY_tgEGN+07ek>FoH>VkYh&u
zV}HNpZ5W`RK^jVhx)&%+j^oPYS>5^lj)Yg(r%akw*r!YaE9_GyyLIQcOrF-A-|vX1
zJHH#gcR3Eu%Ujb`~xYHq$PH}
y<9f&1^Llf4skz%|?$%=`;9H8FG-4-9&94~EudGDiVB(EzxLrZl3XdPQi2n^(0Wkvr

diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/android.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/android.py
deleted file mode 100755
index eda8093..0000000
--- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/android.py
+++ /dev/null
@@ -1,120 +0,0 @@
-from __future__ import annotations
-
-import os
-import re
-import sys
-from functools import lru_cache
-from typing import cast
-
-from .api import PlatformDirsABC
-
-
-class Android(PlatformDirsABC):
-    """
-    Follows the guidance `from here `_. Makes use of the
-    `appname ` and
-    `version `.
-    """
-
-    @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")
-
-    @property
-    def site_data_dir(self) -> str:
-        """:return: data directory shared by users, same as `user_data_dir`"""
-        return self.user_data_dir
-
-    @property
-    def user_config_dir(self) -> str:
-        """
-        :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")
-
-    @property
-    def site_config_dir(self) -> str:
-        """:return: config directory shared by the users, same as `user_config_dir`"""
-        return self.user_config_dir
-
-    @property
-    def user_cache_dir(self) -> str:
-        """: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 user_state_dir(self) -> str:
-        """:return: state directory tied to the user, same as `user_data_dir`"""
-        return self.user_data_dir
-
-    @property
-    def user_log_dir(self) -> str:
-        """
-        :return: log directory tied to the user, same as `user_cache_dir` if not opinionated else ``log`` in it,
-          e.g. ``/data/user///cache//log``
-        """
-        path = self.user_cache_dir
-        if self.opinion:
-            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 _android_documents_folder()
-
-    @property
-    def user_runtime_dir(self) -> str:
-        """
-        :return: runtime directory tied to the user, same as `user_cache_dir` if not opinionated else ``tmp`` in it,
-          e.g. ``/data/user///cache//tmp``
-        """
-        path = self.user_cache_dir
-        if self.opinion:
-            path = os.path.join(path, "tmp")
-        return path
-
-
-@lru_cache(maxsize=1)
-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):
-                result = path.split("/files")[0]
-                break
-        else:
-            result = None
-    return result
-
-
-@lru_cache(maxsize=1)
-def _android_documents_folder() -> str:
-    """:return: documents folder for the Android OS"""
-    # Get directories with pyjnius
-    try:
-        from jnius import autoclass
-
-        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
-
-
-__all__ = [
-    "Android",
-]
diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/api.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/api.py
deleted file mode 100755
index 6f6e2c2..0000000
--- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/api.py
+++ /dev/null
@@ -1,156 +0,0 @@
-from __future__ import annotations
-
-import os
-import sys
-from abc import ABC, abstractmethod
-from pathlib import Path
-
-if sys.version_info >= (3, 8):  # pragma: no branch
-    from typing import Literal  # pragma: no cover
-
-
-class PlatformDirsABC(ABC):
-    """
-    Abstract base class for platform directories.
-    """
-
-    def __init__(
-        self,
-        appname: str | None = None,
-        appauthor: str | None | Literal[False] = None,
-        version: str | None = None,
-        roaming: bool = False,
-        multipath: bool = False,
-        opinion: bool = True,
-    ):
-        """
-        Create a new platform directory.
-
-        :param appname: See `appname`.
-        :param appauthor: See `appauthor`.
-        :param version: See `version`.
-        :param roaming: See `roaming`.
-        :param multipath: See `multipath`.
-        :param opinion: See `opinion`.
-        """
-        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.
-        """
-        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 ``.``.
-        """
-        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 `_).
-        """
-        self.multipath = multipath
-        """
-        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.
-
-    def _append_app_name_and_version(self, *base: str) -> str:
-        params = list(base[1:])
-        if self.appname:
-            params.append(self.appname)
-            if self.version:
-                params.append(self.version)
-        return os.path.join(base[0], *params)
-
-    @property
-    @abstractmethod
-    def user_data_dir(self) -> str:
-        """:return: data directory tied to the user"""
-
-    @property
-    @abstractmethod
-    def site_data_dir(self) -> str:
-        """:return: data directory shared by users"""
-
-    @property
-    @abstractmethod
-    def user_config_dir(self) -> str:
-        """:return: config directory tied to the user"""
-
-    @property
-    @abstractmethod
-    def site_config_dir(self) -> str:
-        """:return: config directory shared by the users"""
-
-    @property
-    @abstractmethod
-    def user_cache_dir(self) -> str:
-        """:return: cache directory tied to the user"""
-
-    @property
-    @abstractmethod
-    def user_state_dir(self) -> str:
-        """:return: state directory tied to the user"""
-
-    @property
-    @abstractmethod
-    def user_log_dir(self) -> str:
-        """:return: log directory tied to the user"""
-
-    @property
-    @abstractmethod
-    def user_documents_dir(self) -> str:
-        """:return: documents directory tied to the user"""
-
-    @property
-    @abstractmethod
-    def user_runtime_dir(self) -> str:
-        """:return: runtime directory tied to the user"""
-
-    @property
-    def user_data_path(self) -> Path:
-        """:return: data path tied to the user"""
-        return Path(self.user_data_dir)
-
-    @property
-    def site_data_path(self) -> Path:
-        """:return: data path shared by users"""
-        return Path(self.site_data_dir)
-
-    @property
-    def user_config_path(self) -> Path:
-        """:return: config path tied to the user"""
-        return Path(self.user_config_dir)
-
-    @property
-    def site_config_path(self) -> Path:
-        """:return: config path shared by the users"""
-        return Path(self.site_config_dir)
-
-    @property
-    def user_cache_path(self) -> Path:
-        """:return: cache path tied to the user"""
-        return Path(self.user_cache_dir)
-
-    @property
-    def user_state_path(self) -> Path:
-        """:return: state path tied to the user"""
-        return Path(self.user_state_dir)
-
-    @property
-    def user_log_path(self) -> Path:
-        """:return: log path tied to the user"""
-        return Path(self.user_log_dir)
-
-    @property
-    def user_documents_path(self) -> Path:
-        """:return: documents path tied to the user"""
-        return Path(self.user_documents_dir)
-
-    @property
-    def user_runtime_path(self) -> Path:
-        """:return: runtime path tied to the user"""
-        return Path(self.user_runtime_dir)
diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/macos.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/macos.py
deleted file mode 100755
index a01337c..0000000
--- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/macos.py
+++ /dev/null
@@ -1,64 +0,0 @@
-from __future__ import annotations
-
-import os
-
-from .api import PlatformDirsABC
-
-
-class MacOS(PlatformDirsABC):
-    """
-    Platform directories for the macOS operating system. Follows the guidance from `Apple documentation
-    `_.
-    Makes use of the `appname ` and
-    `version `.
-    """
-
-    @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/"))
-
-    @property
-    def site_data_dir(self) -> str:
-        """: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:
-        """:return: config directory tied to the user, e.g. ``~/Library/Preferences/$appname/$version``"""
-        return self._append_app_name_and_version(os.path.expanduser("~/Library/Preferences/"))
-
-    @property
-    def site_config_dir(self) -> str:
-        """:return: config directory shared by the users, e.g. ``/Library/Preferences/$appname``"""
-        return self._append_app_name_and_version("/Library/Preferences")
-
-    @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"))
-
-    @property
-    def user_state_dir(self) -> str:
-        """:return: state directory tied to the user, same as `user_data_dir`"""
-        return self.user_data_dir
-
-    @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"))
-
-    @property
-    def user_documents_dir(self) -> str:
-        """:return: documents directory tied to the user, e.g. ``~/Documents``"""
-        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"))
-
-
-__all__ = [
-    "MacOS",
-]
diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/unix.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/unix.py
deleted file mode 100755
index 9aca5a0..0000000
--- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/unix.py
+++ /dev/null
@@ -1,181 +0,0 @@
-from __future__ import annotations
-
-import os
-import sys
-from configparser import ConfigParser
-from pathlib import Path
-
-from .api import PlatformDirsABC
-
-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):
-    """
-    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 `.
-    """
-
-    @property
-    def user_data_dir(self) -> str:
-        """
-        :return: data directory tied to the user, e.g. ``~/.local/share/$appname/$version`` or
-         ``$XDG_DATA_HOME/$appname/$version``
-        """
-        path = os.environ.get("XDG_DATA_HOME", "")
-        if not path.strip():
-            path = os.path.expanduser("~/.local/share")
-        return self._append_app_name_and_version(path)
-
-    @property
-    def site_data_dir(self) -> str:
-        """
-        :return: data directories shared by users (if `multipath ` 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. ``/usr/local/share/$appname/$version`` or ``/usr/share/$appname/$version``
-        """
-        # XDG default for $XDG_DATA_DIRS; only first, if multipath is False
-        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:
-            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:
-        """
-        :return: config directory tied to the user, e.g. ``~/.config/$appname/$version`` or
-         ``$XDG_CONFIG_HOME/$appname/$version``
-        """
-        path = os.environ.get("XDG_CONFIG_HOME", "")
-        if not path.strip():
-            path = os.path.expanduser("~/.config")
-        return self._append_app_name_and_version(path)
-
-    @property
-    def site_config_dir(self) -> str:
-        """
-        :return: config directories shared by users (if `multipath `
-         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
-        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:
-        """
-        :return: cache directory tied to the user, e.g. ``~/.cache/$appname/$version`` or
-         ``~/$XDG_CACHE_HOME/$appname/$version``
-        """
-        path = os.environ.get("XDG_CACHE_HOME", "")
-        if not path.strip():
-            path = os.path.expanduser("~/.cache")
-        return self._append_app_name_and_version(path)
-
-    @property
-    def user_state_dir(self) -> str:
-        """
-        :return: state directory tied to the user, e.g. ``~/.local/state/$appname/$version`` or
-         ``$XDG_STATE_HOME/$appname/$version``
-        """
-        path = os.environ.get("XDG_STATE_HOME", "")
-        if not path.strip():
-            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
-        """
-        path = self.user_state_dir
-        if self.opinion:
-            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``
-        """
-        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")
-
-        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``
-        """
-        path = os.environ.get("XDG_RUNTIME_DIR", "")
-        if not path.strip():
-            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 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. Only return first item, even if ``multipath`` is set to ``True``"""
-        return self._first_item_as_path_if_multipath(self.site_config_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 = os.path.join(Unix().user_config_dir, "user-dirs.dirs")
-    if os.path.exists(user_dirs_config_path):
-        parser = ConfigParser()
-
-        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()}")
-
-        if key not in parser["top"]:
-            return None
-
-        path = parser["top"][key].strip('"')
-        # Handle relative home paths
-        path = path.replace("$HOME", os.path.expanduser("~"))
-        return path
-
-    return None
-
-
-__all__ = [
-    "Unix",
-]
diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/version.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/version.py
deleted file mode 100755
index 9f6eb98..0000000
--- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/version.py
+++ /dev/null
@@ -1,4 +0,0 @@
-# file generated by setuptools_scm
-# don't change, don't track in version control
-__version__ = version = '2.6.2'
-__version_tuple__ = version_tuple = (2, 6, 2)
diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/windows.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/windows.py
deleted file mode 100755
index d5c27b3..0000000
--- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/platformdirs/windows.py
+++ /dev/null
@@ -1,184 +0,0 @@
-from __future__ import annotations
-
-import ctypes
-import os
-import sys
-from functools import lru_cache
-from typing import Callable
-
-from .api import PlatformDirsABC
-
-
-class Windows(PlatformDirsABC):
-    """`MSDN on where to store app data files
-    `_.
-    Makes use of the
-    `appname `,
-    `appauthor `,
-    `version `,
-    `roaming `,
-    `opinion `."""
-
-    @property
-    def user_data_dir(self) -> str:
-        """
-        :return: data directory tied to the user, e.g.
-         ``%USERPROFILE%\\AppData\\Local\\$appauthor\\$appname`` (not roaming) or
-         ``%USERPROFILE%\\AppData\\Roaming\\$appauthor\\$appname`` (roaming)
-        """
-        const = "CSIDL_APPDATA" if self.roaming else "CSIDL_LOCAL_APPDATA"
-        path = os.path.normpath(get_win_folder(const))
-        return self._append_parts(path)
-
-    def _append_parts(self, path: str, *, opinion_value: str | None = None) -> str:
-        params = []
-        if self.appname:
-            if self.appauthor is not False:
-                author = self.appauthor or self.appname
-                params.append(author)
-            params.append(self.appname)
-            if opinion_value is not None and self.opinion:
-                params.append(opinion_value)
-            if self.version:
-                params.append(self.version)
-        return os.path.join(path, *params)
-
-    @property
-    def site_data_dir(self) -> str:
-        """:return: data directory shared by users, e.g. ``C:\\ProgramData\\$appauthor\\$appname``"""
-        path = os.path.normpath(get_win_folder("CSIDL_COMMON_APPDATA"))
-        return self._append_parts(path)
-
-    @property
-    def user_config_dir(self) -> str:
-        """:return: config directory tied to the user, same as `user_data_dir`"""
-        return self.user_data_dir
-
-    @property
-    def site_config_dir(self) -> str:
-        """:return: config directory shared by the users, same as `site_data_dir`"""
-        return self.site_data_dir
-
-    @property
-    def user_cache_dir(self) -> str:
-        """
-        :return: cache directory tied to the user (if opinionated with ``Cache`` folder within ``$appname``) e.g.
-         ``%USERPROFILE%\\AppData\\Local\\$appauthor\\$appname\\Cache\\$version``
-        """
-        path = os.path.normpath(get_win_folder("CSIDL_LOCAL_APPDATA"))
-        return self._append_parts(path, opinion_value="Cache")
-
-    @property
-    def user_state_dir(self) -> str:
-        """:return: state directory tied to the user, same as `user_data_dir`"""
-        return self.user_data_dir
-
-    @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
-        """
-        path = self.user_data_dir
-        if self.opinion:
-            path = os.path.join(path, "Logs")
-        return path
-
-    @property
-    def user_documents_dir(self) -> str:
-        """
-        :return: documents directory tied to the user e.g. ``%USERPROFILE%\\Documents``
-        """
-        return os.path.normpath(get_win_folder("CSIDL_PERSONAL"))
-
-    @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"))
-        return self._append_parts(path)
-
-
-def get_win_folder_from_env_vars(csidl_name: str) -> str:
-    """Get folder from environment variables."""
-    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",
-        "CSIDL_COMMON_APPDATA": "ALLUSERSPROFILE",
-        "CSIDL_LOCAL_APPDATA": "LOCALAPPDATA",
-    }.get(csidl_name)
-    if env_var_name is None:
-        raise ValueError(f"Unknown CSIDL name: {csidl_name}")
-    result = os.environ.get(env_var_name)
-    if result is None:
-        raise ValueError(f"Unset environment variable: {env_var_name}")
-    return result
-
-
-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 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",
-    }.get(csidl_name)
-    if shell_folder_name is None:
-        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
-
-    key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders")
-    directory, _ = winreg.QueryValueEx(key, shell_folder_name)
-    return str(directory)
-
-
-def get_win_folder_via_ctypes(csidl_name: str) -> str:
-    """Get folder with ctypes."""
-    csidl_const = {
-        "CSIDL_APPDATA": 26,
-        "CSIDL_COMMON_APPDATA": 35,
-        "CSIDL_LOCAL_APPDATA": 28,
-        "CSIDL_PERSONAL": 5,
-    }.get(csidl_name)
-    if csidl_const is None:
-        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 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
-
-    return buf.value
-
-
-def _pick_get_win_folder() -> Callable[[str], str]:
-    if hasattr(ctypes, "windll"):
-        return get_win_folder_via_ctypes
-    try:
-        import winreg  # noqa: F401
-    except ImportError:
-        return get_win_folder_from_env_vars
-    else:
-        return get_win_folder_from_registry
-
-
-get_win_folder = lru_cache(maxsize=None)(_pick_get_win_folder())
-
-__all__ = [
-    "Windows",
-]
diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/__init__.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/__init__.py
deleted file mode 100755
index 7802ff1..0000000
--- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/__init__.py
+++ /dev/null
@@ -1,331 +0,0 @@
-# module pyparsing.py
-#
-# Copyright (c) 2003-2022  Paul T. McGuire
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__doc__ = """
-pyparsing module - Classes and methods to define and execute parsing grammars
-=============================================================================
-
-The pyparsing module is an alternative approach to creating and
-executing simple grammars, vs. the traditional lex/yacc approach, or the
-use of regular expressions.  With pyparsing, you don't need to learn
-a new syntax for defining grammars or matching expressions - the parsing
-module provides a library of classes that you use to construct the
-grammar directly in Python.
-
-Here is a program to parse "Hello, World!" (or any greeting of the form
-``", !"``), built up using :class:`Word`,
-:class:`Literal`, and :class:`And` elements
-(the :meth:`'+'` operators create :class:`And` expressions,
-and the strings are auto-converted to :class:`Literal` expressions)::
-
-    from pyparsing import Word, alphas
-
-    # define grammar of a greeting
-    greet = Word(alphas) + "," + Word(alphas) + "!"
-
-    hello = "Hello, World!"
-    print(hello, "->", greet.parse_string(hello))
-
-The program outputs the following::
-
-    Hello, World! -> ['Hello', ',', 'World', '!']
-
-The Python representation of the grammar is quite readable, owing to the
-self-explanatory class names, and the use of :class:`'+'`,
-:class:`'|'`, :class:`'^'` and :class:`'&'` operators.
-
-The :class:`ParseResults` object returned from
-:class:`ParserElement.parseString` can be
-accessed as a nested list, a dictionary, or an object with named
-attributes.
-
-The pyparsing module handles some of the problems that are typically
-vexing when writing text parsers:
-
-  - extra or missing whitespace (the above program will also handle
-    "Hello,World!", "Hello  ,  World  !", etc.)
-  - quoted strings
-  - embedded comments
-
-
-Getting Started -
------------------
-Visit the classes :class:`ParserElement` and :class:`ParseResults` to
-see the base classes that most other pyparsing
-classes inherit from. Use the docstrings for examples of how to:
-
- - construct literal match expressions from :class:`Literal` and
-   :class:`CaselessLiteral` classes
- - construct character word-group expressions using the :class:`Word`
-   class
- - see how to create repetitive expressions using :class:`ZeroOrMore`
-   and :class:`OneOrMore` classes
- - use :class:`'+'`, :class:`'|'`, :class:`'^'`,
-   and :class:`'&'` operators to combine simple expressions into
-   more complex ones
- - associate names with your parsed results using
-   :class:`ParserElement.setResultsName`
- - access the parsed data, which is returned as a :class:`ParseResults`
-   object
- - find some helpful expression short-cuts like :class:`delimitedList`
-   and :class:`oneOf`
- - find more useful common expressions in the :class:`pyparsing_common`
-   namespace class
-"""
-from typing import NamedTuple
-
-
-class version_info(NamedTuple):
-    major: int
-    minor: int
-    micro: int
-    releaselevel: str
-    serial: int
-
-    @property
-    def __version__(self):
-        return (
-            "{}.{}.{}".format(self.major, self.minor, self.micro)
-            + (
-                "{}{}{}".format(
-                    "r" if self.releaselevel[0] == "c" else "",
-                    self.releaselevel[0],
-                    self.serial,
-                ),
-                "",
-            )[self.releaselevel == "final"]
-        )
-
-    def __str__(self):
-        return "{} {} / {}".format(__name__, self.__version__, __version_time__)
-
-    def __repr__(self):
-        return "{}.{}({})".format(
-            __name__,
-            type(self).__name__,
-            ", ".join("{}={!r}".format(*nv) for nv in zip(self._fields, self)),
-        )
-
-
-__version_info__ = version_info(3, 0, 9, "final", 0)
-__version_time__ = "05 May 2022 07:02 UTC"
-__version__ = __version_info__.__version__
-__versionTime__ = __version_time__
-__author__ = "Paul McGuire "
-
-from .util import *
-from .exceptions import *
-from .actions import *
-from .core import __diag__, __compat__
-from .results import *
-from .core import *
-from .core import _builtin_exprs as core_builtin_exprs
-from .helpers import *
-from .helpers import _builtin_exprs as helper_builtin_exprs
-
-from .unicode import unicode_set, UnicodeRangeList, pyparsing_unicode as unicode
-from .testing import pyparsing_test as testing
-from .common import (
-    pyparsing_common as common,
-    _builtin_exprs as common_builtin_exprs,
-)
-
-# define backward compat synonyms
-if "pyparsing_unicode" not in globals():
-    pyparsing_unicode = unicode
-if "pyparsing_common" not in globals():
-    pyparsing_common = common
-if "pyparsing_test" not in globals():
-    pyparsing_test = testing
-
-core_builtin_exprs += common_builtin_exprs + helper_builtin_exprs
-
-
-__all__ = [
-    "__version__",
-    "__version_time__",
-    "__author__",
-    "__compat__",
-    "__diag__",
-    "And",
-    "AtLineStart",
-    "AtStringStart",
-    "CaselessKeyword",
-    "CaselessLiteral",
-    "CharsNotIn",
-    "Combine",
-    "Dict",
-    "Each",
-    "Empty",
-    "FollowedBy",
-    "Forward",
-    "GoToColumn",
-    "Group",
-    "IndentedBlock",
-    "Keyword",
-    "LineEnd",
-    "LineStart",
-    "Literal",
-    "Located",
-    "PrecededBy",
-    "MatchFirst",
-    "NoMatch",
-    "NotAny",
-    "OneOrMore",
-    "OnlyOnce",
-    "OpAssoc",
-    "Opt",
-    "Optional",
-    "Or",
-    "ParseBaseException",
-    "ParseElementEnhance",
-    "ParseException",
-    "ParseExpression",
-    "ParseFatalException",
-    "ParseResults",
-    "ParseSyntaxException",
-    "ParserElement",
-    "PositionToken",
-    "QuotedString",
-    "RecursiveGrammarException",
-    "Regex",
-    "SkipTo",
-    "StringEnd",
-    "StringStart",
-    "Suppress",
-    "Token",
-    "TokenConverter",
-    "White",
-    "Word",
-    "WordEnd",
-    "WordStart",
-    "ZeroOrMore",
-    "Char",
-    "alphanums",
-    "alphas",
-    "alphas8bit",
-    "any_close_tag",
-    "any_open_tag",
-    "c_style_comment",
-    "col",
-    "common_html_entity",
-    "counted_array",
-    "cpp_style_comment",
-    "dbl_quoted_string",
-    "dbl_slash_comment",
-    "delimited_list",
-    "dict_of",
-    "empty",
-    "hexnums",
-    "html_comment",
-    "identchars",
-    "identbodychars",
-    "java_style_comment",
-    "line",
-    "line_end",
-    "line_start",
-    "lineno",
-    "make_html_tags",
-    "make_xml_tags",
-    "match_only_at_col",
-    "match_previous_expr",
-    "match_previous_literal",
-    "nested_expr",
-    "null_debug_action",
-    "nums",
-    "one_of",
-    "printables",
-    "punc8bit",
-    "python_style_comment",
-    "quoted_string",
-    "remove_quotes",
-    "replace_with",
-    "replace_html_entity",
-    "rest_of_line",
-    "sgl_quoted_string",
-    "srange",
-    "string_end",
-    "string_start",
-    "trace_parse_action",
-    "unicode_string",
-    "with_attribute",
-    "indentedBlock",
-    "original_text_for",
-    "ungroup",
-    "infix_notation",
-    "locatedExpr",
-    "with_class",
-    "CloseMatch",
-    "token_map",
-    "pyparsing_common",
-    "pyparsing_unicode",
-    "unicode_set",
-    "condition_as_parse_action",
-    "pyparsing_test",
-    # pre-PEP8 compatibility names
-    "__versionTime__",
-    "anyCloseTag",
-    "anyOpenTag",
-    "cStyleComment",
-    "commonHTMLEntity",
-    "countedArray",
-    "cppStyleComment",
-    "dblQuotedString",
-    "dblSlashComment",
-    "delimitedList",
-    "dictOf",
-    "htmlComment",
-    "javaStyleComment",
-    "lineEnd",
-    "lineStart",
-    "makeHTMLTags",
-    "makeXMLTags",
-    "matchOnlyAtCol",
-    "matchPreviousExpr",
-    "matchPreviousLiteral",
-    "nestedExpr",
-    "nullDebugAction",
-    "oneOf",
-    "opAssoc",
-    "pythonStyleComment",
-    "quotedString",
-    "removeQuotes",
-    "replaceHTMLEntity",
-    "replaceWith",
-    "restOfLine",
-    "sglQuotedString",
-    "stringEnd",
-    "stringStart",
-    "traceParseAction",
-    "unicodeString",
-    "withAttribute",
-    "indentedBlock",
-    "originalTextFor",
-    "infixNotation",
-    "locatedExpr",
-    "withClass",
-    "tokenMap",
-    "conditionAsParseAction",
-    "autoname_elements",
-]
diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/__init__.cpython-311.pyc
deleted file mode 100755
index 3747a09caa4e0e01eda81abfad6dc8d3c0a23375..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 8343
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
P*1M_)lIy+n;Ro|SqaFSK

diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/common.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/common.cpython-311.pyc
deleted file mode 100755
index 6b5e5f75b58e40deae678318bd6bf53f4fe57645..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 14791
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

diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/core.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/core.cpython-311.pyc
deleted file mode 100755
index be510b54b729c2660f64681dd99c0cab151b35e4..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 277643
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%0D;j@{Bm(nc{a&
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
MT3DCVf2{ZZA3?WeHvj+t

diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/testing.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/testing.cpython-311.pyc
deleted file mode 100755
index af49b8ea4b563fcf863ac62ba3025ade9ffacf34..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 19513
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
b!#j%H9|~$SE*?~089rk9Up}Ff&Eo$88P1r(

diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/unicode.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/unicode.cpython-311.pyc
deleted file mode 100755
index e31eb36abd96822888c71f1e5021e2d74d801b74..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 15371
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

diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/util.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/util.cpython-311.pyc
deleted file mode 100755
index 7c220804bb8aac0fbce5bb04d367aa18c1357671..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 14270
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

diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/actions.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/actions.py
deleted file mode 100755
index f72c66e..0000000
--- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/actions.py
+++ /dev/null
@@ -1,207 +0,0 @@
-# actions.py
-
-from .exceptions import ParseException
-from .util import col
-
-
-class OnlyOnce:
-    """
-    Wrapper for parse actions, to ensure they are only called once.
-    """
-
-    def __init__(self, method_call):
-        from .core import _trim_arity
-
-        self.callable = _trim_arity(method_call)
-        self.called = False
-
-    def __call__(self, s, l, t):
-        if not self.called:
-            results = self.callable(s, l, t)
-            self.called = True
-            return results
-        raise ParseException(s, l, "OnlyOnce obj called multiple times w/out reset")
-
-    def reset(self):
-        """
-        Allow the associated parse action to be called once more.
-        """
-
-        self.called = False
-
-
-def match_only_at_col(n):
-    """
-    Helper method for defining parse actions that require matching at
-    a specific column in the input text.
-    """
-
-    def verify_col(strg, locn, toks):
-        if col(locn, strg) != n:
-            raise ParseException(strg, locn, "matched token not at column {}".format(n))
-
-    return verify_col
-
-
-def replace_with(repl_str):
-    """
-    Helper method for common parse actions that simply return
-    a literal value.  Especially useful when used with
-    :class:`transform_string` ().
-
-    Example::
-
-        num = Word(nums).set_parse_action(lambda toks: int(toks[0]))
-        na = one_of("N/A NA").set_parse_action(replace_with(math.nan))
-        term = na | num
-
-        term[1, ...].parse_string("324 234 N/A 234") # -> [324, 234, nan, 234]
-    """
-    return lambda s, l, t: [repl_str]
-
-
-def remove_quotes(s, l, t):
-    """
-    Helper parse action for removing quotation marks from parsed
-    quoted strings.
-
-    Example::
-
-        # by default, quotation marks are included in parsed results
-        quoted_string.parse_string("'Now is the Winter of our Discontent'") # -> ["'Now is the Winter of our Discontent'"]
-
-        # use remove_quotes to strip quotation marks from parsed results
-        quoted_string.set_parse_action(remove_quotes)
-        quoted_string.parse_string("'Now is the Winter of our Discontent'") # -> ["Now is the Winter of our Discontent"]
-    """
-    return t[0][1:-1]
-
-
-def with_attribute(*args, **attr_dict):
-    """
-    Helper to create a validating parse action to be used with start
-    tags created with :class:`make_xml_tags` or
-    :class:`make_html_tags`. Use ``with_attribute`` to qualify
-    a starting tag with a required attribute value, to avoid false
-    matches on common tags such as ```` or ``
``. - - Call ``with_attribute`` with a series of attribute names and - values. Specify the list of filter attributes names and values as: - - - keyword arguments, as in ``(align="right")``, or - - as an explicit dict with ``**`` operator, when an attribute - name is also a Python reserved word, as in ``**{"class":"Customer", "align":"right"}`` - - a list of name-value tuples, as in ``(("ns1:class", "Customer"), ("ns2:align", "right"))`` - - For attribute names with a namespace prefix, you must use the second - form. Attribute names are matched insensitive to upper/lower case. - - If just testing for ``class`` (with or without a namespace), use - :class:`with_class`. - - To verify that the attribute exists, but without specifying a value, - pass ``with_attribute.ANY_VALUE`` as the value. - - Example:: - - html = ''' -
- Some text -
1 4 0 1 0
-
1,3 2,3 1,1
-
this has no type
-
- - ''' - div,div_end = make_html_tags("div") - - # only match div tag having a type attribute with value "grid" - div_grid = div().set_parse_action(with_attribute(type="grid")) - grid_expr = div_grid + SkipTo(div | div_end)("body") - for grid_header in grid_expr.search_string(html): - print(grid_header.body) - - # construct a match with any div tag having a type attribute, regardless of the value - div_any_type = div().set_parse_action(with_attribute(type=with_attribute.ANY_VALUE)) - div_expr = div_any_type + SkipTo(div | div_end)("body") - for div_header in div_expr.search_string(html): - print(div_header.body) - - prints:: - - 1 4 0 1 0 - - 1 4 0 1 0 - 1,3 2,3 1,1 - """ - if args: - attrs = args[:] - else: - attrs = attr_dict.items() - attrs = [(k, v) for k, v in attrs] - - def pa(s, l, tokens): - for attrName, attrValue in attrs: - if attrName not in tokens: - raise ParseException(s, l, "no matching attribute " + attrName) - if attrValue != with_attribute.ANY_VALUE and tokens[attrName] != attrValue: - raise ParseException( - s, - l, - "attribute {!r} has value {!r}, must be {!r}".format( - attrName, tokens[attrName], attrValue - ), - ) - - return pa - - -with_attribute.ANY_VALUE = object() - - -def with_class(classname, namespace=""): - """ - Simplified version of :class:`with_attribute` when - matching on a div class - made difficult because ``class`` is - a reserved word in Python. - - Example:: - - html = ''' -
- Some text -
1 4 0 1 0
-
1,3 2,3 1,1
-
this <div> has no class
-
- - ''' - div,div_end = make_html_tags("div") - div_grid = div().set_parse_action(with_class("grid")) - - grid_expr = div_grid + SkipTo(div | div_end)("body") - for grid_header in grid_expr.search_string(html): - print(grid_header.body) - - div_any_type = div().set_parse_action(with_class(withAttribute.ANY_VALUE)) - div_expr = div_any_type + SkipTo(div | div_end)("body") - for div_header in div_expr.search_string(html): - print(div_header.body) - - prints:: - - 1 4 0 1 0 - - 1 4 0 1 0 - 1,3 2,3 1,1 - """ - classattr = "{}:class".format(namespace) if namespace else "class" - return with_attribute(**{classattr: classname}) - - -# pre-PEP8 compatibility symbols -replaceWith = replace_with -removeQuotes = remove_quotes -withAttribute = with_attribute -withClass = with_class -matchOnlyAtCol = match_only_at_col diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/common.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/common.py deleted file mode 100755 index 1859fb7..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/common.py +++ /dev/null @@ -1,424 +0,0 @@ -# common.py -from .core import * -from .helpers import delimited_list, any_open_tag, any_close_tag -from datetime import datetime - - -# some other useful expressions - using lower-case class name since we are really using this as a namespace -class pyparsing_common: - """Here are some common low-level expressions that may be useful in - jump-starting parser development: - - - numeric forms (:class:`integers`, :class:`reals`, - :class:`scientific notation`) - - common :class:`programming identifiers` - - network addresses (:class:`MAC`, - :class:`IPv4`, :class:`IPv6`) - - ISO8601 :class:`dates` and - :class:`datetime` - - :class:`UUID` - - :class:`comma-separated list` - - :class:`url` - - Parse actions: - - - :class:`convertToInteger` - - :class:`convertToFloat` - - :class:`convertToDate` - - :class:`convertToDatetime` - - :class:`stripHTMLTags` - - :class:`upcaseTokens` - - :class:`downcaseTokens` - - Example:: - - pyparsing_common.number.runTests(''' - # any int or real number, returned as the appropriate type - 100 - -100 - +100 - 3.14159 - 6.02e23 - 1e-12 - ''') - - pyparsing_common.fnumber.runTests(''' - # any int or real number, returned as float - 100 - -100 - +100 - 3.14159 - 6.02e23 - 1e-12 - ''') - - pyparsing_common.hex_integer.runTests(''' - # hex numbers - 100 - FF - ''') - - pyparsing_common.fraction.runTests(''' - # fractions - 1/2 - -3/4 - ''') - - pyparsing_common.mixed_integer.runTests(''' - # mixed fractions - 1 - 1/2 - -3/4 - 1-3/4 - ''') - - import uuid - pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) - pyparsing_common.uuid.runTests(''' - # uuid - 12345678-1234-5678-1234-567812345678 - ''') - - prints:: - - # any int or real number, returned as the appropriate type - 100 - [100] - - -100 - [-100] - - +100 - [100] - - 3.14159 - [3.14159] - - 6.02e23 - [6.02e+23] - - 1e-12 - [1e-12] - - # any int or real number, returned as float - 100 - [100.0] - - -100 - [-100.0] - - +100 - [100.0] - - 3.14159 - [3.14159] - - 6.02e23 - [6.02e+23] - - 1e-12 - [1e-12] - - # hex numbers - 100 - [256] - - FF - [255] - - # fractions - 1/2 - [0.5] - - -3/4 - [-0.75] - - # mixed fractions - 1 - [1] - - 1/2 - [0.5] - - -3/4 - [-0.75] - - 1-3/4 - [1.75] - - # uuid - 12345678-1234-5678-1234-567812345678 - [UUID('12345678-1234-5678-1234-567812345678')] - """ - - convert_to_integer = token_map(int) - """ - Parse action for converting parsed integers to Python int - """ - - convert_to_float = token_map(float) - """ - Parse action for converting parsed numbers to Python float - """ - - integer = Word(nums).set_name("integer").set_parse_action(convert_to_integer) - """expression that parses an unsigned integer, returns an int""" - - hex_integer = ( - Word(hexnums).set_name("hex integer").set_parse_action(token_map(int, 16)) - ) - """expression that parses a hexadecimal integer, returns an int""" - - signed_integer = ( - Regex(r"[+-]?\d+") - .set_name("signed integer") - .set_parse_action(convert_to_integer) - ) - """expression that parses an integer with optional leading sign, returns an int""" - - fraction = ( - signed_integer().set_parse_action(convert_to_float) - + "/" - + signed_integer().set_parse_action(convert_to_float) - ).set_name("fraction") - """fractional expression of an integer divided by an integer, returns a float""" - fraction.add_parse_action(lambda tt: tt[0] / tt[-1]) - - mixed_integer = ( - fraction | signed_integer + Opt(Opt("-").suppress() + fraction) - ).set_name("fraction or mixed integer-fraction") - """mixed integer of the form 'integer - fraction', with optional leading integer, returns float""" - mixed_integer.add_parse_action(sum) - - real = ( - Regex(r"[+-]?(?:\d+\.\d*|\.\d+)") - .set_name("real number") - .set_parse_action(convert_to_float) - ) - """expression that parses a floating point number and returns a float""" - - sci_real = ( - Regex(r"[+-]?(?:\d+(?:[eE][+-]?\d+)|(?:\d+\.\d*|\.\d+)(?:[eE][+-]?\d+)?)") - .set_name("real number with scientific notation") - .set_parse_action(convert_to_float) - ) - """expression that parses a floating point number with optional - scientific notation and returns a float""" - - # streamlining this expression makes the docs nicer-looking - number = (sci_real | real | signed_integer).setName("number").streamline() - """any numeric expression, returns the corresponding Python type""" - - fnumber = ( - Regex(r"[+-]?\d+\.?\d*([eE][+-]?\d+)?") - .set_name("fnumber") - .set_parse_action(convert_to_float) - ) - """any int or real number, returned as float""" - - identifier = Word(identchars, identbodychars).set_name("identifier") - """typical code identifier (leading alpha or '_', followed by 0 or more alphas, nums, or '_')""" - - ipv4_address = Regex( - r"(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})(\.(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})){3}" - ).set_name("IPv4 address") - "IPv4 address (``0.0.0.0 - 255.255.255.255``)" - - _ipv6_part = Regex(r"[0-9a-fA-F]{1,4}").set_name("hex_integer") - _full_ipv6_address = (_ipv6_part + (":" + _ipv6_part) * 7).set_name( - "full IPv6 address" - ) - _short_ipv6_address = ( - Opt(_ipv6_part + (":" + _ipv6_part) * (0, 6)) - + "::" - + Opt(_ipv6_part + (":" + _ipv6_part) * (0, 6)) - ).set_name("short IPv6 address") - _short_ipv6_address.add_condition( - lambda t: sum(1 for tt in t if pyparsing_common._ipv6_part.matches(tt)) < 8 - ) - _mixed_ipv6_address = ("::ffff:" + ipv4_address).set_name("mixed IPv6 address") - ipv6_address = Combine( - (_full_ipv6_address | _mixed_ipv6_address | _short_ipv6_address).set_name( - "IPv6 address" - ) - ).set_name("IPv6 address") - "IPv6 address (long, short, or mixed form)" - - mac_address = Regex( - r"[0-9a-fA-F]{2}([:.-])[0-9a-fA-F]{2}(?:\1[0-9a-fA-F]{2}){4}" - ).set_name("MAC address") - "MAC address xx:xx:xx:xx:xx (may also have '-' or '.' delimiters)" - - @staticmethod - def convert_to_date(fmt: str = "%Y-%m-%d"): - """ - Helper to create a parse action for converting parsed date string to Python datetime.date - - Params - - - fmt - format to be passed to datetime.strptime (default= ``"%Y-%m-%d"``) - - Example:: - - date_expr = pyparsing_common.iso8601_date.copy() - date_expr.setParseAction(pyparsing_common.convertToDate()) - print(date_expr.parseString("1999-12-31")) - - prints:: - - [datetime.date(1999, 12, 31)] - """ - - def cvt_fn(ss, ll, tt): - try: - return datetime.strptime(tt[0], fmt).date() - except ValueError as ve: - raise ParseException(ss, ll, str(ve)) - - return cvt_fn - - @staticmethod - def convert_to_datetime(fmt: str = "%Y-%m-%dT%H:%M:%S.%f"): - """Helper to create a parse action for converting parsed - datetime string to Python datetime.datetime - - Params - - - fmt - format to be passed to datetime.strptime (default= ``"%Y-%m-%dT%H:%M:%S.%f"``) - - Example:: - - dt_expr = pyparsing_common.iso8601_datetime.copy() - dt_expr.setParseAction(pyparsing_common.convertToDatetime()) - print(dt_expr.parseString("1999-12-31T23:59:59.999")) - - prints:: - - [datetime.datetime(1999, 12, 31, 23, 59, 59, 999000)] - """ - - def cvt_fn(s, l, t): - try: - return datetime.strptime(t[0], fmt) - except ValueError as ve: - raise ParseException(s, l, str(ve)) - - return cvt_fn - - iso8601_date = Regex( - r"(?P\d{4})(?:-(?P\d\d)(?:-(?P\d\d))?)?" - ).set_name("ISO8601 date") - "ISO8601 date (``yyyy-mm-dd``)" - - iso8601_datetime = Regex( - r"(?P\d{4})-(?P\d\d)-(?P\d\d)[T ](?P\d\d):(?P\d\d)(:(?P\d\d(\.\d*)?)?)?(?PZ|[+-]\d\d:?\d\d)?" - ).set_name("ISO8601 datetime") - "ISO8601 datetime (``yyyy-mm-ddThh:mm:ss.s(Z|+-00:00)``) - trailing seconds, milliseconds, and timezone optional; accepts separating ``'T'`` or ``' '``" - - uuid = Regex(r"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}").set_name("UUID") - "UUID (``xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx``)" - - _html_stripper = any_open_tag.suppress() | any_close_tag.suppress() - - @staticmethod - def strip_html_tags(s: str, l: int, tokens: ParseResults): - """Parse action to remove HTML tags from web page HTML source - - Example:: - - # strip HTML links from normal text - text = 'More info at the
pyparsing wiki page' - td, td_end = makeHTMLTags("TD") - table_text = td + SkipTo(td_end).setParseAction(pyparsing_common.stripHTMLTags)("body") + td_end - print(table_text.parseString(text).body) - - Prints:: - - More info at the pyparsing wiki page - """ - return pyparsing_common._html_stripper.transform_string(tokens[0]) - - _commasepitem = ( - Combine( - OneOrMore( - ~Literal(",") - + ~LineEnd() - + Word(printables, exclude_chars=",") - + Opt(White(" \t") + ~FollowedBy(LineEnd() | ",")) - ) - ) - .streamline() - .set_name("commaItem") - ) - comma_separated_list = delimited_list( - Opt(quoted_string.copy() | _commasepitem, default="") - ).set_name("comma separated list") - """Predefined expression of 1 or more printable words or quoted strings, separated by commas.""" - - upcase_tokens = staticmethod(token_map(lambda t: t.upper())) - """Parse action to convert tokens to upper case.""" - - downcase_tokens = staticmethod(token_map(lambda t: t.lower())) - """Parse action to convert tokens to lower case.""" - - # fmt: off - url = Regex( - # https://mathiasbynens.be/demo/url-regex - # https://gist.github.com/dperini/729294 - r"^" + - # protocol identifier (optional) - # short syntax // still required - r"(?:(?:(?Phttps?|ftp):)?\/\/)" + - # user:pass BasicAuth (optional) - r"(?:(?P\S+(?::\S*)?)@)?" + - r"(?P" + - # IP address exclusion - # private & local networks - r"(?!(?:10|127)(?:\.\d{1,3}){3})" + - r"(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})" + - r"(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})" + - # IP address dotted notation octets - # excludes loopback network 0.0.0.0 - # excludes reserved space >= 224.0.0.0 - # excludes network & broadcast addresses - # (first & last IP address of each class) - r"(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])" + - r"(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}" + - r"(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))" + - r"|" + - # host & domain names, may end with dot - # can be replaced by a shortest alternative - # (?![-_])(?:[-\w\u00a1-\uffff]{0,63}[^-_]\.)+ - r"(?:" + - r"(?:" + - r"[a-z0-9\u00a1-\uffff]" + - r"[a-z0-9\u00a1-\uffff_-]{0,62}" + - r")?" + - r"[a-z0-9\u00a1-\uffff]\." + - r")+" + - # TLD identifier name, may end with dot - r"(?:[a-z\u00a1-\uffff]{2,}\.?)" + - r")" + - # port number (optional) - r"(:(?P\d{2,5}))?" + - # resource path (optional) - r"(?P\/[^?# ]*)?" + - # query string (optional) - r"(\?(?P[^#]*))?" + - # fragment (optional) - r"(#(?P\S*))?" + - r"$" - ).set_name("url") - # fmt: on - - # pre-PEP8 compatibility names - convertToInteger = convert_to_integer - convertToFloat = convert_to_float - convertToDate = convert_to_date - convertToDatetime = convert_to_datetime - stripHTMLTags = strip_html_tags - upcaseTokens = upcase_tokens - downcaseTokens = downcase_tokens - - -_builtin_exprs = [ - v for v in vars(pyparsing_common).values() if isinstance(v, ParserElement) -] diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/core.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/core.py deleted file mode 100755 index 9acba3f..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/core.py +++ /dev/null @@ -1,5814 +0,0 @@ -# -# core.py -# -import os -import typing -from typing import ( - NamedTuple, - Union, - Callable, - Any, - Generator, - Tuple, - List, - TextIO, - Set, - Sequence, -) -from abc import ABC, abstractmethod -from enum import Enum -import string -import copy -import warnings -import re -import sys -from collections.abc import Iterable -import traceback -import types -from operator import itemgetter -from functools import wraps -from threading import RLock -from pathlib import Path - -from .util import ( - _FifoCache, - _UnboundedCache, - __config_flags, - _collapse_string_to_ranges, - _escape_regex_range_chars, - _bslash, - _flatten, - LRUMemo as _LRUMemo, - UnboundedMemo as _UnboundedMemo, -) -from .exceptions import * -from .actions import * -from .results import ParseResults, _ParseResultsWithOffset -from .unicode import pyparsing_unicode - -_MAX_INT = sys.maxsize -str_type: Tuple[type, ...] = (str, bytes) - -# -# Copyright (c) 2003-2022 Paul T. McGuire -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - - -if sys.version_info >= (3, 8): - from functools import cached_property -else: - - class cached_property: - def __init__(self, func): - self._func = func - - def __get__(self, instance, owner=None): - ret = instance.__dict__[self._func.__name__] = self._func(instance) - return ret - - -class __compat__(__config_flags): - """ - A cross-version compatibility configuration for pyparsing features that will be - released in a future version. By setting values in this configuration to True, - those features can be enabled in prior versions for compatibility development - and testing. - - - ``collect_all_And_tokens`` - flag to enable fix for Issue #63 that fixes erroneous grouping - of results names when an :class:`And` expression is nested within an :class:`Or` or :class:`MatchFirst`; - maintained for compatibility, but setting to ``False`` no longer restores pre-2.3.1 - behavior - """ - - _type_desc = "compatibility" - - collect_all_And_tokens = True - - _all_names = [__ for __ in locals() if not __.startswith("_")] - _fixed_names = """ - collect_all_And_tokens - """.split() - - -class __diag__(__config_flags): - _type_desc = "diagnostic" - - warn_multiple_tokens_in_named_alternation = False - warn_ungrouped_named_tokens_in_collection = False - warn_name_set_on_empty_Forward = False - warn_on_parse_using_empty_Forward = False - warn_on_assignment_to_Forward = False - warn_on_multiple_string_args_to_oneof = False - warn_on_match_first_with_lshift_operator = False - enable_debug_on_named_expressions = False - - _all_names = [__ for __ in locals() if not __.startswith("_")] - _warning_names = [name for name in _all_names if name.startswith("warn")] - _debug_names = [name for name in _all_names if name.startswith("enable_debug")] - - @classmethod - def enable_all_warnings(cls) -> None: - for name in cls._warning_names: - cls.enable(name) - - -class Diagnostics(Enum): - """ - Diagnostic configuration (all default to disabled) - - ``warn_multiple_tokens_in_named_alternation`` - flag to enable warnings when a results - name is defined on a :class:`MatchFirst` or :class:`Or` expression with one or more :class:`And` subexpressions - - ``warn_ungrouped_named_tokens_in_collection`` - flag to enable warnings when a results - name is defined on a containing expression with ungrouped subexpressions that also - have results names - - ``warn_name_set_on_empty_Forward`` - flag to enable warnings when a :class:`Forward` is defined - with a results name, but has no contents defined - - ``warn_on_parse_using_empty_Forward`` - flag to enable warnings when a :class:`Forward` is - defined in a grammar but has never had an expression attached to it - - ``warn_on_assignment_to_Forward`` - flag to enable warnings when a :class:`Forward` is defined - but is overwritten by assigning using ``'='`` instead of ``'<<='`` or ``'<<'`` - - ``warn_on_multiple_string_args_to_oneof`` - flag to enable warnings when :class:`one_of` is - incorrectly called with multiple str arguments - - ``enable_debug_on_named_expressions`` - flag to auto-enable debug on all subsequent - calls to :class:`ParserElement.set_name` - - Diagnostics are enabled/disabled by calling :class:`enable_diag` and :class:`disable_diag`. - All warnings can be enabled by calling :class:`enable_all_warnings`. - """ - - warn_multiple_tokens_in_named_alternation = 0 - warn_ungrouped_named_tokens_in_collection = 1 - warn_name_set_on_empty_Forward = 2 - warn_on_parse_using_empty_Forward = 3 - warn_on_assignment_to_Forward = 4 - warn_on_multiple_string_args_to_oneof = 5 - warn_on_match_first_with_lshift_operator = 6 - enable_debug_on_named_expressions = 7 - - -def enable_diag(diag_enum: Diagnostics) -> None: - """ - Enable a global pyparsing diagnostic flag (see :class:`Diagnostics`). - """ - __diag__.enable(diag_enum.name) - - -def disable_diag(diag_enum: Diagnostics) -> None: - """ - Disable a global pyparsing diagnostic flag (see :class:`Diagnostics`). - """ - __diag__.disable(diag_enum.name) - - -def enable_all_warnings() -> None: - """ - Enable all global pyparsing diagnostic warnings (see :class:`Diagnostics`). - """ - __diag__.enable_all_warnings() - - -# hide abstract class -del __config_flags - - -def _should_enable_warnings( - cmd_line_warn_options: typing.Iterable[str], warn_env_var: typing.Optional[str] -) -> bool: - enable = bool(warn_env_var) - for warn_opt in cmd_line_warn_options: - w_action, w_message, w_category, w_module, w_line = (warn_opt + "::::").split( - ":" - )[:5] - if not w_action.lower().startswith("i") and ( - not (w_message or w_category or w_module) or w_module == "pyparsing" - ): - enable = True - elif w_action.lower().startswith("i") and w_module in ("pyparsing", ""): - enable = False - return enable - - -if _should_enable_warnings( - sys.warnoptions, os.environ.get("PYPARSINGENABLEALLWARNINGS") -): - enable_all_warnings() - - -# build list of single arg builtins, that can be used as parse actions -_single_arg_builtins = { - sum, - len, - sorted, - reversed, - list, - tuple, - set, - any, - all, - min, - max, -} - -_generatorType = types.GeneratorType -ParseAction = Union[ - Callable[[], Any], - Callable[[ParseResults], Any], - Callable[[int, ParseResults], Any], - Callable[[str, int, ParseResults], Any], -] -ParseCondition = Union[ - Callable[[], bool], - Callable[[ParseResults], bool], - Callable[[int, ParseResults], bool], - Callable[[str, int, ParseResults], bool], -] -ParseFailAction = Callable[[str, int, "ParserElement", Exception], None] -DebugStartAction = Callable[[str, int, "ParserElement", bool], None] -DebugSuccessAction = Callable[ - [str, int, int, "ParserElement", ParseResults, bool], None -] -DebugExceptionAction = Callable[[str, int, "ParserElement", Exception, bool], None] - - -alphas = string.ascii_uppercase + string.ascii_lowercase -identchars = pyparsing_unicode.Latin1.identchars -identbodychars = pyparsing_unicode.Latin1.identbodychars -nums = "0123456789" -hexnums = nums + "ABCDEFabcdef" -alphanums = alphas + nums -printables = "".join([c for c in string.printable if c not in string.whitespace]) - -_trim_arity_call_line: traceback.StackSummary = None - - -def _trim_arity(func, max_limit=3): - """decorator to trim function calls to match the arity of the target""" - global _trim_arity_call_line - - if func in _single_arg_builtins: - return lambda s, l, t: func(t) - - limit = 0 - found_arity = False - - def extract_tb(tb, limit=0): - frames = traceback.extract_tb(tb, limit=limit) - frame_summary = frames[-1] - return [frame_summary[:2]] - - # synthesize what would be returned by traceback.extract_stack at the call to - # user's parse action 'func', so that we don't incur call penalty at parse time - - # fmt: off - LINE_DIFF = 7 - # IF ANY CODE CHANGES, EVEN JUST COMMENTS OR BLANK LINES, BETWEEN THE NEXT LINE AND - # THE CALL TO FUNC INSIDE WRAPPER, LINE_DIFF MUST BE MODIFIED!!!! - _trim_arity_call_line = (_trim_arity_call_line or traceback.extract_stack(limit=2)[-1]) - pa_call_line_synth = (_trim_arity_call_line[0], _trim_arity_call_line[1] + LINE_DIFF) - - def wrapper(*args): - nonlocal found_arity, limit - while 1: - try: - ret = func(*args[limit:]) - found_arity = True - return ret - except TypeError as te: - # re-raise TypeErrors if they did not come from our arity testing - if found_arity: - raise - else: - tb = te.__traceback__ - trim_arity_type_error = ( - extract_tb(tb, limit=2)[-1][:2] == pa_call_line_synth - ) - del tb - - if trim_arity_type_error: - if limit < max_limit: - limit += 1 - continue - - raise - # fmt: on - - # copy func name to wrapper for sensible debug output - # (can't use functools.wraps, since that messes with function signature) - func_name = getattr(func, "__name__", getattr(func, "__class__").__name__) - wrapper.__name__ = func_name - wrapper.__doc__ = func.__doc__ - - return wrapper - - -def condition_as_parse_action( - fn: ParseCondition, message: str = None, fatal: bool = False -) -> ParseAction: - """ - Function to convert a simple predicate function that returns ``True`` or ``False`` - into a parse action. Can be used in places when a parse action is required - and :class:`ParserElement.add_condition` cannot be used (such as when adding a condition - to an operator level in :class:`infix_notation`). - - Optional keyword arguments: - - - ``message`` - define a custom message to be used in the raised exception - - ``fatal`` - if True, will raise :class:`ParseFatalException` to stop parsing immediately; - otherwise will raise :class:`ParseException` - - """ - msg = message if message is not None else "failed user-defined condition" - exc_type = ParseFatalException if fatal else ParseException - fn = _trim_arity(fn) - - @wraps(fn) - def pa(s, l, t): - if not bool(fn(s, l, t)): - raise exc_type(s, l, msg) - - return pa - - -def _default_start_debug_action( - instring: str, loc: int, expr: "ParserElement", cache_hit: bool = False -): - cache_hit_str = "*" if cache_hit else "" - print( - ( - "{}Match {} at loc {}({},{})\n {}\n {}^".format( - cache_hit_str, - expr, - loc, - lineno(loc, instring), - col(loc, instring), - line(loc, instring), - " " * (col(loc, instring) - 1), - ) - ) - ) - - -def _default_success_debug_action( - instring: str, - startloc: int, - endloc: int, - expr: "ParserElement", - toks: ParseResults, - cache_hit: bool = False, -): - cache_hit_str = "*" if cache_hit else "" - print("{}Matched {} -> {}".format(cache_hit_str, expr, toks.as_list())) - - -def _default_exception_debug_action( - instring: str, - loc: int, - expr: "ParserElement", - exc: Exception, - cache_hit: bool = False, -): - cache_hit_str = "*" if cache_hit else "" - print( - "{}Match {} failed, {} raised: {}".format( - cache_hit_str, expr, type(exc).__name__, exc - ) - ) - - -def null_debug_action(*args): - """'Do-nothing' debug action, to suppress debugging output during parsing.""" - - -class ParserElement(ABC): - """Abstract base level parser element class.""" - - DEFAULT_WHITE_CHARS: str = " \n\t\r" - verbose_stacktrace: bool = False - _literalStringClass: typing.Optional[type] = None - - @staticmethod - def set_default_whitespace_chars(chars: str) -> None: - r""" - Overrides the default whitespace chars - - Example:: - - # default whitespace chars are space, and newline - Word(alphas)[1, ...].parse_string("abc def\nghi jkl") # -> ['abc', 'def', 'ghi', 'jkl'] - - # change to just treat newline as significant - ParserElement.set_default_whitespace_chars(" \t") - Word(alphas)[1, ...].parse_string("abc def\nghi jkl") # -> ['abc', 'def'] - """ - ParserElement.DEFAULT_WHITE_CHARS = chars - - # update whitespace all parse expressions defined in this module - for expr in _builtin_exprs: - if expr.copyDefaultWhiteChars: - expr.whiteChars = set(chars) - - @staticmethod - def inline_literals_using(cls: type) -> None: - """ - Set class to be used for inclusion of string literals into a parser. - - Example:: - - # default literal class used is Literal - integer = Word(nums) - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - date_str.parse_string("1999/12/31") # -> ['1999', '/', '12', '/', '31'] - - - # change to Suppress - ParserElement.inline_literals_using(Suppress) - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - date_str.parse_string("1999/12/31") # -> ['1999', '12', '31'] - """ - ParserElement._literalStringClass = cls - - class DebugActions(NamedTuple): - debug_try: typing.Optional[DebugStartAction] - debug_match: typing.Optional[DebugSuccessAction] - debug_fail: typing.Optional[DebugExceptionAction] - - def __init__(self, savelist: bool = False): - self.parseAction: List[ParseAction] = list() - self.failAction: typing.Optional[ParseFailAction] = None - self.customName = None - self._defaultName = None - self.resultsName = None - self.saveAsList = savelist - self.skipWhitespace = True - self.whiteChars = set(ParserElement.DEFAULT_WHITE_CHARS) - self.copyDefaultWhiteChars = True - # used when checking for left-recursion - self.mayReturnEmpty = False - self.keepTabs = False - self.ignoreExprs: List["ParserElement"] = list() - self.debug = False - self.streamlined = False - # optimize exception handling for subclasses that don't advance parse index - self.mayIndexError = True - self.errmsg = "" - # mark results names as modal (report only last) or cumulative (list all) - self.modalResults = True - # custom debug actions - self.debugActions = self.DebugActions(None, None, None) - # avoid redundant calls to preParse - self.callPreparse = True - self.callDuringTry = False - self.suppress_warnings_: List[Diagnostics] = [] - - def suppress_warning(self, warning_type: Diagnostics) -> "ParserElement": - """ - Suppress warnings emitted for a particular diagnostic on this expression. - - Example:: - - base = pp.Forward() - base.suppress_warning(Diagnostics.warn_on_parse_using_empty_Forward) - - # statement would normally raise a warning, but is now suppressed - print(base.parseString("x")) - - """ - self.suppress_warnings_.append(warning_type) - return self - - def copy(self) -> "ParserElement": - """ - Make a copy of this :class:`ParserElement`. Useful for defining - different parse actions for the same parsing pattern, using copies of - the original parse element. - - Example:: - - integer = Word(nums).set_parse_action(lambda toks: int(toks[0])) - integerK = integer.copy().add_parse_action(lambda toks: toks[0] * 1024) + Suppress("K") - integerM = integer.copy().add_parse_action(lambda toks: toks[0] * 1024 * 1024) + Suppress("M") - - print((integerK | integerM | integer)[1, ...].parse_string("5K 100 640K 256M")) - - prints:: - - [5120, 100, 655360, 268435456] - - Equivalent form of ``expr.copy()`` is just ``expr()``:: - - integerM = integer().add_parse_action(lambda toks: toks[0] * 1024 * 1024) + Suppress("M") - """ - cpy = copy.copy(self) - cpy.parseAction = self.parseAction[:] - cpy.ignoreExprs = self.ignoreExprs[:] - if self.copyDefaultWhiteChars: - cpy.whiteChars = set(ParserElement.DEFAULT_WHITE_CHARS) - return cpy - - def set_results_name( - self, name: str, list_all_matches: bool = False, *, listAllMatches: bool = False - ) -> "ParserElement": - """ - Define name for referencing matching tokens as a nested attribute - of the returned parse results. - - Normally, results names are assigned as you would assign keys in a dict: - any existing value is overwritten by later values. If it is necessary to - keep all values captured for a particular results name, call ``set_results_name`` - with ``list_all_matches`` = True. - - NOTE: ``set_results_name`` returns a *copy* of the original :class:`ParserElement` object; - this is so that the client can define a basic element, such as an - integer, and reference it in multiple places with different names. - - You can also set results names using the abbreviated syntax, - ``expr("name")`` in place of ``expr.set_results_name("name")`` - - see :class:`__call__`. If ``list_all_matches`` is required, use - ``expr("name*")``. - - Example:: - - date_str = (integer.set_results_name("year") + '/' - + integer.set_results_name("month") + '/' - + integer.set_results_name("day")) - - # equivalent form: - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - """ - listAllMatches = listAllMatches or list_all_matches - return self._setResultsName(name, listAllMatches) - - def _setResultsName(self, name, listAllMatches=False): - if name is None: - return self - newself = self.copy() - if name.endswith("*"): - name = name[:-1] - listAllMatches = True - newself.resultsName = name - newself.modalResults = not listAllMatches - return newself - - def set_break(self, break_flag: bool = True) -> "ParserElement": - """ - Method to invoke the Python pdb debugger when this element is - about to be parsed. Set ``break_flag`` to ``True`` to enable, ``False`` to - disable. - """ - if break_flag: - _parseMethod = self._parse - - def breaker(instring, loc, doActions=True, callPreParse=True): - import pdb - - # this call to pdb.set_trace() is intentional, not a checkin error - pdb.set_trace() - return _parseMethod(instring, loc, doActions, callPreParse) - - breaker._originalParseMethod = _parseMethod - self._parse = breaker - else: - if hasattr(self._parse, "_originalParseMethod"): - self._parse = self._parse._originalParseMethod - return self - - def set_parse_action(self, *fns: ParseAction, **kwargs) -> "ParserElement": - """ - Define one or more actions to perform when successfully matching parse element definition. - - Parse actions can be called to perform data conversions, do extra validation, - update external data structures, or enhance or replace the parsed tokens. - Each parse action ``fn`` is a callable method with 0-3 arguments, called as - ``fn(s, loc, toks)`` , ``fn(loc, toks)`` , ``fn(toks)`` , or just ``fn()`` , where: - - - s = the original string being parsed (see note below) - - loc = the location of the matching substring - - toks = a list of the matched tokens, packaged as a :class:`ParseResults` object - - The parsed tokens are passed to the parse action as ParseResults. They can be - modified in place using list-style append, extend, and pop operations to update - the parsed list elements; and with dictionary-style item set and del operations - to add, update, or remove any named results. If the tokens are modified in place, - it is not necessary to return them with a return statement. - - Parse actions can also completely replace the given tokens, with another ``ParseResults`` - object, or with some entirely different object (common for parse actions that perform data - conversions). A convenient way to build a new parse result is to define the values - using a dict, and then create the return value using :class:`ParseResults.from_dict`. - - If None is passed as the ``fn`` parse action, all previously added parse actions for this - expression are cleared. - - Optional keyword arguments: - - - call_during_try = (default= ``False``) indicate if parse action should be run during - lookaheads and alternate testing. For parse actions that have side effects, it is - important to only call the parse action once it is determined that it is being - called as part of a successful parse. For parse actions that perform additional - validation, then call_during_try should be passed as True, so that the validation - code is included in the preliminary "try" parses. - - Note: the default parsing behavior is to expand tabs in the input string - before starting the parsing process. See :class:`parse_string` for more - information on parsing strings containing ```` s, and suggested - methods to maintain a consistent view of the parsed string, the parse - location, and line and column positions within the parsed string. - - Example:: - - # parse dates in the form YYYY/MM/DD - - # use parse action to convert toks from str to int at parse time - def convert_to_int(toks): - return int(toks[0]) - - # use a parse action to verify that the date is a valid date - def is_valid_date(instring, loc, toks): - from datetime import date - year, month, day = toks[::2] - try: - date(year, month, day) - except ValueError: - raise ParseException(instring, loc, "invalid date given") - - integer = Word(nums) - date_str = integer + '/' + integer + '/' + integer - - # add parse actions - integer.set_parse_action(convert_to_int) - date_str.set_parse_action(is_valid_date) - - # note that integer fields are now ints, not strings - date_str.run_tests(''' - # successful parse - note that integer fields were converted to ints - 1999/12/31 - - # fail - invalid date - 1999/13/31 - ''') - """ - if list(fns) == [None]: - self.parseAction = [] - else: - if not all(callable(fn) for fn in fns): - raise TypeError("parse actions must be callable") - self.parseAction = [_trim_arity(fn) for fn in fns] - self.callDuringTry = kwargs.get( - "call_during_try", kwargs.get("callDuringTry", False) - ) - return self - - def add_parse_action(self, *fns: ParseAction, **kwargs) -> "ParserElement": - """ - Add one or more parse actions to expression's list of parse actions. See :class:`set_parse_action`. - - See examples in :class:`copy`. - """ - self.parseAction += [_trim_arity(fn) for fn in fns] - self.callDuringTry = self.callDuringTry or kwargs.get( - "call_during_try", kwargs.get("callDuringTry", False) - ) - return self - - def add_condition(self, *fns: ParseCondition, **kwargs) -> "ParserElement": - """Add a boolean predicate function to expression's list of parse actions. See - :class:`set_parse_action` for function call signatures. Unlike ``set_parse_action``, - functions passed to ``add_condition`` need to return boolean success/fail of the condition. - - Optional keyword arguments: - - - message = define a custom message to be used in the raised exception - - fatal = if True, will raise ParseFatalException to stop parsing immediately; otherwise will raise - ParseException - - call_during_try = boolean to indicate if this method should be called during internal tryParse calls, - default=False - - Example:: - - integer = Word(nums).set_parse_action(lambda toks: int(toks[0])) - year_int = integer.copy() - year_int.add_condition(lambda toks: toks[0] >= 2000, message="Only support years 2000 and later") - date_str = year_int + '/' + integer + '/' + integer - - result = date_str.parse_string("1999/12/31") # -> Exception: Only support years 2000 and later (at char 0), - (line:1, col:1) - """ - for fn in fns: - self.parseAction.append( - condition_as_parse_action( - fn, message=kwargs.get("message"), fatal=kwargs.get("fatal", False) - ) - ) - - self.callDuringTry = self.callDuringTry or kwargs.get( - "call_during_try", kwargs.get("callDuringTry", False) - ) - return self - - def set_fail_action(self, fn: ParseFailAction) -> "ParserElement": - """ - Define action to perform if parsing fails at this expression. - Fail acton fn is a callable function that takes the arguments - ``fn(s, loc, expr, err)`` where: - - - s = string being parsed - - loc = location where expression match was attempted and failed - - expr = the parse expression that failed - - err = the exception thrown - - The function returns no value. It may throw :class:`ParseFatalException` - if it is desired to stop parsing immediately.""" - self.failAction = fn - return self - - def _skipIgnorables(self, instring, loc): - exprsFound = True - while exprsFound: - exprsFound = False - for e in self.ignoreExprs: - try: - while 1: - loc, dummy = e._parse(instring, loc) - exprsFound = True - except ParseException: - pass - return loc - - def preParse(self, instring, loc): - if self.ignoreExprs: - loc = self._skipIgnorables(instring, loc) - - if self.skipWhitespace: - instrlen = len(instring) - white_chars = self.whiteChars - while loc < instrlen and instring[loc] in white_chars: - loc += 1 - - return loc - - def parseImpl(self, instring, loc, doActions=True): - return loc, [] - - def postParse(self, instring, loc, tokenlist): - return tokenlist - - # @profile - def _parseNoCache( - self, instring, loc, doActions=True, callPreParse=True - ) -> Tuple[int, ParseResults]: - TRY, MATCH, FAIL = 0, 1, 2 - debugging = self.debug # and doActions) - len_instring = len(instring) - - if debugging or self.failAction: - # print("Match {} at loc {}({}, {})".format(self, loc, lineno(loc, instring), col(loc, instring))) - try: - if callPreParse and self.callPreparse: - pre_loc = self.preParse(instring, loc) - else: - pre_loc = loc - tokens_start = pre_loc - if self.debugActions.debug_try: - self.debugActions.debug_try(instring, tokens_start, self, False) - if self.mayIndexError or pre_loc >= len_instring: - try: - loc, tokens = self.parseImpl(instring, pre_loc, doActions) - except IndexError: - raise ParseException(instring, len_instring, self.errmsg, self) - else: - loc, tokens = self.parseImpl(instring, pre_loc, doActions) - except Exception as err: - # print("Exception raised:", err) - if self.debugActions.debug_fail: - self.debugActions.debug_fail( - instring, tokens_start, self, err, False - ) - if self.failAction: - self.failAction(instring, tokens_start, self, err) - raise - else: - if callPreParse and self.callPreparse: - pre_loc = self.preParse(instring, loc) - else: - pre_loc = loc - tokens_start = pre_loc - if self.mayIndexError or pre_loc >= len_instring: - try: - loc, tokens = self.parseImpl(instring, pre_loc, doActions) - except IndexError: - raise ParseException(instring, len_instring, self.errmsg, self) - else: - loc, tokens = self.parseImpl(instring, pre_loc, doActions) - - tokens = self.postParse(instring, loc, tokens) - - ret_tokens = ParseResults( - tokens, self.resultsName, asList=self.saveAsList, modal=self.modalResults - ) - if self.parseAction and (doActions or self.callDuringTry): - if debugging: - try: - for fn in self.parseAction: - try: - tokens = fn(instring, tokens_start, ret_tokens) - except IndexError as parse_action_exc: - exc = ParseException("exception raised in parse action") - raise exc from parse_action_exc - - if tokens is not None and tokens is not ret_tokens: - ret_tokens = ParseResults( - tokens, - self.resultsName, - asList=self.saveAsList - and isinstance(tokens, (ParseResults, list)), - modal=self.modalResults, - ) - except Exception as err: - # print "Exception raised in user parse action:", err - if self.debugActions.debug_fail: - self.debugActions.debug_fail( - instring, tokens_start, self, err, False - ) - raise - else: - for fn in self.parseAction: - try: - tokens = fn(instring, tokens_start, ret_tokens) - except IndexError as parse_action_exc: - exc = ParseException("exception raised in parse action") - raise exc from parse_action_exc - - if tokens is not None and tokens is not ret_tokens: - ret_tokens = ParseResults( - tokens, - self.resultsName, - asList=self.saveAsList - and isinstance(tokens, (ParseResults, list)), - modal=self.modalResults, - ) - if debugging: - # print("Matched", self, "->", ret_tokens.as_list()) - if self.debugActions.debug_match: - self.debugActions.debug_match( - instring, tokens_start, loc, self, ret_tokens, False - ) - - return loc, ret_tokens - - def try_parse(self, instring: str, loc: int, raise_fatal: bool = False) -> int: - try: - return self._parse(instring, loc, doActions=False)[0] - except ParseFatalException: - if raise_fatal: - raise - raise ParseException(instring, loc, self.errmsg, self) - - def can_parse_next(self, instring: str, loc: int) -> bool: - try: - self.try_parse(instring, loc) - except (ParseException, IndexError): - return False - else: - return True - - # cache for left-recursion in Forward references - recursion_lock = RLock() - recursion_memos: typing.Dict[ - Tuple[int, "Forward", bool], Tuple[int, Union[ParseResults, Exception]] - ] = {} - - # argument cache for optimizing repeated calls when backtracking through recursive expressions - packrat_cache = ( - {} - ) # this is set later by enabled_packrat(); this is here so that reset_cache() doesn't fail - packrat_cache_lock = RLock() - packrat_cache_stats = [0, 0] - - # this method gets repeatedly called during backtracking with the same arguments - - # we can cache these arguments and save ourselves the trouble of re-parsing the contained expression - def _parseCache( - self, instring, loc, doActions=True, callPreParse=True - ) -> Tuple[int, ParseResults]: - HIT, MISS = 0, 1 - TRY, MATCH, FAIL = 0, 1, 2 - lookup = (self, instring, loc, callPreParse, doActions) - with ParserElement.packrat_cache_lock: - cache = ParserElement.packrat_cache - value = cache.get(lookup) - if value is cache.not_in_cache: - ParserElement.packrat_cache_stats[MISS] += 1 - try: - value = self._parseNoCache(instring, loc, doActions, callPreParse) - except ParseBaseException as pe: - # cache a copy of the exception, without the traceback - cache.set(lookup, pe.__class__(*pe.args)) - raise - else: - cache.set(lookup, (value[0], value[1].copy(), loc)) - return value - else: - ParserElement.packrat_cache_stats[HIT] += 1 - if self.debug and self.debugActions.debug_try: - try: - self.debugActions.debug_try(instring, loc, self, cache_hit=True) - except TypeError: - pass - if isinstance(value, Exception): - if self.debug and self.debugActions.debug_fail: - try: - self.debugActions.debug_fail( - instring, loc, self, value, cache_hit=True - ) - except TypeError: - pass - raise value - - loc_, result, endloc = value[0], value[1].copy(), value[2] - if self.debug and self.debugActions.debug_match: - try: - self.debugActions.debug_match( - instring, loc_, endloc, self, result, cache_hit=True - ) - except TypeError: - pass - - return loc_, result - - _parse = _parseNoCache - - @staticmethod - def reset_cache() -> None: - ParserElement.packrat_cache.clear() - ParserElement.packrat_cache_stats[:] = [0] * len( - ParserElement.packrat_cache_stats - ) - ParserElement.recursion_memos.clear() - - _packratEnabled = False - _left_recursion_enabled = False - - @staticmethod - def disable_memoization() -> None: - """ - Disables active Packrat or Left Recursion parsing and their memoization - - This method also works if neither Packrat nor Left Recursion are enabled. - This makes it safe to call before activating Packrat nor Left Recursion - to clear any previous settings. - """ - ParserElement.reset_cache() - ParserElement._left_recursion_enabled = False - ParserElement._packratEnabled = False - ParserElement._parse = ParserElement._parseNoCache - - @staticmethod - def enable_left_recursion( - cache_size_limit: typing.Optional[int] = None, *, force=False - ) -> None: - """ - Enables "bounded recursion" parsing, which allows for both direct and indirect - left-recursion. During parsing, left-recursive :class:`Forward` elements are - repeatedly matched with a fixed recursion depth that is gradually increased - until finding the longest match. - - Example:: - - import pyparsing as pp - pp.ParserElement.enable_left_recursion() - - E = pp.Forward("E") - num = pp.Word(pp.nums) - # match `num`, or `num '+' num`, or `num '+' num '+' num`, ... - E <<= E + '+' - num | num - - print(E.parse_string("1+2+3")) - - Recursion search naturally memoizes matches of ``Forward`` elements and may - thus skip reevaluation of parse actions during backtracking. This may break - programs with parse actions which rely on strict ordering of side-effects. - - Parameters: - - - cache_size_limit - (default=``None``) - memoize at most this many - ``Forward`` elements during matching; if ``None`` (the default), - memoize all ``Forward`` elements. - - Bounded Recursion parsing works similar but not identical to Packrat parsing, - thus the two cannot be used together. Use ``force=True`` to disable any - previous, conflicting settings. - """ - if force: - ParserElement.disable_memoization() - elif ParserElement._packratEnabled: - raise RuntimeError("Packrat and Bounded Recursion are not compatible") - if cache_size_limit is None: - ParserElement.recursion_memos = _UnboundedMemo() - elif cache_size_limit > 0: - ParserElement.recursion_memos = _LRUMemo(capacity=cache_size_limit) - else: - raise NotImplementedError("Memo size of %s" % cache_size_limit) - ParserElement._left_recursion_enabled = True - - @staticmethod - def enable_packrat(cache_size_limit: int = 128, *, force: bool = False) -> None: - """ - Enables "packrat" parsing, which adds memoizing to the parsing logic. - Repeated parse attempts at the same string location (which happens - often in many complex grammars) can immediately return a cached value, - instead of re-executing parsing/validating code. Memoizing is done of - both valid results and parsing exceptions. - - Parameters: - - - cache_size_limit - (default= ``128``) - if an integer value is provided - will limit the size of the packrat cache; if None is passed, then - the cache size will be unbounded; if 0 is passed, the cache will - be effectively disabled. - - This speedup may break existing programs that use parse actions that - have side-effects. For this reason, packrat parsing is disabled when - you first import pyparsing. To activate the packrat feature, your - program must call the class method :class:`ParserElement.enable_packrat`. - For best results, call ``enable_packrat()`` immediately after - importing pyparsing. - - Example:: - - import pyparsing - pyparsing.ParserElement.enable_packrat() - - Packrat parsing works similar but not identical to Bounded Recursion parsing, - thus the two cannot be used together. Use ``force=True`` to disable any - previous, conflicting settings. - """ - if force: - ParserElement.disable_memoization() - elif ParserElement._left_recursion_enabled: - raise RuntimeError("Packrat and Bounded Recursion are not compatible") - if not ParserElement._packratEnabled: - ParserElement._packratEnabled = True - if cache_size_limit is None: - ParserElement.packrat_cache = _UnboundedCache() - else: - ParserElement.packrat_cache = _FifoCache(cache_size_limit) - ParserElement._parse = ParserElement._parseCache - - def parse_string( - self, instring: str, parse_all: bool = False, *, parseAll: bool = False - ) -> ParseResults: - """ - Parse a string with respect to the parser definition. This function is intended as the primary interface to the - client code. - - :param instring: The input string to be parsed. - :param parse_all: If set, the entire input string must match the grammar. - :param parseAll: retained for pre-PEP8 compatibility, will be removed in a future release. - :raises ParseException: Raised if ``parse_all`` is set and the input string does not match the whole grammar. - :returns: the parsed data as a :class:`ParseResults` object, which may be accessed as a `list`, a `dict`, or - an object with attributes if the given parser includes results names. - - If the input string is required to match the entire grammar, ``parse_all`` flag must be set to ``True``. This - is also equivalent to ending the grammar with :class:`StringEnd`(). - - To report proper column numbers, ``parse_string`` operates on a copy of the input string where all tabs are - converted to spaces (8 spaces per tab, as per the default in ``string.expandtabs``). If the input string - contains tabs and the grammar uses parse actions that use the ``loc`` argument to index into the string - being parsed, one can ensure a consistent view of the input string by doing one of the following: - - - calling ``parse_with_tabs`` on your grammar before calling ``parse_string`` (see :class:`parse_with_tabs`), - - define your parse action using the full ``(s,loc,toks)`` signature, and reference the input string using the - parse action's ``s`` argument, or - - explicitly expand the tabs in your input string before calling ``parse_string``. - - Examples: - - By default, partial matches are OK. - - >>> res = Word('a').parse_string('aaaaabaaa') - >>> print(res) - ['aaaaa'] - - The parsing behavior varies by the inheriting class of this abstract class. Please refer to the children - directly to see more examples. - - It raises an exception if parse_all flag is set and instring does not match the whole grammar. - - >>> res = Word('a').parse_string('aaaaabaaa', parse_all=True) - Traceback (most recent call last): - ... - pyparsing.ParseException: Expected end of text, found 'b' (at char 5), (line:1, col:6) - """ - parseAll = parse_all or parseAll - - ParserElement.reset_cache() - if not self.streamlined: - self.streamline() - for e in self.ignoreExprs: - e.streamline() - if not self.keepTabs: - instring = instring.expandtabs() - try: - loc, tokens = self._parse(instring, 0) - if parseAll: - loc = self.preParse(instring, loc) - se = Empty() + StringEnd() - se._parse(instring, loc) - except ParseBaseException as exc: - if ParserElement.verbose_stacktrace: - raise - else: - # catch and re-raise exception from here, clearing out pyparsing internal stack trace - raise exc.with_traceback(None) - else: - return tokens - - def scan_string( - self, - instring: str, - max_matches: int = _MAX_INT, - overlap: bool = False, - *, - debug: bool = False, - maxMatches: int = _MAX_INT, - ) -> Generator[Tuple[ParseResults, int, int], None, None]: - """ - Scan the input string for expression matches. Each match will return the - matching tokens, start location, and end location. May be called with optional - ``max_matches`` argument, to clip scanning after 'n' matches are found. If - ``overlap`` is specified, then overlapping matches will be reported. - - Note that the start and end locations are reported relative to the string - being parsed. See :class:`parse_string` for more information on parsing - strings with embedded tabs. - - Example:: - - source = "sldjf123lsdjjkf345sldkjf879lkjsfd987" - print(source) - for tokens, start, end in Word(alphas).scan_string(source): - print(' '*start + '^'*(end-start)) - print(' '*start + tokens[0]) - - prints:: - - sldjf123lsdjjkf345sldkjf879lkjsfd987 - ^^^^^ - sldjf - ^^^^^^^ - lsdjjkf - ^^^^^^ - sldkjf - ^^^^^^ - lkjsfd - """ - maxMatches = min(maxMatches, max_matches) - if not self.streamlined: - self.streamline() - for e in self.ignoreExprs: - e.streamline() - - if not self.keepTabs: - instring = str(instring).expandtabs() - instrlen = len(instring) - loc = 0 - preparseFn = self.preParse - parseFn = self._parse - ParserElement.resetCache() - matches = 0 - try: - while loc <= instrlen and matches < maxMatches: - try: - preloc = preparseFn(instring, loc) - nextLoc, tokens = parseFn(instring, preloc, callPreParse=False) - except ParseException: - loc = preloc + 1 - else: - if nextLoc > loc: - matches += 1 - if debug: - print( - { - "tokens": tokens.asList(), - "start": preloc, - "end": nextLoc, - } - ) - yield tokens, preloc, nextLoc - if overlap: - nextloc = preparseFn(instring, loc) - if nextloc > loc: - loc = nextLoc - else: - loc += 1 - else: - loc = nextLoc - else: - loc = preloc + 1 - except ParseBaseException as exc: - if ParserElement.verbose_stacktrace: - raise - else: - # catch and re-raise exception from here, clears out pyparsing internal stack trace - raise exc.with_traceback(None) - - def transform_string(self, instring: str, *, debug: bool = False) -> str: - """ - Extension to :class:`scan_string`, to modify matching text with modified tokens that may - be returned from a parse action. To use ``transform_string``, define a grammar and - attach a parse action to it that modifies the returned token list. - Invoking ``transform_string()`` on a target string will then scan for matches, - and replace the matched text patterns according to the logic in the parse - action. ``transform_string()`` returns the resulting transformed string. - - Example:: - - wd = Word(alphas) - wd.set_parse_action(lambda toks: toks[0].title()) - - print(wd.transform_string("now is the winter of our discontent made glorious summer by this sun of york.")) - - prints:: - - Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York. - """ - out: List[str] = [] - lastE = 0 - # force preservation of s, to minimize unwanted transformation of string, and to - # keep string locs straight between transform_string and scan_string - self.keepTabs = True - try: - for t, s, e in self.scan_string(instring, debug=debug): - out.append(instring[lastE:s]) - if t: - if isinstance(t, ParseResults): - out += t.as_list() - elif isinstance(t, Iterable) and not isinstance(t, str_type): - out.extend(t) - else: - out.append(t) - lastE = e - out.append(instring[lastE:]) - out = [o for o in out if o] - return "".join([str(s) for s in _flatten(out)]) - except ParseBaseException as exc: - if ParserElement.verbose_stacktrace: - raise - else: - # catch and re-raise exception from here, clears out pyparsing internal stack trace - raise exc.with_traceback(None) - - def search_string( - self, - instring: str, - max_matches: int = _MAX_INT, - *, - debug: bool = False, - maxMatches: int = _MAX_INT, - ) -> ParseResults: - """ - Another extension to :class:`scan_string`, simplifying the access to the tokens found - to match the given parse expression. May be called with optional - ``max_matches`` argument, to clip searching after 'n' matches are found. - - Example:: - - # a capitalized word starts with an uppercase letter, followed by zero or more lowercase letters - cap_word = Word(alphas.upper(), alphas.lower()) - - print(cap_word.search_string("More than Iron, more than Lead, more than Gold I need Electricity")) - - # the sum() builtin can be used to merge results into a single ParseResults object - print(sum(cap_word.search_string("More than Iron, more than Lead, more than Gold I need Electricity"))) - - prints:: - - [['More'], ['Iron'], ['Lead'], ['Gold'], ['I'], ['Electricity']] - ['More', 'Iron', 'Lead', 'Gold', 'I', 'Electricity'] - """ - maxMatches = min(maxMatches, max_matches) - try: - return ParseResults( - [t for t, s, e in self.scan_string(instring, maxMatches, debug=debug)] - ) - except ParseBaseException as exc: - if ParserElement.verbose_stacktrace: - raise - else: - # catch and re-raise exception from here, clears out pyparsing internal stack trace - raise exc.with_traceback(None) - - def split( - self, - instring: str, - maxsplit: int = _MAX_INT, - include_separators: bool = False, - *, - includeSeparators=False, - ) -> Generator[str, None, None]: - """ - Generator method to split a string using the given expression as a separator. - May be called with optional ``maxsplit`` argument, to limit the number of splits; - and the optional ``include_separators`` argument (default= ``False``), if the separating - matching text should be included in the split results. - - Example:: - - punc = one_of(list(".,;:/-!?")) - print(list(punc.split("This, this?, this sentence, is badly punctuated!"))) - - prints:: - - ['This', ' this', '', ' this sentence', ' is badly punctuated', ''] - """ - includeSeparators = includeSeparators or include_separators - last = 0 - for t, s, e in self.scan_string(instring, max_matches=maxsplit): - yield instring[last:s] - if includeSeparators: - yield t[0] - last = e - yield instring[last:] - - def __add__(self, other) -> "ParserElement": - """ - Implementation of ``+`` operator - returns :class:`And`. Adding strings to a :class:`ParserElement` - converts them to :class:`Literal`s by default. - - Example:: - - greet = Word(alphas) + "," + Word(alphas) + "!" - hello = "Hello, World!" - print(hello, "->", greet.parse_string(hello)) - - prints:: - - Hello, World! -> ['Hello', ',', 'World', '!'] - - ``...`` may be used as a parse expression as a short form of :class:`SkipTo`. - - Literal('start') + ... + Literal('end') - - is equivalent to: - - Literal('start') + SkipTo('end')("_skipped*") + Literal('end') - - Note that the skipped text is returned with '_skipped' as a results name, - and to support having multiple skips in the same parser, the value returned is - a list of all skipped text. - """ - if other is Ellipsis: - return _PendingSkip(self) - - if isinstance(other, str_type): - other = self._literalStringClass(other) - if not isinstance(other, ParserElement): - raise TypeError( - "Cannot combine element of type {} with ParserElement".format( - type(other).__name__ - ) - ) - return And([self, other]) - - def __radd__(self, other) -> "ParserElement": - """ - Implementation of ``+`` operator when left operand is not a :class:`ParserElement` - """ - if other is Ellipsis: - return SkipTo(self)("_skipped*") + self - - if isinstance(other, str_type): - other = self._literalStringClass(other) - if not isinstance(other, ParserElement): - raise TypeError( - "Cannot combine element of type {} with ParserElement".format( - type(other).__name__ - ) - ) - return other + self - - def __sub__(self, other) -> "ParserElement": - """ - Implementation of ``-`` operator, returns :class:`And` with error stop - """ - if isinstance(other, str_type): - other = self._literalStringClass(other) - if not isinstance(other, ParserElement): - raise TypeError( - "Cannot combine element of type {} with ParserElement".format( - type(other).__name__ - ) - ) - return self + And._ErrorStop() + other - - def __rsub__(self, other) -> "ParserElement": - """ - Implementation of ``-`` operator when left operand is not a :class:`ParserElement` - """ - if isinstance(other, str_type): - other = self._literalStringClass(other) - if not isinstance(other, ParserElement): - raise TypeError( - "Cannot combine element of type {} with ParserElement".format( - type(other).__name__ - ) - ) - return other - self - - def __mul__(self, other) -> "ParserElement": - """ - Implementation of ``*`` operator, allows use of ``expr * 3`` in place of - ``expr + expr + expr``. Expressions may also be multiplied by a 2-integer - tuple, similar to ``{min, max}`` multipliers in regular expressions. Tuples - may also include ``None`` as in: - - ``expr*(n, None)`` or ``expr*(n, )`` is equivalent - to ``expr*n + ZeroOrMore(expr)`` - (read as "at least n instances of ``expr``") - - ``expr*(None, n)`` is equivalent to ``expr*(0, n)`` - (read as "0 to n instances of ``expr``") - - ``expr*(None, None)`` is equivalent to ``ZeroOrMore(expr)`` - - ``expr*(1, None)`` is equivalent to ``OneOrMore(expr)`` - - Note that ``expr*(None, n)`` does not raise an exception if - more than n exprs exist in the input stream; that is, - ``expr*(None, n)`` does not enforce a maximum number of expr - occurrences. If this behavior is desired, then write - ``expr*(None, n) + ~expr`` - """ - if other is Ellipsis: - other = (0, None) - elif isinstance(other, tuple) and other[:1] == (Ellipsis,): - other = ((0,) + other[1:] + (None,))[:2] - - if isinstance(other, int): - minElements, optElements = other, 0 - elif isinstance(other, tuple): - other = tuple(o if o is not Ellipsis else None for o in other) - other = (other + (None, None))[:2] - if other[0] is None: - other = (0, other[1]) - if isinstance(other[0], int) and other[1] is None: - if other[0] == 0: - return ZeroOrMore(self) - if other[0] == 1: - return OneOrMore(self) - else: - return self * other[0] + ZeroOrMore(self) - elif isinstance(other[0], int) and isinstance(other[1], int): - minElements, optElements = other - optElements -= minElements - else: - raise TypeError( - "cannot multiply ParserElement and ({}) objects".format( - ",".join(type(item).__name__ for item in other) - ) - ) - else: - raise TypeError( - "cannot multiply ParserElement and {} objects".format( - type(other).__name__ - ) - ) - - if minElements < 0: - raise ValueError("cannot multiply ParserElement by negative value") - if optElements < 0: - raise ValueError( - "second tuple value must be greater or equal to first tuple value" - ) - if minElements == optElements == 0: - return And([]) - - if optElements: - - def makeOptionalList(n): - if n > 1: - return Opt(self + makeOptionalList(n - 1)) - else: - return Opt(self) - - if minElements: - if minElements == 1: - ret = self + makeOptionalList(optElements) - else: - ret = And([self] * minElements) + makeOptionalList(optElements) - else: - ret = makeOptionalList(optElements) - else: - if minElements == 1: - ret = self - else: - ret = And([self] * minElements) - return ret - - def __rmul__(self, other) -> "ParserElement": - return self.__mul__(other) - - def __or__(self, other) -> "ParserElement": - """ - Implementation of ``|`` operator - returns :class:`MatchFirst` - """ - if other is Ellipsis: - return _PendingSkip(self, must_skip=True) - - if isinstance(other, str_type): - other = self._literalStringClass(other) - if not isinstance(other, ParserElement): - raise TypeError( - "Cannot combine element of type {} with ParserElement".format( - type(other).__name__ - ) - ) - return MatchFirst([self, other]) - - def __ror__(self, other) -> "ParserElement": - """ - Implementation of ``|`` operator when left operand is not a :class:`ParserElement` - """ - if isinstance(other, str_type): - other = self._literalStringClass(other) - if not isinstance(other, ParserElement): - raise TypeError( - "Cannot combine element of type {} with ParserElement".format( - type(other).__name__ - ) - ) - return other | self - - def __xor__(self, other) -> "ParserElement": - """ - Implementation of ``^`` operator - returns :class:`Or` - """ - if isinstance(other, str_type): - other = self._literalStringClass(other) - if not isinstance(other, ParserElement): - raise TypeError( - "Cannot combine element of type {} with ParserElement".format( - type(other).__name__ - ) - ) - return Or([self, other]) - - def __rxor__(self, other) -> "ParserElement": - """ - Implementation of ``^`` operator when left operand is not a :class:`ParserElement` - """ - if isinstance(other, str_type): - other = self._literalStringClass(other) - if not isinstance(other, ParserElement): - raise TypeError( - "Cannot combine element of type {} with ParserElement".format( - type(other).__name__ - ) - ) - return other ^ self - - def __and__(self, other) -> "ParserElement": - """ - Implementation of ``&`` operator - returns :class:`Each` - """ - if isinstance(other, str_type): - other = self._literalStringClass(other) - if not isinstance(other, ParserElement): - raise TypeError( - "Cannot combine element of type {} with ParserElement".format( - type(other).__name__ - ) - ) - return Each([self, other]) - - def __rand__(self, other) -> "ParserElement": - """ - Implementation of ``&`` operator when left operand is not a :class:`ParserElement` - """ - if isinstance(other, str_type): - other = self._literalStringClass(other) - if not isinstance(other, ParserElement): - raise TypeError( - "Cannot combine element of type {} with ParserElement".format( - type(other).__name__ - ) - ) - return other & self - - def __invert__(self) -> "ParserElement": - """ - Implementation of ``~`` operator - returns :class:`NotAny` - """ - return NotAny(self) - - # disable __iter__ to override legacy use of sequential access to __getitem__ to - # iterate over a sequence - __iter__ = None - - def __getitem__(self, key): - """ - use ``[]`` indexing notation as a short form for expression repetition: - - - ``expr[n]`` is equivalent to ``expr*n`` - - ``expr[m, n]`` is equivalent to ``expr*(m, n)`` - - ``expr[n, ...]`` or ``expr[n,]`` is equivalent - to ``expr*n + ZeroOrMore(expr)`` - (read as "at least n instances of ``expr``") - - ``expr[..., n]`` is equivalent to ``expr*(0, n)`` - (read as "0 to n instances of ``expr``") - - ``expr[...]`` and ``expr[0, ...]`` are equivalent to ``ZeroOrMore(expr)`` - - ``expr[1, ...]`` is equivalent to ``OneOrMore(expr)`` - - ``None`` may be used in place of ``...``. - - Note that ``expr[..., n]`` and ``expr[m, n]``do not raise an exception - if more than ``n`` ``expr``s exist in the input stream. If this behavior is - desired, then write ``expr[..., n] + ~expr``. - """ - - # convert single arg keys to tuples - try: - if isinstance(key, str_type): - key = (key,) - iter(key) - except TypeError: - key = (key, key) - - if len(key) > 2: - raise TypeError( - "only 1 or 2 index arguments supported ({}{})".format( - key[:5], "... [{}]".format(len(key)) if len(key) > 5 else "" - ) - ) - - # clip to 2 elements - ret = self * tuple(key[:2]) - return ret - - def __call__(self, name: str = None) -> "ParserElement": - """ - Shortcut for :class:`set_results_name`, with ``list_all_matches=False``. - - If ``name`` is given with a trailing ``'*'`` character, then ``list_all_matches`` will be - passed as ``True``. - - If ``name` is omitted, same as calling :class:`copy`. - - Example:: - - # these are equivalent - userdata = Word(alphas).set_results_name("name") + Word(nums + "-").set_results_name("socsecno") - userdata = Word(alphas)("name") + Word(nums + "-")("socsecno") - """ - if name is not None: - return self._setResultsName(name) - else: - return self.copy() - - def suppress(self) -> "ParserElement": - """ - Suppresses the output of this :class:`ParserElement`; useful to keep punctuation from - cluttering up returned output. - """ - return Suppress(self) - - def ignore_whitespace(self, recursive: bool = True) -> "ParserElement": - """ - Enables the skipping of whitespace before matching the characters in the - :class:`ParserElement`'s defined pattern. - - :param recursive: If ``True`` (the default), also enable whitespace skipping in child elements (if any) - """ - self.skipWhitespace = True - return self - - def leave_whitespace(self, recursive: bool = True) -> "ParserElement": - """ - Disables the skipping of whitespace before matching the characters in the - :class:`ParserElement`'s defined pattern. This is normally only used internally by - the pyparsing module, but may be needed in some whitespace-sensitive grammars. - - :param recursive: If true (the default), also disable whitespace skipping in child elements (if any) - """ - self.skipWhitespace = False - return self - - def set_whitespace_chars( - self, chars: Union[Set[str], str], copy_defaults: bool = False - ) -> "ParserElement": - """ - Overrides the default whitespace chars - """ - self.skipWhitespace = True - self.whiteChars = set(chars) - self.copyDefaultWhiteChars = copy_defaults - return self - - def parse_with_tabs(self) -> "ParserElement": - """ - Overrides default behavior to expand ```` s to spaces before parsing the input string. - Must be called before ``parse_string`` when the input grammar contains elements that - match ```` characters. - """ - self.keepTabs = True - return self - - def ignore(self, other: "ParserElement") -> "ParserElement": - """ - Define expression to be ignored (e.g., comments) while doing pattern - matching; may be called repeatedly, to define multiple comment or other - ignorable patterns. - - Example:: - - patt = Word(alphas)[1, ...] - patt.parse_string('ablaj /* comment */ lskjd') - # -> ['ablaj'] - - patt.ignore(c_style_comment) - patt.parse_string('ablaj /* comment */ lskjd') - # -> ['ablaj', 'lskjd'] - """ - import typing - - if isinstance(other, str_type): - other = Suppress(other) - - if isinstance(other, Suppress): - if other not in self.ignoreExprs: - self.ignoreExprs.append(other) - else: - self.ignoreExprs.append(Suppress(other.copy())) - return self - - def set_debug_actions( - self, - start_action: DebugStartAction, - success_action: DebugSuccessAction, - exception_action: DebugExceptionAction, - ) -> "ParserElement": - """ - Customize display of debugging messages while doing pattern matching: - - - ``start_action`` - method to be called when an expression is about to be parsed; - should have the signature ``fn(input_string: str, location: int, expression: ParserElement, cache_hit: bool)`` - - - ``success_action`` - method to be called when an expression has successfully parsed; - should have the signature ``fn(input_string: str, start_location: int, end_location: int, expression: ParserELement, parsed_tokens: ParseResults, cache_hit: bool)`` - - - ``exception_action`` - method to be called when expression fails to parse; - should have the signature ``fn(input_string: str, location: int, expression: ParserElement, exception: Exception, cache_hit: bool)`` - """ - self.debugActions = self.DebugActions( - start_action or _default_start_debug_action, - success_action or _default_success_debug_action, - exception_action or _default_exception_debug_action, - ) - self.debug = True - return self - - def set_debug(self, flag: bool = True) -> "ParserElement": - """ - Enable display of debugging messages while doing pattern matching. - Set ``flag`` to ``True`` to enable, ``False`` to disable. - - Example:: - - wd = Word(alphas).set_name("alphaword") - integer = Word(nums).set_name("numword") - term = wd | integer - - # turn on debugging for wd - wd.set_debug() - - term[1, ...].parse_string("abc 123 xyz 890") - - prints:: - - Match alphaword at loc 0(1,1) - Matched alphaword -> ['abc'] - Match alphaword at loc 3(1,4) - Exception raised:Expected alphaword (at char 4), (line:1, col:5) - Match alphaword at loc 7(1,8) - Matched alphaword -> ['xyz'] - Match alphaword at loc 11(1,12) - Exception raised:Expected alphaword (at char 12), (line:1, col:13) - Match alphaword at loc 15(1,16) - Exception raised:Expected alphaword (at char 15), (line:1, col:16) - - The output shown is that produced by the default debug actions - custom debug actions can be - specified using :class:`set_debug_actions`. Prior to attempting - to match the ``wd`` expression, the debugging message ``"Match at loc (,)"`` - is shown. Then if the parse succeeds, a ``"Matched"`` message is shown, or an ``"Exception raised"`` - message is shown. Also note the use of :class:`set_name` to assign a human-readable name to the expression, - which makes debugging and exception messages easier to understand - for instance, the default - name created for the :class:`Word` expression without calling ``set_name`` is ``"W:(A-Za-z)"``. - """ - if flag: - self.set_debug_actions( - _default_start_debug_action, - _default_success_debug_action, - _default_exception_debug_action, - ) - else: - self.debug = False - return self - - @property - def default_name(self) -> str: - if self._defaultName is None: - self._defaultName = self._generateDefaultName() - return self._defaultName - - @abstractmethod - def _generateDefaultName(self): - """ - Child classes must define this method, which defines how the ``default_name`` is set. - """ - - def set_name(self, name: str) -> "ParserElement": - """ - Define name for this expression, makes debugging and exception messages clearer. - Example:: - Word(nums).parse_string("ABC") # -> Exception: Expected W:(0-9) (at char 0), (line:1, col:1) - Word(nums).set_name("integer").parse_string("ABC") # -> Exception: Expected integer (at char 0), (line:1, col:1) - """ - self.customName = name - self.errmsg = "Expected " + self.name - if __diag__.enable_debug_on_named_expressions: - self.set_debug() - return self - - @property - def name(self) -> str: - # This will use a user-defined name if available, but otherwise defaults back to the auto-generated name - return self.customName if self.customName is not None else self.default_name - - def __str__(self) -> str: - return self.name - - def __repr__(self) -> str: - return str(self) - - def streamline(self) -> "ParserElement": - self.streamlined = True - self._defaultName = None - return self - - def recurse(self) -> Sequence["ParserElement"]: - return [] - - def _checkRecursion(self, parseElementList): - subRecCheckList = parseElementList[:] + [self] - for e in self.recurse(): - e._checkRecursion(subRecCheckList) - - def validate(self, validateTrace=None) -> None: - """ - Check defined expressions for valid structure, check for infinite recursive definitions. - """ - self._checkRecursion([]) - - def parse_file( - self, - file_or_filename: Union[str, Path, TextIO], - encoding: str = "utf-8", - parse_all: bool = False, - *, - parseAll: bool = False, - ) -> ParseResults: - """ - Execute the parse expression on the given file or filename. - If a filename is specified (instead of a file object), - the entire file is opened, read, and closed before parsing. - """ - parseAll = parseAll or parse_all - try: - file_contents = file_or_filename.read() - except AttributeError: - with open(file_or_filename, "r", encoding=encoding) as f: - file_contents = f.read() - try: - return self.parse_string(file_contents, parseAll) - except ParseBaseException as exc: - if ParserElement.verbose_stacktrace: - raise - else: - # catch and re-raise exception from here, clears out pyparsing internal stack trace - raise exc.with_traceback(None) - - def __eq__(self, other): - if self is other: - return True - elif isinstance(other, str_type): - return self.matches(other, parse_all=True) - elif isinstance(other, ParserElement): - return vars(self) == vars(other) - return False - - def __hash__(self): - return id(self) - - def matches( - self, test_string: str, parse_all: bool = True, *, parseAll: bool = True - ) -> bool: - """ - Method for quick testing of a parser against a test string. Good for simple - inline microtests of sub expressions while building up larger parser. - - Parameters: - - ``test_string`` - to test against this expression for a match - - ``parse_all`` - (default= ``True``) - flag to pass to :class:`parse_string` when running tests - - Example:: - - expr = Word(nums) - assert expr.matches("100") - """ - parseAll = parseAll and parse_all - try: - self.parse_string(str(test_string), parse_all=parseAll) - return True - except ParseBaseException: - return False - - def run_tests( - self, - tests: Union[str, List[str]], - parse_all: bool = True, - comment: typing.Optional[Union["ParserElement", str]] = "#", - full_dump: bool = True, - print_results: bool = True, - failure_tests: bool = False, - post_parse: Callable[[str, ParseResults], str] = None, - file: typing.Optional[TextIO] = None, - with_line_numbers: bool = False, - *, - parseAll: bool = True, - fullDump: bool = True, - printResults: bool = True, - failureTests: bool = False, - postParse: Callable[[str, ParseResults], str] = None, - ) -> Tuple[bool, List[Tuple[str, Union[ParseResults, Exception]]]]: - """ - Execute the parse expression on a series of test strings, showing each - test, the parsed results or where the parse failed. Quick and easy way to - run a parse expression against a list of sample strings. - - Parameters: - - ``tests`` - a list of separate test strings, or a multiline string of test strings - - ``parse_all`` - (default= ``True``) - flag to pass to :class:`parse_string` when running tests - - ``comment`` - (default= ``'#'``) - expression for indicating embedded comments in the test - string; pass None to disable comment filtering - - ``full_dump`` - (default= ``True``) - dump results as list followed by results names in nested outline; - if False, only dump nested list - - ``print_results`` - (default= ``True``) prints test output to stdout - - ``failure_tests`` - (default= ``False``) indicates if these tests are expected to fail parsing - - ``post_parse`` - (default= ``None``) optional callback for successful parse results; called as - `fn(test_string, parse_results)` and returns a string to be added to the test output - - ``file`` - (default= ``None``) optional file-like object to which test output will be written; - if None, will default to ``sys.stdout`` - - ``with_line_numbers`` - default= ``False``) show test strings with line and column numbers - - Returns: a (success, results) tuple, where success indicates that all tests succeeded - (or failed if ``failure_tests`` is True), and the results contain a list of lines of each - test's output - - Example:: - - number_expr = pyparsing_common.number.copy() - - result = number_expr.run_tests(''' - # unsigned integer - 100 - # negative integer - -100 - # float with scientific notation - 6.02e23 - # integer with scientific notation - 1e-12 - ''') - print("Success" if result[0] else "Failed!") - - result = number_expr.run_tests(''' - # stray character - 100Z - # missing leading digit before '.' - -.100 - # too many '.' - 3.14.159 - ''', failure_tests=True) - print("Success" if result[0] else "Failed!") - - prints:: - - # unsigned integer - 100 - [100] - - # negative integer - -100 - [-100] - - # float with scientific notation - 6.02e23 - [6.02e+23] - - # integer with scientific notation - 1e-12 - [1e-12] - - Success - - # stray character - 100Z - ^ - FAIL: Expected end of text (at char 3), (line:1, col:4) - - # missing leading digit before '.' - -.100 - ^ - FAIL: Expected {real number with scientific notation | real number | signed integer} (at char 0), (line:1, col:1) - - # too many '.' - 3.14.159 - ^ - FAIL: Expected end of text (at char 4), (line:1, col:5) - - Success - - Each test string must be on a single line. If you want to test a string that spans multiple - lines, create a test like this:: - - expr.run_tests(r"this is a test\\n of strings that spans \\n 3 lines") - - (Note that this is a raw string literal, you must include the leading ``'r'``.) - """ - from .testing import pyparsing_test - - parseAll = parseAll and parse_all - fullDump = fullDump and full_dump - printResults = printResults and print_results - failureTests = failureTests or failure_tests - postParse = postParse or post_parse - if isinstance(tests, str_type): - line_strip = type(tests).strip - tests = [line_strip(test_line) for test_line in tests.rstrip().splitlines()] - if isinstance(comment, str_type): - comment = Literal(comment) - if file is None: - file = sys.stdout - print_ = file.write - - result: Union[ParseResults, Exception] - allResults = [] - comments = [] - success = True - NL = Literal(r"\n").add_parse_action(replace_with("\n")).ignore(quoted_string) - BOM = "\ufeff" - for t in tests: - if comment is not None and comment.matches(t, False) or comments and not t: - comments.append( - pyparsing_test.with_line_numbers(t) if with_line_numbers else t - ) - continue - if not t: - continue - out = [ - "\n" + "\n".join(comments) if comments else "", - pyparsing_test.with_line_numbers(t) if with_line_numbers else t, - ] - comments = [] - try: - # convert newline marks to actual newlines, and strip leading BOM if present - t = NL.transform_string(t.lstrip(BOM)) - result = self.parse_string(t, parse_all=parseAll) - except ParseBaseException as pe: - fatal = "(FATAL)" if isinstance(pe, ParseFatalException) else "" - out.append(pe.explain()) - out.append("FAIL: " + str(pe)) - if ParserElement.verbose_stacktrace: - out.extend(traceback.format_tb(pe.__traceback__)) - success = success and failureTests - result = pe - except Exception as exc: - out.append("FAIL-EXCEPTION: {}: {}".format(type(exc).__name__, exc)) - if ParserElement.verbose_stacktrace: - out.extend(traceback.format_tb(exc.__traceback__)) - success = success and failureTests - result = exc - else: - success = success and not failureTests - if postParse is not None: - try: - pp_value = postParse(t, result) - if pp_value is not None: - if isinstance(pp_value, ParseResults): - out.append(pp_value.dump()) - else: - out.append(str(pp_value)) - else: - out.append(result.dump()) - except Exception as e: - out.append(result.dump(full=fullDump)) - out.append( - "{} failed: {}: {}".format( - postParse.__name__, type(e).__name__, e - ) - ) - else: - out.append(result.dump(full=fullDump)) - out.append("") - - if printResults: - print_("\n".join(out)) - - allResults.append((t, result)) - - return success, allResults - - def create_diagram( - self, - output_html: Union[TextIO, Path, str], - vertical: int = 3, - show_results_names: bool = False, - show_groups: bool = False, - **kwargs, - ) -> None: - """ - Create a railroad diagram for the parser. - - Parameters: - - output_html (str or file-like object) - output target for generated - diagram HTML - - vertical (int) - threshold for formatting multiple alternatives vertically - instead of horizontally (default=3) - - show_results_names - bool flag whether diagram should show annotations for - defined results names - - show_groups - bool flag whether groups should be highlighted with an unlabeled surrounding box - Additional diagram-formatting keyword arguments can also be included; - see railroad.Diagram class. - """ - - try: - from .diagram import to_railroad, railroad_to_html - except ImportError as ie: - raise Exception( - "must ``pip install pyparsing[diagrams]`` to generate parser railroad diagrams" - ) from ie - - self.streamline() - - railroad = to_railroad( - self, - vertical=vertical, - show_results_names=show_results_names, - show_groups=show_groups, - diagram_kwargs=kwargs, - ) - if isinstance(output_html, (str, Path)): - with open(output_html, "w", encoding="utf-8") as diag_file: - diag_file.write(railroad_to_html(railroad)) - else: - # we were passed a file-like object, just write to it - output_html.write(railroad_to_html(railroad)) - - setDefaultWhitespaceChars = set_default_whitespace_chars - inlineLiteralsUsing = inline_literals_using - setResultsName = set_results_name - setBreak = set_break - setParseAction = set_parse_action - addParseAction = add_parse_action - addCondition = add_condition - setFailAction = set_fail_action - tryParse = try_parse - canParseNext = can_parse_next - resetCache = reset_cache - enableLeftRecursion = enable_left_recursion - enablePackrat = enable_packrat - parseString = parse_string - scanString = scan_string - searchString = search_string - transformString = transform_string - setWhitespaceChars = set_whitespace_chars - parseWithTabs = parse_with_tabs - setDebugActions = set_debug_actions - setDebug = set_debug - defaultName = default_name - setName = set_name - parseFile = parse_file - runTests = run_tests - ignoreWhitespace = ignore_whitespace - leaveWhitespace = leave_whitespace - - -class _PendingSkip(ParserElement): - # internal placeholder class to hold a place were '...' is added to a parser element, - # once another ParserElement is added, this placeholder will be replaced with a SkipTo - def __init__(self, expr: ParserElement, must_skip: bool = False): - super().__init__() - self.anchor = expr - self.must_skip = must_skip - - def _generateDefaultName(self): - return str(self.anchor + Empty()).replace("Empty", "...") - - def __add__(self, other) -> "ParserElement": - skipper = SkipTo(other).set_name("...")("_skipped*") - if self.must_skip: - - def must_skip(t): - if not t._skipped or t._skipped.as_list() == [""]: - del t[0] - t.pop("_skipped", None) - - def show_skip(t): - if t._skipped.as_list()[-1:] == [""]: - t.pop("_skipped") - t["_skipped"] = "missing <" + repr(self.anchor) + ">" - - return ( - self.anchor + skipper().add_parse_action(must_skip) - | skipper().add_parse_action(show_skip) - ) + other - - return self.anchor + skipper + other - - def __repr__(self): - return self.defaultName - - def parseImpl(self, *args): - raise Exception( - "use of `...` expression without following SkipTo target expression" - ) - - -class Token(ParserElement): - """Abstract :class:`ParserElement` subclass, for defining atomic - matching patterns. - """ - - def __init__(self): - super().__init__(savelist=False) - - def _generateDefaultName(self): - return type(self).__name__ - - -class Empty(Token): - """ - An empty token, will always match. - """ - - def __init__(self): - super().__init__() - self.mayReturnEmpty = True - self.mayIndexError = False - - -class NoMatch(Token): - """ - A token that will never match. - """ - - def __init__(self): - super().__init__() - self.mayReturnEmpty = True - self.mayIndexError = False - self.errmsg = "Unmatchable token" - - def parseImpl(self, instring, loc, doActions=True): - raise ParseException(instring, loc, self.errmsg, self) - - -class Literal(Token): - """ - Token to exactly match a specified string. - - Example:: - - Literal('blah').parse_string('blah') # -> ['blah'] - Literal('blah').parse_string('blahfooblah') # -> ['blah'] - Literal('blah').parse_string('bla') # -> Exception: Expected "blah" - - For case-insensitive matching, use :class:`CaselessLiteral`. - - For keyword matching (force word break before and after the matched string), - use :class:`Keyword` or :class:`CaselessKeyword`. - """ - - def __init__(self, match_string: str = "", *, matchString: str = ""): - super().__init__() - match_string = matchString or match_string - self.match = match_string - self.matchLen = len(match_string) - try: - self.firstMatchChar = match_string[0] - except IndexError: - raise ValueError("null string passed to Literal; use Empty() instead") - self.errmsg = "Expected " + self.name - self.mayReturnEmpty = False - self.mayIndexError = False - - # Performance tuning: modify __class__ to select - # a parseImpl optimized for single-character check - if self.matchLen == 1 and type(self) is Literal: - self.__class__ = _SingleCharLiteral - - def _generateDefaultName(self): - return repr(self.match) - - def parseImpl(self, instring, loc, doActions=True): - if instring[loc] == self.firstMatchChar and instring.startswith( - self.match, loc - ): - return loc + self.matchLen, self.match - raise ParseException(instring, loc, self.errmsg, self) - - -class _SingleCharLiteral(Literal): - def parseImpl(self, instring, loc, doActions=True): - if instring[loc] == self.firstMatchChar: - return loc + 1, self.match - raise ParseException(instring, loc, self.errmsg, self) - - -ParserElement._literalStringClass = Literal - - -class Keyword(Token): - """ - Token to exactly match a specified string as a keyword, that is, - it must be immediately followed by a non-keyword character. Compare - with :class:`Literal`: - - - ``Literal("if")`` will match the leading ``'if'`` in - ``'ifAndOnlyIf'``. - - ``Keyword("if")`` will not; it will only match the leading - ``'if'`` in ``'if x=1'``, or ``'if(y==2)'`` - - Accepts two optional constructor arguments in addition to the - keyword string: - - - ``identChars`` is a string of characters that would be valid - identifier characters, defaulting to all alphanumerics + "_" and - "$" - - ``caseless`` allows case-insensitive matching, default is ``False``. - - Example:: - - Keyword("start").parse_string("start") # -> ['start'] - Keyword("start").parse_string("starting") # -> Exception - - For case-insensitive matching, use :class:`CaselessKeyword`. - """ - - DEFAULT_KEYWORD_CHARS = alphanums + "_$" - - def __init__( - self, - match_string: str = "", - ident_chars: typing.Optional[str] = None, - caseless: bool = False, - *, - matchString: str = "", - identChars: typing.Optional[str] = None, - ): - super().__init__() - identChars = identChars or ident_chars - if identChars is None: - identChars = Keyword.DEFAULT_KEYWORD_CHARS - match_string = matchString or match_string - self.match = match_string - self.matchLen = len(match_string) - try: - self.firstMatchChar = match_string[0] - except IndexError: - raise ValueError("null string passed to Keyword; use Empty() instead") - self.errmsg = "Expected {} {}".format(type(self).__name__, self.name) - self.mayReturnEmpty = False - self.mayIndexError = False - self.caseless = caseless - if caseless: - self.caselessmatch = match_string.upper() - identChars = identChars.upper() - self.identChars = set(identChars) - - def _generateDefaultName(self): - return repr(self.match) - - def parseImpl(self, instring, loc, doActions=True): - errmsg = self.errmsg - errloc = loc - if self.caseless: - if instring[loc : loc + self.matchLen].upper() == self.caselessmatch: - if loc == 0 or instring[loc - 1].upper() not in self.identChars: - if ( - loc >= len(instring) - self.matchLen - or instring[loc + self.matchLen].upper() not in self.identChars - ): - return loc + self.matchLen, self.match - else: - # followed by keyword char - errmsg += ", was immediately followed by keyword character" - errloc = loc + self.matchLen - else: - # preceded by keyword char - errmsg += ", keyword was immediately preceded by keyword character" - errloc = loc - 1 - # else no match just raise plain exception - - else: - if ( - instring[loc] == self.firstMatchChar - and self.matchLen == 1 - or instring.startswith(self.match, loc) - ): - if loc == 0 or instring[loc - 1] not in self.identChars: - if ( - loc >= len(instring) - self.matchLen - or instring[loc + self.matchLen] not in self.identChars - ): - return loc + self.matchLen, self.match - else: - # followed by keyword char - errmsg += ( - ", keyword was immediately followed by keyword character" - ) - errloc = loc + self.matchLen - else: - # preceded by keyword char - errmsg += ", keyword was immediately preceded by keyword character" - errloc = loc - 1 - # else no match just raise plain exception - - raise ParseException(instring, errloc, errmsg, self) - - @staticmethod - def set_default_keyword_chars(chars) -> None: - """ - Overrides the default characters used by :class:`Keyword` expressions. - """ - Keyword.DEFAULT_KEYWORD_CHARS = chars - - setDefaultKeywordChars = set_default_keyword_chars - - -class CaselessLiteral(Literal): - """ - Token to match a specified string, ignoring case of letters. - Note: the matched results will always be in the case of the given - match string, NOT the case of the input text. - - Example:: - - CaselessLiteral("CMD")[1, ...].parse_string("cmd CMD Cmd10") - # -> ['CMD', 'CMD', 'CMD'] - - (Contrast with example for :class:`CaselessKeyword`.) - """ - - def __init__(self, match_string: str = "", *, matchString: str = ""): - match_string = matchString or match_string - super().__init__(match_string.upper()) - # Preserve the defining literal. - self.returnString = match_string - self.errmsg = "Expected " + self.name - - def parseImpl(self, instring, loc, doActions=True): - if instring[loc : loc + self.matchLen].upper() == self.match: - return loc + self.matchLen, self.returnString - raise ParseException(instring, loc, self.errmsg, self) - - -class CaselessKeyword(Keyword): - """ - Caseless version of :class:`Keyword`. - - Example:: - - CaselessKeyword("CMD")[1, ...].parse_string("cmd CMD Cmd10") - # -> ['CMD', 'CMD'] - - (Contrast with example for :class:`CaselessLiteral`.) - """ - - def __init__( - self, - match_string: str = "", - ident_chars: typing.Optional[str] = None, - *, - matchString: str = "", - identChars: typing.Optional[str] = None, - ): - identChars = identChars or ident_chars - match_string = matchString or match_string - super().__init__(match_string, identChars, caseless=True) - - -class CloseMatch(Token): - """A variation on :class:`Literal` which matches "close" matches, - that is, strings with at most 'n' mismatching characters. - :class:`CloseMatch` takes parameters: - - - ``match_string`` - string to be matched - - ``caseless`` - a boolean indicating whether to ignore casing when comparing characters - - ``max_mismatches`` - (``default=1``) maximum number of - mismatches allowed to count as a match - - The results from a successful parse will contain the matched text - from the input string and the following named results: - - - ``mismatches`` - a list of the positions within the - match_string where mismatches were found - - ``original`` - the original match_string used to compare - against the input string - - If ``mismatches`` is an empty list, then the match was an exact - match. - - Example:: - - patt = CloseMatch("ATCATCGAATGGA") - patt.parse_string("ATCATCGAAXGGA") # -> (['ATCATCGAAXGGA'], {'mismatches': [[9]], 'original': ['ATCATCGAATGGA']}) - patt.parse_string("ATCAXCGAAXGGA") # -> Exception: Expected 'ATCATCGAATGGA' (with up to 1 mismatches) (at char 0), (line:1, col:1) - - # exact match - patt.parse_string("ATCATCGAATGGA") # -> (['ATCATCGAATGGA'], {'mismatches': [[]], 'original': ['ATCATCGAATGGA']}) - - # close match allowing up to 2 mismatches - patt = CloseMatch("ATCATCGAATGGA", max_mismatches=2) - patt.parse_string("ATCAXCGAAXGGA") # -> (['ATCAXCGAAXGGA'], {'mismatches': [[4, 9]], 'original': ['ATCATCGAATGGA']}) - """ - - def __init__( - self, - match_string: str, - max_mismatches: int = None, - *, - maxMismatches: int = 1, - caseless=False, - ): - maxMismatches = max_mismatches if max_mismatches is not None else maxMismatches - super().__init__() - self.match_string = match_string - self.maxMismatches = maxMismatches - self.errmsg = "Expected {!r} (with up to {} mismatches)".format( - self.match_string, self.maxMismatches - ) - self.caseless = caseless - self.mayIndexError = False - self.mayReturnEmpty = False - - def _generateDefaultName(self): - return "{}:{!r}".format(type(self).__name__, self.match_string) - - def parseImpl(self, instring, loc, doActions=True): - start = loc - instrlen = len(instring) - maxloc = start + len(self.match_string) - - if maxloc <= instrlen: - match_string = self.match_string - match_stringloc = 0 - mismatches = [] - maxMismatches = self.maxMismatches - - for match_stringloc, s_m in enumerate( - zip(instring[loc:maxloc], match_string) - ): - src, mat = s_m - if self.caseless: - src, mat = src.lower(), mat.lower() - - if src != mat: - mismatches.append(match_stringloc) - if len(mismatches) > maxMismatches: - break - else: - loc = start + match_stringloc + 1 - results = ParseResults([instring[start:loc]]) - results["original"] = match_string - results["mismatches"] = mismatches - return loc, results - - raise ParseException(instring, loc, self.errmsg, self) - - -class Word(Token): - """Token for matching words composed of allowed character sets. - Parameters: - - ``init_chars`` - string of all characters that should be used to - match as a word; "ABC" will match "AAA", "ABAB", "CBAC", etc.; - if ``body_chars`` is also specified, then this is the string of - initial characters - - ``body_chars`` - string of characters that - can be used for matching after a matched initial character as - given in ``init_chars``; if omitted, same as the initial characters - (default=``None``) - - ``min`` - minimum number of characters to match (default=1) - - ``max`` - maximum number of characters to match (default=0) - - ``exact`` - exact number of characters to match (default=0) - - ``as_keyword`` - match as a keyword (default=``False``) - - ``exclude_chars`` - characters that might be - found in the input ``body_chars`` string but which should not be - accepted for matching ;useful to define a word of all - printables except for one or two characters, for instance - (default=``None``) - - :class:`srange` is useful for defining custom character set strings - for defining :class:`Word` expressions, using range notation from - regular expression character sets. - - A common mistake is to use :class:`Word` to match a specific literal - string, as in ``Word("Address")``. Remember that :class:`Word` - uses the string argument to define *sets* of matchable characters. - This expression would match "Add", "AAA", "dAred", or any other word - made up of the characters 'A', 'd', 'r', 'e', and 's'. To match an - exact literal string, use :class:`Literal` or :class:`Keyword`. - - pyparsing includes helper strings for building Words: - - - :class:`alphas` - - :class:`nums` - - :class:`alphanums` - - :class:`hexnums` - - :class:`alphas8bit` (alphabetic characters in ASCII range 128-255 - - accented, tilded, umlauted, etc.) - - :class:`punc8bit` (non-alphabetic characters in ASCII range - 128-255 - currency, symbols, superscripts, diacriticals, etc.) - - :class:`printables` (any non-whitespace character) - - ``alphas``, ``nums``, and ``printables`` are also defined in several - Unicode sets - see :class:`pyparsing_unicode``. - - Example:: - - # a word composed of digits - integer = Word(nums) # equivalent to Word("0123456789") or Word(srange("0-9")) - - # a word with a leading capital, and zero or more lowercase - capital_word = Word(alphas.upper(), alphas.lower()) - - # hostnames are alphanumeric, with leading alpha, and '-' - hostname = Word(alphas, alphanums + '-') - - # roman numeral (not a strict parser, accepts invalid mix of characters) - roman = Word("IVXLCDM") - - # any string of non-whitespace characters, except for ',' - csv_value = Word(printables, exclude_chars=",") - """ - - def __init__( - self, - init_chars: str = "", - body_chars: typing.Optional[str] = None, - min: int = 1, - max: int = 0, - exact: int = 0, - as_keyword: bool = False, - exclude_chars: typing.Optional[str] = None, - *, - initChars: typing.Optional[str] = None, - bodyChars: typing.Optional[str] = None, - asKeyword: bool = False, - excludeChars: typing.Optional[str] = None, - ): - initChars = initChars or init_chars - bodyChars = bodyChars or body_chars - asKeyword = asKeyword or as_keyword - excludeChars = excludeChars or exclude_chars - super().__init__() - if not initChars: - raise ValueError( - "invalid {}, initChars cannot be empty string".format( - type(self).__name__ - ) - ) - - initChars = set(initChars) - self.initChars = initChars - if excludeChars: - excludeChars = set(excludeChars) - initChars -= excludeChars - if bodyChars: - bodyChars = set(bodyChars) - excludeChars - self.initCharsOrig = "".join(sorted(initChars)) - - if bodyChars: - self.bodyCharsOrig = "".join(sorted(bodyChars)) - self.bodyChars = set(bodyChars) - else: - self.bodyCharsOrig = "".join(sorted(initChars)) - self.bodyChars = set(initChars) - - self.maxSpecified = max > 0 - - if min < 1: - raise ValueError( - "cannot specify a minimum length < 1; use Opt(Word()) if zero-length word is permitted" - ) - - self.minLen = min - - if max > 0: - self.maxLen = max - else: - self.maxLen = _MAX_INT - - if exact > 0: - self.maxLen = exact - self.minLen = exact - - self.errmsg = "Expected " + self.name - self.mayIndexError = False - self.asKeyword = asKeyword - - # see if we can make a regex for this Word - if " " not in self.initChars | self.bodyChars and (min == 1 and exact == 0): - if self.bodyChars == self.initChars: - if max == 0: - repeat = "+" - elif max == 1: - repeat = "" - else: - repeat = "{{{},{}}}".format( - self.minLen, "" if self.maxLen == _MAX_INT else self.maxLen - ) - self.reString = "[{}]{}".format( - _collapse_string_to_ranges(self.initChars), - repeat, - ) - elif len(self.initChars) == 1: - if max == 0: - repeat = "*" - else: - repeat = "{{0,{}}}".format(max - 1) - self.reString = "{}[{}]{}".format( - re.escape(self.initCharsOrig), - _collapse_string_to_ranges(self.bodyChars), - repeat, - ) - else: - if max == 0: - repeat = "*" - elif max == 2: - repeat = "" - else: - repeat = "{{0,{}}}".format(max - 1) - self.reString = "[{}][{}]{}".format( - _collapse_string_to_ranges(self.initChars), - _collapse_string_to_ranges(self.bodyChars), - repeat, - ) - if self.asKeyword: - self.reString = r"\b" + self.reString + r"\b" - - try: - self.re = re.compile(self.reString) - except re.error: - self.re = None - else: - self.re_match = self.re.match - self.__class__ = _WordRegex - - def _generateDefaultName(self): - def charsAsStr(s): - max_repr_len = 16 - s = _collapse_string_to_ranges(s, re_escape=False) - if len(s) > max_repr_len: - return s[: max_repr_len - 3] + "..." - else: - return s - - if self.initChars != self.bodyChars: - base = "W:({}, {})".format( - charsAsStr(self.initChars), charsAsStr(self.bodyChars) - ) - else: - base = "W:({})".format(charsAsStr(self.initChars)) - - # add length specification - if self.minLen > 1 or self.maxLen != _MAX_INT: - if self.minLen == self.maxLen: - if self.minLen == 1: - return base[2:] - else: - return base + "{{{}}}".format(self.minLen) - elif self.maxLen == _MAX_INT: - return base + "{{{},...}}".format(self.minLen) - else: - return base + "{{{},{}}}".format(self.minLen, self.maxLen) - return base - - def parseImpl(self, instring, loc, doActions=True): - if instring[loc] not in self.initChars: - raise ParseException(instring, loc, self.errmsg, self) - - start = loc - loc += 1 - instrlen = len(instring) - bodychars = self.bodyChars - maxloc = start + self.maxLen - maxloc = min(maxloc, instrlen) - while loc < maxloc and instring[loc] in bodychars: - loc += 1 - - throwException = False - if loc - start < self.minLen: - throwException = True - elif self.maxSpecified and loc < instrlen and instring[loc] in bodychars: - throwException = True - elif self.asKeyword: - if ( - start > 0 - and instring[start - 1] in bodychars - or loc < instrlen - and instring[loc] in bodychars - ): - throwException = True - - if throwException: - raise ParseException(instring, loc, self.errmsg, self) - - return loc, instring[start:loc] - - -class _WordRegex(Word): - def parseImpl(self, instring, loc, doActions=True): - result = self.re_match(instring, loc) - if not result: - raise ParseException(instring, loc, self.errmsg, self) - - loc = result.end() - return loc, result.group() - - -class Char(_WordRegex): - """A short-cut class for defining :class:`Word` ``(characters, exact=1)``, - when defining a match of any single character in a string of - characters. - """ - - def __init__( - self, - charset: str, - as_keyword: bool = False, - exclude_chars: typing.Optional[str] = None, - *, - asKeyword: bool = False, - excludeChars: typing.Optional[str] = None, - ): - asKeyword = asKeyword or as_keyword - excludeChars = excludeChars or exclude_chars - super().__init__( - charset, exact=1, asKeyword=asKeyword, excludeChars=excludeChars - ) - self.reString = "[{}]".format(_collapse_string_to_ranges(self.initChars)) - if asKeyword: - self.reString = r"\b{}\b".format(self.reString) - self.re = re.compile(self.reString) - self.re_match = self.re.match - - -class Regex(Token): - r"""Token for matching strings that match a given regular - expression. Defined with string specifying the regular expression in - a form recognized by the stdlib Python `re module `_. - If the given regex contains named groups (defined using ``(?P...)``), - these will be preserved as named :class:`ParseResults`. - - If instead of the Python stdlib ``re`` module you wish to use a different RE module - (such as the ``regex`` module), you can do so by building your ``Regex`` object with - a compiled RE that was compiled using ``regex``. - - Example:: - - realnum = Regex(r"[+-]?\d+\.\d*") - # ref: https://stackoverflow.com/questions/267399/how-do-you-match-only-valid-roman-numerals-with-a-regular-expression - roman = Regex(r"M{0,4}(CM|CD|D?{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})") - - # named fields in a regex will be returned as named results - date = Regex(r'(?P\d{4})-(?P\d\d?)-(?P\d\d?)') - - # the Regex class will accept re's compiled using the regex module - import regex - parser = pp.Regex(regex.compile(r'[0-9]')) - """ - - def __init__( - self, - pattern: Any, - flags: Union[re.RegexFlag, int] = 0, - as_group_list: bool = False, - as_match: bool = False, - *, - asGroupList: bool = False, - asMatch: bool = False, - ): - """The parameters ``pattern`` and ``flags`` are passed - to the ``re.compile()`` function as-is. See the Python - `re module `_ module for an - explanation of the acceptable patterns and flags. - """ - super().__init__() - asGroupList = asGroupList or as_group_list - asMatch = asMatch or as_match - - if isinstance(pattern, str_type): - if not pattern: - raise ValueError("null string passed to Regex; use Empty() instead") - - self._re = None - self.reString = self.pattern = pattern - self.flags = flags - - elif hasattr(pattern, "pattern") and hasattr(pattern, "match"): - self._re = pattern - self.pattern = self.reString = pattern.pattern - self.flags = flags - - else: - raise TypeError( - "Regex may only be constructed with a string or a compiled RE object" - ) - - self.errmsg = "Expected " + self.name - self.mayIndexError = False - self.asGroupList = asGroupList - self.asMatch = asMatch - if self.asGroupList: - self.parseImpl = self.parseImplAsGroupList - if self.asMatch: - self.parseImpl = self.parseImplAsMatch - - @cached_property - def re(self): - if self._re: - return self._re - else: - try: - return re.compile(self.pattern, self.flags) - except re.error: - raise ValueError( - "invalid pattern ({!r}) passed to Regex".format(self.pattern) - ) - - @cached_property - def re_match(self): - return self.re.match - - @cached_property - def mayReturnEmpty(self): - return self.re_match("") is not None - - def _generateDefaultName(self): - return "Re:({})".format(repr(self.pattern).replace("\\\\", "\\")) - - def parseImpl(self, instring, loc, doActions=True): - result = self.re_match(instring, loc) - if not result: - raise ParseException(instring, loc, self.errmsg, self) - - loc = result.end() - ret = ParseResults(result.group()) - d = result.groupdict() - if d: - for k, v in d.items(): - ret[k] = v - return loc, ret - - def parseImplAsGroupList(self, instring, loc, doActions=True): - result = self.re_match(instring, loc) - if not result: - raise ParseException(instring, loc, self.errmsg, self) - - loc = result.end() - ret = result.groups() - return loc, ret - - def parseImplAsMatch(self, instring, loc, doActions=True): - result = self.re_match(instring, loc) - if not result: - raise ParseException(instring, loc, self.errmsg, self) - - loc = result.end() - ret = result - return loc, ret - - def sub(self, repl: str) -> ParserElement: - r""" - Return :class:`Regex` with an attached parse action to transform the parsed - result as if called using `re.sub(expr, repl, string) `_. - - Example:: - - make_html = Regex(r"(\w+):(.*?):").sub(r"<\1>\2") - print(make_html.transform_string("h1:main title:")) - # prints "

main title

" - """ - if self.asGroupList: - raise TypeError("cannot use sub() with Regex(asGroupList=True)") - - if self.asMatch and callable(repl): - raise TypeError("cannot use sub() with a callable with Regex(asMatch=True)") - - if self.asMatch: - - def pa(tokens): - return tokens[0].expand(repl) - - else: - - def pa(tokens): - return self.re.sub(repl, tokens[0]) - - return self.add_parse_action(pa) - - -class QuotedString(Token): - r""" - Token for matching strings that are delimited by quoting characters. - - Defined with the following parameters: - - - ``quote_char`` - string of one or more characters defining the - quote delimiting string - - ``esc_char`` - character to re_escape quotes, typically backslash - (default= ``None``) - - ``esc_quote`` - special quote sequence to re_escape an embedded quote - string (such as SQL's ``""`` to re_escape an embedded ``"``) - (default= ``None``) - - ``multiline`` - boolean indicating whether quotes can span - multiple lines (default= ``False``) - - ``unquote_results`` - boolean indicating whether the matched text - should be unquoted (default= ``True``) - - ``end_quote_char`` - string of one or more characters defining the - end of the quote delimited string (default= ``None`` => same as - quote_char) - - ``convert_whitespace_escapes`` - convert escaped whitespace - (``'\t'``, ``'\n'``, etc.) to actual whitespace - (default= ``True``) - - Example:: - - qs = QuotedString('"') - print(qs.search_string('lsjdf "This is the quote" sldjf')) - complex_qs = QuotedString('{{', end_quote_char='}}') - print(complex_qs.search_string('lsjdf {{This is the "quote"}} sldjf')) - sql_qs = QuotedString('"', esc_quote='""') - print(sql_qs.search_string('lsjdf "This is the quote with ""embedded"" quotes" sldjf')) - - prints:: - - [['This is the quote']] - [['This is the "quote"']] - [['This is the quote with "embedded" quotes']] - """ - ws_map = ((r"\t", "\t"), (r"\n", "\n"), (r"\f", "\f"), (r"\r", "\r")) - - def __init__( - self, - quote_char: str = "", - esc_char: typing.Optional[str] = None, - esc_quote: typing.Optional[str] = None, - multiline: bool = False, - unquote_results: bool = True, - end_quote_char: typing.Optional[str] = None, - convert_whitespace_escapes: bool = True, - *, - quoteChar: str = "", - escChar: typing.Optional[str] = None, - escQuote: typing.Optional[str] = None, - unquoteResults: bool = True, - endQuoteChar: typing.Optional[str] = None, - convertWhitespaceEscapes: bool = True, - ): - super().__init__() - escChar = escChar or esc_char - escQuote = escQuote or esc_quote - unquoteResults = unquoteResults and unquote_results - endQuoteChar = endQuoteChar or end_quote_char - convertWhitespaceEscapes = ( - convertWhitespaceEscapes and convert_whitespace_escapes - ) - quote_char = quoteChar or quote_char - - # remove white space from quote chars - wont work anyway - quote_char = quote_char.strip() - if not quote_char: - raise ValueError("quote_char cannot be the empty string") - - if endQuoteChar is None: - endQuoteChar = quote_char - else: - endQuoteChar = endQuoteChar.strip() - if not endQuoteChar: - raise ValueError("endQuoteChar cannot be the empty string") - - self.quoteChar = quote_char - self.quoteCharLen = len(quote_char) - self.firstQuoteChar = quote_char[0] - self.endQuoteChar = endQuoteChar - self.endQuoteCharLen = len(endQuoteChar) - self.escChar = escChar - self.escQuote = escQuote - self.unquoteResults = unquoteResults - self.convertWhitespaceEscapes = convertWhitespaceEscapes - - sep = "" - inner_pattern = "" - - if escQuote: - inner_pattern += r"{}(?:{})".format(sep, re.escape(escQuote)) - sep = "|" - - if escChar: - inner_pattern += r"{}(?:{}.)".format(sep, re.escape(escChar)) - sep = "|" - self.escCharReplacePattern = re.escape(self.escChar) + "(.)" - - if len(self.endQuoteChar) > 1: - inner_pattern += ( - "{}(?:".format(sep) - + "|".join( - "(?:{}(?!{}))".format( - re.escape(self.endQuoteChar[:i]), - re.escape(self.endQuoteChar[i:]), - ) - for i in range(len(self.endQuoteChar) - 1, 0, -1) - ) - + ")" - ) - sep = "|" - - if multiline: - self.flags = re.MULTILINE | re.DOTALL - inner_pattern += r"{}(?:[^{}{}])".format( - sep, - _escape_regex_range_chars(self.endQuoteChar[0]), - (_escape_regex_range_chars(escChar) if escChar is not None else ""), - ) - else: - self.flags = 0 - inner_pattern += r"{}(?:[^{}\n\r{}])".format( - sep, - _escape_regex_range_chars(self.endQuoteChar[0]), - (_escape_regex_range_chars(escChar) if escChar is not None else ""), - ) - - self.pattern = "".join( - [ - re.escape(self.quoteChar), - "(?:", - inner_pattern, - ")*", - re.escape(self.endQuoteChar), - ] - ) - - try: - self.re = re.compile(self.pattern, self.flags) - self.reString = self.pattern - self.re_match = self.re.match - except re.error: - raise ValueError( - "invalid pattern {!r} passed to Regex".format(self.pattern) - ) - - self.errmsg = "Expected " + self.name - self.mayIndexError = False - self.mayReturnEmpty = True - - def _generateDefaultName(self): - if self.quoteChar == self.endQuoteChar and isinstance(self.quoteChar, str_type): - return "string enclosed in {!r}".format(self.quoteChar) - - return "quoted string, starting with {} ending with {}".format( - self.quoteChar, self.endQuoteChar - ) - - def parseImpl(self, instring, loc, doActions=True): - result = ( - instring[loc] == self.firstQuoteChar - and self.re_match(instring, loc) - or None - ) - if not result: - raise ParseException(instring, loc, self.errmsg, self) - - loc = result.end() - ret = result.group() - - if self.unquoteResults: - - # strip off quotes - ret = ret[self.quoteCharLen : -self.endQuoteCharLen] - - if isinstance(ret, str_type): - # replace escaped whitespace - if "\\" in ret and self.convertWhitespaceEscapes: - for wslit, wschar in self.ws_map: - ret = ret.replace(wslit, wschar) - - # replace escaped characters - if self.escChar: - ret = re.sub(self.escCharReplacePattern, r"\g<1>", ret) - - # replace escaped quotes - if self.escQuote: - ret = ret.replace(self.escQuote, self.endQuoteChar) - - return loc, ret - - -class CharsNotIn(Token): - """Token for matching words composed of characters *not* in a given - set (will include whitespace in matched characters if not listed in - the provided exclusion set - see example). Defined with string - containing all disallowed characters, and an optional minimum, - maximum, and/or exact length. The default value for ``min`` is - 1 (a minimum value < 1 is not valid); the default values for - ``max`` and ``exact`` are 0, meaning no maximum or exact - length restriction. - - Example:: - - # define a comma-separated-value as anything that is not a ',' - csv_value = CharsNotIn(',') - print(delimited_list(csv_value).parse_string("dkls,lsdkjf,s12 34,@!#,213")) - - prints:: - - ['dkls', 'lsdkjf', 's12 34', '@!#', '213'] - """ - - def __init__( - self, - not_chars: str = "", - min: int = 1, - max: int = 0, - exact: int = 0, - *, - notChars: str = "", - ): - super().__init__() - self.skipWhitespace = False - self.notChars = not_chars or notChars - self.notCharsSet = set(self.notChars) - - if min < 1: - raise ValueError( - "cannot specify a minimum length < 1; use " - "Opt(CharsNotIn()) if zero-length char group is permitted" - ) - - self.minLen = min - - if max > 0: - self.maxLen = max - else: - self.maxLen = _MAX_INT - - if exact > 0: - self.maxLen = exact - self.minLen = exact - - self.errmsg = "Expected " + self.name - self.mayReturnEmpty = self.minLen == 0 - self.mayIndexError = False - - def _generateDefaultName(self): - not_chars_str = _collapse_string_to_ranges(self.notChars) - if len(not_chars_str) > 16: - return "!W:({}...)".format(self.notChars[: 16 - 3]) - else: - return "!W:({})".format(self.notChars) - - def parseImpl(self, instring, loc, doActions=True): - notchars = self.notCharsSet - if instring[loc] in notchars: - raise ParseException(instring, loc, self.errmsg, self) - - start = loc - loc += 1 - maxlen = min(start + self.maxLen, len(instring)) - while loc < maxlen and instring[loc] not in notchars: - loc += 1 - - if loc - start < self.minLen: - raise ParseException(instring, loc, self.errmsg, self) - - return loc, instring[start:loc] - - -class White(Token): - """Special matching class for matching whitespace. Normally, - whitespace is ignored by pyparsing grammars. This class is included - when some whitespace structures are significant. Define with - a string containing the whitespace characters to be matched; default - is ``" \\t\\r\\n"``. Also takes optional ``min``, - ``max``, and ``exact`` arguments, as defined for the - :class:`Word` class. - """ - - whiteStrs = { - " ": "", - "\t": "", - "\n": "", - "\r": "", - "\f": "", - "\u00A0": "", - "\u1680": "", - "\u180E": "", - "\u2000": "", - "\u2001": "", - "\u2002": "", - "\u2003": "", - "\u2004": "", - "\u2005": "", - "\u2006": "", - "\u2007": "", - "\u2008": "", - "\u2009": "", - "\u200A": "", - "\u200B": "", - "\u202F": "", - "\u205F": "", - "\u3000": "", - } - - def __init__(self, ws: str = " \t\r\n", min: int = 1, max: int = 0, exact: int = 0): - super().__init__() - self.matchWhite = ws - self.set_whitespace_chars( - "".join(c for c in self.whiteStrs if c not in self.matchWhite), - copy_defaults=True, - ) - # self.leave_whitespace() - self.mayReturnEmpty = True - self.errmsg = "Expected " + self.name - - self.minLen = min - - if max > 0: - self.maxLen = max - else: - self.maxLen = _MAX_INT - - if exact > 0: - self.maxLen = exact - self.minLen = exact - - def _generateDefaultName(self): - return "".join(White.whiteStrs[c] for c in self.matchWhite) - - def parseImpl(self, instring, loc, doActions=True): - if instring[loc] not in self.matchWhite: - raise ParseException(instring, loc, self.errmsg, self) - start = loc - loc += 1 - maxloc = start + self.maxLen - maxloc = min(maxloc, len(instring)) - while loc < maxloc and instring[loc] in self.matchWhite: - loc += 1 - - if loc - start < self.minLen: - raise ParseException(instring, loc, self.errmsg, self) - - return loc, instring[start:loc] - - -class PositionToken(Token): - def __init__(self): - super().__init__() - self.mayReturnEmpty = True - self.mayIndexError = False - - -class GoToColumn(PositionToken): - """Token to advance to a specific column of input text; useful for - tabular report scraping. - """ - - def __init__(self, colno: int): - super().__init__() - self.col = colno - - def preParse(self, instring, loc): - if col(loc, instring) != self.col: - instrlen = len(instring) - if self.ignoreExprs: - loc = self._skipIgnorables(instring, loc) - while ( - loc < instrlen - and instring[loc].isspace() - and col(loc, instring) != self.col - ): - loc += 1 - return loc - - def parseImpl(self, instring, loc, doActions=True): - thiscol = col(loc, instring) - if thiscol > self.col: - raise ParseException(instring, loc, "Text not in expected column", self) - newloc = loc + self.col - thiscol - ret = instring[loc:newloc] - return newloc, ret - - -class LineStart(PositionToken): - r"""Matches if current position is at the beginning of a line within - the parse string - - Example:: - - test = '''\ - AAA this line - AAA and this line - AAA but not this one - B AAA and definitely not this one - ''' - - for t in (LineStart() + 'AAA' + restOfLine).search_string(test): - print(t) - - prints:: - - ['AAA', ' this line'] - ['AAA', ' and this line'] - - """ - - def __init__(self): - super().__init__() - self.leave_whitespace() - self.orig_whiteChars = set() | self.whiteChars - self.whiteChars.discard("\n") - self.skipper = Empty().set_whitespace_chars(self.whiteChars) - self.errmsg = "Expected start of line" - - def preParse(self, instring, loc): - if loc == 0: - return loc - else: - ret = self.skipper.preParse(instring, loc) - if "\n" in self.orig_whiteChars: - while instring[ret : ret + 1] == "\n": - ret = self.skipper.preParse(instring, ret + 1) - return ret - - def parseImpl(self, instring, loc, doActions=True): - if col(loc, instring) == 1: - return loc, [] - raise ParseException(instring, loc, self.errmsg, self) - - -class LineEnd(PositionToken): - """Matches if current position is at the end of a line within the - parse string - """ - - def __init__(self): - super().__init__() - self.whiteChars.discard("\n") - self.set_whitespace_chars(self.whiteChars, copy_defaults=False) - self.errmsg = "Expected end of line" - - def parseImpl(self, instring, loc, doActions=True): - if loc < len(instring): - if instring[loc] == "\n": - return loc + 1, "\n" - else: - raise ParseException(instring, loc, self.errmsg, self) - elif loc == len(instring): - return loc + 1, [] - else: - raise ParseException(instring, loc, self.errmsg, self) - - -class StringStart(PositionToken): - """Matches if current position is at the beginning of the parse - string - """ - - def __init__(self): - super().__init__() - self.errmsg = "Expected start of text" - - def parseImpl(self, instring, loc, doActions=True): - if loc != 0: - # see if entire string up to here is just whitespace and ignoreables - if loc != self.preParse(instring, 0): - raise ParseException(instring, loc, self.errmsg, self) - return loc, [] - - -class StringEnd(PositionToken): - """ - Matches if current position is at the end of the parse string - """ - - def __init__(self): - super().__init__() - self.errmsg = "Expected end of text" - - def parseImpl(self, instring, loc, doActions=True): - if loc < len(instring): - raise ParseException(instring, loc, self.errmsg, self) - elif loc == len(instring): - return loc + 1, [] - elif loc > len(instring): - return loc, [] - else: - raise ParseException(instring, loc, self.errmsg, self) - - -class WordStart(PositionToken): - """Matches if the current position is at the beginning of a - :class:`Word`, and is not preceded by any character in a given - set of ``word_chars`` (default= ``printables``). To emulate the - ``\b`` behavior of regular expressions, use - ``WordStart(alphanums)``. ``WordStart`` will also match at - the beginning of the string being parsed, or at the beginning of - a line. - """ - - def __init__(self, word_chars: str = printables, *, wordChars: str = printables): - wordChars = word_chars if wordChars == printables else wordChars - super().__init__() - self.wordChars = set(wordChars) - self.errmsg = "Not at the start of a word" - - def parseImpl(self, instring, loc, doActions=True): - if loc != 0: - if ( - instring[loc - 1] in self.wordChars - or instring[loc] not in self.wordChars - ): - raise ParseException(instring, loc, self.errmsg, self) - return loc, [] - - -class WordEnd(PositionToken): - """Matches if the current position is at the end of a :class:`Word`, - and is not followed by any character in a given set of ``word_chars`` - (default= ``printables``). To emulate the ``\b`` behavior of - regular expressions, use ``WordEnd(alphanums)``. ``WordEnd`` - will also match at the end of the string being parsed, or at the end - of a line. - """ - - def __init__(self, word_chars: str = printables, *, wordChars: str = printables): - wordChars = word_chars if wordChars == printables else wordChars - super().__init__() - self.wordChars = set(wordChars) - self.skipWhitespace = False - self.errmsg = "Not at the end of a word" - - def parseImpl(self, instring, loc, doActions=True): - instrlen = len(instring) - if instrlen > 0 and loc < instrlen: - if ( - instring[loc] in self.wordChars - or instring[loc - 1] not in self.wordChars - ): - raise ParseException(instring, loc, self.errmsg, self) - return loc, [] - - -class ParseExpression(ParserElement): - """Abstract subclass of ParserElement, for combining and - post-processing parsed tokens. - """ - - def __init__(self, exprs: typing.Iterable[ParserElement], savelist: bool = False): - super().__init__(savelist) - self.exprs: List[ParserElement] - if isinstance(exprs, _generatorType): - exprs = list(exprs) - - if isinstance(exprs, str_type): - self.exprs = [self._literalStringClass(exprs)] - elif isinstance(exprs, ParserElement): - self.exprs = [exprs] - elif isinstance(exprs, Iterable): - exprs = list(exprs) - # if sequence of strings provided, wrap with Literal - if any(isinstance(expr, str_type) for expr in exprs): - exprs = ( - self._literalStringClass(e) if isinstance(e, str_type) else e - for e in exprs - ) - self.exprs = list(exprs) - else: - try: - self.exprs = list(exprs) - except TypeError: - self.exprs = [exprs] - self.callPreparse = False - - def recurse(self) -> Sequence[ParserElement]: - return self.exprs[:] - - def append(self, other) -> ParserElement: - self.exprs.append(other) - self._defaultName = None - return self - - def leave_whitespace(self, recursive: bool = True) -> ParserElement: - """ - Extends ``leave_whitespace`` defined in base class, and also invokes ``leave_whitespace`` on - all contained expressions. - """ - super().leave_whitespace(recursive) - - if recursive: - self.exprs = [e.copy() for e in self.exprs] - for e in self.exprs: - e.leave_whitespace(recursive) - return self - - def ignore_whitespace(self, recursive: bool = True) -> ParserElement: - """ - Extends ``ignore_whitespace`` defined in base class, and also invokes ``leave_whitespace`` on - all contained expressions. - """ - super().ignore_whitespace(recursive) - if recursive: - self.exprs = [e.copy() for e in self.exprs] - for e in self.exprs: - e.ignore_whitespace(recursive) - return self - - def ignore(self, other) -> ParserElement: - if isinstance(other, Suppress): - if other not in self.ignoreExprs: - super().ignore(other) - for e in self.exprs: - e.ignore(self.ignoreExprs[-1]) - else: - super().ignore(other) - for e in self.exprs: - e.ignore(self.ignoreExprs[-1]) - return self - - def _generateDefaultName(self): - return "{}:({})".format(self.__class__.__name__, str(self.exprs)) - - def streamline(self) -> ParserElement: - if self.streamlined: - return self - - super().streamline() - - for e in self.exprs: - e.streamline() - - # collapse nested :class:`And`'s of the form ``And(And(And(a, b), c), d)`` to ``And(a, b, c, d)`` - # but only if there are no parse actions or resultsNames on the nested And's - # (likewise for :class:`Or`'s and :class:`MatchFirst`'s) - if len(self.exprs) == 2: - other = self.exprs[0] - if ( - isinstance(other, self.__class__) - and not other.parseAction - and other.resultsName is None - and not other.debug - ): - self.exprs = other.exprs[:] + [self.exprs[1]] - self._defaultName = None - self.mayReturnEmpty |= other.mayReturnEmpty - self.mayIndexError |= other.mayIndexError - - other = self.exprs[-1] - if ( - isinstance(other, self.__class__) - and not other.parseAction - and other.resultsName is None - and not other.debug - ): - self.exprs = self.exprs[:-1] + other.exprs[:] - self._defaultName = None - self.mayReturnEmpty |= other.mayReturnEmpty - self.mayIndexError |= other.mayIndexError - - self.errmsg = "Expected " + str(self) - - return self - - def validate(self, validateTrace=None) -> None: - tmp = (validateTrace if validateTrace is not None else [])[:] + [self] - for e in self.exprs: - e.validate(tmp) - self._checkRecursion([]) - - def copy(self) -> ParserElement: - ret = super().copy() - ret.exprs = [e.copy() for e in self.exprs] - return ret - - def _setResultsName(self, name, listAllMatches=False): - if ( - __diag__.warn_ungrouped_named_tokens_in_collection - and Diagnostics.warn_ungrouped_named_tokens_in_collection - not in self.suppress_warnings_ - ): - for e in self.exprs: - if ( - isinstance(e, ParserElement) - and e.resultsName - and Diagnostics.warn_ungrouped_named_tokens_in_collection - not in e.suppress_warnings_ - ): - warnings.warn( - "{}: setting results name {!r} on {} expression " - "collides with {!r} on contained expression".format( - "warn_ungrouped_named_tokens_in_collection", - name, - type(self).__name__, - e.resultsName, - ), - stacklevel=3, - ) - - return super()._setResultsName(name, listAllMatches) - - ignoreWhitespace = ignore_whitespace - leaveWhitespace = leave_whitespace - - -class And(ParseExpression): - """ - Requires all given :class:`ParseExpression` s to be found in the given order. - Expressions may be separated by whitespace. - May be constructed using the ``'+'`` operator. - May also be constructed using the ``'-'`` operator, which will - suppress backtracking. - - Example:: - - integer = Word(nums) - name_expr = Word(alphas)[1, ...] - - expr = And([integer("id"), name_expr("name"), integer("age")]) - # more easily written as: - expr = integer("id") + name_expr("name") + integer("age") - """ - - class _ErrorStop(Empty): - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.leave_whitespace() - - def _generateDefaultName(self): - return "-" - - def __init__( - self, exprs_arg: typing.Iterable[ParserElement], savelist: bool = True - ): - exprs: List[ParserElement] = list(exprs_arg) - if exprs and Ellipsis in exprs: - tmp = [] - for i, expr in enumerate(exprs): - if expr is Ellipsis: - if i < len(exprs) - 1: - skipto_arg: ParserElement = (Empty() + exprs[i + 1]).exprs[-1] - tmp.append(SkipTo(skipto_arg)("_skipped*")) - else: - raise Exception( - "cannot construct And with sequence ending in ..." - ) - else: - tmp.append(expr) - exprs[:] = tmp - super().__init__(exprs, savelist) - if self.exprs: - self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs) - if not isinstance(self.exprs[0], White): - self.set_whitespace_chars( - self.exprs[0].whiteChars, - copy_defaults=self.exprs[0].copyDefaultWhiteChars, - ) - self.skipWhitespace = self.exprs[0].skipWhitespace - else: - self.skipWhitespace = False - else: - self.mayReturnEmpty = True - self.callPreparse = True - - def streamline(self) -> ParserElement: - # collapse any _PendingSkip's - if self.exprs: - if any( - isinstance(e, ParseExpression) - and e.exprs - and isinstance(e.exprs[-1], _PendingSkip) - for e in self.exprs[:-1] - ): - for i, e in enumerate(self.exprs[:-1]): - if e is None: - continue - if ( - isinstance(e, ParseExpression) - and e.exprs - and isinstance(e.exprs[-1], _PendingSkip) - ): - e.exprs[-1] = e.exprs[-1] + self.exprs[i + 1] - self.exprs[i + 1] = None - self.exprs = [e for e in self.exprs if e is not None] - - super().streamline() - - # link any IndentedBlocks to the prior expression - for prev, cur in zip(self.exprs, self.exprs[1:]): - # traverse cur or any first embedded expr of cur looking for an IndentedBlock - # (but watch out for recursive grammar) - seen = set() - while cur: - if id(cur) in seen: - break - seen.add(id(cur)) - if isinstance(cur, IndentedBlock): - prev.add_parse_action( - lambda s, l, t, cur_=cur: setattr( - cur_, "parent_anchor", col(l, s) - ) - ) - break - subs = cur.recurse() - cur = next(iter(subs), None) - - self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs) - return self - - def parseImpl(self, instring, loc, doActions=True): - # pass False as callPreParse arg to _parse for first element, since we already - # pre-parsed the string as part of our And pre-parsing - loc, resultlist = self.exprs[0]._parse( - instring, loc, doActions, callPreParse=False - ) - errorStop = False - for e in self.exprs[1:]: - # if isinstance(e, And._ErrorStop): - if type(e) is And._ErrorStop: - errorStop = True - continue - if errorStop: - try: - loc, exprtokens = e._parse(instring, loc, doActions) - except ParseSyntaxException: - raise - except ParseBaseException as pe: - pe.__traceback__ = None - raise ParseSyntaxException._from_exception(pe) - except IndexError: - raise ParseSyntaxException( - instring, len(instring), self.errmsg, self - ) - else: - loc, exprtokens = e._parse(instring, loc, doActions) - if exprtokens or exprtokens.haskeys(): - resultlist += exprtokens - return loc, resultlist - - def __iadd__(self, other): - if isinstance(other, str_type): - other = self._literalStringClass(other) - return self.append(other) # And([self, other]) - - def _checkRecursion(self, parseElementList): - subRecCheckList = parseElementList[:] + [self] - for e in self.exprs: - e._checkRecursion(subRecCheckList) - if not e.mayReturnEmpty: - break - - def _generateDefaultName(self): - inner = " ".join(str(e) for e in self.exprs) - # strip off redundant inner {}'s - while len(inner) > 1 and inner[0 :: len(inner) - 1] == "{}": - inner = inner[1:-1] - return "{" + inner + "}" - - -class Or(ParseExpression): - """Requires that at least one :class:`ParseExpression` is found. If - two expressions match, the expression that matches the longest - string will be used. May be constructed using the ``'^'`` - operator. - - Example:: - - # construct Or using '^' operator - - number = Word(nums) ^ Combine(Word(nums) + '.' + Word(nums)) - print(number.search_string("123 3.1416 789")) - - prints:: - - [['123'], ['3.1416'], ['789']] - """ - - def __init__(self, exprs: typing.Iterable[ParserElement], savelist: bool = False): - super().__init__(exprs, savelist) - if self.exprs: - self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs) - self.skipWhitespace = all(e.skipWhitespace for e in self.exprs) - else: - self.mayReturnEmpty = True - - def streamline(self) -> ParserElement: - super().streamline() - if self.exprs: - self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs) - self.saveAsList = any(e.saveAsList for e in self.exprs) - self.skipWhitespace = all( - e.skipWhitespace and not isinstance(e, White) for e in self.exprs - ) - else: - self.saveAsList = False - return self - - def parseImpl(self, instring, loc, doActions=True): - maxExcLoc = -1 - maxException = None - matches = [] - fatals = [] - if all(e.callPreparse for e in self.exprs): - loc = self.preParse(instring, loc) - for e in self.exprs: - try: - loc2 = e.try_parse(instring, loc, raise_fatal=True) - except ParseFatalException as pfe: - pfe.__traceback__ = None - pfe.parserElement = e - fatals.append(pfe) - maxException = None - maxExcLoc = -1 - except ParseException as err: - if not fatals: - err.__traceback__ = None - if err.loc > maxExcLoc: - maxException = err - maxExcLoc = err.loc - except IndexError: - if len(instring) > maxExcLoc: - maxException = ParseException( - instring, len(instring), e.errmsg, self - ) - maxExcLoc = len(instring) - else: - # save match among all matches, to retry longest to shortest - matches.append((loc2, e)) - - if matches: - # re-evaluate all matches in descending order of length of match, in case attached actions - # might change whether or how much they match of the input. - matches.sort(key=itemgetter(0), reverse=True) - - if not doActions: - # no further conditions or parse actions to change the selection of - # alternative, so the first match will be the best match - best_expr = matches[0][1] - return best_expr._parse(instring, loc, doActions) - - longest = -1, None - for loc1, expr1 in matches: - if loc1 <= longest[0]: - # already have a longer match than this one will deliver, we are done - return longest - - try: - loc2, toks = expr1._parse(instring, loc, doActions) - except ParseException as err: - err.__traceback__ = None - if err.loc > maxExcLoc: - maxException = err - maxExcLoc = err.loc - else: - if loc2 >= loc1: - return loc2, toks - # didn't match as much as before - elif loc2 > longest[0]: - longest = loc2, toks - - if longest != (-1, None): - return longest - - if fatals: - if len(fatals) > 1: - fatals.sort(key=lambda e: -e.loc) - if fatals[0].loc == fatals[1].loc: - fatals.sort(key=lambda e: (-e.loc, -len(str(e.parserElement)))) - max_fatal = fatals[0] - raise max_fatal - - if maxException is not None: - maxException.msg = self.errmsg - raise maxException - else: - raise ParseException( - instring, loc, "no defined alternatives to match", self - ) - - def __ixor__(self, other): - if isinstance(other, str_type): - other = self._literalStringClass(other) - return self.append(other) # Or([self, other]) - - def _generateDefaultName(self): - return "{" + " ^ ".join(str(e) for e in self.exprs) + "}" - - def _setResultsName(self, name, listAllMatches=False): - if ( - __diag__.warn_multiple_tokens_in_named_alternation - and Diagnostics.warn_multiple_tokens_in_named_alternation - not in self.suppress_warnings_ - ): - if any( - isinstance(e, And) - and Diagnostics.warn_multiple_tokens_in_named_alternation - not in e.suppress_warnings_ - for e in self.exprs - ): - warnings.warn( - "{}: setting results name {!r} on {} expression " - "will return a list of all parsed tokens in an And alternative, " - "in prior versions only the first token was returned; enclose " - "contained argument in Group".format( - "warn_multiple_tokens_in_named_alternation", - name, - type(self).__name__, - ), - stacklevel=3, - ) - - return super()._setResultsName(name, listAllMatches) - - -class MatchFirst(ParseExpression): - """Requires that at least one :class:`ParseExpression` is found. If - more than one expression matches, the first one listed is the one that will - match. May be constructed using the ``'|'`` operator. - - Example:: - - # construct MatchFirst using '|' operator - - # watch the order of expressions to match - number = Word(nums) | Combine(Word(nums) + '.' + Word(nums)) - print(number.search_string("123 3.1416 789")) # Fail! -> [['123'], ['3'], ['1416'], ['789']] - - # put more selective expression first - number = Combine(Word(nums) + '.' + Word(nums)) | Word(nums) - print(number.search_string("123 3.1416 789")) # Better -> [['123'], ['3.1416'], ['789']] - """ - - def __init__(self, exprs: typing.Iterable[ParserElement], savelist: bool = False): - super().__init__(exprs, savelist) - if self.exprs: - self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs) - self.skipWhitespace = all(e.skipWhitespace for e in self.exprs) - else: - self.mayReturnEmpty = True - - def streamline(self) -> ParserElement: - if self.streamlined: - return self - - super().streamline() - if self.exprs: - self.saveAsList = any(e.saveAsList for e in self.exprs) - self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs) - self.skipWhitespace = all( - e.skipWhitespace and not isinstance(e, White) for e in self.exprs - ) - else: - self.saveAsList = False - self.mayReturnEmpty = True - return self - - def parseImpl(self, instring, loc, doActions=True): - maxExcLoc = -1 - maxException = None - - for e in self.exprs: - try: - return e._parse( - instring, - loc, - doActions, - ) - except ParseFatalException as pfe: - pfe.__traceback__ = None - pfe.parserElement = e - raise - except ParseException as err: - if err.loc > maxExcLoc: - maxException = err - maxExcLoc = err.loc - except IndexError: - if len(instring) > maxExcLoc: - maxException = ParseException( - instring, len(instring), e.errmsg, self - ) - maxExcLoc = len(instring) - - if maxException is not None: - maxException.msg = self.errmsg - raise maxException - else: - raise ParseException( - instring, loc, "no defined alternatives to match", self - ) - - def __ior__(self, other): - if isinstance(other, str_type): - other = self._literalStringClass(other) - return self.append(other) # MatchFirst([self, other]) - - def _generateDefaultName(self): - return "{" + " | ".join(str(e) for e in self.exprs) + "}" - - def _setResultsName(self, name, listAllMatches=False): - if ( - __diag__.warn_multiple_tokens_in_named_alternation - and Diagnostics.warn_multiple_tokens_in_named_alternation - not in self.suppress_warnings_ - ): - if any( - isinstance(e, And) - and Diagnostics.warn_multiple_tokens_in_named_alternation - not in e.suppress_warnings_ - for e in self.exprs - ): - warnings.warn( - "{}: setting results name {!r} on {} expression " - "will return a list of all parsed tokens in an And alternative, " - "in prior versions only the first token was returned; enclose " - "contained argument in Group".format( - "warn_multiple_tokens_in_named_alternation", - name, - type(self).__name__, - ), - stacklevel=3, - ) - - return super()._setResultsName(name, listAllMatches) - - -class Each(ParseExpression): - """Requires all given :class:`ParseExpression` s to be found, but in - any order. Expressions may be separated by whitespace. - - May be constructed using the ``'&'`` operator. - - Example:: - - color = one_of("RED ORANGE YELLOW GREEN BLUE PURPLE BLACK WHITE BROWN") - shape_type = one_of("SQUARE CIRCLE TRIANGLE STAR HEXAGON OCTAGON") - integer = Word(nums) - shape_attr = "shape:" + shape_type("shape") - posn_attr = "posn:" + Group(integer("x") + ',' + integer("y"))("posn") - color_attr = "color:" + color("color") - size_attr = "size:" + integer("size") - - # use Each (using operator '&') to accept attributes in any order - # (shape and posn are required, color and size are optional) - shape_spec = shape_attr & posn_attr & Opt(color_attr) & Opt(size_attr) - - shape_spec.run_tests(''' - shape: SQUARE color: BLACK posn: 100, 120 - shape: CIRCLE size: 50 color: BLUE posn: 50,80 - color:GREEN size:20 shape:TRIANGLE posn:20,40 - ''' - ) - - prints:: - - shape: SQUARE color: BLACK posn: 100, 120 - ['shape:', 'SQUARE', 'color:', 'BLACK', 'posn:', ['100', ',', '120']] - - color: BLACK - - posn: ['100', ',', '120'] - - x: 100 - - y: 120 - - shape: SQUARE - - - shape: CIRCLE size: 50 color: BLUE posn: 50,80 - ['shape:', 'CIRCLE', 'size:', '50', 'color:', 'BLUE', 'posn:', ['50', ',', '80']] - - color: BLUE - - posn: ['50', ',', '80'] - - x: 50 - - y: 80 - - shape: CIRCLE - - size: 50 - - - color: GREEN size: 20 shape: TRIANGLE posn: 20,40 - ['color:', 'GREEN', 'size:', '20', 'shape:', 'TRIANGLE', 'posn:', ['20', ',', '40']] - - color: GREEN - - posn: ['20', ',', '40'] - - x: 20 - - y: 40 - - shape: TRIANGLE - - size: 20 - """ - - def __init__(self, exprs: typing.Iterable[ParserElement], savelist: bool = True): - super().__init__(exprs, savelist) - if self.exprs: - self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs) - else: - self.mayReturnEmpty = True - self.skipWhitespace = True - self.initExprGroups = True - self.saveAsList = True - - def streamline(self) -> ParserElement: - super().streamline() - if self.exprs: - self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs) - else: - self.mayReturnEmpty = True - return self - - def parseImpl(self, instring, loc, doActions=True): - if self.initExprGroups: - self.opt1map = dict( - (id(e.expr), e) for e in self.exprs if isinstance(e, Opt) - ) - opt1 = [e.expr for e in self.exprs if isinstance(e, Opt)] - opt2 = [ - e - for e in self.exprs - if e.mayReturnEmpty and not isinstance(e, (Opt, Regex, ZeroOrMore)) - ] - self.optionals = opt1 + opt2 - self.multioptionals = [ - e.expr.set_results_name(e.resultsName, list_all_matches=True) - for e in self.exprs - if isinstance(e, _MultipleMatch) - ] - self.multirequired = [ - e.expr.set_results_name(e.resultsName, list_all_matches=True) - for e in self.exprs - if isinstance(e, OneOrMore) - ] - self.required = [ - e for e in self.exprs if not isinstance(e, (Opt, ZeroOrMore, OneOrMore)) - ] - self.required += self.multirequired - self.initExprGroups = False - - tmpLoc = loc - tmpReqd = self.required[:] - tmpOpt = self.optionals[:] - multis = self.multioptionals[:] - matchOrder = [] - - keepMatching = True - failed = [] - fatals = [] - while keepMatching: - tmpExprs = tmpReqd + tmpOpt + multis - failed.clear() - fatals.clear() - for e in tmpExprs: - try: - tmpLoc = e.try_parse(instring, tmpLoc, raise_fatal=True) - except ParseFatalException as pfe: - pfe.__traceback__ = None - pfe.parserElement = e - fatals.append(pfe) - failed.append(e) - except ParseException: - failed.append(e) - else: - matchOrder.append(self.opt1map.get(id(e), e)) - if e in tmpReqd: - tmpReqd.remove(e) - elif e in tmpOpt: - tmpOpt.remove(e) - if len(failed) == len(tmpExprs): - keepMatching = False - - # look for any ParseFatalExceptions - if fatals: - if len(fatals) > 1: - fatals.sort(key=lambda e: -e.loc) - if fatals[0].loc == fatals[1].loc: - fatals.sort(key=lambda e: (-e.loc, -len(str(e.parserElement)))) - max_fatal = fatals[0] - raise max_fatal - - if tmpReqd: - missing = ", ".join([str(e) for e in tmpReqd]) - raise ParseException( - instring, - loc, - "Missing one or more required elements ({})".format(missing), - ) - - # add any unmatched Opts, in case they have default values defined - matchOrder += [e for e in self.exprs if isinstance(e, Opt) and e.expr in tmpOpt] - - total_results = ParseResults([]) - for e in matchOrder: - loc, results = e._parse(instring, loc, doActions) - total_results += results - - return loc, total_results - - def _generateDefaultName(self): - return "{" + " & ".join(str(e) for e in self.exprs) + "}" - - -class ParseElementEnhance(ParserElement): - """Abstract subclass of :class:`ParserElement`, for combining and - post-processing parsed tokens. - """ - - def __init__(self, expr: Union[ParserElement, str], savelist: bool = False): - super().__init__(savelist) - if isinstance(expr, str_type): - if issubclass(self._literalStringClass, Token): - expr = self._literalStringClass(expr) - elif issubclass(type(self), self._literalStringClass): - expr = Literal(expr) - else: - expr = self._literalStringClass(Literal(expr)) - self.expr = expr - if expr is not None: - self.mayIndexError = expr.mayIndexError - self.mayReturnEmpty = expr.mayReturnEmpty - self.set_whitespace_chars( - expr.whiteChars, copy_defaults=expr.copyDefaultWhiteChars - ) - self.skipWhitespace = expr.skipWhitespace - self.saveAsList = expr.saveAsList - self.callPreparse = expr.callPreparse - self.ignoreExprs.extend(expr.ignoreExprs) - - def recurse(self) -> Sequence[ParserElement]: - return [self.expr] if self.expr is not None else [] - - def parseImpl(self, instring, loc, doActions=True): - if self.expr is not None: - return self.expr._parse(instring, loc, doActions, callPreParse=False) - else: - raise ParseException(instring, loc, "No expression defined", self) - - def leave_whitespace(self, recursive: bool = True) -> ParserElement: - super().leave_whitespace(recursive) - - if recursive: - self.expr = self.expr.copy() - if self.expr is not None: - self.expr.leave_whitespace(recursive) - return self - - def ignore_whitespace(self, recursive: bool = True) -> ParserElement: - super().ignore_whitespace(recursive) - - if recursive: - self.expr = self.expr.copy() - if self.expr is not None: - self.expr.ignore_whitespace(recursive) - return self - - def ignore(self, other) -> ParserElement: - if isinstance(other, Suppress): - if other not in self.ignoreExprs: - super().ignore(other) - if self.expr is not None: - self.expr.ignore(self.ignoreExprs[-1]) - else: - super().ignore(other) - if self.expr is not None: - self.expr.ignore(self.ignoreExprs[-1]) - return self - - def streamline(self) -> ParserElement: - super().streamline() - if self.expr is not None: - self.expr.streamline() - return self - - def _checkRecursion(self, parseElementList): - if self in parseElementList: - raise RecursiveGrammarException(parseElementList + [self]) - subRecCheckList = parseElementList[:] + [self] - if self.expr is not None: - self.expr._checkRecursion(subRecCheckList) - - def validate(self, validateTrace=None) -> None: - if validateTrace is None: - validateTrace = [] - tmp = validateTrace[:] + [self] - if self.expr is not None: - self.expr.validate(tmp) - self._checkRecursion([]) - - def _generateDefaultName(self): - return "{}:({})".format(self.__class__.__name__, str(self.expr)) - - ignoreWhitespace = ignore_whitespace - leaveWhitespace = leave_whitespace - - -class IndentedBlock(ParseElementEnhance): - """ - Expression to match one or more expressions at a given indentation level. - Useful for parsing text where structure is implied by indentation (like Python source code). - """ - - class _Indent(Empty): - def __init__(self, ref_col: int): - super().__init__() - self.errmsg = "expected indent at column {}".format(ref_col) - self.add_condition(lambda s, l, t: col(l, s) == ref_col) - - class _IndentGreater(Empty): - def __init__(self, ref_col: int): - super().__init__() - self.errmsg = "expected indent at column greater than {}".format(ref_col) - self.add_condition(lambda s, l, t: col(l, s) > ref_col) - - def __init__( - self, expr: ParserElement, *, recursive: bool = False, grouped: bool = True - ): - super().__init__(expr, savelist=True) - # if recursive: - # raise NotImplementedError("IndentedBlock with recursive is not implemented") - self._recursive = recursive - self._grouped = grouped - self.parent_anchor = 1 - - def parseImpl(self, instring, loc, doActions=True): - # advance parse position to non-whitespace by using an Empty() - # this should be the column to be used for all subsequent indented lines - anchor_loc = Empty().preParse(instring, loc) - - # see if self.expr matches at the current location - if not it will raise an exception - # and no further work is necessary - self.expr.try_parse(instring, anchor_loc, doActions) - - indent_col = col(anchor_loc, instring) - peer_detect_expr = self._Indent(indent_col) - - inner_expr = Empty() + peer_detect_expr + self.expr - if self._recursive: - sub_indent = self._IndentGreater(indent_col) - nested_block = IndentedBlock( - self.expr, recursive=self._recursive, grouped=self._grouped - ) - nested_block.set_debug(self.debug) - nested_block.parent_anchor = indent_col - inner_expr += Opt(sub_indent + nested_block) - - inner_expr.set_name(f"inner {hex(id(inner_expr))[-4:].upper()}@{indent_col}") - block = OneOrMore(inner_expr) - - trailing_undent = self._Indent(self.parent_anchor) | StringEnd() - - if self._grouped: - wrapper = Group - else: - wrapper = lambda expr: expr - return (wrapper(block) + Optional(trailing_undent)).parseImpl( - instring, anchor_loc, doActions - ) - - -class AtStringStart(ParseElementEnhance): - """Matches if expression matches at the beginning of the parse - string:: - - AtStringStart(Word(nums)).parse_string("123") - # prints ["123"] - - AtStringStart(Word(nums)).parse_string(" 123") - # raises ParseException - """ - - def __init__(self, expr: Union[ParserElement, str]): - super().__init__(expr) - self.callPreparse = False - - def parseImpl(self, instring, loc, doActions=True): - if loc != 0: - raise ParseException(instring, loc, "not found at string start") - return super().parseImpl(instring, loc, doActions) - - -class AtLineStart(ParseElementEnhance): - r"""Matches if an expression matches at the beginning of a line within - the parse string - - Example:: - - test = '''\ - AAA this line - AAA and this line - AAA but not this one - B AAA and definitely not this one - ''' - - for t in (AtLineStart('AAA') + restOfLine).search_string(test): - print(t) - - prints:: - - ['AAA', ' this line'] - ['AAA', ' and this line'] - - """ - - def __init__(self, expr: Union[ParserElement, str]): - super().__init__(expr) - self.callPreparse = False - - def parseImpl(self, instring, loc, doActions=True): - if col(loc, instring) != 1: - raise ParseException(instring, loc, "not found at line start") - return super().parseImpl(instring, loc, doActions) - - -class FollowedBy(ParseElementEnhance): - """Lookahead matching of the given parse expression. - ``FollowedBy`` does *not* advance the parsing position within - the input string, it only verifies that the specified parse - expression matches at the current position. ``FollowedBy`` - always returns a null token list. If any results names are defined - in the lookahead expression, those *will* be returned for access by - name. - - Example:: - - # use FollowedBy to match a label only if it is followed by a ':' - data_word = Word(alphas) - label = data_word + FollowedBy(':') - attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stop_on=label).set_parse_action(' '.join)) - - attr_expr[1, ...].parse_string("shape: SQUARE color: BLACK posn: upper left").pprint() - - prints:: - - [['shape', 'SQUARE'], ['color', 'BLACK'], ['posn', 'upper left']] - """ - - def __init__(self, expr: Union[ParserElement, str]): - super().__init__(expr) - self.mayReturnEmpty = True - - def parseImpl(self, instring, loc, doActions=True): - # by using self._expr.parse and deleting the contents of the returned ParseResults list - # we keep any named results that were defined in the FollowedBy expression - _, ret = self.expr._parse(instring, loc, doActions=doActions) - del ret[:] - - return loc, ret - - -class PrecededBy(ParseElementEnhance): - """Lookbehind matching of the given parse expression. - ``PrecededBy`` does not advance the parsing position within the - input string, it only verifies that the specified parse expression - matches prior to the current position. ``PrecededBy`` always - returns a null token list, but if a results name is defined on the - given expression, it is returned. - - Parameters: - - - expr - expression that must match prior to the current parse - location - - retreat - (default= ``None``) - (int) maximum number of characters - to lookbehind prior to the current parse location - - If the lookbehind expression is a string, :class:`Literal`, - :class:`Keyword`, or a :class:`Word` or :class:`CharsNotIn` - with a specified exact or maximum length, then the retreat - parameter is not required. Otherwise, retreat must be specified to - give a maximum number of characters to look back from - the current parse position for a lookbehind match. - - Example:: - - # VB-style variable names with type prefixes - int_var = PrecededBy("#") + pyparsing_common.identifier - str_var = PrecededBy("$") + pyparsing_common.identifier - - """ - - def __init__( - self, expr: Union[ParserElement, str], retreat: typing.Optional[int] = None - ): - super().__init__(expr) - self.expr = self.expr().leave_whitespace() - self.mayReturnEmpty = True - self.mayIndexError = False - self.exact = False - if isinstance(expr, str_type): - retreat = len(expr) - self.exact = True - elif isinstance(expr, (Literal, Keyword)): - retreat = expr.matchLen - self.exact = True - elif isinstance(expr, (Word, CharsNotIn)) and expr.maxLen != _MAX_INT: - retreat = expr.maxLen - self.exact = True - elif isinstance(expr, PositionToken): - retreat = 0 - self.exact = True - self.retreat = retreat - self.errmsg = "not preceded by " + str(expr) - self.skipWhitespace = False - self.parseAction.append(lambda s, l, t: t.__delitem__(slice(None, None))) - - def parseImpl(self, instring, loc=0, doActions=True): - if self.exact: - if loc < self.retreat: - raise ParseException(instring, loc, self.errmsg) - start = loc - self.retreat - _, ret = self.expr._parse(instring, start) - else: - # retreat specified a maximum lookbehind window, iterate - test_expr = self.expr + StringEnd() - instring_slice = instring[max(0, loc - self.retreat) : loc] - last_expr = ParseException(instring, loc, self.errmsg) - for offset in range(1, min(loc, self.retreat + 1) + 1): - try: - # print('trying', offset, instring_slice, repr(instring_slice[loc - offset:])) - _, ret = test_expr._parse( - instring_slice, len(instring_slice) - offset - ) - except ParseBaseException as pbe: - last_expr = pbe - else: - break - else: - raise last_expr - return loc, ret - - -class Located(ParseElementEnhance): - """ - Decorates a returned token with its starting and ending - locations in the input string. - - This helper adds the following results names: - - - ``locn_start`` - location where matched expression begins - - ``locn_end`` - location where matched expression ends - - ``value`` - the actual parsed results - - Be careful if the input text contains ```` characters, you - may want to call :class:`ParserElement.parse_with_tabs` - - Example:: - - wd = Word(alphas) - for match in Located(wd).search_string("ljsdf123lksdjjf123lkkjj1222"): - print(match) - - prints:: - - [0, ['ljsdf'], 5] - [8, ['lksdjjf'], 15] - [18, ['lkkjj'], 23] - - """ - - def parseImpl(self, instring, loc, doActions=True): - start = loc - loc, tokens = self.expr._parse(instring, start, doActions, callPreParse=False) - ret_tokens = ParseResults([start, tokens, loc]) - ret_tokens["locn_start"] = start - ret_tokens["value"] = tokens - ret_tokens["locn_end"] = loc - if self.resultsName: - # must return as a list, so that the name will be attached to the complete group - return loc, [ret_tokens] - else: - return loc, ret_tokens - - -class NotAny(ParseElementEnhance): - """ - Lookahead to disallow matching with the given parse expression. - ``NotAny`` does *not* advance the parsing position within the - input string, it only verifies that the specified parse expression - does *not* match at the current position. Also, ``NotAny`` does - *not* skip over leading whitespace. ``NotAny`` always returns - a null token list. May be constructed using the ``'~'`` operator. - - Example:: - - AND, OR, NOT = map(CaselessKeyword, "AND OR NOT".split()) - - # take care not to mistake keywords for identifiers - ident = ~(AND | OR | NOT) + Word(alphas) - boolean_term = Opt(NOT) + ident - - # very crude boolean expression - to support parenthesis groups and - # operation hierarchy, use infix_notation - boolean_expr = boolean_term + ((AND | OR) + boolean_term)[...] - - # integers that are followed by "." are actually floats - integer = Word(nums) + ~Char(".") - """ - - def __init__(self, expr: Union[ParserElement, str]): - super().__init__(expr) - # do NOT use self.leave_whitespace(), don't want to propagate to exprs - # self.leave_whitespace() - self.skipWhitespace = False - - self.mayReturnEmpty = True - self.errmsg = "Found unwanted token, " + str(self.expr) - - def parseImpl(self, instring, loc, doActions=True): - if self.expr.can_parse_next(instring, loc): - raise ParseException(instring, loc, self.errmsg, self) - return loc, [] - - def _generateDefaultName(self): - return "~{" + str(self.expr) + "}" - - -class _MultipleMatch(ParseElementEnhance): - def __init__( - self, - expr: ParserElement, - stop_on: typing.Optional[Union[ParserElement, str]] = None, - *, - stopOn: typing.Optional[Union[ParserElement, str]] = None, - ): - super().__init__(expr) - stopOn = stopOn or stop_on - self.saveAsList = True - ender = stopOn - if isinstance(ender, str_type): - ender = self._literalStringClass(ender) - self.stopOn(ender) - - def stopOn(self, ender) -> ParserElement: - if isinstance(ender, str_type): - ender = self._literalStringClass(ender) - self.not_ender = ~ender if ender is not None else None - return self - - def parseImpl(self, instring, loc, doActions=True): - self_expr_parse = self.expr._parse - self_skip_ignorables = self._skipIgnorables - check_ender = self.not_ender is not None - if check_ender: - try_not_ender = self.not_ender.tryParse - - # must be at least one (but first see if we are the stopOn sentinel; - # if so, fail) - if check_ender: - try_not_ender(instring, loc) - loc, tokens = self_expr_parse(instring, loc, doActions) - try: - hasIgnoreExprs = not not self.ignoreExprs - while 1: - if check_ender: - try_not_ender(instring, loc) - if hasIgnoreExprs: - preloc = self_skip_ignorables(instring, loc) - else: - preloc = loc - loc, tmptokens = self_expr_parse(instring, preloc, doActions) - if tmptokens or tmptokens.haskeys(): - tokens += tmptokens - except (ParseException, IndexError): - pass - - return loc, tokens - - def _setResultsName(self, name, listAllMatches=False): - if ( - __diag__.warn_ungrouped_named_tokens_in_collection - and Diagnostics.warn_ungrouped_named_tokens_in_collection - not in self.suppress_warnings_ - ): - for e in [self.expr] + self.expr.recurse(): - if ( - isinstance(e, ParserElement) - and e.resultsName - and Diagnostics.warn_ungrouped_named_tokens_in_collection - not in e.suppress_warnings_ - ): - warnings.warn( - "{}: setting results name {!r} on {} expression " - "collides with {!r} on contained expression".format( - "warn_ungrouped_named_tokens_in_collection", - name, - type(self).__name__, - e.resultsName, - ), - stacklevel=3, - ) - - return super()._setResultsName(name, listAllMatches) - - -class OneOrMore(_MultipleMatch): - """ - Repetition of one or more of the given expression. - - Parameters: - - expr - expression that must match one or more times - - stop_on - (default= ``None``) - expression for a terminating sentinel - (only required if the sentinel would ordinarily match the repetition - expression) - - Example:: - - data_word = Word(alphas) - label = data_word + FollowedBy(':') - attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).set_parse_action(' '.join)) - - text = "shape: SQUARE posn: upper left color: BLACK" - attr_expr[1, ...].parse_string(text).pprint() # Fail! read 'color' as data instead of next label -> [['shape', 'SQUARE color']] - - # use stop_on attribute for OneOrMore to avoid reading label string as part of the data - attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stop_on=label).set_parse_action(' '.join)) - OneOrMore(attr_expr).parse_string(text).pprint() # Better -> [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'BLACK']] - - # could also be written as - (attr_expr * (1,)).parse_string(text).pprint() - """ - - def _generateDefaultName(self): - return "{" + str(self.expr) + "}..." - - -class ZeroOrMore(_MultipleMatch): - """ - Optional repetition of zero or more of the given expression. - - Parameters: - - ``expr`` - expression that must match zero or more times - - ``stop_on`` - expression for a terminating sentinel - (only required if the sentinel would ordinarily match the repetition - expression) - (default= ``None``) - - Example: similar to :class:`OneOrMore` - """ - - def __init__( - self, - expr: ParserElement, - stop_on: typing.Optional[Union[ParserElement, str]] = None, - *, - stopOn: typing.Optional[Union[ParserElement, str]] = None, - ): - super().__init__(expr, stopOn=stopOn or stop_on) - self.mayReturnEmpty = True - - def parseImpl(self, instring, loc, doActions=True): - try: - return super().parseImpl(instring, loc, doActions) - except (ParseException, IndexError): - return loc, ParseResults([], name=self.resultsName) - - def _generateDefaultName(self): - return "[" + str(self.expr) + "]..." - - -class _NullToken: - def __bool__(self): - return False - - def __str__(self): - return "" - - -class Opt(ParseElementEnhance): - """ - Optional matching of the given expression. - - Parameters: - - ``expr`` - expression that must match zero or more times - - ``default`` (optional) - value to be returned if the optional expression is not found. - - Example:: - - # US postal code can be a 5-digit zip, plus optional 4-digit qualifier - zip = Combine(Word(nums, exact=5) + Opt('-' + Word(nums, exact=4))) - zip.run_tests(''' - # traditional ZIP code - 12345 - - # ZIP+4 form - 12101-0001 - - # invalid ZIP - 98765- - ''') - - prints:: - - # traditional ZIP code - 12345 - ['12345'] - - # ZIP+4 form - 12101-0001 - ['12101-0001'] - - # invalid ZIP - 98765- - ^ - FAIL: Expected end of text (at char 5), (line:1, col:6) - """ - - __optionalNotMatched = _NullToken() - - def __init__( - self, expr: Union[ParserElement, str], default: Any = __optionalNotMatched - ): - super().__init__(expr, savelist=False) - self.saveAsList = self.expr.saveAsList - self.defaultValue = default - self.mayReturnEmpty = True - - def parseImpl(self, instring, loc, doActions=True): - self_expr = self.expr - try: - loc, tokens = self_expr._parse(instring, loc, doActions, callPreParse=False) - except (ParseException, IndexError): - default_value = self.defaultValue - if default_value is not self.__optionalNotMatched: - if self_expr.resultsName: - tokens = ParseResults([default_value]) - tokens[self_expr.resultsName] = default_value - else: - tokens = [default_value] - else: - tokens = [] - return loc, tokens - - def _generateDefaultName(self): - inner = str(self.expr) - # strip off redundant inner {}'s - while len(inner) > 1 and inner[0 :: len(inner) - 1] == "{}": - inner = inner[1:-1] - return "[" + inner + "]" - - -Optional = Opt - - -class SkipTo(ParseElementEnhance): - """ - Token for skipping over all undefined text until the matched - expression is found. - - Parameters: - - ``expr`` - target expression marking the end of the data to be skipped - - ``include`` - if ``True``, the target expression is also parsed - (the skipped text and target expression are returned as a 2-element - list) (default= ``False``). - - ``ignore`` - (default= ``None``) used to define grammars (typically quoted strings and - comments) that might contain false matches to the target expression - - ``fail_on`` - (default= ``None``) define expressions that are not allowed to be - included in the skipped test; if found before the target expression is found, - the :class:`SkipTo` is not a match - - Example:: - - report = ''' - Outstanding Issues Report - 1 Jan 2000 - - # | Severity | Description | Days Open - -----+----------+-------------------------------------------+----------- - 101 | Critical | Intermittent system crash | 6 - 94 | Cosmetic | Spelling error on Login ('log|n') | 14 - 79 | Minor | System slow when running too many reports | 47 - ''' - integer = Word(nums) - SEP = Suppress('|') - # use SkipTo to simply match everything up until the next SEP - # - ignore quoted strings, so that a '|' character inside a quoted string does not match - # - parse action will call token.strip() for each matched token, i.e., the description body - string_data = SkipTo(SEP, ignore=quoted_string) - string_data.set_parse_action(token_map(str.strip)) - ticket_expr = (integer("issue_num") + SEP - + string_data("sev") + SEP - + string_data("desc") + SEP - + integer("days_open")) - - for tkt in ticket_expr.search_string(report): - print tkt.dump() - - prints:: - - ['101', 'Critical', 'Intermittent system crash', '6'] - - days_open: '6' - - desc: 'Intermittent system crash' - - issue_num: '101' - - sev: 'Critical' - ['94', 'Cosmetic', "Spelling error on Login ('log|n')", '14'] - - days_open: '14' - - desc: "Spelling error on Login ('log|n')" - - issue_num: '94' - - sev: 'Cosmetic' - ['79', 'Minor', 'System slow when running too many reports', '47'] - - days_open: '47' - - desc: 'System slow when running too many reports' - - issue_num: '79' - - sev: 'Minor' - """ - - def __init__( - self, - other: Union[ParserElement, str], - include: bool = False, - ignore: bool = None, - fail_on: typing.Optional[Union[ParserElement, str]] = None, - *, - failOn: Union[ParserElement, str] = None, - ): - super().__init__(other) - failOn = failOn or fail_on - self.ignoreExpr = ignore - self.mayReturnEmpty = True - self.mayIndexError = False - self.includeMatch = include - self.saveAsList = False - if isinstance(failOn, str_type): - self.failOn = self._literalStringClass(failOn) - else: - self.failOn = failOn - self.errmsg = "No match found for " + str(self.expr) - - def parseImpl(self, instring, loc, doActions=True): - startloc = loc - instrlen = len(instring) - self_expr_parse = self.expr._parse - self_failOn_canParseNext = ( - self.failOn.canParseNext if self.failOn is not None else None - ) - self_ignoreExpr_tryParse = ( - self.ignoreExpr.tryParse if self.ignoreExpr is not None else None - ) - - tmploc = loc - while tmploc <= instrlen: - if self_failOn_canParseNext is not None: - # break if failOn expression matches - if self_failOn_canParseNext(instring, tmploc): - break - - if self_ignoreExpr_tryParse is not None: - # advance past ignore expressions - while 1: - try: - tmploc = self_ignoreExpr_tryParse(instring, tmploc) - except ParseBaseException: - break - - try: - self_expr_parse(instring, tmploc, doActions=False, callPreParse=False) - except (ParseException, IndexError): - # no match, advance loc in string - tmploc += 1 - else: - # matched skipto expr, done - break - - else: - # ran off the end of the input string without matching skipto expr, fail - raise ParseException(instring, loc, self.errmsg, self) - - # build up return values - loc = tmploc - skiptext = instring[startloc:loc] - skipresult = ParseResults(skiptext) - - if self.includeMatch: - loc, mat = self_expr_parse(instring, loc, doActions, callPreParse=False) - skipresult += mat - - return loc, skipresult - - -class Forward(ParseElementEnhance): - """ - Forward declaration of an expression to be defined later - - used for recursive grammars, such as algebraic infix notation. - When the expression is known, it is assigned to the ``Forward`` - variable using the ``'<<'`` operator. - - Note: take care when assigning to ``Forward`` not to overlook - precedence of operators. - - Specifically, ``'|'`` has a lower precedence than ``'<<'``, so that:: - - fwd_expr << a | b | c - - will actually be evaluated as:: - - (fwd_expr << a) | b | c - - thereby leaving b and c out as parseable alternatives. It is recommended that you - explicitly group the values inserted into the ``Forward``:: - - fwd_expr << (a | b | c) - - Converting to use the ``'<<='`` operator instead will avoid this problem. - - See :class:`ParseResults.pprint` for an example of a recursive - parser created using ``Forward``. - """ - - def __init__(self, other: typing.Optional[Union[ParserElement, str]] = None): - self.caller_frame = traceback.extract_stack(limit=2)[0] - super().__init__(other, savelist=False) - self.lshift_line = None - - def __lshift__(self, other): - if hasattr(self, "caller_frame"): - del self.caller_frame - if isinstance(other, str_type): - other = self._literalStringClass(other) - self.expr = other - self.mayIndexError = self.expr.mayIndexError - self.mayReturnEmpty = self.expr.mayReturnEmpty - self.set_whitespace_chars( - self.expr.whiteChars, copy_defaults=self.expr.copyDefaultWhiteChars - ) - self.skipWhitespace = self.expr.skipWhitespace - self.saveAsList = self.expr.saveAsList - self.ignoreExprs.extend(self.expr.ignoreExprs) - self.lshift_line = traceback.extract_stack(limit=2)[-2] - return self - - def __ilshift__(self, other): - return self << other - - def __or__(self, other): - caller_line = traceback.extract_stack(limit=2)[-2] - if ( - __diag__.warn_on_match_first_with_lshift_operator - and caller_line == self.lshift_line - and Diagnostics.warn_on_match_first_with_lshift_operator - not in self.suppress_warnings_ - ): - warnings.warn( - "using '<<' operator with '|' is probably an error, use '<<='", - stacklevel=2, - ) - ret = super().__or__(other) - return ret - - def __del__(self): - # see if we are getting dropped because of '=' reassignment of var instead of '<<=' or '<<' - if ( - self.expr is None - and __diag__.warn_on_assignment_to_Forward - and Diagnostics.warn_on_assignment_to_Forward not in self.suppress_warnings_ - ): - warnings.warn_explicit( - "Forward defined here but no expression attached later using '<<=' or '<<'", - UserWarning, - filename=self.caller_frame.filename, - lineno=self.caller_frame.lineno, - ) - - def parseImpl(self, instring, loc, doActions=True): - if ( - self.expr is None - and __diag__.warn_on_parse_using_empty_Forward - and Diagnostics.warn_on_parse_using_empty_Forward - not in self.suppress_warnings_ - ): - # walk stack until parse_string, scan_string, search_string, or transform_string is found - parse_fns = [ - "parse_string", - "scan_string", - "search_string", - "transform_string", - ] - tb = traceback.extract_stack(limit=200) - for i, frm in enumerate(reversed(tb), start=1): - if frm.name in parse_fns: - stacklevel = i + 1 - break - else: - stacklevel = 2 - warnings.warn( - "Forward expression was never assigned a value, will not parse any input", - stacklevel=stacklevel, - ) - if not ParserElement._left_recursion_enabled: - return super().parseImpl(instring, loc, doActions) - # ## Bounded Recursion algorithm ## - # Recursion only needs to be processed at ``Forward`` elements, since they are - # the only ones that can actually refer to themselves. The general idea is - # to handle recursion stepwise: We start at no recursion, then recurse once, - # recurse twice, ..., until more recursion offers no benefit (we hit the bound). - # - # The "trick" here is that each ``Forward`` gets evaluated in two contexts - # - to *match* a specific recursion level, and - # - to *search* the bounded recursion level - # and the two run concurrently. The *search* must *match* each recursion level - # to find the best possible match. This is handled by a memo table, which - # provides the previous match to the next level match attempt. - # - # See also "Left Recursion in Parsing Expression Grammars", Medeiros et al. - # - # There is a complication since we not only *parse* but also *transform* via - # actions: We do not want to run the actions too often while expanding. Thus, - # we expand using `doActions=False` and only run `doActions=True` if the next - # recursion level is acceptable. - with ParserElement.recursion_lock: - memo = ParserElement.recursion_memos - try: - # we are parsing at a specific recursion expansion - use it as-is - prev_loc, prev_result = memo[loc, self, doActions] - if isinstance(prev_result, Exception): - raise prev_result - return prev_loc, prev_result.copy() - except KeyError: - act_key = (loc, self, True) - peek_key = (loc, self, False) - # we are searching for the best recursion expansion - keep on improving - # both `doActions` cases must be tracked separately here! - prev_loc, prev_peek = memo[peek_key] = ( - loc - 1, - ParseException( - instring, loc, "Forward recursion without base case", self - ), - ) - if doActions: - memo[act_key] = memo[peek_key] - while True: - try: - new_loc, new_peek = super().parseImpl(instring, loc, False) - except ParseException: - # we failed before getting any match – do not hide the error - if isinstance(prev_peek, Exception): - raise - new_loc, new_peek = prev_loc, prev_peek - # the match did not get better: we are done - if new_loc <= prev_loc: - if doActions: - # replace the match for doActions=False as well, - # in case the action did backtrack - prev_loc, prev_result = memo[peek_key] = memo[act_key] - del memo[peek_key], memo[act_key] - return prev_loc, prev_result.copy() - del memo[peek_key] - return prev_loc, prev_peek.copy() - # the match did get better: see if we can improve further - else: - if doActions: - try: - memo[act_key] = super().parseImpl(instring, loc, True) - except ParseException as e: - memo[peek_key] = memo[act_key] = (new_loc, e) - raise - prev_loc, prev_peek = memo[peek_key] = new_loc, new_peek - - def leave_whitespace(self, recursive: bool = True) -> ParserElement: - self.skipWhitespace = False - return self - - def ignore_whitespace(self, recursive: bool = True) -> ParserElement: - self.skipWhitespace = True - return self - - def streamline(self) -> ParserElement: - if not self.streamlined: - self.streamlined = True - if self.expr is not None: - self.expr.streamline() - return self - - def validate(self, validateTrace=None) -> None: - if validateTrace is None: - validateTrace = [] - - if self not in validateTrace: - tmp = validateTrace[:] + [self] - if self.expr is not None: - self.expr.validate(tmp) - self._checkRecursion([]) - - def _generateDefaultName(self): - # Avoid infinite recursion by setting a temporary _defaultName - self._defaultName = ": ..." - - # Use the string representation of main expression. - retString = "..." - try: - if self.expr is not None: - retString = str(self.expr)[:1000] - else: - retString = "None" - finally: - return self.__class__.__name__ + ": " + retString - - def copy(self) -> ParserElement: - if self.expr is not None: - return super().copy() - else: - ret = Forward() - ret <<= self - return ret - - def _setResultsName(self, name, list_all_matches=False): - if ( - __diag__.warn_name_set_on_empty_Forward - and Diagnostics.warn_name_set_on_empty_Forward - not in self.suppress_warnings_ - ): - if self.expr is None: - warnings.warn( - "{}: setting results name {!r} on {} expression " - "that has no contained expression".format( - "warn_name_set_on_empty_Forward", name, type(self).__name__ - ), - stacklevel=3, - ) - - return super()._setResultsName(name, list_all_matches) - - ignoreWhitespace = ignore_whitespace - leaveWhitespace = leave_whitespace - - -class TokenConverter(ParseElementEnhance): - """ - Abstract subclass of :class:`ParseExpression`, for converting parsed results. - """ - - def __init__(self, expr: Union[ParserElement, str], savelist=False): - super().__init__(expr) # , savelist) - self.saveAsList = False - - -class Combine(TokenConverter): - """Converter to concatenate all matching tokens to a single string. - By default, the matching patterns must also be contiguous in the - input string; this can be disabled by specifying - ``'adjacent=False'`` in the constructor. - - Example:: - - real = Word(nums) + '.' + Word(nums) - print(real.parse_string('3.1416')) # -> ['3', '.', '1416'] - # will also erroneously match the following - print(real.parse_string('3. 1416')) # -> ['3', '.', '1416'] - - real = Combine(Word(nums) + '.' + Word(nums)) - print(real.parse_string('3.1416')) # -> ['3.1416'] - # no match when there are internal spaces - print(real.parse_string('3. 1416')) # -> Exception: Expected W:(0123...) - """ - - def __init__( - self, - expr: ParserElement, - join_string: str = "", - adjacent: bool = True, - *, - joinString: typing.Optional[str] = None, - ): - super().__init__(expr) - joinString = joinString if joinString is not None else join_string - # suppress whitespace-stripping in contained parse expressions, but re-enable it on the Combine itself - if adjacent: - self.leave_whitespace() - self.adjacent = adjacent - self.skipWhitespace = True - self.joinString = joinString - self.callPreparse = True - - def ignore(self, other) -> ParserElement: - if self.adjacent: - ParserElement.ignore(self, other) - else: - super().ignore(other) - return self - - def postParse(self, instring, loc, tokenlist): - retToks = tokenlist.copy() - del retToks[:] - retToks += ParseResults( - ["".join(tokenlist._asStringList(self.joinString))], modal=self.modalResults - ) - - if self.resultsName and retToks.haskeys(): - return [retToks] - else: - return retToks - - -class Group(TokenConverter): - """Converter to return the matched tokens as a list - useful for - returning tokens of :class:`ZeroOrMore` and :class:`OneOrMore` expressions. - - The optional ``aslist`` argument when set to True will return the - parsed tokens as a Python list instead of a pyparsing ParseResults. - - Example:: - - ident = Word(alphas) - num = Word(nums) - term = ident | num - func = ident + Opt(delimited_list(term)) - print(func.parse_string("fn a, b, 100")) - # -> ['fn', 'a', 'b', '100'] - - func = ident + Group(Opt(delimited_list(term))) - print(func.parse_string("fn a, b, 100")) - # -> ['fn', ['a', 'b', '100']] - """ - - def __init__(self, expr: ParserElement, aslist: bool = False): - super().__init__(expr) - self.saveAsList = True - self._asPythonList = aslist - - def postParse(self, instring, loc, tokenlist): - if self._asPythonList: - return ParseResults.List( - tokenlist.asList() - if isinstance(tokenlist, ParseResults) - else list(tokenlist) - ) - else: - return [tokenlist] - - -class Dict(TokenConverter): - """Converter to return a repetitive expression as a list, but also - as a dictionary. Each element can also be referenced using the first - token in the expression as its key. Useful for tabular report - scraping when the first column can be used as a item key. - - The optional ``asdict`` argument when set to True will return the - parsed tokens as a Python dict instead of a pyparsing ParseResults. - - Example:: - - data_word = Word(alphas) - label = data_word + FollowedBy(':') - - text = "shape: SQUARE posn: upper left color: light blue texture: burlap" - attr_expr = (label + Suppress(':') + OneOrMore(data_word, stop_on=label).set_parse_action(' '.join)) - - # print attributes as plain groups - print(attr_expr[1, ...].parse_string(text).dump()) - - # instead of OneOrMore(expr), parse using Dict(Group(expr)[1, ...]) - Dict will auto-assign names - result = Dict(Group(attr_expr)[1, ...]).parse_string(text) - print(result.dump()) - - # access named fields as dict entries, or output as dict - print(result['shape']) - print(result.as_dict()) - - prints:: - - ['shape', 'SQUARE', 'posn', 'upper left', 'color', 'light blue', 'texture', 'burlap'] - [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] - - color: 'light blue' - - posn: 'upper left' - - shape: 'SQUARE' - - texture: 'burlap' - SQUARE - {'color': 'light blue', 'posn': 'upper left', 'texture': 'burlap', 'shape': 'SQUARE'} - - See more examples at :class:`ParseResults` of accessing fields by results name. - """ - - def __init__(self, expr: ParserElement, asdict: bool = False): - super().__init__(expr) - self.saveAsList = True - self._asPythonDict = asdict - - def postParse(self, instring, loc, tokenlist): - for i, tok in enumerate(tokenlist): - if len(tok) == 0: - continue - - ikey = tok[0] - if isinstance(ikey, int): - ikey = str(ikey).strip() - - if len(tok) == 1: - tokenlist[ikey] = _ParseResultsWithOffset("", i) - - elif len(tok) == 2 and not isinstance(tok[1], ParseResults): - tokenlist[ikey] = _ParseResultsWithOffset(tok[1], i) - - else: - try: - dictvalue = tok.copy() # ParseResults(i) - except Exception: - exc = TypeError( - "could not extract dict values from parsed results" - " - Dict expression must contain Grouped expressions" - ) - raise exc from None - - del dictvalue[0] - - if len(dictvalue) != 1 or ( - isinstance(dictvalue, ParseResults) and dictvalue.haskeys() - ): - tokenlist[ikey] = _ParseResultsWithOffset(dictvalue, i) - else: - tokenlist[ikey] = _ParseResultsWithOffset(dictvalue[0], i) - - if self._asPythonDict: - return [tokenlist.as_dict()] if self.resultsName else tokenlist.as_dict() - else: - return [tokenlist] if self.resultsName else tokenlist - - -class Suppress(TokenConverter): - """Converter for ignoring the results of a parsed expression. - - Example:: - - source = "a, b, c,d" - wd = Word(alphas) - wd_list1 = wd + (',' + wd)[...] - print(wd_list1.parse_string(source)) - - # often, delimiters that are useful during parsing are just in the - # way afterward - use Suppress to keep them out of the parsed output - wd_list2 = wd + (Suppress(',') + wd)[...] - print(wd_list2.parse_string(source)) - - # Skipped text (using '...') can be suppressed as well - source = "lead in START relevant text END trailing text" - start_marker = Keyword("START") - end_marker = Keyword("END") - find_body = Suppress(...) + start_marker + ... + end_marker - print(find_body.parse_string(source) - - prints:: - - ['a', ',', 'b', ',', 'c', ',', 'd'] - ['a', 'b', 'c', 'd'] - ['START', 'relevant text ', 'END'] - - (See also :class:`delimited_list`.) - """ - - def __init__(self, expr: Union[ParserElement, str], savelist: bool = False): - if expr is ...: - expr = _PendingSkip(NoMatch()) - super().__init__(expr) - - def __add__(self, other) -> "ParserElement": - if isinstance(self.expr, _PendingSkip): - return Suppress(SkipTo(other)) + other - else: - return super().__add__(other) - - def __sub__(self, other) -> "ParserElement": - if isinstance(self.expr, _PendingSkip): - return Suppress(SkipTo(other)) - other - else: - return super().__sub__(other) - - def postParse(self, instring, loc, tokenlist): - return [] - - def suppress(self) -> ParserElement: - return self - - -def trace_parse_action(f: ParseAction) -> ParseAction: - """Decorator for debugging parse actions. - - When the parse action is called, this decorator will print - ``">> entering method-name(line:, , )"``. - When the parse action completes, the decorator will print - ``"<<"`` followed by the returned value, or any exception that the parse action raised. - - Example:: - - wd = Word(alphas) - - @trace_parse_action - def remove_duplicate_chars(tokens): - return ''.join(sorted(set(''.join(tokens)))) - - wds = wd[1, ...].set_parse_action(remove_duplicate_chars) - print(wds.parse_string("slkdjs sld sldd sdlf sdljf")) - - prints:: - - >>entering remove_duplicate_chars(line: 'slkdjs sld sldd sdlf sdljf', 0, (['slkdjs', 'sld', 'sldd', 'sdlf', 'sdljf'], {})) - < 3: - thisFunc = paArgs[0].__class__.__name__ + "." + thisFunc - sys.stderr.write( - ">>entering {}(line: {!r}, {}, {!r})\n".format(thisFunc, line(l, s), l, t) - ) - try: - ret = f(*paArgs) - except Exception as exc: - sys.stderr.write("< str: - r"""Helper to easily define string ranges for use in :class:`Word` - construction. Borrows syntax from regexp ``'[]'`` string range - definitions:: - - srange("[0-9]") -> "0123456789" - srange("[a-z]") -> "abcdefghijklmnopqrstuvwxyz" - srange("[a-z$_]") -> "abcdefghijklmnopqrstuvwxyz$_" - - The input string must be enclosed in []'s, and the returned string - is the expanded character set joined into a single string. The - values enclosed in the []'s may be: - - - a single character - - an escaped character with a leading backslash (such as ``\-`` - or ``\]``) - - an escaped hex character with a leading ``'\x'`` - (``\x21``, which is a ``'!'`` character) (``\0x##`` - is also supported for backwards compatibility) - - an escaped octal character with a leading ``'\0'`` - (``\041``, which is a ``'!'`` character) - - a range of any of the above, separated by a dash (``'a-z'``, - etc.) - - any combination of the above (``'aeiouy'``, - ``'a-zA-Z0-9_$'``, etc.) - """ - _expanded = ( - lambda p: p - if not isinstance(p, ParseResults) - else "".join(chr(c) for c in range(ord(p[0]), ord(p[1]) + 1)) - ) - try: - return "".join(_expanded(part) for part in _reBracketExpr.parse_string(s).body) - except Exception: - return "" - - -def token_map(func, *args) -> ParseAction: - """Helper to define a parse action by mapping a function to all - elements of a :class:`ParseResults` list. If any additional args are passed, - they are forwarded to the given function as additional arguments - after the token, as in - ``hex_integer = Word(hexnums).set_parse_action(token_map(int, 16))``, - which will convert the parsed data to an integer using base 16. - - Example (compare the last to example in :class:`ParserElement.transform_string`:: - - hex_ints = Word(hexnums)[1, ...].set_parse_action(token_map(int, 16)) - hex_ints.run_tests(''' - 00 11 22 aa FF 0a 0d 1a - ''') - - upperword = Word(alphas).set_parse_action(token_map(str.upper)) - upperword[1, ...].run_tests(''' - my kingdom for a horse - ''') - - wd = Word(alphas).set_parse_action(token_map(str.title)) - wd[1, ...].set_parse_action(' '.join).run_tests(''' - now is the winter of our discontent made glorious summer by this sun of york - ''') - - prints:: - - 00 11 22 aa FF 0a 0d 1a - [0, 17, 34, 170, 255, 10, 13, 26] - - my kingdom for a horse - ['MY', 'KINGDOM', 'FOR', 'A', 'HORSE'] - - now is the winter of our discontent made glorious summer by this sun of york - ['Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York'] - """ - - def pa(s, l, t): - return [func(tokn, *args) for tokn in t] - - func_name = getattr(func, "__name__", getattr(func, "__class__").__name__) - pa.__name__ = func_name - - return pa - - -def autoname_elements() -> None: - """ - Utility to simplify mass-naming of parser elements, for - generating railroad diagram with named subdiagrams. - """ - for name, var in sys._getframe().f_back.f_locals.items(): - if isinstance(var, ParserElement) and not var.customName: - var.set_name(name) - - -dbl_quoted_string = Combine( - Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*') + '"' -).set_name("string enclosed in double quotes") - -sgl_quoted_string = Combine( - Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*") + "'" -).set_name("string enclosed in single quotes") - -quoted_string = Combine( - Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*') + '"' - | Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*") + "'" -).set_name("quotedString using single or double quotes") - -unicode_string = Combine("u" + quoted_string.copy()).set_name("unicode string literal") - - -alphas8bit = srange(r"[\0xc0-\0xd6\0xd8-\0xf6\0xf8-\0xff]") -punc8bit = srange(r"[\0xa1-\0xbf\0xd7\0xf7]") - -# build list of built-in expressions, for future reference if a global default value -# gets updated -_builtin_exprs: List[ParserElement] = [ - v for v in vars().values() if isinstance(v, ParserElement) -] - -# backward compatibility names -tokenMap = token_map -conditionAsParseAction = condition_as_parse_action -nullDebugAction = null_debug_action -sglQuotedString = sgl_quoted_string -dblQuotedString = dbl_quoted_string -quotedString = quoted_string -unicodeString = unicode_string -lineStart = line_start -lineEnd = line_end -stringStart = string_start -stringEnd = string_end -traceParseAction = trace_parse_action diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/diagram/__init__.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/diagram/__init__.py deleted file mode 100755 index 8986447..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/diagram/__init__.py +++ /dev/null @@ -1,642 +0,0 @@ -import railroad -import pyparsing -import typing -from typing import ( - List, - NamedTuple, - Generic, - TypeVar, - Dict, - Callable, - Set, - Iterable, -) -from jinja2 import Template -from io import StringIO -import inspect - - -jinja2_template_source = """\ - - - - {% if not head %} - - {% else %} - {{ head | safe }} - {% endif %} - - -{{ body | safe }} -{% for diagram in diagrams %} -
-

{{ diagram.title }}

-
{{ diagram.text }}
-
- {{ diagram.svg }} -
-
-{% endfor %} - - -""" - -template = Template(jinja2_template_source) - -# Note: ideally this would be a dataclass, but we're supporting Python 3.5+ so we can't do this yet -NamedDiagram = NamedTuple( - "NamedDiagram", - [("name", str), ("diagram", typing.Optional[railroad.DiagramItem]), ("index", int)], -) -""" -A simple structure for associating a name with a railroad diagram -""" - -T = TypeVar("T") - - -class EachItem(railroad.Group): - """ - Custom railroad item to compose a: - - Group containing a - - OneOrMore containing a - - Choice of the elements in the Each - with the group label indicating that all must be matched - """ - - all_label = "[ALL]" - - def __init__(self, *items): - choice_item = railroad.Choice(len(items) - 1, *items) - one_or_more_item = railroad.OneOrMore(item=choice_item) - super().__init__(one_or_more_item, label=self.all_label) - - -class AnnotatedItem(railroad.Group): - """ - Simple subclass of Group that creates an annotation label - """ - - def __init__(self, label: str, item): - super().__init__(item=item, label="[{}]".format(label) if label else label) - - -class EditablePartial(Generic[T]): - """ - Acts like a functools.partial, but can be edited. In other words, it represents a type that hasn't yet been - constructed. - """ - - # We need this here because the railroad constructors actually transform the data, so can't be called until the - # entire tree is assembled - - def __init__(self, func: Callable[..., T], args: list, kwargs: dict): - self.func = func - self.args = args - self.kwargs = kwargs - - @classmethod - def from_call(cls, func: Callable[..., T], *args, **kwargs) -> "EditablePartial[T]": - """ - If you call this function in the same way that you would call the constructor, it will store the arguments - as you expect. For example EditablePartial.from_call(Fraction, 1, 3)() == Fraction(1, 3) - """ - return EditablePartial(func=func, args=list(args), kwargs=kwargs) - - @property - def name(self): - return self.kwargs["name"] - - def __call__(self) -> T: - """ - Evaluate the partial and return the result - """ - args = self.args.copy() - kwargs = self.kwargs.copy() - - # This is a helpful hack to allow you to specify varargs parameters (e.g. *args) as keyword args (e.g. - # args=['list', 'of', 'things']) - arg_spec = inspect.getfullargspec(self.func) - if arg_spec.varargs in self.kwargs: - args += kwargs.pop(arg_spec.varargs) - - return self.func(*args, **kwargs) - - -def railroad_to_html(diagrams: List[NamedDiagram], **kwargs) -> str: - """ - Given a list of NamedDiagram, produce a single HTML string that visualises those diagrams - :params kwargs: kwargs to be passed in to the template - """ - data = [] - for diagram in diagrams: - if diagram.diagram is None: - continue - io = StringIO() - diagram.diagram.writeSvg(io.write) - title = diagram.name - if diagram.index == 0: - title += " (root)" - data.append({"title": title, "text": "", "svg": io.getvalue()}) - - return template.render(diagrams=data, **kwargs) - - -def resolve_partial(partial: "EditablePartial[T]") -> T: - """ - Recursively resolves a collection of Partials into whatever type they are - """ - if isinstance(partial, EditablePartial): - partial.args = resolve_partial(partial.args) - partial.kwargs = resolve_partial(partial.kwargs) - return partial() - elif isinstance(partial, list): - return [resolve_partial(x) for x in partial] - elif isinstance(partial, dict): - return {key: resolve_partial(x) for key, x in partial.items()} - else: - return partial - - -def to_railroad( - element: pyparsing.ParserElement, - diagram_kwargs: typing.Optional[dict] = None, - vertical: int = 3, - show_results_names: bool = False, - show_groups: bool = False, -) -> List[NamedDiagram]: - """ - Convert a pyparsing element tree into a list of diagrams. This is the recommended entrypoint to diagram - creation if you want to access the Railroad tree before it is converted to HTML - :param element: base element of the parser being diagrammed - :param diagram_kwargs: kwargs to pass to the Diagram() constructor - :param vertical: (optional) - int - limit at which number of alternatives should be - shown vertically instead of horizontally - :param show_results_names - bool to indicate whether results name annotations should be - included in the diagram - :param show_groups - bool to indicate whether groups should be highlighted with an unlabeled - surrounding box - """ - # Convert the whole tree underneath the root - lookup = ConverterState(diagram_kwargs=diagram_kwargs or {}) - _to_diagram_element( - element, - lookup=lookup, - parent=None, - vertical=vertical, - show_results_names=show_results_names, - show_groups=show_groups, - ) - - root_id = id(element) - # Convert the root if it hasn't been already - if root_id in lookup: - if not element.customName: - lookup[root_id].name = "" - lookup[root_id].mark_for_extraction(root_id, lookup, force=True) - - # Now that we're finished, we can convert from intermediate structures into Railroad elements - diags = list(lookup.diagrams.values()) - if len(diags) > 1: - # collapse out duplicate diags with the same name - seen = set() - deduped_diags = [] - for d in diags: - # don't extract SkipTo elements, they are uninformative as subdiagrams - if d.name == "...": - continue - if d.name is not None and d.name not in seen: - seen.add(d.name) - deduped_diags.append(d) - resolved = [resolve_partial(partial) for partial in deduped_diags] - else: - # special case - if just one diagram, always display it, even if - # it has no name - resolved = [resolve_partial(partial) for partial in diags] - return sorted(resolved, key=lambda diag: diag.index) - - -def _should_vertical( - specification: int, exprs: Iterable[pyparsing.ParserElement] -) -> bool: - """ - Returns true if we should return a vertical list of elements - """ - if specification is None: - return False - else: - return len(_visible_exprs(exprs)) >= specification - - -class ElementState: - """ - State recorded for an individual pyparsing Element - """ - - # Note: this should be a dataclass, but we have to support Python 3.5 - def __init__( - self, - element: pyparsing.ParserElement, - converted: EditablePartial, - parent: EditablePartial, - number: int, - name: str = None, - parent_index: typing.Optional[int] = None, - ): - #: The pyparsing element that this represents - self.element: pyparsing.ParserElement = element - #: The name of the element - self.name: typing.Optional[str] = name - #: The output Railroad element in an unconverted state - self.converted: EditablePartial = converted - #: The parent Railroad element, which we store so that we can extract this if it's duplicated - self.parent: EditablePartial = parent - #: The order in which we found this element, used for sorting diagrams if this is extracted into a diagram - self.number: int = number - #: The index of this inside its parent - self.parent_index: typing.Optional[int] = parent_index - #: If true, we should extract this out into a subdiagram - self.extract: bool = False - #: If true, all of this element's children have been filled out - self.complete: bool = False - - def mark_for_extraction( - self, el_id: int, state: "ConverterState", name: str = None, force: bool = False - ): - """ - Called when this instance has been seen twice, and thus should eventually be extracted into a sub-diagram - :param el_id: id of the element - :param state: element/diagram state tracker - :param name: name to use for this element's text - :param force: If true, force extraction now, regardless of the state of this. Only useful for extracting the - root element when we know we're finished - """ - self.extract = True - - # Set the name - if not self.name: - if name: - # Allow forcing a custom name - self.name = name - elif self.element.customName: - self.name = self.element.customName - else: - self.name = "" - - # Just because this is marked for extraction doesn't mean we can do it yet. We may have to wait for children - # to be added - # Also, if this is just a string literal etc, don't bother extracting it - if force or (self.complete and _worth_extracting(self.element)): - state.extract_into_diagram(el_id) - - -class ConverterState: - """ - Stores some state that persists between recursions into the element tree - """ - - def __init__(self, diagram_kwargs: typing.Optional[dict] = None): - #: A dictionary mapping ParserElements to state relating to them - self._element_diagram_states: Dict[int, ElementState] = {} - #: A dictionary mapping ParserElement IDs to subdiagrams generated from them - self.diagrams: Dict[int, EditablePartial[NamedDiagram]] = {} - #: The index of the next unnamed element - self.unnamed_index: int = 1 - #: The index of the next element. This is used for sorting - self.index: int = 0 - #: Shared kwargs that are used to customize the construction of diagrams - self.diagram_kwargs: dict = diagram_kwargs or {} - self.extracted_diagram_names: Set[str] = set() - - def __setitem__(self, key: int, value: ElementState): - self._element_diagram_states[key] = value - - def __getitem__(self, key: int) -> ElementState: - return self._element_diagram_states[key] - - def __delitem__(self, key: int): - del self._element_diagram_states[key] - - def __contains__(self, key: int): - return key in self._element_diagram_states - - def generate_unnamed(self) -> int: - """ - Generate a number used in the name of an otherwise unnamed diagram - """ - self.unnamed_index += 1 - return self.unnamed_index - - def generate_index(self) -> int: - """ - Generate a number used to index a diagram - """ - self.index += 1 - return self.index - - def extract_into_diagram(self, el_id: int): - """ - Used when we encounter the same token twice in the same tree. When this - happens, we replace all instances of that token with a terminal, and - create a new subdiagram for the token - """ - position = self[el_id] - - # Replace the original definition of this element with a regular block - if position.parent: - ret = EditablePartial.from_call(railroad.NonTerminal, text=position.name) - if "item" in position.parent.kwargs: - position.parent.kwargs["item"] = ret - elif "items" in position.parent.kwargs: - position.parent.kwargs["items"][position.parent_index] = ret - - # If the element we're extracting is a group, skip to its content but keep the title - if position.converted.func == railroad.Group: - content = position.converted.kwargs["item"] - else: - content = position.converted - - self.diagrams[el_id] = EditablePartial.from_call( - NamedDiagram, - name=position.name, - diagram=EditablePartial.from_call( - railroad.Diagram, content, **self.diagram_kwargs - ), - index=position.number, - ) - - del self[el_id] - - -def _worth_extracting(element: pyparsing.ParserElement) -> bool: - """ - Returns true if this element is worth having its own sub-diagram. Simply, if any of its children - themselves have children, then its complex enough to extract - """ - children = element.recurse() - return any(child.recurse() for child in children) - - -def _apply_diagram_item_enhancements(fn): - """ - decorator to ensure enhancements to a diagram item (such as results name annotations) - get applied on return from _to_diagram_element (we do this since there are several - returns in _to_diagram_element) - """ - - def _inner( - element: pyparsing.ParserElement, - parent: typing.Optional[EditablePartial], - lookup: ConverterState = None, - vertical: int = None, - index: int = 0, - name_hint: str = None, - show_results_names: bool = False, - show_groups: bool = False, - ) -> typing.Optional[EditablePartial]: - - ret = fn( - element, - parent, - lookup, - vertical, - index, - name_hint, - show_results_names, - show_groups, - ) - - # apply annotation for results name, if present - if show_results_names and ret is not None: - element_results_name = element.resultsName - if element_results_name: - # add "*" to indicate if this is a "list all results" name - element_results_name += "" if element.modalResults else "*" - ret = EditablePartial.from_call( - railroad.Group, item=ret, label=element_results_name - ) - - return ret - - return _inner - - -def _visible_exprs(exprs: Iterable[pyparsing.ParserElement]): - non_diagramming_exprs = ( - pyparsing.ParseElementEnhance, - pyparsing.PositionToken, - pyparsing.And._ErrorStop, - ) - return [ - e - for e in exprs - if not (e.customName or e.resultsName or isinstance(e, non_diagramming_exprs)) - ] - - -@_apply_diagram_item_enhancements -def _to_diagram_element( - element: pyparsing.ParserElement, - parent: typing.Optional[EditablePartial], - lookup: ConverterState = None, - vertical: int = None, - index: int = 0, - name_hint: str = None, - show_results_names: bool = False, - show_groups: bool = False, -) -> typing.Optional[EditablePartial]: - """ - Recursively converts a PyParsing Element to a railroad Element - :param lookup: The shared converter state that keeps track of useful things - :param index: The index of this element within the parent - :param parent: The parent of this element in the output tree - :param vertical: Controls at what point we make a list of elements vertical. If this is an integer (the default), - it sets the threshold of the number of items before we go vertical. If True, always go vertical, if False, never - do so - :param name_hint: If provided, this will override the generated name - :param show_results_names: bool flag indicating whether to add annotations for results names - :returns: The converted version of the input element, but as a Partial that hasn't yet been constructed - :param show_groups: bool flag indicating whether to show groups using bounding box - """ - exprs = element.recurse() - name = name_hint or element.customName or element.__class__.__name__ - - # Python's id() is used to provide a unique identifier for elements - el_id = id(element) - - element_results_name = element.resultsName - - # Here we basically bypass processing certain wrapper elements if they contribute nothing to the diagram - if not element.customName: - if isinstance( - element, - ( - # pyparsing.TokenConverter, - # pyparsing.Forward, - pyparsing.Located, - ), - ): - # However, if this element has a useful custom name, and its child does not, we can pass it on to the child - if exprs: - if not exprs[0].customName: - propagated_name = name - else: - propagated_name = None - - return _to_diagram_element( - element.expr, - parent=parent, - lookup=lookup, - vertical=vertical, - index=index, - name_hint=propagated_name, - show_results_names=show_results_names, - show_groups=show_groups, - ) - - # If the element isn't worth extracting, we always treat it as the first time we say it - if _worth_extracting(element): - if el_id in lookup: - # If we've seen this element exactly once before, we are only just now finding out that it's a duplicate, - # so we have to extract it into a new diagram. - looked_up = lookup[el_id] - looked_up.mark_for_extraction(el_id, lookup, name=name_hint) - ret = EditablePartial.from_call(railroad.NonTerminal, text=looked_up.name) - return ret - - elif el_id in lookup.diagrams: - # If we have seen the element at least twice before, and have already extracted it into a subdiagram, we - # just put in a marker element that refers to the sub-diagram - ret = EditablePartial.from_call( - railroad.NonTerminal, text=lookup.diagrams[el_id].kwargs["name"] - ) - return ret - - # Recursively convert child elements - # Here we find the most relevant Railroad element for matching pyparsing Element - # We use ``items=[]`` here to hold the place for where the child elements will go once created - if isinstance(element, pyparsing.And): - # detect And's created with ``expr*N`` notation - for these use a OneOrMore with a repeat - # (all will have the same name, and resultsName) - if not exprs: - return None - if len(set((e.name, e.resultsName) for e in exprs)) == 1: - ret = EditablePartial.from_call( - railroad.OneOrMore, item="", repeat=str(len(exprs)) - ) - elif _should_vertical(vertical, exprs): - ret = EditablePartial.from_call(railroad.Stack, items=[]) - else: - ret = EditablePartial.from_call(railroad.Sequence, items=[]) - elif isinstance(element, (pyparsing.Or, pyparsing.MatchFirst)): - if not exprs: - return None - if _should_vertical(vertical, exprs): - ret = EditablePartial.from_call(railroad.Choice, 0, items=[]) - else: - ret = EditablePartial.from_call(railroad.HorizontalChoice, items=[]) - elif isinstance(element, pyparsing.Each): - if not exprs: - return None - ret = EditablePartial.from_call(EachItem, items=[]) - elif isinstance(element, pyparsing.NotAny): - ret = EditablePartial.from_call(AnnotatedItem, label="NOT", item="") - elif isinstance(element, pyparsing.FollowedBy): - ret = EditablePartial.from_call(AnnotatedItem, label="LOOKAHEAD", item="") - elif isinstance(element, pyparsing.PrecededBy): - ret = EditablePartial.from_call(AnnotatedItem, label="LOOKBEHIND", item="") - elif isinstance(element, pyparsing.Group): - if show_groups: - ret = EditablePartial.from_call(AnnotatedItem, label="", item="") - else: - ret = EditablePartial.from_call(railroad.Group, label="", item="") - elif isinstance(element, pyparsing.TokenConverter): - ret = EditablePartial.from_call( - AnnotatedItem, label=type(element).__name__.lower(), item="" - ) - elif isinstance(element, pyparsing.Opt): - ret = EditablePartial.from_call(railroad.Optional, item="") - elif isinstance(element, pyparsing.OneOrMore): - ret = EditablePartial.from_call(railroad.OneOrMore, item="") - elif isinstance(element, pyparsing.ZeroOrMore): - ret = EditablePartial.from_call(railroad.ZeroOrMore, item="") - elif isinstance(element, pyparsing.Group): - ret = EditablePartial.from_call( - railroad.Group, item=None, label=element_results_name - ) - elif isinstance(element, pyparsing.Empty) and not element.customName: - # Skip unnamed "Empty" elements - ret = None - elif len(exprs) > 1: - ret = EditablePartial.from_call(railroad.Sequence, items=[]) - elif len(exprs) > 0 and not element_results_name: - ret = EditablePartial.from_call(railroad.Group, item="", label=name) - else: - terminal = EditablePartial.from_call(railroad.Terminal, element.defaultName) - ret = terminal - - if ret is None: - return - - # Indicate this element's position in the tree so we can extract it if necessary - lookup[el_id] = ElementState( - element=element, - converted=ret, - parent=parent, - parent_index=index, - number=lookup.generate_index(), - ) - if element.customName: - lookup[el_id].mark_for_extraction(el_id, lookup, element.customName) - - i = 0 - for expr in exprs: - # Add a placeholder index in case we have to extract the child before we even add it to the parent - if "items" in ret.kwargs: - ret.kwargs["items"].insert(i, None) - - item = _to_diagram_element( - expr, - parent=ret, - lookup=lookup, - vertical=vertical, - index=i, - show_results_names=show_results_names, - show_groups=show_groups, - ) - - # Some elements don't need to be shown in the diagram - if item is not None: - if "item" in ret.kwargs: - ret.kwargs["item"] = item - elif "items" in ret.kwargs: - # If we've already extracted the child, don't touch this index, since it's occupied by a nonterminal - ret.kwargs["items"][i] = item - i += 1 - elif "items" in ret.kwargs: - # If we're supposed to skip this element, remove it from the parent - del ret.kwargs["items"][i] - - # If all this items children are none, skip this item - if ret and ( - ("items" in ret.kwargs and len(ret.kwargs["items"]) == 0) - or ("item" in ret.kwargs and ret.kwargs["item"] is None) - ): - ret = EditablePartial.from_call(railroad.Terminal, name) - - # Mark this element as "complete", ie it has all of its children - if el_id in lookup: - lookup[el_id].complete = True - - if el_id in lookup and lookup[el_id].extract and lookup[el_id].complete: - lookup.extract_into_diagram(el_id) - if ret is not None: - ret = EditablePartial.from_call( - railroad.NonTerminal, text=lookup.diagrams[el_id].kwargs["name"] - ) - - return ret diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/diagram/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/diagram/__pycache__/__init__.cpython-311.pyc deleted file mode 100755 index 17c7b7c8dfb261abb510f6e1beda14892be49db6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28006 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 0: - callers = inspect.getinnerframes(exc.__traceback__, context=depth) - seen = set() - for i, ff in enumerate(callers[-depth:]): - frm = ff[0] - - f_self = frm.f_locals.get("self", None) - if isinstance(f_self, ParserElement): - if frm.f_code.co_name not in ("parseImpl", "_parseNoCache"): - continue - if id(f_self) in seen: - continue - seen.add(id(f_self)) - - self_type = type(f_self) - ret.append( - "{}.{} - {}".format( - self_type.__module__, self_type.__name__, f_self - ) - ) - - elif f_self is not None: - self_type = type(f_self) - ret.append("{}.{}".format(self_type.__module__, self_type.__name__)) - - else: - code = frm.f_code - if code.co_name in ("wrapper", ""): - continue - - ret.append("{}".format(code.co_name)) - - depth -= 1 - if not depth: - break - - return "\n".join(ret) - - @classmethod - def _from_exception(cls, pe): - """ - internal factory method to simplify creating one type of ParseException - from another - avoids having __init__ signature conflicts among subclasses - """ - return cls(pe.pstr, pe.loc, pe.msg, pe.parserElement) - - @property - def line(self) -> str: - """ - Return the line of text where the exception occurred. - """ - return line(self.loc, self.pstr) - - @property - def lineno(self) -> int: - """ - Return the 1-based line number of text where the exception occurred. - """ - return lineno(self.loc, self.pstr) - - @property - def col(self) -> int: - """ - Return the 1-based column on the line of text where the exception occurred. - """ - return col(self.loc, self.pstr) - - @property - def column(self) -> int: - """ - Return the 1-based column on the line of text where the exception occurred. - """ - return col(self.loc, self.pstr) - - def __str__(self) -> str: - if self.pstr: - if self.loc >= len(self.pstr): - foundstr = ", found end of text" - else: - # pull out next word at error location - found_match = _exception_word_extractor.match(self.pstr, self.loc) - if found_match is not None: - found = found_match.group(0) - else: - found = self.pstr[self.loc : self.loc + 1] - foundstr = (", found %r" % found).replace(r"\\", "\\") - else: - foundstr = "" - return "{}{} (at char {}), (line:{}, col:{})".format( - self.msg, foundstr, self.loc, self.lineno, self.column - ) - - def __repr__(self): - return str(self) - - def mark_input_line(self, marker_string: str = None, *, markerString=">!<") -> str: - """ - Extracts the exception line from the input string, and marks - the location of the exception with a special symbol. - """ - markerString = marker_string if marker_string is not None else markerString - line_str = self.line - line_column = self.column - 1 - if markerString: - line_str = "".join( - (line_str[:line_column], markerString, line_str[line_column:]) - ) - return line_str.strip() - - def explain(self, depth=16) -> str: - """ - Method to translate the Python internal traceback into a list - of the pyparsing expressions that caused the exception to be raised. - - Parameters: - - - depth (default=16) - number of levels back in the stack trace to list expression - and function names; if None, the full stack trace names will be listed; if 0, only - the failing input line, marker, and exception string will be shown - - Returns a multi-line string listing the ParserElements and/or function names in the - exception's stack trace. - - Example:: - - expr = pp.Word(pp.nums) * 3 - try: - expr.parse_string("123 456 A789") - except pp.ParseException as pe: - print(pe.explain(depth=0)) - - prints:: - - 123 456 A789 - ^ - ParseException: Expected W:(0-9), found 'A' (at char 8), (line:1, col:9) - - Note: the diagnostic output will include string representations of the expressions - that failed to parse. These representations will be more helpful if you use `set_name` to - give identifiable names to your expressions. Otherwise they will use the default string - forms, which may be cryptic to read. - - Note: pyparsing's default truncation of exception tracebacks may also truncate the - stack of expressions that are displayed in the ``explain`` output. To get the full listing - of parser expressions, you may have to set ``ParserElement.verbose_stacktrace = True`` - """ - return self.explain_exception(self, depth) - - markInputline = mark_input_line - - -class ParseException(ParseBaseException): - """ - Exception thrown when a parse expression doesn't match the input string - - Example:: - - try: - Word(nums).set_name("integer").parse_string("ABC") - except ParseException as pe: - print(pe) - print("column: {}".format(pe.column)) - - prints:: - - Expected integer (at char 0), (line:1, col:1) - column: 1 - - """ - - -class ParseFatalException(ParseBaseException): - """ - User-throwable exception thrown when inconsistent parse content - is found; stops all parsing immediately - """ - - -class ParseSyntaxException(ParseFatalException): - """ - Just like :class:`ParseFatalException`, but thrown internally - when an :class:`ErrorStop` ('-' operator) indicates - that parsing is to stop immediately because an unbacktrackable - syntax error has been found. - """ - - -class RecursiveGrammarException(Exception): - """ - Exception thrown by :class:`ParserElement.validate` if the - grammar could be left-recursive; parser may need to enable - left recursion using :class:`ParserElement.enable_left_recursion` - """ - - def __init__(self, parseElementList): - self.parseElementTrace = parseElementList - - def __str__(self) -> str: - return "RecursiveGrammarException: {}".format(self.parseElementTrace) diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/helpers.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/helpers.py deleted file mode 100755 index 9588b3b..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/helpers.py +++ /dev/null @@ -1,1088 +0,0 @@ -# helpers.py -import html.entities -import re -import typing - -from . import __diag__ -from .core import * -from .util import _bslash, _flatten, _escape_regex_range_chars - - -# -# global helpers -# -def delimited_list( - expr: Union[str, ParserElement], - delim: Union[str, ParserElement] = ",", - combine: bool = False, - min: typing.Optional[int] = None, - max: typing.Optional[int] = None, - *, - allow_trailing_delim: bool = False, -) -> ParserElement: - """Helper to define a delimited list of expressions - the delimiter - defaults to ','. By default, the list elements and delimiters can - have intervening whitespace, and comments, but this can be - overridden by passing ``combine=True`` in the constructor. If - ``combine`` is set to ``True``, the matching tokens are - returned as a single token string, with the delimiters included; - otherwise, the matching tokens are returned as a list of tokens, - with the delimiters suppressed. - - If ``allow_trailing_delim`` is set to True, then the list may end with - a delimiter. - - Example:: - - delimited_list(Word(alphas)).parse_string("aa,bb,cc") # -> ['aa', 'bb', 'cc'] - delimited_list(Word(hexnums), delim=':', combine=True).parse_string("AA:BB:CC:DD:EE") # -> ['AA:BB:CC:DD:EE'] - """ - if isinstance(expr, str_type): - expr = ParserElement._literalStringClass(expr) - - dlName = "{expr} [{delim} {expr}]...{end}".format( - expr=str(expr.copy().streamline()), - delim=str(delim), - end=" [{}]".format(str(delim)) if allow_trailing_delim else "", - ) - - if not combine: - delim = Suppress(delim) - - if min is not None: - if min < 1: - raise ValueError("min must be greater than 0") - min -= 1 - if max is not None: - if min is not None and max <= min: - raise ValueError("max must be greater than, or equal to min") - max -= 1 - delimited_list_expr = expr + (delim + expr)[min, max] - - if allow_trailing_delim: - delimited_list_expr += Opt(delim) - - if combine: - return Combine(delimited_list_expr).set_name(dlName) - else: - return delimited_list_expr.set_name(dlName) - - -def counted_array( - expr: ParserElement, - int_expr: typing.Optional[ParserElement] = None, - *, - intExpr: typing.Optional[ParserElement] = None, -) -> ParserElement: - """Helper to define a counted list of expressions. - - This helper defines a pattern of the form:: - - integer expr expr expr... - - where the leading integer tells how many expr expressions follow. - The matched tokens returns the array of expr tokens as a list - the - leading count token is suppressed. - - If ``int_expr`` is specified, it should be a pyparsing expression - that produces an integer value. - - Example:: - - counted_array(Word(alphas)).parse_string('2 ab cd ef') # -> ['ab', 'cd'] - - # in this parser, the leading integer value is given in binary, - # '10' indicating that 2 values are in the array - binary_constant = Word('01').set_parse_action(lambda t: int(t[0], 2)) - counted_array(Word(alphas), int_expr=binary_constant).parse_string('10 ab cd ef') # -> ['ab', 'cd'] - - # if other fields must be parsed after the count but before the - # list items, give the fields results names and they will - # be preserved in the returned ParseResults: - count_with_metadata = integer + Word(alphas)("type") - typed_array = counted_array(Word(alphanums), int_expr=count_with_metadata)("items") - result = typed_array.parse_string("3 bool True True False") - print(result.dump()) - - # prints - # ['True', 'True', 'False'] - # - items: ['True', 'True', 'False'] - # - type: 'bool' - """ - intExpr = intExpr or int_expr - array_expr = Forward() - - def count_field_parse_action(s, l, t): - nonlocal array_expr - n = t[0] - array_expr <<= (expr * n) if n else Empty() - # clear list contents, but keep any named results - del t[:] - - if intExpr is None: - intExpr = Word(nums).set_parse_action(lambda t: int(t[0])) - else: - intExpr = intExpr.copy() - intExpr.set_name("arrayLen") - intExpr.add_parse_action(count_field_parse_action, call_during_try=True) - return (intExpr + array_expr).set_name("(len) " + str(expr) + "...") - - -def match_previous_literal(expr: ParserElement) -> ParserElement: - """Helper to define an expression that is indirectly defined from - the tokens matched in a previous expression, that is, it looks for - a 'repeat' of a previous expression. For example:: - - first = Word(nums) - second = match_previous_literal(first) - match_expr = first + ":" + second - - will match ``"1:1"``, but not ``"1:2"``. Because this - matches a previous literal, will also match the leading - ``"1:1"`` in ``"1:10"``. If this is not desired, use - :class:`match_previous_expr`. Do *not* use with packrat parsing - enabled. - """ - rep = Forward() - - def copy_token_to_repeater(s, l, t): - if t: - if len(t) == 1: - rep << t[0] - else: - # flatten t tokens - tflat = _flatten(t.as_list()) - rep << And(Literal(tt) for tt in tflat) - else: - rep << Empty() - - expr.add_parse_action(copy_token_to_repeater, callDuringTry=True) - rep.set_name("(prev) " + str(expr)) - return rep - - -def match_previous_expr(expr: ParserElement) -> ParserElement: - """Helper to define an expression that is indirectly defined from - the tokens matched in a previous expression, that is, it looks for - a 'repeat' of a previous expression. For example:: - - first = Word(nums) - second = match_previous_expr(first) - match_expr = first + ":" + second - - will match ``"1:1"``, but not ``"1:2"``. Because this - matches by expressions, will *not* match the leading ``"1:1"`` - in ``"1:10"``; the expressions are evaluated first, and then - compared, so ``"1"`` is compared with ``"10"``. Do *not* use - with packrat parsing enabled. - """ - rep = Forward() - e2 = expr.copy() - rep <<= e2 - - def copy_token_to_repeater(s, l, t): - matchTokens = _flatten(t.as_list()) - - def must_match_these_tokens(s, l, t): - theseTokens = _flatten(t.as_list()) - if theseTokens != matchTokens: - raise ParseException( - s, l, "Expected {}, found{}".format(matchTokens, theseTokens) - ) - - rep.set_parse_action(must_match_these_tokens, callDuringTry=True) - - expr.add_parse_action(copy_token_to_repeater, callDuringTry=True) - rep.set_name("(prev) " + str(expr)) - return rep - - -def one_of( - strs: Union[typing.Iterable[str], str], - caseless: bool = False, - use_regex: bool = True, - as_keyword: bool = False, - *, - useRegex: bool = True, - asKeyword: bool = False, -) -> ParserElement: - """Helper to quickly define a set of alternative :class:`Literal` s, - and makes sure to do longest-first testing when there is a conflict, - regardless of the input order, but returns - a :class:`MatchFirst` for best performance. - - Parameters: - - - ``strs`` - a string of space-delimited literals, or a collection of - string literals - - ``caseless`` - treat all literals as caseless - (default= ``False``) - - ``use_regex`` - as an optimization, will - generate a :class:`Regex` object; otherwise, will generate - a :class:`MatchFirst` object (if ``caseless=True`` or ``asKeyword=True``, or if - creating a :class:`Regex` raises an exception) - (default= ``True``) - - ``as_keyword`` - enforce :class:`Keyword`-style matching on the - generated expressions - (default= ``False``) - - ``asKeyword`` and ``useRegex`` are retained for pre-PEP8 compatibility, - but will be removed in a future release - - Example:: - - comp_oper = one_of("< = > <= >= !=") - var = Word(alphas) - number = Word(nums) - term = var | number - comparison_expr = term + comp_oper + term - print(comparison_expr.search_string("B = 12 AA=23 B<=AA AA>12")) - - prints:: - - [['B', '=', '12'], ['AA', '=', '23'], ['B', '<=', 'AA'], ['AA', '>', '12']] - """ - asKeyword = asKeyword or as_keyword - useRegex = useRegex and use_regex - - if ( - isinstance(caseless, str_type) - and __diag__.warn_on_multiple_string_args_to_oneof - ): - warnings.warn( - "More than one string argument passed to one_of, pass" - " choices as a list or space-delimited string", - stacklevel=2, - ) - - if caseless: - isequal = lambda a, b: a.upper() == b.upper() - masks = lambda a, b: b.upper().startswith(a.upper()) - parseElementClass = CaselessKeyword if asKeyword else CaselessLiteral - else: - isequal = lambda a, b: a == b - masks = lambda a, b: b.startswith(a) - parseElementClass = Keyword if asKeyword else Literal - - symbols: List[str] = [] - if isinstance(strs, str_type): - symbols = strs.split() - elif isinstance(strs, Iterable): - symbols = list(strs) - else: - raise TypeError("Invalid argument to one_of, expected string or iterable") - if not symbols: - return NoMatch() - - # reorder given symbols to take care to avoid masking longer choices with shorter ones - # (but only if the given symbols are not just single characters) - if any(len(sym) > 1 for sym in symbols): - i = 0 - while i < len(symbols) - 1: - cur = symbols[i] - for j, other in enumerate(symbols[i + 1 :]): - if isequal(other, cur): - del symbols[i + j + 1] - break - elif masks(cur, other): - del symbols[i + j + 1] - symbols.insert(i, other) - break - else: - i += 1 - - if useRegex: - re_flags: int = re.IGNORECASE if caseless else 0 - - try: - if all(len(sym) == 1 for sym in symbols): - # symbols are just single characters, create range regex pattern - patt = "[{}]".format( - "".join(_escape_regex_range_chars(sym) for sym in symbols) - ) - else: - patt = "|".join(re.escape(sym) for sym in symbols) - - # wrap with \b word break markers if defining as keywords - if asKeyword: - patt = r"\b(?:{})\b".format(patt) - - ret = Regex(patt, flags=re_flags).set_name(" | ".join(symbols)) - - if caseless: - # add parse action to return symbols as specified, not in random - # casing as found in input string - symbol_map = {sym.lower(): sym for sym in symbols} - ret.add_parse_action(lambda s, l, t: symbol_map[t[0].lower()]) - - return ret - - except re.error: - warnings.warn( - "Exception creating Regex for one_of, building MatchFirst", stacklevel=2 - ) - - # last resort, just use MatchFirst - return MatchFirst(parseElementClass(sym) for sym in symbols).set_name( - " | ".join(symbols) - ) - - -def dict_of(key: ParserElement, value: ParserElement) -> ParserElement: - """Helper to easily and clearly define a dictionary by specifying - the respective patterns for the key and value. Takes care of - defining the :class:`Dict`, :class:`ZeroOrMore`, and - :class:`Group` tokens in the proper order. The key pattern - can include delimiting markers or punctuation, as long as they are - suppressed, thereby leaving the significant key text. The value - pattern can include named results, so that the :class:`Dict` results - can include named token fields. - - Example:: - - text = "shape: SQUARE posn: upper left color: light blue texture: burlap" - attr_expr = (label + Suppress(':') + OneOrMore(data_word, stop_on=label).set_parse_action(' '.join)) - print(attr_expr[1, ...].parse_string(text).dump()) - - attr_label = label - attr_value = Suppress(':') + OneOrMore(data_word, stop_on=label).set_parse_action(' '.join) - - # similar to Dict, but simpler call format - result = dict_of(attr_label, attr_value).parse_string(text) - print(result.dump()) - print(result['shape']) - print(result.shape) # object attribute access works too - print(result.as_dict()) - - prints:: - - [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] - - color: 'light blue' - - posn: 'upper left' - - shape: 'SQUARE' - - texture: 'burlap' - SQUARE - SQUARE - {'color': 'light blue', 'shape': 'SQUARE', 'posn': 'upper left', 'texture': 'burlap'} - """ - return Dict(OneOrMore(Group(key + value))) - - -def original_text_for( - expr: ParserElement, as_string: bool = True, *, asString: bool = True -) -> ParserElement: - """Helper to return the original, untokenized text for a given - expression. Useful to restore the parsed fields of an HTML start - tag into the raw tag text itself, or to revert separate tokens with - intervening whitespace back to the original matching input text. By - default, returns astring containing the original parsed text. - - If the optional ``as_string`` argument is passed as - ``False``, then the return value is - a :class:`ParseResults` containing any results names that - were originally matched, and a single token containing the original - matched text from the input string. So if the expression passed to - :class:`original_text_for` contains expressions with defined - results names, you must set ``as_string`` to ``False`` if you - want to preserve those results name values. - - The ``asString`` pre-PEP8 argument is retained for compatibility, - but will be removed in a future release. - - Example:: - - src = "this is test bold text normal text " - for tag in ("b", "i"): - opener, closer = make_html_tags(tag) - patt = original_text_for(opener + SkipTo(closer) + closer) - print(patt.search_string(src)[0]) - - prints:: - - [' bold text '] - ['text'] - """ - asString = asString and as_string - - locMarker = Empty().set_parse_action(lambda s, loc, t: loc) - endlocMarker = locMarker.copy() - endlocMarker.callPreparse = False - matchExpr = locMarker("_original_start") + expr + endlocMarker("_original_end") - if asString: - extractText = lambda s, l, t: s[t._original_start : t._original_end] - else: - - def extractText(s, l, t): - t[:] = [s[t.pop("_original_start") : t.pop("_original_end")]] - - matchExpr.set_parse_action(extractText) - matchExpr.ignoreExprs = expr.ignoreExprs - matchExpr.suppress_warning(Diagnostics.warn_ungrouped_named_tokens_in_collection) - return matchExpr - - -def ungroup(expr: ParserElement) -> ParserElement: - """Helper to undo pyparsing's default grouping of And expressions, - even if all but one are non-empty. - """ - return TokenConverter(expr).add_parse_action(lambda t: t[0]) - - -def locatedExpr(expr: ParserElement) -> ParserElement: - """ - (DEPRECATED - future code should use the Located class) - Helper to decorate a returned token with its starting and ending - locations in the input string. - - This helper adds the following results names: - - - ``locn_start`` - location where matched expression begins - - ``locn_end`` - location where matched expression ends - - ``value`` - the actual parsed results - - Be careful if the input text contains ```` characters, you - may want to call :class:`ParserElement.parseWithTabs` - - Example:: - - wd = Word(alphas) - for match in locatedExpr(wd).searchString("ljsdf123lksdjjf123lkkjj1222"): - print(match) - - prints:: - - [[0, 'ljsdf', 5]] - [[8, 'lksdjjf', 15]] - [[18, 'lkkjj', 23]] - """ - locator = Empty().set_parse_action(lambda ss, ll, tt: ll) - return Group( - locator("locn_start") - + expr("value") - + locator.copy().leaveWhitespace()("locn_end") - ) - - -def nested_expr( - opener: Union[str, ParserElement] = "(", - closer: Union[str, ParserElement] = ")", - content: typing.Optional[ParserElement] = None, - ignore_expr: ParserElement = quoted_string(), - *, - ignoreExpr: ParserElement = quoted_string(), -) -> ParserElement: - """Helper method for defining nested lists enclosed in opening and - closing delimiters (``"("`` and ``")"`` are the default). - - Parameters: - - ``opener`` - opening character for a nested list - (default= ``"("``); can also be a pyparsing expression - - ``closer`` - closing character for a nested list - (default= ``")"``); can also be a pyparsing expression - - ``content`` - expression for items within the nested lists - (default= ``None``) - - ``ignore_expr`` - expression for ignoring opening and closing delimiters - (default= :class:`quoted_string`) - - ``ignoreExpr`` - this pre-PEP8 argument is retained for compatibility - but will be removed in a future release - - If an expression is not provided for the content argument, the - nested expression will capture all whitespace-delimited content - between delimiters as a list of separate values. - - Use the ``ignore_expr`` argument to define expressions that may - contain opening or closing characters that should not be treated as - opening or closing characters for nesting, such as quoted_string or - a comment expression. Specify multiple expressions using an - :class:`Or` or :class:`MatchFirst`. The default is - :class:`quoted_string`, but if no expressions are to be ignored, then - pass ``None`` for this argument. - - Example:: - - data_type = one_of("void int short long char float double") - decl_data_type = Combine(data_type + Opt(Word('*'))) - ident = Word(alphas+'_', alphanums+'_') - number = pyparsing_common.number - arg = Group(decl_data_type + ident) - LPAR, RPAR = map(Suppress, "()") - - code_body = nested_expr('{', '}', ignore_expr=(quoted_string | c_style_comment)) - - c_function = (decl_data_type("type") - + ident("name") - + LPAR + Opt(delimited_list(arg), [])("args") + RPAR - + code_body("body")) - c_function.ignore(c_style_comment) - - source_code = ''' - int is_odd(int x) { - return (x%2); - } - - int dec_to_hex(char hchar) { - if (hchar >= '0' && hchar <= '9') { - return (ord(hchar)-ord('0')); - } else { - return (10+ord(hchar)-ord('A')); - } - } - ''' - for func in c_function.search_string(source_code): - print("%(name)s (%(type)s) args: %(args)s" % func) - - - prints:: - - is_odd (int) args: [['int', 'x']] - dec_to_hex (int) args: [['char', 'hchar']] - """ - if ignoreExpr != ignore_expr: - ignoreExpr = ignore_expr if ignoreExpr == quoted_string() else ignoreExpr - if opener == closer: - raise ValueError("opening and closing strings cannot be the same") - if content is None: - if isinstance(opener, str_type) and isinstance(closer, str_type): - if len(opener) == 1 and len(closer) == 1: - if ignoreExpr is not None: - content = Combine( - OneOrMore( - ~ignoreExpr - + CharsNotIn( - opener + closer + ParserElement.DEFAULT_WHITE_CHARS, - exact=1, - ) - ) - ).set_parse_action(lambda t: t[0].strip()) - else: - content = empty.copy() + CharsNotIn( - opener + closer + ParserElement.DEFAULT_WHITE_CHARS - ).set_parse_action(lambda t: t[0].strip()) - else: - if ignoreExpr is not None: - content = Combine( - OneOrMore( - ~ignoreExpr - + ~Literal(opener) - + ~Literal(closer) - + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS, exact=1) - ) - ).set_parse_action(lambda t: t[0].strip()) - else: - content = Combine( - OneOrMore( - ~Literal(opener) - + ~Literal(closer) - + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS, exact=1) - ) - ).set_parse_action(lambda t: t[0].strip()) - else: - raise ValueError( - "opening and closing arguments must be strings if no content expression is given" - ) - ret = Forward() - if ignoreExpr is not None: - ret <<= Group( - Suppress(opener) + ZeroOrMore(ignoreExpr | ret | content) + Suppress(closer) - ) - else: - ret <<= Group(Suppress(opener) + ZeroOrMore(ret | content) + Suppress(closer)) - ret.set_name("nested %s%s expression" % (opener, closer)) - return ret - - -def _makeTags(tagStr, xml, suppress_LT=Suppress("<"), suppress_GT=Suppress(">")): - """Internal helper to construct opening and closing tag expressions, given a tag name""" - if isinstance(tagStr, str_type): - resname = tagStr - tagStr = Keyword(tagStr, caseless=not xml) - else: - resname = tagStr.name - - tagAttrName = Word(alphas, alphanums + "_-:") - if xml: - tagAttrValue = dbl_quoted_string.copy().set_parse_action(remove_quotes) - openTag = ( - suppress_LT - + tagStr("tag") - + Dict(ZeroOrMore(Group(tagAttrName + Suppress("=") + tagAttrValue))) - + Opt("/", default=[False])("empty").set_parse_action( - lambda s, l, t: t[0] == "/" - ) - + suppress_GT - ) - else: - tagAttrValue = quoted_string.copy().set_parse_action(remove_quotes) | Word( - printables, exclude_chars=">" - ) - openTag = ( - suppress_LT - + tagStr("tag") - + Dict( - ZeroOrMore( - Group( - tagAttrName.set_parse_action(lambda t: t[0].lower()) - + Opt(Suppress("=") + tagAttrValue) - ) - ) - ) - + Opt("/", default=[False])("empty").set_parse_action( - lambda s, l, t: t[0] == "/" - ) - + suppress_GT - ) - closeTag = Combine(Literal("", adjacent=False) - - openTag.set_name("<%s>" % resname) - # add start results name in parse action now that ungrouped names are not reported at two levels - openTag.add_parse_action( - lambda t: t.__setitem__( - "start" + "".join(resname.replace(":", " ").title().split()), t.copy() - ) - ) - closeTag = closeTag( - "end" + "".join(resname.replace(":", " ").title().split()) - ).set_name("" % resname) - openTag.tag = resname - closeTag.tag = resname - openTag.tag_body = SkipTo(closeTag()) - return openTag, closeTag - - -def make_html_tags( - tag_str: Union[str, ParserElement] -) -> Tuple[ParserElement, ParserElement]: - """Helper to construct opening and closing tag expressions for HTML, - given a tag name. Matches tags in either upper or lower case, - attributes with namespaces and with quoted or unquoted values. - - Example:: - - text = 'More info at the pyparsing wiki page' - # make_html_tags returns pyparsing expressions for the opening and - # closing tags as a 2-tuple - a, a_end = make_html_tags("A") - link_expr = a + SkipTo(a_end)("link_text") + a_end - - for link in link_expr.search_string(text): - # attributes in the tag (like "href" shown here) are - # also accessible as named results - print(link.link_text, '->', link.href) - - prints:: - - pyparsing -> https://github.com/pyparsing/pyparsing/wiki - """ - return _makeTags(tag_str, False) - - -def make_xml_tags( - tag_str: Union[str, ParserElement] -) -> Tuple[ParserElement, ParserElement]: - """Helper to construct opening and closing tag expressions for XML, - given a tag name. Matches tags only in the given upper/lower case. - - Example: similar to :class:`make_html_tags` - """ - return _makeTags(tag_str, True) - - -any_open_tag: ParserElement -any_close_tag: ParserElement -any_open_tag, any_close_tag = make_html_tags( - Word(alphas, alphanums + "_:").set_name("any tag") -) - -_htmlEntityMap = {k.rstrip(";"): v for k, v in html.entities.html5.items()} -common_html_entity = Regex("&(?P" + "|".join(_htmlEntityMap) + ");").set_name( - "common HTML entity" -) - - -def replace_html_entity(t): - """Helper parser action to replace common HTML entities with their special characters""" - return _htmlEntityMap.get(t.entity) - - -class OpAssoc(Enum): - LEFT = 1 - RIGHT = 2 - - -InfixNotationOperatorArgType = Union[ - ParserElement, str, Tuple[Union[ParserElement, str], Union[ParserElement, str]] -] -InfixNotationOperatorSpec = Union[ - Tuple[ - InfixNotationOperatorArgType, - int, - OpAssoc, - typing.Optional[ParseAction], - ], - Tuple[ - InfixNotationOperatorArgType, - int, - OpAssoc, - ], -] - - -def infix_notation( - base_expr: ParserElement, - op_list: List[InfixNotationOperatorSpec], - lpar: Union[str, ParserElement] = Suppress("("), - rpar: Union[str, ParserElement] = Suppress(")"), -) -> ParserElement: - """Helper method for constructing grammars of expressions made up of - operators working in a precedence hierarchy. Operators may be unary - or binary, left- or right-associative. Parse actions can also be - attached to operator expressions. The generated parser will also - recognize the use of parentheses to override operator precedences - (see example below). - - Note: if you define a deep operator list, you may see performance - issues when using infix_notation. See - :class:`ParserElement.enable_packrat` for a mechanism to potentially - improve your parser performance. - - Parameters: - - ``base_expr`` - expression representing the most basic operand to - be used in the expression - - ``op_list`` - list of tuples, one for each operator precedence level - in the expression grammar; each tuple is of the form ``(op_expr, - num_operands, right_left_assoc, (optional)parse_action)``, where: - - - ``op_expr`` is the pyparsing expression for the operator; may also - be a string, which will be converted to a Literal; if ``num_operands`` - is 3, ``op_expr`` is a tuple of two expressions, for the two - operators separating the 3 terms - - ``num_operands`` is the number of terms for this operator (must be 1, - 2, or 3) - - ``right_left_assoc`` is the indicator whether the operator is right - or left associative, using the pyparsing-defined constants - ``OpAssoc.RIGHT`` and ``OpAssoc.LEFT``. - - ``parse_action`` is the parse action to be associated with - expressions matching this operator expression (the parse action - tuple member may be omitted); if the parse action is passed - a tuple or list of functions, this is equivalent to calling - ``set_parse_action(*fn)`` - (:class:`ParserElement.set_parse_action`) - - ``lpar`` - expression for matching left-parentheses; if passed as a - str, then will be parsed as Suppress(lpar). If lpar is passed as - an expression (such as ``Literal('(')``), then it will be kept in - the parsed results, and grouped with them. (default= ``Suppress('(')``) - - ``rpar`` - expression for matching right-parentheses; if passed as a - str, then will be parsed as Suppress(rpar). If rpar is passed as - an expression (such as ``Literal(')')``), then it will be kept in - the parsed results, and grouped with them. (default= ``Suppress(')')``) - - Example:: - - # simple example of four-function arithmetic with ints and - # variable names - integer = pyparsing_common.signed_integer - varname = pyparsing_common.identifier - - arith_expr = infix_notation(integer | varname, - [ - ('-', 1, OpAssoc.RIGHT), - (one_of('* /'), 2, OpAssoc.LEFT), - (one_of('+ -'), 2, OpAssoc.LEFT), - ]) - - arith_expr.run_tests(''' - 5+3*6 - (5+3)*6 - -2--11 - ''', full_dump=False) - - prints:: - - 5+3*6 - [[5, '+', [3, '*', 6]]] - - (5+3)*6 - [[[5, '+', 3], '*', 6]] - - -2--11 - [[['-', 2], '-', ['-', 11]]] - """ - # captive version of FollowedBy that does not do parse actions or capture results names - class _FB(FollowedBy): - def parseImpl(self, instring, loc, doActions=True): - self.expr.try_parse(instring, loc) - return loc, [] - - _FB.__name__ = "FollowedBy>" - - ret = Forward() - if isinstance(lpar, str): - lpar = Suppress(lpar) - if isinstance(rpar, str): - rpar = Suppress(rpar) - - # if lpar and rpar are not suppressed, wrap in group - if not (isinstance(rpar, Suppress) and isinstance(rpar, Suppress)): - lastExpr = base_expr | Group(lpar + ret + rpar) - else: - lastExpr = base_expr | (lpar + ret + rpar) - - for i, operDef in enumerate(op_list): - opExpr, arity, rightLeftAssoc, pa = (operDef + (None,))[:4] - if isinstance(opExpr, str_type): - opExpr = ParserElement._literalStringClass(opExpr) - if arity == 3: - if not isinstance(opExpr, (tuple, list)) or len(opExpr) != 2: - raise ValueError( - "if numterms=3, opExpr must be a tuple or list of two expressions" - ) - opExpr1, opExpr2 = opExpr - term_name = "{}{} term".format(opExpr1, opExpr2) - else: - term_name = "{} term".format(opExpr) - - if not 1 <= arity <= 3: - raise ValueError("operator must be unary (1), binary (2), or ternary (3)") - - if rightLeftAssoc not in (OpAssoc.LEFT, OpAssoc.RIGHT): - raise ValueError("operator must indicate right or left associativity") - - thisExpr: Forward = Forward().set_name(term_name) - if rightLeftAssoc is OpAssoc.LEFT: - if arity == 1: - matchExpr = _FB(lastExpr + opExpr) + Group(lastExpr + opExpr[1, ...]) - elif arity == 2: - if opExpr is not None: - matchExpr = _FB(lastExpr + opExpr + lastExpr) + Group( - lastExpr + (opExpr + lastExpr)[1, ...] - ) - else: - matchExpr = _FB(lastExpr + lastExpr) + Group(lastExpr[2, ...]) - elif arity == 3: - matchExpr = _FB( - lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr - ) + Group(lastExpr + OneOrMore(opExpr1 + lastExpr + opExpr2 + lastExpr)) - elif rightLeftAssoc is OpAssoc.RIGHT: - if arity == 1: - # try to avoid LR with this extra test - if not isinstance(opExpr, Opt): - opExpr = Opt(opExpr) - matchExpr = _FB(opExpr.expr + thisExpr) + Group(opExpr + thisExpr) - elif arity == 2: - if opExpr is not None: - matchExpr = _FB(lastExpr + opExpr + thisExpr) + Group( - lastExpr + (opExpr + thisExpr)[1, ...] - ) - else: - matchExpr = _FB(lastExpr + thisExpr) + Group( - lastExpr + thisExpr[1, ...] - ) - elif arity == 3: - matchExpr = _FB( - lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr - ) + Group(lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr) - if pa: - if isinstance(pa, (tuple, list)): - matchExpr.set_parse_action(*pa) - else: - matchExpr.set_parse_action(pa) - thisExpr <<= (matchExpr | lastExpr).setName(term_name) - lastExpr = thisExpr - ret <<= lastExpr - return ret - - -def indentedBlock(blockStatementExpr, indentStack, indent=True, backup_stacks=[]): - """ - (DEPRECATED - use IndentedBlock class instead) - Helper method for defining space-delimited indentation blocks, - such as those used to define block statements in Python source code. - - Parameters: - - - ``blockStatementExpr`` - expression defining syntax of statement that - is repeated within the indented block - - ``indentStack`` - list created by caller to manage indentation stack - (multiple ``statementWithIndentedBlock`` expressions within a single - grammar should share a common ``indentStack``) - - ``indent`` - boolean indicating whether block must be indented beyond - the current level; set to ``False`` for block of left-most statements - (default= ``True``) - - A valid block must contain at least one ``blockStatement``. - - (Note that indentedBlock uses internal parse actions which make it - incompatible with packrat parsing.) - - Example:: - - data = ''' - def A(z): - A1 - B = 100 - G = A2 - A2 - A3 - B - def BB(a,b,c): - BB1 - def BBA(): - bba1 - bba2 - bba3 - C - D - def spam(x,y): - def eggs(z): - pass - ''' - - - indentStack = [1] - stmt = Forward() - - identifier = Word(alphas, alphanums) - funcDecl = ("def" + identifier + Group("(" + Opt(delimitedList(identifier)) + ")") + ":") - func_body = indentedBlock(stmt, indentStack) - funcDef = Group(funcDecl + func_body) - - rvalue = Forward() - funcCall = Group(identifier + "(" + Opt(delimitedList(rvalue)) + ")") - rvalue << (funcCall | identifier | Word(nums)) - assignment = Group(identifier + "=" + rvalue) - stmt << (funcDef | assignment | identifier) - - module_body = stmt[1, ...] - - parseTree = module_body.parseString(data) - parseTree.pprint() - - prints:: - - [['def', - 'A', - ['(', 'z', ')'], - ':', - [['A1'], [['B', '=', '100']], [['G', '=', 'A2']], ['A2'], ['A3']]], - 'B', - ['def', - 'BB', - ['(', 'a', 'b', 'c', ')'], - ':', - [['BB1'], [['def', 'BBA', ['(', ')'], ':', [['bba1'], ['bba2'], ['bba3']]]]]], - 'C', - 'D', - ['def', - 'spam', - ['(', 'x', 'y', ')'], - ':', - [[['def', 'eggs', ['(', 'z', ')'], ':', [['pass']]]]]]] - """ - backup_stacks.append(indentStack[:]) - - def reset_stack(): - indentStack[:] = backup_stacks[-1] - - def checkPeerIndent(s, l, t): - if l >= len(s): - return - curCol = col(l, s) - if curCol != indentStack[-1]: - if curCol > indentStack[-1]: - raise ParseException(s, l, "illegal nesting") - raise ParseException(s, l, "not a peer entry") - - def checkSubIndent(s, l, t): - curCol = col(l, s) - if curCol > indentStack[-1]: - indentStack.append(curCol) - else: - raise ParseException(s, l, "not a subentry") - - def checkUnindent(s, l, t): - if l >= len(s): - return - curCol = col(l, s) - if not (indentStack and curCol in indentStack): - raise ParseException(s, l, "not an unindent") - if curCol < indentStack[-1]: - indentStack.pop() - - NL = OneOrMore(LineEnd().set_whitespace_chars("\t ").suppress()) - INDENT = (Empty() + Empty().set_parse_action(checkSubIndent)).set_name("INDENT") - PEER = Empty().set_parse_action(checkPeerIndent).set_name("") - UNDENT = Empty().set_parse_action(checkUnindent).set_name("UNINDENT") - if indent: - smExpr = Group( - Opt(NL) - + INDENT - + OneOrMore(PEER + Group(blockStatementExpr) + Opt(NL)) - + UNDENT - ) - else: - smExpr = Group( - Opt(NL) - + OneOrMore(PEER + Group(blockStatementExpr) + Opt(NL)) - + Opt(UNDENT) - ) - - # add a parse action to remove backup_stack from list of backups - smExpr.add_parse_action( - lambda: backup_stacks.pop(-1) and None if backup_stacks else None - ) - smExpr.set_fail_action(lambda a, b, c, d: reset_stack()) - blockStatementExpr.ignore(_bslash + LineEnd()) - return smExpr.set_name("indented block") - - -# it's easy to get these comment structures wrong - they're very common, so may as well make them available -c_style_comment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + "*/").set_name( - "C style comment" -) -"Comment of the form ``/* ... */``" - -html_comment = Regex(r"").set_name("HTML comment") -"Comment of the form ````" - -rest_of_line = Regex(r".*").leave_whitespace().set_name("rest of line") -dbl_slash_comment = Regex(r"//(?:\\\n|[^\n])*").set_name("// comment") -"Comment of the form ``// ... (to end of line)``" - -cpp_style_comment = Combine( - Regex(r"/\*(?:[^*]|\*(?!/))*") + "*/" | dbl_slash_comment -).set_name("C++ style comment") -"Comment of either form :class:`c_style_comment` or :class:`dbl_slash_comment`" - -java_style_comment = cpp_style_comment -"Same as :class:`cpp_style_comment`" - -python_style_comment = Regex(r"#.*").set_name("Python style comment") -"Comment of the form ``# ... (to end of line)``" - - -# build list of built-in expressions, for future reference if a global default value -# gets updated -_builtin_exprs: List[ParserElement] = [ - v for v in vars().values() if isinstance(v, ParserElement) -] - - -# pre-PEP8 compatible names -delimitedList = delimited_list -countedArray = counted_array -matchPreviousLiteral = match_previous_literal -matchPreviousExpr = match_previous_expr -oneOf = one_of -dictOf = dict_of -originalTextFor = original_text_for -nestedExpr = nested_expr -makeHTMLTags = make_html_tags -makeXMLTags = make_xml_tags -anyOpenTag, anyCloseTag = any_open_tag, any_close_tag -commonHTMLEntity = common_html_entity -replaceHTMLEntity = replace_html_entity -opAssoc = OpAssoc -infixNotation = infix_notation -cStyleComment = c_style_comment -htmlComment = html_comment -restOfLine = rest_of_line -dblSlashComment = dbl_slash_comment -cppStyleComment = cpp_style_comment -javaStyleComment = java_style_comment -pythonStyleComment = python_style_comment diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/results.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/results.py deleted file mode 100755 index 00c9421..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/results.py +++ /dev/null @@ -1,760 +0,0 @@ -# results.py -from collections.abc import MutableMapping, Mapping, MutableSequence, Iterator -import pprint -from weakref import ref as wkref -from typing import Tuple, Any - -str_type: Tuple[type, ...] = (str, bytes) -_generator_type = type((_ for _ in ())) - - -class _ParseResultsWithOffset: - __slots__ = ["tup"] - - def __init__(self, p1, p2): - self.tup = (p1, p2) - - def __getitem__(self, i): - return self.tup[i] - - def __getstate__(self): - return self.tup - - def __setstate__(self, *args): - self.tup = args[0] - - -class ParseResults: - """Structured parse results, to provide multiple means of access to - the parsed data: - - - as a list (``len(results)``) - - by list index (``results[0], results[1]``, etc.) - - by attribute (``results.`` - see :class:`ParserElement.set_results_name`) - - Example:: - - integer = Word(nums) - date_str = (integer.set_results_name("year") + '/' - + integer.set_results_name("month") + '/' - + integer.set_results_name("day")) - # equivalent form: - # date_str = (integer("year") + '/' - # + integer("month") + '/' - # + integer("day")) - - # parse_string returns a ParseResults object - result = date_str.parse_string("1999/12/31") - - def test(s, fn=repr): - print("{} -> {}".format(s, fn(eval(s)))) - test("list(result)") - test("result[0]") - test("result['month']") - test("result.day") - test("'month' in result") - test("'minutes' in result") - test("result.dump()", str) - - prints:: - - list(result) -> ['1999', '/', '12', '/', '31'] - result[0] -> '1999' - result['month'] -> '12' - result.day -> '31' - 'month' in result -> True - 'minutes' in result -> False - result.dump() -> ['1999', '/', '12', '/', '31'] - - day: '31' - - month: '12' - - year: '1999' - """ - - _null_values: Tuple[Any, ...] = (None, [], "", ()) - - __slots__ = [ - "_name", - "_parent", - "_all_names", - "_modal", - "_toklist", - "_tokdict", - "__weakref__", - ] - - class List(list): - """ - Simple wrapper class to distinguish parsed list results that should be preserved - as actual Python lists, instead of being converted to :class:`ParseResults`: - - LBRACK, RBRACK = map(pp.Suppress, "[]") - element = pp.Forward() - item = ppc.integer - element_list = LBRACK + pp.delimited_list(element) + RBRACK - - # add parse actions to convert from ParseResults to actual Python collection types - def as_python_list(t): - return pp.ParseResults.List(t.as_list()) - element_list.add_parse_action(as_python_list) - - element <<= item | element_list - - element.run_tests(''' - 100 - [2,3,4] - [[2, 1],3,4] - [(2, 1),3,4] - (2,3,4) - ''', post_parse=lambda s, r: (r[0], type(r[0]))) - - prints: - - 100 - (100, ) - - [2,3,4] - ([2, 3, 4], ) - - [[2, 1],3,4] - ([[2, 1], 3, 4], ) - - (Used internally by :class:`Group` when `aslist=True`.) - """ - - def __new__(cls, contained=None): - if contained is None: - contained = [] - - if not isinstance(contained, list): - raise TypeError( - "{} may only be constructed with a list," - " not {}".format(cls.__name__, type(contained).__name__) - ) - - return list.__new__(cls) - - def __new__(cls, toklist=None, name=None, **kwargs): - if isinstance(toklist, ParseResults): - return toklist - self = object.__new__(cls) - self._name = None - self._parent = None - self._all_names = set() - - if toklist is None: - self._toklist = [] - elif isinstance(toklist, (list, _generator_type)): - self._toklist = ( - [toklist[:]] - if isinstance(toklist, ParseResults.List) - else list(toklist) - ) - else: - self._toklist = [toklist] - self._tokdict = dict() - return self - - # Performance tuning: we construct a *lot* of these, so keep this - # constructor as small and fast as possible - def __init__( - self, toklist=None, name=None, asList=True, modal=True, isinstance=isinstance - ): - self._modal = modal - if name is not None and name != "": - if isinstance(name, int): - name = str(name) - if not modal: - self._all_names = {name} - self._name = name - if toklist not in self._null_values: - if isinstance(toklist, (str_type, type)): - toklist = [toklist] - if asList: - if isinstance(toklist, ParseResults): - self[name] = _ParseResultsWithOffset( - ParseResults(toklist._toklist), 0 - ) - else: - self[name] = _ParseResultsWithOffset( - ParseResults(toklist[0]), 0 - ) - self[name]._name = name - else: - try: - self[name] = toklist[0] - except (KeyError, TypeError, IndexError): - if toklist is not self: - self[name] = toklist - else: - self._name = name - - def __getitem__(self, i): - if isinstance(i, (int, slice)): - return self._toklist[i] - else: - if i not in self._all_names: - return self._tokdict[i][-1][0] - else: - return ParseResults([v[0] for v in self._tokdict[i]]) - - def __setitem__(self, k, v, isinstance=isinstance): - if isinstance(v, _ParseResultsWithOffset): - self._tokdict[k] = self._tokdict.get(k, list()) + [v] - sub = v[0] - elif isinstance(k, (int, slice)): - self._toklist[k] = v - sub = v - else: - self._tokdict[k] = self._tokdict.get(k, list()) + [ - _ParseResultsWithOffset(v, 0) - ] - sub = v - if isinstance(sub, ParseResults): - sub._parent = wkref(self) - - def __delitem__(self, i): - if isinstance(i, (int, slice)): - mylen = len(self._toklist) - del self._toklist[i] - - # convert int to slice - if isinstance(i, int): - if i < 0: - i += mylen - i = slice(i, i + 1) - # get removed indices - removed = list(range(*i.indices(mylen))) - removed.reverse() - # fixup indices in token dictionary - for name, occurrences in self._tokdict.items(): - for j in removed: - for k, (value, position) in enumerate(occurrences): - occurrences[k] = _ParseResultsWithOffset( - value, position - (position > j) - ) - else: - del self._tokdict[i] - - def __contains__(self, k) -> bool: - return k in self._tokdict - - def __len__(self) -> int: - return len(self._toklist) - - def __bool__(self) -> bool: - return not not (self._toklist or self._tokdict) - - def __iter__(self) -> Iterator: - return iter(self._toklist) - - def __reversed__(self) -> Iterator: - return iter(self._toklist[::-1]) - - def keys(self): - return iter(self._tokdict) - - def values(self): - return (self[k] for k in self.keys()) - - def items(self): - return ((k, self[k]) for k in self.keys()) - - def haskeys(self) -> bool: - """ - Since ``keys()`` returns an iterator, this method is helpful in bypassing - code that looks for the existence of any defined results names.""" - return bool(self._tokdict) - - def pop(self, *args, **kwargs): - """ - Removes and returns item at specified index (default= ``last``). - Supports both ``list`` and ``dict`` semantics for ``pop()``. If - passed no argument or an integer argument, it will use ``list`` - semantics and pop tokens from the list of parsed tokens. If passed - a non-integer argument (most likely a string), it will use ``dict`` - semantics and pop the corresponding value from any defined results - names. A second default return value argument is supported, just as in - ``dict.pop()``. - - Example:: - - numlist = Word(nums)[...] - print(numlist.parse_string("0 123 321")) # -> ['0', '123', '321'] - - def remove_first(tokens): - tokens.pop(0) - numlist.add_parse_action(remove_first) - print(numlist.parse_string("0 123 321")) # -> ['123', '321'] - - label = Word(alphas) - patt = label("LABEL") + Word(nums)[1, ...] - print(patt.parse_string("AAB 123 321").dump()) - - # Use pop() in a parse action to remove named result (note that corresponding value is not - # removed from list form of results) - def remove_LABEL(tokens): - tokens.pop("LABEL") - return tokens - patt.add_parse_action(remove_LABEL) - print(patt.parse_string("AAB 123 321").dump()) - - prints:: - - ['AAB', '123', '321'] - - LABEL: 'AAB' - - ['AAB', '123', '321'] - """ - if not args: - args = [-1] - for k, v in kwargs.items(): - if k == "default": - args = (args[0], v) - else: - raise TypeError( - "pop() got an unexpected keyword argument {!r}".format(k) - ) - if isinstance(args[0], int) or len(args) == 1 or args[0] in self: - index = args[0] - ret = self[index] - del self[index] - return ret - else: - defaultvalue = args[1] - return defaultvalue - - def get(self, key, default_value=None): - """ - Returns named result matching the given key, or if there is no - such name, then returns the given ``default_value`` or ``None`` if no - ``default_value`` is specified. - - Similar to ``dict.get()``. - - Example:: - - integer = Word(nums) - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - result = date_str.parse_string("1999/12/31") - print(result.get("year")) # -> '1999' - print(result.get("hour", "not specified")) # -> 'not specified' - print(result.get("hour")) # -> None - """ - if key in self: - return self[key] - else: - return default_value - - def insert(self, index, ins_string): - """ - Inserts new element at location index in the list of parsed tokens. - - Similar to ``list.insert()``. - - Example:: - - numlist = Word(nums)[...] - print(numlist.parse_string("0 123 321")) # -> ['0', '123', '321'] - - # use a parse action to insert the parse location in the front of the parsed results - def insert_locn(locn, tokens): - tokens.insert(0, locn) - numlist.add_parse_action(insert_locn) - print(numlist.parse_string("0 123 321")) # -> [0, '0', '123', '321'] - """ - self._toklist.insert(index, ins_string) - # fixup indices in token dictionary - for name, occurrences in self._tokdict.items(): - for k, (value, position) in enumerate(occurrences): - occurrences[k] = _ParseResultsWithOffset( - value, position + (position > index) - ) - - def append(self, item): - """ - Add single element to end of ``ParseResults`` list of elements. - - Example:: - - numlist = Word(nums)[...] - print(numlist.parse_string("0 123 321")) # -> ['0', '123', '321'] - - # use a parse action to compute the sum of the parsed integers, and add it to the end - def append_sum(tokens): - tokens.append(sum(map(int, tokens))) - numlist.add_parse_action(append_sum) - print(numlist.parse_string("0 123 321")) # -> ['0', '123', '321', 444] - """ - self._toklist.append(item) - - def extend(self, itemseq): - """ - Add sequence of elements to end of ``ParseResults`` list of elements. - - Example:: - - patt = Word(alphas)[1, ...] - - # use a parse action to append the reverse of the matched strings, to make a palindrome - def make_palindrome(tokens): - tokens.extend(reversed([t[::-1] for t in tokens])) - return ''.join(tokens) - patt.add_parse_action(make_palindrome) - print(patt.parse_string("lskdj sdlkjf lksd")) # -> 'lskdjsdlkjflksddsklfjkldsjdksl' - """ - if isinstance(itemseq, ParseResults): - self.__iadd__(itemseq) - else: - self._toklist.extend(itemseq) - - def clear(self): - """ - Clear all elements and results names. - """ - del self._toklist[:] - self._tokdict.clear() - - def __getattr__(self, name): - try: - return self[name] - except KeyError: - if name.startswith("__"): - raise AttributeError(name) - return "" - - def __add__(self, other) -> "ParseResults": - ret = self.copy() - ret += other - return ret - - def __iadd__(self, other) -> "ParseResults": - if other._tokdict: - offset = len(self._toklist) - addoffset = lambda a: offset if a < 0 else a + offset - otheritems = other._tokdict.items() - otherdictitems = [ - (k, _ParseResultsWithOffset(v[0], addoffset(v[1]))) - for k, vlist in otheritems - for v in vlist - ] - for k, v in otherdictitems: - self[k] = v - if isinstance(v[0], ParseResults): - v[0]._parent = wkref(self) - - self._toklist += other._toklist - self._all_names |= other._all_names - return self - - def __radd__(self, other) -> "ParseResults": - if isinstance(other, int) and other == 0: - # useful for merging many ParseResults using sum() builtin - return self.copy() - else: - # this may raise a TypeError - so be it - return other + self - - def __repr__(self) -> str: - return "{}({!r}, {})".format(type(self).__name__, self._toklist, self.as_dict()) - - def __str__(self) -> str: - return ( - "[" - + ", ".join( - [ - str(i) if isinstance(i, ParseResults) else repr(i) - for i in self._toklist - ] - ) - + "]" - ) - - def _asStringList(self, sep=""): - out = [] - for item in self._toklist: - if out and sep: - out.append(sep) - if isinstance(item, ParseResults): - out += item._asStringList() - else: - out.append(str(item)) - return out - - def as_list(self) -> list: - """ - Returns the parse results as a nested list of matching tokens, all converted to strings. - - Example:: - - patt = Word(alphas)[1, ...] - result = patt.parse_string("sldkj lsdkj sldkj") - # even though the result prints in string-like form, it is actually a pyparsing ParseResults - print(type(result), result) # -> ['sldkj', 'lsdkj', 'sldkj'] - - # Use as_list() to create an actual list - result_list = result.as_list() - print(type(result_list), result_list) # -> ['sldkj', 'lsdkj', 'sldkj'] - """ - return [ - res.as_list() if isinstance(res, ParseResults) else res - for res in self._toklist - ] - - def as_dict(self) -> dict: - """ - Returns the named parse results as a nested dictionary. - - Example:: - - integer = Word(nums) - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - result = date_str.parse_string('12/31/1999') - print(type(result), repr(result)) # -> (['12', '/', '31', '/', '1999'], {'day': [('1999', 4)], 'year': [('12', 0)], 'month': [('31', 2)]}) - - result_dict = result.as_dict() - print(type(result_dict), repr(result_dict)) # -> {'day': '1999', 'year': '12', 'month': '31'} - - # even though a ParseResults supports dict-like access, sometime you just need to have a dict - import json - print(json.dumps(result)) # -> Exception: TypeError: ... is not JSON serializable - print(json.dumps(result.as_dict())) # -> {"month": "31", "day": "1999", "year": "12"} - """ - - def to_item(obj): - if isinstance(obj, ParseResults): - return obj.as_dict() if obj.haskeys() else [to_item(v) for v in obj] - else: - return obj - - return dict((k, to_item(v)) for k, v in self.items()) - - def copy(self) -> "ParseResults": - """ - Returns a new copy of a :class:`ParseResults` object. - """ - ret = ParseResults(self._toklist) - ret._tokdict = self._tokdict.copy() - ret._parent = self._parent - ret._all_names |= self._all_names - ret._name = self._name - return ret - - def get_name(self): - r""" - Returns the results name for this token expression. Useful when several - different expressions might match at a particular location. - - Example:: - - integer = Word(nums) - ssn_expr = Regex(r"\d\d\d-\d\d-\d\d\d\d") - house_number_expr = Suppress('#') + Word(nums, alphanums) - user_data = (Group(house_number_expr)("house_number") - | Group(ssn_expr)("ssn") - | Group(integer)("age")) - user_info = user_data[1, ...] - - result = user_info.parse_string("22 111-22-3333 #221B") - for item in result: - print(item.get_name(), ':', item[0]) - - prints:: - - age : 22 - ssn : 111-22-3333 - house_number : 221B - """ - if self._name: - return self._name - elif self._parent: - par = self._parent() - - def find_in_parent(sub): - return next( - ( - k - for k, vlist in par._tokdict.items() - for v, loc in vlist - if sub is v - ), - None, - ) - - return find_in_parent(self) if par else None - elif ( - len(self) == 1 - and len(self._tokdict) == 1 - and next(iter(self._tokdict.values()))[0][1] in (0, -1) - ): - return next(iter(self._tokdict.keys())) - else: - return None - - def dump(self, indent="", full=True, include_list=True, _depth=0) -> str: - """ - Diagnostic method for listing out the contents of - a :class:`ParseResults`. Accepts an optional ``indent`` argument so - that this string can be embedded in a nested display of other data. - - Example:: - - integer = Word(nums) - date_str = integer("year") + '/' + integer("month") + '/' + integer("day") - - result = date_str.parse_string('1999/12/31') - print(result.dump()) - - prints:: - - ['1999', '/', '12', '/', '31'] - - day: '31' - - month: '12' - - year: '1999' - """ - out = [] - NL = "\n" - out.append(indent + str(self.as_list()) if include_list else "") - - if full: - if self.haskeys(): - items = sorted((str(k), v) for k, v in self.items()) - for k, v in items: - if out: - out.append(NL) - out.append("{}{}- {}: ".format(indent, (" " * _depth), k)) - if isinstance(v, ParseResults): - if v: - out.append( - v.dump( - indent=indent, - full=full, - include_list=include_list, - _depth=_depth + 1, - ) - ) - else: - out.append(str(v)) - else: - out.append(repr(v)) - if any(isinstance(vv, ParseResults) for vv in self): - v = self - for i, vv in enumerate(v): - if isinstance(vv, ParseResults): - out.append( - "\n{}{}[{}]:\n{}{}{}".format( - indent, - (" " * (_depth)), - i, - indent, - (" " * (_depth + 1)), - vv.dump( - indent=indent, - full=full, - include_list=include_list, - _depth=_depth + 1, - ), - ) - ) - else: - out.append( - "\n%s%s[%d]:\n%s%s%s" - % ( - indent, - (" " * (_depth)), - i, - indent, - (" " * (_depth + 1)), - str(vv), - ) - ) - - return "".join(out) - - def pprint(self, *args, **kwargs): - """ - Pretty-printer for parsed results as a list, using the - `pprint `_ module. - Accepts additional positional or keyword args as defined for - `pprint.pprint `_ . - - Example:: - - ident = Word(alphas, alphanums) - num = Word(nums) - func = Forward() - term = ident | num | Group('(' + func + ')') - func <<= ident + Group(Optional(delimited_list(term))) - result = func.parse_string("fna a,b,(fnb c,d,200),100") - result.pprint(width=40) - - prints:: - - ['fna', - ['a', - 'b', - ['(', 'fnb', ['c', 'd', '200'], ')'], - '100']] - """ - pprint.pprint(self.as_list(), *args, **kwargs) - - # add support for pickle protocol - def __getstate__(self): - return ( - self._toklist, - ( - self._tokdict.copy(), - self._parent is not None and self._parent() or None, - self._all_names, - self._name, - ), - ) - - def __setstate__(self, state): - self._toklist, (self._tokdict, par, inAccumNames, self._name) = state - self._all_names = set(inAccumNames) - if par is not None: - self._parent = wkref(par) - else: - self._parent = None - - def __getnewargs__(self): - return self._toklist, self._name - - def __dir__(self): - return dir(type(self)) + list(self.keys()) - - @classmethod - def from_dict(cls, other, name=None) -> "ParseResults": - """ - Helper classmethod to construct a ``ParseResults`` from a ``dict``, preserving the - name-value relations as results names. If an optional ``name`` argument is - given, a nested ``ParseResults`` will be returned. - """ - - def is_iterable(obj): - try: - iter(obj) - except Exception: - return False - else: - return not isinstance(obj, str_type) - - ret = cls([]) - for k, v in other.items(): - if isinstance(v, Mapping): - ret += cls.from_dict(v, name=k) - else: - ret += cls([v], name=k, asList=is_iterable(v)) - if name is not None: - ret = cls([ret], name=name) - return ret - - asList = as_list - asDict = as_dict - getName = get_name - - -MutableMapping.register(ParseResults) -MutableSequence.register(ParseResults) diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/testing.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/testing.py deleted file mode 100755 index 84a0ef1..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/testing.py +++ /dev/null @@ -1,331 +0,0 @@ -# testing.py - -from contextlib import contextmanager -import typing - -from .core import ( - ParserElement, - ParseException, - Keyword, - __diag__, - __compat__, -) - - -class pyparsing_test: - """ - namespace class for classes useful in writing unit tests - """ - - class reset_pyparsing_context: - """ - Context manager to be used when writing unit tests that modify pyparsing config values: - - packrat parsing - - bounded recursion parsing - - default whitespace characters. - - default keyword characters - - literal string auto-conversion class - - __diag__ settings - - Example:: - - with reset_pyparsing_context(): - # test that literals used to construct a grammar are automatically suppressed - ParserElement.inlineLiteralsUsing(Suppress) - - term = Word(alphas) | Word(nums) - group = Group('(' + term[...] + ')') - - # assert that the '()' characters are not included in the parsed tokens - self.assertParseAndCheckList(group, "(abc 123 def)", ['abc', '123', 'def']) - - # after exiting context manager, literals are converted to Literal expressions again - """ - - def __init__(self): - self._save_context = {} - - def save(self): - self._save_context["default_whitespace"] = ParserElement.DEFAULT_WHITE_CHARS - self._save_context["default_keyword_chars"] = Keyword.DEFAULT_KEYWORD_CHARS - - self._save_context[ - "literal_string_class" - ] = ParserElement._literalStringClass - - self._save_context["verbose_stacktrace"] = ParserElement.verbose_stacktrace - - self._save_context["packrat_enabled"] = ParserElement._packratEnabled - if ParserElement._packratEnabled: - self._save_context[ - "packrat_cache_size" - ] = ParserElement.packrat_cache.size - else: - self._save_context["packrat_cache_size"] = None - self._save_context["packrat_parse"] = ParserElement._parse - self._save_context[ - "recursion_enabled" - ] = ParserElement._left_recursion_enabled - - self._save_context["__diag__"] = { - name: getattr(__diag__, name) for name in __diag__._all_names - } - - self._save_context["__compat__"] = { - "collect_all_And_tokens": __compat__.collect_all_And_tokens - } - - return self - - def restore(self): - # reset pyparsing global state - if ( - ParserElement.DEFAULT_WHITE_CHARS - != self._save_context["default_whitespace"] - ): - ParserElement.set_default_whitespace_chars( - self._save_context["default_whitespace"] - ) - - ParserElement.verbose_stacktrace = self._save_context["verbose_stacktrace"] - - Keyword.DEFAULT_KEYWORD_CHARS = self._save_context["default_keyword_chars"] - ParserElement.inlineLiteralsUsing( - self._save_context["literal_string_class"] - ) - - for name, value in self._save_context["__diag__"].items(): - (__diag__.enable if value else __diag__.disable)(name) - - ParserElement._packratEnabled = False - if self._save_context["packrat_enabled"]: - ParserElement.enable_packrat(self._save_context["packrat_cache_size"]) - else: - ParserElement._parse = self._save_context["packrat_parse"] - ParserElement._left_recursion_enabled = self._save_context[ - "recursion_enabled" - ] - - __compat__.collect_all_And_tokens = self._save_context["__compat__"] - - return self - - def copy(self): - ret = type(self)() - ret._save_context.update(self._save_context) - return ret - - def __enter__(self): - return self.save() - - def __exit__(self, *args): - self.restore() - - class TestParseResultsAsserts: - """ - A mixin class to add parse results assertion methods to normal unittest.TestCase classes. - """ - - def assertParseResultsEquals( - self, result, expected_list=None, expected_dict=None, msg=None - ): - """ - Unit test assertion to compare a :class:`ParseResults` object with an optional ``expected_list``, - and compare any defined results names with an optional ``expected_dict``. - """ - if expected_list is not None: - self.assertEqual(expected_list, result.as_list(), msg=msg) - if expected_dict is not None: - self.assertEqual(expected_dict, result.as_dict(), msg=msg) - - def assertParseAndCheckList( - self, expr, test_string, expected_list, msg=None, verbose=True - ): - """ - Convenience wrapper assert to test a parser element and input string, and assert that - the resulting ``ParseResults.asList()`` is equal to the ``expected_list``. - """ - result = expr.parse_string(test_string, parse_all=True) - if verbose: - print(result.dump()) - else: - print(result.as_list()) - self.assertParseResultsEquals(result, expected_list=expected_list, msg=msg) - - def assertParseAndCheckDict( - self, expr, test_string, expected_dict, msg=None, verbose=True - ): - """ - Convenience wrapper assert to test a parser element and input string, and assert that - the resulting ``ParseResults.asDict()`` is equal to the ``expected_dict``. - """ - result = expr.parse_string(test_string, parseAll=True) - if verbose: - print(result.dump()) - else: - print(result.as_list()) - self.assertParseResultsEquals(result, expected_dict=expected_dict, msg=msg) - - def assertRunTestResults( - self, run_tests_report, expected_parse_results=None, msg=None - ): - """ - Unit test assertion to evaluate output of ``ParserElement.runTests()``. If a list of - list-dict tuples is given as the ``expected_parse_results`` argument, then these are zipped - with the report tuples returned by ``runTests`` and evaluated using ``assertParseResultsEquals``. - Finally, asserts that the overall ``runTests()`` success value is ``True``. - - :param run_tests_report: tuple(bool, [tuple(str, ParseResults or Exception)]) returned from runTests - :param expected_parse_results (optional): [tuple(str, list, dict, Exception)] - """ - run_test_success, run_test_results = run_tests_report - - if expected_parse_results is not None: - merged = [ - (*rpt, expected) - for rpt, expected in zip(run_test_results, expected_parse_results) - ] - for test_string, result, expected in merged: - # expected should be a tuple containing a list and/or a dict or an exception, - # and optional failure message string - # an empty tuple will skip any result validation - fail_msg = next( - (exp for exp in expected if isinstance(exp, str)), None - ) - expected_exception = next( - ( - exp - for exp in expected - if isinstance(exp, type) and issubclass(exp, Exception) - ), - None, - ) - if expected_exception is not None: - with self.assertRaises( - expected_exception=expected_exception, msg=fail_msg or msg - ): - if isinstance(result, Exception): - raise result - else: - expected_list = next( - (exp for exp in expected if isinstance(exp, list)), None - ) - expected_dict = next( - (exp for exp in expected if isinstance(exp, dict)), None - ) - if (expected_list, expected_dict) != (None, None): - self.assertParseResultsEquals( - result, - expected_list=expected_list, - expected_dict=expected_dict, - msg=fail_msg or msg, - ) - else: - # warning here maybe? - print("no validation for {!r}".format(test_string)) - - # do this last, in case some specific test results can be reported instead - self.assertTrue( - run_test_success, msg=msg if msg is not None else "failed runTests" - ) - - @contextmanager - def assertRaisesParseException(self, exc_type=ParseException, msg=None): - with self.assertRaises(exc_type, msg=msg): - yield - - @staticmethod - def with_line_numbers( - s: str, - start_line: typing.Optional[int] = None, - end_line: typing.Optional[int] = None, - expand_tabs: bool = True, - eol_mark: str = "|", - mark_spaces: typing.Optional[str] = None, - mark_control: typing.Optional[str] = None, - ) -> str: - """ - Helpful method for debugging a parser - prints a string with line and column numbers. - (Line and column numbers are 1-based.) - - :param s: tuple(bool, str - string to be printed with line and column numbers - :param start_line: int - (optional) starting line number in s to print (default=1) - :param end_line: int - (optional) ending line number in s to print (default=len(s)) - :param expand_tabs: bool - (optional) expand tabs to spaces, to match the pyparsing default - :param eol_mark: str - (optional) string to mark the end of lines, helps visualize trailing spaces (default="|") - :param mark_spaces: str - (optional) special character to display in place of spaces - :param mark_control: str - (optional) convert non-printing control characters to a placeholding - character; valid values: - - "unicode" - replaces control chars with Unicode symbols, such as "␍" and "␊" - - any single character string - replace control characters with given string - - None (default) - string is displayed as-is - - :return: str - input string with leading line numbers and column number headers - """ - if expand_tabs: - s = s.expandtabs() - if mark_control is not None: - if mark_control == "unicode": - tbl = str.maketrans( - {c: u for c, u in zip(range(0, 33), range(0x2400, 0x2433))} - | {127: 0x2421} - ) - eol_mark = "" - else: - tbl = str.maketrans( - {c: mark_control for c in list(range(0, 32)) + [127]} - ) - s = s.translate(tbl) - if mark_spaces is not None and mark_spaces != " ": - if mark_spaces == "unicode": - tbl = str.maketrans({9: 0x2409, 32: 0x2423}) - s = s.translate(tbl) - else: - s = s.replace(" ", mark_spaces) - if start_line is None: - start_line = 1 - if end_line is None: - end_line = len(s) - end_line = min(end_line, len(s)) - start_line = min(max(1, start_line), end_line) - - if mark_control != "unicode": - s_lines = s.splitlines()[start_line - 1 : end_line] - else: - s_lines = [line + "␊" for line in s.split("␊")[start_line - 1 : end_line]] - if not s_lines: - return "" - - lineno_width = len(str(end_line)) - max_line_len = max(len(line) for line in s_lines) - lead = " " * (lineno_width + 1) - if max_line_len >= 99: - header0 = ( - lead - + "".join( - "{}{}".format(" " * 99, (i + 1) % 100) - for i in range(max(max_line_len // 100, 1)) - ) - + "\n" - ) - else: - header0 = "" - header1 = ( - header0 - + lead - + "".join( - " {}".format((i + 1) % 10) - for i in range(-(-max_line_len // 10)) - ) - + "\n" - ) - header2 = lead + "1234567890" * (-(-max_line_len // 10)) + "\n" - return ( - header1 - + header2 - + "\n".join( - "{:{}d}:{}{}".format(i, lineno_width, line, eol_mark) - for i, line in enumerate(s_lines, start=start_line) - ) - + "\n" - ) diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/unicode.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/unicode.py deleted file mode 100755 index 0652620..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/unicode.py +++ /dev/null @@ -1,352 +0,0 @@ -# unicode.py - -import sys -from itertools import filterfalse -from typing import List, Tuple, Union - - -class _lazyclassproperty: - def __init__(self, fn): - self.fn = fn - self.__doc__ = fn.__doc__ - self.__name__ = fn.__name__ - - def __get__(self, obj, cls): - if cls is None: - cls = type(obj) - if not hasattr(cls, "_intern") or any( - cls._intern is getattr(superclass, "_intern", []) - for superclass in cls.__mro__[1:] - ): - cls._intern = {} - attrname = self.fn.__name__ - if attrname not in cls._intern: - cls._intern[attrname] = self.fn(cls) - return cls._intern[attrname] - - -UnicodeRangeList = List[Union[Tuple[int, int], Tuple[int]]] - - -class unicode_set: - """ - A set of Unicode characters, for language-specific strings for - ``alphas``, ``nums``, ``alphanums``, and ``printables``. - A unicode_set is defined by a list of ranges in the Unicode character - set, in a class attribute ``_ranges``. Ranges can be specified using - 2-tuples or a 1-tuple, such as:: - - _ranges = [ - (0x0020, 0x007e), - (0x00a0, 0x00ff), - (0x0100,), - ] - - Ranges are left- and right-inclusive. A 1-tuple of (x,) is treated as (x, x). - - A unicode set can also be defined using multiple inheritance of other unicode sets:: - - class CJK(Chinese, Japanese, Korean): - pass - """ - - _ranges: UnicodeRangeList = [] - - @_lazyclassproperty - def _chars_for_ranges(cls): - ret = [] - for cc in cls.__mro__: - if cc is unicode_set: - break - for rr in getattr(cc, "_ranges", ()): - ret.extend(range(rr[0], rr[-1] + 1)) - return [chr(c) for c in sorted(set(ret))] - - @_lazyclassproperty - def printables(cls): - "all non-whitespace characters in this range" - return "".join(filterfalse(str.isspace, cls._chars_for_ranges)) - - @_lazyclassproperty - def alphas(cls): - "all alphabetic characters in this range" - return "".join(filter(str.isalpha, cls._chars_for_ranges)) - - @_lazyclassproperty - def nums(cls): - "all numeric digit characters in this range" - return "".join(filter(str.isdigit, cls._chars_for_ranges)) - - @_lazyclassproperty - def alphanums(cls): - "all alphanumeric characters in this range" - return cls.alphas + cls.nums - - @_lazyclassproperty - def identchars(cls): - "all characters in this range that are valid identifier characters, plus underscore '_'" - return "".join( - sorted( - set( - "".join(filter(str.isidentifier, cls._chars_for_ranges)) - + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµº" - + "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ" - + "_" - ) - ) - ) - - @_lazyclassproperty - def identbodychars(cls): - """ - all characters in this range that are valid identifier body characters, - plus the digits 0-9 - """ - return "".join( - sorted( - set( - cls.identchars - + "0123456789" - + "".join( - [c for c in cls._chars_for_ranges if ("_" + c).isidentifier()] - ) - ) - ) - ) - - -class pyparsing_unicode(unicode_set): - """ - A namespace class for defining common language unicode_sets. - """ - - # fmt: off - - # define ranges in language character sets - _ranges: UnicodeRangeList = [ - (0x0020, sys.maxunicode), - ] - - class BasicMultilingualPlane(unicode_set): - "Unicode set for the Basic Multilingual Plane" - _ranges: UnicodeRangeList = [ - (0x0020, 0xFFFF), - ] - - class Latin1(unicode_set): - "Unicode set for Latin-1 Unicode Character Range" - _ranges: UnicodeRangeList = [ - (0x0020, 0x007E), - (0x00A0, 0x00FF), - ] - - class LatinA(unicode_set): - "Unicode set for Latin-A Unicode Character Range" - _ranges: UnicodeRangeList = [ - (0x0100, 0x017F), - ] - - class LatinB(unicode_set): - "Unicode set for Latin-B Unicode Character Range" - _ranges: UnicodeRangeList = [ - (0x0180, 0x024F), - ] - - class Greek(unicode_set): - "Unicode set for Greek Unicode Character Ranges" - _ranges: UnicodeRangeList = [ - (0x0342, 0x0345), - (0x0370, 0x0377), - (0x037A, 0x037F), - (0x0384, 0x038A), - (0x038C,), - (0x038E, 0x03A1), - (0x03A3, 0x03E1), - (0x03F0, 0x03FF), - (0x1D26, 0x1D2A), - (0x1D5E,), - (0x1D60,), - (0x1D66, 0x1D6A), - (0x1F00, 0x1F15), - (0x1F18, 0x1F1D), - (0x1F20, 0x1F45), - (0x1F48, 0x1F4D), - (0x1F50, 0x1F57), - (0x1F59,), - (0x1F5B,), - (0x1F5D,), - (0x1F5F, 0x1F7D), - (0x1F80, 0x1FB4), - (0x1FB6, 0x1FC4), - (0x1FC6, 0x1FD3), - (0x1FD6, 0x1FDB), - (0x1FDD, 0x1FEF), - (0x1FF2, 0x1FF4), - (0x1FF6, 0x1FFE), - (0x2129,), - (0x2719, 0x271A), - (0xAB65,), - (0x10140, 0x1018D), - (0x101A0,), - (0x1D200, 0x1D245), - (0x1F7A1, 0x1F7A7), - ] - - class Cyrillic(unicode_set): - "Unicode set for Cyrillic Unicode Character Range" - _ranges: UnicodeRangeList = [ - (0x0400, 0x052F), - (0x1C80, 0x1C88), - (0x1D2B,), - (0x1D78,), - (0x2DE0, 0x2DFF), - (0xA640, 0xA672), - (0xA674, 0xA69F), - (0xFE2E, 0xFE2F), - ] - - class Chinese(unicode_set): - "Unicode set for Chinese Unicode Character Range" - _ranges: UnicodeRangeList = [ - (0x2E80, 0x2E99), - (0x2E9B, 0x2EF3), - (0x31C0, 0x31E3), - (0x3400, 0x4DB5), - (0x4E00, 0x9FEF), - (0xA700, 0xA707), - (0xF900, 0xFA6D), - (0xFA70, 0xFAD9), - (0x16FE2, 0x16FE3), - (0x1F210, 0x1F212), - (0x1F214, 0x1F23B), - (0x1F240, 0x1F248), - (0x20000, 0x2A6D6), - (0x2A700, 0x2B734), - (0x2B740, 0x2B81D), - (0x2B820, 0x2CEA1), - (0x2CEB0, 0x2EBE0), - (0x2F800, 0x2FA1D), - ] - - class Japanese(unicode_set): - "Unicode set for Japanese Unicode Character Range, combining Kanji, Hiragana, and Katakana ranges" - _ranges: UnicodeRangeList = [] - - class Kanji(unicode_set): - "Unicode set for Kanji Unicode Character Range" - _ranges: UnicodeRangeList = [ - (0x4E00, 0x9FBF), - (0x3000, 0x303F), - ] - - class Hiragana(unicode_set): - "Unicode set for Hiragana Unicode Character Range" - _ranges: UnicodeRangeList = [ - (0x3041, 0x3096), - (0x3099, 0x30A0), - (0x30FC,), - (0xFF70,), - (0x1B001,), - (0x1B150, 0x1B152), - (0x1F200,), - ] - - class Katakana(unicode_set): - "Unicode set for Katakana Unicode Character Range" - _ranges: UnicodeRangeList = [ - (0x3099, 0x309C), - (0x30A0, 0x30FF), - (0x31F0, 0x31FF), - (0x32D0, 0x32FE), - (0xFF65, 0xFF9F), - (0x1B000,), - (0x1B164, 0x1B167), - (0x1F201, 0x1F202), - (0x1F213,), - ] - - class Hangul(unicode_set): - "Unicode set for Hangul (Korean) Unicode Character Range" - _ranges: UnicodeRangeList = [ - (0x1100, 0x11FF), - (0x302E, 0x302F), - (0x3131, 0x318E), - (0x3200, 0x321C), - (0x3260, 0x327B), - (0x327E,), - (0xA960, 0xA97C), - (0xAC00, 0xD7A3), - (0xD7B0, 0xD7C6), - (0xD7CB, 0xD7FB), - (0xFFA0, 0xFFBE), - (0xFFC2, 0xFFC7), - (0xFFCA, 0xFFCF), - (0xFFD2, 0xFFD7), - (0xFFDA, 0xFFDC), - ] - - Korean = Hangul - - class CJK(Chinese, Japanese, Hangul): - "Unicode set for combined Chinese, Japanese, and Korean (CJK) Unicode Character Range" - - class Thai(unicode_set): - "Unicode set for Thai Unicode Character Range" - _ranges: UnicodeRangeList = [ - (0x0E01, 0x0E3A), - (0x0E3F, 0x0E5B) - ] - - class Arabic(unicode_set): - "Unicode set for Arabic Unicode Character Range" - _ranges: UnicodeRangeList = [ - (0x0600, 0x061B), - (0x061E, 0x06FF), - (0x0700, 0x077F), - ] - - class Hebrew(unicode_set): - "Unicode set for Hebrew Unicode Character Range" - _ranges: UnicodeRangeList = [ - (0x0591, 0x05C7), - (0x05D0, 0x05EA), - (0x05EF, 0x05F4), - (0xFB1D, 0xFB36), - (0xFB38, 0xFB3C), - (0xFB3E,), - (0xFB40, 0xFB41), - (0xFB43, 0xFB44), - (0xFB46, 0xFB4F), - ] - - class Devanagari(unicode_set): - "Unicode set for Devanagari Unicode Character Range" - _ranges: UnicodeRangeList = [ - (0x0900, 0x097F), - (0xA8E0, 0xA8FF) - ] - - # fmt: on - - -pyparsing_unicode.Japanese._ranges = ( - pyparsing_unicode.Japanese.Kanji._ranges - + pyparsing_unicode.Japanese.Hiragana._ranges - + pyparsing_unicode.Japanese.Katakana._ranges -) - -pyparsing_unicode.BMP = pyparsing_unicode.BasicMultilingualPlane - -# add language identifiers using language Unicode -pyparsing_unicode.العربية = pyparsing_unicode.Arabic -pyparsing_unicode.中文 = pyparsing_unicode.Chinese -pyparsing_unicode.кириллица = pyparsing_unicode.Cyrillic -pyparsing_unicode.Ελληνικά = pyparsing_unicode.Greek -pyparsing_unicode.עִברִית = pyparsing_unicode.Hebrew -pyparsing_unicode.日本語 = pyparsing_unicode.Japanese -pyparsing_unicode.Japanese.漢字 = pyparsing_unicode.Japanese.Kanji -pyparsing_unicode.Japanese.カタカナ = pyparsing_unicode.Japanese.Katakana -pyparsing_unicode.Japanese.ひらがな = pyparsing_unicode.Japanese.Hiragana -pyparsing_unicode.한국어 = pyparsing_unicode.Korean -pyparsing_unicode.ไทย = pyparsing_unicode.Thai -pyparsing_unicode.देवनागरी = pyparsing_unicode.Devanagari diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/util.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/util.py deleted file mode 100755 index 34ce092..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/pyparsing/util.py +++ /dev/null @@ -1,235 +0,0 @@ -# util.py -import warnings -import types -import collections -import itertools -from functools import lru_cache -from typing import List, Union, Iterable - -_bslash = chr(92) - - -class __config_flags: - """Internal class for defining compatibility and debugging flags""" - - _all_names: List[str] = [] - _fixed_names: List[str] = [] - _type_desc = "configuration" - - @classmethod - def _set(cls, dname, value): - if dname in cls._fixed_names: - warnings.warn( - "{}.{} {} is {} and cannot be overridden".format( - cls.__name__, - dname, - cls._type_desc, - str(getattr(cls, dname)).upper(), - ) - ) - return - if dname in cls._all_names: - setattr(cls, dname, value) - else: - raise ValueError("no such {} {!r}".format(cls._type_desc, dname)) - - enable = classmethod(lambda cls, name: cls._set(name, True)) - disable = classmethod(lambda cls, name: cls._set(name, False)) - - -@lru_cache(maxsize=128) -def col(loc: int, strg: str) -> int: - """ - Returns current column within a string, counting newlines as line separators. - The first column is number 1. - - Note: the default parsing behavior is to expand tabs in the input string - before starting the parsing process. See - :class:`ParserElement.parseString` for more - information on parsing strings containing ```` s, and suggested - methods to maintain a consistent view of the parsed string, the parse - location, and line and column positions within the parsed string. - """ - s = strg - return 1 if 0 < loc < len(s) and s[loc - 1] == "\n" else loc - s.rfind("\n", 0, loc) - - -@lru_cache(maxsize=128) -def lineno(loc: int, strg: str) -> int: - """Returns current line number within a string, counting newlines as line separators. - The first line is number 1. - - Note - the default parsing behavior is to expand tabs in the input string - before starting the parsing process. See :class:`ParserElement.parseString` - for more information on parsing strings containing ```` s, and - suggested methods to maintain a consistent view of the parsed string, the - parse location, and line and column positions within the parsed string. - """ - return strg.count("\n", 0, loc) + 1 - - -@lru_cache(maxsize=128) -def line(loc: int, strg: str) -> str: - """ - Returns the line of text containing loc within a string, counting newlines as line separators. - """ - last_cr = strg.rfind("\n", 0, loc) - next_cr = strg.find("\n", loc) - return strg[last_cr + 1 : next_cr] if next_cr >= 0 else strg[last_cr + 1 :] - - -class _UnboundedCache: - def __init__(self): - cache = {} - cache_get = cache.get - self.not_in_cache = not_in_cache = object() - - def get(_, key): - return cache_get(key, not_in_cache) - - def set_(_, key, value): - cache[key] = value - - def clear(_): - cache.clear() - - self.size = None - self.get = types.MethodType(get, self) - self.set = types.MethodType(set_, self) - self.clear = types.MethodType(clear, self) - - -class _FifoCache: - def __init__(self, size): - self.not_in_cache = not_in_cache = object() - cache = collections.OrderedDict() - cache_get = cache.get - - def get(_, key): - return cache_get(key, not_in_cache) - - def set_(_, key, value): - cache[key] = value - while len(cache) > size: - cache.popitem(last=False) - - def clear(_): - cache.clear() - - self.size = size - self.get = types.MethodType(get, self) - self.set = types.MethodType(set_, self) - self.clear = types.MethodType(clear, self) - - -class LRUMemo: - """ - A memoizing mapping that retains `capacity` deleted items - - The memo tracks retained items by their access order; once `capacity` items - are retained, the least recently used item is discarded. - """ - - def __init__(self, capacity): - self._capacity = capacity - self._active = {} - self._memory = collections.OrderedDict() - - def __getitem__(self, key): - try: - return self._active[key] - except KeyError: - self._memory.move_to_end(key) - return self._memory[key] - - def __setitem__(self, key, value): - self._memory.pop(key, None) - self._active[key] = value - - def __delitem__(self, key): - try: - value = self._active.pop(key) - except KeyError: - pass - else: - while len(self._memory) >= self._capacity: - self._memory.popitem(last=False) - self._memory[key] = value - - def clear(self): - self._active.clear() - self._memory.clear() - - -class UnboundedMemo(dict): - """ - A memoizing mapping that retains all deleted items - """ - - def __delitem__(self, key): - pass - - -def _escape_regex_range_chars(s: str) -> str: - # escape these chars: ^-[] - for c in r"\^-[]": - s = s.replace(c, _bslash + c) - s = s.replace("\n", r"\n") - s = s.replace("\t", r"\t") - return str(s) - - -def _collapse_string_to_ranges( - s: Union[str, Iterable[str]], re_escape: bool = True -) -> str: - def is_consecutive(c): - c_int = ord(c) - is_consecutive.prev, prev = c_int, is_consecutive.prev - if c_int - prev > 1: - is_consecutive.value = next(is_consecutive.counter) - return is_consecutive.value - - is_consecutive.prev = 0 - is_consecutive.counter = itertools.count() - is_consecutive.value = -1 - - def escape_re_range_char(c): - return "\\" + c if c in r"\^-][" else c - - def no_escape_re_range_char(c): - return c - - if not re_escape: - escape_re_range_char = no_escape_re_range_char - - ret = [] - s = "".join(sorted(set(s))) - if len(s) > 3: - for _, chars in itertools.groupby(s, key=is_consecutive): - first = last = next(chars) - last = collections.deque( - itertools.chain(iter([last]), chars), maxlen=1 - ).pop() - if first == last: - ret.append(escape_re_range_char(first)) - else: - sep = "" if ord(last) == ord(first) + 1 else "-" - ret.append( - "{}{}{}".format( - escape_re_range_char(first), sep, escape_re_range_char(last) - ) - ) - else: - ret = [escape_re_range_char(c) for c in s] - - return "".join(ret) - - -def _flatten(ll: list) -> list: - ret = [] - for i in ll: - if isinstance(i, list): - ret.extend(_flatten(i)) - else: - ret.append(i) - return ret diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/typing_extensions.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/typing_extensions.py deleted file mode 100755 index ef42417..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/typing_extensions.py +++ /dev/null @@ -1,2209 +0,0 @@ -import abc -import collections -import collections.abc -import functools -import operator -import sys -import types as _types -import typing - - -__all__ = [ - # Super-special typing primitives. - 'Any', - 'ClassVar', - 'Concatenate', - 'Final', - 'LiteralString', - 'ParamSpec', - 'ParamSpecArgs', - 'ParamSpecKwargs', - 'Self', - 'Type', - 'TypeVar', - 'TypeVarTuple', - 'Unpack', - - # ABCs (from collections.abc). - 'Awaitable', - 'AsyncIterator', - 'AsyncIterable', - 'Coroutine', - 'AsyncGenerator', - 'AsyncContextManager', - 'ChainMap', - - # Concrete collection types. - 'ContextManager', - 'Counter', - 'Deque', - 'DefaultDict', - 'NamedTuple', - 'OrderedDict', - 'TypedDict', - - # Structural checks, a.k.a. protocols. - 'SupportsIndex', - - # One-off things. - 'Annotated', - 'assert_never', - 'assert_type', - 'clear_overloads', - 'dataclass_transform', - 'get_overloads', - 'final', - 'get_args', - 'get_origin', - 'get_type_hints', - 'IntVar', - 'is_typeddict', - 'Literal', - 'NewType', - 'overload', - 'override', - 'Protocol', - 'reveal_type', - 'runtime', - 'runtime_checkable', - 'Text', - 'TypeAlias', - 'TypeGuard', - 'TYPE_CHECKING', - 'Never', - 'NoReturn', - 'Required', - 'NotRequired', -] - -# for backward compatibility -PEP_560 = True -GenericMeta = type - -# The functions below are modified copies of typing internal helpers. -# They are needed by _ProtocolMeta and they provide support for PEP 646. - -_marker = object() - - -def _check_generic(cls, parameters, elen=_marker): - """Check correct count for parameters of a generic cls (internal helper). - This gives a nice error message in case of count mismatch. - """ - if not elen: - raise TypeError(f"{cls} is not a generic class") - if elen is _marker: - if not hasattr(cls, "__parameters__") or not cls.__parameters__: - raise TypeError(f"{cls} is not a generic class") - elen = len(cls.__parameters__) - alen = len(parameters) - if alen != elen: - if hasattr(cls, "__parameters__"): - parameters = [p for p in cls.__parameters__ if not _is_unpack(p)] - num_tv_tuples = sum(isinstance(p, TypeVarTuple) for p in parameters) - if (num_tv_tuples > 0) and (alen >= elen - num_tv_tuples): - return - raise TypeError(f"Too {'many' if alen > elen else 'few'} parameters for {cls};" - f" actual {alen}, expected {elen}") - - -if sys.version_info >= (3, 10): - def _should_collect_from_parameters(t): - return isinstance( - t, (typing._GenericAlias, _types.GenericAlias, _types.UnionType) - ) -elif sys.version_info >= (3, 9): - def _should_collect_from_parameters(t): - return isinstance(t, (typing._GenericAlias, _types.GenericAlias)) -else: - def _should_collect_from_parameters(t): - return isinstance(t, typing._GenericAlias) and not t._special - - -def _collect_type_vars(types, typevar_types=None): - """Collect all type variable contained in types in order of - first appearance (lexicographic order). For example:: - - _collect_type_vars((T, List[S, T])) == (T, S) - """ - if typevar_types is None: - typevar_types = typing.TypeVar - tvars = [] - for t in types: - if ( - isinstance(t, typevar_types) and - t not in tvars and - not _is_unpack(t) - ): - tvars.append(t) - if _should_collect_from_parameters(t): - tvars.extend([t for t in t.__parameters__ if t not in tvars]) - return tuple(tvars) - - -NoReturn = typing.NoReturn - -# Some unconstrained type variables. These are used by the container types. -# (These are not for export.) -T = typing.TypeVar('T') # Any type. -KT = typing.TypeVar('KT') # Key type. -VT = typing.TypeVar('VT') # Value type. -T_co = typing.TypeVar('T_co', covariant=True) # Any type covariant containers. -T_contra = typing.TypeVar('T_contra', contravariant=True) # Ditto contravariant. - - -if sys.version_info >= (3, 11): - from typing import Any -else: - - class _AnyMeta(type): - def __instancecheck__(self, obj): - if self is Any: - raise TypeError("typing_extensions.Any cannot be used with isinstance()") - return super().__instancecheck__(obj) - - def __repr__(self): - if self is Any: - return "typing_extensions.Any" - return super().__repr__() - - class Any(metaclass=_AnyMeta): - """Special type indicating an unconstrained type. - - Any is compatible with every type. - - Any assumed to have all methods. - - All values assumed to be instances of Any. - Note that all the above statements are true from the point of view of - static type checkers. At runtime, Any should not be used with instance - checks. - """ - def __new__(cls, *args, **kwargs): - if cls is Any: - raise TypeError("Any cannot be instantiated") - return super().__new__(cls, *args, **kwargs) - - -ClassVar = typing.ClassVar - -# On older versions of typing there is an internal class named "Final". -# 3.8+ -if hasattr(typing, 'Final') and sys.version_info[:2] >= (3, 7): - Final = typing.Final -# 3.7 -else: - class _FinalForm(typing._SpecialForm, _root=True): - - def __repr__(self): - return 'typing_extensions.' + self._name - - def __getitem__(self, parameters): - item = typing._type_check(parameters, - f'{self._name} accepts only a single type.') - return typing._GenericAlias(self, (item,)) - - Final = _FinalForm('Final', - doc="""A special typing construct to indicate that a name - cannot be re-assigned or overridden in a subclass. - For example: - - MAX_SIZE: Final = 9000 - MAX_SIZE += 1 # Error reported by type checker - - class Connection: - TIMEOUT: Final[int] = 10 - class FastConnector(Connection): - TIMEOUT = 1 # Error reported by type checker - - There is no runtime checking of these properties.""") - -if sys.version_info >= (3, 11): - final = typing.final -else: - # @final exists in 3.8+, but we backport it for all versions - # before 3.11 to keep support for the __final__ attribute. - # See https://bugs.python.org/issue46342 - def final(f): - """This decorator can be used to indicate to type checkers that - the decorated method cannot be overridden, and decorated class - cannot be subclassed. For example: - - class Base: - @final - def done(self) -> None: - ... - class Sub(Base): - def done(self) -> None: # Error reported by type checker - ... - @final - class Leaf: - ... - class Other(Leaf): # Error reported by type checker - ... - - There is no runtime checking of these properties. The decorator - sets the ``__final__`` attribute to ``True`` on the decorated object - to allow runtime introspection. - """ - try: - f.__final__ = True - except (AttributeError, TypeError): - # Skip the attribute silently if it is not writable. - # AttributeError happens if the object has __slots__ or a - # read-only property, TypeError if it's a builtin class. - pass - return f - - -def IntVar(name): - return typing.TypeVar(name) - - -# 3.8+: -if hasattr(typing, 'Literal'): - Literal = typing.Literal -# 3.7: -else: - class _LiteralForm(typing._SpecialForm, _root=True): - - def __repr__(self): - return 'typing_extensions.' + self._name - - def __getitem__(self, parameters): - return typing._GenericAlias(self, parameters) - - Literal = _LiteralForm('Literal', - doc="""A type that can be used to indicate to type checkers - that the corresponding value has a value literally equivalent - to the provided parameter. For example: - - var: Literal[4] = 4 - - The type checker understands that 'var' is literally equal to - the value 4 and no other value. - - Literal[...] cannot be subclassed. There is no runtime - checking verifying that the parameter is actually a value - instead of a type.""") - - -_overload_dummy = typing._overload_dummy # noqa - - -if hasattr(typing, "get_overloads"): # 3.11+ - overload = typing.overload - get_overloads = typing.get_overloads - clear_overloads = typing.clear_overloads -else: - # {module: {qualname: {firstlineno: func}}} - _overload_registry = collections.defaultdict( - functools.partial(collections.defaultdict, dict) - ) - - def overload(func): - """Decorator for overloaded functions/methods. - - In a stub file, place two or more stub definitions for the same - function in a row, each decorated with @overload. For example: - - @overload - def utf8(value: None) -> None: ... - @overload - def utf8(value: bytes) -> bytes: ... - @overload - def utf8(value: str) -> bytes: ... - - In a non-stub file (i.e. a regular .py file), do the same but - follow it with an implementation. The implementation should *not* - be decorated with @overload. For example: - - @overload - def utf8(value: None) -> None: ... - @overload - def utf8(value: bytes) -> bytes: ... - @overload - def utf8(value: str) -> bytes: ... - def utf8(value): - # implementation goes here - - The overloads for a function can be retrieved at runtime using the - get_overloads() function. - """ - # classmethod and staticmethod - f = getattr(func, "__func__", func) - try: - _overload_registry[f.__module__][f.__qualname__][ - f.__code__.co_firstlineno - ] = func - except AttributeError: - # Not a normal function; ignore. - pass - return _overload_dummy - - def get_overloads(func): - """Return all defined overloads for *func* as a sequence.""" - # classmethod and staticmethod - f = getattr(func, "__func__", func) - if f.__module__ not in _overload_registry: - return [] - mod_dict = _overload_registry[f.__module__] - if f.__qualname__ not in mod_dict: - return [] - return list(mod_dict[f.__qualname__].values()) - - def clear_overloads(): - """Clear all overloads in the registry.""" - _overload_registry.clear() - - -# This is not a real generic class. Don't use outside annotations. -Type = typing.Type - -# Various ABCs mimicking those in collections.abc. -# A few are simply re-exported for completeness. - - -Awaitable = typing.Awaitable -Coroutine = typing.Coroutine -AsyncIterable = typing.AsyncIterable -AsyncIterator = typing.AsyncIterator -Deque = typing.Deque -ContextManager = typing.ContextManager -AsyncContextManager = typing.AsyncContextManager -DefaultDict = typing.DefaultDict - -# 3.7.2+ -if hasattr(typing, 'OrderedDict'): - OrderedDict = typing.OrderedDict -# 3.7.0-3.7.2 -else: - OrderedDict = typing._alias(collections.OrderedDict, (KT, VT)) - -Counter = typing.Counter -ChainMap = typing.ChainMap -AsyncGenerator = typing.AsyncGenerator -NewType = typing.NewType -Text = typing.Text -TYPE_CHECKING = typing.TYPE_CHECKING - - -_PROTO_WHITELIST = ['Callable', 'Awaitable', - 'Iterable', 'Iterator', 'AsyncIterable', 'AsyncIterator', - 'Hashable', 'Sized', 'Container', 'Collection', 'Reversible', - 'ContextManager', 'AsyncContextManager'] - - -def _get_protocol_attrs(cls): - attrs = set() - for base in cls.__mro__[:-1]: # without object - if base.__name__ in ('Protocol', 'Generic'): - continue - annotations = getattr(base, '__annotations__', {}) - for attr in list(base.__dict__.keys()) + list(annotations.keys()): - if (not attr.startswith('_abc_') and attr not in ( - '__abstractmethods__', '__annotations__', '__weakref__', - '_is_protocol', '_is_runtime_protocol', '__dict__', - '__args__', '__slots__', - '__next_in_mro__', '__parameters__', '__origin__', - '__orig_bases__', '__extra__', '__tree_hash__', - '__doc__', '__subclasshook__', '__init__', '__new__', - '__module__', '_MutableMapping__marker', '_gorg')): - attrs.add(attr) - return attrs - - -def _is_callable_members_only(cls): - return all(callable(getattr(cls, attr, None)) for attr in _get_protocol_attrs(cls)) - - -def _maybe_adjust_parameters(cls): - """Helper function used in Protocol.__init_subclass__ and _TypedDictMeta.__new__. - - The contents of this function are very similar - to logic found in typing.Generic.__init_subclass__ - on the CPython main branch. - """ - tvars = [] - if '__orig_bases__' in cls.__dict__: - tvars = typing._collect_type_vars(cls.__orig_bases__) - # Look for Generic[T1, ..., Tn] or Protocol[T1, ..., Tn]. - # If found, tvars must be a subset of it. - # If not found, tvars is it. - # Also check for and reject plain Generic, - # and reject multiple Generic[...] and/or Protocol[...]. - gvars = None - for base in cls.__orig_bases__: - if (isinstance(base, typing._GenericAlias) and - base.__origin__ in (typing.Generic, Protocol)): - # for error messages - the_base = base.__origin__.__name__ - if gvars is not None: - raise TypeError( - "Cannot inherit from Generic[...]" - " and/or Protocol[...] multiple types.") - gvars = base.__parameters__ - if gvars is None: - gvars = tvars - else: - tvarset = set(tvars) - gvarset = set(gvars) - if not tvarset <= gvarset: - s_vars = ', '.join(str(t) for t in tvars if t not in gvarset) - s_args = ', '.join(str(g) for g in gvars) - raise TypeError(f"Some type variables ({s_vars}) are" - f" not listed in {the_base}[{s_args}]") - tvars = gvars - cls.__parameters__ = tuple(tvars) - - -# 3.8+ -if hasattr(typing, 'Protocol'): - Protocol = typing.Protocol -# 3.7 -else: - - def _no_init(self, *args, **kwargs): - if type(self)._is_protocol: - raise TypeError('Protocols cannot be instantiated') - - class _ProtocolMeta(abc.ABCMeta): # noqa: B024 - # This metaclass is a bit unfortunate and exists only because of the lack - # of __instancehook__. - def __instancecheck__(cls, instance): - # We need this method for situations where attributes are - # assigned in __init__. - if ((not getattr(cls, '_is_protocol', False) or - _is_callable_members_only(cls)) and - issubclass(instance.__class__, cls)): - return True - if cls._is_protocol: - if all(hasattr(instance, attr) and - (not callable(getattr(cls, attr, None)) or - getattr(instance, attr) is not None) - for attr in _get_protocol_attrs(cls)): - return True - return super().__instancecheck__(instance) - - class Protocol(metaclass=_ProtocolMeta): - # There is quite a lot of overlapping code with typing.Generic. - # Unfortunately it is hard to avoid this while these live in two different - # modules. The duplicated code will be removed when Protocol is moved to typing. - """Base class for protocol classes. Protocol classes are defined as:: - - class Proto(Protocol): - def meth(self) -> int: - ... - - Such classes are primarily used with static type checkers that recognize - structural subtyping (static duck-typing), for example:: - - class C: - def meth(self) -> int: - return 0 - - def func(x: Proto) -> int: - return x.meth() - - func(C()) # Passes static type check - - See PEP 544 for details. Protocol classes decorated with - @typing_extensions.runtime act as simple-minded runtime protocol that checks - only the presence of given attributes, ignoring their type signatures. - - Protocol classes can be generic, they are defined as:: - - class GenProto(Protocol[T]): - def meth(self) -> T: - ... - """ - __slots__ = () - _is_protocol = True - - def __new__(cls, *args, **kwds): - if cls is Protocol: - raise TypeError("Type Protocol cannot be instantiated; " - "it can only be used as a base class") - return super().__new__(cls) - - @typing._tp_cache - def __class_getitem__(cls, params): - if not isinstance(params, tuple): - params = (params,) - if not params and cls is not typing.Tuple: - raise TypeError( - f"Parameter list to {cls.__qualname__}[...] cannot be empty") - msg = "Parameters to generic types must be types." - params = tuple(typing._type_check(p, msg) for p in params) # noqa - if cls is Protocol: - # Generic can only be subscripted with unique type variables. - if not all(isinstance(p, typing.TypeVar) for p in params): - i = 0 - while isinstance(params[i], typing.TypeVar): - i += 1 - raise TypeError( - "Parameters to Protocol[...] must all be type variables." - f" Parameter {i + 1} is {params[i]}") - if len(set(params)) != len(params): - raise TypeError( - "Parameters to Protocol[...] must all be unique") - else: - # Subscripting a regular Generic subclass. - _check_generic(cls, params, len(cls.__parameters__)) - return typing._GenericAlias(cls, params) - - def __init_subclass__(cls, *args, **kwargs): - if '__orig_bases__' in cls.__dict__: - error = typing.Generic in cls.__orig_bases__ - else: - error = typing.Generic in cls.__bases__ - if error: - raise TypeError("Cannot inherit from plain Generic") - _maybe_adjust_parameters(cls) - - # Determine if this is a protocol or a concrete subclass. - if not cls.__dict__.get('_is_protocol', None): - cls._is_protocol = any(b is Protocol for b in cls.__bases__) - - # Set (or override) the protocol subclass hook. - def _proto_hook(other): - if not cls.__dict__.get('_is_protocol', None): - return NotImplemented - if not getattr(cls, '_is_runtime_protocol', False): - if sys._getframe(2).f_globals['__name__'] in ['abc', 'functools']: - return NotImplemented - raise TypeError("Instance and class checks can only be used with" - " @runtime protocols") - if not _is_callable_members_only(cls): - if sys._getframe(2).f_globals['__name__'] in ['abc', 'functools']: - return NotImplemented - raise TypeError("Protocols with non-method members" - " don't support issubclass()") - if not isinstance(other, type): - # Same error as for issubclass(1, int) - raise TypeError('issubclass() arg 1 must be a class') - for attr in _get_protocol_attrs(cls): - for base in other.__mro__: - if attr in base.__dict__: - if base.__dict__[attr] is None: - return NotImplemented - break - annotations = getattr(base, '__annotations__', {}) - if (isinstance(annotations, typing.Mapping) and - attr in annotations and - isinstance(other, _ProtocolMeta) and - other._is_protocol): - break - else: - return NotImplemented - return True - if '__subclasshook__' not in cls.__dict__: - cls.__subclasshook__ = _proto_hook - - # We have nothing more to do for non-protocols. - if not cls._is_protocol: - return - - # Check consistency of bases. - for base in cls.__bases__: - if not (base in (object, typing.Generic) or - base.__module__ == 'collections.abc' and - base.__name__ in _PROTO_WHITELIST or - isinstance(base, _ProtocolMeta) and base._is_protocol): - raise TypeError('Protocols can only inherit from other' - f' protocols, got {repr(base)}') - cls.__init__ = _no_init - - -# 3.8+ -if hasattr(typing, 'runtime_checkable'): - runtime_checkable = typing.runtime_checkable -# 3.7 -else: - def runtime_checkable(cls): - """Mark a protocol class as a runtime protocol, so that it - can be used with isinstance() and issubclass(). Raise TypeError - if applied to a non-protocol class. - - This allows a simple-minded structural check very similar to the - one-offs in collections.abc such as Hashable. - """ - if not isinstance(cls, _ProtocolMeta) or not cls._is_protocol: - raise TypeError('@runtime_checkable can be only applied to protocol classes,' - f' got {cls!r}') - cls._is_runtime_protocol = True - return cls - - -# Exists for backwards compatibility. -runtime = runtime_checkable - - -# 3.8+ -if hasattr(typing, 'SupportsIndex'): - SupportsIndex = typing.SupportsIndex -# 3.7 -else: - @runtime_checkable - class SupportsIndex(Protocol): - __slots__ = () - - @abc.abstractmethod - def __index__(self) -> int: - pass - - -if hasattr(typing, "Required"): - # The standard library TypedDict in Python 3.8 does not store runtime information - # about which (if any) keys are optional. See https://bugs.python.org/issue38834 - # The standard library TypedDict in Python 3.9.0/1 does not honour the "total" - # keyword with old-style TypedDict(). See https://bugs.python.org/issue42059 - # The standard library TypedDict below Python 3.11 does not store runtime - # information about optional and required keys when using Required or NotRequired. - # Generic TypedDicts are also impossible using typing.TypedDict on Python <3.11. - TypedDict = typing.TypedDict - _TypedDictMeta = typing._TypedDictMeta - is_typeddict = typing.is_typeddict -else: - def _check_fails(cls, other): - try: - if sys._getframe(1).f_globals['__name__'] not in ['abc', - 'functools', - 'typing']: - # Typed dicts are only for static structural subtyping. - raise TypeError('TypedDict does not support instance and class checks') - except (AttributeError, ValueError): - pass - return False - - def _dict_new(*args, **kwargs): - if not args: - raise TypeError('TypedDict.__new__(): not enough arguments') - _, args = args[0], args[1:] # allow the "cls" keyword be passed - return dict(*args, **kwargs) - - _dict_new.__text_signature__ = '($cls, _typename, _fields=None, /, **kwargs)' - - def _typeddict_new(*args, total=True, **kwargs): - if not args: - raise TypeError('TypedDict.__new__(): not enough arguments') - _, args = args[0], args[1:] # allow the "cls" keyword be passed - if args: - typename, args = args[0], args[1:] # allow the "_typename" keyword be passed - elif '_typename' in kwargs: - typename = kwargs.pop('_typename') - import warnings - warnings.warn("Passing '_typename' as keyword argument is deprecated", - DeprecationWarning, stacklevel=2) - else: - raise TypeError("TypedDict.__new__() missing 1 required positional " - "argument: '_typename'") - if args: - try: - fields, = args # allow the "_fields" keyword be passed - except ValueError: - raise TypeError('TypedDict.__new__() takes from 2 to 3 ' - f'positional arguments but {len(args) + 2} ' - 'were given') - elif '_fields' in kwargs and len(kwargs) == 1: - fields = kwargs.pop('_fields') - import warnings - warnings.warn("Passing '_fields' as keyword argument is deprecated", - DeprecationWarning, stacklevel=2) - else: - fields = None - - if fields is None: - fields = kwargs - elif kwargs: - raise TypeError("TypedDict takes either a dict or keyword arguments," - " but not both") - - ns = {'__annotations__': dict(fields)} - try: - # Setting correct module is necessary to make typed dict classes pickleable. - ns['__module__'] = sys._getframe(1).f_globals.get('__name__', '__main__') - except (AttributeError, ValueError): - pass - - return _TypedDictMeta(typename, (), ns, total=total) - - _typeddict_new.__text_signature__ = ('($cls, _typename, _fields=None,' - ' /, *, total=True, **kwargs)') - - class _TypedDictMeta(type): - def __init__(cls, name, bases, ns, total=True): - super().__init__(name, bases, ns) - - def __new__(cls, name, bases, ns, total=True): - # Create new typed dict class object. - # This method is called directly when TypedDict is subclassed, - # or via _typeddict_new when TypedDict is instantiated. This way - # TypedDict supports all three syntaxes described in its docstring. - # Subclasses and instances of TypedDict return actual dictionaries - # via _dict_new. - ns['__new__'] = _typeddict_new if name == 'TypedDict' else _dict_new - # Don't insert typing.Generic into __bases__ here, - # or Generic.__init_subclass__ will raise TypeError - # in the super().__new__() call. - # Instead, monkey-patch __bases__ onto the class after it's been created. - tp_dict = super().__new__(cls, name, (dict,), ns) - - if any(issubclass(base, typing.Generic) for base in bases): - tp_dict.__bases__ = (typing.Generic, dict) - _maybe_adjust_parameters(tp_dict) - - annotations = {} - own_annotations = ns.get('__annotations__', {}) - msg = "TypedDict('Name', {f0: t0, f1: t1, ...}); each t must be a type" - own_annotations = { - n: typing._type_check(tp, msg) for n, tp in own_annotations.items() - } - required_keys = set() - optional_keys = set() - - for base in bases: - annotations.update(base.__dict__.get('__annotations__', {})) - required_keys.update(base.__dict__.get('__required_keys__', ())) - optional_keys.update(base.__dict__.get('__optional_keys__', ())) - - annotations.update(own_annotations) - for annotation_key, annotation_type in own_annotations.items(): - annotation_origin = get_origin(annotation_type) - if annotation_origin is Annotated: - annotation_args = get_args(annotation_type) - if annotation_args: - annotation_type = annotation_args[0] - annotation_origin = get_origin(annotation_type) - - if annotation_origin is Required: - required_keys.add(annotation_key) - elif annotation_origin is NotRequired: - optional_keys.add(annotation_key) - elif total: - required_keys.add(annotation_key) - else: - optional_keys.add(annotation_key) - - tp_dict.__annotations__ = annotations - tp_dict.__required_keys__ = frozenset(required_keys) - tp_dict.__optional_keys__ = frozenset(optional_keys) - if not hasattr(tp_dict, '__total__'): - tp_dict.__total__ = total - return tp_dict - - __instancecheck__ = __subclasscheck__ = _check_fails - - TypedDict = _TypedDictMeta('TypedDict', (dict,), {}) - TypedDict.__module__ = __name__ - TypedDict.__doc__ = \ - """A simple typed name space. At runtime it is equivalent to a plain dict. - - TypedDict creates a dictionary type that expects all of its - instances to have a certain set of keys, with each key - associated with a value of a consistent type. This expectation - is not checked at runtime but is only enforced by type checkers. - Usage:: - - class Point2D(TypedDict): - x: int - y: int - label: str - - a: Point2D = {'x': 1, 'y': 2, 'label': 'good'} # OK - b: Point2D = {'z': 3, 'label': 'bad'} # Fails type check - - assert Point2D(x=1, y=2, label='first') == dict(x=1, y=2, label='first') - - The type info can be accessed via the Point2D.__annotations__ dict, and - the Point2D.__required_keys__ and Point2D.__optional_keys__ frozensets. - TypedDict supports two additional equivalent forms:: - - Point2D = TypedDict('Point2D', x=int, y=int, label=str) - Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': str}) - - The class syntax is only supported in Python 3.6+, while two other - syntax forms work for Python 2.7 and 3.2+ - """ - - if hasattr(typing, "_TypedDictMeta"): - _TYPEDDICT_TYPES = (typing._TypedDictMeta, _TypedDictMeta) - else: - _TYPEDDICT_TYPES = (_TypedDictMeta,) - - def is_typeddict(tp): - """Check if an annotation is a TypedDict class - - For example:: - class Film(TypedDict): - title: str - year: int - - is_typeddict(Film) # => True - is_typeddict(Union[list, str]) # => False - """ - return isinstance(tp, tuple(_TYPEDDICT_TYPES)) - - -if hasattr(typing, "assert_type"): - assert_type = typing.assert_type - -else: - def assert_type(__val, __typ): - """Assert (to the type checker) that the value is of the given type. - - When the type checker encounters a call to assert_type(), it - emits an error if the value is not of the specified type:: - - def greet(name: str) -> None: - assert_type(name, str) # ok - assert_type(name, int) # type checker error - - At runtime this returns the first argument unchanged and otherwise - does nothing. - """ - return __val - - -if hasattr(typing, "Required"): - get_type_hints = typing.get_type_hints -else: - import functools - import types - - # replaces _strip_annotations() - def _strip_extras(t): - """Strips Annotated, Required and NotRequired from a given type.""" - if isinstance(t, _AnnotatedAlias): - return _strip_extras(t.__origin__) - if hasattr(t, "__origin__") and t.__origin__ in (Required, NotRequired): - return _strip_extras(t.__args__[0]) - if isinstance(t, typing._GenericAlias): - stripped_args = tuple(_strip_extras(a) for a in t.__args__) - if stripped_args == t.__args__: - return t - return t.copy_with(stripped_args) - if hasattr(types, "GenericAlias") and isinstance(t, types.GenericAlias): - stripped_args = tuple(_strip_extras(a) for a in t.__args__) - if stripped_args == t.__args__: - return t - return types.GenericAlias(t.__origin__, stripped_args) - if hasattr(types, "UnionType") and isinstance(t, types.UnionType): - stripped_args = tuple(_strip_extras(a) for a in t.__args__) - if stripped_args == t.__args__: - return t - return functools.reduce(operator.or_, stripped_args) - - return t - - def get_type_hints(obj, globalns=None, localns=None, include_extras=False): - """Return type hints for an object. - - This is often the same as obj.__annotations__, but it handles - forward references encoded as string literals, adds Optional[t] if a - default value equal to None is set and recursively replaces all - 'Annotated[T, ...]', 'Required[T]' or 'NotRequired[T]' with 'T' - (unless 'include_extras=True'). - - The argument may be a module, class, method, or function. The annotations - are returned as a dictionary. For classes, annotations include also - inherited members. - - TypeError is raised if the argument is not of a type that can contain - annotations, and an empty dictionary is returned if no annotations are - present. - - BEWARE -- the behavior of globalns and localns is counterintuitive - (unless you are familiar with how eval() and exec() work). The - search order is locals first, then globals. - - - If no dict arguments are passed, an attempt is made to use the - globals from obj (or the respective module's globals for classes), - and these are also used as the locals. If the object does not appear - to have globals, an empty dictionary is used. - - - If one dict argument is passed, it is used for both globals and - locals. - - - If two dict arguments are passed, they specify globals and - locals, respectively. - """ - if hasattr(typing, "Annotated"): - hint = typing.get_type_hints( - obj, globalns=globalns, localns=localns, include_extras=True - ) - else: - hint = typing.get_type_hints(obj, globalns=globalns, localns=localns) - if include_extras: - return hint - return {k: _strip_extras(t) for k, t in hint.items()} - - -# Python 3.9+ has PEP 593 (Annotated) -if hasattr(typing, 'Annotated'): - Annotated = typing.Annotated - # Not exported and not a public API, but needed for get_origin() and get_args() - # to work. - _AnnotatedAlias = typing._AnnotatedAlias -# 3.7-3.8 -else: - class _AnnotatedAlias(typing._GenericAlias, _root=True): - """Runtime representation of an annotated type. - - At its core 'Annotated[t, dec1, dec2, ...]' is an alias for the type 't' - with extra annotations. The alias behaves like a normal typing alias, - instantiating is the same as instantiating the underlying type, binding - it to types is also the same. - """ - def __init__(self, origin, metadata): - if isinstance(origin, _AnnotatedAlias): - metadata = origin.__metadata__ + metadata - origin = origin.__origin__ - super().__init__(origin, origin) - self.__metadata__ = metadata - - def copy_with(self, params): - assert len(params) == 1 - new_type = params[0] - return _AnnotatedAlias(new_type, self.__metadata__) - - def __repr__(self): - return (f"typing_extensions.Annotated[{typing._type_repr(self.__origin__)}, " - f"{', '.join(repr(a) for a in self.__metadata__)}]") - - def __reduce__(self): - return operator.getitem, ( - Annotated, (self.__origin__,) + self.__metadata__ - ) - - def __eq__(self, other): - if not isinstance(other, _AnnotatedAlias): - return NotImplemented - if self.__origin__ != other.__origin__: - return False - return self.__metadata__ == other.__metadata__ - - def __hash__(self): - return hash((self.__origin__, self.__metadata__)) - - class Annotated: - """Add context specific metadata to a type. - - Example: Annotated[int, runtime_check.Unsigned] indicates to the - hypothetical runtime_check module that this type is an unsigned int. - Every other consumer of this type can ignore this metadata and treat - this type as int. - - The first argument to Annotated must be a valid type (and will be in - the __origin__ field), the remaining arguments are kept as a tuple in - the __extra__ field. - - Details: - - - It's an error to call `Annotated` with less than two arguments. - - Nested Annotated are flattened:: - - Annotated[Annotated[T, Ann1, Ann2], Ann3] == Annotated[T, Ann1, Ann2, Ann3] - - - Instantiating an annotated type is equivalent to instantiating the - underlying type:: - - Annotated[C, Ann1](5) == C(5) - - - Annotated can be used as a generic type alias:: - - Optimized = Annotated[T, runtime.Optimize()] - Optimized[int] == Annotated[int, runtime.Optimize()] - - OptimizedList = Annotated[List[T], runtime.Optimize()] - OptimizedList[int] == Annotated[List[int], runtime.Optimize()] - """ - - __slots__ = () - - def __new__(cls, *args, **kwargs): - raise TypeError("Type Annotated cannot be instantiated.") - - @typing._tp_cache - def __class_getitem__(cls, params): - if not isinstance(params, tuple) or len(params) < 2: - raise TypeError("Annotated[...] should be used " - "with at least two arguments (a type and an " - "annotation).") - allowed_special_forms = (ClassVar, Final) - if get_origin(params[0]) in allowed_special_forms: - origin = params[0] - else: - msg = "Annotated[t, ...]: t must be a type." - origin = typing._type_check(params[0], msg) - metadata = tuple(params[1:]) - return _AnnotatedAlias(origin, metadata) - - def __init_subclass__(cls, *args, **kwargs): - raise TypeError( - f"Cannot subclass {cls.__module__}.Annotated" - ) - -# Python 3.8 has get_origin() and get_args() but those implementations aren't -# Annotated-aware, so we can't use those. Python 3.9's versions don't support -# ParamSpecArgs and ParamSpecKwargs, so only Python 3.10's versions will do. -if sys.version_info[:2] >= (3, 10): - get_origin = typing.get_origin - get_args = typing.get_args -# 3.7-3.9 -else: - try: - # 3.9+ - from typing import _BaseGenericAlias - except ImportError: - _BaseGenericAlias = typing._GenericAlias - try: - # 3.9+ - from typing import GenericAlias as _typing_GenericAlias - except ImportError: - _typing_GenericAlias = typing._GenericAlias - - def get_origin(tp): - """Get the unsubscripted version of a type. - - This supports generic types, Callable, Tuple, Union, Literal, Final, ClassVar - and Annotated. Return None for unsupported types. Examples:: - - get_origin(Literal[42]) is Literal - get_origin(int) is None - get_origin(ClassVar[int]) is ClassVar - get_origin(Generic) is Generic - get_origin(Generic[T]) is Generic - get_origin(Union[T, int]) is Union - get_origin(List[Tuple[T, T]][int]) == list - get_origin(P.args) is P - """ - if isinstance(tp, _AnnotatedAlias): - return Annotated - if isinstance(tp, (typing._GenericAlias, _typing_GenericAlias, _BaseGenericAlias, - ParamSpecArgs, ParamSpecKwargs)): - return tp.__origin__ - if tp is typing.Generic: - return typing.Generic - return None - - def get_args(tp): - """Get type arguments with all substitutions performed. - - For unions, basic simplifications used by Union constructor are performed. - Examples:: - get_args(Dict[str, int]) == (str, int) - get_args(int) == () - get_args(Union[int, Union[T, int], str][int]) == (int, str) - get_args(Union[int, Tuple[T, int]][str]) == (int, Tuple[str, int]) - get_args(Callable[[], T][int]) == ([], int) - """ - if isinstance(tp, _AnnotatedAlias): - return (tp.__origin__,) + tp.__metadata__ - if isinstance(tp, (typing._GenericAlias, _typing_GenericAlias)): - if getattr(tp, "_special", False): - return () - res = tp.__args__ - if get_origin(tp) is collections.abc.Callable and res[0] is not Ellipsis: - res = (list(res[:-1]), res[-1]) - return res - return () - - -# 3.10+ -if hasattr(typing, 'TypeAlias'): - TypeAlias = typing.TypeAlias -# 3.9 -elif sys.version_info[:2] >= (3, 9): - class _TypeAliasForm(typing._SpecialForm, _root=True): - def __repr__(self): - return 'typing_extensions.' + self._name - - @_TypeAliasForm - def TypeAlias(self, parameters): - """Special marker indicating that an assignment should - be recognized as a proper type alias definition by type - checkers. - - For example:: - - Predicate: TypeAlias = Callable[..., bool] - - It's invalid when used anywhere except as in the example above. - """ - raise TypeError(f"{self} is not subscriptable") -# 3.7-3.8 -else: - class _TypeAliasForm(typing._SpecialForm, _root=True): - def __repr__(self): - return 'typing_extensions.' + self._name - - TypeAlias = _TypeAliasForm('TypeAlias', - doc="""Special marker indicating that an assignment should - be recognized as a proper type alias definition by type - checkers. - - For example:: - - Predicate: TypeAlias = Callable[..., bool] - - It's invalid when used anywhere except as in the example - above.""") - - -class _DefaultMixin: - """Mixin for TypeVarLike defaults.""" - - __slots__ = () - - def __init__(self, default): - if isinstance(default, (tuple, list)): - self.__default__ = tuple((typing._type_check(d, "Default must be a type") - for d in default)) - elif default: - self.__default__ = typing._type_check(default, "Default must be a type") - else: - self.__default__ = None - - -# Add default and infer_variance parameters from PEP 696 and 695 -class TypeVar(typing.TypeVar, _DefaultMixin, _root=True): - """Type variable.""" - - __module__ = 'typing' - - def __init__(self, name, *constraints, bound=None, - covariant=False, contravariant=False, - default=None, infer_variance=False): - super().__init__(name, *constraints, bound=bound, covariant=covariant, - contravariant=contravariant) - _DefaultMixin.__init__(self, default) - self.__infer_variance__ = infer_variance - - # for pickling: - try: - def_mod = sys._getframe(1).f_globals.get('__name__', '__main__') - except (AttributeError, ValueError): - def_mod = None - if def_mod != 'typing_extensions': - self.__module__ = def_mod - - -# Python 3.10+ has PEP 612 -if hasattr(typing, 'ParamSpecArgs'): - ParamSpecArgs = typing.ParamSpecArgs - ParamSpecKwargs = typing.ParamSpecKwargs -# 3.7-3.9 -else: - class _Immutable: - """Mixin to indicate that object should not be copied.""" - __slots__ = () - - def __copy__(self): - return self - - def __deepcopy__(self, memo): - return self - - class ParamSpecArgs(_Immutable): - """The args for a ParamSpec object. - - Given a ParamSpec object P, P.args is an instance of ParamSpecArgs. - - ParamSpecArgs objects have a reference back to their ParamSpec: - - P.args.__origin__ is P - - This type is meant for runtime introspection and has no special meaning to - static type checkers. - """ - def __init__(self, origin): - self.__origin__ = origin - - def __repr__(self): - return f"{self.__origin__.__name__}.args" - - def __eq__(self, other): - if not isinstance(other, ParamSpecArgs): - return NotImplemented - return self.__origin__ == other.__origin__ - - class ParamSpecKwargs(_Immutable): - """The kwargs for a ParamSpec object. - - Given a ParamSpec object P, P.kwargs is an instance of ParamSpecKwargs. - - ParamSpecKwargs objects have a reference back to their ParamSpec: - - P.kwargs.__origin__ is P - - This type is meant for runtime introspection and has no special meaning to - static type checkers. - """ - def __init__(self, origin): - self.__origin__ = origin - - def __repr__(self): - return f"{self.__origin__.__name__}.kwargs" - - def __eq__(self, other): - if not isinstance(other, ParamSpecKwargs): - return NotImplemented - return self.__origin__ == other.__origin__ - -# 3.10+ -if hasattr(typing, 'ParamSpec'): - - # Add default Parameter - PEP 696 - class ParamSpec(typing.ParamSpec, _DefaultMixin, _root=True): - """Parameter specification variable.""" - - __module__ = 'typing' - - def __init__(self, name, *, bound=None, covariant=False, contravariant=False, - default=None): - super().__init__(name, bound=bound, covariant=covariant, - contravariant=contravariant) - _DefaultMixin.__init__(self, default) - - # for pickling: - try: - def_mod = sys._getframe(1).f_globals.get('__name__', '__main__') - except (AttributeError, ValueError): - def_mod = None - if def_mod != 'typing_extensions': - self.__module__ = def_mod - -# 3.7-3.9 -else: - - # Inherits from list as a workaround for Callable checks in Python < 3.9.2. - class ParamSpec(list, _DefaultMixin): - """Parameter specification variable. - - Usage:: - - P = ParamSpec('P') - - Parameter specification variables exist primarily for the benefit of static - type checkers. They are used to forward the parameter types of one - callable to another callable, a pattern commonly found in higher order - functions and decorators. They are only valid when used in ``Concatenate``, - or s the first argument to ``Callable``. In Python 3.10 and higher, - they are also supported in user-defined Generics at runtime. - See class Generic for more information on generic types. An - example for annotating a decorator:: - - T = TypeVar('T') - P = ParamSpec('P') - - def add_logging(f: Callable[P, T]) -> Callable[P, T]: - '''A type-safe decorator to add logging to a function.''' - def inner(*args: P.args, **kwargs: P.kwargs) -> T: - logging.info(f'{f.__name__} was called') - return f(*args, **kwargs) - return inner - - @add_logging - def add_two(x: float, y: float) -> float: - '''Add two numbers together.''' - return x + y - - Parameter specification variables defined with covariant=True or - contravariant=True can be used to declare covariant or contravariant - generic types. These keyword arguments are valid, but their actual semantics - are yet to be decided. See PEP 612 for details. - - Parameter specification variables can be introspected. e.g.: - - P.__name__ == 'T' - P.__bound__ == None - P.__covariant__ == False - P.__contravariant__ == False - - Note that only parameter specification variables defined in global scope can - be pickled. - """ - - # Trick Generic __parameters__. - __class__ = typing.TypeVar - - @property - def args(self): - return ParamSpecArgs(self) - - @property - def kwargs(self): - return ParamSpecKwargs(self) - - def __init__(self, name, *, bound=None, covariant=False, contravariant=False, - default=None): - super().__init__([self]) - self.__name__ = name - self.__covariant__ = bool(covariant) - self.__contravariant__ = bool(contravariant) - if bound: - self.__bound__ = typing._type_check(bound, 'Bound must be a type.') - else: - self.__bound__ = None - _DefaultMixin.__init__(self, default) - - # for pickling: - try: - def_mod = sys._getframe(1).f_globals.get('__name__', '__main__') - except (AttributeError, ValueError): - def_mod = None - if def_mod != 'typing_extensions': - self.__module__ = def_mod - - def __repr__(self): - if self.__covariant__: - prefix = '+' - elif self.__contravariant__: - prefix = '-' - else: - prefix = '~' - return prefix + self.__name__ - - def __hash__(self): - return object.__hash__(self) - - def __eq__(self, other): - return self is other - - def __reduce__(self): - return self.__name__ - - # Hack to get typing._type_check to pass. - def __call__(self, *args, **kwargs): - pass - - -# 3.7-3.9 -if not hasattr(typing, 'Concatenate'): - # Inherits from list as a workaround for Callable checks in Python < 3.9.2. - class _ConcatenateGenericAlias(list): - - # Trick Generic into looking into this for __parameters__. - __class__ = typing._GenericAlias - - # Flag in 3.8. - _special = False - - def __init__(self, origin, args): - super().__init__(args) - self.__origin__ = origin - self.__args__ = args - - def __repr__(self): - _type_repr = typing._type_repr - return (f'{_type_repr(self.__origin__)}' - f'[{", ".join(_type_repr(arg) for arg in self.__args__)}]') - - def __hash__(self): - return hash((self.__origin__, self.__args__)) - - # Hack to get typing._type_check to pass in Generic. - def __call__(self, *args, **kwargs): - pass - - @property - def __parameters__(self): - return tuple( - tp for tp in self.__args__ if isinstance(tp, (typing.TypeVar, ParamSpec)) - ) - - -# 3.7-3.9 -@typing._tp_cache -def _concatenate_getitem(self, parameters): - if parameters == (): - raise TypeError("Cannot take a Concatenate of no types.") - if not isinstance(parameters, tuple): - parameters = (parameters,) - if not isinstance(parameters[-1], ParamSpec): - raise TypeError("The last parameter to Concatenate should be a " - "ParamSpec variable.") - msg = "Concatenate[arg, ...]: each arg must be a type." - parameters = tuple(typing._type_check(p, msg) for p in parameters) - return _ConcatenateGenericAlias(self, parameters) - - -# 3.10+ -if hasattr(typing, 'Concatenate'): - Concatenate = typing.Concatenate - _ConcatenateGenericAlias = typing._ConcatenateGenericAlias # noqa -# 3.9 -elif sys.version_info[:2] >= (3, 9): - @_TypeAliasForm - def Concatenate(self, parameters): - """Used in conjunction with ``ParamSpec`` and ``Callable`` to represent a - higher order function which adds, removes or transforms parameters of a - callable. - - For example:: - - Callable[Concatenate[int, P], int] - - See PEP 612 for detailed information. - """ - return _concatenate_getitem(self, parameters) -# 3.7-8 -else: - class _ConcatenateForm(typing._SpecialForm, _root=True): - def __repr__(self): - return 'typing_extensions.' + self._name - - def __getitem__(self, parameters): - return _concatenate_getitem(self, parameters) - - Concatenate = _ConcatenateForm( - 'Concatenate', - doc="""Used in conjunction with ``ParamSpec`` and ``Callable`` to represent a - higher order function which adds, removes or transforms parameters of a - callable. - - For example:: - - Callable[Concatenate[int, P], int] - - See PEP 612 for detailed information. - """) - -# 3.10+ -if hasattr(typing, 'TypeGuard'): - TypeGuard = typing.TypeGuard -# 3.9 -elif sys.version_info[:2] >= (3, 9): - class _TypeGuardForm(typing._SpecialForm, _root=True): - def __repr__(self): - return 'typing_extensions.' + self._name - - @_TypeGuardForm - def TypeGuard(self, parameters): - """Special typing form used to annotate the return type of a user-defined - type guard function. ``TypeGuard`` only accepts a single type argument. - At runtime, functions marked this way should return a boolean. - - ``TypeGuard`` aims to benefit *type narrowing* -- a technique used by static - type checkers to determine a more precise type of an expression within a - program's code flow. Usually type narrowing is done by analyzing - conditional code flow and applying the narrowing to a block of code. The - conditional expression here is sometimes referred to as a "type guard". - - Sometimes it would be convenient to use a user-defined boolean function - as a type guard. Such a function should use ``TypeGuard[...]`` as its - return type to alert static type checkers to this intention. - - Using ``-> TypeGuard`` tells the static type checker that for a given - function: - - 1. The return value is a boolean. - 2. If the return value is ``True``, the type of its argument - is the type inside ``TypeGuard``. - - For example:: - - def is_str(val: Union[str, float]): - # "isinstance" type guard - if isinstance(val, str): - # Type of ``val`` is narrowed to ``str`` - ... - else: - # Else, type of ``val`` is narrowed to ``float``. - ... - - Strict type narrowing is not enforced -- ``TypeB`` need not be a narrower - form of ``TypeA`` (it can even be a wider form) and this may lead to - type-unsafe results. The main reason is to allow for things like - narrowing ``List[object]`` to ``List[str]`` even though the latter is not - a subtype of the former, since ``List`` is invariant. The responsibility of - writing type-safe type guards is left to the user. - - ``TypeGuard`` also works with type variables. For more information, see - PEP 647 (User-Defined Type Guards). - """ - item = typing._type_check(parameters, f'{self} accepts only a single type.') - return typing._GenericAlias(self, (item,)) -# 3.7-3.8 -else: - class _TypeGuardForm(typing._SpecialForm, _root=True): - - def __repr__(self): - return 'typing_extensions.' + self._name - - def __getitem__(self, parameters): - item = typing._type_check(parameters, - f'{self._name} accepts only a single type') - return typing._GenericAlias(self, (item,)) - - TypeGuard = _TypeGuardForm( - 'TypeGuard', - doc="""Special typing form used to annotate the return type of a user-defined - type guard function. ``TypeGuard`` only accepts a single type argument. - At runtime, functions marked this way should return a boolean. - - ``TypeGuard`` aims to benefit *type narrowing* -- a technique used by static - type checkers to determine a more precise type of an expression within a - program's code flow. Usually type narrowing is done by analyzing - conditional code flow and applying the narrowing to a block of code. The - conditional expression here is sometimes referred to as a "type guard". - - Sometimes it would be convenient to use a user-defined boolean function - as a type guard. Such a function should use ``TypeGuard[...]`` as its - return type to alert static type checkers to this intention. - - Using ``-> TypeGuard`` tells the static type checker that for a given - function: - - 1. The return value is a boolean. - 2. If the return value is ``True``, the type of its argument - is the type inside ``TypeGuard``. - - For example:: - - def is_str(val: Union[str, float]): - # "isinstance" type guard - if isinstance(val, str): - # Type of ``val`` is narrowed to ``str`` - ... - else: - # Else, type of ``val`` is narrowed to ``float``. - ... - - Strict type narrowing is not enforced -- ``TypeB`` need not be a narrower - form of ``TypeA`` (it can even be a wider form) and this may lead to - type-unsafe results. The main reason is to allow for things like - narrowing ``List[object]`` to ``List[str]`` even though the latter is not - a subtype of the former, since ``List`` is invariant. The responsibility of - writing type-safe type guards is left to the user. - - ``TypeGuard`` also works with type variables. For more information, see - PEP 647 (User-Defined Type Guards). - """) - - -# Vendored from cpython typing._SpecialFrom -class _SpecialForm(typing._Final, _root=True): - __slots__ = ('_name', '__doc__', '_getitem') - - def __init__(self, getitem): - self._getitem = getitem - self._name = getitem.__name__ - self.__doc__ = getitem.__doc__ - - def __getattr__(self, item): - if item in {'__name__', '__qualname__'}: - return self._name - - raise AttributeError(item) - - def __mro_entries__(self, bases): - raise TypeError(f"Cannot subclass {self!r}") - - def __repr__(self): - return f'typing_extensions.{self._name}' - - def __reduce__(self): - return self._name - - def __call__(self, *args, **kwds): - raise TypeError(f"Cannot instantiate {self!r}") - - def __or__(self, other): - return typing.Union[self, other] - - def __ror__(self, other): - return typing.Union[other, self] - - def __instancecheck__(self, obj): - raise TypeError(f"{self} cannot be used with isinstance()") - - def __subclasscheck__(self, cls): - raise TypeError(f"{self} cannot be used with issubclass()") - - @typing._tp_cache - def __getitem__(self, parameters): - return self._getitem(self, parameters) - - -if hasattr(typing, "LiteralString"): - LiteralString = typing.LiteralString -else: - @_SpecialForm - def LiteralString(self, params): - """Represents an arbitrary literal string. - - Example:: - - from typing_extensions import LiteralString - - def query(sql: LiteralString) -> ...: - ... - - query("SELECT * FROM table") # ok - query(f"SELECT * FROM {input()}") # not ok - - See PEP 675 for details. - - """ - raise TypeError(f"{self} is not subscriptable") - - -if hasattr(typing, "Self"): - Self = typing.Self -else: - @_SpecialForm - def Self(self, params): - """Used to spell the type of "self" in classes. - - Example:: - - from typing import Self - - class ReturnsSelf: - def parse(self, data: bytes) -> Self: - ... - return self - - """ - - raise TypeError(f"{self} is not subscriptable") - - -if hasattr(typing, "Never"): - Never = typing.Never -else: - @_SpecialForm - def Never(self, params): - """The bottom type, a type that has no members. - - This can be used to define a function that should never be - called, or a function that never returns:: - - from typing_extensions import Never - - def never_call_me(arg: Never) -> None: - pass - - def int_or_str(arg: int | str) -> None: - never_call_me(arg) # type checker error - match arg: - case int(): - print("It's an int") - case str(): - print("It's a str") - case _: - never_call_me(arg) # ok, arg is of type Never - - """ - - raise TypeError(f"{self} is not subscriptable") - - -if hasattr(typing, 'Required'): - Required = typing.Required - NotRequired = typing.NotRequired -elif sys.version_info[:2] >= (3, 9): - class _ExtensionsSpecialForm(typing._SpecialForm, _root=True): - def __repr__(self): - return 'typing_extensions.' + self._name - - @_ExtensionsSpecialForm - def Required(self, parameters): - """A special typing construct to mark a key of a total=False TypedDict - as required. For example: - - class Movie(TypedDict, total=False): - title: Required[str] - year: int - - m = Movie( - title='The Matrix', # typechecker error if key is omitted - year=1999, - ) - - There is no runtime checking that a required key is actually provided - when instantiating a related TypedDict. - """ - item = typing._type_check(parameters, f'{self._name} accepts only a single type.') - return typing._GenericAlias(self, (item,)) - - @_ExtensionsSpecialForm - def NotRequired(self, parameters): - """A special typing construct to mark a key of a TypedDict as - potentially missing. For example: - - class Movie(TypedDict): - title: str - year: NotRequired[int] - - m = Movie( - title='The Matrix', # typechecker error if key is omitted - year=1999, - ) - """ - item = typing._type_check(parameters, f'{self._name} accepts only a single type.') - return typing._GenericAlias(self, (item,)) - -else: - class _RequiredForm(typing._SpecialForm, _root=True): - def __repr__(self): - return 'typing_extensions.' + self._name - - def __getitem__(self, parameters): - item = typing._type_check(parameters, - f'{self._name} accepts only a single type.') - return typing._GenericAlias(self, (item,)) - - Required = _RequiredForm( - 'Required', - doc="""A special typing construct to mark a key of a total=False TypedDict - as required. For example: - - class Movie(TypedDict, total=False): - title: Required[str] - year: int - - m = Movie( - title='The Matrix', # typechecker error if key is omitted - year=1999, - ) - - There is no runtime checking that a required key is actually provided - when instantiating a related TypedDict. - """) - NotRequired = _RequiredForm( - 'NotRequired', - doc="""A special typing construct to mark a key of a TypedDict as - potentially missing. For example: - - class Movie(TypedDict): - title: str - year: NotRequired[int] - - m = Movie( - title='The Matrix', # typechecker error if key is omitted - year=1999, - ) - """) - - -if hasattr(typing, "Unpack"): # 3.11+ - Unpack = typing.Unpack -elif sys.version_info[:2] >= (3, 9): - class _UnpackSpecialForm(typing._SpecialForm, _root=True): - def __repr__(self): - return 'typing_extensions.' + self._name - - class _UnpackAlias(typing._GenericAlias, _root=True): - __class__ = typing.TypeVar - - @_UnpackSpecialForm - def Unpack(self, parameters): - """A special typing construct to unpack a variadic type. For example: - - Shape = TypeVarTuple('Shape') - Batch = NewType('Batch', int) - - def add_batch_axis( - x: Array[Unpack[Shape]] - ) -> Array[Batch, Unpack[Shape]]: ... - - """ - item = typing._type_check(parameters, f'{self._name} accepts only a single type.') - return _UnpackAlias(self, (item,)) - - def _is_unpack(obj): - return isinstance(obj, _UnpackAlias) - -else: - class _UnpackAlias(typing._GenericAlias, _root=True): - __class__ = typing.TypeVar - - class _UnpackForm(typing._SpecialForm, _root=True): - def __repr__(self): - return 'typing_extensions.' + self._name - - def __getitem__(self, parameters): - item = typing._type_check(parameters, - f'{self._name} accepts only a single type.') - return _UnpackAlias(self, (item,)) - - Unpack = _UnpackForm( - 'Unpack', - doc="""A special typing construct to unpack a variadic type. For example: - - Shape = TypeVarTuple('Shape') - Batch = NewType('Batch', int) - - def add_batch_axis( - x: Array[Unpack[Shape]] - ) -> Array[Batch, Unpack[Shape]]: ... - - """) - - def _is_unpack(obj): - return isinstance(obj, _UnpackAlias) - - -if hasattr(typing, "TypeVarTuple"): # 3.11+ - - # Add default Parameter - PEP 696 - class TypeVarTuple(typing.TypeVarTuple, _DefaultMixin, _root=True): - """Type variable tuple.""" - - def __init__(self, name, *, default=None): - super().__init__(name) - _DefaultMixin.__init__(self, default) - - # for pickling: - try: - def_mod = sys._getframe(1).f_globals.get('__name__', '__main__') - except (AttributeError, ValueError): - def_mod = None - if def_mod != 'typing_extensions': - self.__module__ = def_mod - -else: - class TypeVarTuple(_DefaultMixin): - """Type variable tuple. - - Usage:: - - Ts = TypeVarTuple('Ts') - - In the same way that a normal type variable is a stand-in for a single - type such as ``int``, a type variable *tuple* is a stand-in for a *tuple* - type such as ``Tuple[int, str]``. - - Type variable tuples can be used in ``Generic`` declarations. - Consider the following example:: - - class Array(Generic[*Ts]): ... - - The ``Ts`` type variable tuple here behaves like ``tuple[T1, T2]``, - where ``T1`` and ``T2`` are type variables. To use these type variables - as type parameters of ``Array``, we must *unpack* the type variable tuple using - the star operator: ``*Ts``. The signature of ``Array`` then behaves - as if we had simply written ``class Array(Generic[T1, T2]): ...``. - In contrast to ``Generic[T1, T2]``, however, ``Generic[*Shape]`` allows - us to parameterise the class with an *arbitrary* number of type parameters. - - Type variable tuples can be used anywhere a normal ``TypeVar`` can. - This includes class definitions, as shown above, as well as function - signatures and variable annotations:: - - class Array(Generic[*Ts]): - - def __init__(self, shape: Tuple[*Ts]): - self._shape: Tuple[*Ts] = shape - - def get_shape(self) -> Tuple[*Ts]: - return self._shape - - shape = (Height(480), Width(640)) - x: Array[Height, Width] = Array(shape) - y = abs(x) # Inferred type is Array[Height, Width] - z = x + x # ... is Array[Height, Width] - x.get_shape() # ... is tuple[Height, Width] - - """ - - # Trick Generic __parameters__. - __class__ = typing.TypeVar - - def __iter__(self): - yield self.__unpacked__ - - def __init__(self, name, *, default=None): - self.__name__ = name - _DefaultMixin.__init__(self, default) - - # for pickling: - try: - def_mod = sys._getframe(1).f_globals.get('__name__', '__main__') - except (AttributeError, ValueError): - def_mod = None - if def_mod != 'typing_extensions': - self.__module__ = def_mod - - self.__unpacked__ = Unpack[self] - - def __repr__(self): - return self.__name__ - - def __hash__(self): - return object.__hash__(self) - - def __eq__(self, other): - return self is other - - def __reduce__(self): - return self.__name__ - - def __init_subclass__(self, *args, **kwds): - if '_root' not in kwds: - raise TypeError("Cannot subclass special typing classes") - - -if hasattr(typing, "reveal_type"): - reveal_type = typing.reveal_type -else: - def reveal_type(__obj: T) -> T: - """Reveal the inferred type of a variable. - - When a static type checker encounters a call to ``reveal_type()``, - it will emit the inferred type of the argument:: - - x: int = 1 - reveal_type(x) - - Running a static type checker (e.g., ``mypy``) on this example - will produce output similar to 'Revealed type is "builtins.int"'. - - At runtime, the function prints the runtime type of the - argument and returns it unchanged. - - """ - print(f"Runtime type is {type(__obj).__name__!r}", file=sys.stderr) - return __obj - - -if hasattr(typing, "assert_never"): - assert_never = typing.assert_never -else: - def assert_never(__arg: Never) -> Never: - """Assert to the type checker that a line of code is unreachable. - - Example:: - - def int_or_str(arg: int | str) -> None: - match arg: - case int(): - print("It's an int") - case str(): - print("It's a str") - case _: - assert_never(arg) - - If a type checker finds that a call to assert_never() is - reachable, it will emit an error. - - At runtime, this throws an exception when called. - - """ - raise AssertionError("Expected code to be unreachable") - - -if hasattr(typing, 'dataclass_transform'): - dataclass_transform = typing.dataclass_transform -else: - def dataclass_transform( - *, - eq_default: bool = True, - order_default: bool = False, - kw_only_default: bool = False, - field_specifiers: typing.Tuple[ - typing.Union[typing.Type[typing.Any], typing.Callable[..., typing.Any]], - ... - ] = (), - **kwargs: typing.Any, - ) -> typing.Callable[[T], T]: - """Decorator that marks a function, class, or metaclass as providing - dataclass-like behavior. - - Example: - - from typing_extensions import dataclass_transform - - _T = TypeVar("_T") - - # Used on a decorator function - @dataclass_transform() - def create_model(cls: type[_T]) -> type[_T]: - ... - return cls - - @create_model - class CustomerModel: - id: int - name: str - - # Used on a base class - @dataclass_transform() - class ModelBase: ... - - class CustomerModel(ModelBase): - id: int - name: str - - # Used on a metaclass - @dataclass_transform() - class ModelMeta(type): ... - - class ModelBase(metaclass=ModelMeta): ... - - class CustomerModel(ModelBase): - id: int - name: str - - Each of the ``CustomerModel`` classes defined in this example will now - behave similarly to a dataclass created with the ``@dataclasses.dataclass`` - decorator. For example, the type checker will synthesize an ``__init__`` - method. - - The arguments to this decorator can be used to customize this behavior: - - ``eq_default`` indicates whether the ``eq`` parameter is assumed to be - True or False if it is omitted by the caller. - - ``order_default`` indicates whether the ``order`` parameter is - assumed to be True or False if it is omitted by the caller. - - ``kw_only_default`` indicates whether the ``kw_only`` parameter is - assumed to be True or False if it is omitted by the caller. - - ``field_specifiers`` specifies a static list of supported classes - or functions that describe fields, similar to ``dataclasses.field()``. - - At runtime, this decorator records its arguments in the - ``__dataclass_transform__`` attribute on the decorated object. - - See PEP 681 for details. - - """ - def decorator(cls_or_fn): - cls_or_fn.__dataclass_transform__ = { - "eq_default": eq_default, - "order_default": order_default, - "kw_only_default": kw_only_default, - "field_specifiers": field_specifiers, - "kwargs": kwargs, - } - return cls_or_fn - return decorator - - -if hasattr(typing, "override"): - override = typing.override -else: - _F = typing.TypeVar("_F", bound=typing.Callable[..., typing.Any]) - - def override(__arg: _F) -> _F: - """Indicate that a method is intended to override a method in a base class. - - Usage: - - class Base: - def method(self) -> None: ... - pass - - class Child(Base): - @override - def method(self) -> None: - super().method() - - When this decorator is applied to a method, the type checker will - validate that it overrides a method with the same name on a base class. - This helps prevent bugs that may occur when a base class is changed - without an equivalent change to a child class. - - See PEP 698 for details. - - """ - return __arg - - -# We have to do some monkey patching to deal with the dual nature of -# Unpack/TypeVarTuple: -# - We want Unpack to be a kind of TypeVar so it gets accepted in -# Generic[Unpack[Ts]] -# - We want it to *not* be treated as a TypeVar for the purposes of -# counting generic parameters, so that when we subscript a generic, -# the runtime doesn't try to substitute the Unpack with the subscripted type. -if not hasattr(typing, "TypeVarTuple"): - typing._collect_type_vars = _collect_type_vars - typing._check_generic = _check_generic - - -# Backport typing.NamedTuple as it exists in Python 3.11. -# In 3.11, the ability to define generic `NamedTuple`s was supported. -# This was explicitly disallowed in 3.9-3.10, and only half-worked in <=3.8. -if sys.version_info >= (3, 11): - NamedTuple = typing.NamedTuple -else: - def _caller(): - try: - return sys._getframe(2).f_globals.get('__name__', '__main__') - except (AttributeError, ValueError): # For platforms without _getframe() - return None - - def _make_nmtuple(name, types, module, defaults=()): - fields = [n for n, t in types] - annotations = {n: typing._type_check(t, f"field {n} annotation must be a type") - for n, t in types} - nm_tpl = collections.namedtuple(name, fields, - defaults=defaults, module=module) - nm_tpl.__annotations__ = nm_tpl.__new__.__annotations__ = annotations - # The `_field_types` attribute was removed in 3.9; - # in earlier versions, it is the same as the `__annotations__` attribute - if sys.version_info < (3, 9): - nm_tpl._field_types = annotations - return nm_tpl - - _prohibited_namedtuple_fields = typing._prohibited - _special_namedtuple_fields = frozenset({'__module__', '__name__', '__annotations__'}) - - class _NamedTupleMeta(type): - def __new__(cls, typename, bases, ns): - assert _NamedTuple in bases - for base in bases: - if base is not _NamedTuple and base is not typing.Generic: - raise TypeError( - 'can only inherit from a NamedTuple type and Generic') - bases = tuple(tuple if base is _NamedTuple else base for base in bases) - types = ns.get('__annotations__', {}) - default_names = [] - for field_name in types: - if field_name in ns: - default_names.append(field_name) - elif default_names: - raise TypeError(f"Non-default namedtuple field {field_name} " - f"cannot follow default field" - f"{'s' if len(default_names) > 1 else ''} " - f"{', '.join(default_names)}") - nm_tpl = _make_nmtuple( - typename, types.items(), - defaults=[ns[n] for n in default_names], - module=ns['__module__'] - ) - nm_tpl.__bases__ = bases - if typing.Generic in bases: - class_getitem = typing.Generic.__class_getitem__.__func__ - nm_tpl.__class_getitem__ = classmethod(class_getitem) - # update from user namespace without overriding special namedtuple attributes - for key in ns: - if key in _prohibited_namedtuple_fields: - raise AttributeError("Cannot overwrite NamedTuple attribute " + key) - elif key not in _special_namedtuple_fields and key not in nm_tpl._fields: - setattr(nm_tpl, key, ns[key]) - if typing.Generic in bases: - nm_tpl.__init_subclass__() - return nm_tpl - - def NamedTuple(__typename, __fields=None, **kwargs): - if __fields is None: - __fields = kwargs.items() - elif kwargs: - raise TypeError("Either list of fields or keywords" - " can be provided to NamedTuple, not both") - return _make_nmtuple(__typename, __fields, module=_caller()) - - NamedTuple.__doc__ = typing.NamedTuple.__doc__ - _NamedTuple = type.__new__(_NamedTupleMeta, 'NamedTuple', (), {}) - - # On 3.8+, alter the signature so that it matches typing.NamedTuple. - # The signature of typing.NamedTuple on >=3.8 is invalid syntax in Python 3.7, - # so just leave the signature as it is on 3.7. - if sys.version_info >= (3, 8): - NamedTuple.__text_signature__ = '(typename, fields=None, /, **kwargs)' - - def _namedtuple_mro_entries(bases): - assert NamedTuple in bases - return (_NamedTuple,) - - NamedTuple.__mro_entries__ = _namedtuple_mro_entries diff --git a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/zipp.py b/venv/lib/python3.11/site-packages/pkg_resources/_vendor/zipp.py deleted file mode 100755 index 26b723c..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/_vendor/zipp.py +++ /dev/null @@ -1,329 +0,0 @@ -import io -import posixpath -import zipfile -import itertools -import contextlib -import sys -import pathlib - -if sys.version_info < (3, 7): - from collections import OrderedDict -else: - OrderedDict = dict - - -__all__ = ['Path'] - - -def _parents(path): - """ - Given a path with elements separated by - posixpath.sep, generate all parents of that path. - - >>> list(_parents('b/d')) - ['b'] - >>> list(_parents('/b/d/')) - ['/b'] - >>> list(_parents('b/d/f/')) - ['b/d', 'b'] - >>> list(_parents('b')) - [] - >>> list(_parents('')) - [] - """ - return itertools.islice(_ancestry(path), 1, None) - - -def _ancestry(path): - """ - Given a path with elements separated by - posixpath.sep, generate all elements of that path - - >>> list(_ancestry('b/d')) - ['b/d', 'b'] - >>> list(_ancestry('/b/d/')) - ['/b/d', '/b'] - >>> list(_ancestry('b/d/f/')) - ['b/d/f', 'b/d', 'b'] - >>> list(_ancestry('b')) - ['b'] - >>> list(_ancestry('')) - [] - """ - path = path.rstrip(posixpath.sep) - while path and path != posixpath.sep: - yield path - path, tail = posixpath.split(path) - - -_dedupe = OrderedDict.fromkeys -"""Deduplicate an iterable in original order""" - - -def _difference(minuend, subtrahend): - """ - Return items in minuend not in subtrahend, retaining order - with O(1) lookup. - """ - return itertools.filterfalse(set(subtrahend).__contains__, minuend) - - -class CompleteDirs(zipfile.ZipFile): - """ - A ZipFile subclass that ensures that implied directories - are always included in the namelist. - """ - - @staticmethod - def _implied_dirs(names): - parents = itertools.chain.from_iterable(map(_parents, names)) - as_dirs = (p + posixpath.sep for p in parents) - return _dedupe(_difference(as_dirs, names)) - - def namelist(self): - names = super(CompleteDirs, self).namelist() - return names + list(self._implied_dirs(names)) - - def _name_set(self): - return set(self.namelist()) - - def resolve_dir(self, name): - """ - If the name represents a directory, return that name - as a directory (with the trailing slash). - """ - names = self._name_set() - dirname = name + '/' - dir_match = name not in names and dirname in names - return dirname if dir_match else name - - @classmethod - def make(cls, source): - """ - Given a source (filename or zipfile), return an - appropriate CompleteDirs subclass. - """ - if isinstance(source, CompleteDirs): - return source - - if not isinstance(source, zipfile.ZipFile): - return cls(_pathlib_compat(source)) - - # Only allow for FastLookup when supplied zipfile is read-only - if 'r' not in source.mode: - cls = CompleteDirs - - source.__class__ = cls - return source - - -class FastLookup(CompleteDirs): - """ - ZipFile subclass to ensure implicit - dirs exist and are resolved rapidly. - """ - - def namelist(self): - with contextlib.suppress(AttributeError): - return self.__names - self.__names = super(FastLookup, self).namelist() - return self.__names - - def _name_set(self): - with contextlib.suppress(AttributeError): - return self.__lookup - self.__lookup = super(FastLookup, self)._name_set() - return self.__lookup - - -def _pathlib_compat(path): - """ - For path-like objects, convert to a filename for compatibility - on Python 3.6.1 and earlier. - """ - try: - return path.__fspath__() - except AttributeError: - return str(path) - - -class Path: - """ - A pathlib-compatible interface for zip files. - - Consider a zip file with this structure:: - - . - ├── a.txt - └── b - ├── c.txt - └── d - └── e.txt - - >>> data = io.BytesIO() - >>> zf = zipfile.ZipFile(data, 'w') - >>> zf.writestr('a.txt', 'content of a') - >>> zf.writestr('b/c.txt', 'content of c') - >>> zf.writestr('b/d/e.txt', 'content of e') - >>> zf.filename = 'mem/abcde.zip' - - Path accepts the zipfile object itself or a filename - - >>> root = Path(zf) - - From there, several path operations are available. - - Directory iteration (including the zip file itself): - - >>> a, b = root.iterdir() - >>> a - Path('mem/abcde.zip', 'a.txt') - >>> b - Path('mem/abcde.zip', 'b/') - - name property: - - >>> b.name - 'b' - - join with divide operator: - - >>> c = b / 'c.txt' - >>> c - Path('mem/abcde.zip', 'b/c.txt') - >>> c.name - 'c.txt' - - Read text: - - >>> c.read_text() - 'content of c' - - existence: - - >>> c.exists() - True - >>> (b / 'missing.txt').exists() - False - - Coercion to string: - - >>> import os - >>> str(c).replace(os.sep, posixpath.sep) - 'mem/abcde.zip/b/c.txt' - - At the root, ``name``, ``filename``, and ``parent`` - resolve to the zipfile. Note these attributes are not - valid and will raise a ``ValueError`` if the zipfile - has no filename. - - >>> root.name - 'abcde.zip' - >>> str(root.filename).replace(os.sep, posixpath.sep) - 'mem/abcde.zip' - >>> str(root.parent) - 'mem' - """ - - __repr = "{self.__class__.__name__}({self.root.filename!r}, {self.at!r})" - - def __init__(self, root, at=""): - """ - Construct a Path from a ZipFile or filename. - - Note: When the source is an existing ZipFile object, - its type (__class__) will be mutated to a - specialized type. If the caller wishes to retain the - original type, the caller should either create a - separate ZipFile object or pass a filename. - """ - self.root = FastLookup.make(root) - self.at = at - - def open(self, mode='r', *args, pwd=None, **kwargs): - """ - Open this entry as text or binary following the semantics - of ``pathlib.Path.open()`` by passing arguments through - to io.TextIOWrapper(). - """ - if self.is_dir(): - raise IsADirectoryError(self) - zip_mode = mode[0] - if not self.exists() and zip_mode == 'r': - raise FileNotFoundError(self) - stream = self.root.open(self.at, zip_mode, pwd=pwd) - if 'b' in mode: - if args or kwargs: - raise ValueError("encoding args invalid for binary operation") - return stream - return io.TextIOWrapper(stream, *args, **kwargs) - - @property - def name(self): - return pathlib.Path(self.at).name or self.filename.name - - @property - def suffix(self): - return pathlib.Path(self.at).suffix or self.filename.suffix - - @property - def suffixes(self): - return pathlib.Path(self.at).suffixes or self.filename.suffixes - - @property - def stem(self): - return pathlib.Path(self.at).stem or self.filename.stem - - @property - def filename(self): - return pathlib.Path(self.root.filename).joinpath(self.at) - - def read_text(self, *args, **kwargs): - with self.open('r', *args, **kwargs) as strm: - return strm.read() - - def read_bytes(self): - with self.open('rb') as strm: - return strm.read() - - def _is_child(self, path): - return posixpath.dirname(path.at.rstrip("/")) == self.at.rstrip("/") - - def _next(self, at): - return self.__class__(self.root, at) - - def is_dir(self): - return not self.at or self.at.endswith("/") - - def is_file(self): - return self.exists() and not self.is_dir() - - def exists(self): - return self.at in self.root._name_set() - - def iterdir(self): - if not self.is_dir(): - raise ValueError("Can't listdir a file") - subs = map(self._next, self.root.namelist()) - return filter(self._is_child, subs) - - def __str__(self): - return posixpath.join(self.root.filename, self.at) - - def __repr__(self): - return self.__repr.format(self=self) - - def joinpath(self, *other): - next = posixpath.join(self.at, *map(_pathlib_compat, other)) - return self._next(self.root.resolve_dir(next)) - - __truediv__ = joinpath - - @property - def parent(self): - if not self.at: - return self.filename.parent - parent_at = posixpath.dirname(self.at.rstrip('/')) - if parent_at: - parent_at += '/' - return self._next(parent_at) diff --git a/venv/lib/python3.11/site-packages/pkg_resources/extern/__init__.py b/venv/lib/python3.11/site-packages/pkg_resources/extern/__init__.py deleted file mode 100755 index bacc5d7..0000000 --- a/venv/lib/python3.11/site-packages/pkg_resources/extern/__init__.py +++ /dev/null @@ -1,81 +0,0 @@ -import importlib.util -import sys - - -class VendorImporter: - """ - A PEP 302 meta path importer for finding optionally-vendored - or otherwise naturally-installed packages from root_name. - """ - - def __init__(self, root_name, vendored_names=(), vendor_pkg=None): - self.root_name = root_name - self.vendored_names = set(vendored_names) - self.vendor_pkg = vendor_pkg or root_name.replace('extern', '_vendor') - - @property - def search_path(self): - """ - Search first the vendor package then as a natural package. - """ - yield self.vendor_pkg + '.' - yield '' - - def _module_matches_namespace(self, fullname): - """Figure out if the target module is vendored.""" - root, base, target = fullname.partition(self.root_name + '.') - return not root and any(map(target.startswith, self.vendored_names)) - - def load_module(self, fullname): - """ - Iterate over the search path to locate and load fullname. - """ - root, base, target = fullname.partition(self.root_name + '.') - for prefix in self.search_path: - try: - extant = prefix + target - __import__(extant) - mod = sys.modules[extant] - sys.modules[fullname] = mod - return mod - except ImportError: - pass - else: - raise ImportError( - "The '{target}' package is required; " - "normally this is bundled with this package so if you get " - "this warning, consult the packager of your " - "distribution.".format(**locals()) - ) - - def create_module(self, spec): - return self.load_module(spec.name) - - def exec_module(self, module): - pass - - def find_spec(self, fullname, path=None, target=None): - """Return a module spec for vendored names.""" - return ( - importlib.util.spec_from_loader(fullname, self) - if self._module_matches_namespace(fullname) - else None - ) - - def install(self): - """ - Install this importer into sys.meta_path if not already present. - """ - if self not in sys.meta_path: - sys.meta_path.append(self) - - -names = ( - 'packaging', - 'pyparsing', - 'platformdirs', - 'jaraco', - 'importlib_resources', - 'more_itertools', -) -VendorImporter(__name__, names).install() diff --git a/venv/lib/python3.11/site-packages/pkg_resources/extern/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/pkg_resources/extern/__pycache__/__init__.cpython-311.pyc deleted file mode 100755 index ba3269fc6499d4fec18eee4f3866f65f298dd8df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4321 zcmb_f+iw%;760byOB~x#NPv_i!!3!q*s#%p5Zjed7aBIKyILx=8?_n@o=M_h&v?HX zL*hD8ROKNLwBi8-ZB@w+TMF8JKx!ZQxceX2k)=cI z(S@fxA>YE|l{rBd=R}?uf*~1V?^r_)xOTsvLgU-8gM)o;l8p3k?8z6xey9X{?A(IJ zV`8w=%<(!0dnR;ootqO4Ntf11?}~G>F0Yfhh#mnN)uTXTdJJe>@7Lont55HPRzeqG z-=v$oWth4}ua_$pbqrctk1J5FD4$>bT$w)ifl@XcO{r+kqEhr(lzEFP^F>oHnhT0m zaf+6yl}amT@3Msqoh<+?ma}Nkdqvw&OwFlM##1zH2P%dROBU{E3x=)CQ>&~{%W_mx zD;rrh`#FdrPzZ_y>jFGGcY!=6b*@fSsCmV~5x>;=ryPhE9K6Qt@`K zvf?aS=5+S_`J7#JjI)6(bFjEd4cn^Hf??;p)8g@7f@L zzINtXaiK~L#i}|=ah}QD(ddHVC}m5pmJFq6`-(91EFFXmGO`=1Xw)epE-(vs1 zg|b$0v3-$c<+7#(ot?VRfeB3!uXP zi;BroXhNTmU(c>eF;bW6B0A5i+@o%}SCt%b@HBqus=qED4m!zdq#k(>7xxix)guL- z0~|a~oJ2T@oFG)-$XDe4%ssL!d`0eY4nmna(Jui!CV%7E z*6L&c6KKiQ__|u8hJINwEn3Ea1sg#>+_$Tyj$sQ;*X#5_SFtVhj1{Y@pj$Bhdm1$% zIG#}omT6Z@9$xwU5EmIYRrI3m(BkbXI!ZQA(aJM1ik9gGhGD3=almC3cU2Vv%nAe) z&-iV(&kNaCDYd98LreyDaAlN2$<9QXU(qAD*eH@QB;&ZET%pE%ahU}(&2+#qE!{@* zU@jJVSsx0~_n&=WxN8hox7$Df2%}_d;(z$k@JM@jqC--#BqJNwI((#mX#4PZW8x3v z59F8WktY{g>0|Bmv1a<%%i+Th?=&Xb!ns)Y^M)A5IX|&y?OKIKQaLZUKp6{5Me-hEt8{@oro|njm>EoJ$3H+q3;fLyIu*> zVDdEq(jiiR(nfRr?!uLm{0}GNS3Zz_IL`s?L2`6)&&{ENajgOG{iV)zk-XQ;Z<6O+ zKEu<~Fv%4W1fhYU36g}0QLxeH1L*57Py>uSP|J}$aMv?B4fAZYCJ5xI!L8KzW@@}4 zeiLh@PPJ2~n$c7HAq!&-`xXpOm;>J=^ej|8+w@N*`v$oCTz$r}Q3y`8H*)S8y8w&X z2ncYdXktV3jvzuuP_WL9;HBa37iX^!0TDuMB)f33fott6m_PQ0K9gfA zGKnC-p$=Ha>*X5&0jMH7o6m?;ftB5u=bw<5xgz*-$xY)F71LT3{luWaiTY&T=!%F} z%oD?W&&xhym{O}aw{~ccUc(X0%lzaFoGpD|D|L1=b@tg}D|NA*y4Vr;{^8$Uzn|Yq zoZd{Fem3($ZzV3b6PKHb%Rdebbs}Oc?nyjMDqua75R!}QQi9?@NqWy!zh{n=zw-v{QF?}7-FnxIf_;S571W>05RJz zoi4cNGXgyh+qO|v#o@(nNS)BT8W8vVxk$`9f2fH0uK{0_%H%GICegt>Bqbq%?3am0NqbtR5zij zUspAj_`pa+RduVNsuc4}H(H@q#h}g##W=uBjX?xGhfQ>Diq=4XiUhY}+cHz4=tPWQ zzx_8LYvBcGC`AGOfW!sq7aUgi&^VEk9bS?K00X6gR{}KGzw|nig7g`i64Lkq39vFG zXE^CJfN?-%PU^>|Ph?q&cStWuOA?^-e&T%(eu|e;;_o5^Rmd(^AiuP+nt)#`2P2;j ze+90*q*1M4xr3oYcK?OkWZ9yI3O`HKu`CFX5jPpKWzlUZ>YG^*lbkCtH>V$C?>l7t zHu{mL#*gVNu%JWP%RnIVaNIT-Y6kZ=3.9 -Description-Content-Type: text/markdown -License-File: LICENSE -Provides-Extra: cli -Requires-Dist: click>=5.0; extra == "cli" -Dynamic: author -Dynamic: author-email -Dynamic: classifier -Dynamic: description -Dynamic: description-content-type -Dynamic: home-page -Dynamic: keywords -Dynamic: license -Dynamic: license-file -Dynamic: provides-extra -Dynamic: requires-python -Dynamic: summary - -# python-dotenv - -[![Build Status][build_status_badge]][build_status_link] -[![PyPI version][pypi_badge]][pypi_link] - -python-dotenv reads key-value pairs from a `.env` file and can set them as environment -variables. It helps in the development of applications following the -[12-factor](https://12factor.net/) principles. - -- [Getting Started](#getting-started) -- [Other Use Cases](#other-use-cases) - * [Load configuration without altering the environment](#load-configuration-without-altering-the-environment) - * [Parse configuration as a stream](#parse-configuration-as-a-stream) - * [Load .env files in IPython](#load-env-files-in-ipython) -- [Command-line Interface](#command-line-interface) -- [File format](#file-format) - * [Multiline values](#multiline-values) - * [Variable expansion](#variable-expansion) -- [Related Projects](#related-projects) -- [Acknowledgements](#acknowledgements) - -## Getting Started - -```shell -pip install python-dotenv -``` - -If your application takes its configuration from environment variables, like a 12-factor -application, launching it in development is not very practical because you have to set -those environment variables yourself. - -To help you with that, you can add python-dotenv to your application to make it load the -configuration from a `.env` file when it is present (e.g. in development) while remaining -configurable via the environment: - -```python -from dotenv import load_dotenv - -load_dotenv() # take environment variables - -# Code of your application, which uses environment variables (e.g. from `os.environ` or -# `os.getenv`) as if they came from the actual environment. -``` - -By default, `load_dotenv` doesn't override existing environment variables and looks for a `.env` file in same directory as python script or searches for it incrementally higher up. - -To configure the development environment, add a `.env` in the root directory of your -project: - -``` -. -├── .env -└── foo.py -``` - -The syntax of `.env` files supported by python-dotenv is similar to that of Bash: - -```bash -# Development settings -DOMAIN=example.org -ADMIN_EMAIL=admin@${DOMAIN} -ROOT_URL=${DOMAIN}/app -``` - -If you use variables in values, ensure they are surrounded with `{` and `}`, like -`${DOMAIN}`, as bare variables such as `$DOMAIN` are not expanded. - -You will probably want to add `.env` to your `.gitignore`, especially if it contains -secrets like a password. - -See the section "File format" below for more information about what you can write in a -`.env` file. - -## Other Use Cases - -### Load configuration without altering the environment - -The function `dotenv_values` works more or less the same way as `load_dotenv`, except it -doesn't touch the environment, it just returns a `dict` with the values parsed from the -`.env` file. - -```python -from dotenv import dotenv_values - -config = dotenv_values(".env") # config = {"USER": "foo", "EMAIL": "foo@example.org"} -``` - -This notably enables advanced configuration management: - -```python -import os -from dotenv import dotenv_values - -config = { - **dotenv_values(".env.shared"), # load shared development variables - **dotenv_values(".env.secret"), # load sensitive variables - **os.environ, # override loaded values with environment variables -} -``` - -### Parse configuration as a stream - -`load_dotenv` and `dotenv_values` accept [streams][python_streams] via their `stream` -argument. It is thus possible to load the variables from sources other than the -filesystem (e.g. the network). - -```python -from io import StringIO - -from dotenv import load_dotenv - -config = StringIO("USER=foo\nEMAIL=foo@example.org") -load_dotenv(stream=config) -``` - -### Load .env files in IPython - -You can use dotenv in IPython. By default, it will use `find_dotenv` to search for a -`.env` file: - -```python -%load_ext dotenv -%dotenv -``` - -You can also specify a path: - -```python -%dotenv relative/or/absolute/path/to/.env -``` - -Optional flags: - -- `-o` to override existing variables. -- `-v` for increased verbosity. - -## Command-line Interface - -A CLI interface `dotenv` is also included, which helps you manipulate the `.env` file -without manually opening it. - -```shell -$ pip install "python-dotenv[cli]" -$ dotenv set USER foo -$ dotenv set EMAIL foo@example.org -$ dotenv list -USER=foo -EMAIL=foo@example.org -$ dotenv list --format=json -{ - "USER": "foo", - "EMAIL": "foo@example.org" -} -$ dotenv run -- python foo.py -``` - -Run `dotenv --help` for more information about the options and subcommands. - -## File format - -The format is not formally specified and still improves over time. That being said, -`.env` files should mostly look like Bash files. - -Keys can be unquoted or single-quoted. Values can be unquoted, single- or double-quoted. -Spaces before and after keys, equal signs, and values are ignored. Values can be followed -by a comment. Lines can start with the `export` directive, which does not affect their -interpretation. - -Allowed escape sequences: - -- in single-quoted values: `\\`, `\'` -- in double-quoted values: `\\`, `\'`, `\"`, `\a`, `\b`, `\f`, `\n`, `\r`, `\t`, `\v` - -### Multiline values - -It is possible for single- or double-quoted values to span multiple lines. The following -examples are equivalent: - -```bash -FOO="first line -second line" -``` - -```bash -FOO="first line\nsecond line" -``` - -### Variable without a value - -A variable can have no value: - -```bash -FOO -``` - -It results in `dotenv_values` associating that variable name with the value `None` (e.g. -`{"FOO": None}`. `load_dotenv`, on the other hand, simply ignores such variables. - -This shouldn't be confused with `FOO=`, in which case the variable is associated with the -empty string. - -### Variable expansion - -python-dotenv can interpolate variables using POSIX variable expansion. - -With `load_dotenv(override=True)` or `dotenv_values()`, the value of a variable is the -first of the values defined in the following list: - -- Value of that variable in the `.env` file. -- Value of that variable in the environment. -- Default value, if provided. -- Empty string. - -With `load_dotenv(override=False)`, the value of a variable is the first of the values -defined in the following list: - -- Value of that variable in the environment. -- Value of that variable in the `.env` file. -- Default value, if provided. -- Empty string. - -## Related Projects - -- [Honcho](https://github.com/nickstenning/honcho) - For managing - Procfile-based applications. -- [django-dotenv](https://github.com/jpadilla/django-dotenv) -- [django-environ](https://github.com/joke2k/django-environ) -- [django-environ-2](https://github.com/sergeyklay/django-environ-2) -- [django-configuration](https://github.com/jezdez/django-configurations) -- [dump-env](https://github.com/sobolevn/dump-env) -- [environs](https://github.com/sloria/environs) -- [dynaconf](https://github.com/rochacbruno/dynaconf) -- [parse_it](https://github.com/naorlivne/parse_it) -- [python-decouple](https://github.com/HBNetwork/python-decouple) - -## Acknowledgements - -This project is currently maintained by [Saurabh Kumar](https://saurabh-kumar.com) and -[Bertrand Bonnefoy-Claudet](https://github.com/bbc2) and would not have been possible -without the support of these [awesome -people](https://github.com/theskumar/python-dotenv/graphs/contributors). - -[build_status_badge]: https://github.com/theskumar/python-dotenv/actions/workflows/test.yml/badge.svg -[build_status_link]: https://github.com/theskumar/python-dotenv/actions/workflows/test.yml -[pypi_badge]: https://badge.fury.io/py/python-dotenv.svg -[pypi_link]: https://badge.fury.io/py/python-dotenv -[python_streams]: https://docs.python.org/3/library/io.html - -# Changelog - -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this -project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - - -## [Unrelased] - -**Feature** -- Add support for python 3.13 -- Enhance `dotenv run`, switch to `execvpe` for better resource management and signal handling ([#523]) by [@eekstunt] - -**Fixed** -- `find_dotenv` and `load_dotenv` now correctly looks up at the current directory when running in debugger or pdb ([#553] by [@randomseed42]) - -**Misc** -- Drop support for Python 3.8 - -## [1.0.1] - 2024-01-23 - -**Fixed** - -* Gracefully handle code which has been imported from a zipfile ([#456] by [@samwyma]) -* Allow modules using `load_dotenv` to be reloaded when launched in a separate thread ([#497] by [@freddyaboulton]) -* Fix file not closed after deletion, handle error in the rewrite function ([#469] by [@Qwerty-133]) - -**Misc** -* Use pathlib.Path in tests ([#466] by [@eumiro]) -* Fix year in release date in changelog.md ([#454] by [@jankislinger]) -* Use https in README links ([#474] by [@Nicals]) - -## [1.0.0] - 2023-02-24 - -**Fixed** - -* Drop support for python 3.7, add python 3.12-dev (#449 by [@theskumar]) -* Handle situations where the cwd does not exist. (#446 by [@jctanner]) - -## [0.21.1] - 2023-01-21 - -**Added** - -* Use Python 3.11 non-beta in CI (#438 by [@bbc2]) -* Modernize variables code (#434 by [@Nougat-Waffle]) -* Modernize main.py and parser.py code (#435 by [@Nougat-Waffle]) -* Improve conciseness of cli.py and __init__.py (#439 by [@Nougat-Waffle]) -* Improve error message for `get` and `list` commands when env file can't be opened (#441 by [@bbc2]) -* Updated License to align with BSD OSI template (#433 by [@lsmith77]) - - -**Fixed** - -* Fix Out-of-scope error when "dest" variable is undefined (#413 by [@theGOTOguy]) -* Fix IPython test warning about deprecated `magic` (#440 by [@bbc2]) -* Fix type hint for dotenv_path var, add StrPath alias (#432 by [@eaf]) - -## [0.21.0] - 2022-09-03 - -**Added** - -* CLI: add support for invocations via 'python -m'. (#395 by [@theskumar]) -* `load_dotenv` function now returns `False`. (#388 by [@larsks]) -* CLI: add --format= option to list command. (#407 by [@sammck]) - -**Fixed** - -* Drop Python 3.5 and 3.6 and upgrade GA (#393 by [@eggplants]) -* Use `open` instead of `io.open`. (#389 by [@rabinadk1]) -* Improve documentation for variables without a value (#390 by [@bbc2]) -* Add `parse_it` to Related Projects (#410 by [@naorlivne]) -* Update README.md (#415 by [@harveer07]) -* Improve documentation with direct use of MkDocs (#398 by [@bbc2]) - -## [0.20.0] - 2022-03-24 - -**Added** - -- Add `encoding` (`Optional[str]`) parameter to `get_key`, `set_key` and `unset_key`. - (#379 by [@bbc2]) - -**Fixed** - -- Use dict to specify the `entry_points` parameter of `setuptools.setup` (#376 by - [@mgorny]). -- Don't build universal wheels (#387 by [@bbc2]). - -## [0.19.2] - 2021-11-11 - -**Fixed** - -- In `set_key`, add missing newline character before new entry if necessary. (#361 by - [@bbc2]) - -## [0.19.1] - 2021-08-09 - -**Added** - -- Add support for Python 3.10. (#359 by [@theskumar]) - -## [0.19.0] - 2021-07-24 - -**Changed** - -- Require Python 3.5 or a later version. Python 2 and 3.4 are no longer supported. (#341 - by [@bbc2]). - -**Added** - -- The `dotenv_path` argument of `set_key` and `unset_key` now has a type of `Union[str, - os.PathLike]` instead of just `os.PathLike` (#347 by [@bbc2]). -- The `stream` argument of `load_dotenv` and `dotenv_values` can now be a text stream - (`IO[str]`), which includes values like `io.StringIO("foo")` and `open("file.env", - "r")` (#348 by [@bbc2]). - -## [0.18.0] - 2021-06-20 - -**Changed** - -- Raise `ValueError` if `quote_mode` isn't one of `always`, `auto` or `never` in - `set_key` (#330 by [@bbc2]). -- When writing a value to a .env file with `set_key` or `dotenv set ` (#330 - by [@bbc2]): - - Use single quotes instead of double quotes. - - Don't strip surrounding quotes. - - In `auto` mode, don't add quotes if the value is only made of alphanumeric characters - (as determined by `string.isalnum`). - -## [0.17.1] - 2021-04-29 - -**Fixed** - -- Fixed tests for build environments relying on `PYTHONPATH` (#318 by [@befeleme]). - -## [0.17.0] - 2021-04-02 - -**Changed** - -- Make `dotenv get ` only show the value, not `key=value` (#313 by [@bbc2]). - -**Added** - -- Add `--override`/`--no-override` option to `dotenv run` (#312 by [@zueve] and [@bbc2]). - -## [0.16.0] - 2021-03-27 - -**Changed** - -- The default value of the `encoding` parameter for `load_dotenv` and `dotenv_values` is - now `"utf-8"` instead of `None` (#306 by [@bbc2]). -- Fix resolution order in variable expansion with `override=False` (#287 by [@bbc2]). - -## [0.15.0] - 2020-10-28 - -**Added** - -- Add `--export` option to `set` to make it prepend the binding with `export` (#270 by - [@jadutter]). - -**Changed** - -- Make `set` command create the `.env` file in the current directory if no `.env` file was - found (#270 by [@jadutter]). - -**Fixed** - -- Fix potentially empty expanded value for duplicate key (#260 by [@bbc2]). -- Fix import error on Python 3.5.0 and 3.5.1 (#267 by [@gongqingkui]). -- Fix parsing of unquoted values containing several adjacent space or tab characters - (#277 by [@bbc2], review by [@x-yuri]). - -## [0.14.0] - 2020-07-03 - -**Changed** - -- Privilege definition in file over the environment in variable expansion (#256 by - [@elbehery95]). - -**Fixed** - -- Improve error message for when file isn't found (#245 by [@snobu]). -- Use HTTPS URL in package meta data (#251 by [@ekohl]). - -## [0.13.0] - 2020-04-16 - -**Added** - -- Add support for a Bash-like default value in variable expansion (#248 by [@bbc2]). - -## [0.12.0] - 2020-02-28 - -**Changed** - -- Use current working directory to find `.env` when bundled by PyInstaller (#213 by - [@gergelyk]). - -**Fixed** - -- Fix escaping of quoted values written by `set_key` (#236 by [@bbc2]). -- Fix `dotenv run` crashing on environment variables without values (#237 by [@yannham]). -- Remove warning when last line is empty (#238 by [@bbc2]). - -## [0.11.0] - 2020-02-07 - -**Added** - -- Add `interpolate` argument to `load_dotenv` and `dotenv_values` to disable interpolation - (#232 by [@ulyssessouza]). - -**Changed** - -- Use logging instead of warnings (#231 by [@bbc2]). - -**Fixed** - -- Fix installation in non-UTF-8 environments (#225 by [@altendky]). -- Fix PyPI classifiers (#228 by [@bbc2]). - -## [0.10.5] - 2020-01-19 - -**Fixed** - -- Fix handling of malformed lines and lines without a value (#222 by [@bbc2]): - - Don't print warning when key has no value. - - Reject more malformed lines (e.g. "A: B", "a='b',c"). -- Fix handling of lines with just a comment (#224 by [@bbc2]). - -## [0.10.4] - 2020-01-17 - -**Added** - -- Make typing optional (#179 by [@techalchemy]). -- Print a warning on malformed line (#211 by [@bbc2]). -- Support keys without a value (#220 by [@ulyssessouza]). - -## 0.10.3 - -- Improve interactive mode detection ([@andrewsmith])([#183]). -- Refactor parser to fix parsing inconsistencies ([@bbc2])([#170]). - - Interpret escapes as control characters only in double-quoted strings. - - Interpret `#` as start of comment only if preceded by whitespace. - -## 0.10.2 - -- Add type hints and expose them to users ([@qnighy])([#172]) -- `load_dotenv` and `dotenv_values` now accept an `encoding` parameter, defaults to `None` - ([@theskumar])([@earlbread])([#161]) -- Fix `str`/`unicode` inconsistency in Python 2: values are always `str` now. ([@bbc2])([#121]) -- Fix Unicode error in Python 2, introduced in 0.10.0. ([@bbc2])([#176]) - -## 0.10.1 -- Fix parsing of variable without a value ([@asyncee])([@bbc2])([#158]) - -## 0.10.0 - -- Add support for UTF-8 in unquoted values ([@bbc2])([#148]) -- Add support for trailing comments ([@bbc2])([#148]) -- Add backslashes support in values ([@bbc2])([#148]) -- Add support for newlines in values ([@bbc2])([#148]) -- Force environment variables to str with Python2 on Windows ([@greyli]) -- Drop Python 3.3 support ([@greyli]) -- Fix stderr/-out/-in redirection ([@venthur]) - - -## 0.9.0 - -- Add `--version` parameter to cli ([@venthur]) -- Enable loading from current directory ([@cjauvin]) -- Add 'dotenv run' command for calling arbitrary shell script with .env ([@venthur]) - -## 0.8.1 - -- Add tests for docs ([@Flimm]) -- Make 'cli' support optional. Use `pip install python-dotenv[cli]`. ([@theskumar]) - -## 0.8.0 - -- `set_key` and `unset_key` only modified the affected file instead of - parsing and re-writing file, this causes comments and other file - entact as it is. -- Add support for `export` prefix in the line. -- Internal refractoring ([@theskumar]) -- Allow `load_dotenv` and `dotenv_values` to work with `StringIO())` ([@alanjds])([@theskumar])([#78]) - -## 0.7.1 - -- Remove hard dependency on iPython ([@theskumar]) - -## 0.7.0 - -- Add support to override system environment variable via .env. - ([@milonimrod](https://github.com/milonimrod)) - ([\#63](https://github.com/theskumar/python-dotenv/issues/63)) -- Disable ".env not found" warning by default - ([@maxkoryukov](https://github.com/maxkoryukov)) - ([\#57](https://github.com/theskumar/python-dotenv/issues/57)) - -## 0.6.5 - -- Add support for special characters `\`. - ([@pjona](https://github.com/pjona)) - ([\#60](https://github.com/theskumar/python-dotenv/issues/60)) - -## 0.6.4 - -- Fix issue with single quotes ([@Flimm]) - ([\#52](https://github.com/theskumar/python-dotenv/issues/52)) - -## 0.6.3 - -- Handle unicode exception in setup.py - ([\#46](https://github.com/theskumar/python-dotenv/issues/46)) - -## 0.6.2 - -- Fix dotenv list command ([@ticosax](https://github.com/ticosax)) -- Add iPython Support - ([@tillahoffmann](https://github.com/tillahoffmann)) - -## 0.6.0 - -- Drop support for Python 2.6 -- Handle escaped characters and newlines in quoted values. (Thanks - [@iameugenejo](https://github.com/iameugenejo)) -- Remove any spaces around unquoted key/value. (Thanks - [@paulochf](https://github.com/paulochf)) -- Added POSIX variable expansion. (Thanks - [@hugochinchilla](https://github.com/hugochinchilla)) - -## 0.5.1 - -- Fix `find_dotenv` - it now start search from the file where this - function is called from. - -## 0.5.0 - -- Add `find_dotenv` method that will try to find a `.env` file. - (Thanks [@isms](https://github.com/isms)) - -## 0.4.0 - -- cli: Added `-q/--quote` option to control the behaviour of quotes - around values in `.env`. (Thanks - [@hugochinchilla](https://github.com/hugochinchilla)). -- Improved test coverage. - -[#78]: https://github.com/theskumar/python-dotenv/issues/78 -[#121]: https://github.com/theskumar/python-dotenv/issues/121 -[#148]: https://github.com/theskumar/python-dotenv/issues/148 -[#158]: https://github.com/theskumar/python-dotenv/issues/158 -[#170]: https://github.com/theskumar/python-dotenv/issues/170 -[#172]: https://github.com/theskumar/python-dotenv/issues/172 -[#176]: https://github.com/theskumar/python-dotenv/issues/176 -[#183]: https://github.com/theskumar/python-dotenv/issues/183 -[#359]: https://github.com/theskumar/python-dotenv/issues/359 -[#469]: https://github.com/theskumar/python-dotenv/issues/469 -[#456]: https://github.com/theskumar/python-dotenv/issues/456 -[#466]: https://github.com/theskumar/python-dotenv/issues/466 -[#454]: https://github.com/theskumar/python-dotenv/issues/454 -[#474]: https://github.com/theskumar/python-dotenv/issues/474 -[#523]: https://github.com/theskumar/python-dotenv/issues/523 -[#553]: https://github.com/theskumar/python-dotenv/issues/553 - -[@alanjds]: https://github.com/alanjds -[@altendky]: https://github.com/altendky -[@andrewsmith]: https://github.com/andrewsmith -[@asyncee]: https://github.com/asyncee -[@bbc2]: https://github.com/bbc2 -[@befeleme]: https://github.com/befeleme -[@cjauvin]: https://github.com/cjauvin -[@eaf]: https://github.com/eaf -[@earlbread]: https://github.com/earlbread -[@eekstunt]: https://github.com/eekstunt -[@eggplants]: https://github.com/@eggplants -[@ekohl]: https://github.com/ekohl -[@elbehery95]: https://github.com/elbehery95 -[@eumiro]: https://github.com/eumiro -[@Flimm]: https://github.com/Flimm -[@freddyaboulton]: https://github.com/freddyaboulton -[@gergelyk]: https://github.com/gergelyk -[@gongqingkui]: https://github.com/gongqingkui -[@greyli]: https://github.com/greyli -[@harveer07]: https://github.com/@harveer07 -[@jadutter]: https://github.com/jadutter -[@jankislinger]: https://github.com/jankislinger -[@jctanner]: https://github.com/jctanner -[@larsks]: https://github.com/@larsks -[@lsmith77]: https://github.com/lsmith77 -[@mgorny]: https://github.com/mgorny -[@naorlivne]: https://github.com/@naorlivne -[@Nicals]: https://github.com/Nicals -[@Nougat-Waffle]: https://github.com/Nougat-Waffle -[@qnighy]: https://github.com/qnighy -[@Qwerty-133]: https://github.com/Qwerty-133 -[@rabinadk1]: https://github.com/@rabinadk1 -[@sammck]: https://github.com/@sammck -[@samwyma]: https://github.com/samwyma -[@snobu]: https://github.com/snobu -[@techalchemy]: https://github.com/techalchemy -[@theGOTOguy]: https://github.com/theGOTOguy -[@theskumar]: https://github.com/theskumar -[@ulyssessouza]: https://github.com/ulyssessouza -[@venthur]: https://github.com/venthur -[@x-yuri]: https://github.com/x-yuri -[@yannham]: https://github.com/yannham -[@zueve]: https://github.com/zueve -[@randomseed42]: https://github.com/zueve - -[Unreleased]: https://github.com/theskumar/python-dotenv/compare/v1.0.1...HEAD -[1.0.1]: https://github.com/theskumar/python-dotenv/compare/v1.0.0...v1.0.1 -[1.0.0]: https://github.com/theskumar/python-dotenv/compare/v0.21.0...v1.0.0 -[0.21.1]: https://github.com/theskumar/python-dotenv/compare/v0.21.0...v0.21.1 -[0.21.0]: https://github.com/theskumar/python-dotenv/compare/v0.20.0...v0.21.0 -[0.20.0]: https://github.com/theskumar/python-dotenv/compare/v0.19.2...v0.20.0 -[0.19.2]: https://github.com/theskumar/python-dotenv/compare/v0.19.1...v0.19.2 -[0.19.1]: https://github.com/theskumar/python-dotenv/compare/v0.19.0...v0.19.1 -[0.19.0]: https://github.com/theskumar/python-dotenv/compare/v0.18.0...v0.19.0 -[0.18.0]: https://github.com/theskumar/python-dotenv/compare/v0.17.1...v0.18.0 -[0.17.1]: https://github.com/theskumar/python-dotenv/compare/v0.17.0...v0.17.1 -[0.17.0]: https://github.com/theskumar/python-dotenv/compare/v0.16.0...v0.17.0 -[0.16.0]: https://github.com/theskumar/python-dotenv/compare/v0.15.0...v0.16.0 -[0.15.0]: https://github.com/theskumar/python-dotenv/compare/v0.14.0...v0.15.0 -[0.14.0]: https://github.com/theskumar/python-dotenv/compare/v0.13.0...v0.14.0 -[0.13.0]: https://github.com/theskumar/python-dotenv/compare/v0.12.0...v0.13.0 -[0.12.0]: https://github.com/theskumar/python-dotenv/compare/v0.11.0...v0.12.0 -[0.11.0]: https://github.com/theskumar/python-dotenv/compare/v0.10.5...v0.11.0 -[0.10.5]: https://github.com/theskumar/python-dotenv/compare/v0.10.4...v0.10.5 -[0.10.4]: https://github.com/theskumar/python-dotenv/compare/v0.10.3...v0.10.4 diff --git a/venv/lib/python3.11/site-packages/python_dotenv-1.1.0.dist-info/RECORD b/venv/lib/python3.11/site-packages/python_dotenv-1.1.0.dist-info/RECORD deleted file mode 100755 index 8bf09aa..0000000 --- a/venv/lib/python3.11/site-packages/python_dotenv-1.1.0.dist-info/RECORD +++ /dev/null @@ -1,26 +0,0 @@ -../../../bin/dotenv,sha256=TYNlsC9DnLkEQdk3kdqvaZ-0IDpAKlEXIRwCXM0UD-Q,182 -dotenv/__init__.py,sha256=WBU5SfSiKAhS3hzu17ykNuuwbuwyDCX91Szv4vUeOuM,1292 -dotenv/__main__.py,sha256=N0RhLG7nHIqtlJHwwepIo-zbJPNx9sewCCRGY528h_4,129 -dotenv/__pycache__/__init__.cpython-311.pyc,, -dotenv/__pycache__/__main__.cpython-311.pyc,, -dotenv/__pycache__/cli.cpython-311.pyc,, -dotenv/__pycache__/ipython.cpython-311.pyc,, -dotenv/__pycache__/main.cpython-311.pyc,, -dotenv/__pycache__/parser.cpython-311.pyc,, -dotenv/__pycache__/variables.cpython-311.pyc,, -dotenv/__pycache__/version.cpython-311.pyc,, -dotenv/cli.py,sha256=Wj5dqgdk7dT5KfxCHPV6KCsnbKy00mKUV3avbhtNLH8,5759 -dotenv/ipython.py,sha256=avI6aez_RxnBptYgchIquF2TSgKI-GOhY3ppiu3VuWE,1303 -dotenv/main.py,sha256=JIhbi2M287Na5UTfco9YwdL34fXR6kvq1pQ5G6G6MJQ,12388 -dotenv/parser.py,sha256=QgU5HwMwM2wMqt0vz6dHTJ4nzPmwqRqvi4MSyeVifgU,5186 -dotenv/py.typed,sha256=8PjyZ1aVoQpRVvt71muvuq5qE-jTFZkK-GLHkhdebmc,26 -dotenv/variables.py,sha256=CD0qXOvvpB3q5RpBQMD9qX6vHX7SyW-SuiwGMFSlt08,2348 -dotenv/version.py,sha256=LGVQyDsWifdACo7qztwb8RWWHds1E7uQ-ZqD8SAjyw4,22 -python_dotenv-1.1.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -python_dotenv-1.1.0.dist-info/METADATA,sha256=ej7sfbeKQibafDIJgM8c-1F-KQyrYQEqFPxGXt09G58,24100 -python_dotenv-1.1.0.dist-info/RECORD,, -python_dotenv-1.1.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -python_dotenv-1.1.0.dist-info/WHEEL,sha256=DK49LOLCYiurdXXOXwGJm6U4DkHkg4lcxjhqwRa0CP4,91 -python_dotenv-1.1.0.dist-info/entry_points.txt,sha256=yRl1rCbswb1nQTQ_gZRlCw5QfabztUGnfGWLhlXFNdI,47 -python_dotenv-1.1.0.dist-info/licenses/LICENSE,sha256=gGGbcEnwjIFoOtDgHwjyV6hAZS3XHugxRtNmWMfSwrk,1556 -python_dotenv-1.1.0.dist-info/top_level.txt,sha256=eyqUH4SHJNr6ahOYlxIunTr4XinE8Z5ajWLdrK3r0D8,7 diff --git a/venv/lib/python3.11/site-packages/python_dotenv-1.1.0.dist-info/REQUESTED b/venv/lib/python3.11/site-packages/python_dotenv-1.1.0.dist-info/REQUESTED deleted file mode 100755 index e69de29..0000000 diff --git a/venv/lib/python3.11/site-packages/python_dotenv-1.1.0.dist-info/WHEEL b/venv/lib/python3.11/site-packages/python_dotenv-1.1.0.dist-info/WHEEL deleted file mode 100755 index 91720dd..0000000 --- a/venv/lib/python3.11/site-packages/python_dotenv-1.1.0.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: setuptools (78.0.2) -Root-Is-Purelib: true -Tag: py3-none-any - diff --git a/venv/lib/python3.11/site-packages/python_dotenv-1.1.0.dist-info/entry_points.txt b/venv/lib/python3.11/site-packages/python_dotenv-1.1.0.dist-info/entry_points.txt deleted file mode 100755 index 0a86823..0000000 --- a/venv/lib/python3.11/site-packages/python_dotenv-1.1.0.dist-info/entry_points.txt +++ /dev/null @@ -1,2 +0,0 @@ -[console_scripts] -dotenv = dotenv.__main__:cli diff --git a/venv/lib/python3.11/site-packages/python_dotenv-1.1.0.dist-info/licenses/LICENSE b/venv/lib/python3.11/site-packages/python_dotenv-1.1.0.dist-info/licenses/LICENSE deleted file mode 100755 index 3a97119..0000000 --- a/venv/lib/python3.11/site-packages/python_dotenv-1.1.0.dist-info/licenses/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2014, Saurabh Kumar (python-dotenv), 2013, Ted Tieken (django-dotenv-rw), 2013, Jacob Kaplan-Moss (django-dotenv) - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -- Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - -- Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -- Neither the name of django-dotenv nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/venv/lib/python3.11/site-packages/python_dotenv-1.1.0.dist-info/top_level.txt b/venv/lib/python3.11/site-packages/python_dotenv-1.1.0.dist-info/top_level.txt deleted file mode 100755 index fe7c01a..0000000 --- a/venv/lib/python3.11/site-packages/python_dotenv-1.1.0.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -dotenv diff --git a/venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/INSTALLER b/venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/INSTALLER deleted file mode 100755 index a1b589e..0000000 --- a/venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/METADATA b/venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/METADATA deleted file mode 100755 index c245665..0000000 --- a/venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/METADATA +++ /dev/null @@ -1,299 +0,0 @@ -Metadata-Version: 2.4 -Name: python-telegram-bot -Version: 21.10 -Summary: We have made you a wrapper you can't refuse -Project-URL: Homepage, https://python-telegram-bot.org -Project-URL: Documentation, https://docs.python-telegram-bot.org -Project-URL: Bug Tracker, https://github.com/python-telegram-bot/python-telegram-bot/issues -Project-URL: Source Code, https://github.com/python-telegram-bot/python-telegram-bot -Project-URL: News, https://t.me/pythontelegrambotchannel -Project-URL: Changelog, https://docs.python-telegram-bot.org/en/stable/changelog.html -Project-URL: Support, https://t.me/pythontelegrambotgroup -Author-email: Leandro Toledo -License-Expression: LGPL-3.0-only -License-File: LICENSE -License-File: LICENSE.dual -License-File: LICENSE.lesser -Keywords: api,bot,python,telegram,wrapper -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3) -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.9 -Classifier: Programming Language :: Python :: 3.10 -Classifier: Programming Language :: Python :: 3.11 -Classifier: Programming Language :: Python :: 3.12 -Classifier: Programming Language :: Python :: 3.13 -Classifier: Topic :: Communications :: Chat -Classifier: Topic :: Internet -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Requires-Python: >=3.9 -Requires-Dist: httpx~=0.27 -Provides-Extra: all -Requires-Dist: aiolimiter<1.3,>=1.1; extra == 'all' -Requires-Dist: apscheduler<3.12.0,>=3.10.4; extra == 'all' -Requires-Dist: cachetools<5.6.0,>=5.3.3; extra == 'all' -Requires-Dist: cffi>=1.17.0rc1; (python_version > '3.12') and extra == 'all' -Requires-Dist: cryptography!=3.4,!=3.4.1,!=3.4.2,!=3.4.3,>=39.0.1; extra == 'all' -Requires-Dist: httpx[http2]; extra == 'all' -Requires-Dist: httpx[socks]; extra == 'all' -Requires-Dist: tornado~=6.4; extra == 'all' -Provides-Extra: callback-data -Requires-Dist: cachetools<5.6.0,>=5.3.3; extra == 'callback-data' -Provides-Extra: ext -Requires-Dist: aiolimiter<1.3,>=1.1; extra == 'ext' -Requires-Dist: apscheduler<3.12.0,>=3.10.4; extra == 'ext' -Requires-Dist: cachetools<5.6.0,>=5.3.3; extra == 'ext' -Requires-Dist: tornado~=6.4; extra == 'ext' -Provides-Extra: http2 -Requires-Dist: httpx[http2]; extra == 'http2' -Provides-Extra: job-queue -Requires-Dist: apscheduler<3.12.0,>=3.10.4; extra == 'job-queue' -Provides-Extra: passport -Requires-Dist: cffi>=1.17.0rc1; (python_version > '3.12') and extra == 'passport' -Requires-Dist: cryptography!=3.4,!=3.4.1,!=3.4.2,!=3.4.3,>=39.0.1; extra == 'passport' -Provides-Extra: rate-limiter -Requires-Dist: aiolimiter<1.3,>=1.1; extra == 'rate-limiter' -Provides-Extra: socks -Requires-Dist: httpx[socks]; extra == 'socks' -Provides-Extra: webhooks -Requires-Dist: tornado~=6.4; extra == 'webhooks' -Description-Content-Type: text/x-rst - -.. image:: https://raw.githubusercontent.com/python-telegram-bot/logos/master/logo-text/png/ptb-logo-text_768.png - :align: center - :target: https://python-telegram-bot.org - :alt: python-telegram-bot Logo - -.. image:: https://img.shields.io/pypi/v/python-telegram-bot.svg - :target: https://pypi.org/project/python-telegram-bot/ - :alt: PyPi Package Version - -.. image:: https://img.shields.io/pypi/pyversions/python-telegram-bot.svg - :target: https://pypi.org/project/python-telegram-bot/ - :alt: Supported Python versions - -.. image:: https://img.shields.io/badge/Bot%20API-8.2-blue?logo=telegram - :target: https://core.telegram.org/bots/api-changelog - :alt: Supported Bot API version - -.. image:: https://img.shields.io/pypi/dm/python-telegram-bot - :target: https://pypistats.org/packages/python-telegram-bot - :alt: PyPi Package Monthly Download - -.. image:: https://readthedocs.org/projects/python-telegram-bot/badge/?version=stable - :target: https://docs.python-telegram-bot.org/en/stable/ - :alt: Documentation Status - -.. image:: https://img.shields.io/pypi/l/python-telegram-bot.svg - :target: https://www.gnu.org/licenses/lgpl-3.0.html - :alt: LGPLv3 License - -.. image:: https://github.com/python-telegram-bot/python-telegram-bot/actions/workflows/unit_tests.yml/badge.svg?branch=master - :target: https://github.com/python-telegram-bot/python-telegram-bot/ - :alt: Github Actions workflow - -.. image:: https://codecov.io/gh/python-telegram-bot/python-telegram-bot/branch/master/graph/badge.svg - :target: https://app.codecov.io/gh/python-telegram-bot/python-telegram-bot - :alt: Code coverage - -.. image:: https://isitmaintained.com/badge/resolution/python-telegram-bot/python-telegram-bot.svg - :target: https://isitmaintained.com/project/python-telegram-bot/python-telegram-bot - :alt: Median time to resolve an issue - -.. image:: https://api.codacy.com/project/badge/Grade/99d901eaa09b44b4819aec05c330c968 - :target: https://app.codacy.com/gh/python-telegram-bot/python-telegram-bot/dashboard - :alt: Code quality: Codacy - -.. image:: https://results.pre-commit.ci/badge/github/python-telegram-bot/python-telegram-bot/master.svg - :target: https://results.pre-commit.ci/latest/github/python-telegram-bot/python-telegram-bot/master - :alt: pre-commit.ci status - -.. image:: https://img.shields.io/badge/code%20style-black-000000.svg - :target: https://github.com/psf/black - :alt: Code Style: Black - -.. image:: https://img.shields.io/badge/Telegram-Channel-blue.svg?logo=telegram - :target: https://t.me/pythontelegrambotchannel - :alt: Telegram Channel - -.. image:: https://img.shields.io/badge/Telegram-Group-blue.svg?logo=telegram - :target: https://telegram.me/pythontelegrambotgroup - :alt: Telegram Group - -We have made you a wrapper you can't refuse - -We have a vibrant community of developers helping each other in our `Telegram group `_. Join us! - -*Stay tuned for library updates and new releases on our* `Telegram Channel `_. - -Introduction ------------- - -This library provides a pure Python, asynchronous interface for the -`Telegram Bot API `_. -It's compatible with Python versions **3.9+**. - -In addition to the pure API implementation, this library features several convenience methods and shortcuts as well as a number of high-level classes to -make the development of bots easy and straightforward. These classes are contained in the -``telegram.ext`` submodule. - -After installing_ the library, be sure to check out the section on `working with PTB`_. - -Telegram API support -~~~~~~~~~~~~~~~~~~~~ - -All types and methods of the Telegram Bot API **8.2** are natively supported by this library. -In addition, Bot API functionality not yet natively included can still be used as described `in our wiki `_. - -Notable Features -~~~~~~~~~~~~~~~~ - -- `Fully asynchronous `_ -- Convenient shortcut methods, e.g. `Message.reply_text `_ -- `Fully annotated with static type hints `_ -- `Customizable and extendable interface `_ -- Seamless integration with `webhooks `_ and `polling `_ -- `Comprehensive documentation and examples <#working-with-ptb>`_ - -Installing ----------- - -You can install or upgrade ``python-telegram-bot`` via - -.. code:: shell - - $ pip install python-telegram-bot --upgrade - -To install a pre-release, use the ``--pre`` `flag `_ in addition. - -You can also install ``python-telegram-bot`` from source, though this is usually not necessary. - -.. code:: shell - - $ git clone https://github.com/python-telegram-bot/python-telegram-bot - $ cd python-telegram-bot - $ pip install build - $ python -m build - -Verifying Releases -~~~~~~~~~~~~~~~~~~ - -To enable you to verify that a release file that you downloaded was indeed provided by the ``python-telegram-bot`` team, we have taken the following measures. - -Starting with v21.4, all releases are signed via `sigstore `_. -The corresponding signature files are uploaded to the `GitHub releases page`_. -To verify the signature, please install the `sigstore Python client `_ and follow the instructions for `verifying signatures from GitHub Actions `_. As input for the ``--repository`` parameter, please use the value ``python-telegram-bot/python-telegram-bot``. - -Earlier releases are signed with a GPG key. -The signatures are uploaded to both the `GitHub releases page`_ and the `PyPI project `_ and end with a suffix ``.asc``. -Please find the public keys `here `_. -The keys are named in the format ``-.gpg``. - -In addition, the GitHub release page also contains the sha1 hashes of the release files in the files with the suffix ``.sha1``. - -Dependencies & Their Versions -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -``python-telegram-bot`` tries to use as few 3rd party dependencies as possible. -However, for some features using a 3rd party library is more sane than implementing the functionality again. -As these features are *optional*, the corresponding 3rd party dependencies are not installed by default. -Instead, they are listed as optional dependencies. -This allows to avoid unnecessary dependency conflicts for users who don't need the optional features. - -The only required dependency is `httpx ~= 0.27 `_ for -``telegram.request.HTTPXRequest``, the default networking backend. - -``python-telegram-bot`` is most useful when used along with additional libraries. -To minimize dependency conflicts, we try to be liberal in terms of version requirements on the (optional) dependencies. -On the other hand, we have to ensure stability of ``python-telegram-bot``, which is why we do apply version bounds. -If you encounter dependency conflicts due to these bounds, feel free to reach out. - -Optional Dependencies -##################### - -PTB can be installed with optional dependencies: - -* ``pip install "python-telegram-bot[passport]"`` installs the `cryptography>=39.0.1 `_ library. Use this, if you want to use Telegram Passport related functionality. -* ``pip install "python-telegram-bot[socks]"`` installs `httpx[socks] `_. Use this, if you want to work behind a Socks5 server. -* ``pip install "python-telegram-bot[http2]"`` installs `httpx[http2] `_. Use this, if you want to use HTTP/2. -* ``pip install "python-telegram-bot[rate-limiter]"`` installs `aiolimiter~=1.1,<1.3 `_. Use this, if you want to use ``telegram.ext.AIORateLimiter``. -* ``pip install "python-telegram-bot[webhooks]"`` installs the `tornado~=6.4 `_ library. Use this, if you want to use ``telegram.ext.Updater.start_webhook``/``telegram.ext.Application.run_webhook``. -* ``pip install "python-telegram-bot[callback-data]"`` installs the `cachetools>=5.3.3,<5.6.0 `_ library. Use this, if you want to use `arbitrary callback_data `_. -* ``pip install "python-telegram-bot[job-queue]"`` installs the `APScheduler>=3.10.4,<3.12.0 `_ library. Use this, if you want to use the ``telegram.ext.JobQueue``. - -To install multiple optional dependencies, separate them by commas, e.g. ``pip install "python-telegram-bot[socks,webhooks]"``. - -Additionally, two shortcuts are provided: - -* ``pip install "python-telegram-bot[all]"`` installs all optional dependencies. -* ``pip install "python-telegram-bot[ext]"`` installs all optional dependencies that are related to ``telegram.ext``, i.e. ``[rate-limiter, webhooks, callback-data, job-queue]``. - -Working with PTB ----------------- - -Once you have installed the library, you can begin working with it - so let's get started! - -Quick Start -~~~~~~~~~~~ - -Our Wiki contains an `Introduction to the API `_ explaining how the pure Bot API can be accessed via ``python-telegram-bot``. -Moreover, the `Tutorial: Your first Bot `_ gives an introduction on how chatbots can be easily programmed with the help of the ``telegram.ext`` module. - -Resources -~~~~~~~~~ - -- The `package documentation `_ is the technical reference for ``python-telegram-bot``. - It contains descriptions of all available classes, modules, methods and arguments as well as the `changelog `_. -- The `wiki `_ is home to number of more elaborate introductions of the different features of ``python-telegram-bot`` and other useful resources that go beyond the technical documentation. -- Our `examples section `_ contains several examples that showcase the different features of both the Bot API and ``python-telegram-bot``. - Even if it is not your approach for learning, please take a look at ``echobot.py``. It is the de facto base for most of the bots out there. - The code for these examples is released to the public domain, so you can start by grabbing the code and building on top of it. -- The `official Telegram Bot API documentation `_ is of course always worth a read. - -Getting help -~~~~~~~~~~~~ - -If the resources mentioned above don't answer your questions or simply overwhelm you, there are several ways of getting help. - -1. We have a vibrant community of developers helping each other in our `Telegram group `_. Join us! Asking a question here is often the quickest way to get a pointer in the right direction. - -2. Ask questions by opening `a discussion `_. - -3. You can even ask for help on Stack Overflow using the `python-telegram-bot tag `_. - -Concurrency -~~~~~~~~~~~ - -Since v20.0, ``python-telegram-bot`` is built on top of Pythons ``asyncio`` module. -Because ``asyncio`` is in general single-threaded, ``python-telegram-bot`` does currently not aim to be thread-safe. -Noteworthy parts of ``python-telegram-bots`` API that are likely to cause issues (e.g. race conditions) when used in a multi-threaded setting include: - -* ``telegram.ext.Application/Updater.update_queue`` -* ``telegram.ext.ConversationHandler.check/handle_update`` -* ``telegram.ext.CallbackDataCache`` -* ``telegram.ext.BasePersistence`` -* all classes in the ``telegram.ext.filters`` module that allow to add/remove allowed users/chats at runtime - -Contributing ------------- - -Contributions of all sizes are welcome. -Please review our `contribution guidelines `_ to get started. -You can also help by `reporting bugs or feature requests `_. - -Donating --------- -Occasionally we are asked if we accept donations to support the development. -While we appreciate the thought, maintaining PTB is our hobby, and we have almost no running costs for it. We therefore have nothing set up to accept donations. -If you still want to donate, we kindly ask you to donate to another open source project/initiative of your choice instead. - -License -------- - -You may copy, distribute and modify the software provided that modifications are described and licensed for free under `LGPL-3 `_. -Derivative works (including modifications or anything statically linked to the library) can only be redistributed under LGPL-3, but applications that use the library don't have to be. - -.. _`GitHub releases page`: https://github.com/python-telegram-bot/python-telegram-bot/releases diff --git a/venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/RECORD b/venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/RECORD deleted file mode 100755 index 25b2270..0000000 --- a/venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/RECORD +++ /dev/null @@ -1,425 +0,0 @@ -python_telegram_bot-21.10.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -python_telegram_bot-21.10.dist-info/METADATA,sha256=X3SPCzpX4cVXdwqR2StHIEd0-WT-X8O5Ih9kR-_agCk,17038 -python_telegram_bot-21.10.dist-info/RECORD,, -python_telegram_bot-21.10.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -python_telegram_bot-21.10.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87 -python_telegram_bot-21.10.dist-info/licenses/LICENSE,sha256=rY-GA-hD-Jc4hTE-PaXmPl1SLVDDqHaHXUuWu_tJ4RI,32422 -python_telegram_bot-21.10.dist-info/licenses/LICENSE.dual,sha256=eblsAdLmpvSxNh8leJceEVCwU7rNitnIgMs8X_kIEd8,40192 -python_telegram_bot-21.10.dist-info/licenses/LICENSE.lesser,sha256=jhxgj_Bo2unwLKfth30xD0h3N28guEWKtWgVIpcDHvw,7651 -telegram/__init__.py,sha256=aCf9tO3fq2wDPkELoKz-9pzaJXpnd1SsOHessmiDlvE,17796 -telegram/__main__.py,sha256=0ejHx4Zy-YWEo9IS93HKE9Smd0iGg4BANp1lrxvQUGg,1857 -telegram/__pycache__/__init__.cpython-311.pyc,, -telegram/__pycache__/__main__.cpython-311.pyc,, -telegram/__pycache__/_birthdate.cpython-311.pyc,, -telegram/__pycache__/_bot.cpython-311.pyc,, -telegram/__pycache__/_botcommand.cpython-311.pyc,, -telegram/__pycache__/_botcommandscope.cpython-311.pyc,, -telegram/__pycache__/_botdescription.cpython-311.pyc,, -telegram/__pycache__/_botname.cpython-311.pyc,, -telegram/__pycache__/_business.cpython-311.pyc,, -telegram/__pycache__/_callbackquery.cpython-311.pyc,, -telegram/__pycache__/_chat.cpython-311.pyc,, -telegram/__pycache__/_chatadministratorrights.cpython-311.pyc,, -telegram/__pycache__/_chatbackground.cpython-311.pyc,, -telegram/__pycache__/_chatboost.cpython-311.pyc,, -telegram/__pycache__/_chatfullinfo.cpython-311.pyc,, -telegram/__pycache__/_chatinvitelink.cpython-311.pyc,, -telegram/__pycache__/_chatjoinrequest.cpython-311.pyc,, -telegram/__pycache__/_chatlocation.cpython-311.pyc,, -telegram/__pycache__/_chatmember.cpython-311.pyc,, -telegram/__pycache__/_chatmemberupdated.cpython-311.pyc,, -telegram/__pycache__/_chatpermissions.cpython-311.pyc,, -telegram/__pycache__/_choseninlineresult.cpython-311.pyc,, -telegram/__pycache__/_copytextbutton.cpython-311.pyc,, -telegram/__pycache__/_dice.cpython-311.pyc,, -telegram/__pycache__/_forcereply.cpython-311.pyc,, -telegram/__pycache__/_forumtopic.cpython-311.pyc,, -telegram/__pycache__/_gifts.cpython-311.pyc,, -telegram/__pycache__/_giveaway.cpython-311.pyc,, -telegram/__pycache__/_keyboardbutton.cpython-311.pyc,, -telegram/__pycache__/_keyboardbuttonpolltype.cpython-311.pyc,, -telegram/__pycache__/_keyboardbuttonrequest.cpython-311.pyc,, -telegram/__pycache__/_linkpreviewoptions.cpython-311.pyc,, -telegram/__pycache__/_loginurl.cpython-311.pyc,, -telegram/__pycache__/_menubutton.cpython-311.pyc,, -telegram/__pycache__/_message.cpython-311.pyc,, -telegram/__pycache__/_messageautodeletetimerchanged.cpython-311.pyc,, -telegram/__pycache__/_messageentity.cpython-311.pyc,, -telegram/__pycache__/_messageid.cpython-311.pyc,, -telegram/__pycache__/_messageorigin.cpython-311.pyc,, -telegram/__pycache__/_messagereactionupdated.cpython-311.pyc,, -telegram/__pycache__/_paidmedia.cpython-311.pyc,, -telegram/__pycache__/_poll.cpython-311.pyc,, -telegram/__pycache__/_proximityalerttriggered.cpython-311.pyc,, -telegram/__pycache__/_reaction.cpython-311.pyc,, -telegram/__pycache__/_reply.cpython-311.pyc,, -telegram/__pycache__/_replykeyboardmarkup.cpython-311.pyc,, -telegram/__pycache__/_replykeyboardremove.cpython-311.pyc,, -telegram/__pycache__/_sentwebappmessage.cpython-311.pyc,, -telegram/__pycache__/_shared.cpython-311.pyc,, -telegram/__pycache__/_story.cpython-311.pyc,, -telegram/__pycache__/_switchinlinequerychosenchat.cpython-311.pyc,, -telegram/__pycache__/_telegramobject.cpython-311.pyc,, -telegram/__pycache__/_update.cpython-311.pyc,, -telegram/__pycache__/_user.cpython-311.pyc,, -telegram/__pycache__/_userprofilephotos.cpython-311.pyc,, -telegram/__pycache__/_version.cpython-311.pyc,, -telegram/__pycache__/_videochat.cpython-311.pyc,, -telegram/__pycache__/_webappdata.cpython-311.pyc,, -telegram/__pycache__/_webappinfo.cpython-311.pyc,, -telegram/__pycache__/_webhookinfo.cpython-311.pyc,, -telegram/__pycache__/_writeaccessallowed.cpython-311.pyc,, -telegram/__pycache__/constants.cpython-311.pyc,, -telegram/__pycache__/error.cpython-311.pyc,, -telegram/__pycache__/helpers.cpython-311.pyc,, -telegram/__pycache__/warnings.cpython-311.pyc,, -telegram/_birthdate.py,sha256=dXURp_xNK7NNMen0jqAsEzLBlgWWDEayvrClslJW4zc,3019 -telegram/_bot.py,sha256=dY5FRFbaUPSwzl2EH47iUGhaZ8ckjQK2et0Htn1iSp0,426951 -telegram/_botcommand.py,sha256=-cC7_D3MNDg0P1Z0SpogUfe9m5NjZw-70-zJHUJWodc,3273 -telegram/_botcommandscope.py,sha256=PDkMjZBACxNsAnm3-VPnXNaFbNLVnuuMAStHWS5k9ug,10625 -telegram/_botdescription.py,sha256=Hlql0xjqmDJg6iY10tqCoRY1jX5i1x9k4JnpFmi-2jU,2511 -telegram/_botname.py,sha256=-5ZBG9zCGnFb4V3GufwuxoAen1iwK1IrPhGEU90BTk0,1805 -telegram/_business.py,sha256=fiPlzrCBlww0bPkmezYVq-gtWf7rS3tReV_LR0dNfts,15973 -telegram/_callbackquery.py,sha256=4KcVujlR3Cjqc8DfYXAdrcdBYABbfnB5zJgOAJAFsP0,34301 -telegram/_chat.py,sha256=GWeO70QKI9vsvjUUy3DfLVogS5apBdo7cnUikSALVYA,134760 -telegram/_chatadministratorrights.py,sha256=atiBFFtwPtTV783pE7_hLYeLALjB0bXuqyRo6Pn131o,11560 -telegram/_chatbackground.py,sha256=PGPaWoInhmvOYA0moWkifBHvqqBB2mO-fEH9ZF2fL_g,19715 -telegram/_chatboost.py,sha256=AauSELgsQ4W7yRQ1gWCaNYt7Y2JYeFZ8tunMnw75Boo,16378 -telegram/_chatfullinfo.py,sha256=yw43TynYLVcBPWux8tMIc--VxWXqb4AkpNoYS1xjZlo,27000 -telegram/_chatinvitelink.py,sha256=90QwECW2NooRcTCS7CLMeM5FmXKeFOp3T-3yESMbxfc,7970 -telegram/_chatjoinrequest.py,sha256=_UlOs52jPJH5l0OlFvq7ZXcPHNifBG1AbtAYkgoSYL0,8774 -telegram/_chatlocation.py,sha256=0tGzL8oMVSVMh0Bj8RtlmV234u-2Gg3JDj1KdHElHTw,3327 -telegram/_chatmember.py,sha256=ZhI5f8JposvWnq-FeWoLjlYpKniQ11FWgxRU_sT_Js0,27434 -telegram/_chatmemberupdated.py,sha256=vElozXn5NNUPUWr_0FzGnPLJ6Ksx1IcOXOksZrq5tcI,8626 -telegram/_chatpermissions.py,sha256=8zfgtkVpNVmV6WpgTI2yioQmbxNfWqZYu-KM_QHNUtg,10948 -telegram/_choseninlineresult.py,sha256=KZxNRJUZ1PTFjyO6GwiLQly_3WOBU0Qv1vTZ9r2o-dA,4305 -telegram/_copytextbutton.py,sha256=g6AwVFUEYE5Sz0qN6KgDaEMmyAwuCz_rIvBGS5RQEIA,2108 -telegram/_dice.py,sha256=JVB9ogh_VWY0ut7uYvyn4R-Fh11LEtdMyDtp-TaVxk4,6950 -telegram/_files/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -telegram/_files/__pycache__/__init__.cpython-311.pyc,, -telegram/_files/__pycache__/_basemedium.cpython-311.pyc,, -telegram/_files/__pycache__/_basethumbedmedium.cpython-311.pyc,, -telegram/_files/__pycache__/animation.cpython-311.pyc,, -telegram/_files/__pycache__/audio.cpython-311.pyc,, -telegram/_files/__pycache__/chatphoto.cpython-311.pyc,, -telegram/_files/__pycache__/contact.cpython-311.pyc,, -telegram/_files/__pycache__/document.cpython-311.pyc,, -telegram/_files/__pycache__/file.cpython-311.pyc,, -telegram/_files/__pycache__/inputfile.cpython-311.pyc,, -telegram/_files/__pycache__/inputmedia.cpython-311.pyc,, -telegram/_files/__pycache__/inputsticker.cpython-311.pyc,, -telegram/_files/__pycache__/location.cpython-311.pyc,, -telegram/_files/__pycache__/photosize.cpython-311.pyc,, -telegram/_files/__pycache__/sticker.cpython-311.pyc,, -telegram/_files/__pycache__/venue.cpython-311.pyc,, -telegram/_files/__pycache__/video.cpython-311.pyc,, -telegram/_files/__pycache__/videonote.cpython-311.pyc,, -telegram/_files/__pycache__/voice.cpython-311.pyc,, -telegram/_files/_basemedium.py,sha256=_zeUgKXNuiC5e4DzLPdPKcy25EbURcSelPIvgfAI9lo,3536 -telegram/_files/_basethumbedmedium.py,sha256=MF4I0DZ0kc0bJhX5Juv_gE1FIyrrJRzR6bpTHiQJSJ4,3855 -telegram/_files/animation.py,sha256=e1jbm3dMkHpQCGQadoKyLQn9fZyVJW9WdtZAb7pueB4,4312 -telegram/_files/audio.py,sha256=T9JQ72aJ1sj1JY7dhPlXXvVD_wLZp8jA7_7xYtoux5A,4537 -telegram/_files/chatphoto.py,sha256=BMwLG84Gh-5CaxmtdhcmgjRWyVfqQ2Ghz-frRD4Qo7g,7096 -telegram/_files/contact.py,sha256=GEarK_9iNCiJyv4vUmrwMGdAkQ6lE6LA8v5_GMH5Wvs,2720 -telegram/_files/document.py,sha256=Bxd3znFS3KXQpsYubgWHbjzy0Axl5MKOPyQ2Ijmkwpg,3600 -telegram/_files/file.py,sha256=WHeF04pn4TY5kp15kKj60ftv_LUYi9R0cCZmJO7G-kU,15847 -telegram/_files/inputfile.py,sha256=bIUk42XMm9vvb5ui6RJpXr6SQ2ECIXAuuOgTsa8cmL8,5965 -telegram/_files/inputmedia.py,sha256=kSOeBfVaA0z39n7_rNZ-6hfEYsw1mdBwz5CaCOR0xWw,34494 -telegram/_files/inputsticker.py,sha256=XCAgXNsF5e6ivINyBGGREHUzMFpxbeVkgNy6Ha1k8IQ,5690 -telegram/_files/location.py,sha256=aHo2VP02IHG4wbPuRr8JHF8SuKDbxepX7n1uHI_W9PQ,4778 -telegram/_files/photosize.py,sha256=U_xMAdYzB3g3qp-Qw23P-X6xWwehKvv-gyAAgW5CiKU,2826 -telegram/_files/sticker.py,sha256=n1kzLkpJjbkbDpMAoo_8I1Iu0BoFWeoZwfzE4nj_Kvg,15920 -telegram/_files/venue.py,sha256=T1AgasYenMUV47MTA8KlpMiFNGkuxeiAlr71DAu9aQY,4483 -telegram/_files/video.py,sha256=5EtoQqSPUrlLtWmmx2K-R3Vxu2dcTnpAvolJPhirXzA,4154 -telegram/_files/videonote.py,sha256=WgHOg4zfe0agS-97RmEh3yx3bLzqnMYlj1IeDoBnco0,3524 -telegram/_files/voice.py,sha256=yUoK1ZNhVAl1LoFDU41SPYcCB3WyZlQBRlIRv1ERqBo,3047 -telegram/_forcereply.py,sha256=SBjE2HlTB4eYVgFr9QPufsmLjDNYOwmOaPL-x07q-aA,4535 -telegram/_forumtopic.py,sha256=k74-37dMu8ogh7FuzfIaNEHNHy_9JlRri8GoB9Td2l0,6965 -telegram/_games/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -telegram/_games/__pycache__/__init__.cpython-311.pyc,, -telegram/_games/__pycache__/callbackgame.cpython-311.pyc,, -telegram/_games/__pycache__/game.cpython-311.pyc,, -telegram/_games/__pycache__/gamehighscore.cpython-311.pyc,, -telegram/_games/callbackgame.py,sha256=HYcnymZZEe9P2hdopH4Eo9er-4_Prr11JC-nuyblxJ8,1309 -telegram/_games/game.py,sha256=xdeSs9ADTUkfon-FLGZ1gR_5LLOwoaEWVBNPIqoZl3k,8210 -telegram/_games/gamehighscore.py,sha256=Gdulz6yLjwZ7c--IMXkFzO-Wy_QRRN4kE047n2eZXWc,2549 -telegram/_gifts.py,sha256=nnSNuFWmVnDHbUi-ZjUmF86U-z8Fqujgk8K0RO4Itzc,5319 -telegram/_giveaway.py,sha256=_s6z8rLCG2zHXLYLb3mfVz09rJ_tc8IhWKWmmpSeVIQ,17230 -telegram/_inline/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -telegram/_inline/__pycache__/__init__.cpython-311.pyc,, -telegram/_inline/__pycache__/inlinekeyboardbutton.cpython-311.pyc,, -telegram/_inline/__pycache__/inlinekeyboardmarkup.cpython-311.pyc,, -telegram/_inline/__pycache__/inlinequery.cpython-311.pyc,, -telegram/_inline/__pycache__/inlinequeryresult.cpython-311.pyc,, -telegram/_inline/__pycache__/inlinequeryresultarticle.cpython-311.pyc,, -telegram/_inline/__pycache__/inlinequeryresultaudio.cpython-311.pyc,, -telegram/_inline/__pycache__/inlinequeryresultcachedaudio.cpython-311.pyc,, -telegram/_inline/__pycache__/inlinequeryresultcacheddocument.cpython-311.pyc,, -telegram/_inline/__pycache__/inlinequeryresultcachedgif.cpython-311.pyc,, -telegram/_inline/__pycache__/inlinequeryresultcachedmpeg4gif.cpython-311.pyc,, -telegram/_inline/__pycache__/inlinequeryresultcachedphoto.cpython-311.pyc,, -telegram/_inline/__pycache__/inlinequeryresultcachedsticker.cpython-311.pyc,, -telegram/_inline/__pycache__/inlinequeryresultcachedvideo.cpython-311.pyc,, -telegram/_inline/__pycache__/inlinequeryresultcachedvoice.cpython-311.pyc,, -telegram/_inline/__pycache__/inlinequeryresultcontact.cpython-311.pyc,, -telegram/_inline/__pycache__/inlinequeryresultdocument.cpython-311.pyc,, -telegram/_inline/__pycache__/inlinequeryresultgame.cpython-311.pyc,, -telegram/_inline/__pycache__/inlinequeryresultgif.cpython-311.pyc,, -telegram/_inline/__pycache__/inlinequeryresultlocation.cpython-311.pyc,, -telegram/_inline/__pycache__/inlinequeryresultmpeg4gif.cpython-311.pyc,, -telegram/_inline/__pycache__/inlinequeryresultphoto.cpython-311.pyc,, -telegram/_inline/__pycache__/inlinequeryresultsbutton.cpython-311.pyc,, -telegram/_inline/__pycache__/inlinequeryresultvenue.cpython-311.pyc,, -telegram/_inline/__pycache__/inlinequeryresultvideo.cpython-311.pyc,, -telegram/_inline/__pycache__/inlinequeryresultvoice.cpython-311.pyc,, -telegram/_inline/__pycache__/inputcontactmessagecontent.cpython-311.pyc,, -telegram/_inline/__pycache__/inputinvoicemessagecontent.cpython-311.pyc,, -telegram/_inline/__pycache__/inputlocationmessagecontent.cpython-311.pyc,, -telegram/_inline/__pycache__/inputmessagecontent.cpython-311.pyc,, -telegram/_inline/__pycache__/inputtextmessagecontent.cpython-311.pyc,, -telegram/_inline/__pycache__/inputvenuemessagecontent.cpython-311.pyc,, -telegram/_inline/__pycache__/preparedinlinemessage.cpython-311.pyc,, -telegram/_inline/inlinekeyboardbutton.py,sha256=a7rllnIEJ6TQywKprVYtYLK403nlUuQ6ptTY04smQWg,16281 -telegram/_inline/inlinekeyboardmarkup.py,sha256=BnA7xh0VMo0BuTv-oOuP91BsYfrp7HGJMcggrpj9JUg,5649 -telegram/_inline/inlinequery.py,sha256=pGxYHWD873tSq4_829vWis2o8zh1iJJOECzzWcwzbqk,9269 -telegram/_inline/inlinequeryresult.py,sha256=RLt3d2v6N7ZQBYr2oz9WjJr3w7z2rulfRNHbHEODGHo,2838 -telegram/_inline/inlinequeryresultarticle.py,sha256=hoA8NSlkQAkhzjFskikgVPHBu5lohqMzp_TlBfyv2eg,6050 -telegram/_inline/inlinequeryresultaudio.py,sha256=owbM_1BXqT8CBEdVQoeCXEabkFpCLd7aehJn8Ti1jQ4,5715 -telegram/_inline/inlinequeryresultcachedaudio.py,sha256=6X3JfWDriRwftldu9lWCT9PJ-DsSxUs-I307DsWPZys,5158 -telegram/_inline/inlinequeryresultcacheddocument.py,sha256=raTjKftOcEG7pug-Sk8WIRNmqoArLcGpkYIY3Iu_5oI,5686 -telegram/_inline/inlinequeryresultcachedgif.py,sha256=el5BUnn0Cjg5Bde1rSiBXTYfbPSdUv2xvup5N1AUtSI,5856 -telegram/_inline/inlinequeryresultcachedmpeg4gif.py,sha256=n-5_nkkXcOWDY1MDfc2HhPASNY4CcAs39WtVFDYXXEg,5947 -telegram/_inline/inlinequeryresultcachedphoto.py,sha256=V5UY7eAVMKfKJmnR2hNAly2olMAfbVmByYb2-qqnPWI,6112 -telegram/_inline/inlinequeryresultcachedsticker.py,sha256=akPCH9oJbflN-30oTl0JVPvID64omK3ghTDtPlTZd40,3659 -telegram/_inline/inlinequeryresultcachedvideo.py,sha256=7PqKWqo3GmN_8hSagjTsBXX5o61r2ExjmudC391Hgkc,6019 -telegram/_inline/inlinequeryresultcachedvoice.py,sha256=RWtttFdxUbFHvziKHTPf16D9lGpgHTQAG7_uvt3enzo,5371 -telegram/_inline/inlinequeryresultcontact.py,sha256=OJNKBKYAe4Isl5SNpwFMCZhE5KEjo49FnkgI5U5seew,5530 -telegram/_inline/inlinequeryresultdocument.py,sha256=Qxebral6pkTP508hKuR2so2UB8ZNtfiEhXO9aewOFC8,7163 -telegram/_inline/inlinequeryresultgame.py,sha256=obOjS--gze0T_UxVlce2YU66dschSwuBwscXkfftzu0,2735 -telegram/_inline/inlinequeryresultgif.py,sha256=bCceBzYJlrrRJ8jsMD_k1KU4zkFUhWXJU70L8w-YF88,7791 -telegram/_inline/inlinequeryresultlocation.py,sha256=c94IsGD6GklCPDNVWVoiuKaq4KQSRWdbNFI5LYBTOrY,9471 -telegram/_inline/inlinequeryresultmpeg4gif.py,sha256=kGHjqUCPHp8wqrqqtEfVnrso5X9N7i04sifp-Sq6MjU,7895 -telegram/_inline/inlinequeryresultphoto.py,sha256=Fq80du55njrI5tSZ77z7NaE-P4gtBA2vKGCZJ-yAMUY,7105 -telegram/_inline/inlinequeryresultsbutton.py,sha256=alOoGLFU94lgJQnl7fS8JwJ3cqxqtS3f8xEVand9VHk,5384 -telegram/_inline/inlinequeryresultvenue.py,sha256=vcJ545pGSTW0nelFWnSm4hzSsjhdVcqtqIflzq8xA08,7172 -telegram/_inline/inlinequeryresultvideo.py,sha256=A7J7MzdtLtkrc3nt04rJ_QVnHfjsjxhKaIqKRSDZHRg,8122 -telegram/_inline/inlinequeryresultvoice.py,sha256=3jW1oVmh2fqF8-mU9-VEeeq40gYuq_XqQkIIOCN-QEA,5607 -telegram/_inline/inputcontactmessagecontent.py,sha256=g5TUu4JZR1x0EfYnAqCIJA0cdHwLHtmsNXwdQnONFP0,2746 -telegram/_inline/inputinvoicemessagecontent.py,sha256=HVyNKFYwenQjpEhqXrPJSrBVy-YdS46Ehf5zTk6AryQ,14101 -telegram/_inline/inputlocationmessagecontent.py,sha256=KFCQsbsZklJOQttvqtKBUnxPsiGesxIy8KnxIDjbJc4,6729 -telegram/_inline/inputmessagecontent.py,sha256=lv845QzFPrFah-tufYetrN2zJR-onneLbquc7cPE4c8,1567 -telegram/_inline/inputtextmessagecontent.py,sha256=mS6YE4voMcZTY8txCTrHvc08rjPZnuydPU-OAZbbpuI,4822 -telegram/_inline/inputvenuemessagecontent.py,sha256=4AyUBDxpBqc2Ph_YNOQMdkegeOeaFg2fYmOQaIOpn8Q,4561 -telegram/_inline/preparedinlinemessage.py,sha256=5L1bgI2XFtrFyve87Crm1wPAEEPZphuEC41gxt5fbws,3028 -telegram/_keyboardbutton.py,sha256=PnZaKIigqpIDK7aJFDVJxHqIGiOC_jb239FJW9mpZ7A,9282 -telegram/_keyboardbuttonpolltype.py,sha256=3Lm4yBtTiCZQ9vse5q4dWpWsWDlyQxAkLaK1VlNMQpI,2547 -telegram/_keyboardbuttonrequest.py,sha256=UlWdA34C5XaBOLqswMWs0npzOv-Q_zCb6mmw-YfWOaI,12800 -telegram/_linkpreviewoptions.py,sha256=hdtRJw7WAlA7jfIhZXbXi2nwRd39tZF3kpiAEHAGvPY,4498 -telegram/_loginurl.py,sha256=8Ipi_5Yu-OZVTQt2vIGRkCYccjToo7IRUG7IzJBsSjo,5134 -telegram/_menubutton.py,sha256=mZ2rVKaPjuZOeQLnZ586pnJgnOU2bkiqaqS5xwI8J_M,7561 -telegram/_message.py,sha256=5cN3rft17lmlOmlnRSKpKPWXx5vn1WZjUVbRzPX9sJw,218720 -telegram/_messageautodeletetimerchanged.py,sha256=bv2EONmzMKm1EUv007AlSBRhp9ZVeliCg0m7hQda69E,2015 -telegram/_messageentity.py,sha256=7skOKFz6LGdrKVONwNEPDi56dEga10vRRWIKi0i5YzA,18831 -telegram/_messageid.py,sha256=9eUX0R4zSjPK6KQcf86xXGgkEK2ZJ_jBjrPIBS8l-qA,2318 -telegram/_messageorigin.py,sha256=AdFm-nbffMo2w56cwsdLC823m55UqdCjkeU5hWByjQE,10093 -telegram/_messagereactionupdated.py,sha256=AV43GIwGw_PgKn3xdy5Yvyf07PzHw8zQBVezxPS7vDY,8035 -telegram/_paidmedia.py,sha256=pAItRnGzte3eCyHZeeXZ7vbi9PWLTFSc7B6KSx8rnwY,11168 -telegram/_passport/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -telegram/_passport/__pycache__/__init__.cpython-311.pyc,, -telegram/_passport/__pycache__/credentials.cpython-311.pyc,, -telegram/_passport/__pycache__/data.cpython-311.pyc,, -telegram/_passport/__pycache__/encryptedpassportelement.cpython-311.pyc,, -telegram/_passport/__pycache__/passportdata.cpython-311.pyc,, -telegram/_passport/__pycache__/passportelementerrors.cpython-311.pyc,, -telegram/_passport/__pycache__/passportfile.cpython-311.pyc,, -telegram/_passport/credentials.py,sha256=WAcaLDa6-XXv2lW_b1H16AZXYhc-e7gy2HX_QQIe9Ds,22928 -telegram/_passport/data.py,sha256=zZlaWmLPWJ5UOJTnONn6fgjLr6H5_5vj7-EmvejabFY,6373 -telegram/_passport/encryptedpassportelement.py,sha256=nbQwxyr_g87EY--dihn6C6t-r0CdRDVKdvl-QkKYwvY,13250 -telegram/_passport/passportdata.py,sha256=NYHn4XqvEXkhFRXL1B3Mw4eQKWHWOjN8GirmydXC6WM,5222 -telegram/_passport/passportelementerrors.py,sha256=nBhOuomKDWSjMLVfE4tHWn8O9q6MaxI2vmE3PqAHc9Q,18891 -telegram/_passport/passportfile.py,sha256=QXT5o0LIX7elT1fT-wvqYC644U83-YZ3_ujetD7SGlE,7953 -telegram/_payment/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -telegram/_payment/__pycache__/__init__.cpython-311.pyc,, -telegram/_payment/__pycache__/invoice.cpython-311.pyc,, -telegram/_payment/__pycache__/labeledprice.cpython-311.pyc,, -telegram/_payment/__pycache__/orderinfo.cpython-311.pyc,, -telegram/_payment/__pycache__/precheckoutquery.cpython-311.pyc,, -telegram/_payment/__pycache__/refundedpayment.cpython-311.pyc,, -telegram/_payment/__pycache__/shippingaddress.cpython-311.pyc,, -telegram/_payment/__pycache__/shippingoption.cpython-311.pyc,, -telegram/_payment/__pycache__/shippingquery.cpython-311.pyc,, -telegram/_payment/__pycache__/successfulpayment.cpython-311.pyc,, -telegram/_payment/invoice.py,sha256=Y559SezAzCBTsGnwGTog23rylH9epAv_l93TpARZCJ4,5130 -telegram/_payment/labeledprice.py,sha256=1pux8UP9SupwF4imslvHcESmuHVok-ovE-HIiwgXinU,2719 -telegram/_payment/orderinfo.py,sha256=avrF-2_u6kYvDZwUDf4FWZcfLzAsCeXRZ0uyEhsI09g,3149 -telegram/_payment/precheckoutquery.py,sha256=TVWfp0EhO6szoFVvi0CWnSPIPzOEOilcpvNhiXC-cUk,6053 -telegram/_payment/refundedpayment.py,sha256=TnRGpmD7IfjKVmC4JEneGc1I71nCfIHtPrnOOzWnKQQ,4110 -telegram/_payment/shippingaddress.py,sha256=fTP6D-WffrE5NcV2OBTqG-6RFFTXBwCwQ3PQ7q8Ukb0,2977 -telegram/_payment/shippingoption.py,sha256=v7L4WsvIK0o2oihmIZ0-MINW27BLS0dYrCRpvH4962A,2522 -telegram/_payment/shippingquery.py,sha256=P8NdjXpYleuTaa80V5-VivS8bzLlaczV-voy8PXV6Y8,4533 -telegram/_payment/stars/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -telegram/_payment/stars/__pycache__/__init__.cpython-311.pyc,, -telegram/_payment/stars/__pycache__/affiliateinfo.cpython-311.pyc,, -telegram/_payment/stars/__pycache__/revenuewithdrawalstate.cpython-311.pyc,, -telegram/_payment/stars/__pycache__/startransactions.cpython-311.pyc,, -telegram/_payment/stars/__pycache__/transactionpartner.cpython-311.pyc,, -telegram/_payment/stars/affiliateinfo.py,sha256=6z45dQs2qqTCA8DfJ8zRdtQz29V93wCDm7sd4H3dPdY,5256 -telegram/_payment/stars/revenuewithdrawalstate.py,sha256=QPxbEUA4zgKvCC0t1i3ed9wDJQMWH58DxJOxLvIFHUI,6619 -telegram/_payment/stars/startransactions.py,sha256=JnZFM5wSAriuvjYQz5E3aNYRt8rbt4kYy37WLONWduM,7138 -telegram/_payment/stars/transactionpartner.py,sha256=br18pHFGP24sPsWWkIY0MDusT5Df0dtvcQE6ZTw_5iY,15103 -telegram/_payment/successfulpayment.py,sha256=-i5Xvm-SPa-uMHecSZZpRPGbTYEPhDW2q7HCsAwXeCQ,6898 -telegram/_poll.py,sha256=5KGhst2q_JFeHRlcFkMZ9naeHpAk7xG9hEEgzg2fuWc,26951 -telegram/_proximityalerttriggered.py,sha256=LJpIQmqXHCoEleGez70Fr5HfxQyWg2KUVPdzz803IT0,2895 -telegram/_reaction.py,sha256=pl7McGt_d3mVWvdavhVhhPYjb1TCMAvdissW-C5JTf0,7495 -telegram/_reply.py,sha256=gH-ky1cbVJT-j9vSyiHyAnGzvGq1Ob_XX355_zdkPWI,21972 -telegram/_replykeyboardmarkup.py,sha256=4naW1i1EG0gbHDqjwCUHK1ve3-BS3qHvbOu6iNJS2hE,16575 -telegram/_replykeyboardremove.py,sha256=AyNg3twg4srikwnAaHquswJXCDsNRVk1Q5LetsWwwoc,3345 -telegram/_sentwebappmessage.py,sha256=E0uBOAHLRWOJrH0lLWjZHvVKC_yE2KKntkvk_5-sfV4,2199 -telegram/_shared.py,sha256=L2SA_xafA3UiP_oeiRwEYFqvSzPmWeDmyymd01iX8qY,10697 -telegram/_story.py,sha256=AY0Yk1idUSiW1dd1ETpLmOt2RWQ2xcX1ug9DDKcck1E,2568 -telegram/_switchinlinequerychosenchat.py,sha256=OmI92dsm6mgZYltDtXZe2SroSY-sM3hB8tBQ37Ff2Oc,4136 -telegram/_telegramobject.py,sha256=mrgUqyIobC_U3NpmBNZJLQg2LMyIhP9oSYwNK9YkOdk,28300 -telegram/_update.py,sha256=OzbJ1UgWNtVEwdFoEpBSjSfJQH7LTmMWsyKrv2mCsJM,35698 -telegram/_user.py,sha256=ACtl7Z9ZqL7XefeXnmJaXLMWeLeEXLu1fubCCwQHEAw,90245 -telegram/_userprofilephotos.py,sha256=IJpVSZPcK_VA2vaCojzfHkQH0YrGALhrKnn1xYk6p9U,2958 -telegram/_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -telegram/_utils/__pycache__/__init__.cpython-311.pyc,, -telegram/_utils/__pycache__/argumentparsing.cpython-311.pyc,, -telegram/_utils/__pycache__/datetime.cpython-311.pyc,, -telegram/_utils/__pycache__/defaultvalue.cpython-311.pyc,, -telegram/_utils/__pycache__/entities.cpython-311.pyc,, -telegram/_utils/__pycache__/enum.cpython-311.pyc,, -telegram/_utils/__pycache__/files.cpython-311.pyc,, -telegram/_utils/__pycache__/logging.cpython-311.pyc,, -telegram/_utils/__pycache__/markup.cpython-311.pyc,, -telegram/_utils/__pycache__/repr.cpython-311.pyc,, -telegram/_utils/__pycache__/strings.cpython-311.pyc,, -telegram/_utils/__pycache__/types.cpython-311.pyc,, -telegram/_utils/__pycache__/warnings.cpython-311.pyc,, -telegram/_utils/__pycache__/warnings_transition.cpython-311.pyc,, -telegram/_utils/argumentparsing.py,sha256=XyzIiRYadFgv92LqbyIek9lGMVVCF-dZZKrDB3b04yw,2330 -telegram/_utils/datetime.py,sha256=O-BwOPi1edW8UE11882-h-HuQRaKriMg3YsfrA_aJhU,9540 -telegram/_utils/defaultvalue.py,sha256=8FCBZz-zl_-L4s3Tqdw904QojAOID2mzTJGbMBXc6fw,4305 -telegram/_utils/entities.py,sha256=H7mp3dJqQ2StSXxZyUX90XzffRoQs-J0EIjQsLFcdWI,3043 -telegram/_utils/enum.py,sha256=qzV6F0fGYBBzT7w80QIDCoSIDZnizmBnxKf8ZnjX4Kc,3019 -telegram/_utils/files.py,sha256=2uoD5_6fApRyyTNbrQFUgLno7_umUz0OLY2GZYfCh5k,5951 -telegram/_utils/logging.py,sha256=NuLXdUpOxZJvCpbsZbyHz9ruq93WbL8RKx2OCQfPHZI,1970 -telegram/_utils/markup.py,sha256=LgJWs6yapn_edgIOjHYbOhCaw_z3uJ5RRnLfQB3s9mk,2100 -telegram/_utils/repr.py,sha256=NSDMURowcODe8PrBaaoPbMWXCKlkMhXg64eTYvx0UBw,1833 -telegram/_utils/strings.py,sha256=4fx4AIQWmCMufpj-pxq8FvRD6XY1bULLERzQ8QLY6as,1802 -telegram/_utils/types.py,sha256=NMqZ_q38RdRm2w5G95m6FiDN4rVeBWFkx9PN4r4UV8E,3628 -telegram/_utils/warnings.py,sha256=zLtK14_YzhH2JdBsgtdM0n0GxWMoADdV4t3T0Lc3NGw,2170 -telegram/_utils/warnings_transition.py,sha256=spvwFfy7OfNrFxRDblNVzcw8dhdO0SYayCntQCZ7-Vg,4080 -telegram/_version.py,sha256=NDE7hxQTAUCF47dAsWd7ImdYPgigYdAQx4ixlyiTPw8,1813 -telegram/_videochat.py,sha256=skp9tPaZjVLHG2OzDN8Id2S7h2SP2UHnSitijauhNUs,6090 -telegram/_webappdata.py,sha256=V3kg4rbzbsc0rDW1P7XIJZeyNb1SA3tSbamz-D_z-kw,2444 -telegram/_webappinfo.py,sha256=TjOOZanSHb4jmziJOVBia4W-IQ-G1rrkcHkc6veVGCo,2124 -telegram/_webhookinfo.py,sha256=uRcNPWyFGV-VJQBgs89S5pNxvz9WRLO_Bd1BohXkxQE,7810 -telegram/_writeaccessallowed.py,sha256=u6M26BiVDZWa-nfDeTIpMLmAAV0T95UTypMOZ3QN6J0,3585 -telegram/constants.py,sha256=O2OGGxFoSeoDgITELrWBrfzM3GwL7MowU9Mc98HzLDQ,119310 -telegram/error.py,sha256=u3ab2f0UczatJTl4HUVkpmhDqViQ4fC1RUoiNXiNXzc,7278 -telegram/ext/__init__.py,sha256=GlSkUC2FAD0kxdtjuB8ncp-vSbRkLiRE6GUpcFS9iJI,4052 -telegram/ext/__pycache__/__init__.cpython-311.pyc,, -telegram/ext/__pycache__/_aioratelimiter.cpython-311.pyc,, -telegram/ext/__pycache__/_application.cpython-311.pyc,, -telegram/ext/__pycache__/_applicationbuilder.cpython-311.pyc,, -telegram/ext/__pycache__/_basepersistence.cpython-311.pyc,, -telegram/ext/__pycache__/_baseratelimiter.cpython-311.pyc,, -telegram/ext/__pycache__/_baseupdateprocessor.cpython-311.pyc,, -telegram/ext/__pycache__/_callbackcontext.cpython-311.pyc,, -telegram/ext/__pycache__/_callbackdatacache.cpython-311.pyc,, -telegram/ext/__pycache__/_contexttypes.cpython-311.pyc,, -telegram/ext/__pycache__/_defaults.cpython-311.pyc,, -telegram/ext/__pycache__/_dictpersistence.cpython-311.pyc,, -telegram/ext/__pycache__/_extbot.cpython-311.pyc,, -telegram/ext/__pycache__/_jobqueue.cpython-311.pyc,, -telegram/ext/__pycache__/_picklepersistence.cpython-311.pyc,, -telegram/ext/__pycache__/_updater.cpython-311.pyc,, -telegram/ext/__pycache__/filters.cpython-311.pyc,, -telegram/ext/_aioratelimiter.py,sha256=NSrvrNRCfDmA4F7m99WgC-rDLMsAGcE8W7w-HxshHIM,11726 -telegram/ext/_application.py,sha256=Jsx5bf02ExD-G8Pxx5oL-hmxPxKCYHy7JmjPUb5QyaU,84185 -telegram/ext/_applicationbuilder.py,sha256=o5hIkAxr-Dp0JXoA7tUGKixNmWbZtdJlY07kgNNmpt0,58317 -telegram/ext/_basepersistence.py,sha256=CPBJHYR_b7vh_BIMLPqBKMc3jnr4OujJpoBQZt2qLmk,18349 -telegram/ext/_baseratelimiter.py,sha256=x6wWSkWnlQY02qQlm91wRgq-bTh7X2a63H9zXHU9_Z8,6496 -telegram/ext/_baseupdateprocessor.py,sha256=D1_AJS1W3ZOtD7dy255lZZt69mC7XdoRS_NQT1gl8ow,6173 -telegram/ext/_callbackcontext.py,sha256=-UjP7uMnWByhMomg6LTXF5fUYabZDq0SX-cv2i6wss4,17852 -telegram/ext/_callbackdatacache.py,sha256=EMjoAxWckMBCEDNDX7gITKMQCkPrNJdVKOfs4WzalcU,18299 -telegram/ext/_contexttypes.py,sha256=sJpbziSN-kONCb-o2YB17Gkj2vTyNAA1crUBDkIyXZ8,7749 -telegram/ext/_defaults.py,sha256=9ztcmIS3olpoup41Iv8hyIHxsuiUzQSMKTLosWGVJQ8,16730 -telegram/ext/_dictpersistence.py,sha256=DkqAtij2iw2FVsbgw6dFZyFlPm2pRsq5fIbTvcAaqXM,19069 -telegram/ext/_extbot.py,sha256=iP4LAwCGWDvRIi2nIVm5fS6qcBi1nL5ygqx_glJqhKw,191465 -telegram/ext/_handlers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -telegram/ext/_handlers/__pycache__/__init__.cpython-311.pyc,, -telegram/ext/_handlers/__pycache__/basehandler.cpython-311.pyc,, -telegram/ext/_handlers/__pycache__/businessconnectionhandler.cpython-311.pyc,, -telegram/ext/_handlers/__pycache__/businessmessagesdeletedhandler.cpython-311.pyc,, -telegram/ext/_handlers/__pycache__/callbackqueryhandler.cpython-311.pyc,, -telegram/ext/_handlers/__pycache__/chatboosthandler.cpython-311.pyc,, -telegram/ext/_handlers/__pycache__/chatjoinrequesthandler.cpython-311.pyc,, -telegram/ext/_handlers/__pycache__/chatmemberhandler.cpython-311.pyc,, -telegram/ext/_handlers/__pycache__/choseninlineresulthandler.cpython-311.pyc,, -telegram/ext/_handlers/__pycache__/commandhandler.cpython-311.pyc,, -telegram/ext/_handlers/__pycache__/conversationhandler.cpython-311.pyc,, -telegram/ext/_handlers/__pycache__/inlinequeryhandler.cpython-311.pyc,, -telegram/ext/_handlers/__pycache__/messagehandler.cpython-311.pyc,, -telegram/ext/_handlers/__pycache__/messagereactionhandler.cpython-311.pyc,, -telegram/ext/_handlers/__pycache__/paidmediapurchasedhandler.cpython-311.pyc,, -telegram/ext/_handlers/__pycache__/pollanswerhandler.cpython-311.pyc,, -telegram/ext/_handlers/__pycache__/pollhandler.cpython-311.pyc,, -telegram/ext/_handlers/__pycache__/precheckoutqueryhandler.cpython-311.pyc,, -telegram/ext/_handlers/__pycache__/prefixhandler.cpython-311.pyc,, -telegram/ext/_handlers/__pycache__/shippingqueryhandler.cpython-311.pyc,, -telegram/ext/_handlers/__pycache__/stringcommandhandler.cpython-311.pyc,, -telegram/ext/_handlers/__pycache__/stringregexhandler.cpython-311.pyc,, -telegram/ext/_handlers/__pycache__/typehandler.cpython-311.pyc,, -telegram/ext/_handlers/basehandler.py,sha256=RiKGlMA0n1yjoXJaGMLxZZvVnjDaaA7nHo_e7Agzn4U,7353 -telegram/ext/_handlers/businessconnectionhandler.py,sha256=lUbF3D1dIrq3GNRYq_IhRTNFV_cnNKgXDyBkrgXCGYY,3844 -telegram/ext/_handlers/businessmessagesdeletedhandler.py,sha256=YATmTqVMfyTg6a0ztPXcCKzkY1dIfvkL0RtXkPe32nw,3888 -telegram/ext/_handlers/callbackqueryhandler.py,sha256=TRqLhBXId6ZOV-1zKyo2WAFbWRfASeSi31pq4Z0FgV4,9307 -telegram/ext/_handlers/chatboosthandler.py,sha256=Pf9GKw8tX5cYl4fOMD7fomD7LRMmzYOvUUuU0ZdWFRM,5542 -telegram/ext/_handlers/chatjoinrequesthandler.py,sha256=M0E0-qEbb6xIKbR2M8teqBMwnMGkvvEC88ht1m17MU4,4486 -telegram/ext/_handlers/chatmemberhandler.py,sha256=C6g2F-lxmVlFL_BSGBkfF6z70azsE7znKXYk2X-VVQw,5284 -telegram/ext/_handlers/choseninlineresulthandler.py,sha256=t-4mP0VSXu0rEaVa2q9ePEvxtRnZT8Ig4GsQ8bybMAs,4943 -telegram/ext/_handlers/commandhandler.py,sha256=bppOmocy-hmaZSqMoGWrsmBmn8D4urL8C5hBCMPwqjY,10071 -telegram/ext/_handlers/conversationhandler.py,sha256=0-FqLSYPn-uVG1e7I-3gHiKfgJZJTAas21X5wQCzaGY,42540 -telegram/ext/_handlers/inlinequeryhandler.py,sha256=ykHB3XpVelIodWsBSOsLjtKt12bBCdAsfmQKYb7XI4k,5935 -telegram/ext/_handlers/messagehandler.py,sha256=u28bnTm_jcIrVMIf96Gt1FKxN9vLJXkQinC0CNxV_xE,4732 -telegram/ext/_handlers/messagereactionhandler.py,sha256=gD_nTG7q3p9g1YlsxHgZGN4F_5fuohXkebQeRHWYIq8,8175 -telegram/ext/_handlers/paidmediapurchasedhandler.py,sha256=xZJ8gK2epxXJcff14gM2ZE1yZLpugE5WqaWeHBQ6Hgs,3818 -telegram/ext/_handlers/pollanswerhandler.py,sha256=F5Za_Fdbmt6HKDyZdsWLj0PREWK__NqNYAK4lfVlblo,2788 -telegram/ext/_handlers/pollhandler.py,sha256=UV4TdWU7PH6iDLH06gvpFyXwddEsGoiLMyJjy86DP4s,2753 -telegram/ext/_handlers/precheckoutqueryhandler.py,sha256=dAV6D6MlPWBe5l0wsDRQbBVvzJSQcXvUMwwxffj7OK8,4047 -telegram/ext/_handlers/prefixhandler.py,sha256=z_SqTNW1RZ0RGqo9T4r9YRq09hdPvEL-6ngdIG8c7Us,7926 -telegram/ext/_handlers/shippingqueryhandler.py,sha256=-iaC3P5J3fazs2U71_qc9LGZbH2pd3Iaykld9Zp7BiU,2763 -telegram/ext/_handlers/stringcommandhandler.py,sha256=8xOmPDJEuVzh8roB3625n8VGfL-ygupNwwonsDBmMEo,4476 -telegram/ext/_handlers/stringregexhandler.py,sha256=5SLRN7ogydttltbdYJ6K_3GRPzuD7O3SKu4l7O1C3uU,4582 -telegram/ext/_handlers/typehandler.py,sha256=neFHvNHAKphpAG4WzobZeNHkdKUNCxmg9rnAq6d1_6w,4124 -telegram/ext/_jobqueue.py,sha256=OcMFJf1B2y-WWyQRgEgxR_bH0ZK7FVP0HapvDR7OxOs,41541 -telegram/ext/_picklepersistence.py,sha256=pXa-tEu0qrWSwYKHGj5clLpy7QN6enVIt1uVC7A5FP4,22918 -telegram/ext/_updater.py,sha256=scHG-4Tb69ZXy2z0-OaZpruL4-N1Xw56o9PV3fZjfAU,37986 -telegram/ext/_utils/__init__.py,sha256=98SxNI18NCwxl9r23FYrCkb83A-POKPo-ksskcZhL5k,800 -telegram/ext/_utils/__pycache__/__init__.cpython-311.pyc,, -telegram/ext/_utils/__pycache__/_update_parsing.cpython-311.pyc,, -telegram/ext/_utils/__pycache__/stack.cpython-311.pyc,, -telegram/ext/_utils/__pycache__/trackingdict.cpython-311.pyc,, -telegram/ext/_utils/__pycache__/types.cpython-311.pyc,, -telegram/ext/_utils/__pycache__/webhookhandler.cpython-311.pyc,, -telegram/ext/_utils/_update_parsing.py,sha256=KpQOeDCKjobVamYL_MkcgN3B9dgSqJziu8oxGuC0mlY,1938 -telegram/ext/_utils/stack.py,sha256=mu95lYJ7HW4OEL49-wcNCViAkGJyIuuAMqBd7oFnchY,2586 -telegram/ext/_utils/trackingdict.py,sha256=owPj4tosQKK2_pqQtzU3Fqrnl3fugTENLya73jClN8g,4597 -telegram/ext/_utils/types.py,sha256=lN_QFfGECJJWh2vKIb1wBXB0UV0XTCA5BNPZ3AE4o0M,3096 -telegram/ext/_utils/webhookhandler.py,sha256=sywQieWYqScTsnqanjVIhX4yuyiAu2b_l_ihmZkX_Gc,8029 -telegram/ext/filters.py,sha256=MeLamuSajcHlOHcBWqI0_qi-ffSgdciTLNAEfeDmXH8,99197 -telegram/helpers.py,sha256=HDOoAwWWszF2EZ-O282aHx42uZyM4bNobwMOfjkQo3c,7413 -telegram/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -telegram/request/__init__.py,sha256=raFq4yfvwbI55hGJkHhGEqpyGgitkLQlwfAdl4wkVVk,1081 -telegram/request/__pycache__/__init__.cpython-311.pyc,, -telegram/request/__pycache__/_baserequest.cpython-311.pyc,, -telegram/request/__pycache__/_httpxrequest.cpython-311.pyc,, -telegram/request/__pycache__/_requestdata.cpython-311.pyc,, -telegram/request/__pycache__/_requestparameter.cpython-311.pyc,, -telegram/request/_baserequest.py,sha256=YYRxzQJATmhqjzMF05rUuo29NyOv7W9MB0ECsgM0r1Y,20594 -telegram/request/_httpxrequest.py,sha256=sh3hcZhoLWNwAy3NvblDvuct4da2wJchpNGUc258iyA,13889 -telegram/request/_requestdata.py,sha256=THgNSR5HgOuTWEQ_vrXmnOEg_X0APnHguME0MII9y3s,5630 -telegram/request/_requestparameter.py,sha256=AxebtM6Xxf6hckZ8sI_pXKn1ntHRenEiY7LdQ9f_qB8,7540 -telegram/warnings.py,sha256=hxkpKC9RKCvwDssxW0g403hG_DAXAKCvXHpX_jYgeIg,2749 diff --git a/venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/REQUESTED b/venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/REQUESTED deleted file mode 100755 index e69de29..0000000 diff --git a/venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/WHEEL b/venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/WHEEL deleted file mode 100755 index 12228d4..0000000 --- a/venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/WHEEL +++ /dev/null @@ -1,4 +0,0 @@ -Wheel-Version: 1.0 -Generator: hatchling 1.27.0 -Root-Is-Purelib: true -Tag: py3-none-any diff --git a/venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/licenses/LICENSE b/venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/licenses/LICENSE deleted file mode 100755 index ae6b8d0..0000000 --- a/venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/licenses/LICENSE +++ /dev/null @@ -1,619 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. [http://fsf.org/] - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. diff --git a/venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/licenses/LICENSE.dual b/venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/licenses/LICENSE.dual deleted file mode 100755 index c2730fd..0000000 --- a/venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/licenses/LICENSE.dual +++ /dev/null @@ -1,792 +0,0 @@ - NOTICE: You can find here the GPLv3 license and after the Lesser GPLv3 license. -You may choose either license. - - - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. [http://fsf.org/] - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. - - - - - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. [http://fsf.org/] - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. diff --git a/venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/licenses/LICENSE.lesser b/venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/licenses/LICENSE.lesser deleted file mode 100755 index 5cc63c2..0000000 --- a/venv/lib/python3.11/site-packages/python_telegram_bot-21.10.dist-info/licenses/LICENSE.lesser +++ /dev/null @@ -1,165 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. [http://fsf.org/] - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. diff --git a/venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/INSTALLER b/venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/INSTALLER deleted file mode 100755 index a1b589e..0000000 --- a/venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/LICENSE b/venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/LICENSE deleted file mode 100755 index 353924b..0000000 --- a/venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright Jason R. Coombs - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. diff --git a/venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/METADATA b/venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/METADATA deleted file mode 100755 index f7f6278..0000000 --- a/venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/METADATA +++ /dev/null @@ -1,137 +0,0 @@ -Metadata-Version: 2.1 -Name: setuptools -Version: 66.1.1 -Summary: Easily download, build, install, upgrade, and uninstall Python packages -Home-page: https://github.com/pypa/setuptools -Author: Python Packaging Authority -Author-email: distutils-sig@python.org -Project-URL: Documentation, https://setuptools.pypa.io/ -Project-URL: Changelog, https://setuptools.pypa.io/en/stable/history.html -Keywords: CPAN PyPI distutils eggs package management -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3 :: Only -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Classifier: Topic :: System :: Archiving :: Packaging -Classifier: Topic :: System :: Systems Administration -Classifier: Topic :: Utilities -Requires-Python: >=3.7 -License-File: LICENSE -Provides-Extra: certs -Provides-Extra: docs -Requires-Dist: furo ; extra == 'docs' -Requires-Dist: jaraco.packaging (>=9) ; extra == 'docs' -Requires-Dist: jaraco.tidelift (>=1.4) ; extra == 'docs' -Requires-Dist: pygments-github-lexers (==0.0.5) ; extra == 'docs' -Requires-Dist: rst.linker (>=1.9) ; extra == 'docs' -Requires-Dist: sphinx-favicon ; extra == 'docs' -Requires-Dist: sphinx-hoverxref (<2) ; extra == 'docs' -Requires-Dist: sphinx-inline-tabs ; extra == 'docs' -Requires-Dist: sphinx-lint ; extra == 'docs' -Requires-Dist: sphinx-notfound-page (==0.8.3) ; extra == 'docs' -Requires-Dist: sphinx-reredirects ; extra == 'docs' -Requires-Dist: sphinx (>=3.5) ; extra == 'docs' -Requires-Dist: sphinxcontrib-towncrier ; extra == 'docs' -Provides-Extra: ssl -Provides-Extra: testing -Requires-Dist: build[virtualenv] ; extra == 'testing' -Requires-Dist: filelock (>=3.4.0) ; extra == 'testing' -Requires-Dist: flake8-2020 ; extra == 'testing' -Requires-Dist: flake8 (<5) ; extra == 'testing' -Requires-Dist: ini2toml[lite] (>=0.9) ; extra == 'testing' -Requires-Dist: jaraco.envs (>=2.2) ; extra == 'testing' -Requires-Dist: jaraco.path (>=3.2.0) ; extra == 'testing' -Requires-Dist: pip (>=19.1) ; extra == 'testing' -Requires-Dist: pip-run (>=8.8) ; extra == 'testing' -Requires-Dist: pytest-checkdocs (>=2.4) ; extra == 'testing' -Requires-Dist: pytest-enabler (>=1.3) ; extra == 'testing' -Requires-Dist: pytest-perf ; extra == 'testing' -Requires-Dist: pytest-timeout ; extra == 'testing' -Requires-Dist: pytest-xdist ; extra == 'testing' -Requires-Dist: pytest (>=6) ; extra == 'testing' -Requires-Dist: tomli-w (>=1.0.0) ; extra == 'testing' -Requires-Dist: virtualenv (>=13.0.0) ; extra == 'testing' -Requires-Dist: wheel ; extra == 'testing' -Provides-Extra: testing-integration -Requires-Dist: build[virtualenv] ; extra == 'testing-integration' -Requires-Dist: filelock (>=3.4.0) ; extra == 'testing-integration' -Requires-Dist: jaraco.envs (>=2.2) ; extra == 'testing-integration' -Requires-Dist: jaraco.path (>=3.2.0) ; extra == 'testing-integration' -Requires-Dist: pytest ; extra == 'testing-integration' -Requires-Dist: pytest-enabler ; extra == 'testing-integration' -Requires-Dist: pytest-xdist ; extra == 'testing-integration' -Requires-Dist: tomli ; extra == 'testing-integration' -Requires-Dist: virtualenv (>=13.0.0) ; extra == 'testing-integration' -Requires-Dist: wheel ; extra == 'testing-integration' -Requires-Dist: pytest-black (>=0.3.7) ; (platform_python_implementation != "PyPy") and extra == 'testing' -Requires-Dist: pytest-cov ; (platform_python_implementation != "PyPy") and extra == 'testing' -Requires-Dist: pytest-mypy (>=0.9.1) ; (platform_python_implementation != "PyPy") and extra == 'testing' -Requires-Dist: pytest-flake8 ; (python_version < "3.12") and extra == 'testing' - -.. image:: https://img.shields.io/pypi/v/setuptools.svg - :target: https://pypi.org/project/setuptools - -.. image:: https://img.shields.io/pypi/pyversions/setuptools.svg - -.. image:: https://github.com/pypa/setuptools/workflows/tests/badge.svg - :target: https://github.com/pypa/setuptools/actions?query=workflow%3A%22tests%22 - :alt: tests - -.. image:: https://img.shields.io/badge/code%20style-black-000000.svg - :target: https://github.com/psf/black - :alt: Code style: Black - -.. image:: https://img.shields.io/readthedocs/setuptools/latest.svg - :target: https://setuptools.pypa.io - -.. image:: https://img.shields.io/badge/skeleton-2023-informational - :target: https://blog.jaraco.com/skeleton - -.. image:: https://img.shields.io/codecov/c/github/pypa/setuptools/master.svg?logo=codecov&logoColor=white - :target: https://codecov.io/gh/pypa/setuptools - -.. image:: https://tidelift.com/badges/github/pypa/setuptools?style=flat - :target: https://tidelift.com/subscription/pkg/pypi-setuptools?utm_source=pypi-setuptools&utm_medium=readme - -.. image:: https://img.shields.io/discord/803025117553754132 - :target: https://discord.com/channels/803025117553754132/815945031150993468 - :alt: Discord - -See the `Installation Instructions -`_ in the Python Packaging -User's Guide for instructions on installing, upgrading, and uninstalling -Setuptools. - -Questions and comments should be directed to `GitHub Discussions -`_. -Bug reports and especially tested patches may be -submitted directly to the `bug tracker -`_. - - -Code of Conduct -=============== - -Everyone interacting in the setuptools project's codebases, issue trackers, -chat rooms, and fora is expected to follow the -`PSF Code of Conduct `_. - - -For Enterprise -============== - -Available as part of the Tidelift Subscription. - -Setuptools and the maintainers of thousands of other packages are working with Tidelift to deliver one enterprise subscription that covers all of the open source you use. - -`Learn more `_. - - -Security Contact -================ - -To report a security vulnerability, please use the -`Tidelift security contact `_. -Tidelift will coordinate the fix and disclosure. diff --git a/venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/RECORD b/venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/RECORD deleted file mode 100755 index 97436db..0000000 --- a/venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/RECORD +++ /dev/null @@ -1,484 +0,0 @@ -_distutils_hack/__init__.py,sha256=TSekhUW1fdE3rjU3b88ybSBkJxCEpIeWBob4cEuU3ko,6128 -_distutils_hack/__pycache__/__init__.cpython-311.pyc,, -_distutils_hack/__pycache__/override.cpython-311.pyc,, -_distutils_hack/override.py,sha256=Eu_s-NF6VIZ4Cqd0tbbA5wtWky2IZPNd8et6GLt1mzo,44 -distutils-precedence.pth,sha256=JjjOniUA5XKl4N5_rtZmHrVp0baW_LoHsN0iPaX10iQ,151 -pkg_resources/__init__.py,sha256=ufA9MJopMbYWZuVKlWjFhGh42_00zkoUPmhIvPHu5YU,106278 -pkg_resources/__pycache__/__init__.cpython-311.pyc,, -pkg_resources/_vendor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pkg_resources/_vendor/__pycache__/__init__.cpython-311.pyc,, -pkg_resources/_vendor/__pycache__/typing_extensions.cpython-311.pyc,, -pkg_resources/_vendor/__pycache__/zipp.cpython-311.pyc,, -pkg_resources/_vendor/importlib_resources/__init__.py,sha256=evPm12kLgYqTm-pbzm60bOuumumT8IpBNWFp0uMyrzE,506 -pkg_resources/_vendor/importlib_resources/__pycache__/__init__.cpython-311.pyc,, -pkg_resources/_vendor/importlib_resources/__pycache__/_adapters.cpython-311.pyc,, -pkg_resources/_vendor/importlib_resources/__pycache__/_common.cpython-311.pyc,, -pkg_resources/_vendor/importlib_resources/__pycache__/_compat.cpython-311.pyc,, -pkg_resources/_vendor/importlib_resources/__pycache__/_itertools.cpython-311.pyc,, -pkg_resources/_vendor/importlib_resources/__pycache__/_legacy.cpython-311.pyc,, -pkg_resources/_vendor/importlib_resources/__pycache__/abc.cpython-311.pyc,, -pkg_resources/_vendor/importlib_resources/__pycache__/readers.cpython-311.pyc,, -pkg_resources/_vendor/importlib_resources/__pycache__/simple.cpython-311.pyc,, -pkg_resources/_vendor/importlib_resources/_adapters.py,sha256=o51tP2hpVtohP33gSYyAkGNpLfYDBqxxYsadyiRZi1E,4504 -pkg_resources/_vendor/importlib_resources/_common.py,sha256=iIxAaQhotSh6TLLUEfL_ynU2fzEeyHMz9JcL46mUhLg,2741 -pkg_resources/_vendor/importlib_resources/_compat.py,sha256=nFBCGMvImglrqgYkb9aPgOj68-h6xbw-ca94XOv1-zs,2706 -pkg_resources/_vendor/importlib_resources/_itertools.py,sha256=WCdJ1Gs_kNFwKENyIG7TO0Y434IWCu0zjVVSsSbZwU8,884 -pkg_resources/_vendor/importlib_resources/_legacy.py,sha256=TMLkx6aEM6U8xIREPXqGZrMbUhTiPUuPl6ESD7RdYj4,3494 -pkg_resources/_vendor/importlib_resources/abc.py,sha256=MvTJJXajbl74s36Gyeesf76egtbFnh-TMtzQMVhFWXo,3886 -pkg_resources/_vendor/importlib_resources/readers.py,sha256=_9QLGQ5AzrED3PY8S2Zf8V6yLR0-nqqYqtQmgleDJzY,3566 -pkg_resources/_vendor/importlib_resources/simple.py,sha256=xt0qhXbwt3bZ86zuaaKbTiE9A0mDbwu0saRjUq_pcY0,2836 -pkg_resources/_vendor/jaraco/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pkg_resources/_vendor/jaraco/__pycache__/__init__.cpython-311.pyc,, -pkg_resources/_vendor/jaraco/__pycache__/context.cpython-311.pyc,, -pkg_resources/_vendor/jaraco/__pycache__/functools.cpython-311.pyc,, -pkg_resources/_vendor/jaraco/context.py,sha256=NvdB7ArVCDrhtexOnOwSv4ScDuueGbf9LRiOSCqPn6Y,6488 -pkg_resources/_vendor/jaraco/functools.py,sha256=eLwPh8FWY7rQ_cj1YxCekUkibTuerwyoJ_41H7Q7oWM,13515 -pkg_resources/_vendor/jaraco/text/__init__.py,sha256=cN55bFcceW4wTHG5ruv5IuEDRarP-4hBYX8zl94_c30,15526 -pkg_resources/_vendor/jaraco/text/__pycache__/__init__.cpython-311.pyc,, -pkg_resources/_vendor/more_itertools/__init__.py,sha256=5PNQMpy400s5GB3jcWwzje0RCw8k0bvU9W_C49V0fd0,148 -pkg_resources/_vendor/more_itertools/__pycache__/__init__.cpython-311.pyc,, -pkg_resources/_vendor/more_itertools/__pycache__/more.cpython-311.pyc,, -pkg_resources/_vendor/more_itertools/__pycache__/recipes.cpython-311.pyc,, -pkg_resources/_vendor/more_itertools/more.py,sha256=NTUZ0P0n0gDy3qezmlR5xGtqA1LWMAockWvyHYLLuYQ,133344 -pkg_resources/_vendor/more_itertools/recipes.py,sha256=ZX4-2IfbZKlPIVaDITH2buX_fPuMDe1EVc6e2XSsCz8,22975 -pkg_resources/_vendor/packaging/__about__.py,sha256=ugASIO2w1oUyH8_COqQ2X_s0rDhjbhQC3yJocD03h2c,661 -pkg_resources/_vendor/packaging/__init__.py,sha256=b9Kk5MF7KxhhLgcDmiUWukN-LatWFxPdNug0joPhHSk,497 -pkg_resources/_vendor/packaging/__pycache__/__about__.cpython-311.pyc,, -pkg_resources/_vendor/packaging/__pycache__/__init__.cpython-311.pyc,, -pkg_resources/_vendor/packaging/__pycache__/_manylinux.cpython-311.pyc,, -pkg_resources/_vendor/packaging/__pycache__/_musllinux.cpython-311.pyc,, -pkg_resources/_vendor/packaging/__pycache__/_structures.cpython-311.pyc,, -pkg_resources/_vendor/packaging/__pycache__/markers.cpython-311.pyc,, -pkg_resources/_vendor/packaging/__pycache__/requirements.cpython-311.pyc,, -pkg_resources/_vendor/packaging/__pycache__/specifiers.cpython-311.pyc,, -pkg_resources/_vendor/packaging/__pycache__/tags.cpython-311.pyc,, -pkg_resources/_vendor/packaging/__pycache__/utils.cpython-311.pyc,, -pkg_resources/_vendor/packaging/__pycache__/version.cpython-311.pyc,, -pkg_resources/_vendor/packaging/_manylinux.py,sha256=XcbiXB-qcjv3bcohp6N98TMpOP4_j3m-iOA8ptK2GWY,11488 -pkg_resources/_vendor/packaging/_musllinux.py,sha256=_KGgY_qc7vhMGpoqss25n2hiLCNKRtvz9mCrS7gkqyc,4378 -pkg_resources/_vendor/packaging/_structures.py,sha256=q3eVNmbWJGG_S0Dit_S3Ao8qQqz_5PYTXFAKBZe5yr4,1431 -pkg_resources/_vendor/packaging/markers.py,sha256=gFSKoBTb0sKDw1v_apJy15lPr0v2mEvuEkfooTtcWx4,8496 -pkg_resources/_vendor/packaging/requirements.py,sha256=uJ4cjwm3_nrfHJLCcGU9mT5aw8SXfw8v1aBUD7OFuVs,4706 -pkg_resources/_vendor/packaging/specifiers.py,sha256=LRQ0kFsHrl5qfcFNEEJrIFYsnIHQUJXY9fIsakTrrqE,30110 -pkg_resources/_vendor/packaging/tags.py,sha256=lmsnGNiJ8C4D_Pf9PbM0qgbZvD9kmB9lpZBQUZa3R_Y,15699 -pkg_resources/_vendor/packaging/utils.py,sha256=dJjeat3BS-TYn1RrUFVwufUMasbtzLfYRoy_HXENeFQ,4200 -pkg_resources/_vendor/packaging/version.py,sha256=_fLRNrFrxYcHVfyo8vk9j8s6JM8N_xsSxVFr6RJyco8,14665 -pkg_resources/_vendor/platformdirs/__init__.py,sha256=edi2JSKpLCapqir0AW_CjpHtinRE3hf6aDk5-VHggLk,12806 -pkg_resources/_vendor/platformdirs/__main__.py,sha256=VsC0t5m-6f0YVr96PVks93G3EDF8MSNY4KpUMvPahDA,1164 -pkg_resources/_vendor/platformdirs/__pycache__/__init__.cpython-311.pyc,, -pkg_resources/_vendor/platformdirs/__pycache__/__main__.cpython-311.pyc,, -pkg_resources/_vendor/platformdirs/__pycache__/android.cpython-311.pyc,, -pkg_resources/_vendor/platformdirs/__pycache__/api.cpython-311.pyc,, -pkg_resources/_vendor/platformdirs/__pycache__/macos.cpython-311.pyc,, -pkg_resources/_vendor/platformdirs/__pycache__/unix.cpython-311.pyc,, -pkg_resources/_vendor/platformdirs/__pycache__/version.cpython-311.pyc,, -pkg_resources/_vendor/platformdirs/__pycache__/windows.cpython-311.pyc,, -pkg_resources/_vendor/platformdirs/android.py,sha256=GKizhyS7ESRiU67u8UnBJLm46goau9937EchXWbPBlk,4068 -pkg_resources/_vendor/platformdirs/api.py,sha256=MXKHXOL3eh_-trSok-JUTjAR_zjmmKF3rjREVABjP8s,4910 -pkg_resources/_vendor/platformdirs/macos.py,sha256=-3UXQewbT0yMhMdkzRXfXGAntmLIH7Qt4a9Hlf8I5_Y,2655 -pkg_resources/_vendor/platformdirs/unix.py,sha256=P-WQjSSieE38DXjMDa1t4XHnKJQ5idEaKT0PyXwm8KQ,6911 -pkg_resources/_vendor/platformdirs/version.py,sha256=qaN-fw_htIgKUVXoAuAEVgKxQu3tZ9qE2eiKkWIS7LA,160 -pkg_resources/_vendor/platformdirs/windows.py,sha256=LOrXLgI0CjQldDo2zhOZYGYZ6g4e_cJOCB_pF9aMRWQ,6596 -pkg_resources/_vendor/pyparsing/__init__.py,sha256=52QH3lgPbJhba0estckoGPHRH8JvQSSCGoWiEn2m0bU,9159 -pkg_resources/_vendor/pyparsing/__pycache__/__init__.cpython-311.pyc,, -pkg_resources/_vendor/pyparsing/__pycache__/actions.cpython-311.pyc,, -pkg_resources/_vendor/pyparsing/__pycache__/common.cpython-311.pyc,, -pkg_resources/_vendor/pyparsing/__pycache__/core.cpython-311.pyc,, -pkg_resources/_vendor/pyparsing/__pycache__/exceptions.cpython-311.pyc,, -pkg_resources/_vendor/pyparsing/__pycache__/helpers.cpython-311.pyc,, -pkg_resources/_vendor/pyparsing/__pycache__/results.cpython-311.pyc,, -pkg_resources/_vendor/pyparsing/__pycache__/testing.cpython-311.pyc,, -pkg_resources/_vendor/pyparsing/__pycache__/unicode.cpython-311.pyc,, -pkg_resources/_vendor/pyparsing/__pycache__/util.cpython-311.pyc,, -pkg_resources/_vendor/pyparsing/actions.py,sha256=wU9i32e0y1ymxKE3OUwSHO-SFIrt1h_wv6Ws0GQjpNU,6426 -pkg_resources/_vendor/pyparsing/common.py,sha256=lFL97ooIeR75CmW5hjURZqwDCTgruqltcTCZ-ulLO2Q,12936 -pkg_resources/_vendor/pyparsing/core.py,sha256=u8GptQE_H6wMkl8OZhxeK1aAPIDXXNgwdShORBwBVS4,213310 -pkg_resources/_vendor/pyparsing/diagram/__init__.py,sha256=f_EfxahqrdkRVahmTwLJXkZ9EEDKNd-O7lBbpJYlE1g,23668 -pkg_resources/_vendor/pyparsing/diagram/__pycache__/__init__.cpython-311.pyc,, -pkg_resources/_vendor/pyparsing/exceptions.py,sha256=3LbSafD32NYb1Tzt85GHNkhEAU1eZkTtNSk24cPMemo,9023 -pkg_resources/_vendor/pyparsing/helpers.py,sha256=QpUOjW0-psvueMwWb9bQpU2noqKCv98_wnw1VSzSdVo,39129 -pkg_resources/_vendor/pyparsing/results.py,sha256=HgNvWVXBdQP-Q6PtJfoCEeOJk2nwEvG-2KVKC5sGA30,25341 -pkg_resources/_vendor/pyparsing/testing.py,sha256=7tu4Abp4uSeJV0N_yEPRmmNUhpd18ZQP3CrX41DM814,13402 -pkg_resources/_vendor/pyparsing/unicode.py,sha256=fwuhMj30SQ165Cv7HJpu-rSxGbRm93kN9L4Ei7VGc1Y,10787 -pkg_resources/_vendor/pyparsing/util.py,sha256=kq772O5YSeXOSdP-M31EWpbH_ayj7BMHImBYo9xPD5M,6805 -pkg_resources/_vendor/typing_extensions.py,sha256=ipqWiq5AHzrwczt6c26AP05Llh6a5_GaXRpOBqbogHA,80078 -pkg_resources/_vendor/zipp.py,sha256=ajztOH-9I7KA_4wqDYygtHa6xUBVZgFpmZ8FE74HHHI,8425 -pkg_resources/extern/__init__.py,sha256=E5tEMzbV1FK5GjJmYo_sxZBvOqgFhGC6pv6-FKcgnWY,2459 -pkg_resources/extern/__pycache__/__init__.cpython-311.pyc,, -setuptools-66.1.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -setuptools-66.1.1.dist-info/LICENSE,sha256=2z8CRrH5J48VhFuZ_sR4uLUG63ZIeZNyL4xuJUKF-vg,1050 -setuptools-66.1.1.dist-info/METADATA,sha256=Ztj6hfDpBS6I2H6RTAV406EVbv0DtG4joIH-XFtL2IY,6213 -setuptools-66.1.1.dist-info/RECORD,, -setuptools-66.1.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -setuptools-66.1.1.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92 -setuptools-66.1.1.dist-info/entry_points.txt,sha256=3siAu4kYm1ybFJHJ7ooqpX5TAW70Gitp9dcdHC-7BFM,2740 -setuptools-66.1.1.dist-info/top_level.txt,sha256=1Euo4fJMWPMc6iG8BrvoHx4c65FnzA7Mv_p3en0BDds,48 -setuptools/__init__.py,sha256=V1kPVIPkfgZs86YUoUvAAQ9ZvTSr5AD1MHpn3mrV7W0,9170 -setuptools/__pycache__/__init__.cpython-311.pyc,, -setuptools/__pycache__/_deprecation_warning.cpython-311.pyc,, -setuptools/__pycache__/_entry_points.cpython-311.pyc,, -setuptools/__pycache__/_imp.cpython-311.pyc,, -setuptools/__pycache__/_importlib.cpython-311.pyc,, -setuptools/__pycache__/_itertools.cpython-311.pyc,, -setuptools/__pycache__/_path.cpython-311.pyc,, -setuptools/__pycache__/_reqs.cpython-311.pyc,, -setuptools/__pycache__/archive_util.cpython-311.pyc,, -setuptools/__pycache__/build_meta.cpython-311.pyc,, -setuptools/__pycache__/dep_util.cpython-311.pyc,, -setuptools/__pycache__/depends.cpython-311.pyc,, -setuptools/__pycache__/discovery.cpython-311.pyc,, -setuptools/__pycache__/dist.cpython-311.pyc,, -setuptools/__pycache__/errors.cpython-311.pyc,, -setuptools/__pycache__/extension.cpython-311.pyc,, -setuptools/__pycache__/glob.cpython-311.pyc,, -setuptools/__pycache__/installer.cpython-311.pyc,, -setuptools/__pycache__/launch.cpython-311.pyc,, -setuptools/__pycache__/logging.cpython-311.pyc,, -setuptools/__pycache__/monkey.cpython-311.pyc,, -setuptools/__pycache__/msvc.cpython-311.pyc,, -setuptools/__pycache__/namespaces.cpython-311.pyc,, -setuptools/__pycache__/package_index.cpython-311.pyc,, -setuptools/__pycache__/py34compat.cpython-311.pyc,, -setuptools/__pycache__/sandbox.cpython-311.pyc,, -setuptools/__pycache__/unicode_utils.cpython-311.pyc,, -setuptools/__pycache__/version.cpython-311.pyc,, -setuptools/__pycache__/wheel.cpython-311.pyc,, -setuptools/__pycache__/windows_support.cpython-311.pyc,, -setuptools/_deprecation_warning.py,sha256=jU9-dtfv6cKmtQJOXN8nP1mm7gONw5kKEtiPtbwnZyI,218 -setuptools/_distutils/__init__.py,sha256=swqU6jm29LbH4slGa3UTxYAaMUCLOzPY1qTMa4tv7PE,359 -setuptools/_distutils/__pycache__/__init__.cpython-311.pyc,, -setuptools/_distutils/__pycache__/_collections.cpython-311.pyc,, -setuptools/_distutils/__pycache__/_functools.cpython-311.pyc,, -setuptools/_distutils/__pycache__/_log.cpython-311.pyc,, -setuptools/_distutils/__pycache__/_macos_compat.cpython-311.pyc,, -setuptools/_distutils/__pycache__/_msvccompiler.cpython-311.pyc,, -setuptools/_distutils/__pycache__/archive_util.cpython-311.pyc,, -setuptools/_distutils/__pycache__/bcppcompiler.cpython-311.pyc,, -setuptools/_distutils/__pycache__/ccompiler.cpython-311.pyc,, -setuptools/_distutils/__pycache__/cmd.cpython-311.pyc,, -setuptools/_distutils/__pycache__/config.cpython-311.pyc,, -setuptools/_distutils/__pycache__/core.cpython-311.pyc,, -setuptools/_distutils/__pycache__/cygwinccompiler.cpython-311.pyc,, -setuptools/_distutils/__pycache__/debug.cpython-311.pyc,, -setuptools/_distutils/__pycache__/dep_util.cpython-311.pyc,, -setuptools/_distutils/__pycache__/dir_util.cpython-311.pyc,, -setuptools/_distutils/__pycache__/dist.cpython-311.pyc,, -setuptools/_distutils/__pycache__/errors.cpython-311.pyc,, -setuptools/_distutils/__pycache__/extension.cpython-311.pyc,, -setuptools/_distutils/__pycache__/fancy_getopt.cpython-311.pyc,, -setuptools/_distutils/__pycache__/file_util.cpython-311.pyc,, -setuptools/_distutils/__pycache__/filelist.cpython-311.pyc,, -setuptools/_distutils/__pycache__/log.cpython-311.pyc,, -setuptools/_distutils/__pycache__/msvc9compiler.cpython-311.pyc,, -setuptools/_distutils/__pycache__/msvccompiler.cpython-311.pyc,, -setuptools/_distutils/__pycache__/py38compat.cpython-311.pyc,, -setuptools/_distutils/__pycache__/py39compat.cpython-311.pyc,, -setuptools/_distutils/__pycache__/spawn.cpython-311.pyc,, -setuptools/_distutils/__pycache__/sysconfig.cpython-311.pyc,, -setuptools/_distutils/__pycache__/text_file.cpython-311.pyc,, -setuptools/_distutils/__pycache__/unixccompiler.cpython-311.pyc,, -setuptools/_distutils/__pycache__/util.cpython-311.pyc,, -setuptools/_distutils/__pycache__/version.cpython-311.pyc,, -setuptools/_distutils/__pycache__/versionpredicate.cpython-311.pyc,, -setuptools/_distutils/_collections.py,sha256=MfGW9qk6SkMwIWYqdph95fvPGdhgriVCbMTFND2jQ1g,5305 -setuptools/_distutils/_functools.py,sha256=ABZ-Lyw-igKwBFoLF3QYtFmfutwZLiAdWcpRMbcacGU,411 -setuptools/_distutils/_log.py,sha256=zwFOk2ValRHMQa_kCqDXpHnwaqqZzhxGEwuR4zV-dEs,43 -setuptools/_distutils/_macos_compat.py,sha256=-v_Z0M1LEH5k-VhSBBbuz_pDp3nSZ4rzU9E7iIskPDc,239 -setuptools/_distutils/_msvccompiler.py,sha256=2BJnJ2xQFQZyftYi_kgz6DT1nVB-RxqEgd_pUz3qYO4,19641 -setuptools/_distutils/archive_util.py,sha256=JtMIta8JuFkCXVTHvZhmneAEdIMnpsdX84nOWKF24rk,8572 -setuptools/_distutils/bcppcompiler.py,sha256=claWCdHFRSgByxTJy3LG2LdqCGmgy9gtXGlhq-SInzQ,14752 -setuptools/_distutils/ccompiler.py,sha256=ZRMg5BKwFGfMd9hoRscEm-2JkEUVYG83ssaAFa9NZfI,47311 -setuptools/_distutils/cmd.py,sha256=pbvM1mE3KRK0pwu1JlKucLmTvsDZlTMklRNHCjxCP1U,17867 -setuptools/_distutils/command/__init__.py,sha256=fVUps4DJhvShMAod0y7xl02m46bd7r31irEhNofPrrs,430 -setuptools/_distutils/command/__pycache__/__init__.cpython-311.pyc,, -setuptools/_distutils/command/__pycache__/_framework_compat.cpython-311.pyc,, -setuptools/_distutils/command/__pycache__/bdist.cpython-311.pyc,, -setuptools/_distutils/command/__pycache__/bdist_dumb.cpython-311.pyc,, -setuptools/_distutils/command/__pycache__/bdist_rpm.cpython-311.pyc,, -setuptools/_distutils/command/__pycache__/build.cpython-311.pyc,, -setuptools/_distutils/command/__pycache__/build_clib.cpython-311.pyc,, -setuptools/_distutils/command/__pycache__/build_ext.cpython-311.pyc,, -setuptools/_distutils/command/__pycache__/build_py.cpython-311.pyc,, -setuptools/_distutils/command/__pycache__/build_scripts.cpython-311.pyc,, -setuptools/_distutils/command/__pycache__/check.cpython-311.pyc,, -setuptools/_distutils/command/__pycache__/clean.cpython-311.pyc,, -setuptools/_distutils/command/__pycache__/config.cpython-311.pyc,, -setuptools/_distutils/command/__pycache__/install.cpython-311.pyc,, -setuptools/_distutils/command/__pycache__/install_data.cpython-311.pyc,, -setuptools/_distutils/command/__pycache__/install_egg_info.cpython-311.pyc,, -setuptools/_distutils/command/__pycache__/install_headers.cpython-311.pyc,, -setuptools/_distutils/command/__pycache__/install_lib.cpython-311.pyc,, -setuptools/_distutils/command/__pycache__/install_scripts.cpython-311.pyc,, -setuptools/_distutils/command/__pycache__/py37compat.cpython-311.pyc,, -setuptools/_distutils/command/__pycache__/register.cpython-311.pyc,, -setuptools/_distutils/command/__pycache__/sdist.cpython-311.pyc,, -setuptools/_distutils/command/__pycache__/upload.cpython-311.pyc,, -setuptools/_distutils/command/_framework_compat.py,sha256=HW84Z1cWmg4b6aMJvlMI9o6sGZSEH_aWMTlDKstL8lY,1614 -setuptools/_distutils/command/bdist.py,sha256=Zzg5OBMzubEd7zcvm5YrtqS3N-0pAUj9VJCCWEBFa7g,5409 -setuptools/_distutils/command/bdist_dumb.py,sha256=OldkwJUb4oNzmacrPFfYuRbXK4saYg1cVt5K8UBjn7I,4666 -setuptools/_distutils/command/bdist_rpm.py,sha256=HvYKZCogAHRtwBYVpGxtMvfw7qfFb2-4443kc0WGJ_k,22016 -setuptools/_distutils/command/build.py,sha256=u5v5dE6F44KfPTdnERYpP0XKS0sScia8WA6RicJidpA,5585 -setuptools/_distutils/command/build_clib.py,sha256=1FWSWDWik2R-Dswms5S2fGt0ApahAfHzcRpSG4QKNUA,7693 -setuptools/_distutils/command/build_ext.py,sha256=fQfpwzP77lEtfQ7aZzAZ8sGTgXxocl2LgaZmk8Vfmj4,31514 -setuptools/_distutils/command/build_py.py,sha256=j9VIdUua3_ZSLEW6BWuWNxUIHWmV7brZDTZDtIzn5D4,16544 -setuptools/_distutils/command/build_scripts.py,sha256=6YpD8tuybY2p9msIXc0zG5CCJUX4J1WsFEuodhdmWtw,5605 -setuptools/_distutils/command/check.py,sha256=f7QOy4LkKUXiRyyti4orzCJX9Z8sY_uOyMYUADADG6g,4872 -setuptools/_distutils/command/clean.py,sha256=UvsVh_xrDx48CZC9ZM2gk8l_-FP65soHLsrh5nfENy0,2595 -setuptools/_distutils/command/config.py,sha256=0bV9VhyxrLs5f4gdXAA8Ulq8_X1hTffaIXqgobdeFu0,13078 -setuptools/_distutils/command/install.py,sha256=kbXnkHk7rv1xvHEN7b285ouKVsoYi3cNa2RsT1fkVoM,30165 -setuptools/_distutils/command/install_data.py,sha256=Xkyi69RZzeB0LZnA54s1lAXU_15oOlkaF9SiOhBhHlA,2763 -setuptools/_distutils/command/install_egg_info.py,sha256=Cv69kqrFORuwb1I1owe-IxyK0ZANirqGgiLyxcYSnBI,2788 -setuptools/_distutils/command/install_headers.py,sha256=H1JMCAYpuDzCUva2m1AkprHfnTiZqNSq_UHXEGaxzQo,1181 -setuptools/_distutils/command/install_lib.py,sha256=FwMicMNktfnr6kzqtD-10YbiCXng-W9DbTcyWggyD7o,8410 -setuptools/_distutils/command/install_scripts.py,sha256=c_kfAU7LKSKETupXr6kdE2K4S_pWc5jj7rqhEpO9fyY,1933 -setuptools/_distutils/command/py37compat.py,sha256=EoJC8gVYMIv2tA1NpVA2XDyCT1qGp4BEn7aX_5ve1gw,672 -setuptools/_distutils/command/register.py,sha256=1ZkaxvsQQeGy_VW42nJka0FeUMHu9pCdKfA7avspZqY,11818 -setuptools/_distutils/command/sdist.py,sha256=_1eV7GZYs2cYnDlab5OR4b3IgRs2WF9UdgMnSKoQoW8,19196 -setuptools/_distutils/command/upload.py,sha256=zn7ph7ft-L9zUw_UmNSTffBY90qRD8cFLixaDAXt_YQ,7492 -setuptools/_distutils/config.py,sha256=NrQjaUO9B88P-JtOfww3BMt9rSn1TirU4G7u0ut5FrM,4911 -setuptools/_distutils/core.py,sha256=td9vxB2oqIsyBCv-wnedZRWZrzYb3uIGilNtle2N2tg,9397 -setuptools/_distutils/cygwinccompiler.py,sha256=KGamMxV6dIb_IopimrVdN7Gqi5vCT1wrU0qgqrq6DFs,11942 -setuptools/_distutils/debug.py,sha256=N6MrTAqK6l9SVk6tWweR108PM8Ol7qNlfyV-nHcLhsY,139 -setuptools/_distutils/dep_util.py,sha256=9pqhyGw2q2HGGGXAOpbbezj024aAr_47xDfXz5Fas7U,3414 -setuptools/_distutils/dir_util.py,sha256=J4nOKIoP32yARHEYPIRxKDr5dDDDZ_9rUWwR79Fl6LI,8072 -setuptools/_distutils/dist.py,sha256=BWq3AXCfawVM6tz4rkglJIkwDSkby_Rq6NJYyWQpbiA,50190 -setuptools/_distutils/errors.py,sha256=ZtBwnhDpQA2bxIazPXNDQ25uNxM4p2omsaSRNpV3rpE,3589 -setuptools/_distutils/extension.py,sha256=F0TBNjYkMmte_Yg1bhKVHXSNWWNFEPIDUgwhuHdkox8,10270 -setuptools/_distutils/fancy_getopt.py,sha256=n4QHj6LtDTdBn4bqgZ_rqGVhtFw9tvpnI6k8HbepyiY,17901 -setuptools/_distutils/file_util.py,sha256=YCXV_p8yCNywx6wGdnfmBQx7aJPCt7vdcR6AXjL20GQ,8213 -setuptools/_distutils/filelist.py,sha256=rOKJPBvuLSjElfYuOwju95AzR3Ev5lvJoCJvI_XvZ9g,13715 -setuptools/_distutils/log.py,sha256=725W7ISJzoSYNtLnEP1FwZe_IMUn1Xq6NEYwFbXg63k,1201 -setuptools/_distutils/msvc9compiler.py,sha256=4wXPx2KlT4xcoLuM_RZ7O-LK9kwEm4OXpj72Fh6cTfQ,30204 -setuptools/_distutils/msvccompiler.py,sha256=4j7mR6JWMh9Xt9V0slOqNcu-BIbeqrd5mnxzOEYkxqM,23580 -setuptools/_distutils/py38compat.py,sha256=gZ-NQ5c6ufwVEkJ0BwkbrqG9TvWirVJIrVGqhgvaY-Q,217 -setuptools/_distutils/py39compat.py,sha256=vkxjv22H1bhToalClz3M0UUD8Xr21klbUBTQoVQxx20,639 -setuptools/_distutils/spawn.py,sha256=E6Il74CIINCRjakXUcWqSWjfC_sdp4Qtod0Bw5y_NNQ,3495 -setuptools/_distutils/sysconfig.py,sha256=i4rh3y4EyDk05eKa2wY0MmrmWZvDyz_b8Y149P4Imtg,18774 -setuptools/_distutils/text_file.py,sha256=tLjIJVBu7VMY2ZamSpQ9aBv0kbvX9_Abt26cjAAgHiQ,12096 -setuptools/_distutils/unixccompiler.py,sha256=7EpD-X7nAPYnnA8C12YdJaXezog2xtOegCjcFFMOGUc,15602 -setuptools/_distutils/util.py,sha256=Qx17Q8C68fT4FvaXeBfeY5Pzu76I6SlYneZAGCqXCtE,18097 -setuptools/_distutils/version.py,sha256=6HV4l0tHESXxMJMDwd5Fn8Y9_U8ivZIowFCNXhCSnRM,12952 -setuptools/_distutils/versionpredicate.py,sha256=mkg9LtyF3EWox-KnbBx08gKV8zu0ymIl1izIho2-f7k,5205 -setuptools/_entry_points.py,sha256=FL1tONMODSygpiA_3rN_46k-HSmKqf3LgoxJdUpvox8,2282 -setuptools/_imp.py,sha256=HmF91IbitRfsD5z-g4_wmcuH-RahyIONbPgiCOFgtzA,2392 -setuptools/_importlib.py,sha256=1RLRzpNCPKEJRbUPVIPU1-H9dzUXulyL6N_ryxnjEwc,1311 -setuptools/_itertools.py,sha256=pZAgXNz6tRPUFnHAaKJ90xAgD0gLPemcE1396Zgz73o,675 -setuptools/_path.py,sha256=9GdbEur6f_lWmokar-Y-DDyds-XmzYnXrcBy0DExwDw,749 -setuptools/_reqs.py,sha256=ApdTOmDFyK7hbHDnAH8VwhtVD5kvnOthyMNTmrUeFXs,501 -setuptools/_vendor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -setuptools/_vendor/__pycache__/__init__.cpython-311.pyc,, -setuptools/_vendor/__pycache__/ordered_set.cpython-311.pyc,, -setuptools/_vendor/__pycache__/typing_extensions.cpython-311.pyc,, -setuptools/_vendor/__pycache__/zipp.cpython-311.pyc,, -setuptools/_vendor/importlib_metadata/__init__.py,sha256=xRXwTtvg4EAYuBotYeGawbjraQD4GFIvKgMClxApCDY,30130 -setuptools/_vendor/importlib_metadata/__pycache__/__init__.cpython-311.pyc,, -setuptools/_vendor/importlib_metadata/__pycache__/_adapters.cpython-311.pyc,, -setuptools/_vendor/importlib_metadata/__pycache__/_collections.cpython-311.pyc,, -setuptools/_vendor/importlib_metadata/__pycache__/_compat.cpython-311.pyc,, -setuptools/_vendor/importlib_metadata/__pycache__/_functools.cpython-311.pyc,, -setuptools/_vendor/importlib_metadata/__pycache__/_itertools.cpython-311.pyc,, -setuptools/_vendor/importlib_metadata/__pycache__/_meta.cpython-311.pyc,, -setuptools/_vendor/importlib_metadata/__pycache__/_text.cpython-311.pyc,, -setuptools/_vendor/importlib_metadata/_adapters.py,sha256=B6fCi5-8mLVDFUZj3krI5nAo-mKp1dH_qIavyIyFrJs,1862 -setuptools/_vendor/importlib_metadata/_collections.py,sha256=CJ0OTCHIjWA0ZIVS4voORAsn2R4R2cQBEtPsZEJpASY,743 -setuptools/_vendor/importlib_metadata/_compat.py,sha256=cotBaMUB-2pIRZboQnWp9fEqm6Dwlypndn-EEn0bj5M,1828 -setuptools/_vendor/importlib_metadata/_functools.py,sha256=PsY2-4rrKX4RVeRC1oGp1lB1pmC9eKN88_f-bD9uOoA,2895 -setuptools/_vendor/importlib_metadata/_itertools.py,sha256=cvr_2v8BRbxcIl5x5ldfqdHjhI8Yi8s8yk50G_nm6jQ,2068 -setuptools/_vendor/importlib_metadata/_meta.py,sha256=_F48Hu_jFxkfKWz5wcYS8vO23qEygbVdF9r-6qh-hjE,1154 -setuptools/_vendor/importlib_metadata/_text.py,sha256=HCsFksZpJLeTP3NEk_ngrAeXVRRtTrtyh9eOABoRP4A,2166 -setuptools/_vendor/importlib_resources/__init__.py,sha256=evPm12kLgYqTm-pbzm60bOuumumT8IpBNWFp0uMyrzE,506 -setuptools/_vendor/importlib_resources/__pycache__/__init__.cpython-311.pyc,, -setuptools/_vendor/importlib_resources/__pycache__/_adapters.cpython-311.pyc,, -setuptools/_vendor/importlib_resources/__pycache__/_common.cpython-311.pyc,, -setuptools/_vendor/importlib_resources/__pycache__/_compat.cpython-311.pyc,, -setuptools/_vendor/importlib_resources/__pycache__/_itertools.cpython-311.pyc,, -setuptools/_vendor/importlib_resources/__pycache__/_legacy.cpython-311.pyc,, -setuptools/_vendor/importlib_resources/__pycache__/abc.cpython-311.pyc,, -setuptools/_vendor/importlib_resources/__pycache__/readers.cpython-311.pyc,, -setuptools/_vendor/importlib_resources/__pycache__/simple.cpython-311.pyc,, -setuptools/_vendor/importlib_resources/_adapters.py,sha256=o51tP2hpVtohP33gSYyAkGNpLfYDBqxxYsadyiRZi1E,4504 -setuptools/_vendor/importlib_resources/_common.py,sha256=iIxAaQhotSh6TLLUEfL_ynU2fzEeyHMz9JcL46mUhLg,2741 -setuptools/_vendor/importlib_resources/_compat.py,sha256=nFBCGMvImglrqgYkb9aPgOj68-h6xbw-ca94XOv1-zs,2706 -setuptools/_vendor/importlib_resources/_itertools.py,sha256=WCdJ1Gs_kNFwKENyIG7TO0Y434IWCu0zjVVSsSbZwU8,884 -setuptools/_vendor/importlib_resources/_legacy.py,sha256=TMLkx6aEM6U8xIREPXqGZrMbUhTiPUuPl6ESD7RdYj4,3494 -setuptools/_vendor/importlib_resources/abc.py,sha256=MvTJJXajbl74s36Gyeesf76egtbFnh-TMtzQMVhFWXo,3886 -setuptools/_vendor/importlib_resources/readers.py,sha256=_9QLGQ5AzrED3PY8S2Zf8V6yLR0-nqqYqtQmgleDJzY,3566 -setuptools/_vendor/importlib_resources/simple.py,sha256=xt0qhXbwt3bZ86zuaaKbTiE9A0mDbwu0saRjUq_pcY0,2836 -setuptools/_vendor/jaraco/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -setuptools/_vendor/jaraco/__pycache__/__init__.cpython-311.pyc,, -setuptools/_vendor/jaraco/__pycache__/context.cpython-311.pyc,, -setuptools/_vendor/jaraco/__pycache__/functools.cpython-311.pyc,, -setuptools/_vendor/jaraco/context.py,sha256=NvdB7ArVCDrhtexOnOwSv4ScDuueGbf9LRiOSCqPn6Y,6488 -setuptools/_vendor/jaraco/functools.py,sha256=ap1qoXaNABOx897366NTMEd2objrqAoSO1zuxZPjcmM,13512 -setuptools/_vendor/jaraco/text/__init__.py,sha256=KfFGMerrkN_0V0rgtJVx-9dHt3tW7i_uJypjwEcLtC0,15517 -setuptools/_vendor/jaraco/text/__pycache__/__init__.cpython-311.pyc,, -setuptools/_vendor/more_itertools/__init__.py,sha256=C7sXffHTXM3P-iaLPPfqfmDoxOflQMJLcM7ed9p3jak,82 -setuptools/_vendor/more_itertools/__pycache__/__init__.cpython-311.pyc,, -setuptools/_vendor/more_itertools/__pycache__/more.cpython-311.pyc,, -setuptools/_vendor/more_itertools/__pycache__/recipes.cpython-311.pyc,, -setuptools/_vendor/more_itertools/more.py,sha256=0rB_mibFR51sq33UlAI_bWfaNdsYNnJr1v6S0CaW7QA,117959 -setuptools/_vendor/more_itertools/recipes.py,sha256=UkNkrsZyqiwgLHANBTmvMhCvaNSvSNYhyOpz_Jc55DY,16256 -setuptools/_vendor/ordered_set.py,sha256=dbaCcs27dyN9gnMWGF5nA_BrVn6Q-NrjKYJpV9_fgBs,15130 -setuptools/_vendor/packaging/__about__.py,sha256=ugASIO2w1oUyH8_COqQ2X_s0rDhjbhQC3yJocD03h2c,661 -setuptools/_vendor/packaging/__init__.py,sha256=b9Kk5MF7KxhhLgcDmiUWukN-LatWFxPdNug0joPhHSk,497 -setuptools/_vendor/packaging/__pycache__/__about__.cpython-311.pyc,, -setuptools/_vendor/packaging/__pycache__/__init__.cpython-311.pyc,, -setuptools/_vendor/packaging/__pycache__/_manylinux.cpython-311.pyc,, -setuptools/_vendor/packaging/__pycache__/_musllinux.cpython-311.pyc,, -setuptools/_vendor/packaging/__pycache__/_structures.cpython-311.pyc,, -setuptools/_vendor/packaging/__pycache__/markers.cpython-311.pyc,, -setuptools/_vendor/packaging/__pycache__/requirements.cpython-311.pyc,, -setuptools/_vendor/packaging/__pycache__/specifiers.cpython-311.pyc,, -setuptools/_vendor/packaging/__pycache__/tags.cpython-311.pyc,, -setuptools/_vendor/packaging/__pycache__/utils.cpython-311.pyc,, -setuptools/_vendor/packaging/__pycache__/version.cpython-311.pyc,, -setuptools/_vendor/packaging/_manylinux.py,sha256=XcbiXB-qcjv3bcohp6N98TMpOP4_j3m-iOA8ptK2GWY,11488 -setuptools/_vendor/packaging/_musllinux.py,sha256=_KGgY_qc7vhMGpoqss25n2hiLCNKRtvz9mCrS7gkqyc,4378 -setuptools/_vendor/packaging/_structures.py,sha256=q3eVNmbWJGG_S0Dit_S3Ao8qQqz_5PYTXFAKBZe5yr4,1431 -setuptools/_vendor/packaging/markers.py,sha256=lihRgqpZjLM-JW-vxlLPqU3kmVe79g9vypy1kxmTRuQ,8493 -setuptools/_vendor/packaging/requirements.py,sha256=Opd0FjqgdEiWkzBLyo1oLU0Dj01uIFwTAnAJQrr6j2A,4700 -setuptools/_vendor/packaging/specifiers.py,sha256=LRQ0kFsHrl5qfcFNEEJrIFYsnIHQUJXY9fIsakTrrqE,30110 -setuptools/_vendor/packaging/tags.py,sha256=lmsnGNiJ8C4D_Pf9PbM0qgbZvD9kmB9lpZBQUZa3R_Y,15699 -setuptools/_vendor/packaging/utils.py,sha256=dJjeat3BS-TYn1RrUFVwufUMasbtzLfYRoy_HXENeFQ,4200 -setuptools/_vendor/packaging/version.py,sha256=_fLRNrFrxYcHVfyo8vk9j8s6JM8N_xsSxVFr6RJyco8,14665 -setuptools/_vendor/pyparsing/__init__.py,sha256=52QH3lgPbJhba0estckoGPHRH8JvQSSCGoWiEn2m0bU,9159 -setuptools/_vendor/pyparsing/__pycache__/__init__.cpython-311.pyc,, -setuptools/_vendor/pyparsing/__pycache__/actions.cpython-311.pyc,, -setuptools/_vendor/pyparsing/__pycache__/common.cpython-311.pyc,, -setuptools/_vendor/pyparsing/__pycache__/core.cpython-311.pyc,, -setuptools/_vendor/pyparsing/__pycache__/exceptions.cpython-311.pyc,, -setuptools/_vendor/pyparsing/__pycache__/helpers.cpython-311.pyc,, -setuptools/_vendor/pyparsing/__pycache__/results.cpython-311.pyc,, -setuptools/_vendor/pyparsing/__pycache__/testing.cpython-311.pyc,, -setuptools/_vendor/pyparsing/__pycache__/unicode.cpython-311.pyc,, -setuptools/_vendor/pyparsing/__pycache__/util.cpython-311.pyc,, -setuptools/_vendor/pyparsing/actions.py,sha256=wU9i32e0y1ymxKE3OUwSHO-SFIrt1h_wv6Ws0GQjpNU,6426 -setuptools/_vendor/pyparsing/common.py,sha256=lFL97ooIeR75CmW5hjURZqwDCTgruqltcTCZ-ulLO2Q,12936 -setuptools/_vendor/pyparsing/core.py,sha256=u8GptQE_H6wMkl8OZhxeK1aAPIDXXNgwdShORBwBVS4,213310 -setuptools/_vendor/pyparsing/diagram/__init__.py,sha256=f_EfxahqrdkRVahmTwLJXkZ9EEDKNd-O7lBbpJYlE1g,23668 -setuptools/_vendor/pyparsing/diagram/__pycache__/__init__.cpython-311.pyc,, -setuptools/_vendor/pyparsing/exceptions.py,sha256=3LbSafD32NYb1Tzt85GHNkhEAU1eZkTtNSk24cPMemo,9023 -setuptools/_vendor/pyparsing/helpers.py,sha256=QpUOjW0-psvueMwWb9bQpU2noqKCv98_wnw1VSzSdVo,39129 -setuptools/_vendor/pyparsing/results.py,sha256=HgNvWVXBdQP-Q6PtJfoCEeOJk2nwEvG-2KVKC5sGA30,25341 -setuptools/_vendor/pyparsing/testing.py,sha256=7tu4Abp4uSeJV0N_yEPRmmNUhpd18ZQP3CrX41DM814,13402 -setuptools/_vendor/pyparsing/unicode.py,sha256=fwuhMj30SQ165Cv7HJpu-rSxGbRm93kN9L4Ei7VGc1Y,10787 -setuptools/_vendor/pyparsing/util.py,sha256=kq772O5YSeXOSdP-M31EWpbH_ayj7BMHImBYo9xPD5M,6805 -setuptools/_vendor/tomli/__init__.py,sha256=JhUwV66DB1g4Hvt1UQCVMdfCu-IgAV8FXmvDU9onxd4,396 -setuptools/_vendor/tomli/__pycache__/__init__.cpython-311.pyc,, -setuptools/_vendor/tomli/__pycache__/_parser.cpython-311.pyc,, -setuptools/_vendor/tomli/__pycache__/_re.cpython-311.pyc,, -setuptools/_vendor/tomli/__pycache__/_types.cpython-311.pyc,, -setuptools/_vendor/tomli/_parser.py,sha256=g9-ENaALS-B8dokYpCuzUFalWlog7T-SIYMjLZSWrtM,22633 -setuptools/_vendor/tomli/_re.py,sha256=dbjg5ChZT23Ka9z9DHOXfdtSpPwUfdgMXnj8NOoly-w,2943 -setuptools/_vendor/tomli/_types.py,sha256=-GTG2VUqkpxwMqzmVO4F7ybKddIbAnuAHXfmWQcTi3Q,254 -setuptools/_vendor/typing_extensions.py,sha256=1uqi_RSlI7gos4eJB_NEV3d5wQwzTUQHd3_jrkbTo8Q,87149 -setuptools/_vendor/zipp.py,sha256=ajztOH-9I7KA_4wqDYygtHa6xUBVZgFpmZ8FE74HHHI,8425 -setuptools/archive_util.py,sha256=6WShpDR_uGZOaORRfzBmJyTYtX9xtrhmXTFPqE8kL8s,7346 -setuptools/build_meta.py,sha256=gsOBREDts9wDiGUARQUQgINXnjZVeDmS74maDIqntCg,19595 -setuptools/cli-32.exe,sha256=dfEuovMNnA2HLa3jRfMPVi5tk4R7alCbpTvuxtCyw0Y,65536 -setuptools/cli-64.exe,sha256=KLABu5pyrnokJCv6skjXZ6GsXeyYHGcqOUT3oHI3Xpo,74752 -setuptools/cli-arm64.exe,sha256=o9amxowudZ98NvNWh_a2DRY8LhoIRqTAekxABqltiMc,137216 -setuptools/cli.exe,sha256=dfEuovMNnA2HLa3jRfMPVi5tk4R7alCbpTvuxtCyw0Y,65536 -setuptools/command/__init__.py,sha256=HZlSppOB8Vro73ffvP-xrORuMrh4GnVkOqJspFRG8Pg,396 -setuptools/command/__pycache__/__init__.cpython-311.pyc,, -setuptools/command/__pycache__/alias.cpython-311.pyc,, -setuptools/command/__pycache__/bdist_egg.cpython-311.pyc,, -setuptools/command/__pycache__/bdist_rpm.cpython-311.pyc,, -setuptools/command/__pycache__/build.cpython-311.pyc,, -setuptools/command/__pycache__/build_clib.cpython-311.pyc,, -setuptools/command/__pycache__/build_ext.cpython-311.pyc,, -setuptools/command/__pycache__/build_py.cpython-311.pyc,, -setuptools/command/__pycache__/develop.cpython-311.pyc,, -setuptools/command/__pycache__/dist_info.cpython-311.pyc,, -setuptools/command/__pycache__/easy_install.cpython-311.pyc,, -setuptools/command/__pycache__/editable_wheel.cpython-311.pyc,, -setuptools/command/__pycache__/egg_info.cpython-311.pyc,, -setuptools/command/__pycache__/install.cpython-311.pyc,, -setuptools/command/__pycache__/install_egg_info.cpython-311.pyc,, -setuptools/command/__pycache__/install_lib.cpython-311.pyc,, -setuptools/command/__pycache__/install_scripts.cpython-311.pyc,, -setuptools/command/__pycache__/py36compat.cpython-311.pyc,, -setuptools/command/__pycache__/register.cpython-311.pyc,, -setuptools/command/__pycache__/rotate.cpython-311.pyc,, -setuptools/command/__pycache__/saveopts.cpython-311.pyc,, -setuptools/command/__pycache__/sdist.cpython-311.pyc,, -setuptools/command/__pycache__/setopt.cpython-311.pyc,, -setuptools/command/__pycache__/test.cpython-311.pyc,, -setuptools/command/__pycache__/upload.cpython-311.pyc,, -setuptools/command/__pycache__/upload_docs.cpython-311.pyc,, -setuptools/command/alias.py,sha256=1sLQxZcNh6dDQpDmm4G7UGGTol83nY1NTPmNBbm2siI,2381 -setuptools/command/bdist_egg.py,sha256=QEIu1AkgS02j6ejonJY7kwGp6LNxfMeYZ3sxkd55ftA,16623 -setuptools/command/bdist_rpm.py,sha256=PxrgoHPNaw2Pw2qNjjHDPC-Ay_IaDbCqP3d_5N-cj2A,1182 -setuptools/command/build.py,sha256=cgkmzJhXFXw5lHMPgohJFyEByz8L7H9JurCnk2iRnFI,6589 -setuptools/command/build_clib.py,sha256=Rq4Q5OoyF19o25XQHF1kzTO4XrA_fS1VJGO7Pw5hztk,4423 -setuptools/command/build_ext.py,sha256=cYm4OvllPf6I9YE3cWlnjPqqE546Mc7nQTpdJ-yH3jg,15821 -setuptools/command/build_py.py,sha256=CMoD9Gxd5vs8KfPVNFFD1cmJsCd3l0NJS5kdDTlx4Y4,14115 -setuptools/command/develop.py,sha256=5_Ss7ENd1_B_jVMY1tF5UV_y1Xu6jbVzAPG8oKeluGA,7012 -setuptools/command/dist_info.py,sha256=VdcNHtbPFGdPD_t20wxcROa4uALbyz1RnJMJEHQmrQU,4800 -setuptools/command/easy_install.py,sha256=WguGqmbkMaLuD5J8uMRjbywVPy0xUWCnmd1L8I_Z7Ek,87967 -setuptools/command/editable_wheel.py,sha256=yUCwBNcS75sBqcEOkW9CvRypgQ0dsMTn9646yXftAhk,31188 -setuptools/command/egg_info.py,sha256=asfMWMz-nffb4LS3VHcsLIO_UV00y5W-Cy73PJjG4v0,27419 -setuptools/command/install.py,sha256=CBdw9iITHAc0Zt1YE_8dSWY5BscuTJGrCe2jtEsnepk,5163 -setuptools/command/install_egg_info.py,sha256=T4VAV3coelU-KLcASBK-fa3-jX6keYDWzfg4UVwsLbY,3218 -setuptools/command/install_lib.py,sha256=4zK0nihAAwMYIoOS0UOBLZKSOCBbXXPKsTraO_a8qmk,5036 -setuptools/command/install_scripts.py,sha256=APFFpt_lYUEo-viMtpXr-Hkwycwq8knTxSTNUu_TwHo,2612 -setuptools/command/launcher manifest.xml,sha256=xlLbjWrB01tKC0-hlVkOKkiSPbzMml2eOPtJ_ucCnbE,628 -setuptools/command/py36compat.py,sha256=7yLWzQj179Enx3pJ8V1cDDCzeLMFMd9XJXlK-iZTq5Y,4946 -setuptools/command/register.py,sha256=kk3DxXCb5lXTvqnhfwx2g6q7iwbUmgTyXUCaBooBOUk,468 -setuptools/command/rotate.py,sha256=SvsQPasezIojPjvMnfkqzh8P0U0tCj0daczF8uc3NQM,2128 -setuptools/command/saveopts.py,sha256=za7QCBcQimKKriWcoCcbhxPjUz30gSB74zuTL47xpP4,658 -setuptools/command/sdist.py,sha256=d8Ty0eCiUKfWh4VTjqV9e8g-02Zsy8L4BcMe1OzIIn8,7071 -setuptools/command/setopt.py,sha256=okxhqD1NM1nQlbSVDCNv6P7Y7g680sc2r-tUW7wPH1Y,5086 -setuptools/command/test.py,sha256=ZWoIUdm6u2Zv-WhvSC5If1rPouxm5JmygwsajNA8WWI,8102 -setuptools/command/upload.py,sha256=XT3YFVfYPAmA5qhGg0euluU98ftxRUW-PzKcODMLxUs,462 -setuptools/command/upload_docs.py,sha256=5lQkUAbSSwDac3_qjaSIogJstQ1Aujh746ZmPQORIjo,7470 -setuptools/config/__init__.py,sha256=Jg48Ac6C8AtdjkAFhe4Kh_xwNUfK6q04CJlJ5LbVMB0,1121 -setuptools/config/__pycache__/__init__.cpython-311.pyc,, -setuptools/config/__pycache__/_apply_pyprojecttoml.cpython-311.pyc,, -setuptools/config/__pycache__/expand.cpython-311.pyc,, -setuptools/config/__pycache__/pyprojecttoml.cpython-311.pyc,, -setuptools/config/__pycache__/setupcfg.cpython-311.pyc,, -setuptools/config/_apply_pyprojecttoml.py,sha256=aCjS7MFA45ek5K1VZ-gjA3sPVSdFJ--RhykYkofNRQw,13579 -setuptools/config/_validate_pyproject/__init__.py,sha256=5YXPW1sabVn5jpZ25sUjeF6ij3_4odJiwUWi4nRD2Dc,1038 -setuptools/config/_validate_pyproject/__pycache__/__init__.cpython-311.pyc,, -setuptools/config/_validate_pyproject/__pycache__/error_reporting.cpython-311.pyc,, -setuptools/config/_validate_pyproject/__pycache__/extra_validations.cpython-311.pyc,, -setuptools/config/_validate_pyproject/__pycache__/fastjsonschema_exceptions.cpython-311.pyc,, -setuptools/config/_validate_pyproject/__pycache__/fastjsonschema_validations.cpython-311.pyc,, -setuptools/config/_validate_pyproject/__pycache__/formats.cpython-311.pyc,, -setuptools/config/_validate_pyproject/error_reporting.py,sha256=vWiDs0hjlCBjZ_g4Xszsh97lIP9M4_JaLQ6MCQ26W9U,11266 -setuptools/config/_validate_pyproject/extra_validations.py,sha256=wHzrgfdZUMRPBR1ke1lg5mhqRsBSbjEYOMsuFXQH9jY,1153 -setuptools/config/_validate_pyproject/fastjsonschema_exceptions.py,sha256=w749JgqKi8clBFcObdcbZVqsmF4oJ_QByhZ1SGbUFNw,1612 -setuptools/config/_validate_pyproject/fastjsonschema_validations.py,sha256=oqXSDfYecymwM2I40JGcTB-1P9vd7CtfSIW5kDxZQPM,269900 -setuptools/config/_validate_pyproject/formats.py,sha256=uMUnp4mLIjrQCTe6-LDjtqglmEFLfOW9E1ZZLqOzhMI,8736 -setuptools/config/expand.py,sha256=FQja-T8zG9bV_G1b7SBjWjsZNjvSbhg5vxFWhusSYoE,16319 -setuptools/config/pyprojecttoml.py,sha256=kEKCzDSQ9Pl2kAxnFNY9JgPQU5Fjp2s3grQYHou3gZ0,19598 -setuptools/config/setupcfg.py,sha256=Wonn8eLDu-28PKbND9ZdVQdxGEK9i6wgl2D_gpud0_4,25574 -setuptools/dep_util.py,sha256=BDx1BkzNQntvAB4alypHbW5UVBzjqths000PrUL4Zqc,949 -setuptools/depends.py,sha256=QYQIadr5DwLxPzkErhNt5hmRhvGhWxoXZMRXCm_jcQ0,5499 -setuptools/discovery.py,sha256=5l1rFH0XJB4zgh3hWD9O6ZRLCP9eiNumJ0LMDArPflQ,20818 -setuptools/dist.py,sha256=zo16G3VPq89bPkGr08EK8O7nzpu6kRggWL4y5TMEreQ,45530 -setuptools/errors.py,sha256=2uToNIRA7dG995pf8ox8a4r7nJtP62-hpLhzsRirnx0,2464 -setuptools/extension.py,sha256=jpsAdQvCBCkAuvmEXYI90TV4kNGO2Y13NqDr_PrvdhA,5591 -setuptools/extern/__init__.py,sha256=LYHS20uf-nl_zBPmrIzTxokYdiVMZNZBYVu6hd8c5zg,2512 -setuptools/extern/__pycache__/__init__.cpython-311.pyc,, -setuptools/glob.py,sha256=1oZjbfjAHSXbgdhSuR6YGU8jKob9L8NtEmBYqcPTLYk,4873 -setuptools/gui-32.exe,sha256=XBr0bHMA6Hpz2s9s9Bzjl-PwXfa9nH4ie0rFn4V2kWA,65536 -setuptools/gui-64.exe,sha256=aYKMhX1IJLn4ULHgWX0sE0yREUt6B3TEHf_jOw6yNyE,75264 -setuptools/gui-arm64.exe,sha256=TEFnOKDi-mq3ZszxqbCoCXTnM_lhUWjdIqBpr6fVs40,137728 -setuptools/gui.exe,sha256=XBr0bHMA6Hpz2s9s9Bzjl-PwXfa9nH4ie0rFn4V2kWA,65536 -setuptools/installer.py,sha256=s6DQfsoICBJxbUqbduhOJtl1oG0S4yegRCg3EAs0i3M,3824 -setuptools/launch.py,sha256=TyPT-Ic1T2EnYvGO26gfNRP4ysBlrhpbRjQxWsiO414,812 -setuptools/logging.py,sha256=WT1k7lH5hL-mOxsdVkrBjGV468QSpwAShlQ6pP09H6g,1232 -setuptools/monkey.py,sha256=t6To7LEhTyOWRRZLwiFv7Eeg2mjHZlVmTdHD1DC94QM,4857 -setuptools/msvc.py,sha256=x6jsjA9JdUew6VAfHapIHgEjAjy-T5dxqjPCZr0Tt04,47724 -setuptools/namespaces.py,sha256=PMqGVPXPYQgjUTvEg9bGccRAkIODrQ6NmsDg_fwErwI,3093 -setuptools/package_index.py,sha256=CKtnE5rw7NaLQHT_bY3bCm0L1uxaOmnwl2oSxMJPmCE,40537 -setuptools/py34compat.py,sha256=KYOd6ybRxjBW8NJmYD8t_UyyVmysppFXqHpFLdslGXU,245 -setuptools/sandbox.py,sha256=mR83i-mu-ZUU_7TaMgYCeRSyzkqv8loJ_GR9xhS2DDw,14348 -setuptools/script (dev).tmpl,sha256=RUzQzCQUaXtwdLtYHWYbIQmOaES5Brqq1FvUA_tu-5I,218 -setuptools/script.tmpl,sha256=WGTt5piezO27c-Dbx6l5Q4T3Ff20A5z7872hv3aAhYY,138 -setuptools/unicode_utils.py,sha256=aOOFo4JGwAsiBttGYDsqFS7YqWQeZ2j6DWiCuctR_00,941 -setuptools/version.py,sha256=og_cuZQb0QI6ukKZFfZWPlr1HgJBPPn2vO2m_bI9ZTE,144 -setuptools/wheel.py,sha256=6LphzUKYfdLnIp9kIUzLGPY-F7MTJr4hiabB5almLps,8376 -setuptools/windows_support.py,sha256=KXrFWrteXjhIou0gGwlfBy0ttAszHP52ETq-2pc0mes,718 diff --git a/venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/REQUESTED b/venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/REQUESTED deleted file mode 100755 index e69de29..0000000 diff --git a/venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/WHEEL b/venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/WHEEL deleted file mode 100755 index 57e3d84..0000000 --- a/venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.38.4) -Root-Is-Purelib: true -Tag: py3-none-any - diff --git a/venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/entry_points.txt b/venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/entry_points.txt deleted file mode 100755 index 93df463..0000000 --- a/venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/entry_points.txt +++ /dev/null @@ -1,57 +0,0 @@ -[distutils.commands] -alias = setuptools.command.alias:alias -bdist_egg = setuptools.command.bdist_egg:bdist_egg -bdist_rpm = setuptools.command.bdist_rpm:bdist_rpm -build = setuptools.command.build:build -build_clib = setuptools.command.build_clib:build_clib -build_ext = setuptools.command.build_ext:build_ext -build_py = setuptools.command.build_py:build_py -develop = setuptools.command.develop:develop -dist_info = setuptools.command.dist_info:dist_info -easy_install = setuptools.command.easy_install:easy_install -editable_wheel = setuptools.command.editable_wheel:editable_wheel -egg_info = setuptools.command.egg_info:egg_info -install = setuptools.command.install:install -install_egg_info = setuptools.command.install_egg_info:install_egg_info -install_lib = setuptools.command.install_lib:install_lib -install_scripts = setuptools.command.install_scripts:install_scripts -rotate = setuptools.command.rotate:rotate -saveopts = setuptools.command.saveopts:saveopts -sdist = setuptools.command.sdist:sdist -setopt = setuptools.command.setopt:setopt -test = setuptools.command.test:test -upload_docs = setuptools.command.upload_docs:upload_docs - -[distutils.setup_keywords] -dependency_links = setuptools.dist:assert_string_list -eager_resources = setuptools.dist:assert_string_list -entry_points = setuptools.dist:check_entry_points -exclude_package_data = setuptools.dist:check_package_data -extras_require = setuptools.dist:check_extras -include_package_data = setuptools.dist:assert_bool -install_requires = setuptools.dist:check_requirements -namespace_packages = setuptools.dist:check_nsp -package_data = setuptools.dist:check_package_data -packages = setuptools.dist:check_packages -python_requires = setuptools.dist:check_specifier -setup_requires = setuptools.dist:check_requirements -test_loader = setuptools.dist:check_importable -test_runner = setuptools.dist:check_importable -test_suite = setuptools.dist:check_test_suite -tests_require = setuptools.dist:check_requirements -use_2to3 = setuptools.dist:invalid_unless_false -zip_safe = setuptools.dist:assert_bool - -[egg_info.writers] -PKG-INFO = setuptools.command.egg_info:write_pkg_info -dependency_links.txt = setuptools.command.egg_info:overwrite_arg -depends.txt = setuptools.command.egg_info:warn_depends_obsolete -eager_resources.txt = setuptools.command.egg_info:overwrite_arg -entry_points.txt = setuptools.command.egg_info:write_entries -namespace_packages.txt = setuptools.command.egg_info:overwrite_arg -requires.txt = setuptools.command.egg_info:write_requirements -top_level.txt = setuptools.command.egg_info:write_toplevel_names - -[setuptools.finalize_distribution_options] -keywords = setuptools.dist:Distribution._finalize_setup_keywords -parent_finalize = setuptools.dist:_Distribution.finalize_options diff --git a/venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/top_level.txt b/venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/top_level.txt deleted file mode 100755 index 3702032..0000000 --- a/venv/lib/python3.11/site-packages/setuptools-66.1.1.dist-info/top_level.txt +++ /dev/null @@ -1,4 +0,0 @@ -_distutils_hack -debian -pkg_resources -setuptools diff --git a/venv/lib/python3.11/site-packages/setuptools/__init__.py b/venv/lib/python3.11/site-packages/setuptools/__init__.py deleted file mode 100755 index 89f6f06..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/__init__.py +++ /dev/null @@ -1,268 +0,0 @@ -"""Extensions to the 'distutils' for large or complex distributions""" - -import functools -import os -import re -import warnings - -import _distutils_hack.override # noqa: F401 - -import distutils.core -from distutils.errors import DistutilsOptionError -from distutils.util import convert_path as _convert_path - -from ._deprecation_warning import SetuptoolsDeprecationWarning - -import setuptools.version -from setuptools.extension import Extension -from setuptools.dist import Distribution -from setuptools.depends import Require -from setuptools.discovery import PackageFinder, PEP420PackageFinder -from . import monkey -from . import logging - - -__all__ = [ - 'setup', - 'Distribution', - 'Command', - 'Extension', - 'Require', - 'SetuptoolsDeprecationWarning', - 'find_packages', - 'find_namespace_packages', -] - -__version__ = setuptools.version.__version__ - -bootstrap_install_from = None - - -find_packages = PackageFinder.find -find_namespace_packages = PEP420PackageFinder.find - - -def _install_setup_requires(attrs): - # Note: do not use `setuptools.Distribution` directly, as - # our PEP 517 backend patch `distutils.core.Distribution`. - class MinimalDistribution(distutils.core.Distribution): - """ - A minimal version of a distribution for supporting the - fetch_build_eggs interface. - """ - - def __init__(self, attrs): - _incl = 'dependency_links', 'setup_requires' - filtered = {k: attrs[k] for k in set(_incl) & set(attrs)} - super().__init__(filtered) - # Prevent accidentally triggering discovery with incomplete set of attrs - self.set_defaults._disable() - - def _get_project_config_files(self, filenames=None): - """Ignore ``pyproject.toml``, they are not related to setup_requires""" - try: - cfg, toml = super()._split_standard_project_metadata(filenames) - return cfg, () - except Exception: - return filenames, () - - def finalize_options(self): - """ - Disable finalize_options to avoid building the working set. - Ref #2158. - """ - - dist = MinimalDistribution(attrs) - - # Honor setup.cfg's options. - dist.parse_config_files(ignore_option_errors=True) - if dist.setup_requires: - _fetch_build_eggs(dist) - - -def _fetch_build_eggs(dist): - try: - dist.fetch_build_eggs(dist.setup_requires) - except Exception as ex: - msg = """ - It is possible a package already installed in your system - contains an version that is invalid according to PEP 440. - You can try `pip install --use-pep517` as a workaround for this problem, - or rely on a new virtual environment. - - If the problem refers to a package that is not installed yet, - please contact that package's maintainers or distributors. - """ - if "InvalidVersion" in ex.__class__.__name__: - if hasattr(ex, "add_note"): - ex.add_note(msg) # PEP 678 - else: - dist.announce(f"\n{msg}\n") - raise - - -def setup(**attrs): - # Make sure we have any requirements needed to interpret 'attrs'. - logging.configure() - _install_setup_requires(attrs) - return distutils.core.setup(**attrs) - - -setup.__doc__ = distutils.core.setup.__doc__ - - -_Command = monkey.get_unpatched(distutils.core.Command) - - -class Command(_Command): - """ - Setuptools internal actions are organized using a *command design pattern*. - This means that each action (or group of closely related actions) executed during - the build should be implemented as a ``Command`` subclass. - - These commands are abstractions and do not necessarily correspond to a command that - can (or should) be executed via a terminal, in a CLI fashion (although historically - they would). - - When creating a new command from scratch, custom defined classes **SHOULD** inherit - from ``setuptools.Command`` and implement a few mandatory methods. - Between these mandatory methods, are listed: - - .. method:: initialize_options(self) - - Set or (reset) all options/attributes/caches used by the command - to their default values. Note that these values may be overwritten during - the build. - - .. method:: finalize_options(self) - - Set final values for all options/attributes used by the command. - Most of the time, each option/attribute/cache should only be set if it does not - have any value yet (e.g. ``if self.attr is None: self.attr = val``). - - .. method:: run(self) - - Execute the actions intended by the command. - (Side effects **SHOULD** only take place when ``run`` is executed, - for example, creating new files or writing to the terminal output). - - A useful analogy for command classes is to think of them as subroutines with local - variables called "options". The options are "declared" in ``initialize_options()`` - and "defined" (given their final values, aka "finalized") in ``finalize_options()``, - both of which must be defined by every command class. The "body" of the subroutine, - (where it does all the work) is the ``run()`` method. - Between ``initialize_options()`` and ``finalize_options()``, ``setuptools`` may set - the values for options/attributes based on user's input (or circumstance), - which means that the implementation should be careful to not overwrite values in - ``finalize_options`` unless necessary. - - Please note that other commands (or other parts of setuptools) may also overwrite - the values of the command's options/attributes multiple times during the build - process. - Therefore it is important to consistently implement ``initialize_options()`` and - ``finalize_options()``. For example, all derived attributes (or attributes that - depend on the value of other attributes) **SHOULD** be recomputed in - ``finalize_options``. - - When overwriting existing commands, custom defined classes **MUST** abide by the - same APIs implemented by the original class. They also **SHOULD** inherit from the - original class. - """ - - command_consumes_arguments = False - - def __init__(self, dist, **kw): - """ - Construct the command for dist, updating - vars(self) with any keyword parameters. - """ - super().__init__(dist) - vars(self).update(kw) - - def _ensure_stringlike(self, option, what, default=None): - val = getattr(self, option) - if val is None: - setattr(self, option, default) - return default - elif not isinstance(val, str): - raise DistutilsOptionError( - "'%s' must be a %s (got `%s`)" % (option, what, val) - ) - return val - - def ensure_string_list(self, option): - r"""Ensure that 'option' is a list of strings. If 'option' is - currently a string, we split it either on /,\s*/ or /\s+/, so - "foo bar baz", "foo,bar,baz", and "foo, bar baz" all become - ["foo", "bar", "baz"]. - - .. - TODO: This method seems to be similar to the one in ``distutils.cmd`` - Probably it is just here for backward compatibility with old Python versions? - - :meta private: - """ - val = getattr(self, option) - if val is None: - return - elif isinstance(val, str): - setattr(self, option, re.split(r',\s*|\s+', val)) - else: - if isinstance(val, list): - ok = all(isinstance(v, str) for v in val) - else: - ok = False - if not ok: - raise DistutilsOptionError( - "'%s' must be a list of strings (got %r)" % (option, val) - ) - - def reinitialize_command(self, command, reinit_subcommands=0, **kw): - cmd = _Command.reinitialize_command(self, command, reinit_subcommands) - vars(cmd).update(kw) - return cmd - - -def _find_all_simple(path): - """ - Find all files under 'path' - """ - results = ( - os.path.join(base, file) - for base, dirs, files in os.walk(path, followlinks=True) - for file in files - ) - return filter(os.path.isfile, results) - - -def findall(dir=os.curdir): - """ - Find all files under 'dir' and return the list of full filenames. - Unless dir is '.', return full filenames with dir prepended. - """ - files = _find_all_simple(dir) - if dir == os.curdir: - make_rel = functools.partial(os.path.relpath, start=dir) - files = map(make_rel, files) - return list(files) - - -@functools.wraps(_convert_path) -def convert_path(pathname): - from inspect import cleandoc - - msg = """ - The function `convert_path` is considered internal and not part of the public API. - Its direct usage by 3rd-party packages is considered deprecated and the function - may be removed in the future. - """ - warnings.warn(cleandoc(msg), SetuptoolsDeprecationWarning) - return _convert_path(pathname) - - -class sic(str): - """Treat this string as-is (https://en.wikipedia.org/wiki/Sic)""" - - -# Apply monkey patches -monkey.patch_all() diff --git a/venv/lib/python3.11/site-packages/setuptools/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/__pycache__/__init__.cpython-311.pyc deleted file mode 100755 index bd1ffd066527f8dc36ad8202eaa6154c4ba58fa3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13926 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 IZ-zAg2O0TUt^fc4 diff --git a/venv/lib/python3.11/site-packages/setuptools/__pycache__/_deprecation_warning.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/__pycache__/_deprecation_warning.cpython-311.pyc deleted file mode 100755 index eb906fe7bfe408f42f79010352c4f7f481bbe77b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 642 zcmZuvJxc>I7|va-)?ycDk>FO)hT)qj$-f+*Ru2;7o0xg$1ty12duAQWRd pR<}RNxU!euZ(psLFyr4fU|4b-XXq|EhI-yT?R?qn_dlhK`Uh0Qtfv3~ diff --git a/venv/lib/python3.11/site-packages/setuptools/__pycache__/_entry_points.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/__pycache__/_entry_points.cpython-311.pyc deleted file mode 100755 index 1684394298ad94d5535f37d955f110fd1106ccfe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5199 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 YTi{yi1lLkFgcyNpuMfL+6Je|W0cB%sfB*mh diff --git a/venv/lib/python3.11/site-packages/setuptools/__pycache__/_imp.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/__pycache__/_imp.cpython-311.pyc deleted file mode 100755 index 3317d58f649295e4f2756db1180682b81ab833db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3655 zcmb6bOKjW7btq93C0deYIdN>K32isFd`Vv7k^#w|3`%@bkOEIovO@|Iqh4KZAUp3}wnim5t-YrgtW?QD}m zcj&YxMbYCyhQ~k#)2@FBeaS4u{dQ2%6;&r`H6z<>PSJ@S0PAR&eMSANhn@5Os8wf3P#Wd#);omLQs}_zontUokbebH%>_cy|0i6>OD22qWJNws%4IiE)Jx#7QX|4P2sMD;4>Z5iI zI6_X>F$g*PIEbL(D; z92so#tu-uIi8WW7BZF)A1u4+mKoN zTX-LuN~csrg9qO3&=G3mXJy*szOpJh(L$`g9ahaNi#Ou z;#W459J#2dm_B-&!L|pl#QU8XWeamoG@Zd%!*)kDtv7_)ewd{R!I-`UOdq4&NrS4J zd~#Zv##+w(Vu7MrvRROAPQ%IrMWvw|cAUwjbsdK(Iy~!a$<;{X^zHkp**lBLnFTv? zgYHpLo4Bdejk|NVmgg31kEYu!joUV_7jh7O9}zpUw0QT<)J$sW?(FQ`y_qFPmb+$0 zZ`@y=nOdA~!3v;hYVl{c=WfkR+g&sFmS+~0<`x&4?7~#4v1+qgL001dOkWA655#8O zWU>xf!)8~N92^pI5>Ybv0!4HB#_Fo_$Y$YsWE~0-npE6|Pf!A(<NEMiGPl$H+wT29XuE$mxEB~S1A~=S0DtLgm2nkhOk4*U6W0OvAsIVVh85_m zp-x{v$lrckW)GsV&wE}+2lk=^mG4)hBUW_eC1XX$%H00R)6WBzIBAJf=1JPidRhNR zH$7+c>3!?OsCD8;ra=2a>~wj$JiQ-^J>9f=#;l&JW{CEK*qQeAYi5XcXZ?*3c{=y( zu^BsW3bY@@z-GHrH8y0$hRW0bebat^Am8cUcb`2XMp*b{H(X< zXXe}UbEPGpgOa0W9LwoYRCyLK4Tf>nty9jz7!Lukd0Lugz<=Z3rsHE8{OVPb>&nru zm9Y3HK=e~ecmqHQ9UOCLAwpgBlMnm!_LbMd**)QGg{ul9mM~(nBd!5k4@7HDI)9f1 z@T~@fkp6K7B#k;1A;a6A@|F<32Fkz~PCe(?iEaZ7*Af;Kbyah1L~-=RyG9C9Be}5} zQ=`x-Q2#N2?_!+;p?`O}Dhyb{fXNOxR>8EmiFexmR7%n^sT4jBb2|)a#jS|PX}Rmf zYdh9lY^jn9o0Fepv^+#pOm~bE6kMWUk^-8A@hAn(scEEgZr3@)m&n}%jcD)rtM2ix z<4<8qt494#0BT-_VQL;P!`2W5LBs@00s7lVC(L@^M}20!zd@sBd#`aQ6b6QHq$IeY nBLq_lY8=N5)KCL-jW8E#s2wabEHhd|?I6rDgLLgUa8C4pB{Vf0 diff --git a/venv/lib/python3.11/site-packages/setuptools/__pycache__/_importlib.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/__pycache__/_importlib.cpython-311.pyc deleted file mode 100755 index 96e55517364915da116d2808427269d249a77272..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1955 zcmah~-%A`v9H0Gl?%jE&DkgYnyV2NkG~UHZ`x0wyFohHv0tVU$;oQ5OyIbAeIcD}W z$_dg2YJyM;35G(!Crk06|H>){ITi$=82INpH47BY|_SZEd*;&U`BU^FkbfQGaX4rvcyWJ|K;Sw%o1 z!U9%y1cY|sJ!=ATVj)k=Ryd}OMLB0t0TBb1j#*Uzoik^e0(Lyg3=Zj(FM%E&93sC?)0Z(R-%g>!RSRdpX;gqy07}Ba(7q&0$ zw{Qs6#rOUC5iOx-(i5~Kyin?>hN#Hd*OiiB$j?3qpQeB!x zPj9ZuSL3%kBIu<-U4Gw|jUlc(qpZ{t8npWkt5K|(c9l@qG7EVdySkyfx@Hi}oKIY> zO39*WV2xM?rnfcIDH6M?yJo?{A;YxETxu3-u1Or0O@wRT6S|;NQgaNgM5s1AK6dA` zY`8;ts2{HUJ{M^mZE2j-7BOYOqM58sjkaXE6>W}Tw^nrtvDjQT@wfsYFb%A*Io>iC zu(hnYL@Qv85o-|}T45Pzn5$cs>6A6y(P~xj3^rPNNJ+cOj%-`)@Qn1rdprr^wXlWC zsE(fYuL|y^3abk*#QA8x15WNnHTBnxy6~&Gk)A<+qKxP#Ocq+@6tUm)-FdVh>2Bp4 z(}4(QBwx(l@kLVbd!iUcSz)}2HEr$mQLaL4oU?UWB)M-%nT+T3YBjfroy8oaF;`u7 zE5sSkj*aD*>Eh9#ZY+bnqL+l};Bd&#Lraw_NmNK;J&QXBLb z2vA0){8sqM2Vr5}r<72?>udL{((u__UDBxosb#**N4~_CnIGrnl!pSX_%VuYvWPP= zUv1SG{eZJdHY@vam*md?z6=qvLxqfIo8JpW~-qKx%6D1yeNm=a{LIDF2}x-m z;4j^aY?RkQz7db8FX_uhixhrhh^DyUxjj`UY+}?bJV}RP%5N{@-(2uh5Sl2l7Cu4j zLjgh)iF*Q)I~r2&W_e#4^rXS2Jmt0braa=wBiofdIoFVLUf2)ijMv_S*f~#WUmEbF Tfu?-VyQ&|`pL$pI(2xHB-D(0l diff --git a/venv/lib/python3.11/site-packages/setuptools/__pycache__/_itertools.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/__pycache__/_itertools.cpython-311.pyc deleted file mode 100755 index 873a7a359ce9d9b5f89f0c47b73062969d88af5f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1154 zcmZ`&%}X0W6rb5mOq!3{#?~JC!AK7=pjkvcD3VJp6eCh-v0xFI?2a1Uug>lUBP)dB zAwmuw3PMXkDA*P+{ZlM>2n#*+(%u507f*e&F{YvIo1Ndz%=>7*pU5b|0za(WEmYn=^Im;4CRZ^JK!KefL?HF6KWEX zJT2*rxEA5G>@Y&fGSxlym~)Gh@;WgsbKEn_uRKO7g5eO#8DXYsc_t_`EuRQ2777KT zmmPPMK`%L5>*$PTX-UoIa-qn}EX|IQY)OEcUAhet>yFi@ZU>emdty$URJ3KLF>#AS`bEm0-_?jnZE^h(|vMFIXRHw z>I5>?v>?%Qk{bx(-AV@XHme2^hcPpV3tSVzu}j|p-VQI6@JI-cL1Tk-U&Z(>I14Xc z6&62W)X=YClo~vkZcNwan}b7*o!XP;(A^e_Mu$VF$C|0Z`lG|x!D3^vj+@EUVWd7& zpZS)#cXof_OBSH>ea#flGsUx1u^GQnk00JVNH&u7Wb^v%db%@O$*xU)4ZMqlN$;)X z*$#Bv%o`T;_v+bj@k+y}xd=N{3=@OLWLTP~vjQImhPd0#96(FP7&p<>S^w9Hqmi-W OWD8|5r1c*Nt^WqN94!q1 diff --git a/venv/lib/python3.11/site-packages/setuptools/__pycache__/_path.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/__pycache__/_path.cpython-311.pyc deleted file mode 100755 index 42f8cf841085dc7d0dffbcaefae14e5a9c806337..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1475 zcmbtU&ubGw6rR~^lC5b&@uUcLXp}afyS6<4*~ygPCs6fI7Ptho{lC6UW%D2X3% z>Pg1igjLB*$BiQA77cGXjiBO0ZCPXCm_0J$h(OYlk?YmnSt=Ys zWh;`5HH0&*>e*2{?x&jnbi$YCpo*#~PJ!v5&-wnxvrpI~w&<_s3*CI7bLoSbnZL4- zT{^a64y~F)U2_PW?Pm*OP;5ja&`0A8hl)J(l4XOJiC_<4@_&N;li2uovFn->NQm91 zp!)fsTBTf&DrZf?gsqoHfE3lBK}m&rZc9)SfUb-R5;93Rz1aedL2p?TM6zvl?E?hb zHP{i2HW88s;Vh}Rg8F1QWW-}l*dBpkA*7VIDGf<*GGsm##qGfH@o}Q6YI%kSU8gd5 zf(+V@a*8_jByUme>FO01f#@?S>EtI;2(ps*xVwQL>#1wmU={O_X5$MO&MG&Vz%-FgH9Igg+ z8mFg~tItYoR^UkKvTu-1pecQ~&Ni9fYS3}6?mBg|2mxj@g)!bhJsthqK!;X-e?D4$ s550xaXJ=OON4wTQC%u_T;o(h`nBIPTdg1scf?;t=4@*)He>Ixa57ii2ng9R* diff --git a/venv/lib/python3.11/site-packages/setuptools/__pycache__/_reqs.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/__pycache__/_reqs.cpython-311.pyc deleted file mode 100755 index 64e3e41fffcf2cb2d8af3ded2c0aad12385d7112..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1136 zcmah|&1(}u6rV{pY3L@lig>Cp)+z>?Y)e5Yh$j(L?3X8dNjJNbWYgW9b!JkGig@s- zH=!VSY_;@n@a{2zJ;Ehm!5nxNz=rFK6W0zc{A_L?|tl-LSYht#2-I3k1;~O z)aF!D18{U3z%Fu;i+vPeCxuav(mK7F#>$@ZjUcm`0i1q^HnXk)dcws|Q8Dvd1z9QL z#N43ITOOwY4W$E54J8LC4eRI)s9hvS&YD9kGsF8xo3hjI2H zsl(I6{yGD?_~rXa0`knGzDxKSVU?UCtt~2db)x*;ceGz6VhcaAGJzLZwbl9$O6-P%E&x!>mWF z&Xz1YimV+P?pVH8wW79cuyCooxM&IBQi^P6+pbe#2`XEWWXu;<1?nNnQ9CI_HW#!q zCDzURg_?|i!)FF*V~*IizXmsh*9Yw_$_*IbXy^^UQA z1P*9y7*rfR3=aT|4}%=G4WZF-_;-tSQ&)5~@6(7==ofW~Dq9J9#%bi+j-E-~*=V~C zSqj$T4uw>8nj=#n25m|6382RnQJpXdjDNjs7H{Al8qt>wyx2qM HmFDpW?0p&g diff --git a/venv/lib/python3.11/site-packages/setuptools/__pycache__/archive_util.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/__pycache__/archive_util.cpython-311.pyc deleted file mode 100755 index ebf84913f29159528d9c67427f8c4b301cfc9159..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10164 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 diff --git a/venv/lib/python3.11/site-packages/setuptools/__pycache__/build_meta.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/__pycache__/build_meta.cpython-311.pyc deleted file mode 100755 index 593e8305ed2ae24480add3f1d467ab34434ae6ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28147 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 diff --git a/venv/lib/python3.11/site-packages/setuptools/__pycache__/discovery.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/__pycache__/discovery.cpython-311.pyc deleted file mode 100755 index 9b40591f284c5bd4d1eddb7cfddaa54081e147f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31128 zcmchA3v?XUdEV>`7+@Dz5Q{efVhNDMgW!TsQKTSB6u<}g04b5OEXeX=u{!{lTii&a$hkWO)%P&07asP=P^rK9>dA#D} zxHq{NH_XKxF=xUt>|j^tuoG8T!ZqO@b~`A|o$yR}hCS@wlPH-e9WG_}B?*3_Y`AQq ze7JnVJM5kC4f`f4hASp2hbt%i!~Th?;i`#E!<#0mhpSnBXCg3MgYrrfwG(y2bu5lg z)K4@FH#j(P%bo%JA`IiY>QAKG+J_P5geCW^_MOO^}FG% zLYY{C@0KOnCfbMF@!fJ^bIgm<+%ezl?%{1t?gSUBc%6$?ehYo_9sJZ|cson+Bc)2% z{w){M@YB+Eu(VA`s}^?TrFF2h0Mcp--s@y(wMeTII`ZD@VrlhAYY;l~(z;`fLSw9n z)x6T$?y-{CX0&1_d$$?yw&b;efy@9sdp3x7jC}G#9$QMMuP(i+}f*+&TXdRtc z8>?xRt)_ge9q;$XwxJ~(ztcFz$F?Ki?t<^^U}bvqzl9#?K>j^3=LN2-b1LlSxT90) z)I=m5j|O9LDVn+}h||H;Sn&LG`cf(xoJhr{5`q+rBxAwJNc2i%91opiDKQvNMiWy~ z9C_l&VEU3!j@Q#-d~_;}xGwfW3ejRPno5qv$AecRi77z}m6spK%SZ@LPKlE#3B}=S z=}U1*`&JK297`nH<^< z?@lEV!|FpHYtyn&EhdCW5=Etgqo@@1L`;b39TB9SG`b>q?UInx`i{zEO;@XeZ(WZ} zOeTcGXiyMGh=qT8=kA~0nZt?luZQBvcwX$}wAPdmMlPWx-qBt`J$qRcmG`H2^yrD{ z$t&Y#f|{s*CLG2`(&2Dua@u&+o?~KK1%$#J<_E&DNIDW8izkFo`g)p;&=`izIz$>! z*+wFk0th5iX&PADm<9n#=u#;yL}IAcrN~vmHp=GU=;eti6hp8nM532;aQ!*iW5MlL;*4KO!P9^qxcUjwOL+qL-o(N$7GY?(sxwl&V>M#c9W7BVWd#g?buYXSr`7$9K$JR93<9EyR4sh`qqQ=NRg8E6$W8)*x2lN6}@; z$b_Ky;!-?Dcx@~$h+PhrEK%XXkI(g90;24lh=|ct@2S*yYF{tS7 ze7-NVXHTybPYb(rWZo;G!ISA!Dk1e61OU@q@rHr1JMa}K)&k5CeGSt+AX8gus{H&XecsUAud%E~zUi*1VWph9JWS12)g9dI!AXRqM1 zrh|g|Uia8XV7Njk)5@yE`<37V{K!}Fx;rmlm9QyRiCTk80B7JYNUx4nfzDPdrQzdo zA|*4=K8K+Uf|^N^N{58&Dh(W)N=8-aji;v>4pZk)uQpD>F;;-|9v4z7kDhty=*t(v z$3EMC=EZ?yihtnP@uM%Exu{2c>#$D(`;!xsFf7(a<7F0zX5w z0^$%;lVUuQ7J`XXG?HNN2Bm4V_qw$)8enx$b0Vnk7pB0f3DnPoHPFOVP|NaEu%o*p z7>y*U=0tFeim=+F$+2ie)LAI?b+g?s5er3KPa~oaSWmEHER_nOSk__Mhu8>9Q=@t= zsto1pFh1Bxd<8KaEIJrZOG09-%i1h$ntW2Tv@B*72gguShZK}1g(#utSPwuaG0pmu zIs;8(@TL#0&NLR5KvlDpLJ+Hh*H0^;!>Bj)v&P{9U<8!FV1PPG?PkCN=qcFW%Tt&a ziTD-4=$;OJP|cckm5Obcl8T#Vkx~vGFBuD?HlkQf(JnB%N=0~d3Z)bOM+sYz@Sa<7 zMH7;^1NUMF1)T^a!aD@a;%3|^ZYpfXry~Ks;YFgYg!vvY3h5E;b=gL4dGKQ8MV7m}dc;*pud#$Z~3Kh(#NrgQ{1k%`e*gl-6p zQjGrYFQ7s zq?Str79&~(dHu699iOs(tTNlFGC!H)-tM=4@j)k^a;>Ljgw3br=F@W=tArRtcCeuA z>okfZtan6e(oAj9?|uD5FE zhVYYG(KU0Hzcu%%toziX9i4MS3&$4Q7p29{JLj_QPMkS+=UPYC+_{Ap7x!gci%;GO zXWd;mbMCH3o~rc{u3_`q*7min9qVO54-giDNB)|14?UD{)lG}-cUsm<>512$SjKX$ zymCHzyK&vCzsBDE(8ZN(di|AkC&dmp@UZT5c-j`H);V03uCdF5dUpBXC3Z0b<7H&U z$4jc$ogU8_M<%e&(RB&0(bXE#E7h-mPR(ddP{E0MEQ+6T=nUlJQAC;Yf+;P;T;ROj zkP$ril?XgI^wI(jybKZnk9?2{kjDr8S9w96ikKJ3)2CFNR~1~xL4&}n4>Ig`0&`s? zMyMzcX>b`f2GF95Vr6tW6<(MLGf8X4*BuT|PDi1k0Nm!$#zMxNSYetFkN*OIq#`ye zN;Bopw826bGTbr8J*OS<4REji>(9A3?uPq@=SIn_C+3Q|e$k>wzEKKBT#F@aJzI)5 ze(MHrlYQ~NdSu-Co%K5Fp5^Udy-~Ko`xv*j5>I52Z^cA4C$*JVQ> ziMjJ?;*FtpS2?K;!VHn#f&*Xo+TW2Jx4#TA#D#c_#diqju|xDD)|nqGxo5p9d71TO zbXeA3VOR8ytsD@d-@g5aF&ALbGh-^^j)HqriL0i4)tJGgAxkio(4;C-3PF<#R9Uee z(xVxKoR~{0&EWFDRuh^tN%lpM7q6;*O~jK|q#=foyUN7|)LL<0izKcv)T-(x+?P}F zq*5vh2~f*RbOQ+_Du5>xCY3-qkxE^W!o*)f>B8!-lt8+GY}Mrxdr@HC1W?>05h-qn zM3Uk`)dWf5!KQ>+gbSfkHa3N4_B9@#RqsmmiAV?>yrprdIGJ%?4YuhWGWoAx#ye6i z#zLjUKlX8L+uo`FZeZ!f_nPiCJ*dfUJ)YZoT;6(oovSI^%7UD)Wqx2`+oI=D{pQ7^ z^mpgl{K>Vt2E=Znzndo>)wiy5{tDzru;6;wyyfnRZ=8AS%u>yglxyB6H}6|0d$_sf z?!j+7^VTyrHJ-Czej!KauO{ zlY9DD#9GtVg|qYrIiDM%lzs8>kKRGH|uzHD<9T8BAR)kA<_(A;tu6A0U;o1qnllO@v%V4so>EbI07?Y*REh3DC+|1TIkSYZCZ_|4u_RMiV zF5#-GZ(n=kOSiuC_UPU5ZzSGIEbYJFlH2l(yycmk|5@4pY?gmkV}mNir}2__go0-% zc$R{#6g)>kKLrC69HW2$Ts%$z<9ghq(C4u#=5r?}DGvp&<0rk1z~oNWolXzG&QZW~ zb$jQAi0yDTdbSczfD7>ixDZc(3-JWFn1R6)Q0xIx^d-$fJ&BmwJ8RR}=}a|rI3Qvl@>N37kK6e*fOx zw($ceNN9zPwMvPt5Kj2sh2LWWby$NP1ZzVVSqB43h)dZ3N;-;sD^vtE{w9i$sA+TD zBY$8%t$_lc4+?CY8352=i(v`~9P`IILU9y)7eDC)0&}d_JdE9|$s8c2u4WmG8!iuO z*u@NtfkC1ftBwklY#SAw$~``h6mwLFV>3qu99s!-Y~a>P3Py)_asoIu`m(75Jeu?gOxZ~QMIlp`wt&rL<32;cQ*g{ecDJ(`_Qr$l`oazO1|_-+ibKQ(d5g1H zZu{5lPoG2G8GFbTXS!xR_WWRwUSbSVUcAO2<;8+Q@@Vq6Nb)x((~P?tmIr8?sIn$P zW{6nfC1^X-!u7OB%6+BUI)PN75HA*GDF~S>C2AhU9YzssmT5eKg+r*f0+@wCSjGpX zZz50`gdf&4yj^{_{u|A2HD`pS&*U2S%Z>YUH3#GxOs3MZ78cA8Fyg+tdFRUJo!@=# z-ig(ozLlQ7<%_wV=j5K}a+~|*&HXpe%pYGEcoe8x4Roypx|Vk20(<1Z9?Z0g#85rb(Vr#gj9gEGG zE4jwKa^v2tyG}jTO3~74G@SMKTpj0Iw!b3S&?Li-ruWDk>=z2&W8#fx=Hjl9S|1 z0R@wAO;XCDmmE^-zfTDKgBnm~!J*B8v|58-Q4;-XKaf{eo*|wmiiR zKMYtxDU_5F)%vG+n3{^%Yka~@wn4>3flq|$9_|xVK`J34T|tRskx@2v%E@3DhHpp` z6&i(x{}QZ>SCn$&7CgFeT@a&jNl?o4JLzN3E1~eK-8M}fVXSui9&bZn=;^#S9JBcQ z2V9JM+d1acu!2t|u`|w4_mECy58^e&F=^w(4kK=6>juMND%?IqHi-zPrf=JEBD>?n z@}?!nQe^2#`peuvMBb?a;3$37r!kJIL6lk04BU=%g8}|yJV5*C$lzLd0NaCRn8M=? z=d3ek5xg@T>FTP_jfidks1|FJwC}Jg8Z!S?xN!(sel3)hBoLAu8`=@bM!W zGZ^eWj6$)xVnQTi64?Wxs!b#yUJwk43kVbsQzS6R8xDNxqwL+JAZ~| zeT34b1Oo7nRn4naZ7Wr6nSHsc4!Nph-t(w=Yi8@+ldH{pR+{&y0%*4Rh5J*>&%b|t z_29{sgC{>|$Q^t^KKMeGZ(Q>Sv;GV3YR&zi_Jc2cAbueJVI!KK>%1T%+PzO%K{oVsL$9rNAmvqfeJ&`aG$Fu|+ms80Q0Vvga|oE(2v_|mjxqCn z4sJMaa^nu&RyOO*$8yxaj0d%0vJ%7w@MD415(GFFQ=1|oNE{4k#M^aouDH65LFff((k)1V~nwUH?)1|7ZG{hx^RTl#b0yDC< z0P>_Rl=Bl9lNyey=l$mw1K((Pt0D8`(({>JxyIdc<8C974FIre1TQh82aGRN8}U5^ zN=XtBD8yLRMs#a!ZPDt8-@^-=>HB1W!}lLn1XnAzuT*T$jOQvsaz$wF_?oX~{;=_B z+$`@vkZU+9BlI54x{tEz*yfT4rP1+t8_Ld`OU)$Q54&TY*STR2_%v>~1l(IG%mB_9 zUm#ePu{3f8@>(5?khiQLuP@dDmmtS*MXUm@Kc&pIrxM@tTb|+SGhD^eoUtn0Z_@5J z;l5hCuf}~qyAR;LM!T=UeQm5(s1v+2Khy&*&R)0>)g!Gw)_~SDAa|oR2kP30)TScw zO^Dwd+YBJvqWJrnyDePXRA1hiUpx+Xl3j31fz2vHE}E)qF7uVsoRG*}U=$V(-4hrT zYZ@*vB237tpGN1Hn3@Qx?!0<2y(zT_&0iPD1P&sA802FO-Z z7HLx1rZ_PZY>E@lK3!16@-*}>B2P4!8g#K(cGzKjT1@yN(6#FR21 z6^Z-@W6GwmbR|AXVxVSBlwhB6lM{&e+jz&yT9D~cb&Z{A$m`dTp0b_bemh>ApQB^rBO_g*;K|fA0iLEkdIA&4kd-DH0VGT?7R{7V zQw(f;JeflM$C>v=LCeSqUra>>G@MnIEIE1oWO3RU8PUlG^$Ola#Iz3cT1QcbsvqkV zLgOLTSsiZuWM*L@a02c_W4YJO*nf8LIRG6ukz>rud zxC+#8Z3Re#{-L7{9$xfe;z?AaR|#~5 z;7JNvSH|)XyE4;Q&?d&xAn7S;Ngck3mcRl~b9-9$Z_WBc@4oQP%UM2DIJ1m~Jb{}?{u@FWje;PgwPQ)cP9ioh`PQe!dR1H>B zArX^|89=iO3Py7LQyn|?2@C{gP(8vGqihLEJV}n4QNf1y;A6lnxuZmT$0Ab+veW`i zFvl$BkfknxNCt(mF?Ase`J;;P!Ai#`=w;K1Z)7BIBrV^T7z!e{Qlt78Q^0bQ0x8nT z?<;vVb;ZICn6xEmK@!X+t*&D+$^i_aVzdND)n`dvJweERipE5*<9wSIj?EvLKeCv< zJ3D`5DShut^G6=}s^^bC;(e?9wiSL`cKg8`|D?=6ndP5c^ZKFTEeo#ss#bk1E54ST zuT}Q7W__(NFcUK|k3TlG#D9e^*jOh*Xl!;-PY~;r=erGt!kk&AJ%Z-oBvdj!4mv1n z4r3M}hhuWLEseg#4wlviKk;DNtH;rD2lGp@JeQM{*P3ejcrym)_{fL`6d>pXSpXLi zOMWc=v_T2$8;E>^!5j-}c&S&_>NEFl(5xY)!ZuA|5nyDA@q%6pn?TN$syl^JZqh_Z zyb%eWv7-2gXcMF%0ucUaA%}4Hk)LJe`;h8~(a8+w&$~sA#rV2v)A4 zOyJU%-fYX@{r&R3!7Sgjwz>80A$jxe`vcj{Pi8j{W&4J*b?4^2k9<|P2W8)uOf2i` zUgumD=NuZ+ZC~1-_4ls3DC&{FY28CNWNWTpNZ*;x^yd6~W&hr+f9QVt{b~8&(0ZBS z>1r_1s0fWZgQ6^Mi0Wi;Ej;q&YG7&@LanOg!tZb>)0JW#3MMxt##HRe#5dza!`GlKou-bUPVSv+D0$@ptC@-Lk)Xz09M# zQllEiK?B7A>^fq<;<7U~#g#br;b!_{E65r}W5seFvLR42xw~7gS%>5#&noM(6m!uD ze8FIRc)I{x(8~PD5~`9kY4gMa|3fv@m(4 zvSWjq(=r_+_hln@vDTTN9^M(&xXHk_DxFKP4JqPf#O!T%1LEWL}4 z?fX~S_vhN5klUXC6>Td2kj4Ngk=@Zc5m#0Dy!*#Ix1}w!jaHt3F)Ne#riX+?v(?Wo z4cr@)dye1^XO2HA^GCD%QQ%C?mB%&{2#GLsI1iY$BSWlOu%J1Uo@R=|JrICFD}kJf z(!)XoX`dUIcg4S0f?5_F`3Orxt>kpC9hYgIvjeErSqvGWrUu&5^U^i8QQHmFX3d>n z6ML&b1c>)F_|vdYe>dHv-*H@~(!4kC@=LarW3)6KG~f6elw%Nqv{52lAkDt>SigGN z$WyF8Hzj@nqMA^s&`;jPLDg+p1$avxvD~jnE2vOIqsAPs znJ`n(L#mch>M?3-(+8>&KQxSmp9ns!ZdWlfVrt*SH2@(TuEpr_nRXhBpF)tuhsghN zqm?2UT0xa2R5O~8M;IAhP+a2zoKxZw2HT_&N;xX4=`5IcmP#XtE||t8MlzTik@)YB zpi5Vbc$5-bOr(`C9Qs|Q9Djs|BFaLY<)wF2CgqojXp|sel6U=PP>p%-!|Iwl9dGu0 zwFeUTmzKWxz1M!@wPo?afn4vP+&h@7J|$P5q6LMU;E{Xd){VuNa{leIAHJ%26yzvY z5mq0?nd6_6`RB6yb09&h{FW7d%cA)1-ggeJw(nbM-v*BRbh=-MQMjd!=>v{rX(%A-VOC8sGfMq zhgjx}{Qf7Q8%?XmHlQ)_jlL5GDOfEt@&Z=BG9?&h4GC2GEEr)kos{Y^aD?%;d@}IF>9KY_*4_nHTA^DrVEHcdQ6~ zKL-*~)5w4~v7PAr*BMls|x`bupDUo!G5z|IOX|yp1^-M}+o8GXkZOCFq zFJV6&vge^pLgGOEFyBxUG>=(Al{4FH-M)b|(B(1FhKf<@>|(G^Ym{1hyheBOb@1YU z0Cdf4+mOAqh}Q2AmUs@?;fi0wmHCKg8(gmW{uW$t=J-=Ge=5tLVnS~BioZMO?~(mI zS^t^)?$zC=R(7At?LH&#K9l9o6e{fv>9z-7v9Et9F56n?nq4|X3e8n^&<0KFVO6tP zIlM%F+Xnz8GX|NJDc7x`>@ny5D4KP7b_6_dLc|w?jOV{dcC|sGwR5OeqsS<^k zIr=bX1XT|CGTvoLN*&x2u{%{*bxY9A783a`vUui)W&)Se8Wxfg_KXTAQ(<$C!*0;x{4Rz{?M|2wdK%C%c13M-w)+l z2IZDP9p~3{f46Vh{rxie$y2$Vr{$feb2Vq=nltldpN#d_NNL=&!uKq_yj-5+`(?gA z%lBhB{K6o42g9~p2$BRk4C(WK3m|FgbIE}HGk{T1WlHf9ih!2E(K6k05#Y6hz6x%C zhK^B6HH6Yt#@v*#|+IsUB7pUv`T2^a?M49Yc7!;x|> z%c~w%3a{&B6!#Ty^iiXiP!mH6eH{;W#votQ8*^MCh{6h^7*uHq$At5S3)VCzHa)}! zh&SB0_mHd?D`B3zrR<)6yYz+!YXabtjfInWD*)_c^JO?yVSLJl#5?pAVnnbKk&nWB zl!Ws%?rYDhTBrft)q(A_FcUbd(@;#}U2GBuXSNu+T97IbHIQ(VCpa9O`6CNSCF%tW zSmbId4td952k@G{!yVX!spK{6_=dt5D?r*~D>q;eb}Ebc1~8Mq%E^;NkY~0B4QH;{ zd9{F4f$i)V^-hb-=>W9XFp-fu4dmD=k>CUHSumK0$h!bBTU|i@wSD$_Skc<{F;pe; zYryUeMb+E3G6vN>*m@Xq171np5zpMAPjdv)_OPQKpkq&nIwCkV8H{3&5x5WO0>^Z) zbA&`oU1B7)BWuQp%6$o{ONF)#$%yJdq?Q>B?hP?ZVkBr4bZoWV7qTifnG|JJ^JCz2 zZKgD$e%D;t%{+5WL6klUz+iGPd)fB`K5Fao=di{q*9V6>oFa+q~xM%-YXKzGt%bbKPAT zs9M^#&f&s>4=$Pa>*d^#;|0gMS5IU~^Zn~vxIkyNx?_o7;_nCEtGHK@tA0YRej@98 zV!ey=wcy)@l#MVL{T}~00=w?a6lY9PM)HB4Ag6km@tW<*LV--C2eby=@g4lsgW0Z% z>elQ+4YNtna1V&B z&Y43f&&JdJOGFepy6E(pzV=5n5q=5Tpiba97+zsDYmvQeSeRPYkcqt$e<#Uq9|h_) z3tG1NbdEnG^CTO<9!8e4{VTrxIo}g9;22A{dYMqsv*Pc``9rclwC>@`Dp=v9aM-!F zqkDdU*>`1MdzPK+F2u9MLii{6V(?E3)5v8Is{}t|-|GetZ@?~N%8}pPl6TTEPF8=X zc-XdWL>|n?Tvr$ziXGNfBbGS=-EPcd`mh!i6l^)7P6ufG?U$G*e924;wm*%+e9ra| zQkf(otQw4C1j!J%=rXp;!h|r zz)RCV(Ix}%%;z;jmIYkXzW5eEd?1X=9$hr9+hw(swE1FM(BMyuJ>G<(9M%T*Ni z$lz;{5KQxEEN|T_cvr%)o|!(Y>YETJDVcPDWGWL~#fxo)kDU)<3Awsg9bi_VT~1wB zglUo(nc_vY9vZLbgDFFu8|J|lgV@k7t|?$t6s#dy80{EDv+40yfHb88s@X5K8I@<+qs=_Tq;ADyg|Sz4t0!6Xh~+o=ioeEF5nG-)Cu}HqohAag{9z)f z4uaS%z){u!dmZp*p!MC7O!}Q^x#Q69NZDY2F4!+43=GJDfq8zduIWx(uG^Wd+p{Fj zdw*Elxzup~sR!;KROV{W$+hR^%h$ZMgoU>}^!aZOX6sHb&mh2=^PQ1>XR^LCYk`)m zuZ0YOe0Gy*05nykL%=Y7RmcHO5|;=2*(E>NR^_Q7UK5x6U|YSXCUbF}!zDl1>-C&DQq zgn-yni1tqF!cd@VVmh=VUp;WcwIK<~Tk>ir5MW)NV$L7#TOO;A%e)8vHZJ(vI6v8! zM%+B>EN=9M!ofXLPRm>=w0{+QE%nXP+6vFik6vKGL$yy!UQE$YXS_9u z{m79c5TJ`GBs*Vei?sCw+ajUSJ=%4z{v3+#X?s-_XkY1wbiB$0*PmY0D7_yI#k33d zbseMI@z5o;;E1hM?29_ufdDVi1-Y~jiO|t-8|<8T62ofo$7#OdxarL3V{N$L41 zs(IJ65FLHbDYoMkB8TO0+7;7mAuJd!=2+ul%ZSufyaZ4BvNzR{rmJ|T7IB-Y0BE2ENsLJ{i-uxuzkBPfoz+8pAyh*$i!Usb{&M+uTJuu`1MpNN<~&Y6rhebUpD0(P0j zTJT`!;Ynfg@W_ED_KaX>%(0wGqvsuAp6Op(g za35d8MI^YuJxvZ#L12?szl(?&9n-KbvP=bI?Pnvw*I{JE(ogSs^<3y*+V{Ofzj5gP zh4+r!JF>i0-r2Xh^VrJHV-GIncAk@WozYB|40FOV}>ac%Rjpzpp?`ZEzEEWNdpnEb8vK}ep{ z2uZ0`f|)M`A#s9`Knopn&7e*(x0S5rL$w{RNsw5Rb+fLF8!r|dH%slgL00-_T_la) zDzzHyZk9sR^@HZJ|y(y$t28y1{!Np8e^dbG$ay-bMsuM-jQlGG%n9%XR`}EA?Q06!#qqd*1B(YF}o5rkwtAft_+- zr|M&24NdAXB)*EuV0T1=hKQS}x^GeyUqGO2(kjH38$dmU4aOQMv4(=P6nq{*7q2Qi zjESREsn&Z~!K2_zU}_g@P%wlKERd&C6gRC*Rl9-2aYlFy(u4my#fcO&Q$znV(uwr& zTvgq|rFZ+Y0W56J!jFwJGvQ1w<+L#e?xtn#fZd~3#?;~$vDA_RWEfd`IVK+^#P@|NLJBjjJb>8hH}{dV(!? zHGR(s#~2%xs~8DpF80q9u#JAu{2vJFUZ~ptXn^YaifN=GpF?`p=B76S+Y(#0ZeinT zGQqE|V48NeO-zR{+rVyou?_!&r;T($y>Y2ml@!`;fDH+?soXsA@KjDn+yAsPC55m9 zDsuE{IXXhU_V;@yrh8F(hiY!p3;3xOnVA0nP?f(?Jy_rT+`Hvd^#>CnjIq&%>E}=t zR<1fKgicL{?MHu&V~BZLe(dOl>4G>n#UnD0GNxE&nA}9{KSVmR5guax@r)T#JfN&; z4UuC%DKQ<7B$(|2J9M#?28A2bH4-AHU_T*p(jkHM>Vb*jjZ?QyEl4-d-99&W>|sUq z*Y+(;{p#U6hZnz)Y0Fh?mn)!=@pz7~VBYblzUj^DU%j63WJWVz$c(;ImaFfU>$~TD zYu@_Br?TE1IM-@}nP#~*G=KbIp!UweJAD~`X-78j^!)?No0hAWtKUC_2krDdon?A87ShO zff)gx&I^&m0O)}=FMeI3F4E=ckIVaF_|I9i#R0aFfl*N1{6{yCk-M#hFEX;eOkmcB za=PxqZHWA@F9yR~xcT`xlQR$XxjL%inx?N&5BAzw>!K<~ALWHytqYv*APy z{}SbhL}tXTXah9OOnlykdj+e~+0q)I9!cy#jIL@{WoM>+;=NS$FSJaYNZ$6UMz@0QDk<<& zP=x^IO0uuAP5Hu?;LQ@E|FlJmkU;aEQcLsZG ztNLiBb{?Ql9-~is*uGmz1yjvaOUb8GUDZQw+uHyBVmfg4Z@$?7E)a=FYQnL@L7Orc4;M~+ z$WlJCroZ5DIiRvG3>J4`O_ietE2;E!UzKAY6!- zNgr7=#2n2IXzL4u#m{|6u^*X9N1Tr592w}#=z1Ttldj7H4+7sGRPT#~<)3HGC?0;u zQT#_NTvx;AO8t&nNIUKCybMEtqxSy(W!L*yj*Hv;U|WgfdB@`ZjO#Aa=^nerNAESN z_eH|$T1VAdB>_r&-9`61b}dEk?_0Vg?>MMN^q*wcM;?IN>#weRkO>wFTd=#;ab&H$ zV%{mICjf$LN0fMfLh1{Xu{B S`HLT%{K1#hh))g~YW{ye+rQTU diff --git a/venv/lib/python3.11/site-packages/setuptools/__pycache__/dist.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/__pycache__/dist.cpython-311.pyc deleted file mode 100755 index 3d7f3a37da8d8b4050ab81edf30bf2f45cab8555..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 63795 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 diff --git a/venv/lib/python3.11/site-packages/setuptools/__pycache__/extension.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/__pycache__/extension.cpython-311.pyc deleted file mode 100755 index 16550cb79aae7da854c0d183f1701ab874e16be2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6807 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 diff --git a/venv/lib/python3.11/site-packages/setuptools/__pycache__/glob.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/__pycache__/glob.cpython-311.pyc deleted file mode 100755 index 1b4eaded2ded7b6429da579eef1bf763655de54a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6564 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 P6P^IUl+eS(9`64D+t(}_ diff --git a/venv/lib/python3.11/site-packages/setuptools/__pycache__/launch.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/__pycache__/launch.cpython-311.pyc deleted file mode 100755 index 11c8b6bd1deeaa7a5e92eb01bdb51ac656688d03..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1530 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 diff --git a/venv/lib/python3.11/site-packages/setuptools/__pycache__/sandbox.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/__pycache__/sandbox.cpython-311.pyc deleted file mode 100755 index 6afd59f7ed8f4c0be4f51f02dd5b1cf031bc09d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27333 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 diff --git a/venv/lib/python3.11/site-packages/setuptools/__pycache__/unicode_utils.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/__pycache__/unicode_utils.cpython-311.pyc deleted file mode 100755 index 23539c1126df7eae30bcc926849af2e1e005cca9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1819 zcmb7E-D@0G6u);q_Io<{*mZ4fbwWPKLfRqb!Ae94BvmSGmC%O-B#b*Z$+WvO%e{A- zCf$Wa1ec<;h>#!%eUMm*zWONSKghy9ECYdp_~6?@5JK?5b7#Mju7aN3`n0tfp>KB7r-v!=g!KAcjLg>KI{*A_cX;-P<~X>6QTA)#0{>A zyKTEAN%<48Cb`0Ag%7P-R1K!El(-=8QcPm}c)}myE4VICedQ zJS>tNC$)+w5hr_-O#3ww7KW+S8p|k(|hTsZ&Yu;&@Z=;qNW0<$t_8arkbPa z-TANQ_gH;&yfHd{l<53VkM%JiSQL!A&`cz29{|guDPUPE+;tRC?U&?&CLL%`M1RyjnoDk6^Rgo=&hElrp|ZfuQ{7JVE&tF-OE~?Ghj(?U=koU8B>Z{Tezh z_YBKeFS$AHc&?Q+oi(N3RtM90Ym|y#5Wfew|AI diff --git a/venv/lib/python3.11/site-packages/setuptools/__pycache__/version.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/__pycache__/version.cpython-311.pyc deleted file mode 100755 index 39f26a9f7ae50ad82eb7e6524e8836eef92b46a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 437 zcmYL^ze~eF6vy8+(b{T2f=<>+hjwVMrK@z)!J>`Xaw~KRoxIb=zI(j;Jl>b@yPGLW7I@4bo;p*0e~Bguc@4{34v%1hiF(k4 z45WZS2PHBy^}_k>zwe}yNmDXW15SX*r{HZPFr}t+$6XpQgb}A9D#+hLd>v&O@dMYV zw8x@!;B*~2bP8LM;&v^~Ba8-~L0GhJ5nnTH=6iN4@NMcu=>hSWfL%>nqozff^N~SZ zA$WzQSg^XnZQ3WeuX_f?m(-$Fth+8A5NCjUb_=^>zfGNLsZznr_DRvzjjnDHhBxox z;@?#zcf8s;>r*r6k(#G)cky+0!^=WK2!(L)k>o;_P%c!<)8bq$zvn*H+Faztq%KYz kruP?sP;OH~_2_RlsSC4Q9LH>rJKrB3!*e<>%}`$Y0hLL6rT_o{ diff --git a/venv/lib/python3.11/site-packages/setuptools/__pycache__/wheel.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/__pycache__/wheel.cpython-311.pyc deleted file mode 100755 index ce17c4ed712e206bfa6dfaf15f8714704cf0b314..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15493 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 Hw&ni=KX3)X diff --git a/venv/lib/python3.11/site-packages/setuptools/__pycache__/windows_support.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/__pycache__/windows_support.cpython-311.pyc deleted file mode 100755 index f2a0e0d8256615c074f13812dcd7de723f74b36c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1434 zcmZWo&1)M+6rcUjM`T-SO;S{nTC0S#sG(YHmF9zBuq&Iob>(6^2z*i2+L0xBrPhQ(&{J+|e9I|sMwJqix0Kpj{aqaY&1TGJ)_tSp@)k~vba z&ceVXR*2OKf1->oOo#3;5#HUG|4ah0tXKE!DrsQ5;m|U%za~2*XFI-c@8Ra2?bWtz zzs;+pnaj@3+N{R$XTDS3b#^eb8RjjY6XG#@e~6>RTE0&x&-(3G(Yv10*mj-ygPD<+ zG`)8Au1Cs_$L2v8`Xx*zSr}LyfE32NRHM90P!p@k?o_qt!?Kf$HPPy3D2MP=|=nNUO_I6`iw2M%Ien z(M!>hb}mMitOz1huS&%=4-Fl4^bYD6$AIHxjOEbmnCxOldo0U*hmOJWreA-8N}*3e z2M=Nv&<5rfuVSlOb6woD9L{NNyT!3ZK(Q({4TKoCL~OWmrer+@%}r> z#iiwy)uqzH=H~j!;=RqK(pM|_{8B*}6muq!QIl z3Qc#vmESWn-b+}gW;!s_Ju}@;&ipp zGkxphCyBuNTxlOYzhd>w51+>__hOeH<$G6ep2ltkv0L3Q`xEg2(n3~0e(@LbGdYc? zf_SPIO$`h%DvuhGj6o*>mYOexl*%4fE;WWQ>kZ? diff --git a/venv/lib/python3.11/site-packages/setuptools/_deprecation_warning.py b/venv/lib/python3.11/site-packages/setuptools/_deprecation_warning.py deleted file mode 100755 index 086b64d..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_deprecation_warning.py +++ /dev/null @@ -1,7 +0,0 @@ -class SetuptoolsDeprecationWarning(Warning): - """ - Base class for warning deprecations in ``setuptools`` - - This class is not derived from ``DeprecationWarning``, and as such is - visible by default. - """ diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/__init__.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/__init__.py deleted file mode 100755 index 1a188c3..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -import sys -import importlib - -__version__, _, _ = sys.version.partition(' ') - - -try: - # Allow Debian and pkgsrc (only) to customize system - # behavior. Ref pypa/distutils#2 and pypa/distutils#16. - # This hook is deprecated and no other environments - # should use it. - importlib.import_module('_distutils_system_mod') -except ImportError: - pass diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/__init__.cpython-311.pyc deleted file mode 100755 index 3fc0e3f6aee47cdef24df68b76f665f9c01b1269..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 561 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 G!+!$>x#?2? diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/_functools.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/_functools.cpython-311.pyc deleted file mode 100755 index f2f1ceea7d6310b4ea1adcc9120bc363060b670c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 863 zcmZuv&1(}u6o0eH#(a`M3PMzzgOElrW2h&oIePGrg9<`D#5KD~x83Y6Gn3Yq2oVC> zi}avW^dh2F=|2;phq5QZled*1NKd}mq>IHqW`6VA_c`zFd@dBSfO7ci?bCrz}Nzzzv^v2X2Q7kJ_>-sOw4EF&xJ-soh1Dpk12_NqvJG zeQFEZ@?0w$1vi^b>T}zbZD~D`^cMOE(RR_k7^!P#cr8|yZ*^u;^ei7$V&-vb5IVMS z8Ta%G!fUbzLwJ_gU?(wz9=7#?+yxtk+DGydTQmXNB(1MdO9py$`5cY zC77_}z?Yuq2-Y@jAqUb{RArB}b$=^3w~2H1ExuieM^s;SJe;#=*5|e&-b6GI{*2&z zt~AMAJSv~xz41n$l-c_v!fbs>&1s&63CLeUzbOXcFAXwr%|KU4MNQ)wH1QmQP>=5s z diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/_log.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/_log.cpython-311.pyc deleted file mode 100755 index dbd3420ad0239d06c4de24236cfb7456201970ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 280 zcmZ3^%ge<81Xrfa%F+hXk3k$5V1hC}>i`+k8B!Qh7;_k+7?>DR8L}8*ik1Nxt6?05 zD5ey~U8P3BwdIr-`7nR)5AIMY*0e1PoKqFc;Bv6T#;K}vpw>SyHVrt0S= z7A5EFd*!F+8|x<)6zG?w=9TH^WG3ksRF-7q=Nao68tNBkmZa(yBqnDkrl%I`7pIn# z7L?@Y=M?M5r(_nFl$K$P>0Xeo<1xS2gW@Kc%!NAu5 dh9B4%*d-d$uds<NU;C_ diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/_macos_compat.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/_macos_compat.cpython-311.pyc deleted file mode 100755 index c04eba6faf2be67cd88aa4769d3c5e8b19689c9f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 572 zcmYjNyG|=H5FPI(Av^-yVnsni8w6O0h9cqvKuSY(w_s(~CT!S^E!zu3qDa99P#_`k z0l?M$89*r_S4dP;L`p}6olOv9`^*`8#>bw=T5S%j^>6RnpVq&-U~2w^jHo4dK!KtZ z!os5vQSTZ;k3oBy2h>0FT#a1ufT4D2QV+EBfB^p6Ram<`Wnr13LttLv>*Wu3(2U2o zOmbY6Qy5h&+`$zbLLD{#LESTcoKaIEvZa)(SX=u#!lyiAI3qIVc%QfU4kkk2bJjV> zX>yE3SD*6E&erxeR*7btg2ZQ}#S~Ud=R$LyDjd;7>0Bp{W+dh+ig_l8-V$9C9Crm# z#ZHnk8J#4TxsX+>?*61^Ec9S7zu4O!Sqi2?iM&WUW+CG0GE%t^T!Hn(Y@f8p6jffb>IZQs*NIVPyVr?YnTcx41I*q0Ooq* zF@WXg=^R!NS{lL+RG~C;-MHC(^;e($)j_av^S2*tJRQ9RjlP=)y`~#)!FoZ)+TXIE BmQDZw diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/_msvccompiler.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/_msvccompiler.cpython-311.pyc deleted file mode 100755 index dc4af155a1357adb88f73a1a8e084f74445a28a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25074 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 ..." % action - ) - dir = convert_path(words[1]) - patterns = [convert_path(w) for w in words[2:]] - elif action in ('graft', 'prune'): - if len(words) != 2: - raise DistutilsTemplateError( - "'%s' expects a single " % action - ) - dir_pattern = convert_path(words[1]) - else: - raise DistutilsTemplateError("unknown action '%s'" % action) - - return (action, patterns, dir, dir_pattern) - - def process_template_line(self, line): # noqa: C901 - # Parse the line: split it up, make sure the right number of words - # is there, and return the relevant words. 'action' is always - # defined: it's the first word of the line. Which of the other - # three are defined depends on the action; it'll be either - # patterns, (dir and patterns), or (dir_pattern). - (action, patterns, dir, dir_pattern) = self._parse_template_line(line) - - # OK, now we know that the action is valid and we have the - # right number of words on the line for that action -- so we - # can proceed with minimal error-checking. - if action == 'include': - self.debug_print("include " + ' '.join(patterns)) - for pattern in patterns: - if not self.include_pattern(pattern, anchor=1): - log.warning("warning: no files found matching '%s'", pattern) - - elif action == 'exclude': - self.debug_print("exclude " + ' '.join(patterns)) - for pattern in patterns: - if not self.exclude_pattern(pattern, anchor=1): - log.warning( - ( - "warning: no previously-included files " - "found matching '%s'" - ), - pattern, - ) - - elif action == 'global-include': - self.debug_print("global-include " + ' '.join(patterns)) - for pattern in patterns: - if not self.include_pattern(pattern, anchor=0): - log.warning( - ( - "warning: no files found matching '%s' " - "anywhere in distribution" - ), - pattern, - ) - - elif action == 'global-exclude': - self.debug_print("global-exclude " + ' '.join(patterns)) - for pattern in patterns: - if not self.exclude_pattern(pattern, anchor=0): - log.warning( - ( - "warning: no previously-included files matching " - "'%s' found anywhere in distribution" - ), - pattern, - ) - - elif action == 'recursive-include': - self.debug_print("recursive-include {} {}".format(dir, ' '.join(patterns))) - for pattern in patterns: - if not self.include_pattern(pattern, prefix=dir): - msg = ( - "warning: no files found matching '%s' " "under directory '%s'" - ) - log.warning(msg, pattern, dir) - - elif action == 'recursive-exclude': - self.debug_print("recursive-exclude {} {}".format(dir, ' '.join(patterns))) - for pattern in patterns: - if not self.exclude_pattern(pattern, prefix=dir): - log.warning( - ( - "warning: no previously-included files matching " - "'%s' found under directory '%s'" - ), - pattern, - dir, - ) - - elif action == 'graft': - self.debug_print("graft " + dir_pattern) - if not self.include_pattern(None, prefix=dir_pattern): - log.warning("warning: no directories found matching '%s'", dir_pattern) - - elif action == 'prune': - self.debug_print("prune " + dir_pattern) - if not self.exclude_pattern(None, prefix=dir_pattern): - log.warning( - ("no previously-included directories found " "matching '%s'"), - dir_pattern, - ) - else: - raise DistutilsInternalError( - "this cannot happen: invalid action '%s'" % action - ) - - # Filtering/selection methods - - def include_pattern(self, pattern, anchor=1, prefix=None, is_regex=0): - """Select strings (presumably filenames) from 'self.files' that - match 'pattern', a Unix-style wildcard (glob) pattern. Patterns - are not quite the same as implemented by the 'fnmatch' module: '*' - and '?' match non-special characters, where "special" is platform- - dependent: slash on Unix; colon, slash, and backslash on - DOS/Windows; and colon on Mac OS. - - If 'anchor' is true (the default), then the pattern match is more - stringent: "*.py" will match "foo.py" but not "foo/bar.py". If - 'anchor' is false, both of these will match. - - If 'prefix' is supplied, then only filenames starting with 'prefix' - (itself a pattern) and ending with 'pattern', with anything in between - them, will match. 'anchor' is ignored in this case. - - If 'is_regex' is true, 'anchor' and 'prefix' are ignored, and - 'pattern' is assumed to be either a string containing a regex or a - regex object -- no translation is done, the regex is just compiled - and used as-is. - - Selected strings will be added to self.files. - - Return True if files are found, False otherwise. - """ - # XXX docstring lying about what the special chars are? - files_found = False - pattern_re = translate_pattern(pattern, anchor, prefix, is_regex) - self.debug_print("include_pattern: applying regex r'%s'" % pattern_re.pattern) - - # delayed loading of allfiles list - if self.allfiles is None: - self.findall() - - for name in self.allfiles: - if pattern_re.search(name): - self.debug_print(" adding " + name) - self.files.append(name) - files_found = True - return files_found - - def exclude_pattern(self, pattern, anchor=1, prefix=None, is_regex=0): - """Remove strings (presumably filenames) from 'files' that match - 'pattern'. Other parameters are the same as for - 'include_pattern()', above. - The list 'self.files' is modified in place. - Return True if files are found, False otherwise. - """ - files_found = False - pattern_re = translate_pattern(pattern, anchor, prefix, is_regex) - self.debug_print("exclude_pattern: applying regex r'%s'" % pattern_re.pattern) - for i in range(len(self.files) - 1, -1, -1): - if pattern_re.search(self.files[i]): - self.debug_print(" removing " + self.files[i]) - del self.files[i] - files_found = True - return files_found - - -# Utility functions - - -def _find_all_simple(path): - """ - Find all files under 'path' - """ - all_unique = _UniqueDirs.filter(os.walk(path, followlinks=True)) - results = ( - os.path.join(base, file) for base, dirs, files in all_unique for file in files - ) - return filter(os.path.isfile, results) - - -class _UniqueDirs(set): - """ - Exclude previously-seen dirs from walk results, - avoiding infinite recursion. - Ref https://bugs.python.org/issue44497. - """ - - def __call__(self, walk_item): - """ - Given an item from an os.walk result, determine - if the item represents a unique dir for this instance - and if not, prevent further traversal. - """ - base, dirs, files = walk_item - stat = os.stat(base) - candidate = stat.st_dev, stat.st_ino - found = candidate in self - if found: - del dirs[:] - self.add(candidate) - return not found - - @classmethod - def filter(cls, items): - return filter(cls(), items) - - -def findall(dir=os.curdir): - """ - Find all files under 'dir' and return the list of full filenames. - Unless dir is '.', return full filenames with dir prepended. - """ - files = _find_all_simple(dir) - if dir == os.curdir: - make_rel = functools.partial(os.path.relpath, start=dir) - files = map(make_rel, files) - return list(files) - - -def glob_to_re(pattern): - """Translate a shell-like glob pattern to a regular expression; return - a string containing the regex. Differs from 'fnmatch.translate()' in - that '*' does not match "special characters" (which are - platform-specific). - """ - pattern_re = fnmatch.translate(pattern) - - # '?' and '*' in the glob pattern become '.' and '.*' in the RE, which - # IMHO is wrong -- '?' and '*' aren't supposed to match slash in Unix, - # and by extension they shouldn't match such "special characters" under - # any OS. So change all non-escaped dots in the RE to match any - # character except the special characters (currently: just os.sep). - sep = os.sep - if os.sep == '\\': - # we're using a regex to manipulate a regex, so we need - # to escape the backslash twice - sep = r'\\\\' - escaped = r'\1[^%s]' % sep - pattern_re = re.sub(r'((?= 2: - set_threshold(logging.DEBUG) - - -class Log(logging.Logger): - """distutils.log.Log is deprecated, please use an alternative from `logging`.""" - - def __init__(self, threshold=WARN): - warnings.warn(Log.__doc__) # avoid DeprecationWarning to ensure warn is shown - super().__init__(__name__, level=threshold) - - @property - def threshold(self): - return self.level - - @threshold.setter - def threshold(self, level): - self.setLevel(level) - - warn = logging.Logger.warning diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/msvc9compiler.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/msvc9compiler.py deleted file mode 100755 index a4714a5..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/msvc9compiler.py +++ /dev/null @@ -1,832 +0,0 @@ -"""distutils.msvc9compiler - -Contains MSVCCompiler, an implementation of the abstract CCompiler class -for the Microsoft Visual Studio 2008. - -The module is compatible with VS 2005 and VS 2008. You can find legacy support -for older versions of VS in distutils.msvccompiler. -""" - -# Written by Perry Stoll -# hacked by Robin Becker and Thomas Heller to do a better job of -# finding DevStudio (through the registry) -# ported to VS2005 and VS 2008 by Christian Heimes - -import os -import subprocess -import sys -import re -import warnings - -from .errors import ( - DistutilsExecError, - DistutilsPlatformError, - CompileError, - LibError, - LinkError, -) -from .ccompiler import CCompiler, gen_lib_options -from ._log import log -from .util import get_platform - -import winreg - -warnings.warn( - "msvc9compiler is deprecated and slated to be removed " - "in the future. Please discontinue use or file an issue " - "with pypa/distutils describing your use case.", - DeprecationWarning, -) - -RegOpenKeyEx = winreg.OpenKeyEx -RegEnumKey = winreg.EnumKey -RegEnumValue = winreg.EnumValue -RegError = winreg.error - -HKEYS = ( - winreg.HKEY_USERS, - winreg.HKEY_CURRENT_USER, - winreg.HKEY_LOCAL_MACHINE, - winreg.HKEY_CLASSES_ROOT, -) - -NATIVE_WIN64 = sys.platform == 'win32' and sys.maxsize > 2**32 -if NATIVE_WIN64: - # Visual C++ is a 32-bit application, so we need to look in - # the corresponding registry branch, if we're running a - # 64-bit Python on Win64 - VS_BASE = r"Software\Wow6432Node\Microsoft\VisualStudio\%0.1f" - WINSDK_BASE = r"Software\Wow6432Node\Microsoft\Microsoft SDKs\Windows" - NET_BASE = r"Software\Wow6432Node\Microsoft\.NETFramework" -else: - VS_BASE = r"Software\Microsoft\VisualStudio\%0.1f" - WINSDK_BASE = r"Software\Microsoft\Microsoft SDKs\Windows" - NET_BASE = r"Software\Microsoft\.NETFramework" - -# A map keyed by get_platform() return values to values accepted by -# 'vcvarsall.bat'. Note a cross-compile may combine these (eg, 'x86_amd64' is -# the param to cross-compile on x86 targeting amd64.) -PLAT_TO_VCVARS = { - 'win32': 'x86', - 'win-amd64': 'amd64', -} - - -class Reg: - """Helper class to read values from the registry""" - - def get_value(cls, path, key): - for base in HKEYS: - d = cls.read_values(base, path) - if d and key in d: - return d[key] - raise KeyError(key) - - get_value = classmethod(get_value) - - def read_keys(cls, base, key): - """Return list of registry keys.""" - try: - handle = RegOpenKeyEx(base, key) - except RegError: - return None - L = [] - i = 0 - while True: - try: - k = RegEnumKey(handle, i) - except RegError: - break - L.append(k) - i += 1 - return L - - read_keys = classmethod(read_keys) - - def read_values(cls, base, key): - """Return dict of registry keys and values. - - All names are converted to lowercase. - """ - try: - handle = RegOpenKeyEx(base, key) - except RegError: - return None - d = {} - i = 0 - while True: - try: - name, value, type = RegEnumValue(handle, i) - except RegError: - break - name = name.lower() - d[cls.convert_mbcs(name)] = cls.convert_mbcs(value) - i += 1 - return d - - read_values = classmethod(read_values) - - def convert_mbcs(s): - dec = getattr(s, "decode", None) - if dec is not None: - try: - s = dec("mbcs") - except UnicodeError: - pass - return s - - convert_mbcs = staticmethod(convert_mbcs) - - -class MacroExpander: - def __init__(self, version): - self.macros = {} - self.vsbase = VS_BASE % version - self.load_macros(version) - - def set_macro(self, macro, path, key): - self.macros["$(%s)" % macro] = Reg.get_value(path, key) - - def load_macros(self, version): - self.set_macro("VCInstallDir", self.vsbase + r"\Setup\VC", "productdir") - self.set_macro("VSInstallDir", self.vsbase + r"\Setup\VS", "productdir") - self.set_macro("FrameworkDir", NET_BASE, "installroot") - try: - if version >= 8.0: - self.set_macro("FrameworkSDKDir", NET_BASE, "sdkinstallrootv2.0") - else: - raise KeyError("sdkinstallrootv2.0") - except KeyError: - raise DistutilsPlatformError( - """Python was built with Visual Studio 2008; -extensions must be built with a compiler than can generate compatible binaries. -Visual Studio 2008 was not found on this system. If you have Cygwin installed, -you can try compiling with MingW32, by passing "-c mingw32" to setup.py.""" - ) - - if version >= 9.0: - self.set_macro("FrameworkVersion", self.vsbase, "clr version") - self.set_macro("WindowsSdkDir", WINSDK_BASE, "currentinstallfolder") - else: - p = r"Software\Microsoft\NET Framework Setup\Product" - for base in HKEYS: - try: - h = RegOpenKeyEx(base, p) - except RegError: - continue - key = RegEnumKey(h, 0) - d = Reg.get_value(base, r"{}\{}".format(p, key)) - self.macros["$(FrameworkVersion)"] = d["version"] - - def sub(self, s): - for k, v in self.macros.items(): - s = s.replace(k, v) - return s - - -def get_build_version(): - """Return the version of MSVC that was used to build Python. - - For Python 2.3 and up, the version number is included in - sys.version. For earlier versions, assume the compiler is MSVC 6. - """ - prefix = "MSC v." - i = sys.version.find(prefix) - if i == -1: - return 6 - i = i + len(prefix) - s, rest = sys.version[i:].split(" ", 1) - majorVersion = int(s[:-2]) - 6 - if majorVersion >= 13: - # v13 was skipped and should be v14 - majorVersion += 1 - minorVersion = int(s[2:3]) / 10.0 - # I don't think paths are affected by minor version in version 6 - if majorVersion == 6: - minorVersion = 0 - if majorVersion >= 6: - return majorVersion + minorVersion - # else we don't know what version of the compiler this is - return None - - -def normalize_and_reduce_paths(paths): - """Return a list of normalized paths with duplicates removed. - - The current order of paths is maintained. - """ - # Paths are normalized so things like: /a and /a/ aren't both preserved. - reduced_paths = [] - for p in paths: - np = os.path.normpath(p) - # XXX(nnorwitz): O(n**2), if reduced_paths gets long perhaps use a set. - if np not in reduced_paths: - reduced_paths.append(np) - return reduced_paths - - -def removeDuplicates(variable): - """Remove duplicate values of an environment variable.""" - oldList = variable.split(os.pathsep) - newList = [] - for i in oldList: - if i not in newList: - newList.append(i) - newVariable = os.pathsep.join(newList) - return newVariable - - -def find_vcvarsall(version): - """Find the vcvarsall.bat file - - At first it tries to find the productdir of VS 2008 in the registry. If - that fails it falls back to the VS90COMNTOOLS env var. - """ - vsbase = VS_BASE % version - try: - productdir = Reg.get_value(r"%s\Setup\VC" % vsbase, "productdir") - except KeyError: - log.debug("Unable to find productdir in registry") - productdir = None - - if not productdir or not os.path.isdir(productdir): - toolskey = "VS%0.f0COMNTOOLS" % version - toolsdir = os.environ.get(toolskey, None) - - if toolsdir and os.path.isdir(toolsdir): - productdir = os.path.join(toolsdir, os.pardir, os.pardir, "VC") - productdir = os.path.abspath(productdir) - if not os.path.isdir(productdir): - log.debug("%s is not a valid directory" % productdir) - return None - else: - log.debug("Env var %s is not set or invalid" % toolskey) - if not productdir: - log.debug("No productdir found") - return None - vcvarsall = os.path.join(productdir, "vcvarsall.bat") - if os.path.isfile(vcvarsall): - return vcvarsall - log.debug("Unable to find vcvarsall.bat") - return None - - -def query_vcvarsall(version, arch="x86"): - """Launch vcvarsall.bat and read the settings from its environment""" - vcvarsall = find_vcvarsall(version) - interesting = {"include", "lib", "libpath", "path"} - result = {} - - if vcvarsall is None: - raise DistutilsPlatformError("Unable to find vcvarsall.bat") - log.debug("Calling 'vcvarsall.bat %s' (version=%s)", arch, version) - popen = subprocess.Popen( - '"{}" {} & set'.format(vcvarsall, arch), - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - ) - try: - stdout, stderr = popen.communicate() - if popen.wait() != 0: - raise DistutilsPlatformError(stderr.decode("mbcs")) - - stdout = stdout.decode("mbcs") - for line in stdout.split("\n"): - line = Reg.convert_mbcs(line) - if '=' not in line: - continue - line = line.strip() - key, value = line.split('=', 1) - key = key.lower() - if key in interesting: - if value.endswith(os.pathsep): - value = value[:-1] - result[key] = removeDuplicates(value) - - finally: - popen.stdout.close() - popen.stderr.close() - - if len(result) != len(interesting): - raise ValueError(str(list(result.keys()))) - - return result - - -# More globals -VERSION = get_build_version() -# MACROS = MacroExpander(VERSION) - - -class MSVCCompiler(CCompiler): - """Concrete class that implements an interface to Microsoft Visual C++, - as defined by the CCompiler abstract class.""" - - compiler_type = 'msvc' - - # Just set this so CCompiler's constructor doesn't barf. We currently - # don't use the 'set_executables()' bureaucracy provided by CCompiler, - # as it really isn't necessary for this sort of single-compiler class. - # Would be nice to have a consistent interface with UnixCCompiler, - # though, so it's worth thinking about. - executables = {} - - # Private class data (need to distinguish C from C++ source for compiler) - _c_extensions = ['.c'] - _cpp_extensions = ['.cc', '.cpp', '.cxx'] - _rc_extensions = ['.rc'] - _mc_extensions = ['.mc'] - - # Needed for the filename generation methods provided by the - # base class, CCompiler. - src_extensions = _c_extensions + _cpp_extensions + _rc_extensions + _mc_extensions - res_extension = '.res' - obj_extension = '.obj' - static_lib_extension = '.lib' - shared_lib_extension = '.dll' - static_lib_format = shared_lib_format = '%s%s' - exe_extension = '.exe' - - def __init__(self, verbose=0, dry_run=0, force=0): - super().__init__(verbose, dry_run, force) - self.__version = VERSION - self.__root = r"Software\Microsoft\VisualStudio" - # self.__macros = MACROS - self.__paths = [] - # target platform (.plat_name is consistent with 'bdist') - self.plat_name = None - self.__arch = None # deprecated name - self.initialized = False - - def initialize(self, plat_name=None): # noqa: C901 - # multi-init means we would need to check platform same each time... - assert not self.initialized, "don't init multiple times" - if self.__version < 8.0: - raise DistutilsPlatformError( - "VC %0.1f is not supported by this module" % self.__version - ) - if plat_name is None: - plat_name = get_platform() - # sanity check for platforms to prevent obscure errors later. - ok_plats = 'win32', 'win-amd64' - if plat_name not in ok_plats: - raise DistutilsPlatformError( - "--plat-name must be one of {}".format(ok_plats) - ) - - if ( - "DISTUTILS_USE_SDK" in os.environ - and "MSSdk" in os.environ - and self.find_exe("cl.exe") - ): - # Assume that the SDK set up everything alright; don't try to be - # smarter - self.cc = "cl.exe" - self.linker = "link.exe" - self.lib = "lib.exe" - self.rc = "rc.exe" - self.mc = "mc.exe" - else: - # On x86, 'vcvars32.bat amd64' creates an env that doesn't work; - # to cross compile, you use 'x86_amd64'. - # On AMD64, 'vcvars32.bat amd64' is a native build env; to cross - # compile use 'x86' (ie, it runs the x86 compiler directly) - if plat_name == get_platform() or plat_name == 'win32': - # native build or cross-compile to win32 - plat_spec = PLAT_TO_VCVARS[plat_name] - else: - # cross compile from win32 -> some 64bit - plat_spec = ( - PLAT_TO_VCVARS[get_platform()] + '_' + PLAT_TO_VCVARS[plat_name] - ) - - vc_env = query_vcvarsall(VERSION, plat_spec) - - self.__paths = vc_env['path'].split(os.pathsep) - os.environ['lib'] = vc_env['lib'] - os.environ['include'] = vc_env['include'] - - if len(self.__paths) == 0: - raise DistutilsPlatformError( - "Python was built with %s, " - "and extensions need to be built with the same " - "version of the compiler, but it isn't installed." % self.__product - ) - - self.cc = self.find_exe("cl.exe") - self.linker = self.find_exe("link.exe") - self.lib = self.find_exe("lib.exe") - self.rc = self.find_exe("rc.exe") # resource compiler - self.mc = self.find_exe("mc.exe") # message compiler - # self.set_path_env_var('lib') - # self.set_path_env_var('include') - - # extend the MSVC path with the current path - try: - for p in os.environ['path'].split(';'): - self.__paths.append(p) - except KeyError: - pass - self.__paths = normalize_and_reduce_paths(self.__paths) - os.environ['path'] = ";".join(self.__paths) - - self.preprocess_options = None - if self.__arch == "x86": - self.compile_options = ['/nologo', '/O2', '/MD', '/W3', '/DNDEBUG'] - self.compile_options_debug = [ - '/nologo', - '/Od', - '/MDd', - '/W3', - '/Z7', - '/D_DEBUG', - ] - else: - # Win64 - self.compile_options = ['/nologo', '/O2', '/MD', '/W3', '/GS-', '/DNDEBUG'] - self.compile_options_debug = [ - '/nologo', - '/Od', - '/MDd', - '/W3', - '/GS-', - '/Z7', - '/D_DEBUG', - ] - - self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO'] - if self.__version >= 7: - self.ldflags_shared_debug = ['/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG'] - self.ldflags_static = ['/nologo'] - - self.initialized = True - - # -- Worker methods ------------------------------------------------ - - def object_filenames(self, source_filenames, strip_dir=0, output_dir=''): - # Copied from ccompiler.py, extended to return .res as 'object'-file - # for .rc input file - if output_dir is None: - output_dir = '' - obj_names = [] - for src_name in source_filenames: - (base, ext) = os.path.splitext(src_name) - base = os.path.splitdrive(base)[1] # Chop off the drive - base = base[os.path.isabs(base) :] # If abs, chop off leading / - if ext not in self.src_extensions: - # Better to raise an exception instead of silently continuing - # and later complain about sources and targets having - # different lengths - raise CompileError("Don't know how to compile %s" % src_name) - if strip_dir: - base = os.path.basename(base) - if ext in self._rc_extensions: - obj_names.append(os.path.join(output_dir, base + self.res_extension)) - elif ext in self._mc_extensions: - obj_names.append(os.path.join(output_dir, base + self.res_extension)) - else: - obj_names.append(os.path.join(output_dir, base + self.obj_extension)) - return obj_names - - def compile( # noqa: C901 - self, - sources, - output_dir=None, - macros=None, - include_dirs=None, - debug=0, - extra_preargs=None, - extra_postargs=None, - depends=None, - ): - - if not self.initialized: - self.initialize() - compile_info = self._setup_compile( - output_dir, macros, include_dirs, sources, depends, extra_postargs - ) - macros, objects, extra_postargs, pp_opts, build = compile_info - - compile_opts = extra_preargs or [] - compile_opts.append('/c') - if debug: - compile_opts.extend(self.compile_options_debug) - else: - compile_opts.extend(self.compile_options) - - for obj in objects: - try: - src, ext = build[obj] - except KeyError: - continue - if debug: - # pass the full pathname to MSVC in debug mode, - # this allows the debugger to find the source file - # without asking the user to browse for it - src = os.path.abspath(src) - - if ext in self._c_extensions: - input_opt = "/Tc" + src - elif ext in self._cpp_extensions: - input_opt = "/Tp" + src - elif ext in self._rc_extensions: - # compile .RC to .RES file - input_opt = src - output_opt = "/fo" + obj - try: - self.spawn([self.rc] + pp_opts + [output_opt] + [input_opt]) - except DistutilsExecError as msg: - raise CompileError(msg) - continue - elif ext in self._mc_extensions: - # Compile .MC to .RC file to .RES file. - # * '-h dir' specifies the directory for the - # generated include file - # * '-r dir' specifies the target directory of the - # generated RC file and the binary message resource - # it includes - # - # For now (since there are no options to change this), - # we use the source-directory for the include file and - # the build directory for the RC file and message - # resources. This works at least for win32all. - h_dir = os.path.dirname(src) - rc_dir = os.path.dirname(obj) - try: - # first compile .MC to .RC and .H file - self.spawn([self.mc] + ['-h', h_dir, '-r', rc_dir] + [src]) - base, _ = os.path.splitext(os.path.basename(src)) - rc_file = os.path.join(rc_dir, base + '.rc') - # then compile .RC to .RES file - self.spawn([self.rc] + ["/fo" + obj] + [rc_file]) - - except DistutilsExecError as msg: - raise CompileError(msg) - continue - else: - # how to handle this file? - raise CompileError( - "Don't know how to compile {} to {}".format(src, obj) - ) - - output_opt = "/Fo" + obj - try: - self.spawn( - [self.cc] - + compile_opts - + pp_opts - + [input_opt, output_opt] - + extra_postargs - ) - except DistutilsExecError as msg: - raise CompileError(msg) - - return objects - - def create_static_lib( - self, objects, output_libname, output_dir=None, debug=0, target_lang=None - ): - - if not self.initialized: - self.initialize() - (objects, output_dir) = self._fix_object_args(objects, output_dir) - output_filename = self.library_filename(output_libname, output_dir=output_dir) - - if self._need_link(objects, output_filename): - lib_args = objects + ['/OUT:' + output_filename] - if debug: - pass # XXX what goes here? - try: - self.spawn([self.lib] + lib_args) - except DistutilsExecError as msg: - raise LibError(msg) - else: - log.debug("skipping %s (up-to-date)", output_filename) - - def link( # noqa: C901 - self, - target_desc, - objects, - output_filename, - output_dir=None, - libraries=None, - library_dirs=None, - runtime_library_dirs=None, - export_symbols=None, - debug=0, - extra_preargs=None, - extra_postargs=None, - build_temp=None, - target_lang=None, - ): - - if not self.initialized: - self.initialize() - (objects, output_dir) = self._fix_object_args(objects, output_dir) - fixed_args = self._fix_lib_args(libraries, library_dirs, runtime_library_dirs) - (libraries, library_dirs, runtime_library_dirs) = fixed_args - - if runtime_library_dirs: - self.warn( - "I don't know what to do with 'runtime_library_dirs': " - + str(runtime_library_dirs) - ) - - lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, libraries) - if output_dir is not None: - output_filename = os.path.join(output_dir, output_filename) - - if self._need_link(objects, output_filename): - if target_desc == CCompiler.EXECUTABLE: - if debug: - ldflags = self.ldflags_shared_debug[1:] - else: - ldflags = self.ldflags_shared[1:] - else: - if debug: - ldflags = self.ldflags_shared_debug - else: - ldflags = self.ldflags_shared - - export_opts = [] - for sym in export_symbols or []: - export_opts.append("/EXPORT:" + sym) - - ld_args = ( - ldflags + lib_opts + export_opts + objects + ['/OUT:' + output_filename] - ) - - # The MSVC linker generates .lib and .exp files, which cannot be - # suppressed by any linker switches. The .lib files may even be - # needed! Make sure they are generated in the temporary build - # directory. Since they have different names for debug and release - # builds, they can go into the same directory. - build_temp = os.path.dirname(objects[0]) - if export_symbols is not None: - (dll_name, dll_ext) = os.path.splitext( - os.path.basename(output_filename) - ) - implib_file = os.path.join(build_temp, self.library_filename(dll_name)) - ld_args.append('/IMPLIB:' + implib_file) - - self.manifest_setup_ldargs(output_filename, build_temp, ld_args) - - if extra_preargs: - ld_args[:0] = extra_preargs - if extra_postargs: - ld_args.extend(extra_postargs) - - self.mkpath(os.path.dirname(output_filename)) - try: - self.spawn([self.linker] + ld_args) - except DistutilsExecError as msg: - raise LinkError(msg) - - # embed the manifest - # XXX - this is somewhat fragile - if mt.exe fails, distutils - # will still consider the DLL up-to-date, but it will not have a - # manifest. Maybe we should link to a temp file? OTOH, that - # implies a build environment error that shouldn't go undetected. - mfinfo = self.manifest_get_embed_info(target_desc, ld_args) - if mfinfo is not None: - mffilename, mfid = mfinfo - out_arg = '-outputresource:{};{}'.format(output_filename, mfid) - try: - self.spawn(['mt.exe', '-nologo', '-manifest', mffilename, out_arg]) - except DistutilsExecError as msg: - raise LinkError(msg) - else: - log.debug("skipping %s (up-to-date)", output_filename) - - def manifest_setup_ldargs(self, output_filename, build_temp, ld_args): - # If we need a manifest at all, an embedded manifest is recommended. - # See MSDN article titled - # "How to: Embed a Manifest Inside a C/C++ Application" - # (currently at http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx) - # Ask the linker to generate the manifest in the temp dir, so - # we can check it, and possibly embed it, later. - temp_manifest = os.path.join( - build_temp, os.path.basename(output_filename) + ".manifest" - ) - ld_args.append('/MANIFESTFILE:' + temp_manifest) - - def manifest_get_embed_info(self, target_desc, ld_args): - # If a manifest should be embedded, return a tuple of - # (manifest_filename, resource_id). Returns None if no manifest - # should be embedded. See http://bugs.python.org/issue7833 for why - # we want to avoid any manifest for extension modules if we can) - for arg in ld_args: - if arg.startswith("/MANIFESTFILE:"): - temp_manifest = arg.split(":", 1)[1] - break - else: - # no /MANIFESTFILE so nothing to do. - return None - if target_desc == CCompiler.EXECUTABLE: - # by default, executables always get the manifest with the - # CRT referenced. - mfid = 1 - else: - # Extension modules try and avoid any manifest if possible. - mfid = 2 - temp_manifest = self._remove_visual_c_ref(temp_manifest) - if temp_manifest is None: - return None - return temp_manifest, mfid - - def _remove_visual_c_ref(self, manifest_file): - try: - # Remove references to the Visual C runtime, so they will - # fall through to the Visual C dependency of Python.exe. - # This way, when installed for a restricted user (e.g. - # runtimes are not in WinSxS folder, but in Python's own - # folder), the runtimes do not need to be in every folder - # with .pyd's. - # Returns either the filename of the modified manifest or - # None if no manifest should be embedded. - manifest_f = open(manifest_file) - try: - manifest_buf = manifest_f.read() - finally: - manifest_f.close() - pattern = re.compile( - r"""|)""", - re.DOTALL, - ) - manifest_buf = re.sub(pattern, "", manifest_buf) - pattern = r"\s*" - manifest_buf = re.sub(pattern, "", manifest_buf) - # Now see if any other assemblies are referenced - if not, we - # don't want a manifest embedded. - pattern = re.compile( - r"""|)""", - re.DOTALL, - ) - if re.search(pattern, manifest_buf) is None: - return None - - manifest_f = open(manifest_file, 'w') - try: - manifest_f.write(manifest_buf) - return manifest_file - finally: - manifest_f.close() - except OSError: - pass - - # -- Miscellaneous methods ----------------------------------------- - # These are all used by the 'gen_lib_options() function, in - # ccompiler.py. - - def library_dir_option(self, dir): - return "/LIBPATH:" + dir - - def runtime_library_dir_option(self, dir): - raise DistutilsPlatformError( - "don't know how to set runtime library search path for MSVC++" - ) - - def library_option(self, lib): - return self.library_filename(lib) - - def find_library_file(self, dirs, lib, debug=0): - # Prefer a debugging library if found (and requested), but deal - # with it if we don't have one. - if debug: - try_names = [lib + "_d", lib] - else: - try_names = [lib] - for dir in dirs: - for name in try_names: - libfile = os.path.join(dir, self.library_filename(name)) - if os.path.exists(libfile): - return libfile - else: - # Oops, didn't find it in *any* of 'dirs' - return None - - # Helper methods for using the MSVC registry settings - - def find_exe(self, exe): - """Return path to an MSVC executable program. - - Tries to find the program in several places: first, one of the - MSVC program search paths from the registry; next, the directories - in the PATH environment variable. If any of those work, return an - absolute path that is known to exist. If none of them work, just - return the original program name, 'exe'. - """ - for p in self.__paths: - fn = os.path.join(os.path.abspath(p), exe) - if os.path.isfile(fn): - return fn - - # didn't find it; try existing path - for p in os.environ['Path'].split(';'): - fn = os.path.join(os.path.abspath(p), exe) - if os.path.isfile(fn): - return fn - - return exe diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/msvccompiler.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/msvccompiler.py deleted file mode 100755 index 59ebe99..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/msvccompiler.py +++ /dev/null @@ -1,695 +0,0 @@ -"""distutils.msvccompiler - -Contains MSVCCompiler, an implementation of the abstract CCompiler class -for the Microsoft Visual Studio. -""" - -# Written by Perry Stoll -# hacked by Robin Becker and Thomas Heller to do a better job of -# finding DevStudio (through the registry) - -import sys -import os -import warnings -from .errors import ( - DistutilsExecError, - DistutilsPlatformError, - CompileError, - LibError, - LinkError, -) -from .ccompiler import CCompiler, gen_lib_options -from ._log import log - -_can_read_reg = False -try: - import winreg - - _can_read_reg = True - hkey_mod = winreg - - RegOpenKeyEx = winreg.OpenKeyEx - RegEnumKey = winreg.EnumKey - RegEnumValue = winreg.EnumValue - RegError = winreg.error - -except ImportError: - try: - import win32api - import win32con - - _can_read_reg = True - hkey_mod = win32con - - RegOpenKeyEx = win32api.RegOpenKeyEx - RegEnumKey = win32api.RegEnumKey - RegEnumValue = win32api.RegEnumValue - RegError = win32api.error - except ImportError: - log.info( - "Warning: Can't read registry to find the " - "necessary compiler setting\n" - "Make sure that Python modules winreg, " - "win32api or win32con are installed." - ) - pass - -if _can_read_reg: - HKEYS = ( - hkey_mod.HKEY_USERS, - hkey_mod.HKEY_CURRENT_USER, - hkey_mod.HKEY_LOCAL_MACHINE, - hkey_mod.HKEY_CLASSES_ROOT, - ) - - -warnings.warn( - "msvccompiler is deprecated and slated to be removed " - "in the future. Please discontinue use or file an issue " - "with pypa/distutils describing your use case.", - DeprecationWarning, -) - - -def read_keys(base, key): - """Return list of registry keys.""" - try: - handle = RegOpenKeyEx(base, key) - except RegError: - return None - L = [] - i = 0 - while True: - try: - k = RegEnumKey(handle, i) - except RegError: - break - L.append(k) - i += 1 - return L - - -def read_values(base, key): - """Return dict of registry keys and values. - - All names are converted to lowercase. - """ - try: - handle = RegOpenKeyEx(base, key) - except RegError: - return None - d = {} - i = 0 - while True: - try: - name, value, type = RegEnumValue(handle, i) - except RegError: - break - name = name.lower() - d[convert_mbcs(name)] = convert_mbcs(value) - i += 1 - return d - - -def convert_mbcs(s): - dec = getattr(s, "decode", None) - if dec is not None: - try: - s = dec("mbcs") - except UnicodeError: - pass - return s - - -class MacroExpander: - def __init__(self, version): - self.macros = {} - self.load_macros(version) - - def set_macro(self, macro, path, key): - for base in HKEYS: - d = read_values(base, path) - if d: - self.macros["$(%s)" % macro] = d[key] - break - - def load_macros(self, version): - vsbase = r"Software\Microsoft\VisualStudio\%0.1f" % version - self.set_macro("VCInstallDir", vsbase + r"\Setup\VC", "productdir") - self.set_macro("VSInstallDir", vsbase + r"\Setup\VS", "productdir") - net = r"Software\Microsoft\.NETFramework" - self.set_macro("FrameworkDir", net, "installroot") - try: - if version > 7.0: - self.set_macro("FrameworkSDKDir", net, "sdkinstallrootv1.1") - else: - self.set_macro("FrameworkSDKDir", net, "sdkinstallroot") - except KeyError: - raise DistutilsPlatformError( - """Python was built with Visual Studio 2003; -extensions must be built with a compiler than can generate compatible binaries. -Visual Studio 2003 was not found on this system. If you have Cygwin installed, -you can try compiling with MingW32, by passing "-c mingw32" to setup.py.""" - ) - - p = r"Software\Microsoft\NET Framework Setup\Product" - for base in HKEYS: - try: - h = RegOpenKeyEx(base, p) - except RegError: - continue - key = RegEnumKey(h, 0) - d = read_values(base, r"{}\{}".format(p, key)) - self.macros["$(FrameworkVersion)"] = d["version"] - - def sub(self, s): - for k, v in self.macros.items(): - s = s.replace(k, v) - return s - - -def get_build_version(): - """Return the version of MSVC that was used to build Python. - - For Python 2.3 and up, the version number is included in - sys.version. For earlier versions, assume the compiler is MSVC 6. - """ - prefix = "MSC v." - i = sys.version.find(prefix) - if i == -1: - return 6 - i = i + len(prefix) - s, rest = sys.version[i:].split(" ", 1) - majorVersion = int(s[:-2]) - 6 - if majorVersion >= 13: - # v13 was skipped and should be v14 - majorVersion += 1 - minorVersion = int(s[2:3]) / 10.0 - # I don't think paths are affected by minor version in version 6 - if majorVersion == 6: - minorVersion = 0 - if majorVersion >= 6: - return majorVersion + minorVersion - # else we don't know what version of the compiler this is - return None - - -def get_build_architecture(): - """Return the processor architecture. - - Possible results are "Intel" or "AMD64". - """ - - prefix = " bit (" - i = sys.version.find(prefix) - if i == -1: - return "Intel" - j = sys.version.find(")", i) - return sys.version[i + len(prefix) : j] - - -def normalize_and_reduce_paths(paths): - """Return a list of normalized paths with duplicates removed. - - The current order of paths is maintained. - """ - # Paths are normalized so things like: /a and /a/ aren't both preserved. - reduced_paths = [] - for p in paths: - np = os.path.normpath(p) - # XXX(nnorwitz): O(n**2), if reduced_paths gets long perhaps use a set. - if np not in reduced_paths: - reduced_paths.append(np) - return reduced_paths - - -class MSVCCompiler(CCompiler): - """Concrete class that implements an interface to Microsoft Visual C++, - as defined by the CCompiler abstract class.""" - - compiler_type = 'msvc' - - # Just set this so CCompiler's constructor doesn't barf. We currently - # don't use the 'set_executables()' bureaucracy provided by CCompiler, - # as it really isn't necessary for this sort of single-compiler class. - # Would be nice to have a consistent interface with UnixCCompiler, - # though, so it's worth thinking about. - executables = {} - - # Private class data (need to distinguish C from C++ source for compiler) - _c_extensions = ['.c'] - _cpp_extensions = ['.cc', '.cpp', '.cxx'] - _rc_extensions = ['.rc'] - _mc_extensions = ['.mc'] - - # Needed for the filename generation methods provided by the - # base class, CCompiler. - src_extensions = _c_extensions + _cpp_extensions + _rc_extensions + _mc_extensions - res_extension = '.res' - obj_extension = '.obj' - static_lib_extension = '.lib' - shared_lib_extension = '.dll' - static_lib_format = shared_lib_format = '%s%s' - exe_extension = '.exe' - - def __init__(self, verbose=0, dry_run=0, force=0): - super().__init__(verbose, dry_run, force) - self.__version = get_build_version() - self.__arch = get_build_architecture() - if self.__arch == "Intel": - # x86 - if self.__version >= 7: - self.__root = r"Software\Microsoft\VisualStudio" - self.__macros = MacroExpander(self.__version) - else: - self.__root = r"Software\Microsoft\Devstudio" - self.__product = "Visual Studio version %s" % self.__version - else: - # Win64. Assume this was built with the platform SDK - self.__product = "Microsoft SDK compiler %s" % (self.__version + 6) - - self.initialized = False - - def initialize(self): - self.__paths = [] - if ( - "DISTUTILS_USE_SDK" in os.environ - and "MSSdk" in os.environ - and self.find_exe("cl.exe") - ): - # Assume that the SDK set up everything alright; don't try to be - # smarter - self.cc = "cl.exe" - self.linker = "link.exe" - self.lib = "lib.exe" - self.rc = "rc.exe" - self.mc = "mc.exe" - else: - self.__paths = self.get_msvc_paths("path") - - if len(self.__paths) == 0: - raise DistutilsPlatformError( - "Python was built with %s, " - "and extensions need to be built with the same " - "version of the compiler, but it isn't installed." % self.__product - ) - - self.cc = self.find_exe("cl.exe") - self.linker = self.find_exe("link.exe") - self.lib = self.find_exe("lib.exe") - self.rc = self.find_exe("rc.exe") # resource compiler - self.mc = self.find_exe("mc.exe") # message compiler - self.set_path_env_var('lib') - self.set_path_env_var('include') - - # extend the MSVC path with the current path - try: - for p in os.environ['path'].split(';'): - self.__paths.append(p) - except KeyError: - pass - self.__paths = normalize_and_reduce_paths(self.__paths) - os.environ['path'] = ";".join(self.__paths) - - self.preprocess_options = None - if self.__arch == "Intel": - self.compile_options = ['/nologo', '/O2', '/MD', '/W3', '/GX', '/DNDEBUG'] - self.compile_options_debug = [ - '/nologo', - '/Od', - '/MDd', - '/W3', - '/GX', - '/Z7', - '/D_DEBUG', - ] - else: - # Win64 - self.compile_options = ['/nologo', '/O2', '/MD', '/W3', '/GS-', '/DNDEBUG'] - self.compile_options_debug = [ - '/nologo', - '/Od', - '/MDd', - '/W3', - '/GS-', - '/Z7', - '/D_DEBUG', - ] - - self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO'] - if self.__version >= 7: - self.ldflags_shared_debug = ['/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG'] - else: - self.ldflags_shared_debug = [ - '/DLL', - '/nologo', - '/INCREMENTAL:no', - '/pdb:None', - '/DEBUG', - ] - self.ldflags_static = ['/nologo'] - - self.initialized = True - - # -- Worker methods ------------------------------------------------ - - def object_filenames(self, source_filenames, strip_dir=0, output_dir=''): - # Copied from ccompiler.py, extended to return .res as 'object'-file - # for .rc input file - if output_dir is None: - output_dir = '' - obj_names = [] - for src_name in source_filenames: - (base, ext) = os.path.splitext(src_name) - base = os.path.splitdrive(base)[1] # Chop off the drive - base = base[os.path.isabs(base) :] # If abs, chop off leading / - if ext not in self.src_extensions: - # Better to raise an exception instead of silently continuing - # and later complain about sources and targets having - # different lengths - raise CompileError("Don't know how to compile %s" % src_name) - if strip_dir: - base = os.path.basename(base) - if ext in self._rc_extensions: - obj_names.append(os.path.join(output_dir, base + self.res_extension)) - elif ext in self._mc_extensions: - obj_names.append(os.path.join(output_dir, base + self.res_extension)) - else: - obj_names.append(os.path.join(output_dir, base + self.obj_extension)) - return obj_names - - def compile( # noqa: C901 - self, - sources, - output_dir=None, - macros=None, - include_dirs=None, - debug=0, - extra_preargs=None, - extra_postargs=None, - depends=None, - ): - - if not self.initialized: - self.initialize() - compile_info = self._setup_compile( - output_dir, macros, include_dirs, sources, depends, extra_postargs - ) - macros, objects, extra_postargs, pp_opts, build = compile_info - - compile_opts = extra_preargs or [] - compile_opts.append('/c') - if debug: - compile_opts.extend(self.compile_options_debug) - else: - compile_opts.extend(self.compile_options) - - for obj in objects: - try: - src, ext = build[obj] - except KeyError: - continue - if debug: - # pass the full pathname to MSVC in debug mode, - # this allows the debugger to find the source file - # without asking the user to browse for it - src = os.path.abspath(src) - - if ext in self._c_extensions: - input_opt = "/Tc" + src - elif ext in self._cpp_extensions: - input_opt = "/Tp" + src - elif ext in self._rc_extensions: - # compile .RC to .RES file - input_opt = src - output_opt = "/fo" + obj - try: - self.spawn([self.rc] + pp_opts + [output_opt] + [input_opt]) - except DistutilsExecError as msg: - raise CompileError(msg) - continue - elif ext in self._mc_extensions: - # Compile .MC to .RC file to .RES file. - # * '-h dir' specifies the directory for the - # generated include file - # * '-r dir' specifies the target directory of the - # generated RC file and the binary message resource - # it includes - # - # For now (since there are no options to change this), - # we use the source-directory for the include file and - # the build directory for the RC file and message - # resources. This works at least for win32all. - h_dir = os.path.dirname(src) - rc_dir = os.path.dirname(obj) - try: - # first compile .MC to .RC and .H file - self.spawn([self.mc] + ['-h', h_dir, '-r', rc_dir] + [src]) - base, _ = os.path.splitext(os.path.basename(src)) - rc_file = os.path.join(rc_dir, base + '.rc') - # then compile .RC to .RES file - self.spawn([self.rc] + ["/fo" + obj] + [rc_file]) - - except DistutilsExecError as msg: - raise CompileError(msg) - continue - else: - # how to handle this file? - raise CompileError( - "Don't know how to compile {} to {}".format(src, obj) - ) - - output_opt = "/Fo" + obj - try: - self.spawn( - [self.cc] - + compile_opts - + pp_opts - + [input_opt, output_opt] - + extra_postargs - ) - except DistutilsExecError as msg: - raise CompileError(msg) - - return objects - - def create_static_lib( - self, objects, output_libname, output_dir=None, debug=0, target_lang=None - ): - - if not self.initialized: - self.initialize() - (objects, output_dir) = self._fix_object_args(objects, output_dir) - output_filename = self.library_filename(output_libname, output_dir=output_dir) - - if self._need_link(objects, output_filename): - lib_args = objects + ['/OUT:' + output_filename] - if debug: - pass # XXX what goes here? - try: - self.spawn([self.lib] + lib_args) - except DistutilsExecError as msg: - raise LibError(msg) - else: - log.debug("skipping %s (up-to-date)", output_filename) - - def link( # noqa: C901 - self, - target_desc, - objects, - output_filename, - output_dir=None, - libraries=None, - library_dirs=None, - runtime_library_dirs=None, - export_symbols=None, - debug=0, - extra_preargs=None, - extra_postargs=None, - build_temp=None, - target_lang=None, - ): - - if not self.initialized: - self.initialize() - (objects, output_dir) = self._fix_object_args(objects, output_dir) - fixed_args = self._fix_lib_args(libraries, library_dirs, runtime_library_dirs) - (libraries, library_dirs, runtime_library_dirs) = fixed_args - - if runtime_library_dirs: - self.warn( - "I don't know what to do with 'runtime_library_dirs': " - + str(runtime_library_dirs) - ) - - lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, libraries) - if output_dir is not None: - output_filename = os.path.join(output_dir, output_filename) - - if self._need_link(objects, output_filename): - if target_desc == CCompiler.EXECUTABLE: - if debug: - ldflags = self.ldflags_shared_debug[1:] - else: - ldflags = self.ldflags_shared[1:] - else: - if debug: - ldflags = self.ldflags_shared_debug - else: - ldflags = self.ldflags_shared - - export_opts = [] - for sym in export_symbols or []: - export_opts.append("/EXPORT:" + sym) - - ld_args = ( - ldflags + lib_opts + export_opts + objects + ['/OUT:' + output_filename] - ) - - # The MSVC linker generates .lib and .exp files, which cannot be - # suppressed by any linker switches. The .lib files may even be - # needed! Make sure they are generated in the temporary build - # directory. Since they have different names for debug and release - # builds, they can go into the same directory. - if export_symbols is not None: - (dll_name, dll_ext) = os.path.splitext( - os.path.basename(output_filename) - ) - implib_file = os.path.join( - os.path.dirname(objects[0]), self.library_filename(dll_name) - ) - ld_args.append('/IMPLIB:' + implib_file) - - if extra_preargs: - ld_args[:0] = extra_preargs - if extra_postargs: - ld_args.extend(extra_postargs) - - self.mkpath(os.path.dirname(output_filename)) - try: - self.spawn([self.linker] + ld_args) - except DistutilsExecError as msg: - raise LinkError(msg) - - else: - log.debug("skipping %s (up-to-date)", output_filename) - - # -- Miscellaneous methods ----------------------------------------- - # These are all used by the 'gen_lib_options() function, in - # ccompiler.py. - - def library_dir_option(self, dir): - return "/LIBPATH:" + dir - - def runtime_library_dir_option(self, dir): - raise DistutilsPlatformError( - "don't know how to set runtime library search path for MSVC++" - ) - - def library_option(self, lib): - return self.library_filename(lib) - - def find_library_file(self, dirs, lib, debug=0): - # Prefer a debugging library if found (and requested), but deal - # with it if we don't have one. - if debug: - try_names = [lib + "_d", lib] - else: - try_names = [lib] - for dir in dirs: - for name in try_names: - libfile = os.path.join(dir, self.library_filename(name)) - if os.path.exists(libfile): - return libfile - else: - # Oops, didn't find it in *any* of 'dirs' - return None - - # Helper methods for using the MSVC registry settings - - def find_exe(self, exe): - """Return path to an MSVC executable program. - - Tries to find the program in several places: first, one of the - MSVC program search paths from the registry; next, the directories - in the PATH environment variable. If any of those work, return an - absolute path that is known to exist. If none of them work, just - return the original program name, 'exe'. - """ - for p in self.__paths: - fn = os.path.join(os.path.abspath(p), exe) - if os.path.isfile(fn): - return fn - - # didn't find it; try existing path - for p in os.environ['Path'].split(';'): - fn = os.path.join(os.path.abspath(p), exe) - if os.path.isfile(fn): - return fn - - return exe - - def get_msvc_paths(self, path, platform='x86'): - """Get a list of devstudio directories (include, lib or path). - - Return a list of strings. The list will be empty if unable to - access the registry or appropriate registry keys not found. - """ - if not _can_read_reg: - return [] - - path = path + " dirs" - if self.__version >= 7: - key = r"{}\{:0.1f}\VC\VC_OBJECTS_PLATFORM_INFO\Win32\Directories".format( - self.__root, - self.__version, - ) - else: - key = ( - r"%s\6.0\Build System\Components\Platforms" - r"\Win32 (%s)\Directories" % (self.__root, platform) - ) - - for base in HKEYS: - d = read_values(base, key) - if d: - if self.__version >= 7: - return self.__macros.sub(d[path]).split(";") - else: - return d[path].split(";") - # MSVC 6 seems to create the registry entries we need only when - # the GUI is run. - if self.__version == 6: - for base in HKEYS: - if read_values(base, r"%s\6.0" % self.__root) is not None: - self.warn( - "It seems you have Visual Studio 6 installed, " - "but the expected registry settings are not present.\n" - "You must at least run the Visual Studio GUI once " - "so that these entries are created." - ) - break - return [] - - def set_path_env_var(self, name): - """Set environment variable 'name' to an MSVC path type value. - - This is equivalent to a SET command prior to execution of spawned - commands. - """ - - if name == "lib": - p = self.get_msvc_paths("library") - else: - p = self.get_msvc_paths(name) - if p: - os.environ[name] = ';'.join(p) - - -if get_build_version() >= 8.0: - log.debug("Importing new compiler from distutils.msvc9compiler") - OldMSVCCompiler = MSVCCompiler - from distutils.msvc9compiler import MSVCCompiler - - # get_build_architecture not really relevant now we support cross-compile - from distutils.msvc9compiler import MacroExpander # noqa: F811 diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/py38compat.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/py38compat.py deleted file mode 100755 index 59224e7..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/py38compat.py +++ /dev/null @@ -1,8 +0,0 @@ -def aix_platform(osname, version, release): - try: - import _aix_support - - return _aix_support.aix_platform() - except ImportError: - pass - return "{}-{}.{}".format(osname, version, release) diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/py39compat.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/py39compat.py deleted file mode 100755 index c43e5f1..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/py39compat.py +++ /dev/null @@ -1,22 +0,0 @@ -import sys -import platform - - -def add_ext_suffix_39(vars): - """ - Ensure vars contains 'EXT_SUFFIX'. pypa/distutils#130 - """ - import _imp - - ext_suffix = _imp.extension_suffixes()[0] - vars.update( - EXT_SUFFIX=ext_suffix, - # sysconfig sets SO to match EXT_SUFFIX, so maintain - # that expectation. - # https://github.com/python/cpython/blob/785cc6770588de087d09e89a69110af2542be208/Lib/sysconfig.py#L671-L673 - SO=ext_suffix, - ) - - -needs_ext_suffix = sys.version_info < (3, 10) and platform.system() == 'Windows' -add_ext_suffix = add_ext_suffix_39 if needs_ext_suffix else lambda vars: None diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/spawn.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/spawn.py deleted file mode 100755 index afefe52..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/spawn.py +++ /dev/null @@ -1,109 +0,0 @@ -"""distutils.spawn - -Provides the 'spawn()' function, a front-end to various platform- -specific functions for launching another program in a sub-process. -Also provides the 'find_executable()' to search the path for a given -executable name. -""" - -import sys -import os -import subprocess - -from .errors import DistutilsExecError -from .debug import DEBUG -from ._log import log - - -def spawn(cmd, search_path=1, verbose=0, dry_run=0, env=None): # noqa: C901 - """Run another program, specified as a command list 'cmd', in a new process. - - 'cmd' is just the argument list for the new process, ie. - cmd[0] is the program to run and cmd[1:] are the rest of its arguments. - There is no way to run a program with a name different from that of its - executable. - - If 'search_path' is true (the default), the system's executable - search path will be used to find the program; otherwise, cmd[0] - must be the exact path to the executable. If 'dry_run' is true, - the command will not actually be run. - - Raise DistutilsExecError if running the program fails in any way; just - return on success. - """ - # cmd is documented as a list, but just in case some code passes a tuple - # in, protect our %-formatting code against horrible death - cmd = list(cmd) - - log.info(subprocess.list2cmdline(cmd)) - if dry_run: - return - - if search_path: - executable = find_executable(cmd[0]) - if executable is not None: - cmd[0] = executable - - env = env if env is not None else dict(os.environ) - - if sys.platform == 'darwin': - from distutils.util import MACOSX_VERSION_VAR, get_macosx_target_ver - - macosx_target_ver = get_macosx_target_ver() - if macosx_target_ver: - env[MACOSX_VERSION_VAR] = macosx_target_ver - - try: - proc = subprocess.Popen(cmd, env=env) - proc.wait() - exitcode = proc.returncode - except OSError as exc: - if not DEBUG: - cmd = cmd[0] - raise DistutilsExecError( - "command {!r} failed: {}".format(cmd, exc.args[-1]) - ) from exc - - if exitcode: - if not DEBUG: - cmd = cmd[0] - raise DistutilsExecError( - "command {!r} failed with exit code {}".format(cmd, exitcode) - ) - - -def find_executable(executable, path=None): - """Tries to find 'executable' in the directories listed in 'path'. - - A string listing directories separated by 'os.pathsep'; defaults to - os.environ['PATH']. Returns the complete filename or None if not found. - """ - _, ext = os.path.splitext(executable) - if (sys.platform == 'win32') and (ext != '.exe'): - executable = executable + '.exe' - - if os.path.isfile(executable): - return executable - - if path is None: - path = os.environ.get('PATH', None) - if path is None: - try: - path = os.confstr("CS_PATH") - except (AttributeError, ValueError): - # os.confstr() or CS_PATH is not available - path = os.defpath - # bpo-35755: Don't use os.defpath if the PATH environment variable is - # set to an empty string - - # PATH='' doesn't match, whereas PATH=':' looks in the current directory - if not path: - return None - - paths = path.split(os.pathsep) - for p in paths: - f = os.path.join(p, executable) - if os.path.isfile(f): - # the file exists, we have a shot at spawn working - return f - return None diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/sysconfig.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/sysconfig.py deleted file mode 100755 index 0ec6936..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/sysconfig.py +++ /dev/null @@ -1,552 +0,0 @@ -"""Provide access to Python's configuration information. The specific -configuration variables available depend heavily on the platform and -configuration. The values may be retrieved using -get_config_var(name), and the list of variables is available via -get_config_vars().keys(). Additional convenience functions are also -available. - -Written by: Fred L. Drake, Jr. -Email: -""" - -import os -import re -import sys -import sysconfig -import pathlib - -from .errors import DistutilsPlatformError -from . import py39compat -from ._functools import pass_none - -IS_PYPY = '__pypy__' in sys.builtin_module_names - -# These are needed in a couple of spots, so just compute them once. -PREFIX = os.path.normpath(sys.prefix) -EXEC_PREFIX = os.path.normpath(sys.exec_prefix) -BASE_PREFIX = os.path.normpath(sys.base_prefix) -BASE_EXEC_PREFIX = os.path.normpath(sys.base_exec_prefix) - -# Path to the base directory of the project. On Windows the binary may -# live in project/PCbuild/win32 or project/PCbuild/amd64. -# set for cross builds -if "_PYTHON_PROJECT_BASE" in os.environ: - project_base = os.path.abspath(os.environ["_PYTHON_PROJECT_BASE"]) -else: - if sys.executable: - project_base = os.path.dirname(os.path.abspath(sys.executable)) - else: - # sys.executable can be empty if argv[0] has been changed and Python is - # unable to retrieve the real program name - project_base = os.getcwd() - - -def _is_python_source_dir(d): - """ - Return True if the target directory appears to point to an - un-installed Python. - """ - modules = pathlib.Path(d).joinpath('Modules') - return any(modules.joinpath(fn).is_file() for fn in ('Setup', 'Setup.local')) - - -_sys_home = getattr(sys, '_home', None) - - -def _is_parent(dir_a, dir_b): - """ - Return True if a is a parent of b. - """ - return os.path.normcase(dir_a).startswith(os.path.normcase(dir_b)) - - -if os.name == 'nt': - - @pass_none - def _fix_pcbuild(d): - # In a venv, sys._home will be inside BASE_PREFIX rather than PREFIX. - prefixes = PREFIX, BASE_PREFIX - matched = ( - prefix - for prefix in prefixes - if _is_parent(d, os.path.join(prefix, "PCbuild")) - ) - return next(matched, d) - - project_base = _fix_pcbuild(project_base) - _sys_home = _fix_pcbuild(_sys_home) - - -def _python_build(): - if _sys_home: - return _is_python_source_dir(_sys_home) - return _is_python_source_dir(project_base) - - -python_build = _python_build() - - -# Calculate the build qualifier flags if they are defined. Adding the flags -# to the include and lib directories only makes sense for an installation, not -# an in-source build. -build_flags = '' -try: - if not python_build: - build_flags = sys.abiflags -except AttributeError: - # It's not a configure-based build, so the sys module doesn't have - # this attribute, which is fine. - pass - - -def get_python_version(): - """Return a string containing the major and minor Python version, - leaving off the patchlevel. Sample return values could be '1.5' - or '2.2'. - """ - return '%d.%d' % sys.version_info[:2] - - -def get_python_inc(plat_specific=0, prefix=None): - """Return the directory containing installed Python header files. - - If 'plat_specific' is false (the default), this is the path to the - non-platform-specific header files, i.e. Python.h and so on; - otherwise, this is the path to platform-specific header files - (namely pyconfig.h). - - If 'prefix' is supplied, use it instead of sys.base_prefix or - sys.base_exec_prefix -- i.e., ignore 'plat_specific'. - """ - default_prefix = BASE_EXEC_PREFIX if plat_specific else BASE_PREFIX - resolved_prefix = prefix if prefix is not None else default_prefix - try: - getter = globals()[f'_get_python_inc_{os.name}'] - except KeyError: - raise DistutilsPlatformError( - "I don't know where Python installs its C header files " - "on platform '%s'" % os.name - ) - return getter(resolved_prefix, prefix, plat_specific) - - -def _get_python_inc_posix(prefix, spec_prefix, plat_specific): - if IS_PYPY and sys.version_info < (3, 8): - return os.path.join(prefix, 'include') - return ( - _get_python_inc_posix_python(plat_specific) - or _get_python_inc_from_config(plat_specific, spec_prefix) - or _get_python_inc_posix_prefix(prefix) - ) - - -def _get_python_inc_posix_python(plat_specific): - """ - Assume the executable is in the build directory. The - pyconfig.h file should be in the same directory. Since - the build directory may not be the source directory, - use "srcdir" from the makefile to find the "Include" - directory. - """ - if not python_build: - return - if plat_specific: - return _sys_home or project_base - incdir = os.path.join(get_config_var('srcdir'), 'Include') - return os.path.normpath(incdir) - - -def _get_python_inc_from_config(plat_specific, spec_prefix): - """ - If no prefix was explicitly specified, provide the include - directory from the config vars. Useful when - cross-compiling, since the config vars may come from - the host - platform Python installation, while the current Python - executable is from the build platform installation. - - >>> monkeypatch = getfixture('monkeypatch') - >>> gpifc = _get_python_inc_from_config - >>> monkeypatch.setitem(gpifc.__globals__, 'get_config_var', str.lower) - >>> gpifc(False, '/usr/bin/') - >>> gpifc(False, '') - >>> gpifc(False, None) - 'includepy' - >>> gpifc(True, None) - 'confincludepy' - """ - if spec_prefix is None: - return get_config_var('CONF' * plat_specific + 'INCLUDEPY') - - -def _get_python_inc_posix_prefix(prefix): - implementation = 'pypy' if IS_PYPY else 'python' - python_dir = implementation + get_python_version() + build_flags - return os.path.join(prefix, "include", python_dir) - - -def _get_python_inc_nt(prefix, spec_prefix, plat_specific): - if python_build: - # Include both the include and PC dir to ensure we can find - # pyconfig.h - return ( - os.path.join(prefix, "include") - + os.path.pathsep - + os.path.join(prefix, "PC") - ) - return os.path.join(prefix, "include") - - -# allow this behavior to be monkey-patched. Ref pypa/distutils#2. -def _posix_lib(standard_lib, libpython, early_prefix, prefix): - if standard_lib: - return libpython - else: - return os.path.join(libpython, "site-packages") - - -def get_python_lib(plat_specific=0, standard_lib=0, prefix=None): - """Return the directory containing the Python library (standard or - site additions). - - If 'plat_specific' is true, return the directory containing - platform-specific modules, i.e. any module from a non-pure-Python - module distribution; otherwise, return the platform-shared library - directory. If 'standard_lib' is true, return the directory - containing standard Python library modules; otherwise, return the - directory for site-specific modules. - - If 'prefix' is supplied, use it instead of sys.base_prefix or - sys.base_exec_prefix -- i.e., ignore 'plat_specific'. - """ - - if IS_PYPY and sys.version_info < (3, 8): - # PyPy-specific schema - if prefix is None: - prefix = PREFIX - if standard_lib: - return os.path.join(prefix, "lib-python", sys.version[0]) - return os.path.join(prefix, 'site-packages') - - early_prefix = prefix - - if prefix is None: - if standard_lib: - prefix = plat_specific and BASE_EXEC_PREFIX or BASE_PREFIX - else: - prefix = plat_specific and EXEC_PREFIX or PREFIX - - if os.name == "posix": - if plat_specific or standard_lib: - # Platform-specific modules (any module from a non-pure-Python - # module distribution) or standard Python library modules. - libdir = getattr(sys, "platlibdir", "lib") - else: - # Pure Python - libdir = "lib" - implementation = 'pypy' if IS_PYPY else 'python' - libpython = os.path.join(prefix, libdir, implementation + get_python_version()) - return _posix_lib(standard_lib, libpython, early_prefix, prefix) - elif os.name == "nt": - if standard_lib: - return os.path.join(prefix, "Lib") - else: - return os.path.join(prefix, "Lib", "site-packages") - else: - raise DistutilsPlatformError( - "I don't know where Python installs its library " - "on platform '%s'" % os.name - ) - - -def customize_compiler(compiler): # noqa: C901 - """Do any platform-specific customization of a CCompiler instance. - - Mainly needed on Unix, so we can plug in the information that - varies across Unices and is stored in Python's Makefile. - """ - if compiler.compiler_type == "unix": - if sys.platform == "darwin": - # Perform first-time customization of compiler-related - # config vars on OS X now that we know we need a compiler. - # This is primarily to support Pythons from binary - # installers. The kind and paths to build tools on - # the user system may vary significantly from the system - # that Python itself was built on. Also the user OS - # version and build tools may not support the same set - # of CPU architectures for universal builds. - global _config_vars - # Use get_config_var() to ensure _config_vars is initialized. - if not get_config_var('CUSTOMIZED_OSX_COMPILER'): - import _osx_support - - _osx_support.customize_compiler(_config_vars) - _config_vars['CUSTOMIZED_OSX_COMPILER'] = 'True' - - ( - cc, - cxx, - cflags, - ccshared, - ldshared, - shlib_suffix, - ar, - ar_flags, - ) = get_config_vars( - 'CC', - 'CXX', - 'CFLAGS', - 'CCSHARED', - 'LDSHARED', - 'SHLIB_SUFFIX', - 'AR', - 'ARFLAGS', - ) - - if 'CC' in os.environ: - newcc = os.environ['CC'] - if 'LDSHARED' not in os.environ and ldshared.startswith(cc): - # If CC is overridden, use that as the default - # command for LDSHARED as well - ldshared = newcc + ldshared[len(cc) :] - cc = newcc - if 'CXX' in os.environ: - cxx = os.environ['CXX'] - if 'LDSHARED' in os.environ: - ldshared = os.environ['LDSHARED'] - if 'CPP' in os.environ: - cpp = os.environ['CPP'] - else: - cpp = cc + " -E" # not always - if 'LDFLAGS' in os.environ: - ldshared = ldshared + ' ' + os.environ['LDFLAGS'] - if 'CFLAGS' in os.environ: - cflags = cflags + ' ' + os.environ['CFLAGS'] - ldshared = ldshared + ' ' + os.environ['CFLAGS'] - if 'CPPFLAGS' in os.environ: - cpp = cpp + ' ' + os.environ['CPPFLAGS'] - cflags = cflags + ' ' + os.environ['CPPFLAGS'] - ldshared = ldshared + ' ' + os.environ['CPPFLAGS'] - if 'AR' in os.environ: - ar = os.environ['AR'] - if 'ARFLAGS' in os.environ: - archiver = ar + ' ' + os.environ['ARFLAGS'] - else: - archiver = ar + ' ' + ar_flags - - cc_cmd = cc + ' ' + cflags - compiler.set_executables( - preprocessor=cpp, - compiler=cc_cmd, - compiler_so=cc_cmd + ' ' + ccshared, - compiler_cxx=cxx, - linker_so=ldshared, - linker_exe=cc, - archiver=archiver, - ) - - if 'RANLIB' in os.environ and compiler.executables.get('ranlib', None): - compiler.set_executables(ranlib=os.environ['RANLIB']) - - compiler.shared_lib_extension = shlib_suffix - - -def get_config_h_filename(): - """Return full pathname of installed pyconfig.h file.""" - if python_build: - if os.name == "nt": - inc_dir = os.path.join(_sys_home or project_base, "PC") - else: - inc_dir = _sys_home or project_base - return os.path.join(inc_dir, 'pyconfig.h') - else: - return sysconfig.get_config_h_filename() - - -def get_makefile_filename(): - """Return full pathname of installed Makefile from the Python build.""" - return sysconfig.get_makefile_filename() - - -def parse_config_h(fp, g=None): - """Parse a config.h-style file. - - A dictionary containing name/value pairs is returned. If an - optional dictionary is passed in as the second argument, it is - used instead of a new dictionary. - """ - return sysconfig.parse_config_h(fp, vars=g) - - -# Regexes needed for parsing Makefile (and similar syntaxes, -# like old-style Setup files). -_variable_rx = re.compile(r"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)") -_findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)") -_findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}") - - -def parse_makefile(fn, g=None): # noqa: C901 - """Parse a Makefile-style file. - - A dictionary containing name/value pairs is returned. If an - optional dictionary is passed in as the second argument, it is - used instead of a new dictionary. - """ - from distutils.text_file import TextFile - - fp = TextFile( - fn, strip_comments=1, skip_blanks=1, join_lines=1, errors="surrogateescape" - ) - - if g is None: - g = {} - done = {} - notdone = {} - - while True: - line = fp.readline() - if line is None: # eof - break - m = _variable_rx.match(line) - if m: - n, v = m.group(1, 2) - v = v.strip() - # `$$' is a literal `$' in make - tmpv = v.replace('$$', '') - - if "$" in tmpv: - notdone[n] = v - else: - try: - v = int(v) - except ValueError: - # insert literal `$' - done[n] = v.replace('$$', '$') - else: - done[n] = v - - # Variables with a 'PY_' prefix in the makefile. These need to - # be made available without that prefix through sysconfig. - # Special care is needed to ensure that variable expansion works, even - # if the expansion uses the name without a prefix. - renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS') - - # do variable interpolation here - while notdone: - for name in list(notdone): - value = notdone[name] - m = _findvar1_rx.search(value) or _findvar2_rx.search(value) - if m: - n = m.group(1) - found = True - if n in done: - item = str(done[n]) - elif n in notdone: - # get it on a subsequent round - found = False - elif n in os.environ: - # do it like make: fall back to environment - item = os.environ[n] - - elif n in renamed_variables: - if name.startswith('PY_') and name[3:] in renamed_variables: - item = "" - - elif 'PY_' + n in notdone: - found = False - - else: - item = str(done['PY_' + n]) - else: - done[n] = item = "" - if found: - after = value[m.end() :] - value = value[: m.start()] + item + after - if "$" in after: - notdone[name] = value - else: - try: - value = int(value) - except ValueError: - done[name] = value.strip() - else: - done[name] = value - del notdone[name] - - if name.startswith('PY_') and name[3:] in renamed_variables: - - name = name[3:] - if name not in done: - done[name] = value - else: - # bogus variable reference; just drop it since we can't deal - del notdone[name] - - fp.close() - - # strip spurious spaces - for k, v in done.items(): - if isinstance(v, str): - done[k] = v.strip() - - # save the results in the global dictionary - g.update(done) - return g - - -def expand_makefile_vars(s, vars): - """Expand Makefile-style variables -- "${foo}" or "$(foo)" -- in - 'string' according to 'vars' (a dictionary mapping variable names to - values). Variables not present in 'vars' are silently expanded to the - empty string. The variable values in 'vars' should not contain further - variable expansions; if 'vars' is the output of 'parse_makefile()', - you're fine. Returns a variable-expanded version of 's'. - """ - - # This algorithm does multiple expansion, so if vars['foo'] contains - # "${bar}", it will expand ${foo} to ${bar}, and then expand - # ${bar}... and so forth. This is fine as long as 'vars' comes from - # 'parse_makefile()', which takes care of such expansions eagerly, - # according to make's variable expansion semantics. - - while True: - m = _findvar1_rx.search(s) or _findvar2_rx.search(s) - if m: - (beg, end) = m.span() - s = s[0:beg] + vars.get(m.group(1)) + s[end:] - else: - break - return s - - -_config_vars = None - - -def get_config_vars(*args): - """With no arguments, return a dictionary of all configuration - variables relevant for the current platform. Generally this includes - everything needed to build extensions and install both pure modules and - extensions. On Unix, this means every variable defined in Python's - installed Makefile; on Windows it's a much smaller set. - - With arguments, return a list of values that result from looking up - each argument in the configuration variable dictionary. - """ - global _config_vars - if _config_vars is None: - _config_vars = sysconfig.get_config_vars().copy() - py39compat.add_ext_suffix(_config_vars) - - return [_config_vars.get(name) for name in args] if args else _config_vars - - -def get_config_var(name): - """Return the value of a single variable using the dictionary - returned by 'get_config_vars()'. Equivalent to - get_config_vars().get(name) - """ - if name == 'SO': - import warnings - - warnings.warn('SO is deprecated, use EXT_SUFFIX', DeprecationWarning, 2) - return get_config_vars().get(name) diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/text_file.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/text_file.py deleted file mode 100755 index 7274d4b..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/text_file.py +++ /dev/null @@ -1,287 +0,0 @@ -"""text_file - -provides the TextFile class, which gives an interface to text files -that (optionally) takes care of stripping comments, ignoring blank -lines, and joining lines with backslashes.""" - -import sys - - -class TextFile: - """Provides a file-like object that takes care of all the things you - commonly want to do when processing a text file that has some - line-by-line syntax: strip comments (as long as "#" is your - comment character), skip blank lines, join adjacent lines by - escaping the newline (ie. backslash at end of line), strip - leading and/or trailing whitespace. All of these are optional - and independently controllable. - - Provides a 'warn()' method so you can generate warning messages that - report physical line number, even if the logical line in question - spans multiple physical lines. Also provides 'unreadline()' for - implementing line-at-a-time lookahead. - - Constructor is called as: - - TextFile (filename=None, file=None, **options) - - It bombs (RuntimeError) if both 'filename' and 'file' are None; - 'filename' should be a string, and 'file' a file object (or - something that provides 'readline()' and 'close()' methods). It is - recommended that you supply at least 'filename', so that TextFile - can include it in warning messages. If 'file' is not supplied, - TextFile creates its own using 'io.open()'. - - The options are all boolean, and affect the value returned by - 'readline()': - strip_comments [default: true] - strip from "#" to end-of-line, as well as any whitespace - leading up to the "#" -- unless it is escaped by a backslash - lstrip_ws [default: false] - strip leading whitespace from each line before returning it - rstrip_ws [default: true] - strip trailing whitespace (including line terminator!) from - each line before returning it - skip_blanks [default: true} - skip lines that are empty *after* stripping comments and - whitespace. (If both lstrip_ws and rstrip_ws are false, - then some lines may consist of solely whitespace: these will - *not* be skipped, even if 'skip_blanks' is true.) - join_lines [default: false] - if a backslash is the last non-newline character on a line - after stripping comments and whitespace, join the following line - to it to form one "logical line"; if N consecutive lines end - with a backslash, then N+1 physical lines will be joined to - form one logical line. - collapse_join [default: false] - strip leading whitespace from lines that are joined to their - predecessor; only matters if (join_lines and not lstrip_ws) - errors [default: 'strict'] - error handler used to decode the file content - - Note that since 'rstrip_ws' can strip the trailing newline, the - semantics of 'readline()' must differ from those of the builtin file - object's 'readline()' method! In particular, 'readline()' returns - None for end-of-file: an empty string might just be a blank line (or - an all-whitespace line), if 'rstrip_ws' is true but 'skip_blanks' is - not.""" - - default_options = { - 'strip_comments': 1, - 'skip_blanks': 1, - 'lstrip_ws': 0, - 'rstrip_ws': 1, - 'join_lines': 0, - 'collapse_join': 0, - 'errors': 'strict', - } - - def __init__(self, filename=None, file=None, **options): - """Construct a new TextFile object. At least one of 'filename' - (a string) and 'file' (a file-like object) must be supplied. - They keyword argument options are described above and affect - the values returned by 'readline()'.""" - if filename is None and file is None: - raise RuntimeError( - "you must supply either or both of 'filename' and 'file'" - ) - - # set values for all options -- either from client option hash - # or fallback to default_options - for opt in self.default_options.keys(): - if opt in options: - setattr(self, opt, options[opt]) - else: - setattr(self, opt, self.default_options[opt]) - - # sanity check client option hash - for opt in options.keys(): - if opt not in self.default_options: - raise KeyError("invalid TextFile option '%s'" % opt) - - if file is None: - self.open(filename) - else: - self.filename = filename - self.file = file - self.current_line = 0 # assuming that file is at BOF! - - # 'linebuf' is a stack of lines that will be emptied before we - # actually read from the file; it's only populated by an - # 'unreadline()' operation - self.linebuf = [] - - def open(self, filename): - """Open a new file named 'filename'. This overrides both the - 'filename' and 'file' arguments to the constructor.""" - self.filename = filename - self.file = open(self.filename, errors=self.errors) - self.current_line = 0 - - def close(self): - """Close the current file and forget everything we know about it - (filename, current line number).""" - file = self.file - self.file = None - self.filename = None - self.current_line = None - file.close() - - def gen_error(self, msg, line=None): - outmsg = [] - if line is None: - line = self.current_line - outmsg.append(self.filename + ", ") - if isinstance(line, (list, tuple)): - outmsg.append("lines %d-%d: " % tuple(line)) - else: - outmsg.append("line %d: " % line) - outmsg.append(str(msg)) - return "".join(outmsg) - - def error(self, msg, line=None): - raise ValueError("error: " + self.gen_error(msg, line)) - - def warn(self, msg, line=None): - """Print (to stderr) a warning message tied to the current logical - line in the current file. If the current logical line in the - file spans multiple physical lines, the warning refers to the - whole range, eg. "lines 3-5". If 'line' supplied, it overrides - the current line number; it may be a list or tuple to indicate a - range of physical lines, or an integer for a single physical - line.""" - sys.stderr.write("warning: " + self.gen_error(msg, line) + "\n") - - def readline(self): # noqa: C901 - """Read and return a single logical line from the current file (or - from an internal buffer if lines have previously been "unread" - with 'unreadline()'). If the 'join_lines' option is true, this - may involve reading multiple physical lines concatenated into a - single string. Updates the current line number, so calling - 'warn()' after 'readline()' emits a warning about the physical - line(s) just read. Returns None on end-of-file, since the empty - string can occur if 'rstrip_ws' is true but 'strip_blanks' is - not.""" - # If any "unread" lines waiting in 'linebuf', return the top - # one. (We don't actually buffer read-ahead data -- lines only - # get put in 'linebuf' if the client explicitly does an - # 'unreadline()'. - if self.linebuf: - line = self.linebuf[-1] - del self.linebuf[-1] - return line - - buildup_line = '' - - while True: - # read the line, make it None if EOF - line = self.file.readline() - if line == '': - line = None - - if self.strip_comments and line: - - # Look for the first "#" in the line. If none, never - # mind. If we find one and it's the first character, or - # is not preceded by "\", then it starts a comment -- - # strip the comment, strip whitespace before it, and - # carry on. Otherwise, it's just an escaped "#", so - # unescape it (and any other escaped "#"'s that might be - # lurking in there) and otherwise leave the line alone. - - pos = line.find("#") - if pos == -1: # no "#" -- no comments - pass - - # It's definitely a comment -- either "#" is the first - # character, or it's elsewhere and unescaped. - elif pos == 0 or line[pos - 1] != "\\": - # Have to preserve the trailing newline, because it's - # the job of a later step (rstrip_ws) to remove it -- - # and if rstrip_ws is false, we'd better preserve it! - # (NB. this means that if the final line is all comment - # and has no trailing newline, we will think that it's - # EOF; I think that's OK.) - eol = (line[-1] == '\n') and '\n' or '' - line = line[0:pos] + eol - - # If all that's left is whitespace, then skip line - # *now*, before we try to join it to 'buildup_line' -- - # that way constructs like - # hello \\ - # # comment that should be ignored - # there - # result in "hello there". - if line.strip() == "": - continue - else: # it's an escaped "#" - line = line.replace("\\#", "#") - - # did previous line end with a backslash? then accumulate - if self.join_lines and buildup_line: - # oops: end of file - if line is None: - self.warn("continuation line immediately precedes " "end-of-file") - return buildup_line - - if self.collapse_join: - line = line.lstrip() - line = buildup_line + line - - # careful: pay attention to line number when incrementing it - if isinstance(self.current_line, list): - self.current_line[1] = self.current_line[1] + 1 - else: - self.current_line = [self.current_line, self.current_line + 1] - # just an ordinary line, read it as usual - else: - if line is None: # eof - return None - - # still have to be careful about incrementing the line number! - if isinstance(self.current_line, list): - self.current_line = self.current_line[1] + 1 - else: - self.current_line = self.current_line + 1 - - # strip whitespace however the client wants (leading and - # trailing, or one or the other, or neither) - if self.lstrip_ws and self.rstrip_ws: - line = line.strip() - elif self.lstrip_ws: - line = line.lstrip() - elif self.rstrip_ws: - line = line.rstrip() - - # blank line (whether we rstrip'ed or not)? skip to next line - # if appropriate - if (line == '' or line == '\n') and self.skip_blanks: - continue - - if self.join_lines: - if line[-1] == '\\': - buildup_line = line[:-1] - continue - - if line[-2:] == '\\\n': - buildup_line = line[0:-2] + '\n' - continue - - # well, I guess there's some actual content there: return it - return line - - def readlines(self): - """Read and return the list of all logical lines remaining in the - current file.""" - lines = [] - while True: - line = self.readline() - if line is None: - return lines - lines.append(line) - - def unreadline(self, line): - """Push 'line' (a string) onto an internal buffer that will be - checked by future 'readline()' calls. Handy for implementing - a parser with line-at-a-time lookahead.""" - self.linebuf.append(line) diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/unixccompiler.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/unixccompiler.py deleted file mode 100755 index 4bf2e6a..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/unixccompiler.py +++ /dev/null @@ -1,401 +0,0 @@ -"""distutils.unixccompiler - -Contains the UnixCCompiler class, a subclass of CCompiler that handles -the "typical" Unix-style command-line C compiler: - * macros defined with -Dname[=value] - * macros undefined with -Uname - * include search directories specified with -Idir - * libraries specified with -lllib - * library search directories specified with -Ldir - * compile handled by 'cc' (or similar) executable with -c option: - compiles .c to .o - * link static library handled by 'ar' command (possibly with 'ranlib') - * link shared library handled by 'cc -shared' -""" - -import os -import sys -import re -import shlex -import itertools - -from . import sysconfig -from .dep_util import newer -from .ccompiler import CCompiler, gen_preprocess_options, gen_lib_options -from .errors import DistutilsExecError, CompileError, LibError, LinkError -from ._log import log -from ._macos_compat import compiler_fixup - -# XXX Things not currently handled: -# * optimization/debug/warning flags; we just use whatever's in Python's -# Makefile and live with it. Is this adequate? If not, we might -# have to have a bunch of subclasses GNUCCompiler, SGICCompiler, -# SunCCompiler, and I suspect down that road lies madness. -# * even if we don't know a warning flag from an optimization flag, -# we need some way for outsiders to feed preprocessor/compiler/linker -# flags in to us -- eg. a sysadmin might want to mandate certain flags -# via a site config file, or a user might want to set something for -# compiling this module distribution only via the setup.py command -# line, whatever. As long as these options come from something on the -# current system, they can be as system-dependent as they like, and we -# should just happily stuff them into the preprocessor/compiler/linker -# options and carry on. - - -def _split_env(cmd): - """ - For macOS, split command into 'env' portion (if any) - and the rest of the linker command. - - >>> _split_env(['a', 'b', 'c']) - ([], ['a', 'b', 'c']) - >>> _split_env(['/usr/bin/env', 'A=3', 'gcc']) - (['/usr/bin/env', 'A=3'], ['gcc']) - """ - pivot = 0 - if os.path.basename(cmd[0]) == "env": - pivot = 1 - while '=' in cmd[pivot]: - pivot += 1 - return cmd[:pivot], cmd[pivot:] - - -def _split_aix(cmd): - """ - AIX platforms prefix the compiler with the ld_so_aix - script, so split that from the linker command. - - >>> _split_aix(['a', 'b', 'c']) - ([], ['a', 'b', 'c']) - >>> _split_aix(['/bin/foo/ld_so_aix', 'gcc']) - (['/bin/foo/ld_so_aix'], ['gcc']) - """ - pivot = os.path.basename(cmd[0]) == 'ld_so_aix' - return cmd[:pivot], cmd[pivot:] - - -def _linker_params(linker_cmd, compiler_cmd): - """ - The linker command usually begins with the compiler - command (possibly multiple elements), followed by zero or more - params for shared library building. - - If the LDSHARED env variable overrides the linker command, - however, the commands may not match. - - Return the best guess of the linker parameters by stripping - the linker command. If the compiler command does not - match the linker command, assume the linker command is - just the first element. - - >>> _linker_params('gcc foo bar'.split(), ['gcc']) - ['foo', 'bar'] - >>> _linker_params('gcc foo bar'.split(), ['other']) - ['foo', 'bar'] - >>> _linker_params('ccache gcc foo bar'.split(), 'ccache gcc'.split()) - ['foo', 'bar'] - >>> _linker_params(['gcc'], ['gcc']) - [] - """ - c_len = len(compiler_cmd) - pivot = c_len if linker_cmd[:c_len] == compiler_cmd else 1 - return linker_cmd[pivot:] - - -class UnixCCompiler(CCompiler): - - compiler_type = 'unix' - - # These are used by CCompiler in two places: the constructor sets - # instance attributes 'preprocessor', 'compiler', etc. from them, and - # 'set_executable()' allows any of these to be set. The defaults here - # are pretty generic; they will probably have to be set by an outsider - # (eg. using information discovered by the sysconfig about building - # Python extensions). - executables = { - 'preprocessor': None, - 'compiler': ["cc"], - 'compiler_so': ["cc"], - 'compiler_cxx': ["cc"], - 'linker_so': ["cc", "-shared"], - 'linker_exe': ["cc"], - 'archiver': ["ar", "-cr"], - 'ranlib': None, - } - - if sys.platform[:6] == "darwin": - executables['ranlib'] = ["ranlib"] - - # Needed for the filename generation methods provided by the base - # class, CCompiler. NB. whoever instantiates/uses a particular - # UnixCCompiler instance should set 'shared_lib_ext' -- we set a - # reasonable common default here, but it's not necessarily used on all - # Unices! - - src_extensions = [".c", ".C", ".cc", ".cxx", ".cpp", ".m"] - obj_extension = ".o" - static_lib_extension = ".a" - shared_lib_extension = ".so" - dylib_lib_extension = ".dylib" - xcode_stub_lib_extension = ".tbd" - static_lib_format = shared_lib_format = dylib_lib_format = "lib%s%s" - xcode_stub_lib_format = dylib_lib_format - if sys.platform == "cygwin": - exe_extension = ".exe" - - def preprocess( - self, - source, - output_file=None, - macros=None, - include_dirs=None, - extra_preargs=None, - extra_postargs=None, - ): - fixed_args = self._fix_compile_args(None, macros, include_dirs) - ignore, macros, include_dirs = fixed_args - pp_opts = gen_preprocess_options(macros, include_dirs) - pp_args = self.preprocessor + pp_opts - if output_file: - pp_args.extend(['-o', output_file]) - if extra_preargs: - pp_args[:0] = extra_preargs - if extra_postargs: - pp_args.extend(extra_postargs) - pp_args.append(source) - - # reasons to preprocess: - # - force is indicated - # - output is directed to stdout - # - source file is newer than the target - preprocess = self.force or output_file is None or newer(source, output_file) - if not preprocess: - return - - if output_file: - self.mkpath(os.path.dirname(output_file)) - - try: - self.spawn(pp_args) - except DistutilsExecError as msg: - raise CompileError(msg) - - def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts): - compiler_so = compiler_fixup(self.compiler_so, cc_args + extra_postargs) - try: - self.spawn(compiler_so + cc_args + [src, '-o', obj] + extra_postargs) - except DistutilsExecError as msg: - raise CompileError(msg) - - def create_static_lib( - self, objects, output_libname, output_dir=None, debug=0, target_lang=None - ): - objects, output_dir = self._fix_object_args(objects, output_dir) - - output_filename = self.library_filename(output_libname, output_dir=output_dir) - - if self._need_link(objects, output_filename): - self.mkpath(os.path.dirname(output_filename)) - self.spawn(self.archiver + [output_filename] + objects + self.objects) - - # Not many Unices required ranlib anymore -- SunOS 4.x is, I - # think the only major Unix that does. Maybe we need some - # platform intelligence here to skip ranlib if it's not - # needed -- or maybe Python's configure script took care of - # it for us, hence the check for leading colon. - if self.ranlib: - try: - self.spawn(self.ranlib + [output_filename]) - except DistutilsExecError as msg: - raise LibError(msg) - else: - log.debug("skipping %s (up-to-date)", output_filename) - - def link( - self, - target_desc, - objects, - output_filename, - output_dir=None, - libraries=None, - library_dirs=None, - runtime_library_dirs=None, - export_symbols=None, - debug=0, - extra_preargs=None, - extra_postargs=None, - build_temp=None, - target_lang=None, - ): - objects, output_dir = self._fix_object_args(objects, output_dir) - fixed_args = self._fix_lib_args(libraries, library_dirs, runtime_library_dirs) - libraries, library_dirs, runtime_library_dirs = fixed_args - - lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, libraries) - if not isinstance(output_dir, (str, type(None))): - raise TypeError("'output_dir' must be a string or None") - if output_dir is not None: - output_filename = os.path.join(output_dir, output_filename) - - if self._need_link(objects, output_filename): - ld_args = objects + self.objects + lib_opts + ['-o', output_filename] - if debug: - ld_args[:0] = ['-g'] - if extra_preargs: - ld_args[:0] = extra_preargs - if extra_postargs: - ld_args.extend(extra_postargs) - self.mkpath(os.path.dirname(output_filename)) - try: - # Select a linker based on context: linker_exe when - # building an executable or linker_so (with shared options) - # when building a shared library. - building_exe = target_desc == CCompiler.EXECUTABLE - linker = (self.linker_exe if building_exe else self.linker_so)[:] - - if target_lang == "c++" and self.compiler_cxx: - env, linker_ne = _split_env(linker) - aix, linker_na = _split_aix(linker_ne) - _, compiler_cxx_ne = _split_env(self.compiler_cxx) - _, linker_exe_ne = _split_env(self.linker_exe) - - params = _linker_params(linker_na, linker_exe_ne) - linker = env + aix + compiler_cxx_ne + params - - linker = compiler_fixup(linker, ld_args) - - self.spawn(linker + ld_args) - except DistutilsExecError as msg: - raise LinkError(msg) - else: - log.debug("skipping %s (up-to-date)", output_filename) - - # -- Miscellaneous methods ----------------------------------------- - # These are all used by the 'gen_lib_options() function, in - # ccompiler.py. - - def library_dir_option(self, dir): - return "-L" + dir - - def _is_gcc(self): - cc_var = sysconfig.get_config_var("CC") - compiler = os.path.basename(shlex.split(cc_var)[0]) - return "gcc" in compiler or "g++" in compiler - - def runtime_library_dir_option(self, dir): - # XXX Hackish, at the very least. See Python bug #445902: - # http://sourceforge.net/tracker/index.php - # ?func=detail&aid=445902&group_id=5470&atid=105470 - # Linkers on different platforms need different options to - # specify that directories need to be added to the list of - # directories searched for dependencies when a dynamic library - # is sought. GCC on GNU systems (Linux, FreeBSD, ...) has to - # be told to pass the -R option through to the linker, whereas - # other compilers and gcc on other systems just know this. - # Other compilers may need something slightly different. At - # this time, there's no way to determine this information from - # the configuration data stored in the Python installation, so - # we use this hack. - if sys.platform[:6] == "darwin": - from distutils.util import get_macosx_target_ver, split_version - - macosx_target_ver = get_macosx_target_ver() - if macosx_target_ver and split_version(macosx_target_ver) >= [10, 5]: - return "-Wl,-rpath," + dir - else: # no support for -rpath on earlier macOS versions - return "-L" + dir - elif sys.platform[:7] == "freebsd": - return "-Wl,-rpath=" + dir - elif sys.platform[:5] == "hp-ux": - return [ - "-Wl,+s" if self._is_gcc() else "+s", - "-L" + dir, - ] - - # For all compilers, `-Wl` is the presumed way to - # pass a compiler option to the linker and `-R` is - # the way to pass an RPATH. - if sysconfig.get_config_var("GNULD") == "yes": - # GNU ld needs an extra option to get a RUNPATH - # instead of just an RPATH. - return "-Wl,--enable-new-dtags,-R" + dir - else: - return "-Wl,-R" + dir - - def library_option(self, lib): - return "-l" + lib - - @staticmethod - def _library_root(dir): - """ - macOS users can specify an alternate SDK using'-isysroot'. - Calculate the SDK root if it is specified. - - Note that, as of Xcode 7, Apple SDKs may contain textual stub - libraries with .tbd extensions rather than the normal .dylib - shared libraries installed in /. The Apple compiler tool - chain handles this transparently but it can cause problems - for programs that are being built with an SDK and searching - for specific libraries. Callers of find_library_file need to - keep in mind that the base filename of the returned SDK library - file might have a different extension from that of the library - file installed on the running system, for example: - /Applications/Xcode.app/Contents/Developer/Platforms/ - MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/ - usr/lib/libedit.tbd - vs - /usr/lib/libedit.dylib - """ - cflags = sysconfig.get_config_var('CFLAGS') - match = re.search(r'-isysroot\s*(\S+)', cflags) - - apply_root = ( - sys.platform == 'darwin' - and match - and ( - dir.startswith('/System/') - or (dir.startswith('/usr/') and not dir.startswith('/usr/local/')) - ) - ) - - return os.path.join(match.group(1), dir[1:]) if apply_root else dir - - def find_library_file(self, dirs, lib, debug=0): - r""" - Second-guess the linker with not much hard - data to go on: GCC seems to prefer the shared library, so - assume that *all* Unix C compilers do, - ignoring even GCC's "-static" option. - - >>> compiler = UnixCCompiler() - >>> compiler._library_root = lambda dir: dir - >>> monkeypatch = getfixture('monkeypatch') - >>> monkeypatch.setattr(os.path, 'exists', lambda d: 'existing' in d) - >>> dirs = ('/foo/bar/missing', '/foo/bar/existing') - >>> compiler.find_library_file(dirs, 'abc').replace('\\', '/') - '/foo/bar/existing/libabc.dylib' - >>> compiler.find_library_file(reversed(dirs), 'abc').replace('\\', '/') - '/foo/bar/existing/libabc.dylib' - >>> monkeypatch.setattr(os.path, 'exists', - ... lambda d: 'existing' in d and '.a' in d) - >>> compiler.find_library_file(dirs, 'abc').replace('\\', '/') - '/foo/bar/existing/libabc.a' - >>> compiler.find_library_file(reversed(dirs), 'abc').replace('\\', '/') - '/foo/bar/existing/libabc.a' - """ - lib_names = ( - self.library_filename(lib, lib_type=type) - for type in 'dylib xcode_stub shared static'.split() - ) - - roots = map(self._library_root, dirs) - - searched = ( - os.path.join(root, lib_name) - for root, lib_name in itertools.product(roots, lib_names) - ) - - found = filter(os.path.exists, searched) - - # Return None if it could not be found in any dir. - return next(found, None) diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/util.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/util.py deleted file mode 100755 index 8668b43..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/util.py +++ /dev/null @@ -1,513 +0,0 @@ -"""distutils.util - -Miscellaneous utility functions -- anything that doesn't fit into -one of the other *util.py modules. -""" - -import importlib.util -import os -import re -import string -import subprocess -import sys -import sysconfig -import functools - -from .errors import DistutilsPlatformError, DistutilsByteCompileError -from .dep_util import newer -from .spawn import spawn -from ._log import log - - -def get_host_platform(): - """ - Return a string that identifies the current platform. Use this - function to distinguish platform-specific build directories and - platform-specific built distributions. - """ - - # This function initially exposed platforms as defined in Python 3.9 - # even with older Python versions when distutils was split out. - # Now it delegates to stdlib sysconfig, but maintains compatibility. - - if sys.version_info < (3, 8): - if os.name == 'nt': - if '(arm)' in sys.version.lower(): - return 'win-arm32' - if '(arm64)' in sys.version.lower(): - return 'win-arm64' - - if sys.version_info < (3, 9): - if os.name == "posix" and hasattr(os, 'uname'): - osname, host, release, version, machine = os.uname() - if osname[:3] == "aix": - from .py38compat import aix_platform - - return aix_platform(osname, version, release) - - return sysconfig.get_platform() - - -def get_platform(): - if os.name == 'nt': - TARGET_TO_PLAT = { - 'x86': 'win32', - 'x64': 'win-amd64', - 'arm': 'win-arm32', - 'arm64': 'win-arm64', - } - target = os.environ.get('VSCMD_ARG_TGT_ARCH') - return TARGET_TO_PLAT.get(target) or get_host_platform() - return get_host_platform() - - -if sys.platform == 'darwin': - _syscfg_macosx_ver = None # cache the version pulled from sysconfig -MACOSX_VERSION_VAR = 'MACOSX_DEPLOYMENT_TARGET' - - -def _clear_cached_macosx_ver(): - """For testing only. Do not call.""" - global _syscfg_macosx_ver - _syscfg_macosx_ver = None - - -def get_macosx_target_ver_from_syscfg(): - """Get the version of macOS latched in the Python interpreter configuration. - Returns the version as a string or None if can't obtain one. Cached.""" - global _syscfg_macosx_ver - if _syscfg_macosx_ver is None: - from distutils import sysconfig - - ver = sysconfig.get_config_var(MACOSX_VERSION_VAR) or '' - if ver: - _syscfg_macosx_ver = ver - return _syscfg_macosx_ver - - -def get_macosx_target_ver(): - """Return the version of macOS for which we are building. - - The target version defaults to the version in sysconfig latched at time - the Python interpreter was built, unless overridden by an environment - variable. If neither source has a value, then None is returned""" - - syscfg_ver = get_macosx_target_ver_from_syscfg() - env_ver = os.environ.get(MACOSX_VERSION_VAR) - - if env_ver: - # Validate overridden version against sysconfig version, if have both. - # Ensure that the deployment target of the build process is not less - # than 10.3 if the interpreter was built for 10.3 or later. This - # ensures extension modules are built with correct compatibility - # values, specifically LDSHARED which can use - # '-undefined dynamic_lookup' which only works on >= 10.3. - if ( - syscfg_ver - and split_version(syscfg_ver) >= [10, 3] - and split_version(env_ver) < [10, 3] - ): - my_msg = ( - '$' + MACOSX_VERSION_VAR + ' mismatch: ' - 'now "%s" but "%s" during configure; ' - 'must use 10.3 or later' % (env_ver, syscfg_ver) - ) - raise DistutilsPlatformError(my_msg) - return env_ver - return syscfg_ver - - -def split_version(s): - """Convert a dot-separated string into a list of numbers for comparisons""" - return [int(n) for n in s.split('.')] - - -def convert_path(pathname): - """Return 'pathname' as a name that will work on the native filesystem, - i.e. split it on '/' and put it back together again using the current - directory separator. Needed because filenames in the setup script are - always supplied in Unix style, and have to be converted to the local - convention before we can actually use them in the filesystem. Raises - ValueError on non-Unix-ish systems if 'pathname' either starts or - ends with a slash. - """ - if os.sep == '/': - return pathname - if not pathname: - return pathname - if pathname[0] == '/': - raise ValueError("path '%s' cannot be absolute" % pathname) - if pathname[-1] == '/': - raise ValueError("path '%s' cannot end with '/'" % pathname) - - paths = pathname.split('/') - while '.' in paths: - paths.remove('.') - if not paths: - return os.curdir - return os.path.join(*paths) - - -# convert_path () - - -def change_root(new_root, pathname): - """Return 'pathname' with 'new_root' prepended. If 'pathname' is - relative, this is equivalent to "os.path.join(new_root,pathname)". - Otherwise, it requires making 'pathname' relative and then joining the - two, which is tricky on DOS/Windows and Mac OS. - """ - if os.name == 'posix': - if not os.path.isabs(pathname): - return os.path.join(new_root, pathname) - else: - return os.path.join(new_root, pathname[1:]) - - elif os.name == 'nt': - (drive, path) = os.path.splitdrive(pathname) - if path[0] == '\\': - path = path[1:] - return os.path.join(new_root, path) - - raise DistutilsPlatformError(f"nothing known about platform '{os.name}'") - - -@functools.lru_cache() -def check_environ(): - """Ensure that 'os.environ' has all the environment variables we - guarantee that users can use in config files, command-line options, - etc. Currently this includes: - HOME - user's home directory (Unix only) - PLAT - description of the current platform, including hardware - and OS (see 'get_platform()') - """ - if os.name == 'posix' and 'HOME' not in os.environ: - try: - import pwd - - os.environ['HOME'] = pwd.getpwuid(os.getuid())[5] - except (ImportError, KeyError): - # bpo-10496: if the current user identifier doesn't exist in the - # password database, do nothing - pass - - if 'PLAT' not in os.environ: - os.environ['PLAT'] = get_platform() - - -def subst_vars(s, local_vars): - """ - Perform variable substitution on 'string'. - Variables are indicated by format-style braces ("{var}"). - Variable is substituted by the value found in the 'local_vars' - dictionary or in 'os.environ' if it's not in 'local_vars'. - 'os.environ' is first checked/augmented to guarantee that it contains - certain values: see 'check_environ()'. Raise ValueError for any - variables not found in either 'local_vars' or 'os.environ'. - """ - check_environ() - lookup = dict(os.environ) - lookup.update((name, str(value)) for name, value in local_vars.items()) - try: - return _subst_compat(s).format_map(lookup) - except KeyError as var: - raise ValueError(f"invalid variable {var}") - - -def _subst_compat(s): - """ - Replace shell/Perl-style variable substitution with - format-style. For compatibility. - """ - - def _subst(match): - return f'{{{match.group(1)}}}' - - repl = re.sub(r'\$([a-zA-Z_][a-zA-Z_0-9]*)', _subst, s) - if repl != s: - import warnings - - warnings.warn( - "shell/Perl-style substitions are deprecated", - DeprecationWarning, - ) - return repl - - -def grok_environment_error(exc, prefix="error: "): - # Function kept for backward compatibility. - # Used to try clever things with EnvironmentErrors, - # but nowadays str(exception) produces good messages. - return prefix + str(exc) - - -# Needed by 'split_quoted()' -_wordchars_re = _squote_re = _dquote_re = None - - -def _init_regex(): - global _wordchars_re, _squote_re, _dquote_re - _wordchars_re = re.compile(r'[^\\\'\"%s ]*' % string.whitespace) - _squote_re = re.compile(r"'(?:[^'\\]|\\.)*'") - _dquote_re = re.compile(r'"(?:[^"\\]|\\.)*"') - - -def split_quoted(s): - """Split a string up according to Unix shell-like rules for quotes and - backslashes. In short: words are delimited by spaces, as long as those - spaces are not escaped by a backslash, or inside a quoted string. - Single and double quotes are equivalent, and the quote characters can - be backslash-escaped. The backslash is stripped from any two-character - escape sequence, leaving only the escaped character. The quote - characters are stripped from any quoted string. Returns a list of - words. - """ - - # This is a nice algorithm for splitting up a single string, since it - # doesn't require character-by-character examination. It was a little - # bit of a brain-bender to get it working right, though... - if _wordchars_re is None: - _init_regex() - - s = s.strip() - words = [] - pos = 0 - - while s: - m = _wordchars_re.match(s, pos) - end = m.end() - if end == len(s): - words.append(s[:end]) - break - - if s[end] in string.whitespace: - # unescaped, unquoted whitespace: now - # we definitely have a word delimiter - words.append(s[:end]) - s = s[end:].lstrip() - pos = 0 - - elif s[end] == '\\': - # preserve whatever is being escaped; - # will become part of the current word - s = s[:end] + s[end + 1 :] - pos = end + 1 - - else: - if s[end] == "'": # slurp singly-quoted string - m = _squote_re.match(s, end) - elif s[end] == '"': # slurp doubly-quoted string - m = _dquote_re.match(s, end) - else: - raise RuntimeError("this can't happen (bad char '%c')" % s[end]) - - if m is None: - raise ValueError("bad string (mismatched %s quotes?)" % s[end]) - - (beg, end) = m.span() - s = s[:beg] + s[beg + 1 : end - 1] + s[end:] - pos = m.end() - 2 - - if pos >= len(s): - words.append(s) - break - - return words - - -# split_quoted () - - -def execute(func, args, msg=None, verbose=0, dry_run=0): - """Perform some action that affects the outside world (eg. by - writing to the filesystem). Such actions are special because they - are disabled by the 'dry_run' flag. This method takes care of all - that bureaucracy for you; all you have to do is supply the - function to call and an argument tuple for it (to embody the - "external action" being performed), and an optional message to - print. - """ - if msg is None: - msg = "{}{!r}".format(func.__name__, args) - if msg[-2:] == ',)': # correct for singleton tuple - msg = msg[0:-2] + ')' - - log.info(msg) - if not dry_run: - func(*args) - - -def strtobool(val): - """Convert a string representation of truth to true (1) or false (0). - - True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values - are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if - 'val' is anything else. - """ - val = val.lower() - if val in ('y', 'yes', 't', 'true', 'on', '1'): - return 1 - elif val in ('n', 'no', 'f', 'false', 'off', '0'): - return 0 - else: - raise ValueError("invalid truth value {!r}".format(val)) - - -def byte_compile( # noqa: C901 - py_files, - optimize=0, - force=0, - prefix=None, - base_dir=None, - verbose=1, - dry_run=0, - direct=None, -): - """Byte-compile a collection of Python source files to .pyc - files in a __pycache__ subdirectory. 'py_files' is a list - of files to compile; any files that don't end in ".py" are silently - skipped. 'optimize' must be one of the following: - 0 - don't optimize - 1 - normal optimization (like "python -O") - 2 - extra optimization (like "python -OO") - If 'force' is true, all files are recompiled regardless of - timestamps. - - The source filename encoded in each bytecode file defaults to the - filenames listed in 'py_files'; you can modify these with 'prefix' and - 'basedir'. 'prefix' is a string that will be stripped off of each - source filename, and 'base_dir' is a directory name that will be - prepended (after 'prefix' is stripped). You can supply either or both - (or neither) of 'prefix' and 'base_dir', as you wish. - - If 'dry_run' is true, doesn't actually do anything that would - affect the filesystem. - - Byte-compilation is either done directly in this interpreter process - with the standard py_compile module, or indirectly by writing a - temporary script and executing it. Normally, you should let - 'byte_compile()' figure out to use direct compilation or not (see - the source for details). The 'direct' flag is used by the script - generated in indirect mode; unless you know what you're doing, leave - it set to None. - """ - - # nothing is done if sys.dont_write_bytecode is True - if sys.dont_write_bytecode: - raise DistutilsByteCompileError('byte-compiling is disabled.') - - # First, if the caller didn't force us into direct or indirect mode, - # figure out which mode we should be in. We take a conservative - # approach: choose direct mode *only* if the current interpreter is - # in debug mode and optimize is 0. If we're not in debug mode (-O - # or -OO), we don't know which level of optimization this - # interpreter is running with, so we can't do direct - # byte-compilation and be certain that it's the right thing. Thus, - # always compile indirectly if the current interpreter is in either - # optimize mode, or if either optimization level was requested by - # the caller. - if direct is None: - direct = __debug__ and optimize == 0 - - # "Indirect" byte-compilation: write a temporary script and then - # run it with the appropriate flags. - if not direct: - try: - from tempfile import mkstemp - - (script_fd, script_name) = mkstemp(".py") - except ImportError: - from tempfile import mktemp - - (script_fd, script_name) = None, mktemp(".py") - log.info("writing byte-compilation script '%s'", script_name) - if not dry_run: - if script_fd is not None: - script = os.fdopen(script_fd, "w") - else: - script = open(script_name, "w") - - with script: - script.write( - """\ -from distutils.util import byte_compile -files = [ -""" - ) - - # XXX would be nice to write absolute filenames, just for - # safety's sake (script should be more robust in the face of - # chdir'ing before running it). But this requires abspath'ing - # 'prefix' as well, and that breaks the hack in build_lib's - # 'byte_compile()' method that carefully tacks on a trailing - # slash (os.sep really) to make sure the prefix here is "just - # right". This whole prefix business is rather delicate -- the - # problem is that it's really a directory, but I'm treating it - # as a dumb string, so trailing slashes and so forth matter. - - script.write(",\n".join(map(repr, py_files)) + "]\n") - script.write( - """ -byte_compile(files, optimize=%r, force=%r, - prefix=%r, base_dir=%r, - verbose=%r, dry_run=0, - direct=1) -""" - % (optimize, force, prefix, base_dir, verbose) - ) - - cmd = [sys.executable] - cmd.extend(subprocess._optim_args_from_interpreter_flags()) - cmd.append(script_name) - spawn(cmd, dry_run=dry_run) - execute(os.remove, (script_name,), "removing %s" % script_name, dry_run=dry_run) - - # "Direct" byte-compilation: use the py_compile module to compile - # right here, right now. Note that the script generated in indirect - # mode simply calls 'byte_compile()' in direct mode, a weird sort of - # cross-process recursion. Hey, it works! - else: - from py_compile import compile - - for file in py_files: - if file[-3:] != ".py": - # This lets us be lazy and not filter filenames in - # the "install_lib" command. - continue - - # Terminology from the py_compile module: - # cfile - byte-compiled file - # dfile - purported source filename (same as 'file' by default) - if optimize >= 0: - opt = '' if optimize == 0 else optimize - cfile = importlib.util.cache_from_source(file, optimization=opt) - else: - cfile = importlib.util.cache_from_source(file) - dfile = file - if prefix: - if file[: len(prefix)] != prefix: - raise ValueError( - "invalid prefix: filename %r doesn't start with %r" - % (file, prefix) - ) - dfile = dfile[len(prefix) :] - if base_dir: - dfile = os.path.join(base_dir, dfile) - - cfile_base = os.path.basename(cfile) - if direct: - if force or newer(file, cfile): - log.info("byte-compiling %s to %s", file, cfile_base) - if not dry_run: - compile(file, cfile, dfile) - else: - log.debug("skipping byte-compilation of %s to %s", file, cfile_base) - - -def rfc822_escape(header): - """Return a version of the string escaped for inclusion in an - RFC-822 header, by ensuring there are 8 spaces space after each newline. - """ - lines = header.split('\n') - sep = '\n' + 8 * ' ' - return sep.join(lines) diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/version.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/version.py deleted file mode 100755 index e29e265..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/version.py +++ /dev/null @@ -1,358 +0,0 @@ -# -# distutils/version.py -# -# Implements multiple version numbering conventions for the -# Python Module Distribution Utilities. -# -# $Id$ -# - -"""Provides classes to represent module version numbers (one class for -each style of version numbering). There are currently two such classes -implemented: StrictVersion and LooseVersion. - -Every version number class implements the following interface: - * the 'parse' method takes a string and parses it to some internal - representation; if the string is an invalid version number, - 'parse' raises a ValueError exception - * the class constructor takes an optional string argument which, - if supplied, is passed to 'parse' - * __str__ reconstructs the string that was passed to 'parse' (or - an equivalent string -- ie. one that will generate an equivalent - version number instance) - * __repr__ generates Python code to recreate the version number instance - * _cmp compares the current instance with either another instance - of the same class or a string (which will be parsed to an instance - of the same class, thus must follow the same rules) -""" - -import re -import warnings -import contextlib - - -@contextlib.contextmanager -def suppress_known_deprecation(): - with warnings.catch_warnings(record=True) as ctx: - warnings.filterwarnings( - action='default', - category=DeprecationWarning, - message="distutils Version classes are deprecated.", - ) - yield ctx - - -class Version: - """Abstract base class for version numbering classes. Just provides - constructor (__init__) and reproducer (__repr__), because those - seem to be the same for all version numbering classes; and route - rich comparisons to _cmp. - """ - - def __init__(self, vstring=None): - if vstring: - self.parse(vstring) - warnings.warn( - "distutils Version classes are deprecated. " - "Use packaging.version instead.", - DeprecationWarning, - stacklevel=2, - ) - - def __repr__(self): - return "{} ('{}')".format(self.__class__.__name__, str(self)) - - def __eq__(self, other): - c = self._cmp(other) - if c is NotImplemented: - return c - return c == 0 - - def __lt__(self, other): - c = self._cmp(other) - if c is NotImplemented: - return c - return c < 0 - - def __le__(self, other): - c = self._cmp(other) - if c is NotImplemented: - return c - return c <= 0 - - def __gt__(self, other): - c = self._cmp(other) - if c is NotImplemented: - return c - return c > 0 - - def __ge__(self, other): - c = self._cmp(other) - if c is NotImplemented: - return c - return c >= 0 - - -# Interface for version-number classes -- must be implemented -# by the following classes (the concrete ones -- Version should -# be treated as an abstract class). -# __init__ (string) - create and take same action as 'parse' -# (string parameter is optional) -# parse (string) - convert a string representation to whatever -# internal representation is appropriate for -# this style of version numbering -# __str__ (self) - convert back to a string; should be very similar -# (if not identical to) the string supplied to parse -# __repr__ (self) - generate Python code to recreate -# the instance -# _cmp (self, other) - compare two version numbers ('other' may -# be an unparsed version string, or another -# instance of your version class) - - -class StrictVersion(Version): - - """Version numbering for anal retentives and software idealists. - Implements the standard interface for version number classes as - described above. A version number consists of two or three - dot-separated numeric components, with an optional "pre-release" tag - on the end. The pre-release tag consists of the letter 'a' or 'b' - followed by a number. If the numeric components of two version - numbers are equal, then one with a pre-release tag will always - be deemed earlier (lesser) than one without. - - The following are valid version numbers (shown in the order that - would be obtained by sorting according to the supplied cmp function): - - 0.4 0.4.0 (these two are equivalent) - 0.4.1 - 0.5a1 - 0.5b3 - 0.5 - 0.9.6 - 1.0 - 1.0.4a3 - 1.0.4b1 - 1.0.4 - - The following are examples of invalid version numbers: - - 1 - 2.7.2.2 - 1.3.a4 - 1.3pl1 - 1.3c4 - - The rationale for this version numbering system will be explained - in the distutils documentation. - """ - - version_re = re.compile( - r'^(\d+) \. (\d+) (\. (\d+))? ([ab](\d+))?$', re.VERBOSE | re.ASCII - ) - - def parse(self, vstring): - match = self.version_re.match(vstring) - if not match: - raise ValueError("invalid version number '%s'" % vstring) - - (major, minor, patch, prerelease, prerelease_num) = match.group(1, 2, 4, 5, 6) - - if patch: - self.version = tuple(map(int, [major, minor, patch])) - else: - self.version = tuple(map(int, [major, minor])) + (0,) - - if prerelease: - self.prerelease = (prerelease[0], int(prerelease_num)) - else: - self.prerelease = None - - def __str__(self): - - if self.version[2] == 0: - vstring = '.'.join(map(str, self.version[0:2])) - else: - vstring = '.'.join(map(str, self.version)) - - if self.prerelease: - vstring = vstring + self.prerelease[0] + str(self.prerelease[1]) - - return vstring - - def _cmp(self, other): # noqa: C901 - if isinstance(other, str): - with suppress_known_deprecation(): - other = StrictVersion(other) - elif not isinstance(other, StrictVersion): - return NotImplemented - - if self.version != other.version: - # numeric versions don't match - # prerelease stuff doesn't matter - if self.version < other.version: - return -1 - else: - return 1 - - # have to compare prerelease - # case 1: neither has prerelease; they're equal - # case 2: self has prerelease, other doesn't; other is greater - # case 3: self doesn't have prerelease, other does: self is greater - # case 4: both have prerelease: must compare them! - - if not self.prerelease and not other.prerelease: - return 0 - elif self.prerelease and not other.prerelease: - return -1 - elif not self.prerelease and other.prerelease: - return 1 - elif self.prerelease and other.prerelease: - if self.prerelease == other.prerelease: - return 0 - elif self.prerelease < other.prerelease: - return -1 - else: - return 1 - else: - assert False, "never get here" - - -# end class StrictVersion - - -# The rules according to Greg Stein: -# 1) a version number has 1 or more numbers separated by a period or by -# sequences of letters. If only periods, then these are compared -# left-to-right to determine an ordering. -# 2) sequences of letters are part of the tuple for comparison and are -# compared lexicographically -# 3) recognize the numeric components may have leading zeroes -# -# The LooseVersion class below implements these rules: a version number -# string is split up into a tuple of integer and string components, and -# comparison is a simple tuple comparison. This means that version -# numbers behave in a predictable and obvious way, but a way that might -# not necessarily be how people *want* version numbers to behave. There -# wouldn't be a problem if people could stick to purely numeric version -# numbers: just split on period and compare the numbers as tuples. -# However, people insist on putting letters into their version numbers; -# the most common purpose seems to be: -# - indicating a "pre-release" version -# ('alpha', 'beta', 'a', 'b', 'pre', 'p') -# - indicating a post-release patch ('p', 'pl', 'patch') -# but of course this can't cover all version number schemes, and there's -# no way to know what a programmer means without asking him. -# -# The problem is what to do with letters (and other non-numeric -# characters) in a version number. The current implementation does the -# obvious and predictable thing: keep them as strings and compare -# lexically within a tuple comparison. This has the desired effect if -# an appended letter sequence implies something "post-release": -# eg. "0.99" < "0.99pl14" < "1.0", and "5.001" < "5.001m" < "5.002". -# -# However, if letters in a version number imply a pre-release version, -# the "obvious" thing isn't correct. Eg. you would expect that -# "1.5.1" < "1.5.2a2" < "1.5.2", but under the tuple/lexical comparison -# implemented here, this just isn't so. -# -# Two possible solutions come to mind. The first is to tie the -# comparison algorithm to a particular set of semantic rules, as has -# been done in the StrictVersion class above. This works great as long -# as everyone can go along with bondage and discipline. Hopefully a -# (large) subset of Python module programmers will agree that the -# particular flavour of bondage and discipline provided by StrictVersion -# provides enough benefit to be worth using, and will submit their -# version numbering scheme to its domination. The free-thinking -# anarchists in the lot will never give in, though, and something needs -# to be done to accommodate them. -# -# Perhaps a "moderately strict" version class could be implemented that -# lets almost anything slide (syntactically), and makes some heuristic -# assumptions about non-digits in version number strings. This could -# sink into special-case-hell, though; if I was as talented and -# idiosyncratic as Larry Wall, I'd go ahead and implement a class that -# somehow knows that "1.2.1" < "1.2.2a2" < "1.2.2" < "1.2.2pl3", and is -# just as happy dealing with things like "2g6" and "1.13++". I don't -# think I'm smart enough to do it right though. -# -# In any case, I've coded the test suite for this module (see -# ../test/test_version.py) specifically to fail on things like comparing -# "1.2a2" and "1.2". That's not because the *code* is doing anything -# wrong, it's because the simple, obvious design doesn't match my -# complicated, hairy expectations for real-world version numbers. It -# would be a snap to fix the test suite to say, "Yep, LooseVersion does -# the Right Thing" (ie. the code matches the conception). But I'd rather -# have a conception that matches common notions about version numbers. - - -class LooseVersion(Version): - - """Version numbering for anarchists and software realists. - Implements the standard interface for version number classes as - described above. A version number consists of a series of numbers, - separated by either periods or strings of letters. When comparing - version numbers, the numeric components will be compared - numerically, and the alphabetic components lexically. The following - are all valid version numbers, in no particular order: - - 1.5.1 - 1.5.2b2 - 161 - 3.10a - 8.02 - 3.4j - 1996.07.12 - 3.2.pl0 - 3.1.1.6 - 2g6 - 11g - 0.960923 - 2.2beta29 - 1.13++ - 5.5.kw - 2.0b1pl0 - - In fact, there is no such thing as an invalid version number under - this scheme; the rules for comparison are simple and predictable, - but may not always give the results you want (for some definition - of "want"). - """ - - component_re = re.compile(r'(\d+ | [a-z]+ | \.)', re.VERBOSE) - - def parse(self, vstring): - # I've given up on thinking I can reconstruct the version string - # from the parsed tuple -- so I just store the string here for - # use by __str__ - self.vstring = vstring - components = [x for x in self.component_re.split(vstring) if x and x != '.'] - for i, obj in enumerate(components): - try: - components[i] = int(obj) - except ValueError: - pass - - self.version = components - - def __str__(self): - return self.vstring - - def __repr__(self): - return "LooseVersion ('%s')" % str(self) - - def _cmp(self, other): - if isinstance(other, str): - other = LooseVersion(other) - elif not isinstance(other, LooseVersion): - return NotImplemented - - if self.version == other.version: - return 0 - if self.version < other.version: - return -1 - if self.version > other.version: - return 1 - - -# end class LooseVersion diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/versionpredicate.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/versionpredicate.py deleted file mode 100755 index d6c0c00..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/versionpredicate.py +++ /dev/null @@ -1,175 +0,0 @@ -"""Module for parsing and testing package version predicate strings. -""" -import re -from . import version -import operator - - -re_validPackage = re.compile(r"(?i)^\s*([a-z_]\w*(?:\.[a-z_]\w*)*)(.*)", re.ASCII) -# (package) (rest) - -re_paren = re.compile(r"^\s*\((.*)\)\s*$") # (list) inside of parentheses -re_splitComparison = re.compile(r"^\s*(<=|>=|<|>|!=|==)\s*([^\s,]+)\s*$") -# (comp) (version) - - -def splitUp(pred): - """Parse a single version comparison. - - Return (comparison string, StrictVersion) - """ - res = re_splitComparison.match(pred) - if not res: - raise ValueError("bad package restriction syntax: %r" % pred) - comp, verStr = res.groups() - with version.suppress_known_deprecation(): - other = version.StrictVersion(verStr) - return (comp, other) - - -compmap = { - "<": operator.lt, - "<=": operator.le, - "==": operator.eq, - ">": operator.gt, - ">=": operator.ge, - "!=": operator.ne, -} - - -class VersionPredicate: - """Parse and test package version predicates. - - >>> v = VersionPredicate('pyepat.abc (>1.0, <3333.3a1, !=1555.1b3)') - - The `name` attribute provides the full dotted name that is given:: - - >>> v.name - 'pyepat.abc' - - The str() of a `VersionPredicate` provides a normalized - human-readable version of the expression:: - - >>> print(v) - pyepat.abc (> 1.0, < 3333.3a1, != 1555.1b3) - - The `satisfied_by()` method can be used to determine with a given - version number is included in the set described by the version - restrictions:: - - >>> v.satisfied_by('1.1') - True - >>> v.satisfied_by('1.4') - True - >>> v.satisfied_by('1.0') - False - >>> v.satisfied_by('4444.4') - False - >>> v.satisfied_by('1555.1b3') - False - - `VersionPredicate` is flexible in accepting extra whitespace:: - - >>> v = VersionPredicate(' pat( == 0.1 ) ') - >>> v.name - 'pat' - >>> v.satisfied_by('0.1') - True - >>> v.satisfied_by('0.2') - False - - If any version numbers passed in do not conform to the - restrictions of `StrictVersion`, a `ValueError` is raised:: - - >>> v = VersionPredicate('p1.p2.p3.p4(>=1.0, <=1.3a1, !=1.2zb3)') - Traceback (most recent call last): - ... - ValueError: invalid version number '1.2zb3' - - It the module or package name given does not conform to what's - allowed as a legal module or package name, `ValueError` is - raised:: - - >>> v = VersionPredicate('foo-bar') - Traceback (most recent call last): - ... - ValueError: expected parenthesized list: '-bar' - - >>> v = VersionPredicate('foo bar (12.21)') - Traceback (most recent call last): - ... - ValueError: expected parenthesized list: 'bar (12.21)' - - """ - - def __init__(self, versionPredicateStr): - """Parse a version predicate string.""" - # Fields: - # name: package name - # pred: list of (comparison string, StrictVersion) - - versionPredicateStr = versionPredicateStr.strip() - if not versionPredicateStr: - raise ValueError("empty package restriction") - match = re_validPackage.match(versionPredicateStr) - if not match: - raise ValueError("bad package name in %r" % versionPredicateStr) - self.name, paren = match.groups() - paren = paren.strip() - if paren: - match = re_paren.match(paren) - if not match: - raise ValueError("expected parenthesized list: %r" % paren) - str = match.groups()[0] - self.pred = [splitUp(aPred) for aPred in str.split(",")] - if not self.pred: - raise ValueError("empty parenthesized list in %r" % versionPredicateStr) - else: - self.pred = [] - - def __str__(self): - if self.pred: - seq = [cond + " " + str(ver) for cond, ver in self.pred] - return self.name + " (" + ", ".join(seq) + ")" - else: - return self.name - - def satisfied_by(self, version): - """True if version is compatible with all the predicates in self. - The parameter version must be acceptable to the StrictVersion - constructor. It may be either a string or StrictVersion. - """ - for cond, ver in self.pred: - if not compmap[cond](version, ver): - return False - return True - - -_provision_rx = None - - -def split_provision(value): - """Return the name and optional version number of a provision. - - The version number, if given, will be returned as a `StrictVersion` - instance, otherwise it will be `None`. - - >>> split_provision('mypkg') - ('mypkg', None) - >>> split_provision(' mypkg( 1.2 ) ') - ('mypkg', StrictVersion ('1.2')) - """ - global _provision_rx - if _provision_rx is None: - _provision_rx = re.compile( - r"([a-zA-Z_]\w*(?:\.[a-zA-Z_]\w*)*)(?:\s*\(\s*([^)\s]+)\s*\))?$", re.ASCII - ) - value = value.strip() - m = _provision_rx.match(value) - if not m: - raise ValueError("illegal provides specification: %r" % value) - ver = m.group(2) or None - if ver: - with version.suppress_known_deprecation(): - ver = version.StrictVersion(ver) - return m.group(1), ver diff --git a/venv/lib/python3.11/site-packages/setuptools/_entry_points.py b/venv/lib/python3.11/site-packages/setuptools/_entry_points.py deleted file mode 100755 index a234634..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_entry_points.py +++ /dev/null @@ -1,94 +0,0 @@ -import functools -import operator -import itertools - -from .errors import OptionError -from .extern.jaraco.text import yield_lines -from .extern.jaraco.functools import pass_none -from ._importlib import metadata -from ._itertools import ensure_unique -from .extern.more_itertools import consume - - -def ensure_valid(ep): - """ - Exercise one of the dynamic properties to trigger - the pattern match. - """ - try: - ep.extras - except AttributeError as ex: - msg = ( - f"Problems to parse {ep}.\nPlease ensure entry-point follows the spec: " - "https://packaging.python.org/en/latest/specifications/entry-points/" - ) - raise OptionError(msg) from ex - - -def load_group(value, group): - """ - Given a value of an entry point or series of entry points, - return each as an EntryPoint. - """ - # normalize to a single sequence of lines - lines = yield_lines(value) - text = f'[{group}]\n' + '\n'.join(lines) - return metadata.EntryPoints._from_text(text) - - -def by_group_and_name(ep): - return ep.group, ep.name - - -def validate(eps: metadata.EntryPoints): - """ - Ensure entry points are unique by group and name and validate each. - """ - consume(map(ensure_valid, ensure_unique(eps, key=by_group_and_name))) - return eps - - -@functools.singledispatch -def load(eps): - """ - Given a Distribution.entry_points, produce EntryPoints. - """ - groups = itertools.chain.from_iterable( - load_group(value, group) - for group, value in eps.items()) - return validate(metadata.EntryPoints(groups)) - - -@load.register(str) -def _(eps): - r""" - >>> ep, = load('[console_scripts]\nfoo=bar') - >>> ep.group - 'console_scripts' - >>> ep.name - 'foo' - >>> ep.value - 'bar' - """ - return validate(metadata.EntryPoints(metadata.EntryPoints._from_text(eps))) - - -load.register(type(None), lambda x: x) - - -@pass_none -def render(eps: metadata.EntryPoints): - by_group = operator.attrgetter('group') - groups = itertools.groupby(sorted(eps, key=by_group), by_group) - - return '\n'.join( - f'[{group}]\n{render_items(items)}\n' - for group, items in groups - ) - - -def render_items(eps): - return '\n'.join( - f'{ep.name} = {ep.value}' - for ep in sorted(eps) - ) diff --git a/venv/lib/python3.11/site-packages/setuptools/_imp.py b/venv/lib/python3.11/site-packages/setuptools/_imp.py deleted file mode 100755 index 47efd79..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_imp.py +++ /dev/null @@ -1,82 +0,0 @@ -""" -Re-implementation of find_module and get_frozen_object -from the deprecated imp module. -""" - -import os -import importlib.util -import importlib.machinery - -from .py34compat import module_from_spec - - -PY_SOURCE = 1 -PY_COMPILED = 2 -C_EXTENSION = 3 -C_BUILTIN = 6 -PY_FROZEN = 7 - - -def find_spec(module, paths): - finder = ( - importlib.machinery.PathFinder().find_spec - if isinstance(paths, list) else - importlib.util.find_spec - ) - return finder(module, paths) - - -def find_module(module, paths=None): - """Just like 'imp.find_module()', but with package support""" - spec = find_spec(module, paths) - if spec is None: - raise ImportError("Can't find %s" % module) - if not spec.has_location and hasattr(spec, 'submodule_search_locations'): - spec = importlib.util.spec_from_loader('__init__.py', spec.loader) - - kind = -1 - file = None - static = isinstance(spec.loader, type) - if spec.origin == 'frozen' or static and issubclass( - spec.loader, importlib.machinery.FrozenImporter): - kind = PY_FROZEN - path = None # imp compabilty - suffix = mode = '' # imp compatibility - elif spec.origin == 'built-in' or static and issubclass( - spec.loader, importlib.machinery.BuiltinImporter): - kind = C_BUILTIN - path = None # imp compabilty - suffix = mode = '' # imp compatibility - elif spec.has_location: - path = spec.origin - suffix = os.path.splitext(path)[1] - mode = 'r' if suffix in importlib.machinery.SOURCE_SUFFIXES else 'rb' - - if suffix in importlib.machinery.SOURCE_SUFFIXES: - kind = PY_SOURCE - elif suffix in importlib.machinery.BYTECODE_SUFFIXES: - kind = PY_COMPILED - elif suffix in importlib.machinery.EXTENSION_SUFFIXES: - kind = C_EXTENSION - - if kind in {PY_SOURCE, PY_COMPILED}: - file = open(path, mode) - else: - path = None - suffix = mode = '' - - return file, path, (suffix, mode, kind) - - -def get_frozen_object(module, paths=None): - spec = find_spec(module, paths) - if not spec: - raise ImportError("Can't find %s" % module) - return spec.loader.get_code(module) - - -def get_module(module, paths, info): - spec = find_spec(module, paths) - if not spec: - raise ImportError("Can't find %s" % module) - return module_from_spec(spec) diff --git a/venv/lib/python3.11/site-packages/setuptools/_importlib.py b/venv/lib/python3.11/site-packages/setuptools/_importlib.py deleted file mode 100755 index 819bf5d..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_importlib.py +++ /dev/null @@ -1,47 +0,0 @@ -import sys - - -def disable_importlib_metadata_finder(metadata): - """ - Ensure importlib_metadata doesn't provide older, incompatible - Distributions. - - Workaround for #3102. - """ - try: - import importlib_metadata - except ImportError: - return - except AttributeError: - import warnings - - msg = ( - "`importlib-metadata` version is incompatible with `setuptools`.\n" - "This problem is likely to be solved by installing an updated version of " - "`importlib-metadata`." - ) - warnings.warn(msg) # Ensure a descriptive message is shown. - raise # This exception can be suppressed by _distutils_hack - - if importlib_metadata is metadata: - return - to_remove = [ - ob - for ob in sys.meta_path - if isinstance(ob, importlib_metadata.MetadataPathFinder) - ] - for item in to_remove: - sys.meta_path.remove(item) - - -if sys.version_info < (3, 10): - from setuptools.extern import importlib_metadata as metadata - disable_importlib_metadata_finder(metadata) -else: - import importlib.metadata as metadata # noqa: F401 - - -if sys.version_info < (3, 9): - from setuptools.extern import importlib_resources as resources -else: - import importlib.resources as resources # noqa: F401 diff --git a/venv/lib/python3.11/site-packages/setuptools/_itertools.py b/venv/lib/python3.11/site-packages/setuptools/_itertools.py deleted file mode 100755 index b8bf6d2..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_itertools.py +++ /dev/null @@ -1,23 +0,0 @@ -from setuptools.extern.more_itertools import consume # noqa: F401 - - -# copied from jaraco.itertools 6.1 -def ensure_unique(iterable, key=lambda x: x): - """ - Wrap an iterable to raise a ValueError if non-unique values are encountered. - - >>> list(ensure_unique('abc')) - ['a', 'b', 'c'] - >>> consume(ensure_unique('abca')) - Traceback (most recent call last): - ... - ValueError: Duplicate element 'a' encountered. - """ - seen = set() - seen_add = seen.add - for element in iterable: - k = key(element) - if k in seen: - raise ValueError(f"Duplicate element {element!r} encountered.") - seen_add(k) - yield element diff --git a/venv/lib/python3.11/site-packages/setuptools/_path.py b/venv/lib/python3.11/site-packages/setuptools/_path.py deleted file mode 100755 index 3767523..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_path.py +++ /dev/null @@ -1,29 +0,0 @@ -import os -from typing import Union - -_Path = Union[str, os.PathLike] - - -def ensure_directory(path): - """Ensure that the parent directory of `path` exists""" - dirname = os.path.dirname(path) - os.makedirs(dirname, exist_ok=True) - - -def same_path(p1: _Path, p2: _Path) -> bool: - """Differs from os.path.samefile because it does not require paths to exist. - Purely string based (no comparison between i-nodes). - >>> same_path("a/b", "./a/b") - True - >>> same_path("a/b", "a/./b") - True - >>> same_path("a/b", "././a/b") - True - >>> same_path("a/b", "./a/b/c/..") - True - >>> same_path("a/b", "../a/b/c") - False - >>> same_path("a", "a/b") - False - """ - return os.path.normpath(p1) == os.path.normpath(p2) diff --git a/venv/lib/python3.11/site-packages/setuptools/_reqs.py b/venv/lib/python3.11/site-packages/setuptools/_reqs.py deleted file mode 100755 index ca72417..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_reqs.py +++ /dev/null @@ -1,19 +0,0 @@ -import setuptools.extern.jaraco.text as text - -from pkg_resources import Requirement - - -def parse_strings(strs): - """ - Yield requirement strings for each specification in `strs`. - - `strs` must be a string, or a (possibly-nested) iterable thereof. - """ - return text.join_continuation(map(text.drop_comment, text.yield_lines(strs))) - - -def parse(strs): - """ - Deprecated drop-in replacement for pkg_resources.parse_requirements. - """ - return map(Requirement, parse_strings(strs)) diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/__init__.py b/venv/lib/python3.11/site-packages/setuptools/_vendor/__init__.py deleted file mode 100755 index e69de29..0000000 diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_vendor/__pycache__/__init__.cpython-311.pyc deleted file mode 100755 index d552bd3b2de3f1d4d66a94ff2528de0d5d6d2e23..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 195 zcmZ3^%ge<81Xrfa$^y}kK?DpiLK&agfQ;!3DGb33nv8xc8H$*I{LdiCUt#(g`MIh3 zxrs%|`TAb@>G{U`i3J7vWvO{(`Z<|N`URCG8Tom}dWMGj#hE3kx&?{J*@@|?#rnmm zC8Y%=`T04;`td;3DfvbE@$s2?nI-Y@dIgogIBatBQ%ZAE?TT1|)_@#R%nu|!Ff%eT MeqewRMa)1k02^E~T>t<8 diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/__pycache__/ordered_set.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_vendor/__pycache__/ordered_set.cpython-311.pyc deleted file mode 100755 index 42d9d5ce52be36553c81f3b20416bed71f616ed9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21781 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 IX@}?k0ySAU`v3p{ diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/__pycache__/typing_extensions.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_vendor/__pycache__/typing_extensions.cpython-311.pyc deleted file mode 100755 index d37c462b90d6f6d334130948b573d4569babacb9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 107612 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 A B C D - # unique_everseen('ABBCcAD', str.lower) --> A B C D - seen = set() - seen_add = seen.add - if key is None: - for element in filterfalse(seen.__contains__, iterable): - seen_add(element) - yield element - else: - for element in iterable: - k = key(element) - if k not in seen: - seen_add(k) - yield element - - -# copied from more_itertools 8.8 -def always_iterable(obj, base_type=(str, bytes)): - """If *obj* is iterable, return an iterator over its items:: - - >>> obj = (1, 2, 3) - >>> list(always_iterable(obj)) - [1, 2, 3] - - If *obj* is not iterable, return a one-item iterable containing *obj*:: - - >>> obj = 1 - >>> list(always_iterable(obj)) - [1] - - If *obj* is ``None``, return an empty iterable: - - >>> obj = None - >>> list(always_iterable(None)) - [] - - By default, binary and text strings are not considered iterable:: - - >>> obj = 'foo' - >>> list(always_iterable(obj)) - ['foo'] - - If *base_type* is set, objects for which ``isinstance(obj, base_type)`` - returns ``True`` won't be considered iterable. - - >>> obj = {'a': 1} - >>> list(always_iterable(obj)) # Iterate over the dict's keys - ['a'] - >>> list(always_iterable(obj, base_type=dict)) # Treat dicts as a unit - [{'a': 1}] - - Set *base_type* to ``None`` to avoid any special handling and treat objects - Python considers iterable as iterable: - - >>> obj = 'foo' - >>> list(always_iterable(obj, base_type=None)) - ['f', 'o', 'o'] - """ - if obj is None: - return iter(()) - - if (base_type is not None) and isinstance(obj, base_type): - return iter((obj,)) - - try: - return iter(obj) - except TypeError: - return iter((obj,)) diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_metadata/_meta.py b/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_metadata/_meta.py deleted file mode 100755 index 37ee43e..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_metadata/_meta.py +++ /dev/null @@ -1,48 +0,0 @@ -from ._compat import Protocol -from typing import Any, Dict, Iterator, List, TypeVar, Union - - -_T = TypeVar("_T") - - -class PackageMetadata(Protocol): - def __len__(self) -> int: - ... # pragma: no cover - - def __contains__(self, item: str) -> bool: - ... # pragma: no cover - - def __getitem__(self, key: str) -> str: - ... # pragma: no cover - - def __iter__(self) -> Iterator[str]: - ... # pragma: no cover - - def get_all(self, name: str, failobj: _T = ...) -> Union[List[Any], _T]: - """ - Return all values associated with a possibly multi-valued key. - """ - - @property - def json(self) -> Dict[str, Union[str, List[str]]]: - """ - A JSON-compatible form of the metadata. - """ - - -class SimplePath(Protocol): - """ - A minimal subset of pathlib.Path required by PathDistribution. - """ - - def joinpath(self) -> 'SimplePath': - ... # pragma: no cover - - def __truediv__(self) -> 'SimplePath': - ... # pragma: no cover - - def parent(self) -> 'SimplePath': - ... # pragma: no cover - - def read_text(self) -> str: - ... # pragma: no cover diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_metadata/_text.py b/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_metadata/_text.py deleted file mode 100755 index c88cfbb..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_metadata/_text.py +++ /dev/null @@ -1,99 +0,0 @@ -import re - -from ._functools import method_cache - - -# from jaraco.text 3.5 -class FoldedCase(str): - """ - A case insensitive string class; behaves just like str - except compares equal when the only variation is case. - - >>> s = FoldedCase('hello world') - - >>> s == 'Hello World' - True - - >>> 'Hello World' == s - True - - >>> s != 'Hello World' - False - - >>> s.index('O') - 4 - - >>> s.split('O') - ['hell', ' w', 'rld'] - - >>> sorted(map(FoldedCase, ['GAMMA', 'alpha', 'Beta'])) - ['alpha', 'Beta', 'GAMMA'] - - Sequence membership is straightforward. - - >>> "Hello World" in [s] - True - >>> s in ["Hello World"] - True - - You may test for set inclusion, but candidate and elements - must both be folded. - - >>> FoldedCase("Hello World") in {s} - True - >>> s in {FoldedCase("Hello World")} - True - - String inclusion works as long as the FoldedCase object - is on the right. - - >>> "hello" in FoldedCase("Hello World") - True - - But not if the FoldedCase object is on the left: - - >>> FoldedCase('hello') in 'Hello World' - False - - In that case, use in_: - - >>> FoldedCase('hello').in_('Hello World') - True - - >>> FoldedCase('hello') > FoldedCase('Hello') - False - """ - - def __lt__(self, other): - return self.lower() < other.lower() - - def __gt__(self, other): - return self.lower() > other.lower() - - def __eq__(self, other): - return self.lower() == other.lower() - - def __ne__(self, other): - return self.lower() != other.lower() - - def __hash__(self): - return hash(self.lower()) - - def __contains__(self, other): - return super().lower().__contains__(other.lower()) - - def in_(self, other): - "Does self appear in other?" - return self in FoldedCase(other) - - # cache lower since it's likely to be called frequently. - @method_cache - def lower(self): - return super().lower() - - def index(self, sub): - return self.lower().index(sub.lower()) - - def split(self, splitter=' ', maxsplit=0): - pattern = re.compile(re.escape(splitter), re.I) - return pattern.split(self, maxsplit) diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/__init__.py b/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/__init__.py deleted file mode 100755 index 34e3a99..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/__init__.py +++ /dev/null @@ -1,36 +0,0 @@ -"""Read resources contained within a package.""" - -from ._common import ( - as_file, - files, - Package, -) - -from ._legacy import ( - contents, - open_binary, - read_binary, - open_text, - read_text, - is_resource, - path, - Resource, -) - -from .abc import ResourceReader - - -__all__ = [ - 'Package', - 'Resource', - 'ResourceReader', - 'as_file', - 'contents', - 'files', - 'is_resource', - 'open_binary', - 'open_text', - 'path', - 'read_binary', - 'read_text', -] diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/__pycache__/__init__.cpython-311.pyc deleted file mode 100755 index bba22a219ec955a5381e6434bf0fc6d79137b460..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 829 zcmcJMF^|(Q6vyo*ZIY(Bg8>-H8YJpF-HP}C3Y7t2jd>m!aM+dU`~9|8%9kp=Np zm~LP|UYXb`-PQ@ev_-58IMGkf&wl^+&&!vhn4+-0fB1B@!wCI^&2fzm!7UBJN7NvS z8r+OptVVRCA{wcf#u#!@J601qQ3*{{N>i25Oik%j{*S+Z2LU!D2d~QOM<0czUoOtVeHspsemzEt}__*h8<WE6uQz+qL23{f^gw0bV^9VgKH`gd@B-SrZ5jKDZo>iEU6GYmf+%ikO`hqcz978s z$+hUNNh=qm-?)|TF6QUw#7ZX~9|mrT6>i--ty@c2xZP+&r0TVCq3X}H!WomDbd1gW z%`SbSbhB>7Q}ZCShCgP%1#BaX@eg!%gU+^bj7MAaFPLRe@qck2;qnGO{QKQbiahi^ M;(Y>-xfed?HzJMLzW@LL diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/__pycache__/_adapters.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/__pycache__/_adapters.cpython-311.pyc deleted file mode 100755 index 492b3d6a5ca149480107455f6a51f9ad7388c15e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10746 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 R+MC>Td&T$A&lz&|`(Ghe@1Otx diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/__pycache__/_common.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/__pycache__/_common.cpython-311.pyc deleted file mode 100755 index e42ff6e49e51b24dec2248b075686b703b819c88..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4273 zcmb7H>uVgz5$~Rv)jnpQUP+c^>oiERoei=!=a-b&Rydtsxi~r_D>-{Fu#9#_(#pFt zOV3EM#roI_Cg_4g^ub`~VK9L>XMA4+A&?K}`v+!^fm;RyhH#Mkwm}Jq`;_XQozd=E zmq*V`^`pA0yQ`~zRrAMKEP^1}4}Y`rCn)`mR=mWw3OiRZLXVJw6kI|%H^({5>RgUv zIiKTMF60E32XXJV+b771WUJ*)>vX~Rg(Oi_(1Ep9wo{M9ohSb1H z!drlvT;vXU6_iUUJ@--WfD#0nRzg5~l`zmgB?7cx6;=*me?hKNWnKyCixW|I-B8~z>l?} zt~sH1D<6sog{FosB;IMHCP|sI2Dl~T~SR*mfEJ4NNZWrBGJphtH_1h@{-DW z!?L5aIp1n@#3j}ADzNBatKFc>lD;lxm-VumEz6{!XW!A6^ix^6Qpv8V+FG_$T*y}L zn#;O&YU0f|vqsTWPk5uVhH9=>OkFP-**x@CbdoKWD>^Y@RNh-4@CtgltZNgMyG~%S zSW*oVhj~-*8G}G-=wA^O9e5%>y;2_-w+F`S;t5+kVF@R8fQ$Cms{))ypuZK`g{6DA zL$i2=^Ee7txM!gC7ry52aaFFyDclXjp(VN_rGn)~dP@Wl1KJNsfhisa}>2W1Gf+m;M=RAqR z9vp$1m($}8H0V;nB1jB!LY2q}y-LP;AT`wNMbWe^9jDl&ZyBebXO zXVCh>=Mb)nw6qz7;jOenWwO+5{nXxPGXW=3G>V#G%348n0_NR{YB-S}>B?$Jorj7O z_HE3Gxy5{$alx{Mf~+a7Su+JWL8|u>Tv!RF{5E_BB{lSAdg!t8hfDU@>3aH%ojzlU zH#bjjp8o51?Q?V1jrZ#3ZrbN=TEfl$ppps*>Q+go`E;9PCwEU}wFB)6s-oY5X+GgP zd;bhqDPZv%AI{6SRWP;IEtIIGNIH>R9Z34Zidq1$&=i0O-(+3pM8q{^xoCg{O;Ya^ zR0em{f~jScxduJEk&?PO8G&h-gg`0Ips~8(&X_k;K$YcuNiWD0 zR}Cjj&+rl~UZd564N4Qe%>Ws6WIlw{#Erhx!XL{akK)_OfLY$t|mSGR-7t$})Q z(5CMhD|lf$e(>?6HPCwN@hLk#Wre01V!HP3>jz2gn%VZxq43`h5-`HY@Tb0Y!$3cM zGm22OdForeKL84yK8fM|g?6;*g#6agF2Z5c!&)i==I)&g8N6Ck}H+y#d|TB3MM z`hj$!2gDeNP;!p4&H{05miR-V+aGbqGkzWrLm!xHH$EIpMrFFF6B@OYj;01oC%y zm~HkRvD2d;pS98_>*K*eh$c5LZeDEi(7Fq$8Q6dHHx2a%?(Q0Mu<<8DZza%Q`eu%! zPZRxb9pyhgItb;LsCT9xz3h+7jPWl=F{Q`x+j0J7rgvsqczJ=9rz3BR!Oub*w0{=C zv@G&a-rv7Z!Cc)K*mg(T{5#xMxSx9-9#D(hSY_yQg(1>@pf$edjAYaIQ4le)anukb z-3_j&rzlC(@+9LfH9V=PfdeY&nyKC~rLwF+luKMkM7{;9&hX4soCuAN@(XuOh%YJV zfjJAz!dQ^oiUwpOPel_NmfwQUpuZT*u|)eIRLWC~v&6}|IBAQMmN5Cc*PzlEt{s4a zi)&Tn-gEXx!EH>kJzZ3nR81wasY(m#vb*01(urA{;j%-=QMtrU?ya+1}XUeH}XQ z#uU@!Dlq6d7;8Y`#$en);Tn4yC|+Yv10`zgX`rO#y$zJIytjd(HTJZ3c!fr+{oV!| zxAuEqp*O6~_f;gZ6|j@i(@`sV)Q%jh1)DtqJkdlxNyhO|6ZvF>!?$n~wb4iz_coDF z27-97iG0$FxTp;+ToMEBc;p{E;tu=G#}Fsl_)wDz;3+!u6lD+kElI?Mzrd-_acb-M h!|^&Ew()QS!w8Tn;6xJv@dVOb0)A8QIE>BC<=>6v$6){f diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/__pycache__/_compat.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/__pycache__/_compat.cpython-311.pyc deleted file mode 100755 index e3e4134b02bb9eac68aae31332479805c9aba445..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5558 zcmc&&O>7j&6|U;;>G`)Yws$ZX+`+(l0+|8v7Zd~-2nor`Yc1>#bLq6F+qhw7dQ#oC zv9TpfLBd`k#acl?5hy-H1Oky($sTga!RK6NtckE%LPE-k+aUH}t#ZhF)zjk{Y#*8geXF=eQa&kVH2~kpz^#FW@y{|B~Cg&pgXeJ7EExp8u?I291 zL=Rpgndk*lkjBXs@d6pAoHqo#@k|_eH`aI~&?~vr;`f?~H_8a)XG9NQBYNb%K*%Hb zdnwbZN1^=&?Q8`d94QkHFbCiaUHa1#t%)Fsy zM~v)cZ764CDb)B0^CnSg(9%rbn#2k=<1?jr)|R-EjpH!v(qYY>lRC!`J%-f zkWyjj)+oyYo0_%qMa@YSCs+tN>!XCvfR3HHu4g(IIPehvm7gH<+51dCtp`D z4?xLn&@rw!tTxSvx&XS9jDRj)Bln^9kuO6svMxbgP!E7!Wq0#=ri~fQMkRgXkL@E% z(+xKH&xiu4U)PF`lH*0T;#f+NS!1SdDC#1c$~ZJ*DA1Tv&>VBj;Nt#3bW15%jxu353TQWH zzJ#9&5~gO zOh{;27RXd!j$FcadAbj?d{m!l@hsGfZ>T>4_0k*alTa_ep}uQMSnv(0KLq}My$o!f z(7JSJnw^qk~zB2P!Hm@ z1emC63-a~RH=EEb8h-dSmr}rYFWEF8MQOEcx zV-|D68MF8apR6l;`_PpNTHbi*p^$Zhkhei*Jn%);NwWwxkDHTIZ@}P1!>OCb8h`3& z&dO>z`&g=>ku>(O0Ayu`JZx!nGxK8w~PyO1~&Bic)_txEP^8-whW|eSOI* zYgxlc9ShKBJvHH?X-B;;E?5tA;zmBxa-%h1v(tAg9SN{vTjrKY$Ut?d$AvwjF91n#aaNt4-C$G&6@z$@?SX)us+(XZL`tF(D^898Llp zw%ok>Byngdap-I3n~8Fwzmn)jJopT_vVI=%aFXM}FKMh@o3G*FZOj}Gw|e@ixJae` zKyWccfi@WsGzfE*9 zlsorSI`_<;dAfDS!e!5 zLp3L^?vYnDSZM1d4j$vR1o00Bl}(bbTkH+52XlbHYMB{_@+y_ng?=>$!&G zSayTxq(S_^a1^Wyh#NjXQLLF?*|=ibj_pRy!0LGxI4SXU0&A_ zx4&?w-+AF0S~(6K*q4F8vQ-5!-u*PO?dH_N=|7$=CsLI}YF?U`R-U$ZP zc?b7cH*65_L4SMo%d2zKH>QzsFSpOhr9|?Ajr$-T&K z@y~R(m<+hYoAg$w@c_K>6c4v*u?Q;4PKLQsJQKt@cOZKb$vz}#DLCRi&n66?zfyQQ zae_NIY&R55roNxz_!im>Co)VFupR0vt@l(VA&f4~YiLLaNqp1nFYicq!{ylaN^E;Ih@~+S-&Trk zy`$eX%dx&ntgjl!;*BKUHT%(>j=NpuSZ^iPTW!bE56FhDC#}1eT6aG<{rGIT^-!ht zP<2a7IKubwKr)0879QxT>PA$x=1{0^OjUn9s^w}mK~>eQtg5mPU@_bfgr`M=ITIfA zae-JA3C3C8qM>WXkaWY}{v60m{Z|#_KnPR;WCIO!0ls`96S<`-(13zv$_o)buYKVa z$jLyYO4bsuPwZ)p-9{7oasbF`_%ux^graYE_#M11sHJ9G4mMnze9Gh9Q{ZViY&7dA zno_%&P%xNP#!Y8LaaMzVr71?|vQ~iy-N>Hy-2Aj>{c92YxlvFsMDd2L)FYnMIMa$M z?*Xm|M(y>l2fT=wcQVYZyrK=f{R0e^ch5HMmJ zNT9nUZE1X-MLV8EcP&MCEsR$_Jp8XC=gQIZmFW4Bbe^wxvdtB>p{y&~6E;Kt(~V@U zf@5648z3*Tis79Lc*AgiFl@O&h?3BTa_jB}A<7yAbMHz}Ty$k;qG%Q_^7|n-dY0cL z@oES9~w50k}ktbdcZn4m!a3s!V0x&QzG diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/__pycache__/_itertools.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/__pycache__/_itertools.cpython-311.pyc deleted file mode 100755 index 59472f218776873d19bf5ed4f2be94c71f2a5341..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1391 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 diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/__pycache__/readers.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/__pycache__/readers.cpython-311.pyc deleted file mode 100755 index c5c367001fa691f63bd4e16c2b5ab8a44cf5984a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8364 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 BjjjLy diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/_adapters.py b/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/_adapters.py deleted file mode 100755 index ea363d8..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/_adapters.py +++ /dev/null @@ -1,170 +0,0 @@ -from contextlib import suppress -from io import TextIOWrapper - -from . import abc - - -class SpecLoaderAdapter: - """ - Adapt a package spec to adapt the underlying loader. - """ - - def __init__(self, spec, adapter=lambda spec: spec.loader): - self.spec = spec - self.loader = adapter(spec) - - def __getattr__(self, name): - return getattr(self.spec, name) - - -class TraversableResourcesLoader: - """ - Adapt a loader to provide TraversableResources. - """ - - def __init__(self, spec): - self.spec = spec - - def get_resource_reader(self, name): - return CompatibilityFiles(self.spec)._native() - - -def _io_wrapper(file, mode='r', *args, **kwargs): - if mode == 'r': - return TextIOWrapper(file, *args, **kwargs) - elif mode == 'rb': - return file - raise ValueError( - "Invalid mode value '{}', only 'r' and 'rb' are supported".format(mode) - ) - - -class CompatibilityFiles: - """ - Adapter for an existing or non-existent resource reader - to provide a compatibility .files(). - """ - - class SpecPath(abc.Traversable): - """ - Path tied to a module spec. - Can be read and exposes the resource reader children. - """ - - def __init__(self, spec, reader): - self._spec = spec - self._reader = reader - - def iterdir(self): - if not self._reader: - return iter(()) - return iter( - CompatibilityFiles.ChildPath(self._reader, path) - for path in self._reader.contents() - ) - - def is_file(self): - return False - - is_dir = is_file - - def joinpath(self, other): - if not self._reader: - return CompatibilityFiles.OrphanPath(other) - return CompatibilityFiles.ChildPath(self._reader, other) - - @property - def name(self): - return self._spec.name - - def open(self, mode='r', *args, **kwargs): - return _io_wrapper(self._reader.open_resource(None), mode, *args, **kwargs) - - class ChildPath(abc.Traversable): - """ - Path tied to a resource reader child. - Can be read but doesn't expose any meaningful children. - """ - - def __init__(self, reader, name): - self._reader = reader - self._name = name - - def iterdir(self): - return iter(()) - - def is_file(self): - return self._reader.is_resource(self.name) - - def is_dir(self): - return not self.is_file() - - def joinpath(self, other): - return CompatibilityFiles.OrphanPath(self.name, other) - - @property - def name(self): - return self._name - - def open(self, mode='r', *args, **kwargs): - return _io_wrapper( - self._reader.open_resource(self.name), mode, *args, **kwargs - ) - - class OrphanPath(abc.Traversable): - """ - Orphan path, not tied to a module spec or resource reader. - Can't be read and doesn't expose any meaningful children. - """ - - def __init__(self, *path_parts): - if len(path_parts) < 1: - raise ValueError('Need at least one path part to construct a path') - self._path = path_parts - - def iterdir(self): - return iter(()) - - def is_file(self): - return False - - is_dir = is_file - - def joinpath(self, other): - return CompatibilityFiles.OrphanPath(*self._path, other) - - @property - def name(self): - return self._path[-1] - - def open(self, mode='r', *args, **kwargs): - raise FileNotFoundError("Can't open orphan path") - - def __init__(self, spec): - self.spec = spec - - @property - def _reader(self): - with suppress(AttributeError): - return self.spec.loader.get_resource_reader(self.spec.name) - - def _native(self): - """ - Return the native reader if it supports files(). - """ - reader = self._reader - return reader if hasattr(reader, 'files') else self - - def __getattr__(self, attr): - return getattr(self._reader, attr) - - def files(self): - return CompatibilityFiles.SpecPath(self.spec, self._reader) - - -def wrap_spec(package): - """ - Construct a package spec with traversable compatibility - on the spec/loader/reader. - """ - return SpecLoaderAdapter(package.__spec__, TraversableResourcesLoader) diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/_common.py b/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/_common.py deleted file mode 100755 index a12e2c7..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/_common.py +++ /dev/null @@ -1,104 +0,0 @@ -import os -import pathlib -import tempfile -import functools -import contextlib -import types -import importlib - -from typing import Union, Optional -from .abc import ResourceReader, Traversable - -from ._compat import wrap_spec - -Package = Union[types.ModuleType, str] - - -def files(package): - # type: (Package) -> Traversable - """ - Get a Traversable resource from a package - """ - return from_package(get_package(package)) - - -def get_resource_reader(package): - # type: (types.ModuleType) -> Optional[ResourceReader] - """ - Return the package's loader if it's a ResourceReader. - """ - # We can't use - # a issubclass() check here because apparently abc.'s __subclasscheck__() - # hook wants to create a weak reference to the object, but - # zipimport.zipimporter does not support weak references, resulting in a - # TypeError. That seems terrible. - spec = package.__spec__ - reader = getattr(spec.loader, 'get_resource_reader', None) # type: ignore - if reader is None: - return None - return reader(spec.name) # type: ignore - - -def resolve(cand): - # type: (Package) -> types.ModuleType - return cand if isinstance(cand, types.ModuleType) else importlib.import_module(cand) - - -def get_package(package): - # type: (Package) -> types.ModuleType - """Take a package name or module object and return the module. - - Raise an exception if the resolved module is not a package. - """ - resolved = resolve(package) - if wrap_spec(resolved).submodule_search_locations is None: - raise TypeError(f'{package!r} is not a package') - return resolved - - -def from_package(package): - """ - Return a Traversable object for the given package. - - """ - spec = wrap_spec(package) - reader = spec.loader.get_resource_reader(spec.name) - return reader.files() - - -@contextlib.contextmanager -def _tempfile(reader, suffix=''): - # Not using tempfile.NamedTemporaryFile as it leads to deeper 'try' - # blocks due to the need to close the temporary file to work on Windows - # properly. - fd, raw_path = tempfile.mkstemp(suffix=suffix) - try: - try: - os.write(fd, reader()) - finally: - os.close(fd) - del reader - yield pathlib.Path(raw_path) - finally: - try: - os.remove(raw_path) - except FileNotFoundError: - pass - - -@functools.singledispatch -def as_file(path): - """ - Given a Traversable object, return that object as a - path on the local file system in a context manager. - """ - return _tempfile(path.read_bytes, suffix=path.name) - - -@as_file.register(pathlib.Path) -@contextlib.contextmanager -def _(path): - """ - Degenerate behavior for pathlib.Path objects. - """ - yield path diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/_compat.py b/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/_compat.py deleted file mode 100755 index cb9fc82..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/_compat.py +++ /dev/null @@ -1,98 +0,0 @@ -# flake8: noqa - -import abc -import sys -import pathlib -from contextlib import suppress - -if sys.version_info >= (3, 10): - from zipfile import Path as ZipPath # type: ignore -else: - from ..zipp import Path as ZipPath # type: ignore - - -try: - from typing import runtime_checkable # type: ignore -except ImportError: - - def runtime_checkable(cls): # type: ignore - return cls - - -try: - from typing import Protocol # type: ignore -except ImportError: - Protocol = abc.ABC # type: ignore - - -class TraversableResourcesLoader: - """ - Adapt loaders to provide TraversableResources and other - compatibility. - - Used primarily for Python 3.9 and earlier where the native - loaders do not yet implement TraversableResources. - """ - - def __init__(self, spec): - self.spec = spec - - @property - def path(self): - return self.spec.origin - - def get_resource_reader(self, name): - from . import readers, _adapters - - def _zip_reader(spec): - with suppress(AttributeError): - return readers.ZipReader(spec.loader, spec.name) - - def _namespace_reader(spec): - with suppress(AttributeError, ValueError): - return readers.NamespaceReader(spec.submodule_search_locations) - - def _available_reader(spec): - with suppress(AttributeError): - return spec.loader.get_resource_reader(spec.name) - - def _native_reader(spec): - reader = _available_reader(spec) - return reader if hasattr(reader, 'files') else None - - def _file_reader(spec): - try: - path = pathlib.Path(self.path) - except TypeError: - return None - if path.exists(): - return readers.FileReader(self) - - return ( - # native reader if it supplies 'files' - _native_reader(self.spec) - or - # local ZipReader if a zip module - _zip_reader(self.spec) - or - # local NamespaceReader if a namespace module - _namespace_reader(self.spec) - or - # local FileReader - _file_reader(self.spec) - # fallback - adapt the spec ResourceReader to TraversableReader - or _adapters.CompatibilityFiles(self.spec) - ) - - -def wrap_spec(package): - """ - Construct a package spec with traversable compatibility - on the spec/loader/reader. - - Supersedes _adapters.wrap_spec to use TraversableResourcesLoader - from above for older Python compatibility (<3.10). - """ - from . import _adapters - - return _adapters.SpecLoaderAdapter(package.__spec__, TraversableResourcesLoader) diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/_itertools.py b/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/_itertools.py deleted file mode 100755 index cce0558..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/_itertools.py +++ /dev/null @@ -1,35 +0,0 @@ -from itertools import filterfalse - -from typing import ( - Callable, - Iterable, - Iterator, - Optional, - Set, - TypeVar, - Union, -) - -# Type and type variable definitions -_T = TypeVar('_T') -_U = TypeVar('_U') - - -def unique_everseen( - iterable: Iterable[_T], key: Optional[Callable[[_T], _U]] = None -) -> Iterator[_T]: - "List unique elements, preserving order. Remember all elements ever seen." - # unique_everseen('AAAABBBCCDAABBB') --> A B C D - # unique_everseen('ABBCcAD', str.lower) --> A B C D - seen: Set[Union[_T, _U]] = set() - seen_add = seen.add - if key is None: - for element in filterfalse(seen.__contains__, iterable): - seen_add(element) - yield element - else: - for element in iterable: - k = key(element) - if k not in seen: - seen_add(k) - yield element diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/_legacy.py b/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/_legacy.py deleted file mode 100755 index 1d5d3f1..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/_legacy.py +++ /dev/null @@ -1,121 +0,0 @@ -import functools -import os -import pathlib -import types -import warnings - -from typing import Union, Iterable, ContextManager, BinaryIO, TextIO, Any - -from . import _common - -Package = Union[types.ModuleType, str] -Resource = str - - -def deprecated(func): - @functools.wraps(func) - def wrapper(*args, **kwargs): - warnings.warn( - f"{func.__name__} is deprecated. Use files() instead. " - "Refer to https://importlib-resources.readthedocs.io" - "/en/latest/using.html#migrating-from-legacy for migration advice.", - DeprecationWarning, - stacklevel=2, - ) - return func(*args, **kwargs) - - return wrapper - - -def normalize_path(path): - # type: (Any) -> str - """Normalize a path by ensuring it is a string. - - If the resulting string contains path separators, an exception is raised. - """ - str_path = str(path) - parent, file_name = os.path.split(str_path) - if parent: - raise ValueError(f'{path!r} must be only a file name') - return file_name - - -@deprecated -def open_binary(package: Package, resource: Resource) -> BinaryIO: - """Return a file-like object opened for binary reading of the resource.""" - return (_common.files(package) / normalize_path(resource)).open('rb') - - -@deprecated -def read_binary(package: Package, resource: Resource) -> bytes: - """Return the binary contents of the resource.""" - return (_common.files(package) / normalize_path(resource)).read_bytes() - - -@deprecated -def open_text( - package: Package, - resource: Resource, - encoding: str = 'utf-8', - errors: str = 'strict', -) -> TextIO: - """Return a file-like object opened for text reading of the resource.""" - return (_common.files(package) / normalize_path(resource)).open( - 'r', encoding=encoding, errors=errors - ) - - -@deprecated -def read_text( - package: Package, - resource: Resource, - encoding: str = 'utf-8', - errors: str = 'strict', -) -> str: - """Return the decoded string of the resource. - - The decoding-related arguments have the same semantics as those of - bytes.decode(). - """ - with open_text(package, resource, encoding, errors) as fp: - return fp.read() - - -@deprecated -def contents(package: Package) -> Iterable[str]: - """Return an iterable of entries in `package`. - - Note that not all entries are resources. Specifically, directories are - not considered resources. Use `is_resource()` on each entry returned here - to check if it is a resource or not. - """ - return [path.name for path in _common.files(package).iterdir()] - - -@deprecated -def is_resource(package: Package, name: str) -> bool: - """True if `name` is a resource inside `package`. - - Directories are *not* resources. - """ - resource = normalize_path(name) - return any( - traversable.name == resource and traversable.is_file() - for traversable in _common.files(package).iterdir() - ) - - -@deprecated -def path( - package: Package, - resource: Resource, -) -> ContextManager[pathlib.Path]: - """A context manager providing a file path object to the resource. - - If the resource does not already exist on its own on the file system, - a temporary file will be created. If the file was created, the file - will be deleted upon exiting the context manager (no exception is - raised if the file was deleted prior to the context manager - exiting). - """ - return _common.as_file(_common.files(package) / normalize_path(resource)) diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/abc.py b/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/abc.py deleted file mode 100755 index d39dc1a..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/abc.py +++ /dev/null @@ -1,137 +0,0 @@ -import abc -from typing import BinaryIO, Iterable, Text - -from ._compat import runtime_checkable, Protocol - - -class ResourceReader(metaclass=abc.ABCMeta): - """Abstract base class for loaders to provide resource reading support.""" - - @abc.abstractmethod - def open_resource(self, resource: Text) -> BinaryIO: - """Return an opened, file-like object for binary reading. - - The 'resource' argument is expected to represent only a file name. - If the resource cannot be found, FileNotFoundError is raised. - """ - # This deliberately raises FileNotFoundError instead of - # NotImplementedError so that if this method is accidentally called, - # it'll still do the right thing. - raise FileNotFoundError - - @abc.abstractmethod - def resource_path(self, resource: Text) -> Text: - """Return the file system path to the specified resource. - - The 'resource' argument is expected to represent only a file name. - If the resource does not exist on the file system, raise - FileNotFoundError. - """ - # This deliberately raises FileNotFoundError instead of - # NotImplementedError so that if this method is accidentally called, - # it'll still do the right thing. - raise FileNotFoundError - - @abc.abstractmethod - def is_resource(self, path: Text) -> bool: - """Return True if the named 'path' is a resource. - - Files are resources, directories are not. - """ - raise FileNotFoundError - - @abc.abstractmethod - def contents(self) -> Iterable[str]: - """Return an iterable of entries in `package`.""" - raise FileNotFoundError - - -@runtime_checkable -class Traversable(Protocol): - """ - An object with a subset of pathlib.Path methods suitable for - traversing directories and opening files. - """ - - @abc.abstractmethod - def iterdir(self): - """ - Yield Traversable objects in self - """ - - def read_bytes(self): - """ - Read contents of self as bytes - """ - with self.open('rb') as strm: - return strm.read() - - def read_text(self, encoding=None): - """ - Read contents of self as text - """ - with self.open(encoding=encoding) as strm: - return strm.read() - - @abc.abstractmethod - def is_dir(self) -> bool: - """ - Return True if self is a directory - """ - - @abc.abstractmethod - def is_file(self) -> bool: - """ - Return True if self is a file - """ - - @abc.abstractmethod - def joinpath(self, child): - """ - Return Traversable child in self - """ - - def __truediv__(self, child): - """ - Return Traversable child in self - """ - return self.joinpath(child) - - @abc.abstractmethod - def open(self, mode='r', *args, **kwargs): - """ - mode may be 'r' or 'rb' to open as text or binary. Return a handle - suitable for reading (same as pathlib.Path.open). - - When opening as text, accepts encoding parameters such as those - accepted by io.TextIOWrapper. - """ - - @abc.abstractproperty - def name(self) -> str: - """ - The base name of this object without any parent references. - """ - - -class TraversableResources(ResourceReader): - """ - The required interface for providing traversable - resources. - """ - - @abc.abstractmethod - def files(self): - """Return a Traversable object for the loaded package.""" - - def open_resource(self, resource): - return self.files().joinpath(resource).open('rb') - - def resource_path(self, resource): - raise FileNotFoundError(resource) - - def is_resource(self, path): - return self.files().joinpath(path).is_file() - - def contents(self): - return (item.name for item in self.files().iterdir()) diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/readers.py b/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/readers.py deleted file mode 100755 index f1190ca..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/readers.py +++ /dev/null @@ -1,122 +0,0 @@ -import collections -import pathlib -import operator - -from . import abc - -from ._itertools import unique_everseen -from ._compat import ZipPath - - -def remove_duplicates(items): - return iter(collections.OrderedDict.fromkeys(items)) - - -class FileReader(abc.TraversableResources): - def __init__(self, loader): - self.path = pathlib.Path(loader.path).parent - - def resource_path(self, resource): - """ - Return the file system path to prevent - `resources.path()` from creating a temporary - copy. - """ - return str(self.path.joinpath(resource)) - - def files(self): - return self.path - - -class ZipReader(abc.TraversableResources): - def __init__(self, loader, module): - _, _, name = module.rpartition('.') - self.prefix = loader.prefix.replace('\\', '/') + name + '/' - self.archive = loader.archive - - def open_resource(self, resource): - try: - return super().open_resource(resource) - except KeyError as exc: - raise FileNotFoundError(exc.args[0]) - - def is_resource(self, path): - # workaround for `zipfile.Path.is_file` returning true - # for non-existent paths. - target = self.files().joinpath(path) - return target.is_file() and target.exists() - - def files(self): - return ZipPath(self.archive, self.prefix) - - -class MultiplexedPath(abc.Traversable): - """ - Given a series of Traversable objects, implement a merged - version of the interface across all objects. Useful for - namespace packages which may be multihomed at a single - name. - """ - - def __init__(self, *paths): - self._paths = list(map(pathlib.Path, remove_duplicates(paths))) - if not self._paths: - message = 'MultiplexedPath must contain at least one path' - raise FileNotFoundError(message) - if not all(path.is_dir() for path in self._paths): - raise NotADirectoryError('MultiplexedPath only supports directories') - - def iterdir(self): - files = (file for path in self._paths for file in path.iterdir()) - return unique_everseen(files, key=operator.attrgetter('name')) - - def read_bytes(self): - raise FileNotFoundError(f'{self} is not a file') - - def read_text(self, *args, **kwargs): - raise FileNotFoundError(f'{self} is not a file') - - def is_dir(self): - return True - - def is_file(self): - return False - - def joinpath(self, child): - # first try to find child in current paths - for file in self.iterdir(): - if file.name == child: - return file - # if it does not exist, construct it with the first path - return self._paths[0] / child - - __truediv__ = joinpath - - def open(self, *args, **kwargs): - raise FileNotFoundError(f'{self} is not a file') - - @property - def name(self): - return self._paths[0].name - - def __repr__(self): - paths = ', '.join(f"'{path}'" for path in self._paths) - return f'MultiplexedPath({paths})' - - -class NamespaceReader(abc.TraversableResources): - def __init__(self, namespace_path): - if 'NamespacePath' not in str(namespace_path): - raise ValueError('Invalid path') - self.path = MultiplexedPath(*list(namespace_path)) - - def resource_path(self, resource): - """ - Return the file system path to prevent - `resources.path()` from creating a temporary - copy. - """ - return str(self.path.joinpath(resource)) - - def files(self): - return self.path diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/simple.py b/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/simple.py deleted file mode 100755 index da073cb..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_vendor/importlib_resources/simple.py +++ /dev/null @@ -1,116 +0,0 @@ -""" -Interface adapters for low-level readers. -""" - -import abc -import io -import itertools -from typing import BinaryIO, List - -from .abc import Traversable, TraversableResources - - -class SimpleReader(abc.ABC): - """ - The minimum, low-level interface required from a resource - provider. - """ - - @abc.abstractproperty - def package(self): - # type: () -> str - """ - The name of the package for which this reader loads resources. - """ - - @abc.abstractmethod - def children(self): - # type: () -> List['SimpleReader'] - """ - Obtain an iterable of SimpleReader for available - child containers (e.g. directories). - """ - - @abc.abstractmethod - def resources(self): - # type: () -> List[str] - """ - Obtain available named resources for this virtual package. - """ - - @abc.abstractmethod - def open_binary(self, resource): - # type: (str) -> BinaryIO - """ - Obtain a File-like for a named resource. - """ - - @property - def name(self): - return self.package.split('.')[-1] - - -class ResourceHandle(Traversable): - """ - Handle to a named resource in a ResourceReader. - """ - - def __init__(self, parent, name): - # type: (ResourceContainer, str) -> None - self.parent = parent - self.name = name # type: ignore - - def is_file(self): - return True - - def is_dir(self): - return False - - def open(self, mode='r', *args, **kwargs): - stream = self.parent.reader.open_binary(self.name) - if 'b' not in mode: - stream = io.TextIOWrapper(*args, **kwargs) - return stream - - def joinpath(self, name): - raise RuntimeError("Cannot traverse into a resource") - - -class ResourceContainer(Traversable): - """ - Traversable container for a package's resources via its reader. - """ - - def __init__(self, reader): - # type: (SimpleReader) -> None - self.reader = reader - - def is_dir(self): - return True - - def is_file(self): - return False - - def iterdir(self): - files = (ResourceHandle(self, name) for name in self.reader.resources) - dirs = map(ResourceContainer, self.reader.children()) - return itertools.chain(files, dirs) - - def open(self, *args, **kwargs): - raise IsADirectoryError() - - def joinpath(self, name): - return next( - traversable for traversable in self.iterdir() if traversable.name == name - ) - - -class TraversableReader(TraversableResources, SimpleReader): - """ - A TraversableResources based on SimpleReader. Resource providers - may derive from this class to provide the TraversableResources - interface by supplying the SimpleReader interface. - """ - - def files(self): - return ResourceContainer(self) diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/jaraco/__init__.py b/venv/lib/python3.11/site-packages/setuptools/_vendor/jaraco/__init__.py deleted file mode 100755 index e69de29..0000000 diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/jaraco/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_vendor/jaraco/__pycache__/__init__.cpython-311.pyc deleted file mode 100755 index 9cfc2c4f2d31cff9a4eba354dca963ac518309e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 202 zcmZ3^%ge<81Xrfa$^y}kK?DpiLK&agfQ;!3DGb33nv8xc8H$*I{LdiCU$Ocb`MIh3 zxrs%|`TAb@>G{U`i3J7vWvO{(`Z<|N`URCG8Tom}dWMGj#hE3kx&?{J*@@|?#rnmm zC8Y%=`T04;`td;3DfvbES&2o7KvUx5GxIV_;^XxSDt~d<x%axu=*P SNPJ*sWMurn03(W+fnor{`85Lo diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/jaraco/__pycache__/context.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_vendor/jaraco/__pycache__/context.cpython-311.pyc deleted file mode 100755 index 55532f100d5e09c7b0c1e7a420b98d618ec862d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10977 zcmcIqTWlLwdY&PN10w-;4~_&?-(<+?Qt@5k-p9iSP60O}dg^(F zSH&^E;=jT-;e{393O5pI#8v~7Elx*cyb@T`rnM1U;gz7;ioQc@@Y+0h;u;#;ecTC7 z318uq$ooD}kIPCUQC8D}8XBv^DM!B3$-gh41uiR%bg&j}XwmM$@&gN(jTKY)Gh8D2 zIXw=iF#m1}Ah#XY>c0X!%kfwlS|2A(x_R&X&G8;A_YI2N`)Kij+luGHT#D zxK6`L(y#tta3VLQ4o=BhDmQpKH=cWJP|oKEFRIy#gPHW`V1Cw^$YmcJ7#bSX(}ub? zFQ+cZ%zK&-~$YSDq_9x8m~$dTZ^S2E^X+B! zyZ0ksW5K<9_jKy~1L1Ih`*~p9;Z6RO%MtdVY)$_fuWPMokuRMvQ01ihx-PjZ;ndN+ zc^#KrUTVZre2U-8!4JR_n(^lNqOT+w;d*bA#EC2!txk^P8e~0iGw2;_&gbKbxRlVO z=(JGU(wx!dJaJ9h;V1l$*YHo6Q^Ywz3C{(T$P&|D_10FdC=>%@J};Nf1+B4*!N#$b z7NfV`x_J)M{MVxlBlwF=^zMg*7I{mapn>r7&I!+DTefpUoG#4xEVGedbB_<8WtpjERho~()|E8@voTdaI;;lOg+mTKFU6^;)-!ayyyxzcL? zSNu*XtGY`_U$~g{HcdI$lco~uG026ZWstF_65UZHxF7$YDL2M$j#>F-@rkPVM8)~v z!#n-D=w!o&uznwR9_~FF=RS!Cjy&c6WN$0wpAwEd9s1;HKk}b)Jo2CNEFa%-tku89 zdm+oTItK7AtQIt)?~i?OJ?-T6Qxv}FqkCdy@r*?652-QK6S3y@D(nwML43V zvY}!X3>6AeleO8peQ;Fxfb@c_>%d7(>qc%$($uNkMO9<%VG1a(rLj0X}uhcMBL!=RCkulvD6na1*G$-rJswKT{dzegXX^&%S7@*nLUjVQ))t9YY$NFk? z>vHtbYV^_4Npk--*4o!u-rgNCS`ICU%i@NrxS`_w@0CN%r6fb-`MfK{x$ABF{bxO1 zU=THIfi{D;tp!r}B6pF~d1|jl28-g&khdLt zqJZra1r_|7Yn33e)cw37s!522C5xHJx=Fcd!)Ap%`3X$OR7Dz{m0-vQA`J7?n53w> zkxUtv$h**|^Z86#g)5RaBz+<`odG^^Ws?)(upIMS*dUf!Y~Wd@A;5^t(h@C}u7Day z8>Vk!98paMjzB@&yLVKRv#AM_pBaXu5!4L@*s!-jSW-kL2zc^pmKl7Ff=4r?s28)- znT)m$Pa65DiLj+sf_6`V*Qe8}VT#VHnSS+>YKrgUx&qtx(e0tWzea^9hBtYn$# zR)*`?=p#TlNtmQPTpQiJVe!bqp@l=`o#mZNXG=$F;m-2D{y3+Fxz$ueA2xj;(t~yEb#}jqCp9SbsIv z4~x6`(Mso@h2DkUC8Hd?Eyk+iBa5l)eHC$NSsbd0L&&(Ywi3mdY+wfN5(!@rsFyu3 z$IRx#Q1uwz`<=sEzsvhS=7sMDLLZAfU<##fBD=F4*DB%KQfkM`6bEZ0D;jMCSYVKH z%p(%mS{}pmYq)fZd8{eEBZN!GoS#MwJOeu6-f9^&?{X?fTQAsl;j!i78xhpN7>~^l zY?zD$*%nDi6|oi46iAJPQ5sxR8bN7jO=*jQEs&8`+VB`@Q`?oud%V(e#WxaFT2a!W zv_S;h&9-BgQfi+3^Rt?qmrsCBCN77Yg$QzkC}1X?$w)ANsR=2iYKEN7B4)5VfUeIf z5}ekHq}Jsu>&KR4=KoKqvr;aVn$|Q`u_gMMXP!Zy#)RY{Bc70C1P>tS0PAF6V1Ti^ zCZ~0^jv7y}TIypI-gBH9SVd>GY1L90UvGdsEY^eiJT7PShj;ptoS9aSXE7#%_7C8a=HOSoID&A08e~IeZVUM+D1peq5^*LBMTttB8N;@ zGh^B*pfy@~Q%u4aOB=~#VVz4B@$i6CUZNIl041)raYtF0kCySXM6=QFq&y>wj2(Hi zjq-nk*G^MEgk%Rr;banXgn%nq=xrX^uJ|KhuTnIHp`%^pmbHVrb3q;^4LXUtl@z}2 zNT1Gz_erI68ze;L4ygP)lU#S>erVB$Wpc^(dOLIeqF)O!mL~dGD*C}m-$NELMkK8x zqEA7lbjHfs87dbTbFsX376lYjK(`|3C(=lYEUN=vS1;Y4*RAqD1G>H+fEccKk)OX@ z7HY9|mDr)bIx^DLsac>PFNx zkO|vD(wN5);9y5?9HB33uBa&lU5G)cshmlZvCJ`dIHwuX3v3r%dTij^?%-!;vxa=B zp+_={%$n-b({+PN>NDP8Nd_zwOW6}4!?_uF;B0X6v+G-XJI_l@q2mWYM{;?-l!O188*7F3PmmrjYSIOr9LmMV2ljg?1j7{y9L& z{jK;m1;iDOzyYp9DxJKuy??16$|A6{83g%2HLte6!{7Eb`H+P2OKoZx2RixDu=~yh^4>dpvIq7XRT0__3Vhk1$8!w zeb=1kSY0QyzC8EZu3g_}xMW!y@L1U}bg_na(R2a^foTFwOfXAj1pW(`z6GF>2|~mK z9$?KJHSo-wqaRl-@3V2UB#bW`6cJk_JibxE1_{1U!G;JnO+uK_u-Tf+B0@rNrr~=5 zIf#xJ`7c^0ZIUcuT1IoSrkrw+tT{b1t7C8Z7<}ybP@*2(l8>U~>OD5kn&qdg>9b*D zqLH5XE;jYM67j}96W=TpuTy+L8gkd|e#7A?7l$BE@7ursw>~iXe8A8SA3oq^iN~0u zj9{Hk5D>=4cj5C7IQF{|w%bW8>|Lw+ZUocs-j_{}XLFkRfbq-#n|keKVl_X2lZe&m zd375Ag@BEF5)|+y9WjRA=X!2t5U1pjQ&XU+h4yD^{s-tndjr6GB1B5I(9=k)yG8N8 zgiIU5Q1$Ix?<3fxXsLCt$BliF!o*4Wf5Rrp62zupoN4yLx~7rsEs8JE zf%ZHB7L5zYIf({fgIqy|=7i+kNz=UE(ij3N`~@biINks;o*JKB(_^?Fnb0RL^&<(d zw_Wu8&=X)QeycqMTNpNj*7|Bi5W-YULNGhmaEL~0U`Fb~!PdieBOmBHh+)>!#?t*vwZ zwZ#*++O}8Pw%?9zUOfBWtIM%n)!441Yon6AFt6-GtNjRrj2w)%h5x-jbeY_!M;XdUlp)3Q+%W_ zWoW8u9pN281C6%YE$4#FgxPV#8sexE0<%|cvO~WT4_ThjGun^Ph=fM}CqTq9JYVC& zCHAXvofYTr&39Bd`(NXtCHAXvZ6)?|OE8JP)+)bo#TVq^F95(j@ojQTVper+NBqO? zkIt=d>-i_^ppHt#Pl)_uSP2KLvs?CTy7v7QE{q{uP;W=Y>utnG9=+cE5!N?KggBs% zN+mlSVtGCShlh{UtEohspU|I$hoIdv~e!i#p1> YojiDHEm$~E?HagC6<^$^mT}tu16r;ty#N3J diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/jaraco/__pycache__/functools.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_vendor/jaraco/__pycache__/functools.cpython-311.pyc deleted file mode 100755 index 8c14f6ce53e0a169cec265c58b31e69e041753e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20282 zcmbV!du&@*n%}*Ah@?cBwnf|VGdH$ulCd6^=CA&~@7yOPJ2Sna4)49^ea`p(zQcdn+uJSSYJTu%H~-slN&4UP;9N2L=FvB0 zN%~0ABuy?$6XIK*koh?@5#sOgM3}!L6A}K7PDJ^;Ya)j4P&q!Gm`F@_Pjt&tNYcBt zu%6H&dQUO5+v!dE%jjnzN%|cB;+jZmU3aC4UM+@nixx+kLS5gxcS_9kczUF z(34uXj`X^$C;e?}J$UZYl6RvM+q7P^v|ZbRv`0|`?g&Y*NZPi$lD55L96Pl> zTE?TxO2lz1pl-nk4BMT zH{`q09ofRpIM+@0eoAs7sTP&lifYU& z#o0>1Dpf0{QmR;0MODmF<$77~$Q|nDhR&WntCY}|VJVhAXWcf`8TY+DH=`FUT~o#t z(=vweUz*7}rG_+J(<@fCAVxBj&ui5}KA+3E)wz6Lt!Q~s6wTO$vu<+(Zm)KGkFUO= zCuMwGafZm9UNvTQF)Md@$|e?|T&~_W73+qM1*z!9bk(%nMN+Urmii7>(wHh)2CbiJ zT%VoB)J)$J8MK*s>xQB0m_}Khp3+oh?u^3kvvUJVMJrt|S?2hdH-VyW!oKpwt zL&cGHs5oj8HYiH1_S^3b->6RO!_%r!s1CncyNY*HCB!L2l1z^Jv;uOhy-_wkAD7 z8Oi8Dk_#DI=stzSq!pf=G>F)>d+e^Mr-gk_8plDZx)aG)=(d$QyXODI&lyO2ZUF=-cT(t5ufePLa4lHYVm$sNs}y(_QX z-_ht9ZuShXMTWVR30j8GfDdaFCy~nM?CmK<+Bn?VQZ? zJdrazbNhkih+-8Ok-&YW55pfxev-Z@Ek%Na{Ei#~zAS}Gz#YPxE0RGB94sS-sj8M` zZ-{?is?h#9rr}Z+aW5S@C17es`UKCh3XcrXI^kAEw?J{GiZf1}G z&K{U4iA%{{YmuFs!yv)oqwgUR)XTr@9w%Lrf@H~~ zaY5PReHpY*)WcCyzv+GLe)?$ok3Xvb17LF698MDSM*x|FJ5kq zc}=lofX`T^Y2D@{S8tR|MH3BxwincjqF2mWLl@{kk6^eJvvf;WkYA}*21}X_-fV#x zxwyl_VAQEpEoDmgSE?xH?3Ag$J4+R4C?*61O+mL_Lq4XaY933gRtkF7=4$E_j&9X8hqc$3y6zutGRWWo>Z(b+Us)Bwgx76~iJ^)!|dIpPG zDC?@h*)v9UMmMZ^WpdI~Z|PbdHD}A#%3kPb3D-fS*I#HnQY`u6&@i)_;DpuKL#Hpx3Cx)fOj0JD1$dNarUHg1UH`T=|i zgf>W5%wFQi9yeYJ=Ut+`6!s7Td^vQvo%F8~I7jS;Y7*@+4xzJL#E07Z@S+_f!4Ui4 za&0C##$n_w>>$|jD2!cl0$Jt>B*64vg1X#Z-O@-6H&er4H;L1&Lz&g%_tR^KzVTou z5`5~fG?PjzwX>Nzv=%=k5FWMNi;$hE?6+|9A%vB{YIGp^sylPHK5npLc>lSZ2g*y# z7PF7sQVp}+0~uB?L&TVdP$u)_Oe!qstFaBY3p<08bwq_pTZ7dY9qR*8QrrU3P=0brH#q2!cx~>w?MbF<7Ig*{gU|9Ub%az z)w8{Jna9=c66CtwTTlx(^t`=`BwG;k4oHr141;NJ4L5@JYO;lU=h8xfr*PmY;(sc} zAvZ{nIiq)zcS58sE`~g?wFm|5Ye`z_0QebsF$C%yQ?EfbWz2d5YpRruSul6ZfkbrX4U zZ|F?Abw_Lg^)8nRB@5(>kc((9j|!Rt5C?n%qN|}7OLL%hplX)Ttz7zswgt-|!p(GB zEIswETHKOH-OKYn5>zOwrm0+-f04e=aLJ*eAyN}azoXyU04EJoB~F% zZZJ9NYDGitMrCu8lLOqjYD4Pn>TFpl~X5`tTxL8!`(!C!N{y~jEWNVpu*e` z?+!Yhn&%bHOl91i$l2@pqAS4&n6Sr(5fFK0`GyAO!wGv;f+a-$6^Q%1bE-pZcniU^ zD;Z0fha|=GpvBWQ--Z@8-O$1ldO9zl%m!qe3nA~I?dmN7Bb7u8wP z6_r6nt3tH4e3CLSoaV_pDMllJ$woK_#;QO)bGC3pK#~c0^qfPx0bgJTCE$7C1{rGv z!!Y$}wPKYD&<~2-xTF5s8*~M>Bp4y8+~5t%nmIE(T&QaL5U37x01ymICj-T>p%+Rs zuy>p|b?W$u(Lr@^TA!|BVFz7hVh}hw=pZz*NsTs#1*n3cIWr;IS|`(%%4`uhb z^PxO<-6Tnauf@n`xc}UJCOhITWT?RcJ* zXGnN4V+8GblWQm0WNT~3wjiY0kH!#{9YkW1C5%`bG;g02yx$MV8>Hc%P{pfANE$wv zX&xMHCATkM_*FP`sQcFvl6rEzOWJ*8rFXU5cxtTq)L6auVLY`QSuTE1UA@zYpJ>KU zti?~XQv2$6RVjW3uFli%QYeCZAzcG$1 zjmngeu&v)+nuufILQUtg1?rM;Pzf!Zt0$Szp95(id_tJ976 z@n-z^TKt7CV(Z~hv`eg`tNWvC8Y2Ba`X&;#bVWasmZY0_5*K7v8P=}QV)&M9gfz&b z8lD!A`F@ln+jMzF2QZ)V&Bf zLRTR-a5IoUi4VHeUzp`sj#X4|Ol-B|#)y*GlAbD5c%4MtIj~2V*V))7^hcZY5w$Zx z?qD*%F$*aHM9#L{imxG;jSrVhbCzfy_XAZ8N}6pZ%jfL}p|M>i)Mhx;Hm6X3gIyu> z+)~W1I)W}?OFk!z;S2jXYSEtC*G(55eh(T(B*MNx!(tmLS7ob}a7suLl?f{IcOsk9 zwx~e{JA+Jj#&JqW!#4IH$;CU!nL+5V+RJe7vyMlf&m>dUrG3zk2Qd)kb=>nI5gb)Ji|Id};M? zBb{xgv-OuACi|8ztPI?bHj+cl8W zY*%bghk^v7nQ0>_Bv)1`2+2JOx{H;6X-XM?1AihH!9k6A-beCBOBtTr#b!uZiq&+sF9U$pHl}uj9hE zMZ@)#a{Q6pUuKh$Y+}eK_+YL%fg3V0g#tzt@BM=ntC8w&rusj9h<3n}^36sk2RZl57W(Fyn`eSE>8gs0D&Z$8;a%ZVa+J{!hv~gybt2><>7OBF|+c z?%+4tT6^vP2h3r~>aeVD0COn1?9cvMASZDC9RQs{!U1+AOX@8=w_sbEKB$A;7OWiH z(xhP9@Ja2$e0048uM<}mo%r;ubK*^2U|e2=HYRk^z3d+_8K4>dNu89nY?wM1oKKWr*SRmzPg2UA}j@e!11RyMBqG z7#7(yDlvLOawW`U>#Xtja3>^JMPMdl&%)j(j7g>;oTVXP3=b3A?>)VeZX^yg69-_o zP3(c)c0&TYZTHh|fo^H*uKE@pmxH%7jE#8P8yJOg1%-Y^<8|;?iA8sjoV+0co7xnA zX_wj4Oa5r0hl_AsI{FrN6M98X_E^=6Y`OIC)Q?(dSSO329X9A-oKn$4YoR0-6|9u$_2g969IgWH5C%8zyq-~Sp~<3n-d}{3Di79*dWSf&)#uvLlaplAV!QZ5HvELnS!yXYP-Aw6QJzQNwBfu zps4Dfk1#@TQ#^jL_2IVc)5jSSAVf`o2Swp__w>WHN>VvDjT*AszTlsum=v^gp7_Od9gQZE~> zAd!?k9UI>J?h-<-AjpvO=I^7X;OueO!}8=jHlD>hP?ZrU%lIztf_n*Fh5#_1U)b(0 z8e|&r?g(w{8Powi>DjTYeR8qUbEMe=IaE&UZ}si^;B+0r>r?f}y+rFN1z)|bc=Dfg zzu&!-yqB!=-xGK>5k87e!z$oTTx3B&M36yCib#bXcp5AbLZQJ^MiXIAnE*td-$Ke8 zH^`E14bq?~_5`}Z-hK5*Gyc>Xe>M)qB|8^T{3DQ=ReW!}I=6txlgHmYLgk2Dh>ywN zRuSbz9vts$2KwR}e6fTRnn=KJnbf33j0_ z!|i{^O%QHx;*Ge1)ALVlp<6=aAnlL`#R~{OT9i2_6kzx+B>Oc^EwmU4YMh;%I?#qQ zB&l;up07@$h@Z&9h#k@Ze+UfV2!I$tV3z=U_=*bEiUt=1xibiY7{C7xizzW+T?Xnz zC}6@Mz+CC|{n{unnk_isHE zipD9lD83$-G6Spn{g?hl`A6k-DH`3;nQW1x`$>zjlde$oS*mF#@n|$dHS7e1Uz4fy z<5Mwr8d$(-PLz}3fkY|cH1|T0?f@N$z%Kk(X7#T>CSZ7II#~7~Fp-Z@C@$m}BmGIpp2BZX zz#QGnRTZ*$rCBYYrA_5#o#FrOBDgfdznqS!O$AS&oz{?H{LlSSr zd+X7q*u5CA|FKpkTj(-wp>5+fCDaS!3@k~a-*@OWB`;9xtZSh8^(`T?4m~bGU|XLZ zdJ$MGG$FvG3pc-u<(|V*E>X`^1LpawH5*F^UkVW<&P5x+AoxFU1GXCA6P>{^@38b_ z^lfen4Q^j$i{-a?c8G^$`@SH(edta!!5T!cZUGwF73q+)816@mBl~pZUGsz;32rvS2^4V5U2wp^B4Oeqp8B)F@LP?5bBp@3+0{1NV>M8ad zh=%Y$judb^B)tQXZR&N5#`d*^OO+xbuS{%CI{}-v!J*Bt;3D?iLZlFR7Gdrr;iVn3 z2h)z(!v!(NB-?SjXR{r1?g%VE-*GXxw!5juJPU8eA0dxn=Z|qiFe@D%_{r>pKm76H zUoQT<|GBmP=g6GYNGZ*fvX)Z*cE?X||LnkjIZ*pnt8eeR6p8NSq#h$hb|(bS<>Nm% z`N7HhCHngcL8K&*qKuQYl7018mM-4ASm(d>Ffw3rh36}|wSIi*ryzSi|Z|b3Xt1Iqn7)Rt7rf_<*A{PS59Ao881} zbkL%3QhcWQ#K${9%c@Y5xf+k2OiFfRLCa`IE1OtFiGr{}iOhi?hJFu&l7xuxu!sl` zV)WOTlrB?89dXp2T)z~)4#D>?IS$%V?eH}A0;XWzXyHrQ2&NS{aN;10h` z?{B6LuWD=QbN8;N<42lK>y&!rZY*R~g z_dXI4iS1a;+Hq${3%eNFypcH>(=@afQF9X$RVZ-=Y;5zyvr|!lc&D8zY`8-*{)EOA zM&j^IihTqjGVbBs_o#oDa~|j-3)SP2tx_^w`_4w4%H?hk&|pyD_JGIo@k5I!qkRR1 zYMjbSI60DJLECb!n{FLGp@sQ)@d#w|3}{U*Pwey;K=;CgKgYkgz`^8&zh*>zv08zz zh0Gz>b(~dF5w{2q1ajoFkFZ0PF&vZ!zS{YcUd9nC1+iazZpmk@;!=6L0C(V!mN{6{ z+!w?hxR5gToPBfIiA`f`v>QxACEYCe9N9`r7)2`D40#VRT6So(w@f4CG4C-l96~|3 zJG496XxpgTPKXg=8tq6LYtEHvKg3GWQ9QT_ zNF2}Ow1DpSI|NH*GgQ{LNYd>lEoG?-+W_f8Cgx6f#g_hl+>lpnQTm5TA+CcE%Qhjl zBXEL|COG>Q>eLC@)X>Rq(jDQ|q3AIZ<$Z}4 zSxv9~(mcz}XooJBCjE0f&Q(<^WwFNQC4$j6AO z@=>#!G$y_l;c|v8KO$HpT+THNodM%KLQAfTP-ojF&L$i7r{nY;B11U#*@j>adUgUy z2=2%^%wh|UGR{M!3DOycT{<#3FMy3|0D{pWfFDjTzRfe(m|1FO01+nzD?2w1KiI;! zAGgc)G7oX!~7;i-~{DaIYe^T%W>WMkUKfQfUnKxgEBS+3QB(YcJ6>&WJ_LDInpF zq>5WX?Jrt%0I8zj2;4h#Ajyd!@{L-AiGK^RIxxTo_rwYJwu8OVddH>_*%uo}c`o$` zZkFA2Hpk(e_O_w?c&1?B_?%kK3_v=r;*nxwGr63-Z+0%X8t`QjsIut!EN+PO09>WF zQzSkvg>FfI)kWWnvUdRepM~yih3$YeUt4o;hlY-|<#*Z%7kF*PQe$oCx82VZa3KI` z=Ip{Vf$4Z;$Sd;ih)56}1d&+Va$bB^M;<)$VE)0-gQ5Dn%ej^F9}Lj_gCQn9kTGNM z1<*n2c7lLhg~p(_yFIvSM{sh{^cX3eqAb#Vf^OPjRB3k!WPs8K4w0{zCasGyi7gQt zU2kCA22qATqk&Qw15vZ%QqT5gH%xYo?q{0a&(vOQ^=`fQyRQhrKC5qt@3n{>b?DMC^cBHBvrG#&(91fG zEO}BG&eeBVpWhFN@SY*`F;436-FOH66JawE^#}&QfW$o34VR|CT@f3@k@N63fu{5DE0;i{U0avS3U zsGN;+l*#pp>OqgIZXT)6Id*I{4vZ^y;Pr?y8mv5&7pK2O3?LB`VFmHkaXacLE0%|w zd+$z1tD?EAN|bMEJOfm>C5|yd`;Nko8$!oCH|?HI{xeV5*p>Gi0K^0^GjWukIe>R2 zgY*dsb+=@As2A;fh-Y$!B?G(M?-)9h;y3j)}Yy{Xqhgk%? z3B)D~t|lWe8~5T`z?U7)jU!nds#L^pKt%XJcw;amgh_;lZxklsaD;b2fGWbHPNEx* zcib4couHssj%dV>4bUmZ`&9M`(b~^+Vy8##ZK3mj5d|d`8x-`*^#0YZAEnqa)Jh$w zBfx6)S|c^kObyf{B22rqnr_68G~-9s;zwGk9rarjv^W5=nHmtERUD+|+xUQB3=#TG z07(4ew>sM0#Go|%paGaOD^<3Z#6i=CX*x6~p+VaLjP0$RvoQV&W&Vanew9W}#Q%aU z?K;@pIj}Z(_NTp#otK+CFW0{F%jg!I9=z6w?rTQ(t%oAfK{DiZCM4tTcMBvvi#44W zHT0P>@j1^gWC8;c}z%*e_&K^A<70!4~@D@13EW3i7kbd z2DhXlVXg7&CD(6|D2&rAvt`xrNyR=2=#CQy;x->B+8xgjk$LOb+nL7=cE$>fR*YN> zc>_^m;ZT?he-9O%U@=^e6eARHyQv(}@!KaPZ!!HN!REurM-n+Qg8r&QIC~8TMn*=S zU&&jF22DMM(3|Y;@CT=$UQEXCL{Of{cbpy0w{WH6oHBtk!e|_o0PcV!hGg_2X?J@r z1|dO`AokyBxV z4WhR6%oLMOtr*@a&^AuODrzqRStJ*BKXwtY#ga(@P@C99V+oA>Nr`6|rBd5F4Wkin zR0a={t)nDAPXh6TR3EcPW_*Fy|A%P$Fb{^d;8+h?NS~PO@yw*Trv*pRQQ!D;N`6Ag z7$xr^X(KYj`6Znp7>9JDGSp$a>-I|Ew@Kz_AT1e0=nWdPL1q(!R+kNb{8Jx%XuX|q z4+HX%9uaZ>Z7O($l53QZr<~oVY?EhmFx&UoD#OYQb2VNDq1kPx8e5Uzr+q|F!CB)! z;gNI^^BHU#z({MVAU)cCI@ZC`UfEh$;!KYx`krOcZ1`BLg%+w23! zRd2ff%JOTga}UA~u07~!W}aV5jyICy&E$A3vEH>qhRMiHj-_Pmnw#`zWH`v&OUZ*MEHz239@=34x~ufw5q*LswTb;Dw{ z-s9B}_3YFN?UlE!OK$S~c6sZ%D`UYUX&Hcx-W?|<#jeZGgL z21JAB}_rb^)qwCTZd3$GaaF?83m)zudFRhrHC@E^oP5SrCL+g^8oRg1IwwquD T4<5OHd|f(BZ9XYs3GDv?3T^|) diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/jaraco/context.py b/venv/lib/python3.11/site-packages/setuptools/_vendor/jaraco/context.py deleted file mode 100755 index 818f16f..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_vendor/jaraco/context.py +++ /dev/null @@ -1,253 +0,0 @@ -import os -import subprocess -import contextlib -import functools -import tempfile -import shutil -import operator - - -@contextlib.contextmanager -def pushd(dir): - orig = os.getcwd() - os.chdir(dir) - try: - yield dir - finally: - os.chdir(orig) - - -@contextlib.contextmanager -def tarball_context(url, target_dir=None, runner=None, pushd=pushd): - """ - Get a tarball, extract it, change to that directory, yield, then - clean up. - `runner` is the function to invoke commands. - `pushd` is a context manager for changing the directory. - """ - if target_dir is None: - target_dir = os.path.basename(url).replace('.tar.gz', '').replace('.tgz', '') - if runner is None: - runner = functools.partial(subprocess.check_call, shell=True) - # In the tar command, use --strip-components=1 to strip the first path and - # then - # use -C to cause the files to be extracted to {target_dir}. This ensures - # that we always know where the files were extracted. - runner('mkdir {target_dir}'.format(**vars())) - try: - getter = 'wget {url} -O -' - extract = 'tar x{compression} --strip-components=1 -C {target_dir}' - cmd = ' | '.join((getter, extract)) - runner(cmd.format(compression=infer_compression(url), **vars())) - with pushd(target_dir): - yield target_dir - finally: - runner('rm -Rf {target_dir}'.format(**vars())) - - -def infer_compression(url): - """ - Given a URL or filename, infer the compression code for tar. - """ - # cheat and just assume it's the last two characters - compression_indicator = url[-2:] - mapping = dict(gz='z', bz='j', xz='J') - # Assume 'z' (gzip) if no match - return mapping.get(compression_indicator, 'z') - - -@contextlib.contextmanager -def temp_dir(remover=shutil.rmtree): - """ - Create a temporary directory context. Pass a custom remover - to override the removal behavior. - """ - temp_dir = tempfile.mkdtemp() - try: - yield temp_dir - finally: - remover(temp_dir) - - -@contextlib.contextmanager -def repo_context(url, branch=None, quiet=True, dest_ctx=temp_dir): - """ - Check out the repo indicated by url. - - If dest_ctx is supplied, it should be a context manager - to yield the target directory for the check out. - """ - exe = 'git' if 'git' in url else 'hg' - with dest_ctx() as repo_dir: - cmd = [exe, 'clone', url, repo_dir] - if branch: - cmd.extend(['--branch', branch]) - devnull = open(os.path.devnull, 'w') - stdout = devnull if quiet else None - subprocess.check_call(cmd, stdout=stdout) - yield repo_dir - - -@contextlib.contextmanager -def null(): - yield - - -class ExceptionTrap: - """ - A context manager that will catch certain exceptions and provide an - indication they occurred. - - >>> with ExceptionTrap() as trap: - ... raise Exception() - >>> bool(trap) - True - - >>> with ExceptionTrap() as trap: - ... pass - >>> bool(trap) - False - - >>> with ExceptionTrap(ValueError) as trap: - ... raise ValueError("1 + 1 is not 3") - >>> bool(trap) - True - - >>> with ExceptionTrap(ValueError) as trap: - ... raise Exception() - Traceback (most recent call last): - ... - Exception - - >>> bool(trap) - False - """ - - exc_info = None, None, None - - def __init__(self, exceptions=(Exception,)): - self.exceptions = exceptions - - def __enter__(self): - return self - - @property - def type(self): - return self.exc_info[0] - - @property - def value(self): - return self.exc_info[1] - - @property - def tb(self): - return self.exc_info[2] - - def __exit__(self, *exc_info): - type = exc_info[0] - matches = type and issubclass(type, self.exceptions) - if matches: - self.exc_info = exc_info - return matches - - def __bool__(self): - return bool(self.type) - - def raises(self, func, *, _test=bool): - """ - Wrap func and replace the result with the truth - value of the trap (True if an exception occurred). - - First, give the decorator an alias to support Python 3.8 - Syntax. - - >>> raises = ExceptionTrap(ValueError).raises - - Now decorate a function that always fails. - - >>> @raises - ... def fail(): - ... raise ValueError('failed') - >>> fail() - True - """ - - @functools.wraps(func) - def wrapper(*args, **kwargs): - with ExceptionTrap(self.exceptions) as trap: - func(*args, **kwargs) - return _test(trap) - - return wrapper - - def passes(self, func): - """ - Wrap func and replace the result with the truth - value of the trap (True if no exception). - - First, give the decorator an alias to support Python 3.8 - Syntax. - - >>> passes = ExceptionTrap(ValueError).passes - - Now decorate a function that always fails. - - >>> @passes - ... def fail(): - ... raise ValueError('failed') - - >>> fail() - False - """ - return self.raises(func, _test=operator.not_) - - -class suppress(contextlib.suppress, contextlib.ContextDecorator): - """ - A version of contextlib.suppress with decorator support. - - >>> @suppress(KeyError) - ... def key_error(): - ... {}[''] - >>> key_error() - """ - - -class on_interrupt(contextlib.ContextDecorator): - """ - Replace a KeyboardInterrupt with SystemExit(1) - - >>> def do_interrupt(): - ... raise KeyboardInterrupt() - >>> on_interrupt('error')(do_interrupt)() - Traceback (most recent call last): - ... - SystemExit: 1 - >>> on_interrupt('error', code=255)(do_interrupt)() - Traceback (most recent call last): - ... - SystemExit: 255 - >>> on_interrupt('suppress')(do_interrupt)() - >>> with __import__('pytest').raises(KeyboardInterrupt): - ... on_interrupt('ignore')(do_interrupt)() - """ - - def __init__( - self, - action='error', - # py3.7 compat - # /, - code=1, - ): - self.action = action - self.code = code - - def __enter__(self): - return self - - def __exit__(self, exctype, excinst, exctb): - if exctype is not KeyboardInterrupt or self.action == 'ignore': - return - elif self.action == 'error': - raise SystemExit(self.code) from excinst - return self.action == 'suppress' diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/jaraco/functools.py b/venv/lib/python3.11/site-packages/setuptools/_vendor/jaraco/functools.py deleted file mode 100755 index bbd8b29..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_vendor/jaraco/functools.py +++ /dev/null @@ -1,525 +0,0 @@ -import functools -import time -import inspect -import collections -import types -import itertools - -import setuptools.extern.more_itertools - -from typing import Callable, TypeVar - - -CallableT = TypeVar("CallableT", bound=Callable[..., object]) - - -def compose(*funcs): - """ - Compose any number of unary functions into a single unary function. - - >>> import textwrap - >>> expected = str.strip(textwrap.dedent(compose.__doc__)) - >>> strip_and_dedent = compose(str.strip, textwrap.dedent) - >>> strip_and_dedent(compose.__doc__) == expected - True - - Compose also allows the innermost function to take arbitrary arguments. - - >>> round_three = lambda x: round(x, ndigits=3) - >>> f = compose(round_three, int.__truediv__) - >>> [f(3*x, x+1) for x in range(1,10)] - [1.5, 2.0, 2.25, 2.4, 2.5, 2.571, 2.625, 2.667, 2.7] - """ - - def compose_two(f1, f2): - return lambda *args, **kwargs: f1(f2(*args, **kwargs)) - - return functools.reduce(compose_two, funcs) - - -def method_caller(method_name, *args, **kwargs): - """ - Return a function that will call a named method on the - target object with optional positional and keyword - arguments. - - >>> lower = method_caller('lower') - >>> lower('MyString') - 'mystring' - """ - - def call_method(target): - func = getattr(target, method_name) - return func(*args, **kwargs) - - return call_method - - -def once(func): - """ - Decorate func so it's only ever called the first time. - - This decorator can ensure that an expensive or non-idempotent function - will not be expensive on subsequent calls and is idempotent. - - >>> add_three = once(lambda a: a+3) - >>> add_three(3) - 6 - >>> add_three(9) - 6 - >>> add_three('12') - 6 - - To reset the stored value, simply clear the property ``saved_result``. - - >>> del add_three.saved_result - >>> add_three(9) - 12 - >>> add_three(8) - 12 - - Or invoke 'reset()' on it. - - >>> add_three.reset() - >>> add_three(-3) - 0 - >>> add_three(0) - 0 - """ - - @functools.wraps(func) - def wrapper(*args, **kwargs): - if not hasattr(wrapper, 'saved_result'): - wrapper.saved_result = func(*args, **kwargs) - return wrapper.saved_result - - wrapper.reset = lambda: vars(wrapper).__delitem__('saved_result') - return wrapper - - -def method_cache( - method: CallableT, - cache_wrapper: Callable[ - [CallableT], CallableT - ] = functools.lru_cache(), # type: ignore[assignment] -) -> CallableT: - """ - Wrap lru_cache to support storing the cache data in the object instances. - - Abstracts the common paradigm where the method explicitly saves an - underscore-prefixed protected property on first call and returns that - subsequently. - - >>> class MyClass: - ... calls = 0 - ... - ... @method_cache - ... def method(self, value): - ... self.calls += 1 - ... return value - - >>> a = MyClass() - >>> a.method(3) - 3 - >>> for x in range(75): - ... res = a.method(x) - >>> a.calls - 75 - - Note that the apparent behavior will be exactly like that of lru_cache - except that the cache is stored on each instance, so values in one - instance will not flush values from another, and when an instance is - deleted, so are the cached values for that instance. - - >>> b = MyClass() - >>> for x in range(35): - ... res = b.method(x) - >>> b.calls - 35 - >>> a.method(0) - 0 - >>> a.calls - 75 - - Note that if method had been decorated with ``functools.lru_cache()``, - a.calls would have been 76 (due to the cached value of 0 having been - flushed by the 'b' instance). - - Clear the cache with ``.cache_clear()`` - - >>> a.method.cache_clear() - - Same for a method that hasn't yet been called. - - >>> c = MyClass() - >>> c.method.cache_clear() - - Another cache wrapper may be supplied: - - >>> cache = functools.lru_cache(maxsize=2) - >>> MyClass.method2 = method_cache(lambda self: 3, cache_wrapper=cache) - >>> a = MyClass() - >>> a.method2() - 3 - - Caution - do not subsequently wrap the method with another decorator, such - as ``@property``, which changes the semantics of the function. - - See also - http://code.activestate.com/recipes/577452-a-memoize-decorator-for-instance-methods/ - for another implementation and additional justification. - """ - - def wrapper(self: object, *args: object, **kwargs: object) -> object: - # it's the first call, replace the method with a cached, bound method - bound_method: CallableT = types.MethodType( # type: ignore[assignment] - method, self - ) - cached_method = cache_wrapper(bound_method) - setattr(self, method.__name__, cached_method) - return cached_method(*args, **kwargs) - - # Support cache clear even before cache has been created. - wrapper.cache_clear = lambda: None # type: ignore[attr-defined] - - return ( # type: ignore[return-value] - _special_method_cache(method, cache_wrapper) or wrapper - ) - - -def _special_method_cache(method, cache_wrapper): - """ - Because Python treats special methods differently, it's not - possible to use instance attributes to implement the cached - methods. - - Instead, install the wrapper method under a different name - and return a simple proxy to that wrapper. - - https://github.com/jaraco/jaraco.functools/issues/5 - """ - name = method.__name__ - special_names = '__getattr__', '__getitem__' - if name not in special_names: - return - - wrapper_name = '__cached' + name - - def proxy(self, *args, **kwargs): - if wrapper_name not in vars(self): - bound = types.MethodType(method, self) - cache = cache_wrapper(bound) - setattr(self, wrapper_name, cache) - else: - cache = getattr(self, wrapper_name) - return cache(*args, **kwargs) - - return proxy - - -def apply(transform): - """ - Decorate a function with a transform function that is - invoked on results returned from the decorated function. - - >>> @apply(reversed) - ... def get_numbers(start): - ... "doc for get_numbers" - ... return range(start, start+3) - >>> list(get_numbers(4)) - [6, 5, 4] - >>> get_numbers.__doc__ - 'doc for get_numbers' - """ - - def wrap(func): - return functools.wraps(func)(compose(transform, func)) - - return wrap - - -def result_invoke(action): - r""" - Decorate a function with an action function that is - invoked on the results returned from the decorated - function (for its side-effect), then return the original - result. - - >>> @result_invoke(print) - ... def add_two(a, b): - ... return a + b - >>> x = add_two(2, 3) - 5 - >>> x - 5 - """ - - def wrap(func): - @functools.wraps(func) - def wrapper(*args, **kwargs): - result = func(*args, **kwargs) - action(result) - return result - - return wrapper - - return wrap - - -def call_aside(f, *args, **kwargs): - """ - Call a function for its side effect after initialization. - - >>> @call_aside - ... def func(): print("called") - called - >>> func() - called - - Use functools.partial to pass parameters to the initial call - - >>> @functools.partial(call_aside, name='bingo') - ... def func(name): print("called with", name) - called with bingo - """ - f(*args, **kwargs) - return f - - -class Throttler: - """ - Rate-limit a function (or other callable) - """ - - def __init__(self, func, max_rate=float('Inf')): - if isinstance(func, Throttler): - func = func.func - self.func = func - self.max_rate = max_rate - self.reset() - - def reset(self): - self.last_called = 0 - - def __call__(self, *args, **kwargs): - self._wait() - return self.func(*args, **kwargs) - - def _wait(self): - "ensure at least 1/max_rate seconds from last call" - elapsed = time.time() - self.last_called - must_wait = 1 / self.max_rate - elapsed - time.sleep(max(0, must_wait)) - self.last_called = time.time() - - def __get__(self, obj, type=None): - return first_invoke(self._wait, functools.partial(self.func, obj)) - - -def first_invoke(func1, func2): - """ - Return a function that when invoked will invoke func1 without - any parameters (for its side-effect) and then invoke func2 - with whatever parameters were passed, returning its result. - """ - - def wrapper(*args, **kwargs): - func1() - return func2(*args, **kwargs) - - return wrapper - - -def retry_call(func, cleanup=lambda: None, retries=0, trap=()): - """ - Given a callable func, trap the indicated exceptions - for up to 'retries' times, invoking cleanup on the - exception. On the final attempt, allow any exceptions - to propagate. - """ - attempts = itertools.count() if retries == float('inf') else range(retries) - for attempt in attempts: - try: - return func() - except trap: - cleanup() - - return func() - - -def retry(*r_args, **r_kwargs): - """ - Decorator wrapper for retry_call. Accepts arguments to retry_call - except func and then returns a decorator for the decorated function. - - Ex: - - >>> @retry(retries=3) - ... def my_func(a, b): - ... "this is my funk" - ... print(a, b) - >>> my_func.__doc__ - 'this is my funk' - """ - - def decorate(func): - @functools.wraps(func) - def wrapper(*f_args, **f_kwargs): - bound = functools.partial(func, *f_args, **f_kwargs) - return retry_call(bound, *r_args, **r_kwargs) - - return wrapper - - return decorate - - -def print_yielded(func): - """ - Convert a generator into a function that prints all yielded elements - - >>> @print_yielded - ... def x(): - ... yield 3; yield None - >>> x() - 3 - None - """ - print_all = functools.partial(map, print) - print_results = compose(more_itertools.consume, print_all, func) - return functools.wraps(func)(print_results) - - -def pass_none(func): - """ - Wrap func so it's not called if its first param is None - - >>> print_text = pass_none(print) - >>> print_text('text') - text - >>> print_text(None) - """ - - @functools.wraps(func) - def wrapper(param, *args, **kwargs): - if param is not None: - return func(param, *args, **kwargs) - - return wrapper - - -def assign_params(func, namespace): - """ - Assign parameters from namespace where func solicits. - - >>> def func(x, y=3): - ... print(x, y) - >>> assigned = assign_params(func, dict(x=2, z=4)) - >>> assigned() - 2 3 - - The usual errors are raised if a function doesn't receive - its required parameters: - - >>> assigned = assign_params(func, dict(y=3, z=4)) - >>> assigned() - Traceback (most recent call last): - TypeError: func() ...argument... - - It even works on methods: - - >>> class Handler: - ... def meth(self, arg): - ... print(arg) - >>> assign_params(Handler().meth, dict(arg='crystal', foo='clear'))() - crystal - """ - sig = inspect.signature(func) - params = sig.parameters.keys() - call_ns = {k: namespace[k] for k in params if k in namespace} - return functools.partial(func, **call_ns) - - -def save_method_args(method): - """ - Wrap a method such that when it is called, the args and kwargs are - saved on the method. - - >>> class MyClass: - ... @save_method_args - ... def method(self, a, b): - ... print(a, b) - >>> my_ob = MyClass() - >>> my_ob.method(1, 2) - 1 2 - >>> my_ob._saved_method.args - (1, 2) - >>> my_ob._saved_method.kwargs - {} - >>> my_ob.method(a=3, b='foo') - 3 foo - >>> my_ob._saved_method.args - () - >>> my_ob._saved_method.kwargs == dict(a=3, b='foo') - True - - The arguments are stored on the instance, allowing for - different instance to save different args. - - >>> your_ob = MyClass() - >>> your_ob.method({str('x'): 3}, b=[4]) - {'x': 3} [4] - >>> your_ob._saved_method.args - ({'x': 3},) - >>> my_ob._saved_method.args - () - """ - args_and_kwargs = collections.namedtuple('args_and_kwargs', 'args kwargs') - - @functools.wraps(method) - def wrapper(self, *args, **kwargs): - attr_name = '_saved_' + method.__name__ - attr = args_and_kwargs(args, kwargs) - setattr(self, attr_name, attr) - return method(self, *args, **kwargs) - - return wrapper - - -def except_(*exceptions, replace=None, use=None): - """ - Replace the indicated exceptions, if raised, with the indicated - literal replacement or evaluated expression (if present). - - >>> safe_int = except_(ValueError)(int) - >>> safe_int('five') - >>> safe_int('5') - 5 - - Specify a literal replacement with ``replace``. - - >>> safe_int_r = except_(ValueError, replace=0)(int) - >>> safe_int_r('five') - 0 - - Provide an expression to ``use`` to pass through particular parameters. - - >>> safe_int_pt = except_(ValueError, use='args[0]')(int) - >>> safe_int_pt('five') - 'five' - - """ - - def decorate(func): - @functools.wraps(func) - def wrapper(*args, **kwargs): - try: - return func(*args, **kwargs) - except exceptions: - try: - return eval(use) - except TypeError: - return replace - - return wrapper - - return decorate diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/jaraco/text/__init__.py b/venv/lib/python3.11/site-packages/setuptools/_vendor/jaraco/text/__init__.py deleted file mode 100755 index a0306d5..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_vendor/jaraco/text/__init__.py +++ /dev/null @@ -1,599 +0,0 @@ -import re -import itertools -import textwrap -import functools - -try: - from importlib.resources import files # type: ignore -except ImportError: # pragma: nocover - from setuptools.extern.importlib_resources import files # type: ignore - -from setuptools.extern.jaraco.functools import compose, method_cache -from setuptools.extern.jaraco.context import ExceptionTrap - - -def substitution(old, new): - """ - Return a function that will perform a substitution on a string - """ - return lambda s: s.replace(old, new) - - -def multi_substitution(*substitutions): - """ - Take a sequence of pairs specifying substitutions, and create - a function that performs those substitutions. - - >>> multi_substitution(('foo', 'bar'), ('bar', 'baz'))('foo') - 'baz' - """ - substitutions = itertools.starmap(substitution, substitutions) - # compose function applies last function first, so reverse the - # substitutions to get the expected order. - substitutions = reversed(tuple(substitutions)) - return compose(*substitutions) - - -class FoldedCase(str): - """ - A case insensitive string class; behaves just like str - except compares equal when the only variation is case. - - >>> s = FoldedCase('hello world') - - >>> s == 'Hello World' - True - - >>> 'Hello World' == s - True - - >>> s != 'Hello World' - False - - >>> s.index('O') - 4 - - >>> s.split('O') - ['hell', ' w', 'rld'] - - >>> sorted(map(FoldedCase, ['GAMMA', 'alpha', 'Beta'])) - ['alpha', 'Beta', 'GAMMA'] - - Sequence membership is straightforward. - - >>> "Hello World" in [s] - True - >>> s in ["Hello World"] - True - - You may test for set inclusion, but candidate and elements - must both be folded. - - >>> FoldedCase("Hello World") in {s} - True - >>> s in {FoldedCase("Hello World")} - True - - String inclusion works as long as the FoldedCase object - is on the right. - - >>> "hello" in FoldedCase("Hello World") - True - - But not if the FoldedCase object is on the left: - - >>> FoldedCase('hello') in 'Hello World' - False - - In that case, use ``in_``: - - >>> FoldedCase('hello').in_('Hello World') - True - - >>> FoldedCase('hello') > FoldedCase('Hello') - False - """ - - def __lt__(self, other): - return self.lower() < other.lower() - - def __gt__(self, other): - return self.lower() > other.lower() - - def __eq__(self, other): - return self.lower() == other.lower() - - def __ne__(self, other): - return self.lower() != other.lower() - - def __hash__(self): - return hash(self.lower()) - - def __contains__(self, other): - return super().lower().__contains__(other.lower()) - - def in_(self, other): - "Does self appear in other?" - return self in FoldedCase(other) - - # cache lower since it's likely to be called frequently. - @method_cache - def lower(self): - return super().lower() - - def index(self, sub): - return self.lower().index(sub.lower()) - - def split(self, splitter=' ', maxsplit=0): - pattern = re.compile(re.escape(splitter), re.I) - return pattern.split(self, maxsplit) - - -# Python 3.8 compatibility -_unicode_trap = ExceptionTrap(UnicodeDecodeError) - - -@_unicode_trap.passes -def is_decodable(value): - r""" - Return True if the supplied value is decodable (using the default - encoding). - - >>> is_decodable(b'\xff') - False - >>> is_decodable(b'\x32') - True - """ - value.decode() - - -def is_binary(value): - r""" - Return True if the value appears to be binary (that is, it's a byte - string and isn't decodable). - - >>> is_binary(b'\xff') - True - >>> is_binary('\xff') - False - """ - return isinstance(value, bytes) and not is_decodable(value) - - -def trim(s): - r""" - Trim something like a docstring to remove the whitespace that - is common due to indentation and formatting. - - >>> trim("\n\tfoo = bar\n\t\tbar = baz\n") - 'foo = bar\n\tbar = baz' - """ - return textwrap.dedent(s).strip() - - -def wrap(s): - """ - Wrap lines of text, retaining existing newlines as - paragraph markers. - - >>> print(wrap(lorem_ipsum)) - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do - eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad - minim veniam, quis nostrud exercitation ullamco laboris nisi ut - aliquip ex ea commodo consequat. Duis aute irure dolor in - reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla - pariatur. Excepteur sint occaecat cupidatat non proident, sunt in - culpa qui officia deserunt mollit anim id est laborum. - - Curabitur pretium tincidunt lacus. Nulla gravida orci a odio. Nullam - varius, turpis et commodo pharetra, est eros bibendum elit, nec luctus - magna felis sollicitudin mauris. Integer in mauris eu nibh euismod - gravida. Duis ac tellus et risus vulputate vehicula. Donec lobortis - risus a elit. Etiam tempor. Ut ullamcorper, ligula eu tempor congue, - eros est euismod turpis, id tincidunt sapien risus a quam. Maecenas - fermentum consequat mi. Donec fermentum. Pellentesque malesuada nulla - a mi. Duis sapien sem, aliquet nec, commodo eget, consequat quis, - neque. Aliquam faucibus, elit ut dictum aliquet, felis nisl adipiscing - sapien, sed malesuada diam lacus eget erat. Cras mollis scelerisque - nunc. Nullam arcu. Aliquam consequat. Curabitur augue lorem, dapibus - quis, laoreet et, pretium ac, nisi. Aenean magna nisl, mollis quis, - molestie eu, feugiat in, orci. In hac habitasse platea dictumst. - """ - paragraphs = s.splitlines() - wrapped = ('\n'.join(textwrap.wrap(para)) for para in paragraphs) - return '\n\n'.join(wrapped) - - -def unwrap(s): - r""" - Given a multi-line string, return an unwrapped version. - - >>> wrapped = wrap(lorem_ipsum) - >>> wrapped.count('\n') - 20 - >>> unwrapped = unwrap(wrapped) - >>> unwrapped.count('\n') - 1 - >>> print(unwrapped) - Lorem ipsum dolor sit amet, consectetur adipiscing ... - Curabitur pretium tincidunt lacus. Nulla gravida orci ... - - """ - paragraphs = re.split(r'\n\n+', s) - cleaned = (para.replace('\n', ' ') for para in paragraphs) - return '\n'.join(cleaned) - - - - -class Splitter(object): - """object that will split a string with the given arguments for each call - - >>> s = Splitter(',') - >>> s('hello, world, this is your, master calling') - ['hello', ' world', ' this is your', ' master calling'] - """ - - def __init__(self, *args): - self.args = args - - def __call__(self, s): - return s.split(*self.args) - - -def indent(string, prefix=' ' * 4): - """ - >>> indent('foo') - ' foo' - """ - return prefix + string - - -class WordSet(tuple): - """ - Given an identifier, return the words that identifier represents, - whether in camel case, underscore-separated, etc. - - >>> WordSet.parse("camelCase") - ('camel', 'Case') - - >>> WordSet.parse("under_sep") - ('under', 'sep') - - Acronyms should be retained - - >>> WordSet.parse("firstSNL") - ('first', 'SNL') - - >>> WordSet.parse("you_and_I") - ('you', 'and', 'I') - - >>> WordSet.parse("A simple test") - ('A', 'simple', 'test') - - Multiple caps should not interfere with the first cap of another word. - - >>> WordSet.parse("myABCClass") - ('my', 'ABC', 'Class') - - The result is a WordSet, so you can get the form you need. - - >>> WordSet.parse("myABCClass").underscore_separated() - 'my_ABC_Class' - - >>> WordSet.parse('a-command').camel_case() - 'ACommand' - - >>> WordSet.parse('someIdentifier').lowered().space_separated() - 'some identifier' - - Slices of the result should return another WordSet. - - >>> WordSet.parse('taken-out-of-context')[1:].underscore_separated() - 'out_of_context' - - >>> WordSet.from_class_name(WordSet()).lowered().space_separated() - 'word set' - - >>> example = WordSet.parse('figured it out') - >>> example.headless_camel_case() - 'figuredItOut' - >>> example.dash_separated() - 'figured-it-out' - - """ - - _pattern = re.compile('([A-Z]?[a-z]+)|([A-Z]+(?![a-z]))') - - def capitalized(self): - return WordSet(word.capitalize() for word in self) - - def lowered(self): - return WordSet(word.lower() for word in self) - - def camel_case(self): - return ''.join(self.capitalized()) - - def headless_camel_case(self): - words = iter(self) - first = next(words).lower() - new_words = itertools.chain((first,), WordSet(words).camel_case()) - return ''.join(new_words) - - def underscore_separated(self): - return '_'.join(self) - - def dash_separated(self): - return '-'.join(self) - - def space_separated(self): - return ' '.join(self) - - def trim_right(self, item): - """ - Remove the item from the end of the set. - - >>> WordSet.parse('foo bar').trim_right('foo') - ('foo', 'bar') - >>> WordSet.parse('foo bar').trim_right('bar') - ('foo',) - >>> WordSet.parse('').trim_right('bar') - () - """ - return self[:-1] if self and self[-1] == item else self - - def trim_left(self, item): - """ - Remove the item from the beginning of the set. - - >>> WordSet.parse('foo bar').trim_left('foo') - ('bar',) - >>> WordSet.parse('foo bar').trim_left('bar') - ('foo', 'bar') - >>> WordSet.parse('').trim_left('bar') - () - """ - return self[1:] if self and self[0] == item else self - - def trim(self, item): - """ - >>> WordSet.parse('foo bar').trim('foo') - ('bar',) - """ - return self.trim_left(item).trim_right(item) - - def __getitem__(self, item): - result = super(WordSet, self).__getitem__(item) - if isinstance(item, slice): - result = WordSet(result) - return result - - @classmethod - def parse(cls, identifier): - matches = cls._pattern.finditer(identifier) - return WordSet(match.group(0) for match in matches) - - @classmethod - def from_class_name(cls, subject): - return cls.parse(subject.__class__.__name__) - - -# for backward compatibility -words = WordSet.parse - - -def simple_html_strip(s): - r""" - Remove HTML from the string `s`. - - >>> str(simple_html_strip('')) - '' - - >>> print(simple_html_strip('A stormy day in paradise')) - A stormy day in paradise - - >>> print(simple_html_strip('Somebody tell the truth.')) - Somebody tell the truth. - - >>> print(simple_html_strip('What about
\nmultiple lines?')) - What about - multiple lines? - """ - html_stripper = re.compile('()|(<[^>]*>)|([^<]+)', re.DOTALL) - texts = (match.group(3) or '' for match in html_stripper.finditer(s)) - return ''.join(texts) - - -class SeparatedValues(str): - """ - A string separated by a separator. Overrides __iter__ for getting - the values. - - >>> list(SeparatedValues('a,b,c')) - ['a', 'b', 'c'] - - Whitespace is stripped and empty values are discarded. - - >>> list(SeparatedValues(' a, b , c, ')) - ['a', 'b', 'c'] - """ - - separator = ',' - - def __iter__(self): - parts = self.split(self.separator) - return filter(None, (part.strip() for part in parts)) - - -class Stripper: - r""" - Given a series of lines, find the common prefix and strip it from them. - - >>> lines = [ - ... 'abcdefg\n', - ... 'abc\n', - ... 'abcde\n', - ... ] - >>> res = Stripper.strip_prefix(lines) - >>> res.prefix - 'abc' - >>> list(res.lines) - ['defg\n', '\n', 'de\n'] - - If no prefix is common, nothing should be stripped. - - >>> lines = [ - ... 'abcd\n', - ... '1234\n', - ... ] - >>> res = Stripper.strip_prefix(lines) - >>> res.prefix = '' - >>> list(res.lines) - ['abcd\n', '1234\n'] - """ - - def __init__(self, prefix, lines): - self.prefix = prefix - self.lines = map(self, lines) - - @classmethod - def strip_prefix(cls, lines): - prefix_lines, lines = itertools.tee(lines) - prefix = functools.reduce(cls.common_prefix, prefix_lines) - return cls(prefix, lines) - - def __call__(self, line): - if not self.prefix: - return line - null, prefix, rest = line.partition(self.prefix) - return rest - - @staticmethod - def common_prefix(s1, s2): - """ - Return the common prefix of two lines. - """ - index = min(len(s1), len(s2)) - while s1[:index] != s2[:index]: - index -= 1 - return s1[:index] - - -def remove_prefix(text, prefix): - """ - Remove the prefix from the text if it exists. - - >>> remove_prefix('underwhelming performance', 'underwhelming ') - 'performance' - - >>> remove_prefix('something special', 'sample') - 'something special' - """ - null, prefix, rest = text.rpartition(prefix) - return rest - - -def remove_suffix(text, suffix): - """ - Remove the suffix from the text if it exists. - - >>> remove_suffix('name.git', '.git') - 'name' - - >>> remove_suffix('something special', 'sample') - 'something special' - """ - rest, suffix, null = text.partition(suffix) - return rest - - -def normalize_newlines(text): - r""" - Replace alternate newlines with the canonical newline. - - >>> normalize_newlines('Lorem Ipsum\u2029') - 'Lorem Ipsum\n' - >>> normalize_newlines('Lorem Ipsum\r\n') - 'Lorem Ipsum\n' - >>> normalize_newlines('Lorem Ipsum\x85') - 'Lorem Ipsum\n' - """ - newlines = ['\r\n', '\r', '\n', '\u0085', '\u2028', '\u2029'] - pattern = '|'.join(newlines) - return re.sub(pattern, '\n', text) - - -def _nonblank(str): - return str and not str.startswith('#') - - -@functools.singledispatch -def yield_lines(iterable): - r""" - Yield valid lines of a string or iterable. - - >>> list(yield_lines('')) - [] - >>> list(yield_lines(['foo', 'bar'])) - ['foo', 'bar'] - >>> list(yield_lines('foo\nbar')) - ['foo', 'bar'] - >>> list(yield_lines('\nfoo\n#bar\nbaz #comment')) - ['foo', 'baz #comment'] - >>> list(yield_lines(['foo\nbar', 'baz', 'bing\n\n\n'])) - ['foo', 'bar', 'baz', 'bing'] - """ - return itertools.chain.from_iterable(map(yield_lines, iterable)) - - -@yield_lines.register(str) -def _(text): - return filter(_nonblank, map(str.strip, text.splitlines())) - - -def drop_comment(line): - """ - Drop comments. - - >>> drop_comment('foo # bar') - 'foo' - - A hash without a space may be in a URL. - - >>> drop_comment('http://example.com/foo#bar') - 'http://example.com/foo#bar' - """ - return line.partition(' #')[0] - - -def join_continuation(lines): - r""" - Join lines continued by a trailing backslash. - - >>> list(join_continuation(['foo \\', 'bar', 'baz'])) - ['foobar', 'baz'] - >>> list(join_continuation(['foo \\', 'bar', 'baz'])) - ['foobar', 'baz'] - >>> list(join_continuation(['foo \\', 'bar \\', 'baz'])) - ['foobarbaz'] - - Not sure why, but... - The character preceeding the backslash is also elided. - - >>> list(join_continuation(['goo\\', 'dly'])) - ['godly'] - - A terrible idea, but... - If no line is available to continue, suppress the lines. - - >>> list(join_continuation(['foo', 'bar\\', 'baz\\'])) - ['foo'] - """ - lines = iter(lines) - for item in lines: - while item.endswith('\\'): - try: - item = item[:-2].strip() + next(lines) - except StopIteration: - return - yield item diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/jaraco/text/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_vendor/jaraco/text/__pycache__/__init__.cpython-311.pyc deleted file mode 100755 index 868fd21e74cb488404d3461925517ef77ff7f510..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26596 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 diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/more_itertools/__init__.py b/venv/lib/python3.11/site-packages/setuptools/_vendor/more_itertools/__init__.py deleted file mode 100755 index 19a169f..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_vendor/more_itertools/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from .more import * # noqa -from .recipes import * # noqa - -__version__ = '8.8.0' diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/more_itertools/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_vendor/more_itertools/__pycache__/__init__.cpython-311.pyc deleted file mode 100755 index 1d78fd5ef6335ce2d7d7e856d8276767910c1372..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 295 zcmZ3^%ge<81Xrfa$_fI~k3k$5V1hC}O92_v8B!Qh7;_jxAT%S8W{P4;VGd@{WO>O5 zRG`Uti&3kJ)k4og&%jTU`4&rVeo^Wz_M+6}%!1V7Tio&SWvNBQnfZC~@hcfVgN*)_ zs-Kaco2s9iSd^Tv@0FjPZ>*nKP@rFynpdWulbNJnP+5|ZpJ%LRXsBPDS(2(-keHmE zn4Vg!Uz}P}T2PXopHr+4G&L_JzepcsTRc!v5mY!nGcU6wK3=b&@)w6qZhlH>PO4oI n$gd!`7OMe?56p~=j5ipBFTl_Z2C)k;^ng#afg1#iIDkq4*rrqW diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/more_itertools/__pycache__/more.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_vendor/more_itertools/__pycache__/more.cpython-311.pyc deleted file mode 100755 index bdf20da2d27fc3a4bda9de4694cbe79e05e09b41..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 149182 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

Os-{E!ldZFDEOS3&+}(2D2bLx2)HDPhs? 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 Mo_kQ>f?xpu4}I2hqW}N^ diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/more_itertools/__pycache__/recipes.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_vendor/more_itertools/__pycache__/recipes.cpython-311.pyc deleted file mode 100755 index 5ba358b1f56831cab8521dd9c9053b7948a0e9be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23764 zcmd6Pd2Ae4nqO5PWRuP2Es45|ht!8C-qOk%NgnE!EosJ<#<59j$Revqw$ukz)s#pr z1<+paOw*9Ft%U^B8*9PYopI#Y$r=F?B!47W2MKnOzq)}AK=ej|b1afU0)z`?0Ac>w z{J!^IRaZ4BdS}-NQtbX%UB|2UzW3eV_v#;pLbVdM;-f#fx%8?e{a5;7Z9cK{`~z8% zK9)3TMABr0M*?ek#-{=?A+c!!JvE=SbH(Qp$H% zn)kjV-IdYmcC;GScA$lb)&>~Wb^^w5W*5#J!vEd)-;Mu!@c*zD)%N0lkG4Kh`QpwEd zilI-&XLVCC^~p>;ol??M>~K7z8<})EVJcdBaxST-GAf8 z8tFSab;DF<)H}Fd$77SKrlUtaJqlVcZS5~ZK|}pVie&soKn_MpB(Ec{93R3f_y)jwRBmY2D03y`>sMO=$9XmgX9QtedSFf(Hr zV-6jeN~oEPo)SIMjZ%;XI;PK0>a*xhiuKnlc~hC0QUk!4V^pQ;SyfA=Q+N<|#;m=# zaW`)2rJ7mQ$i!*ZaXNihH%uK3&eA|rS}A~@rZVxVg;FPtDxGvTJa#vZC*jJ3I>~0O z)V%Q```D~*BX|tMoIq2f#8NQ@(~vZs?4%M+tEQqViMW{o-6~=`b?Ox3qsU;l!l)zC z-xrPAr$_s`mHuvJ;0C|r5@S#UP2oGGV_v|pYRd74JtZFv#HazDKKGPlObU@6J<=ppDax<4-Wf1=Z&EcT)4i{yr_+PI z>g;Uq9X)l2__CL?>0nQPf3Jyq56?mhs9=^}klNfVlRv#?{PkioveDuj@I^OMg>3Sd`q9;GTIm zRS+GhpMxv}DPT?*J~C-Tf$*YfB5`ZZB_PBgX2-{gsv{&YGSTtzZZ<8>gUTVLpH8^0 z#K8d^?CB8`7o$dEiaC>>OK1>_ATLWg6J2B!b&@0jo|w{=cq*e$qbI5{&1AZ010)q= z-2l~^N-CXE%vq>~sW=oxJfmp(l*&4tNh^Il%B75QHx7!zv*M{qgYh>m)YZuuHiS$Z z@|?zMj~-Ox$!31|BVzq4C8 zJXq!wn~{dP?R&~+M_=hya00B`=nlEKHS-D9LMCQ5oJ6lm$ zLah`)F@`^|WlYRB!xNBBl9Pl^c=+_0v**rV2yb5YQ70l9@&yfD3UkI!fTjbY?#Q5Z6fD>Cerq-p)5h3ysktU@%q;#`3<{ zM(kDNCTje73gBaDQC@0s3hPBl^L*)bV~uRZYcA%^_;It?7SYC{{2AK(g4$)9R)Kfk zLe!_ejZ20(`6^{pDiaG#US|xgp*dJtCDv@Lw zYyqVKge#Mz5Q$Hs$L&@X<$N4y>o{R%w0P=NM>h}vi3w?ev7Jc5@=EBZ?5nS3(zBOH z*%3~idfCQ1%v4jTXG{ew0SHQ1m3)#g9W+xmx*4v!=@@&0dj@T3E09&Gvg4ahgi~`9 zY8;q8^8XLgt{P-17{>vkUM4_FKAL%ERFFuv$k^z|B`&$rOg9pU)0qnZOVaxHWhqdz zwD6aKPI%m>%p;A%{3fY02#Njh)@kuyqq#wy`br81YMn*;neccMfOgF>j z4NkNJ98YAd!6`P5V(=E0eAKcFQ5`sI5cm>b%NMAJnf8&H8(L{AG;|ajItszgVz4vs z>)c47TVTcQ3xFJ5%sOnqt&Q5;AdJxN})Wjajg2(HA*U*S=p ziMe?WaZgFyx9>O-K;g_L1 z#8xSAU=TtXZRzFTvE&F5x;>rtT#^OIsGd_Si2!Ctiy%y7v_pkm(J|3+gJd?Js?o4Y zcJ%~-4SSZK;$t{0g(zyrd|-028A?ljILZlKFvLbJxf6pm2>cno<^cc*4)8-$F}Ux^ zonPorFa9k3^YmA@3;SOw?ti5aJYEbQ&-;#Vf$BHWh8xvRIh>)%7TZmd^lT%0+pQPf z%tNm8Jt0ImuOQq-<`KoaEMm;uO>^st0t^lbQjUy8Mk#X9-v{)LlI|Pm6Cz}&uTKaO zpK%U7VnU=8NF(y3!aauSZ!U+6dJmV z4c&#{;bQP`-gkJTU?E&E%}1_~8-Ha|tt3f?m;We)tJ60SQ9t5a^6L`_c(D*q3V}vC z2$tnxCPE(3poK6?f-t%itwctdtYBCJVcxj0NzjLma}-wc`(!$iP-jgY4$s}0IF#lj zIx1RLfY(eM^vQe3!XBcFVgfDk@EWj!7;KRG^@FL))MKZZ*pAZ%fxp1l+y($LZsugX z^4o>rpz6iiv$GvXX(Mh~8*0z-CTiv-qdbnf>O{97Oht81eA!0V< z;3+Z0V$2w%KZTEVEwO;mo9*yfQx1x^LrBcR5Md;NL~=fv++hx=9lK!;h0QYDjeyUR zq?k5j_7wJ^dJrNabuF5m)p^L*JkDp^q8FAgu=s`I@kk>esH3^;9j@_DDsEqm1_F^Fcp22CX*(X)F&xv-gMv#;n_oQQYH!a5G8J z{tx_d`HAQyISlWeT^e4x{md80Hf7JgcjbdCOIMyXH0Szr>hi*ag}krrWgjMRqq4CN ztxnn&7k&`=F`}SQ=(iIErc-iECtSDBWy;Al+n6X1i>IQl?>%evzUpId7@jYuf zusTy{=`FVO<^wPNaFs#bwKj?q((mV=0aVg*2Gnb9ZgbJt=cL%O?W4&V^6tduzDJhG zGP)0b$Phb=t&(G=5v#n1UfuU*Le@2swCL45i=Mdr_YvoWpSyAfdKfueMN=~>^gmqK zsrbCE9Y%z98hU1OW-fIL3fNF466wiXmOWtGs4StW8xcDe3}S{!Iv=*lJv>Y{>S+RJ z!bIocv$QW_!|cEXIxx?H#R2yYiKY?dL{mrjS}-an5LU zsWxuLQwYVwXDWFyq*4GWVhW)_$kAS@`K%5P5S}HXaDR`VGAIdT5T2sGa!A7%r=xEH zm?W-9t8vM=gN_r}L&T$EhuO!0=3L~-nL@QvtX9?~pTFZ-pz%Ryt?rfo@VzU4<@MCm z{vQcooq;N8$Np70dn_wIt82`)Enj_bH6Pr)q85Vtm(D&5Zhv|`9~@ZS2|yp;0H-)S z$==97A?f^l9pKxU#T^;ZYy?{Cg#I-#4fF<{nUCtDq;HK@$9yqHX7Ui!lXx?iQeGy@Q4Y+?N zt|v4r0G{M>nZ;l%YN0eHD1`FyFmNaI%v~x0fFqU^RuE09P0r<1F{5ZANlvZjErO=Y zM>$QG>6lSBOLUyE5*^n`PFtBF;gg8C26FhY%jPn(6k#`Q;f*Alk2Yw*cjXu;5gWefkwV)uaqA7uxxz zWB5GvJnqUF4yQA>j;Sp;E{dmgjLzU#Z4M6{;7IO9uIr z{M31qDbWgn5J5u*fo|&9zs8QxmTeL=Vstt6AhmSiSzVLpXdM3wO~;CWb;pWz$Cl2m z)i$k5RsMl>kH2PMt!?kRB!@W2`PR1Y%4rX$9!=%y_}{u0Ctv(!!yXbP17)yQ*OI%v zd^vmJS?kUx2UoW}tuE~9EAHwmwDuQU`?KfhZ{3euUc7j*ULysY`6JnL-N2-%;Xi2_ zmZYzx?%`hV*F7?zD>+HZjw!sKVCSb$dCSsLbq4#^_Mw!OP%7p5Ah0M`3Ytno&P_?o z*z?}^X| zfQp-AX-$Jm`K>@A)3|A)zE4pM-5NYal{XnZ?|{{Mc{KLe z9gSFnFE>@bo{e5~DI6Aq=K*W#ml*ri%|$Pn=Z|Gu_%_{_J<>AiOGub6NQ$v-QJ(S$ zaocQ*+s`R2MhUKxJa3%Ge_`M+aqHz4j@;X0PxdC_b%dlCg_>hFu zj5!=}`6Zon{5K9`1~z~@Fy=Ff^qk6(d!>q_Bxyo zghj8ruuHwBL(UKDHN_%{U6`vE^|P7hUS3cqQ<6SQrG( z(DQZdynwqOkpgu~i_aQbvc7K|)BUs!Ghb*PC^io)z5XoJnA=?l?Jb7(zIT4420MH-ny!F$?LD$h;Qxe?r>AhTqd!4;*LUL(xng90uhciL=8ZlNZEE1i);2i`gM`z*X$!J9rlGm7<}9ss=a_JyvY za%p!3q7^W#7^mwtH(69%$vaxsF{6&2+I^&suqIuqg&3a6;$zrxsFqf@UC)#Z=(?QK z5(;LUEuRs)p~h@2W0YhocIebGyDjW)qGIlllsSw>EETiwN`Bv!uhb`tPlul(vD9DO z-;VfALJCin{44-#Bcsc?e*@U)pSwM2_}ZSb19jg!E#3Dm`pWX`zMrZ@=H&ZTzU&>SG9QMtDppDx7w0-bYjvDG1%TL%w+0fDOKxK&&MA@G!R1 zr%#_bbC&(z#1&@__!;i5yIGL&(#96i+T<`f@Tf%YNl=-(llfgSD;5I~>~u}!;!OxS zM8{Mm8J{P=0##cxyigmF+PRedliAoTwS}@*Zora!xK4frV(%1y;^GpgP1X(g@jZGE zig$kyN&OflyHV!oS2iio_9jYDn0L>-k@0aF>^MZ`#7!14qskP=orjf$^c?F9dcuTi z?3TU|W7B1a(x`|f14c4gtbrsiHA+WSg}YG^p09&NZVfYv)2tOPn^iUxEq#~PeK^IT zWl%#Rb7g1e4!K(}Ao8wsk1e1p=gw**8m0WlH6YD?#wgREcB6j-La-X^R)C39T6iriWteV{y<;4u-3fu(V?Z+*BY9ZF0Qrge)Q_n z<+b{zmDX%}>B2WHyVs=}|2_t?)oXh?^L2gMGubn_>gCH1E@v-4-I0~oJ=Hb))*2dD zs`Cx|@mXu!oeQoEKdgULpQ~TnzBd=5zZWl_HMGI{tU+TIpqm2u1_htB#yz>Zl{X$X zJZi`_IBr_6#>Esm30d7>VUmB@G92=J9ojp5*#C964Co4z)MA_viqi8efZLXJW(Ayq zwU=cC+%nv0&9X`fm&&e)s=CgRq`vo`h1qJCp}>Y?A{kEqbP9Pbh-irFI7)xZ))nXH zO5U`V$slIBxug~WQ>T=MR27K<&Zb+m`BGWEp;^}ASt|rR&Qt{I zh4RKy!9^J=8_CRfSn0Z@j-iU*Mz6&jTgyjSu*nVagh00laXpi45VsIzOrIsv>DdaMLlv-AP1`04fjS{p zy+sl|v+3Dx3r`FkC6SgNtRS@N@Rp*v2|hHDH0|CH#6 zQmS0;t+!SALu=pW3_sBIn*P6HIx*i^UbTA9qmc5LaZ_UmZ z-vnC`8TN3G=-FaP4tCjMqt6Ejp;2PfD7In_bJyTg{=J=ao~6qip^t>kDZ`l6IT7AjW($oQxxskeY^xN^#MOMqepYrhOsD z5~LaBY)VzghyvpvQHmoP!vxL)xJi>rq6`9mMx;q8afrAMUYwm-dArbfu-JGIS%hF; zG1!;)^*P)xnN^WY;uf~yeu*R-WmKNO34rC>lw#Zv`CpV+QrhEGc*qg3B%@pUxz!yD zw@^3F8tPpVRBW12hD7x-aI=|gqOvHqy-Wi+K9%gtyHKz8`WdR^5H(aHqaaqt zF&aU^&t0)T+Lg`x_CaW_QSk1Z9N2OoR6h#w7N%RVoQ8FPr7z*^#1S{7wJ+oqsJF-_ zP%VU;upGDtL#P*QM(7qLD7*|a!Yb8JniZpk+S8EmVhkH16D>qJWFCHuMfu1!BH-<$ zk;=gLL(hX|WEWYWSTXYXr4jcVe*oYd z1`l|*zqJ2W>hyn6_anGj#O@pW@{N6~U5~e~_#WiI4 ztI#fKq325gZtYZA+(M-ZOAYQ~Ft@xw7({j>-f31t!);l3!1No%h`4GiQ+>>cp(>Tt z#yA$BlUYJa&S^}S7ySu}Ck2MPVOF`<%EH;hv2l9=AR5BDY+Pxrr(xVjo;ZK5Nab&6 z-%>0Vft1(B3w3sc`^+y9Xpm(nTcheUDop#%#6Ycjny_7{Tf#bA5h*UlN31ckMc_F@$H@3He!-_|tvq0dQw%RV>#A;V1pK(W0n z4N+M;yfsy#lnZ0Fwyck*I5uX;-92IM-d}G)$She=US#sEgj_*rj#oq2ghra=<@Kqo z=8?)Bzbh(pbm1jb=2AB_#Y|3+Z`G{HBEue6!pvTQ<8AlXBcip3cDc0l|Zg zemNA4C8+B`de5nX%L;)v#`29ZWL8^q>Z2Xlt@to{McmtF7rYOIy_bctjqyHO!dYhT zEn#1*%EN*nyeh=xT_uvF=@a4bF1m~Wa?9K`p>Q}>=h@8kED+?31SYC)ef-vwbF1y2 zT>SLns#@3Z8T_C~8|s)R#NF8pf|eW2^}H@)g>)!2fe};iule8^e9*buwJm zyD|S)X+mtB-va|zG8>h$c(%TanW@*dRvZ=lwz<;a@jm$3>APfh(JW$-HQw`5Rx&Wk z5ahF*_|0uY2L*0;y^7#gN+2GIBAEIT#Q>Ecw8D3(7#tllH}-5(P2u8U+t#A+j)R9Q ztgYpW#TlDfTlHuGN{0$2j6WvO4Z zE4LrM`{-T#sQ7HOEdP!Y%lM=3bVU0xBID6aC;}>-FeLCutM4!=7!m3LO zeP2kSPC7xLi7+*dofjmA_Adv{S z)<*J?en0h2n6Sc?;HX<|VM;let#$q*9HIT!NJzRO;|Db8n zWA)4M!wmM{3*k7jkJeH27DsOpCaAaM4~Xr38Cgjb^BLFh1Xf$V=%ZE_edr54jp}{z zAL}%H$XAwI+0C9qmB2V=jgR%pb-(+ruXZm6R!Ku_*iggn#gp-*vZi)ppK6c4y5^MM zm03*4X`f08_?*khfH`Eo67#$j)Ke4|6#j4_8!PElfrM zm7=h>aN*@6)MI!PSj{qt*M?xhop?nEZ-=xCnS2N{VG-|~$vk;St5(gwW%X5b$7%AB z9$~lBwY1QMd3}k6*H5w;LZ3=Pueb+J<{2kOIdmo7 z*S|cs9C{GKfe>4uv(o-hUmklfMsehJ2D0*6T`1R-d*k6YRQT;&{=v%aLY^cdEFVdV@82k`bRytDxPv(b#h zIx_3sNkm%|^kp|AB@ylm+l)fTnY}~n&XBDL_ahJ&9w0DSQM^hast6dBlD84omgALG zW!4)-^SImH4tw79H1RpzUS4F&+A%2$V^?97!+7kahP((2y%Y6h?2a*hN|>Ff2qL_q z1kumV8n5D)D|*$A0|tT1MAF-_1Cnkdl0J~zu@b3xy8^DUw*dA!@qK;~v#_y{rqZm( zt2UvCe%D)84u}IeRdq$_pW9Q{ydVM3mp(TUEPBLJDvA(@4R3ZJ&J`O}l1KBCQgYwv z{sjd+4Aa27%G9fMul0YiB8GtFj8M+jmZ9K?*fJC$6x&U^7cd^YTP>Iu#_wr*$yKyU zJq>hHQjcC0$w=6;y768&Q@601Mo&}{HopPn%hok=$?sAJMCJTeqH!n& z%BXFUk)zTH>QIEYNR=7%JZE_hZlPD~f_m{rO-c=P(<&U|V3fnKp)pP&&5%su4J6P&$d961^lnWA@WDDJIMq&z zUNyeJM3mo1#M92TWyQf>P*i@M1=AAc_X!x3ls2vcME&sR8Qx1(yeC{|RKWp6H4U$T zCb}VEqVRe)3Yr@PMv1BZ5q3mPMVkZ>dvy86gBvSD_SD|1+qfg_br!d}M5mh>)t1hP~^7y>5Ul znr4e<*$PwR$2eOG^0(+R1Bk61Wb1`k#kHZ(?Uegq^#&|i%+hi!)XsvPEK0+iBxV*c zLCPkcMWh%id9EX1y>-l>RY>4)$vg+)hy1XN>X?A+TbBqlOLF5<1O2T@d-Lwkx+f@m z)}{aVpv}>#?!5HU&$@445FNC@QuX?2IV2xgmu#Rk$l-O#4Y~sIAsV~@+Yiv58~jkN zm50_PH`o=F`v@BX?2-1uVyc$ADnV;dj?#4k?2&>k=vh^@{5`r-fYxfchkgpsS|fw0 zY|z$5C*0s@P~J(+3b3a}j;{HR<=vn4TG@~O*`P{lYcKAIEL|-6TJyfv7wZjDpatit z6$`92v@KnvKcbDDRM*rRk_QQiPN1~PSYc*^o;@<^_HA&gRlX|IX&d&$WK>nT!H8TV zzlO^;z_w-?r3`KmYm)odB{zsj9i5fO%9lhM9oPVCK*z0BQQx4d>yVDJ}G^Dvifwj_uo{>fd3ci1M*n_ diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/more_itertools/more.py b/venv/lib/python3.11/site-packages/setuptools/_vendor/more_itertools/more.py deleted file mode 100755 index e6fca4d..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_vendor/more_itertools/more.py +++ /dev/null @@ -1,3824 +0,0 @@ -import warnings - -from collections import Counter, defaultdict, deque, abc -from collections.abc import Sequence -from functools import partial, reduce, wraps -from heapq import merge, heapify, heapreplace, heappop -from itertools import ( - chain, - compress, - count, - cycle, - dropwhile, - groupby, - islice, - repeat, - starmap, - takewhile, - tee, - zip_longest, -) -from math import exp, factorial, floor, log -from queue import Empty, Queue -from random import random, randrange, uniform -from operator import itemgetter, mul, sub, gt, lt -from sys import hexversion, maxsize -from time import monotonic - -from .recipes import ( - consume, - flatten, - pairwise, - powerset, - take, - unique_everseen, -) - -__all__ = [ - 'AbortThread', - 'adjacent', - 'always_iterable', - 'always_reversible', - 'bucket', - 'callback_iter', - 'chunked', - 'circular_shifts', - 'collapse', - 'collate', - 'consecutive_groups', - 'consumer', - 'countable', - 'count_cycle', - 'mark_ends', - 'difference', - 'distinct_combinations', - 'distinct_permutations', - 'distribute', - 'divide', - 'exactly_n', - 'filter_except', - 'first', - 'groupby_transform', - 'ilen', - 'interleave_longest', - 'interleave', - 'intersperse', - 'islice_extended', - 'iterate', - 'ichunked', - 'is_sorted', - 'last', - 'locate', - 'lstrip', - 'make_decorator', - 'map_except', - 'map_reduce', - 'nth_or_last', - 'nth_permutation', - 'nth_product', - 'numeric_range', - 'one', - 'only', - 'padded', - 'partitions', - 'set_partitions', - 'peekable', - 'repeat_last', - 'replace', - 'rlocate', - 'rstrip', - 'run_length', - 'sample', - 'seekable', - 'SequenceView', - 'side_effect', - 'sliced', - 'sort_together', - 'split_at', - 'split_after', - 'split_before', - 'split_when', - 'split_into', - 'spy', - 'stagger', - 'strip', - 'substrings', - 'substrings_indexes', - 'time_limited', - 'unique_to_each', - 'unzip', - 'windowed', - 'with_iter', - 'UnequalIterablesError', - 'zip_equal', - 'zip_offset', - 'windowed_complete', - 'all_unique', - 'value_chain', - 'product_index', - 'combination_index', - 'permutation_index', -] - -_marker = object() - - -def chunked(iterable, n, strict=False): - """Break *iterable* into lists of length *n*: - - >>> list(chunked([1, 2, 3, 4, 5, 6], 3)) - [[1, 2, 3], [4, 5, 6]] - - By the default, the last yielded list will have fewer than *n* elements - if the length of *iterable* is not divisible by *n*: - - >>> list(chunked([1, 2, 3, 4, 5, 6, 7, 8], 3)) - [[1, 2, 3], [4, 5, 6], [7, 8]] - - To use a fill-in value instead, see the :func:`grouper` recipe. - - If the length of *iterable* is not divisible by *n* and *strict* is - ``True``, then ``ValueError`` will be raised before the last - list is yielded. - - """ - iterator = iter(partial(take, n, iter(iterable)), []) - if strict: - - def ret(): - for chunk in iterator: - if len(chunk) != n: - raise ValueError('iterable is not divisible by n.') - yield chunk - - return iter(ret()) - else: - return iterator - - -def first(iterable, default=_marker): - """Return the first item of *iterable*, or *default* if *iterable* is - empty. - - >>> first([0, 1, 2, 3]) - 0 - >>> first([], 'some default') - 'some default' - - If *default* is not provided and there are no items in the iterable, - raise ``ValueError``. - - :func:`first` is useful when you have a generator of expensive-to-retrieve - values and want any arbitrary one. It is marginally shorter than - ``next(iter(iterable), default)``. - - """ - try: - return next(iter(iterable)) - except StopIteration as e: - if default is _marker: - raise ValueError( - 'first() was called on an empty iterable, and no ' - 'default value was provided.' - ) from e - return default - - -def last(iterable, default=_marker): - """Return the last item of *iterable*, or *default* if *iterable* is - empty. - - >>> last([0, 1, 2, 3]) - 3 - >>> last([], 'some default') - 'some default' - - If *default* is not provided and there are no items in the iterable, - raise ``ValueError``. - """ - try: - if isinstance(iterable, Sequence): - return iterable[-1] - # Work around https://bugs.python.org/issue38525 - elif hasattr(iterable, '__reversed__') and (hexversion != 0x030800F0): - return next(reversed(iterable)) - else: - return deque(iterable, maxlen=1)[-1] - except (IndexError, TypeError, StopIteration): - if default is _marker: - raise ValueError( - 'last() was called on an empty iterable, and no default was ' - 'provided.' - ) - return default - - -def nth_or_last(iterable, n, default=_marker): - """Return the nth or the last item of *iterable*, - or *default* if *iterable* is empty. - - >>> nth_or_last([0, 1, 2, 3], 2) - 2 - >>> nth_or_last([0, 1], 2) - 1 - >>> nth_or_last([], 0, 'some default') - 'some default' - - If *default* is not provided and there are no items in the iterable, - raise ``ValueError``. - """ - return last(islice(iterable, n + 1), default=default) - - -class peekable: - """Wrap an iterator to allow lookahead and prepending elements. - - Call :meth:`peek` on the result to get the value that will be returned - by :func:`next`. This won't advance the iterator: - - >>> p = peekable(['a', 'b']) - >>> p.peek() - 'a' - >>> next(p) - 'a' - - Pass :meth:`peek` a default value to return that instead of raising - ``StopIteration`` when the iterator is exhausted. - - >>> p = peekable([]) - >>> p.peek('hi') - 'hi' - - peekables also offer a :meth:`prepend` method, which "inserts" items - at the head of the iterable: - - >>> p = peekable([1, 2, 3]) - >>> p.prepend(10, 11, 12) - >>> next(p) - 10 - >>> p.peek() - 11 - >>> list(p) - [11, 12, 1, 2, 3] - - peekables can be indexed. Index 0 is the item that will be returned by - :func:`next`, index 1 is the item after that, and so on: - The values up to the given index will be cached. - - >>> p = peekable(['a', 'b', 'c', 'd']) - >>> p[0] - 'a' - >>> p[1] - 'b' - >>> next(p) - 'a' - - Negative indexes are supported, but be aware that they will cache the - remaining items in the source iterator, which may require significant - storage. - - To check whether a peekable is exhausted, check its truth value: - - >>> p = peekable(['a', 'b']) - >>> if p: # peekable has items - ... list(p) - ['a', 'b'] - >>> if not p: # peekable is exhausted - ... list(p) - [] - - """ - - def __init__(self, iterable): - self._it = iter(iterable) - self._cache = deque() - - def __iter__(self): - return self - - def __bool__(self): - try: - self.peek() - except StopIteration: - return False - return True - - def peek(self, default=_marker): - """Return the item that will be next returned from ``next()``. - - Return ``default`` if there are no items left. If ``default`` is not - provided, raise ``StopIteration``. - - """ - if not self._cache: - try: - self._cache.append(next(self._it)) - except StopIteration: - if default is _marker: - raise - return default - return self._cache[0] - - def prepend(self, *items): - """Stack up items to be the next ones returned from ``next()`` or - ``self.peek()``. The items will be returned in - first in, first out order:: - - >>> p = peekable([1, 2, 3]) - >>> p.prepend(10, 11, 12) - >>> next(p) - 10 - >>> list(p) - [11, 12, 1, 2, 3] - - It is possible, by prepending items, to "resurrect" a peekable that - previously raised ``StopIteration``. - - >>> p = peekable([]) - >>> next(p) - Traceback (most recent call last): - ... - StopIteration - >>> p.prepend(1) - >>> next(p) - 1 - >>> next(p) - Traceback (most recent call last): - ... - StopIteration - - """ - self._cache.extendleft(reversed(items)) - - def __next__(self): - if self._cache: - return self._cache.popleft() - - return next(self._it) - - def _get_slice(self, index): - # Normalize the slice's arguments - step = 1 if (index.step is None) else index.step - if step > 0: - start = 0 if (index.start is None) else index.start - stop = maxsize if (index.stop is None) else index.stop - elif step < 0: - start = -1 if (index.start is None) else index.start - stop = (-maxsize - 1) if (index.stop is None) else index.stop - else: - raise ValueError('slice step cannot be zero') - - # If either the start or stop index is negative, we'll need to cache - # the rest of the iterable in order to slice from the right side. - if (start < 0) or (stop < 0): - self._cache.extend(self._it) - # Otherwise we'll need to find the rightmost index and cache to that - # point. - else: - n = min(max(start, stop) + 1, maxsize) - cache_len = len(self._cache) - if n >= cache_len: - self._cache.extend(islice(self._it, n - cache_len)) - - return list(self._cache)[index] - - def __getitem__(self, index): - if isinstance(index, slice): - return self._get_slice(index) - - cache_len = len(self._cache) - if index < 0: - self._cache.extend(self._it) - elif index >= cache_len: - self._cache.extend(islice(self._it, index + 1 - cache_len)) - - return self._cache[index] - - -def collate(*iterables, **kwargs): - """Return a sorted merge of the items from each of several already-sorted - *iterables*. - - >>> list(collate('ACDZ', 'AZ', 'JKL')) - ['A', 'A', 'C', 'D', 'J', 'K', 'L', 'Z', 'Z'] - - Works lazily, keeping only the next value from each iterable in memory. Use - :func:`collate` to, for example, perform a n-way mergesort of items that - don't fit in memory. - - If a *key* function is specified, the iterables will be sorted according - to its result: - - >>> key = lambda s: int(s) # Sort by numeric value, not by string - >>> list(collate(['1', '10'], ['2', '11'], key=key)) - ['1', '2', '10', '11'] - - - If the *iterables* are sorted in descending order, set *reverse* to - ``True``: - - >>> list(collate([5, 3, 1], [4, 2, 0], reverse=True)) - [5, 4, 3, 2, 1, 0] - - If the elements of the passed-in iterables are out of order, you might get - unexpected results. - - On Python 3.5+, this function is an alias for :func:`heapq.merge`. - - """ - warnings.warn( - "collate is no longer part of more_itertools, use heapq.merge", - DeprecationWarning, - ) - return merge(*iterables, **kwargs) - - -def consumer(func): - """Decorator that automatically advances a PEP-342-style "reverse iterator" - to its first yield point so you don't have to call ``next()`` on it - manually. - - >>> @consumer - ... def tally(): - ... i = 0 - ... while True: - ... print('Thing number %s is %s.' % (i, (yield))) - ... i += 1 - ... - >>> t = tally() - >>> t.send('red') - Thing number 0 is red. - >>> t.send('fish') - Thing number 1 is fish. - - Without the decorator, you would have to call ``next(t)`` before - ``t.send()`` could be used. - - """ - - @wraps(func) - def wrapper(*args, **kwargs): - gen = func(*args, **kwargs) - next(gen) - return gen - - return wrapper - - -def ilen(iterable): - """Return the number of items in *iterable*. - - >>> ilen(x for x in range(1000000) if x % 3 == 0) - 333334 - - This consumes the iterable, so handle with care. - - """ - # This approach was selected because benchmarks showed it's likely the - # fastest of the known implementations at the time of writing. - # See GitHub tracker: #236, #230. - counter = count() - deque(zip(iterable, counter), maxlen=0) - return next(counter) - - -def iterate(func, start): - """Return ``start``, ``func(start)``, ``func(func(start))``, ... - - >>> from itertools import islice - >>> list(islice(iterate(lambda x: 2*x, 1), 10)) - [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] - - """ - while True: - yield start - start = func(start) - - -def with_iter(context_manager): - """Wrap an iterable in a ``with`` statement, so it closes once exhausted. - - For example, this will close the file when the iterator is exhausted:: - - upper_lines = (line.upper() for line in with_iter(open('foo'))) - - Any context manager which returns an iterable is a candidate for - ``with_iter``. - - """ - with context_manager as iterable: - yield from iterable - - -def one(iterable, too_short=None, too_long=None): - """Return the first item from *iterable*, which is expected to contain only - that item. Raise an exception if *iterable* is empty or has more than one - item. - - :func:`one` is useful for ensuring that an iterable contains only one item. - For example, it can be used to retrieve the result of a database query - that is expected to return a single row. - - If *iterable* is empty, ``ValueError`` will be raised. You may specify a - different exception with the *too_short* keyword: - - >>> it = [] - >>> one(it) # doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ... - ValueError: too many items in iterable (expected 1)' - >>> too_short = IndexError('too few items') - >>> one(it, too_short=too_short) # doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ... - IndexError: too few items - - Similarly, if *iterable* contains more than one item, ``ValueError`` will - be raised. You may specify a different exception with the *too_long* - keyword: - - >>> it = ['too', 'many'] - >>> one(it) # doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ... - ValueError: Expected exactly one item in iterable, but got 'too', - 'many', and perhaps more. - >>> too_long = RuntimeError - >>> one(it, too_long=too_long) # doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ... - RuntimeError - - Note that :func:`one` attempts to advance *iterable* twice to ensure there - is only one item. See :func:`spy` or :func:`peekable` to check iterable - contents less destructively. - - """ - it = iter(iterable) - - try: - first_value = next(it) - except StopIteration as e: - raise ( - too_short or ValueError('too few items in iterable (expected 1)') - ) from e - - try: - second_value = next(it) - except StopIteration: - pass - else: - msg = ( - 'Expected exactly one item in iterable, but got {!r}, {!r}, ' - 'and perhaps more.'.format(first_value, second_value) - ) - raise too_long or ValueError(msg) - - return first_value - - -def distinct_permutations(iterable, r=None): - """Yield successive distinct permutations of the elements in *iterable*. - - >>> sorted(distinct_permutations([1, 0, 1])) - [(0, 1, 1), (1, 0, 1), (1, 1, 0)] - - Equivalent to ``set(permutations(iterable))``, except duplicates are not - generated and thrown away. For larger input sequences this is much more - efficient. - - Duplicate permutations arise when there are duplicated elements in the - input iterable. The number of items returned is - `n! / (x_1! * x_2! * ... * x_n!)`, where `n` is the total number of - items input, and each `x_i` is the count of a distinct item in the input - sequence. - - If *r* is given, only the *r*-length permutations are yielded. - - >>> sorted(distinct_permutations([1, 0, 1], r=2)) - [(0, 1), (1, 0), (1, 1)] - >>> sorted(distinct_permutations(range(3), r=2)) - [(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)] - - """ - # Algorithm: https://w.wiki/Qai - def _full(A): - while True: - # Yield the permutation we have - yield tuple(A) - - # Find the largest index i such that A[i] < A[i + 1] - for i in range(size - 2, -1, -1): - if A[i] < A[i + 1]: - break - # If no such index exists, this permutation is the last one - else: - return - - # Find the largest index j greater than j such that A[i] < A[j] - for j in range(size - 1, i, -1): - if A[i] < A[j]: - break - - # Swap the value of A[i] with that of A[j], then reverse the - # sequence from A[i + 1] to form the new permutation - A[i], A[j] = A[j], A[i] - A[i + 1 :] = A[: i - size : -1] # A[i + 1:][::-1] - - # Algorithm: modified from the above - def _partial(A, r): - # Split A into the first r items and the last r items - head, tail = A[:r], A[r:] - right_head_indexes = range(r - 1, -1, -1) - left_tail_indexes = range(len(tail)) - - while True: - # Yield the permutation we have - yield tuple(head) - - # Starting from the right, find the first index of the head with - # value smaller than the maximum value of the tail - call it i. - pivot = tail[-1] - for i in right_head_indexes: - if head[i] < pivot: - break - pivot = head[i] - else: - return - - # Starting from the left, find the first value of the tail - # with a value greater than head[i] and swap. - for j in left_tail_indexes: - if tail[j] > head[i]: - head[i], tail[j] = tail[j], head[i] - break - # If we didn't find one, start from the right and find the first - # index of the head with a value greater than head[i] and swap. - else: - for j in right_head_indexes: - if head[j] > head[i]: - head[i], head[j] = head[j], head[i] - break - - # Reverse head[i + 1:] and swap it with tail[:r - (i + 1)] - tail += head[: i - r : -1] # head[i + 1:][::-1] - i += 1 - head[i:], tail[:] = tail[: r - i], tail[r - i :] - - items = sorted(iterable) - - size = len(items) - if r is None: - r = size - - if 0 < r <= size: - return _full(items) if (r == size) else _partial(items, r) - - return iter(() if r else ((),)) - - -def intersperse(e, iterable, n=1): - """Intersperse filler element *e* among the items in *iterable*, leaving - *n* items between each filler element. - - >>> list(intersperse('!', [1, 2, 3, 4, 5])) - [1, '!', 2, '!', 3, '!', 4, '!', 5] - - >>> list(intersperse(None, [1, 2, 3, 4, 5], n=2)) - [1, 2, None, 3, 4, None, 5] - - """ - if n == 0: - raise ValueError('n must be > 0') - elif n == 1: - # interleave(repeat(e), iterable) -> e, x_0, e, e, x_1, e, x_2... - # islice(..., 1, None) -> x_0, e, e, x_1, e, x_2... - return islice(interleave(repeat(e), iterable), 1, None) - else: - # interleave(filler, chunks) -> [e], [x_0, x_1], [e], [x_2, x_3]... - # islice(..., 1, None) -> [x_0, x_1], [e], [x_2, x_3]... - # flatten(...) -> x_0, x_1, e, x_2, x_3... - filler = repeat([e]) - chunks = chunked(iterable, n) - return flatten(islice(interleave(filler, chunks), 1, None)) - - -def unique_to_each(*iterables): - """Return the elements from each of the input iterables that aren't in the - other input iterables. - - For example, suppose you have a set of packages, each with a set of - dependencies:: - - {'pkg_1': {'A', 'B'}, 'pkg_2': {'B', 'C'}, 'pkg_3': {'B', 'D'}} - - If you remove one package, which dependencies can also be removed? - - If ``pkg_1`` is removed, then ``A`` is no longer necessary - it is not - associated with ``pkg_2`` or ``pkg_3``. Similarly, ``C`` is only needed for - ``pkg_2``, and ``D`` is only needed for ``pkg_3``:: - - >>> unique_to_each({'A', 'B'}, {'B', 'C'}, {'B', 'D'}) - [['A'], ['C'], ['D']] - - If there are duplicates in one input iterable that aren't in the others - they will be duplicated in the output. Input order is preserved:: - - >>> unique_to_each("mississippi", "missouri") - [['p', 'p'], ['o', 'u', 'r']] - - It is assumed that the elements of each iterable are hashable. - - """ - pool = [list(it) for it in iterables] - counts = Counter(chain.from_iterable(map(set, pool))) - uniques = {element for element in counts if counts[element] == 1} - return [list(filter(uniques.__contains__, it)) for it in pool] - - -def windowed(seq, n, fillvalue=None, step=1): - """Return a sliding window of width *n* over the given iterable. - - >>> all_windows = windowed([1, 2, 3, 4, 5], 3) - >>> list(all_windows) - [(1, 2, 3), (2, 3, 4), (3, 4, 5)] - - When the window is larger than the iterable, *fillvalue* is used in place - of missing values: - - >>> list(windowed([1, 2, 3], 4)) - [(1, 2, 3, None)] - - Each window will advance in increments of *step*: - - >>> list(windowed([1, 2, 3, 4, 5, 6], 3, fillvalue='!', step=2)) - [(1, 2, 3), (3, 4, 5), (5, 6, '!')] - - To slide into the iterable's items, use :func:`chain` to add filler items - to the left: - - >>> iterable = [1, 2, 3, 4] - >>> n = 3 - >>> padding = [None] * (n - 1) - >>> list(windowed(chain(padding, iterable), 3)) - [(None, None, 1), (None, 1, 2), (1, 2, 3), (2, 3, 4)] - """ - if n < 0: - raise ValueError('n must be >= 0') - if n == 0: - yield tuple() - return - if step < 1: - raise ValueError('step must be >= 1') - - window = deque(maxlen=n) - i = n - for _ in map(window.append, seq): - i -= 1 - if not i: - i = step - yield tuple(window) - - size = len(window) - if size < n: - yield tuple(chain(window, repeat(fillvalue, n - size))) - elif 0 < i < min(step, n): - window += (fillvalue,) * i - yield tuple(window) - - -def substrings(iterable): - """Yield all of the substrings of *iterable*. - - >>> [''.join(s) for s in substrings('more')] - ['m', 'o', 'r', 'e', 'mo', 'or', 're', 'mor', 'ore', 'more'] - - Note that non-string iterables can also be subdivided. - - >>> list(substrings([0, 1, 2])) - [(0,), (1,), (2,), (0, 1), (1, 2), (0, 1, 2)] - - """ - # The length-1 substrings - seq = [] - for item in iter(iterable): - seq.append(item) - yield (item,) - seq = tuple(seq) - item_count = len(seq) - - # And the rest - for n in range(2, item_count + 1): - for i in range(item_count - n + 1): - yield seq[i : i + n] - - -def substrings_indexes(seq, reverse=False): - """Yield all substrings and their positions in *seq* - - The items yielded will be a tuple of the form ``(substr, i, j)``, where - ``substr == seq[i:j]``. - - This function only works for iterables that support slicing, such as - ``str`` objects. - - >>> for item in substrings_indexes('more'): - ... print(item) - ('m', 0, 1) - ('o', 1, 2) - ('r', 2, 3) - ('e', 3, 4) - ('mo', 0, 2) - ('or', 1, 3) - ('re', 2, 4) - ('mor', 0, 3) - ('ore', 1, 4) - ('more', 0, 4) - - Set *reverse* to ``True`` to yield the same items in the opposite order. - - - """ - r = range(1, len(seq) + 1) - if reverse: - r = reversed(r) - return ( - (seq[i : i + L], i, i + L) for L in r for i in range(len(seq) - L + 1) - ) - - -class bucket: - """Wrap *iterable* and return an object that buckets it iterable into - child iterables based on a *key* function. - - >>> iterable = ['a1', 'b1', 'c1', 'a2', 'b2', 'c2', 'b3'] - >>> s = bucket(iterable, key=lambda x: x[0]) # Bucket by 1st character - >>> sorted(list(s)) # Get the keys - ['a', 'b', 'c'] - >>> a_iterable = s['a'] - >>> next(a_iterable) - 'a1' - >>> next(a_iterable) - 'a2' - >>> list(s['b']) - ['b1', 'b2', 'b3'] - - The original iterable will be advanced and its items will be cached until - they are used by the child iterables. This may require significant storage. - - By default, attempting to select a bucket to which no items belong will - exhaust the iterable and cache all values. - If you specify a *validator* function, selected buckets will instead be - checked against it. - - >>> from itertools import count - >>> it = count(1, 2) # Infinite sequence of odd numbers - >>> key = lambda x: x % 10 # Bucket by last digit - >>> validator = lambda x: x in {1, 3, 5, 7, 9} # Odd digits only - >>> s = bucket(it, key=key, validator=validator) - >>> 2 in s - False - >>> list(s[2]) - [] - - """ - - def __init__(self, iterable, key, validator=None): - self._it = iter(iterable) - self._key = key - self._cache = defaultdict(deque) - self._validator = validator or (lambda x: True) - - def __contains__(self, value): - if not self._validator(value): - return False - - try: - item = next(self[value]) - except StopIteration: - return False - else: - self._cache[value].appendleft(item) - - return True - - def _get_values(self, value): - """ - Helper to yield items from the parent iterator that match *value*. - Items that don't match are stored in the local cache as they - are encountered. - """ - while True: - # If we've cached some items that match the target value, emit - # the first one and evict it from the cache. - if self._cache[value]: - yield self._cache[value].popleft() - # Otherwise we need to advance the parent iterator to search for - # a matching item, caching the rest. - else: - while True: - try: - item = next(self._it) - except StopIteration: - return - item_value = self._key(item) - if item_value == value: - yield item - break - elif self._validator(item_value): - self._cache[item_value].append(item) - - def __iter__(self): - for item in self._it: - item_value = self._key(item) - if self._validator(item_value): - self._cache[item_value].append(item) - - yield from self._cache.keys() - - def __getitem__(self, value): - if not self._validator(value): - return iter(()) - - return self._get_values(value) - - -def spy(iterable, n=1): - """Return a 2-tuple with a list containing the first *n* elements of - *iterable*, and an iterator with the same items as *iterable*. - This allows you to "look ahead" at the items in the iterable without - advancing it. - - There is one item in the list by default: - - >>> iterable = 'abcdefg' - >>> head, iterable = spy(iterable) - >>> head - ['a'] - >>> list(iterable) - ['a', 'b', 'c', 'd', 'e', 'f', 'g'] - - You may use unpacking to retrieve items instead of lists: - - >>> (head,), iterable = spy('abcdefg') - >>> head - 'a' - >>> (first, second), iterable = spy('abcdefg', 2) - >>> first - 'a' - >>> second - 'b' - - The number of items requested can be larger than the number of items in - the iterable: - - >>> iterable = [1, 2, 3, 4, 5] - >>> head, iterable = spy(iterable, 10) - >>> head - [1, 2, 3, 4, 5] - >>> list(iterable) - [1, 2, 3, 4, 5] - - """ - it = iter(iterable) - head = take(n, it) - - return head.copy(), chain(head, it) - - -def interleave(*iterables): - """Return a new iterable yielding from each iterable in turn, - until the shortest is exhausted. - - >>> list(interleave([1, 2, 3], [4, 5], [6, 7, 8])) - [1, 4, 6, 2, 5, 7] - - For a version that doesn't terminate after the shortest iterable is - exhausted, see :func:`interleave_longest`. - - """ - return chain.from_iterable(zip(*iterables)) - - -def interleave_longest(*iterables): - """Return a new iterable yielding from each iterable in turn, - skipping any that are exhausted. - - >>> list(interleave_longest([1, 2, 3], [4, 5], [6, 7, 8])) - [1, 4, 6, 2, 5, 7, 3, 8] - - This function produces the same output as :func:`roundrobin`, but may - perform better for some inputs (in particular when the number of iterables - is large). - - """ - i = chain.from_iterable(zip_longest(*iterables, fillvalue=_marker)) - return (x for x in i if x is not _marker) - - -def collapse(iterable, base_type=None, levels=None): - """Flatten an iterable with multiple levels of nesting (e.g., a list of - lists of tuples) into non-iterable types. - - >>> iterable = [(1, 2), ([3, 4], [[5], [6]])] - >>> list(collapse(iterable)) - [1, 2, 3, 4, 5, 6] - - Binary and text strings are not considered iterable and - will not be collapsed. - - To avoid collapsing other types, specify *base_type*: - - >>> iterable = ['ab', ('cd', 'ef'), ['gh', 'ij']] - >>> list(collapse(iterable, base_type=tuple)) - ['ab', ('cd', 'ef'), 'gh', 'ij'] - - Specify *levels* to stop flattening after a certain level: - - >>> iterable = [('a', ['b']), ('c', ['d'])] - >>> list(collapse(iterable)) # Fully flattened - ['a', 'b', 'c', 'd'] - >>> list(collapse(iterable, levels=1)) # Only one level flattened - ['a', ['b'], 'c', ['d']] - - """ - - def walk(node, level): - if ( - ((levels is not None) and (level > levels)) - or isinstance(node, (str, bytes)) - or ((base_type is not None) and isinstance(node, base_type)) - ): - yield node - return - - try: - tree = iter(node) - except TypeError: - yield node - return - else: - for child in tree: - yield from walk(child, level + 1) - - yield from walk(iterable, 0) - - -def side_effect(func, iterable, chunk_size=None, before=None, after=None): - """Invoke *func* on each item in *iterable* (or on each *chunk_size* group - of items) before yielding the item. - - `func` must be a function that takes a single argument. Its return value - will be discarded. - - *before* and *after* are optional functions that take no arguments. They - will be executed before iteration starts and after it ends, respectively. - - `side_effect` can be used for logging, updating progress bars, or anything - that is not functionally "pure." - - Emitting a status message: - - >>> from more_itertools import consume - >>> func = lambda item: print('Received {}'.format(item)) - >>> consume(side_effect(func, range(2))) - Received 0 - Received 1 - - Operating on chunks of items: - - >>> pair_sums = [] - >>> func = lambda chunk: pair_sums.append(sum(chunk)) - >>> list(side_effect(func, [0, 1, 2, 3, 4, 5], 2)) - [0, 1, 2, 3, 4, 5] - >>> list(pair_sums) - [1, 5, 9] - - Writing to a file-like object: - - >>> from io import StringIO - >>> from more_itertools import consume - >>> f = StringIO() - >>> func = lambda x: print(x, file=f) - >>> before = lambda: print(u'HEADER', file=f) - >>> after = f.close - >>> it = [u'a', u'b', u'c'] - >>> consume(side_effect(func, it, before=before, after=after)) - >>> f.closed - True - - """ - try: - if before is not None: - before() - - if chunk_size is None: - for item in iterable: - func(item) - yield item - else: - for chunk in chunked(iterable, chunk_size): - func(chunk) - yield from chunk - finally: - if after is not None: - after() - - -def sliced(seq, n, strict=False): - """Yield slices of length *n* from the sequence *seq*. - - >>> list(sliced((1, 2, 3, 4, 5, 6), 3)) - [(1, 2, 3), (4, 5, 6)] - - By the default, the last yielded slice will have fewer than *n* elements - if the length of *seq* is not divisible by *n*: - - >>> list(sliced((1, 2, 3, 4, 5, 6, 7, 8), 3)) - [(1, 2, 3), (4, 5, 6), (7, 8)] - - If the length of *seq* is not divisible by *n* and *strict* is - ``True``, then ``ValueError`` will be raised before the last - slice is yielded. - - This function will only work for iterables that support slicing. - For non-sliceable iterables, see :func:`chunked`. - - """ - iterator = takewhile(len, (seq[i : i + n] for i in count(0, n))) - if strict: - - def ret(): - for _slice in iterator: - if len(_slice) != n: - raise ValueError("seq is not divisible by n.") - yield _slice - - return iter(ret()) - else: - return iterator - - -def split_at(iterable, pred, maxsplit=-1, keep_separator=False): - """Yield lists of items from *iterable*, where each list is delimited by - an item where callable *pred* returns ``True``. - - >>> list(split_at('abcdcba', lambda x: x == 'b')) - [['a'], ['c', 'd', 'c'], ['a']] - - >>> list(split_at(range(10), lambda n: n % 2 == 1)) - [[0], [2], [4], [6], [8], []] - - At most *maxsplit* splits are done. If *maxsplit* is not specified or -1, - then there is no limit on the number of splits: - - >>> list(split_at(range(10), lambda n: n % 2 == 1, maxsplit=2)) - [[0], [2], [4, 5, 6, 7, 8, 9]] - - By default, the delimiting items are not included in the output. - The include them, set *keep_separator* to ``True``. - - >>> list(split_at('abcdcba', lambda x: x == 'b', keep_separator=True)) - [['a'], ['b'], ['c', 'd', 'c'], ['b'], ['a']] - - """ - if maxsplit == 0: - yield list(iterable) - return - - buf = [] - it = iter(iterable) - for item in it: - if pred(item): - yield buf - if keep_separator: - yield [item] - if maxsplit == 1: - yield list(it) - return - buf = [] - maxsplit -= 1 - else: - buf.append(item) - yield buf - - -def split_before(iterable, pred, maxsplit=-1): - """Yield lists of items from *iterable*, where each list ends just before - an item for which callable *pred* returns ``True``: - - >>> list(split_before('OneTwo', lambda s: s.isupper())) - [['O', 'n', 'e'], ['T', 'w', 'o']] - - >>> list(split_before(range(10), lambda n: n % 3 == 0)) - [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]] - - At most *maxsplit* splits are done. If *maxsplit* is not specified or -1, - then there is no limit on the number of splits: - - >>> list(split_before(range(10), lambda n: n % 3 == 0, maxsplit=2)) - [[0, 1, 2], [3, 4, 5], [6, 7, 8, 9]] - """ - if maxsplit == 0: - yield list(iterable) - return - - buf = [] - it = iter(iterable) - for item in it: - if pred(item) and buf: - yield buf - if maxsplit == 1: - yield [item] + list(it) - return - buf = [] - maxsplit -= 1 - buf.append(item) - if buf: - yield buf - - -def split_after(iterable, pred, maxsplit=-1): - """Yield lists of items from *iterable*, where each list ends with an - item where callable *pred* returns ``True``: - - >>> list(split_after('one1two2', lambda s: s.isdigit())) - [['o', 'n', 'e', '1'], ['t', 'w', 'o', '2']] - - >>> list(split_after(range(10), lambda n: n % 3 == 0)) - [[0], [1, 2, 3], [4, 5, 6], [7, 8, 9]] - - At most *maxsplit* splits are done. If *maxsplit* is not specified or -1, - then there is no limit on the number of splits: - - >>> list(split_after(range(10), lambda n: n % 3 == 0, maxsplit=2)) - [[0], [1, 2, 3], [4, 5, 6, 7, 8, 9]] - - """ - if maxsplit == 0: - yield list(iterable) - return - - buf = [] - it = iter(iterable) - for item in it: - buf.append(item) - if pred(item) and buf: - yield buf - if maxsplit == 1: - yield list(it) - return - buf = [] - maxsplit -= 1 - if buf: - yield buf - - -def split_when(iterable, pred, maxsplit=-1): - """Split *iterable* into pieces based on the output of *pred*. - *pred* should be a function that takes successive pairs of items and - returns ``True`` if the iterable should be split in between them. - - For example, to find runs of increasing numbers, split the iterable when - element ``i`` is larger than element ``i + 1``: - - >>> list(split_when([1, 2, 3, 3, 2, 5, 2, 4, 2], lambda x, y: x > y)) - [[1, 2, 3, 3], [2, 5], [2, 4], [2]] - - At most *maxsplit* splits are done. If *maxsplit* is not specified or -1, - then there is no limit on the number of splits: - - >>> list(split_when([1, 2, 3, 3, 2, 5, 2, 4, 2], - ... lambda x, y: x > y, maxsplit=2)) - [[1, 2, 3, 3], [2, 5], [2, 4, 2]] - - """ - if maxsplit == 0: - yield list(iterable) - return - - it = iter(iterable) - try: - cur_item = next(it) - except StopIteration: - return - - buf = [cur_item] - for next_item in it: - if pred(cur_item, next_item): - yield buf - if maxsplit == 1: - yield [next_item] + list(it) - return - buf = [] - maxsplit -= 1 - - buf.append(next_item) - cur_item = next_item - - yield buf - - -def split_into(iterable, sizes): - """Yield a list of sequential items from *iterable* of length 'n' for each - integer 'n' in *sizes*. - - >>> list(split_into([1,2,3,4,5,6], [1,2,3])) - [[1], [2, 3], [4, 5, 6]] - - If the sum of *sizes* is smaller than the length of *iterable*, then the - remaining items of *iterable* will not be returned. - - >>> list(split_into([1,2,3,4,5,6], [2,3])) - [[1, 2], [3, 4, 5]] - - If the sum of *sizes* is larger than the length of *iterable*, fewer items - will be returned in the iteration that overruns *iterable* and further - lists will be empty: - - >>> list(split_into([1,2,3,4], [1,2,3,4])) - [[1], [2, 3], [4], []] - - When a ``None`` object is encountered in *sizes*, the returned list will - contain items up to the end of *iterable* the same way that itertools.slice - does: - - >>> list(split_into([1,2,3,4,5,6,7,8,9,0], [2,3,None])) - [[1, 2], [3, 4, 5], [6, 7, 8, 9, 0]] - - :func:`split_into` can be useful for grouping a series of items where the - sizes of the groups are not uniform. An example would be where in a row - from a table, multiple columns represent elements of the same feature - (e.g. a point represented by x,y,z) but, the format is not the same for - all columns. - """ - # convert the iterable argument into an iterator so its contents can - # be consumed by islice in case it is a generator - it = iter(iterable) - - for size in sizes: - if size is None: - yield list(it) - return - else: - yield list(islice(it, size)) - - -def padded(iterable, fillvalue=None, n=None, next_multiple=False): - """Yield the elements from *iterable*, followed by *fillvalue*, such that - at least *n* items are emitted. - - >>> list(padded([1, 2, 3], '?', 5)) - [1, 2, 3, '?', '?'] - - If *next_multiple* is ``True``, *fillvalue* will be emitted until the - number of items emitted is a multiple of *n*:: - - >>> list(padded([1, 2, 3, 4], n=3, next_multiple=True)) - [1, 2, 3, 4, None, None] - - If *n* is ``None``, *fillvalue* will be emitted indefinitely. - - """ - it = iter(iterable) - if n is None: - yield from chain(it, repeat(fillvalue)) - elif n < 1: - raise ValueError('n must be at least 1') - else: - item_count = 0 - for item in it: - yield item - item_count += 1 - - remaining = (n - item_count) % n if next_multiple else n - item_count - for _ in range(remaining): - yield fillvalue - - -def repeat_last(iterable, default=None): - """After the *iterable* is exhausted, keep yielding its last element. - - >>> list(islice(repeat_last(range(3)), 5)) - [0, 1, 2, 2, 2] - - If the iterable is empty, yield *default* forever:: - - >>> list(islice(repeat_last(range(0), 42), 5)) - [42, 42, 42, 42, 42] - - """ - item = _marker - for item in iterable: - yield item - final = default if item is _marker else item - yield from repeat(final) - - -def distribute(n, iterable): - """Distribute the items from *iterable* among *n* smaller iterables. - - >>> group_1, group_2 = distribute(2, [1, 2, 3, 4, 5, 6]) - >>> list(group_1) - [1, 3, 5] - >>> list(group_2) - [2, 4, 6] - - If the length of *iterable* is not evenly divisible by *n*, then the - length of the returned iterables will not be identical: - - >>> children = distribute(3, [1, 2, 3, 4, 5, 6, 7]) - >>> [list(c) for c in children] - [[1, 4, 7], [2, 5], [3, 6]] - - If the length of *iterable* is smaller than *n*, then the last returned - iterables will be empty: - - >>> children = distribute(5, [1, 2, 3]) - >>> [list(c) for c in children] - [[1], [2], [3], [], []] - - This function uses :func:`itertools.tee` and may require significant - storage. If you need the order items in the smaller iterables to match the - original iterable, see :func:`divide`. - - """ - if n < 1: - raise ValueError('n must be at least 1') - - children = tee(iterable, n) - return [islice(it, index, None, n) for index, it in enumerate(children)] - - -def stagger(iterable, offsets=(-1, 0, 1), longest=False, fillvalue=None): - """Yield tuples whose elements are offset from *iterable*. - The amount by which the `i`-th item in each tuple is offset is given by - the `i`-th item in *offsets*. - - >>> list(stagger([0, 1, 2, 3])) - [(None, 0, 1), (0, 1, 2), (1, 2, 3)] - >>> list(stagger(range(8), offsets=(0, 2, 4))) - [(0, 2, 4), (1, 3, 5), (2, 4, 6), (3, 5, 7)] - - By default, the sequence will end when the final element of a tuple is the - last item in the iterable. To continue until the first element of a tuple - is the last item in the iterable, set *longest* to ``True``:: - - >>> list(stagger([0, 1, 2, 3], longest=True)) - [(None, 0, 1), (0, 1, 2), (1, 2, 3), (2, 3, None), (3, None, None)] - - By default, ``None`` will be used to replace offsets beyond the end of the - sequence. Specify *fillvalue* to use some other value. - - """ - children = tee(iterable, len(offsets)) - - return zip_offset( - *children, offsets=offsets, longest=longest, fillvalue=fillvalue - ) - - -class UnequalIterablesError(ValueError): - def __init__(self, details=None): - msg = 'Iterables have different lengths' - if details is not None: - msg += (': index 0 has length {}; index {} has length {}').format( - *details - ) - - super().__init__(msg) - - -def _zip_equal_generator(iterables): - for combo in zip_longest(*iterables, fillvalue=_marker): - for val in combo: - if val is _marker: - raise UnequalIterablesError() - yield combo - - -def zip_equal(*iterables): - """``zip`` the input *iterables* together, but raise - ``UnequalIterablesError`` if they aren't all the same length. - - >>> it_1 = range(3) - >>> it_2 = iter('abc') - >>> list(zip_equal(it_1, it_2)) - [(0, 'a'), (1, 'b'), (2, 'c')] - - >>> it_1 = range(3) - >>> it_2 = iter('abcd') - >>> list(zip_equal(it_1, it_2)) # doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ... - more_itertools.more.UnequalIterablesError: Iterables have different - lengths - - """ - if hexversion >= 0x30A00A6: - warnings.warn( - ( - 'zip_equal will be removed in a future version of ' - 'more-itertools. Use the builtin zip function with ' - 'strict=True instead.' - ), - DeprecationWarning, - ) - # Check whether the iterables are all the same size. - try: - first_size = len(iterables[0]) - for i, it in enumerate(iterables[1:], 1): - size = len(it) - if size != first_size: - break - else: - # If we didn't break out, we can use the built-in zip. - return zip(*iterables) - - # If we did break out, there was a mismatch. - raise UnequalIterablesError(details=(first_size, i, size)) - # If any one of the iterables didn't have a length, start reading - # them until one runs out. - except TypeError: - return _zip_equal_generator(iterables) - - -def zip_offset(*iterables, offsets, longest=False, fillvalue=None): - """``zip`` the input *iterables* together, but offset the `i`-th iterable - by the `i`-th item in *offsets*. - - >>> list(zip_offset('0123', 'abcdef', offsets=(0, 1))) - [('0', 'b'), ('1', 'c'), ('2', 'd'), ('3', 'e')] - - This can be used as a lightweight alternative to SciPy or pandas to analyze - data sets in which some series have a lead or lag relationship. - - By default, the sequence will end when the shortest iterable is exhausted. - To continue until the longest iterable is exhausted, set *longest* to - ``True``. - - >>> list(zip_offset('0123', 'abcdef', offsets=(0, 1), longest=True)) - [('0', 'b'), ('1', 'c'), ('2', 'd'), ('3', 'e'), (None, 'f')] - - By default, ``None`` will be used to replace offsets beyond the end of the - sequence. Specify *fillvalue* to use some other value. - - """ - if len(iterables) != len(offsets): - raise ValueError("Number of iterables and offsets didn't match") - - staggered = [] - for it, n in zip(iterables, offsets): - if n < 0: - staggered.append(chain(repeat(fillvalue, -n), it)) - elif n > 0: - staggered.append(islice(it, n, None)) - else: - staggered.append(it) - - if longest: - return zip_longest(*staggered, fillvalue=fillvalue) - - return zip(*staggered) - - -def sort_together(iterables, key_list=(0,), key=None, reverse=False): - """Return the input iterables sorted together, with *key_list* as the - priority for sorting. All iterables are trimmed to the length of the - shortest one. - - This can be used like the sorting function in a spreadsheet. If each - iterable represents a column of data, the key list determines which - columns are used for sorting. - - By default, all iterables are sorted using the ``0``-th iterable:: - - >>> iterables = [(4, 3, 2, 1), ('a', 'b', 'c', 'd')] - >>> sort_together(iterables) - [(1, 2, 3, 4), ('d', 'c', 'b', 'a')] - - Set a different key list to sort according to another iterable. - Specifying multiple keys dictates how ties are broken:: - - >>> iterables = [(3, 1, 2), (0, 1, 0), ('c', 'b', 'a')] - >>> sort_together(iterables, key_list=(1, 2)) - [(2, 3, 1), (0, 0, 1), ('a', 'c', 'b')] - - To sort by a function of the elements of the iterable, pass a *key* - function. Its arguments are the elements of the iterables corresponding to - the key list:: - - >>> names = ('a', 'b', 'c') - >>> lengths = (1, 2, 3) - >>> widths = (5, 2, 1) - >>> def area(length, width): - ... return length * width - >>> sort_together([names, lengths, widths], key_list=(1, 2), key=area) - [('c', 'b', 'a'), (3, 2, 1), (1, 2, 5)] - - Set *reverse* to ``True`` to sort in descending order. - - >>> sort_together([(1, 2, 3), ('c', 'b', 'a')], reverse=True) - [(3, 2, 1), ('a', 'b', 'c')] - - """ - if key is None: - # if there is no key function, the key argument to sorted is an - # itemgetter - key_argument = itemgetter(*key_list) - else: - # if there is a key function, call it with the items at the offsets - # specified by the key function as arguments - key_list = list(key_list) - if len(key_list) == 1: - # if key_list contains a single item, pass the item at that offset - # as the only argument to the key function - key_offset = key_list[0] - key_argument = lambda zipped_items: key(zipped_items[key_offset]) - else: - # if key_list contains multiple items, use itemgetter to return a - # tuple of items, which we pass as *args to the key function - get_key_items = itemgetter(*key_list) - key_argument = lambda zipped_items: key( - *get_key_items(zipped_items) - ) - - return list( - zip(*sorted(zip(*iterables), key=key_argument, reverse=reverse)) - ) - - -def unzip(iterable): - """The inverse of :func:`zip`, this function disaggregates the elements - of the zipped *iterable*. - - The ``i``-th iterable contains the ``i``-th element from each element - of the zipped iterable. The first element is used to to determine the - length of the remaining elements. - - >>> iterable = [('a', 1), ('b', 2), ('c', 3), ('d', 4)] - >>> letters, numbers = unzip(iterable) - >>> list(letters) - ['a', 'b', 'c', 'd'] - >>> list(numbers) - [1, 2, 3, 4] - - This is similar to using ``zip(*iterable)``, but it avoids reading - *iterable* into memory. Note, however, that this function uses - :func:`itertools.tee` and thus may require significant storage. - - """ - head, iterable = spy(iter(iterable)) - if not head: - # empty iterable, e.g. zip([], [], []) - return () - # spy returns a one-length iterable as head - head = head[0] - iterables = tee(iterable, len(head)) - - def itemgetter(i): - def getter(obj): - try: - return obj[i] - except IndexError: - # basically if we have an iterable like - # iter([(1, 2, 3), (4, 5), (6,)]) - # the second unzipped iterable would fail at the third tuple - # since it would try to access tup[1] - # same with the third unzipped iterable and the second tuple - # to support these "improperly zipped" iterables, - # we create a custom itemgetter - # which just stops the unzipped iterables - # at first length mismatch - raise StopIteration - - return getter - - return tuple(map(itemgetter(i), it) for i, it in enumerate(iterables)) - - -def divide(n, iterable): - """Divide the elements from *iterable* into *n* parts, maintaining - order. - - >>> group_1, group_2 = divide(2, [1, 2, 3, 4, 5, 6]) - >>> list(group_1) - [1, 2, 3] - >>> list(group_2) - [4, 5, 6] - - If the length of *iterable* is not evenly divisible by *n*, then the - length of the returned iterables will not be identical: - - >>> children = divide(3, [1, 2, 3, 4, 5, 6, 7]) - >>> [list(c) for c in children] - [[1, 2, 3], [4, 5], [6, 7]] - - If the length of the iterable is smaller than n, then the last returned - iterables will be empty: - - >>> children = divide(5, [1, 2, 3]) - >>> [list(c) for c in children] - [[1], [2], [3], [], []] - - This function will exhaust the iterable before returning and may require - significant storage. If order is not important, see :func:`distribute`, - which does not first pull the iterable into memory. - - """ - if n < 1: - raise ValueError('n must be at least 1') - - try: - iterable[:0] - except TypeError: - seq = tuple(iterable) - else: - seq = iterable - - q, r = divmod(len(seq), n) - - ret = [] - stop = 0 - for i in range(1, n + 1): - start = stop - stop += q + 1 if i <= r else q - ret.append(iter(seq[start:stop])) - - return ret - - -def always_iterable(obj, base_type=(str, bytes)): - """If *obj* is iterable, return an iterator over its items:: - - >>> obj = (1, 2, 3) - >>> list(always_iterable(obj)) - [1, 2, 3] - - If *obj* is not iterable, return a one-item iterable containing *obj*:: - - >>> obj = 1 - >>> list(always_iterable(obj)) - [1] - - If *obj* is ``None``, return an empty iterable: - - >>> obj = None - >>> list(always_iterable(None)) - [] - - By default, binary and text strings are not considered iterable:: - - >>> obj = 'foo' - >>> list(always_iterable(obj)) - ['foo'] - - If *base_type* is set, objects for which ``isinstance(obj, base_type)`` - returns ``True`` won't be considered iterable. - - >>> obj = {'a': 1} - >>> list(always_iterable(obj)) # Iterate over the dict's keys - ['a'] - >>> list(always_iterable(obj, base_type=dict)) # Treat dicts as a unit - [{'a': 1}] - - Set *base_type* to ``None`` to avoid any special handling and treat objects - Python considers iterable as iterable: - - >>> obj = 'foo' - >>> list(always_iterable(obj, base_type=None)) - ['f', 'o', 'o'] - """ - if obj is None: - return iter(()) - - if (base_type is not None) and isinstance(obj, base_type): - return iter((obj,)) - - try: - return iter(obj) - except TypeError: - return iter((obj,)) - - -def adjacent(predicate, iterable, distance=1): - """Return an iterable over `(bool, item)` tuples where the `item` is - drawn from *iterable* and the `bool` indicates whether - that item satisfies the *predicate* or is adjacent to an item that does. - - For example, to find whether items are adjacent to a ``3``:: - - >>> list(adjacent(lambda x: x == 3, range(6))) - [(False, 0), (False, 1), (True, 2), (True, 3), (True, 4), (False, 5)] - - Set *distance* to change what counts as adjacent. For example, to find - whether items are two places away from a ``3``: - - >>> list(adjacent(lambda x: x == 3, range(6), distance=2)) - [(False, 0), (True, 1), (True, 2), (True, 3), (True, 4), (True, 5)] - - This is useful for contextualizing the results of a search function. - For example, a code comparison tool might want to identify lines that - have changed, but also surrounding lines to give the viewer of the diff - context. - - The predicate function will only be called once for each item in the - iterable. - - See also :func:`groupby_transform`, which can be used with this function - to group ranges of items with the same `bool` value. - - """ - # Allow distance=0 mainly for testing that it reproduces results with map() - if distance < 0: - raise ValueError('distance must be at least 0') - - i1, i2 = tee(iterable) - padding = [False] * distance - selected = chain(padding, map(predicate, i1), padding) - adjacent_to_selected = map(any, windowed(selected, 2 * distance + 1)) - return zip(adjacent_to_selected, i2) - - -def groupby_transform(iterable, keyfunc=None, valuefunc=None, reducefunc=None): - """An extension of :func:`itertools.groupby` that can apply transformations - to the grouped data. - - * *keyfunc* is a function computing a key value for each item in *iterable* - * *valuefunc* is a function that transforms the individual items from - *iterable* after grouping - * *reducefunc* is a function that transforms each group of items - - >>> iterable = 'aAAbBBcCC' - >>> keyfunc = lambda k: k.upper() - >>> valuefunc = lambda v: v.lower() - >>> reducefunc = lambda g: ''.join(g) - >>> list(groupby_transform(iterable, keyfunc, valuefunc, reducefunc)) - [('A', 'aaa'), ('B', 'bbb'), ('C', 'ccc')] - - Each optional argument defaults to an identity function if not specified. - - :func:`groupby_transform` is useful when grouping elements of an iterable - using a separate iterable as the key. To do this, :func:`zip` the iterables - and pass a *keyfunc* that extracts the first element and a *valuefunc* - that extracts the second element:: - - >>> from operator import itemgetter - >>> keys = [0, 0, 1, 1, 1, 2, 2, 2, 3] - >>> values = 'abcdefghi' - >>> iterable = zip(keys, values) - >>> grouper = groupby_transform(iterable, itemgetter(0), itemgetter(1)) - >>> [(k, ''.join(g)) for k, g in grouper] - [(0, 'ab'), (1, 'cde'), (2, 'fgh'), (3, 'i')] - - Note that the order of items in the iterable is significant. - Only adjacent items are grouped together, so if you don't want any - duplicate groups, you should sort the iterable by the key function. - - """ - ret = groupby(iterable, keyfunc) - if valuefunc: - ret = ((k, map(valuefunc, g)) for k, g in ret) - if reducefunc: - ret = ((k, reducefunc(g)) for k, g in ret) - - return ret - - -class numeric_range(abc.Sequence, abc.Hashable): - """An extension of the built-in ``range()`` function whose arguments can - be any orderable numeric type. - - With only *stop* specified, *start* defaults to ``0`` and *step* - defaults to ``1``. The output items will match the type of *stop*: - - >>> list(numeric_range(3.5)) - [0.0, 1.0, 2.0, 3.0] - - With only *start* and *stop* specified, *step* defaults to ``1``. The - output items will match the type of *start*: - - >>> from decimal import Decimal - >>> start = Decimal('2.1') - >>> stop = Decimal('5.1') - >>> list(numeric_range(start, stop)) - [Decimal('2.1'), Decimal('3.1'), Decimal('4.1')] - - With *start*, *stop*, and *step* specified the output items will match - the type of ``start + step``: - - >>> from fractions import Fraction - >>> start = Fraction(1, 2) # Start at 1/2 - >>> stop = Fraction(5, 2) # End at 5/2 - >>> step = Fraction(1, 2) # Count by 1/2 - >>> list(numeric_range(start, stop, step)) - [Fraction(1, 2), Fraction(1, 1), Fraction(3, 2), Fraction(2, 1)] - - If *step* is zero, ``ValueError`` is raised. Negative steps are supported: - - >>> list(numeric_range(3, -1, -1.0)) - [3.0, 2.0, 1.0, 0.0] - - Be aware of the limitations of floating point numbers; the representation - of the yielded numbers may be surprising. - - ``datetime.datetime`` objects can be used for *start* and *stop*, if *step* - is a ``datetime.timedelta`` object: - - >>> import datetime - >>> start = datetime.datetime(2019, 1, 1) - >>> stop = datetime.datetime(2019, 1, 3) - >>> step = datetime.timedelta(days=1) - >>> items = iter(numeric_range(start, stop, step)) - >>> next(items) - datetime.datetime(2019, 1, 1, 0, 0) - >>> next(items) - datetime.datetime(2019, 1, 2, 0, 0) - - """ - - _EMPTY_HASH = hash(range(0, 0)) - - def __init__(self, *args): - argc = len(args) - if argc == 1: - (self._stop,) = args - self._start = type(self._stop)(0) - self._step = type(self._stop - self._start)(1) - elif argc == 2: - self._start, self._stop = args - self._step = type(self._stop - self._start)(1) - elif argc == 3: - self._start, self._stop, self._step = args - elif argc == 0: - raise TypeError( - 'numeric_range expected at least ' - '1 argument, got {}'.format(argc) - ) - else: - raise TypeError( - 'numeric_range expected at most ' - '3 arguments, got {}'.format(argc) - ) - - self._zero = type(self._step)(0) - if self._step == self._zero: - raise ValueError('numeric_range() arg 3 must not be zero') - self._growing = self._step > self._zero - self._init_len() - - def __bool__(self): - if self._growing: - return self._start < self._stop - else: - return self._start > self._stop - - def __contains__(self, elem): - if self._growing: - if self._start <= elem < self._stop: - return (elem - self._start) % self._step == self._zero - else: - if self._start >= elem > self._stop: - return (self._start - elem) % (-self._step) == self._zero - - return False - - def __eq__(self, other): - if isinstance(other, numeric_range): - empty_self = not bool(self) - empty_other = not bool(other) - if empty_self or empty_other: - return empty_self and empty_other # True if both empty - else: - return ( - self._start == other._start - and self._step == other._step - and self._get_by_index(-1) == other._get_by_index(-1) - ) - else: - return False - - def __getitem__(self, key): - if isinstance(key, int): - return self._get_by_index(key) - elif isinstance(key, slice): - step = self._step if key.step is None else key.step * self._step - - if key.start is None or key.start <= -self._len: - start = self._start - elif key.start >= self._len: - start = self._stop - else: # -self._len < key.start < self._len - start = self._get_by_index(key.start) - - if key.stop is None or key.stop >= self._len: - stop = self._stop - elif key.stop <= -self._len: - stop = self._start - else: # -self._len < key.stop < self._len - stop = self._get_by_index(key.stop) - - return numeric_range(start, stop, step) - else: - raise TypeError( - 'numeric range indices must be ' - 'integers or slices, not {}'.format(type(key).__name__) - ) - - def __hash__(self): - if self: - return hash((self._start, self._get_by_index(-1), self._step)) - else: - return self._EMPTY_HASH - - def __iter__(self): - values = (self._start + (n * self._step) for n in count()) - if self._growing: - return takewhile(partial(gt, self._stop), values) - else: - return takewhile(partial(lt, self._stop), values) - - def __len__(self): - return self._len - - def _init_len(self): - if self._growing: - start = self._start - stop = self._stop - step = self._step - else: - start = self._stop - stop = self._start - step = -self._step - distance = stop - start - if distance <= self._zero: - self._len = 0 - else: # distance > 0 and step > 0: regular euclidean division - q, r = divmod(distance, step) - self._len = int(q) + int(r != self._zero) - - def __reduce__(self): - return numeric_range, (self._start, self._stop, self._step) - - def __repr__(self): - if self._step == 1: - return "numeric_range({}, {})".format( - repr(self._start), repr(self._stop) - ) - else: - return "numeric_range({}, {}, {})".format( - repr(self._start), repr(self._stop), repr(self._step) - ) - - def __reversed__(self): - return iter( - numeric_range( - self._get_by_index(-1), self._start - self._step, -self._step - ) - ) - - def count(self, value): - return int(value in self) - - def index(self, value): - if self._growing: - if self._start <= value < self._stop: - q, r = divmod(value - self._start, self._step) - if r == self._zero: - return int(q) - else: - if self._start >= value > self._stop: - q, r = divmod(self._start - value, -self._step) - if r == self._zero: - return int(q) - - raise ValueError("{} is not in numeric range".format(value)) - - def _get_by_index(self, i): - if i < 0: - i += self._len - if i < 0 or i >= self._len: - raise IndexError("numeric range object index out of range") - return self._start + i * self._step - - -def count_cycle(iterable, n=None): - """Cycle through the items from *iterable* up to *n* times, yielding - the number of completed cycles along with each item. If *n* is omitted the - process repeats indefinitely. - - >>> list(count_cycle('AB', 3)) - [(0, 'A'), (0, 'B'), (1, 'A'), (1, 'B'), (2, 'A'), (2, 'B')] - - """ - iterable = tuple(iterable) - if not iterable: - return iter(()) - counter = count() if n is None else range(n) - return ((i, item) for i in counter for item in iterable) - - -def mark_ends(iterable): - """Yield 3-tuples of the form ``(is_first, is_last, item)``. - - >>> list(mark_ends('ABC')) - [(True, False, 'A'), (False, False, 'B'), (False, True, 'C')] - - Use this when looping over an iterable to take special action on its first - and/or last items: - - >>> iterable = ['Header', 100, 200, 'Footer'] - >>> total = 0 - >>> for is_first, is_last, item in mark_ends(iterable): - ... if is_first: - ... continue # Skip the header - ... if is_last: - ... continue # Skip the footer - ... total += item - >>> print(total) - 300 - """ - it = iter(iterable) - - try: - b = next(it) - except StopIteration: - return - - try: - for i in count(): - a = b - b = next(it) - yield i == 0, False, a - - except StopIteration: - yield i == 0, True, a - - -def locate(iterable, pred=bool, window_size=None): - """Yield the index of each item in *iterable* for which *pred* returns - ``True``. - - *pred* defaults to :func:`bool`, which will select truthy items: - - >>> list(locate([0, 1, 1, 0, 1, 0, 0])) - [1, 2, 4] - - Set *pred* to a custom function to, e.g., find the indexes for a particular - item. - - >>> list(locate(['a', 'b', 'c', 'b'], lambda x: x == 'b')) - [1, 3] - - If *window_size* is given, then the *pred* function will be called with - that many items. This enables searching for sub-sequences: - - >>> iterable = [0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3] - >>> pred = lambda *args: args == (1, 2, 3) - >>> list(locate(iterable, pred=pred, window_size=3)) - [1, 5, 9] - - Use with :func:`seekable` to find indexes and then retrieve the associated - items: - - >>> from itertools import count - >>> from more_itertools import seekable - >>> source = (3 * n + 1 if (n % 2) else n // 2 for n in count()) - >>> it = seekable(source) - >>> pred = lambda x: x > 100 - >>> indexes = locate(it, pred=pred) - >>> i = next(indexes) - >>> it.seek(i) - >>> next(it) - 106 - - """ - if window_size is None: - return compress(count(), map(pred, iterable)) - - if window_size < 1: - raise ValueError('window size must be at least 1') - - it = windowed(iterable, window_size, fillvalue=_marker) - return compress(count(), starmap(pred, it)) - - -def lstrip(iterable, pred): - """Yield the items from *iterable*, but strip any from the beginning - for which *pred* returns ``True``. - - For example, to remove a set of items from the start of an iterable: - - >>> iterable = (None, False, None, 1, 2, None, 3, False, None) - >>> pred = lambda x: x in {None, False, ''} - >>> list(lstrip(iterable, pred)) - [1, 2, None, 3, False, None] - - This function is analogous to to :func:`str.lstrip`, and is essentially - an wrapper for :func:`itertools.dropwhile`. - - """ - return dropwhile(pred, iterable) - - -def rstrip(iterable, pred): - """Yield the items from *iterable*, but strip any from the end - for which *pred* returns ``True``. - - For example, to remove a set of items from the end of an iterable: - - >>> iterable = (None, False, None, 1, 2, None, 3, False, None) - >>> pred = lambda x: x in {None, False, ''} - >>> list(rstrip(iterable, pred)) - [None, False, None, 1, 2, None, 3] - - This function is analogous to :func:`str.rstrip`. - - """ - cache = [] - cache_append = cache.append - cache_clear = cache.clear - for x in iterable: - if pred(x): - cache_append(x) - else: - yield from cache - cache_clear() - yield x - - -def strip(iterable, pred): - """Yield the items from *iterable*, but strip any from the - beginning and end for which *pred* returns ``True``. - - For example, to remove a set of items from both ends of an iterable: - - >>> iterable = (None, False, None, 1, 2, None, 3, False, None) - >>> pred = lambda x: x in {None, False, ''} - >>> list(strip(iterable, pred)) - [1, 2, None, 3] - - This function is analogous to :func:`str.strip`. - - """ - return rstrip(lstrip(iterable, pred), pred) - - -class islice_extended: - """An extension of :func:`itertools.islice` that supports negative values - for *stop*, *start*, and *step*. - - >>> iterable = iter('abcdefgh') - >>> list(islice_extended(iterable, -4, -1)) - ['e', 'f', 'g'] - - Slices with negative values require some caching of *iterable*, but this - function takes care to minimize the amount of memory required. - - For example, you can use a negative step with an infinite iterator: - - >>> from itertools import count - >>> list(islice_extended(count(), 110, 99, -2)) - [110, 108, 106, 104, 102, 100] - - You can also use slice notation directly: - - >>> iterable = map(str, count()) - >>> it = islice_extended(iterable)[10:20:2] - >>> list(it) - ['10', '12', '14', '16', '18'] - - """ - - def __init__(self, iterable, *args): - it = iter(iterable) - if args: - self._iterable = _islice_helper(it, slice(*args)) - else: - self._iterable = it - - def __iter__(self): - return self - - def __next__(self): - return next(self._iterable) - - def __getitem__(self, key): - if isinstance(key, slice): - return islice_extended(_islice_helper(self._iterable, key)) - - raise TypeError('islice_extended.__getitem__ argument must be a slice') - - -def _islice_helper(it, s): - start = s.start - stop = s.stop - if s.step == 0: - raise ValueError('step argument must be a non-zero integer or None.') - step = s.step or 1 - - if step > 0: - start = 0 if (start is None) else start - - if start < 0: - # Consume all but the last -start items - cache = deque(enumerate(it, 1), maxlen=-start) - len_iter = cache[-1][0] if cache else 0 - - # Adjust start to be positive - i = max(len_iter + start, 0) - - # Adjust stop to be positive - if stop is None: - j = len_iter - elif stop >= 0: - j = min(stop, len_iter) - else: - j = max(len_iter + stop, 0) - - # Slice the cache - n = j - i - if n <= 0: - return - - for index, item in islice(cache, 0, n, step): - yield item - elif (stop is not None) and (stop < 0): - # Advance to the start position - next(islice(it, start, start), None) - - # When stop is negative, we have to carry -stop items while - # iterating - cache = deque(islice(it, -stop), maxlen=-stop) - - for index, item in enumerate(it): - cached_item = cache.popleft() - if index % step == 0: - yield cached_item - cache.append(item) - else: - # When both start and stop are positive we have the normal case - yield from islice(it, start, stop, step) - else: - start = -1 if (start is None) else start - - if (stop is not None) and (stop < 0): - # Consume all but the last items - n = -stop - 1 - cache = deque(enumerate(it, 1), maxlen=n) - len_iter = cache[-1][0] if cache else 0 - - # If start and stop are both negative they are comparable and - # we can just slice. Otherwise we can adjust start to be negative - # and then slice. - if start < 0: - i, j = start, stop - else: - i, j = min(start - len_iter, -1), None - - for index, item in list(cache)[i:j:step]: - yield item - else: - # Advance to the stop position - if stop is not None: - m = stop + 1 - next(islice(it, m, m), None) - - # stop is positive, so if start is negative they are not comparable - # and we need the rest of the items. - if start < 0: - i = start - n = None - # stop is None and start is positive, so we just need items up to - # the start index. - elif stop is None: - i = None - n = start + 1 - # Both stop and start are positive, so they are comparable. - else: - i = None - n = start - stop - if n <= 0: - return - - cache = list(islice(it, n)) - - yield from cache[i::step] - - -def always_reversible(iterable): - """An extension of :func:`reversed` that supports all iterables, not - just those which implement the ``Reversible`` or ``Sequence`` protocols. - - >>> print(*always_reversible(x for x in range(3))) - 2 1 0 - - If the iterable is already reversible, this function returns the - result of :func:`reversed()`. If the iterable is not reversible, - this function will cache the remaining items in the iterable and - yield them in reverse order, which may require significant storage. - """ - try: - return reversed(iterable) - except TypeError: - return reversed(list(iterable)) - - -def consecutive_groups(iterable, ordering=lambda x: x): - """Yield groups of consecutive items using :func:`itertools.groupby`. - The *ordering* function determines whether two items are adjacent by - returning their position. - - By default, the ordering function is the identity function. This is - suitable for finding runs of numbers: - - >>> iterable = [1, 10, 11, 12, 20, 30, 31, 32, 33, 40] - >>> for group in consecutive_groups(iterable): - ... print(list(group)) - [1] - [10, 11, 12] - [20] - [30, 31, 32, 33] - [40] - - For finding runs of adjacent letters, try using the :meth:`index` method - of a string of letters: - - >>> from string import ascii_lowercase - >>> iterable = 'abcdfgilmnop' - >>> ordering = ascii_lowercase.index - >>> for group in consecutive_groups(iterable, ordering): - ... print(list(group)) - ['a', 'b', 'c', 'd'] - ['f', 'g'] - ['i'] - ['l', 'm', 'n', 'o', 'p'] - - Each group of consecutive items is an iterator that shares it source with - *iterable*. When an an output group is advanced, the previous group is - no longer available unless its elements are copied (e.g., into a ``list``). - - >>> iterable = [1, 2, 11, 12, 21, 22] - >>> saved_groups = [] - >>> for group in consecutive_groups(iterable): - ... saved_groups.append(list(group)) # Copy group elements - >>> saved_groups - [[1, 2], [11, 12], [21, 22]] - - """ - for k, g in groupby( - enumerate(iterable), key=lambda x: x[0] - ordering(x[1]) - ): - yield map(itemgetter(1), g) - - -def difference(iterable, func=sub, *, initial=None): - """This function is the inverse of :func:`itertools.accumulate`. By default - it will compute the first difference of *iterable* using - :func:`operator.sub`: - - >>> from itertools import accumulate - >>> iterable = accumulate([0, 1, 2, 3, 4]) # produces 0, 1, 3, 6, 10 - >>> list(difference(iterable)) - [0, 1, 2, 3, 4] - - *func* defaults to :func:`operator.sub`, but other functions can be - specified. They will be applied as follows:: - - A, B, C, D, ... --> A, func(B, A), func(C, B), func(D, C), ... - - For example, to do progressive division: - - >>> iterable = [1, 2, 6, 24, 120] - >>> func = lambda x, y: x // y - >>> list(difference(iterable, func)) - [1, 2, 3, 4, 5] - - If the *initial* keyword is set, the first element will be skipped when - computing successive differences. - - >>> it = [10, 11, 13, 16] # from accumulate([1, 2, 3], initial=10) - >>> list(difference(it, initial=10)) - [1, 2, 3] - - """ - a, b = tee(iterable) - try: - first = [next(b)] - except StopIteration: - return iter([]) - - if initial is not None: - first = [] - - return chain(first, starmap(func, zip(b, a))) - - -class SequenceView(Sequence): - """Return a read-only view of the sequence object *target*. - - :class:`SequenceView` objects are analogous to Python's built-in - "dictionary view" types. They provide a dynamic view of a sequence's items, - meaning that when the sequence updates, so does the view. - - >>> seq = ['0', '1', '2'] - >>> view = SequenceView(seq) - >>> view - SequenceView(['0', '1', '2']) - >>> seq.append('3') - >>> view - SequenceView(['0', '1', '2', '3']) - - Sequence views support indexing, slicing, and length queries. They act - like the underlying sequence, except they don't allow assignment: - - >>> view[1] - '1' - >>> view[1:-1] - ['1', '2'] - >>> len(view) - 4 - - Sequence views are useful as an alternative to copying, as they don't - require (much) extra storage. - - """ - - def __init__(self, target): - if not isinstance(target, Sequence): - raise TypeError - self._target = target - - def __getitem__(self, index): - return self._target[index] - - def __len__(self): - return len(self._target) - - def __repr__(self): - return '{}({})'.format(self.__class__.__name__, repr(self._target)) - - -class seekable: - """Wrap an iterator to allow for seeking backward and forward. This - progressively caches the items in the source iterable so they can be - re-visited. - - Call :meth:`seek` with an index to seek to that position in the source - iterable. - - To "reset" an iterator, seek to ``0``: - - >>> from itertools import count - >>> it = seekable((str(n) for n in count())) - >>> next(it), next(it), next(it) - ('0', '1', '2') - >>> it.seek(0) - >>> next(it), next(it), next(it) - ('0', '1', '2') - >>> next(it) - '3' - - You can also seek forward: - - >>> it = seekable((str(n) for n in range(20))) - >>> it.seek(10) - >>> next(it) - '10' - >>> it.seek(20) # Seeking past the end of the source isn't a problem - >>> list(it) - [] - >>> it.seek(0) # Resetting works even after hitting the end - >>> next(it), next(it), next(it) - ('0', '1', '2') - - Call :meth:`peek` to look ahead one item without advancing the iterator: - - >>> it = seekable('1234') - >>> it.peek() - '1' - >>> list(it) - ['1', '2', '3', '4'] - >>> it.peek(default='empty') - 'empty' - - Before the iterator is at its end, calling :func:`bool` on it will return - ``True``. After it will return ``False``: - - >>> it = seekable('5678') - >>> bool(it) - True - >>> list(it) - ['5', '6', '7', '8'] - >>> bool(it) - False - - You may view the contents of the cache with the :meth:`elements` method. - That returns a :class:`SequenceView`, a view that updates automatically: - - >>> it = seekable((str(n) for n in range(10))) - >>> next(it), next(it), next(it) - ('0', '1', '2') - >>> elements = it.elements() - >>> elements - SequenceView(['0', '1', '2']) - >>> next(it) - '3' - >>> elements - SequenceView(['0', '1', '2', '3']) - - By default, the cache grows as the source iterable progresses, so beware of - wrapping very large or infinite iterables. Supply *maxlen* to limit the - size of the cache (this of course limits how far back you can seek). - - >>> from itertools import count - >>> it = seekable((str(n) for n in count()), maxlen=2) - >>> next(it), next(it), next(it), next(it) - ('0', '1', '2', '3') - >>> list(it.elements()) - ['2', '3'] - >>> it.seek(0) - >>> next(it), next(it), next(it), next(it) - ('2', '3', '4', '5') - >>> next(it) - '6' - - """ - - def __init__(self, iterable, maxlen=None): - self._source = iter(iterable) - if maxlen is None: - self._cache = [] - else: - self._cache = deque([], maxlen) - self._index = None - - def __iter__(self): - return self - - def __next__(self): - if self._index is not None: - try: - item = self._cache[self._index] - except IndexError: - self._index = None - else: - self._index += 1 - return item - - item = next(self._source) - self._cache.append(item) - return item - - def __bool__(self): - try: - self.peek() - except StopIteration: - return False - return True - - def peek(self, default=_marker): - try: - peeked = next(self) - except StopIteration: - if default is _marker: - raise - return default - if self._index is None: - self._index = len(self._cache) - self._index -= 1 - return peeked - - def elements(self): - return SequenceView(self._cache) - - def seek(self, index): - self._index = index - remainder = index - len(self._cache) - if remainder > 0: - consume(self, remainder) - - -class run_length: - """ - :func:`run_length.encode` compresses an iterable with run-length encoding. - It yields groups of repeated items with the count of how many times they - were repeated: - - >>> uncompressed = 'abbcccdddd' - >>> list(run_length.encode(uncompressed)) - [('a', 1), ('b', 2), ('c', 3), ('d', 4)] - - :func:`run_length.decode` decompresses an iterable that was previously - compressed with run-length encoding. It yields the items of the - decompressed iterable: - - >>> compressed = [('a', 1), ('b', 2), ('c', 3), ('d', 4)] - >>> list(run_length.decode(compressed)) - ['a', 'b', 'b', 'c', 'c', 'c', 'd', 'd', 'd', 'd'] - - """ - - @staticmethod - def encode(iterable): - return ((k, ilen(g)) for k, g in groupby(iterable)) - - @staticmethod - def decode(iterable): - return chain.from_iterable(repeat(k, n) for k, n in iterable) - - -def exactly_n(iterable, n, predicate=bool): - """Return ``True`` if exactly ``n`` items in the iterable are ``True`` - according to the *predicate* function. - - >>> exactly_n([True, True, False], 2) - True - >>> exactly_n([True, True, False], 1) - False - >>> exactly_n([0, 1, 2, 3, 4, 5], 3, lambda x: x < 3) - True - - The iterable will be advanced until ``n + 1`` truthy items are encountered, - so avoid calling it on infinite iterables. - - """ - return len(take(n + 1, filter(predicate, iterable))) == n - - -def circular_shifts(iterable): - """Return a list of circular shifts of *iterable*. - - >>> circular_shifts(range(4)) - [(0, 1, 2, 3), (1, 2, 3, 0), (2, 3, 0, 1), (3, 0, 1, 2)] - """ - lst = list(iterable) - return take(len(lst), windowed(cycle(lst), len(lst))) - - -def make_decorator(wrapping_func, result_index=0): - """Return a decorator version of *wrapping_func*, which is a function that - modifies an iterable. *result_index* is the position in that function's - signature where the iterable goes. - - This lets you use itertools on the "production end," i.e. at function - definition. This can augment what the function returns without changing the - function's code. - - For example, to produce a decorator version of :func:`chunked`: - - >>> from more_itertools import chunked - >>> chunker = make_decorator(chunked, result_index=0) - >>> @chunker(3) - ... def iter_range(n): - ... return iter(range(n)) - ... - >>> list(iter_range(9)) - [[0, 1, 2], [3, 4, 5], [6, 7, 8]] - - To only allow truthy items to be returned: - - >>> truth_serum = make_decorator(filter, result_index=1) - >>> @truth_serum(bool) - ... def boolean_test(): - ... return [0, 1, '', ' ', False, True] - ... - >>> list(boolean_test()) - [1, ' ', True] - - The :func:`peekable` and :func:`seekable` wrappers make for practical - decorators: - - >>> from more_itertools import peekable - >>> peekable_function = make_decorator(peekable) - >>> @peekable_function() - ... def str_range(*args): - ... return (str(x) for x in range(*args)) - ... - >>> it = str_range(1, 20, 2) - >>> next(it), next(it), next(it) - ('1', '3', '5') - >>> it.peek() - '7' - >>> next(it) - '7' - - """ - # See https://sites.google.com/site/bbayles/index/decorator_factory for - # notes on how this works. - def decorator(*wrapping_args, **wrapping_kwargs): - def outer_wrapper(f): - def inner_wrapper(*args, **kwargs): - result = f(*args, **kwargs) - wrapping_args_ = list(wrapping_args) - wrapping_args_.insert(result_index, result) - return wrapping_func(*wrapping_args_, **wrapping_kwargs) - - return inner_wrapper - - return outer_wrapper - - return decorator - - -def map_reduce(iterable, keyfunc, valuefunc=None, reducefunc=None): - """Return a dictionary that maps the items in *iterable* to categories - defined by *keyfunc*, transforms them with *valuefunc*, and - then summarizes them by category with *reducefunc*. - - *valuefunc* defaults to the identity function if it is unspecified. - If *reducefunc* is unspecified, no summarization takes place: - - >>> keyfunc = lambda x: x.upper() - >>> result = map_reduce('abbccc', keyfunc) - >>> sorted(result.items()) - [('A', ['a']), ('B', ['b', 'b']), ('C', ['c', 'c', 'c'])] - - Specifying *valuefunc* transforms the categorized items: - - >>> keyfunc = lambda x: x.upper() - >>> valuefunc = lambda x: 1 - >>> result = map_reduce('abbccc', keyfunc, valuefunc) - >>> sorted(result.items()) - [('A', [1]), ('B', [1, 1]), ('C', [1, 1, 1])] - - Specifying *reducefunc* summarizes the categorized items: - - >>> keyfunc = lambda x: x.upper() - >>> valuefunc = lambda x: 1 - >>> reducefunc = sum - >>> result = map_reduce('abbccc', keyfunc, valuefunc, reducefunc) - >>> sorted(result.items()) - [('A', 1), ('B', 2), ('C', 3)] - - You may want to filter the input iterable before applying the map/reduce - procedure: - - >>> all_items = range(30) - >>> items = [x for x in all_items if 10 <= x <= 20] # Filter - >>> keyfunc = lambda x: x % 2 # Evens map to 0; odds to 1 - >>> categories = map_reduce(items, keyfunc=keyfunc) - >>> sorted(categories.items()) - [(0, [10, 12, 14, 16, 18, 20]), (1, [11, 13, 15, 17, 19])] - >>> summaries = map_reduce(items, keyfunc=keyfunc, reducefunc=sum) - >>> sorted(summaries.items()) - [(0, 90), (1, 75)] - - Note that all items in the iterable are gathered into a list before the - summarization step, which may require significant storage. - - The returned object is a :obj:`collections.defaultdict` with the - ``default_factory`` set to ``None``, such that it behaves like a normal - dictionary. - - """ - valuefunc = (lambda x: x) if (valuefunc is None) else valuefunc - - ret = defaultdict(list) - for item in iterable: - key = keyfunc(item) - value = valuefunc(item) - ret[key].append(value) - - if reducefunc is not None: - for key, value_list in ret.items(): - ret[key] = reducefunc(value_list) - - ret.default_factory = None - return ret - - -def rlocate(iterable, pred=bool, window_size=None): - """Yield the index of each item in *iterable* for which *pred* returns - ``True``, starting from the right and moving left. - - *pred* defaults to :func:`bool`, which will select truthy items: - - >>> list(rlocate([0, 1, 1, 0, 1, 0, 0])) # Truthy at 1, 2, and 4 - [4, 2, 1] - - Set *pred* to a custom function to, e.g., find the indexes for a particular - item: - - >>> iterable = iter('abcb') - >>> pred = lambda x: x == 'b' - >>> list(rlocate(iterable, pred)) - [3, 1] - - If *window_size* is given, then the *pred* function will be called with - that many items. This enables searching for sub-sequences: - - >>> iterable = [0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3] - >>> pred = lambda *args: args == (1, 2, 3) - >>> list(rlocate(iterable, pred=pred, window_size=3)) - [9, 5, 1] - - Beware, this function won't return anything for infinite iterables. - If *iterable* is reversible, ``rlocate`` will reverse it and search from - the right. Otherwise, it will search from the left and return the results - in reverse order. - - See :func:`locate` to for other example applications. - - """ - if window_size is None: - try: - len_iter = len(iterable) - return (len_iter - i - 1 for i in locate(reversed(iterable), pred)) - except TypeError: - pass - - return reversed(list(locate(iterable, pred, window_size))) - - -def replace(iterable, pred, substitutes, count=None, window_size=1): - """Yield the items from *iterable*, replacing the items for which *pred* - returns ``True`` with the items from the iterable *substitutes*. - - >>> iterable = [1, 1, 0, 1, 1, 0, 1, 1] - >>> pred = lambda x: x == 0 - >>> substitutes = (2, 3) - >>> list(replace(iterable, pred, substitutes)) - [1, 1, 2, 3, 1, 1, 2, 3, 1, 1] - - If *count* is given, the number of replacements will be limited: - - >>> iterable = [1, 1, 0, 1, 1, 0, 1, 1, 0] - >>> pred = lambda x: x == 0 - >>> substitutes = [None] - >>> list(replace(iterable, pred, substitutes, count=2)) - [1, 1, None, 1, 1, None, 1, 1, 0] - - Use *window_size* to control the number of items passed as arguments to - *pred*. This allows for locating and replacing subsequences. - - >>> iterable = [0, 1, 2, 5, 0, 1, 2, 5] - >>> window_size = 3 - >>> pred = lambda *args: args == (0, 1, 2) # 3 items passed to pred - >>> substitutes = [3, 4] # Splice in these items - >>> list(replace(iterable, pred, substitutes, window_size=window_size)) - [3, 4, 5, 3, 4, 5] - - """ - if window_size < 1: - raise ValueError('window_size must be at least 1') - - # Save the substitutes iterable, since it's used more than once - substitutes = tuple(substitutes) - - # Add padding such that the number of windows matches the length of the - # iterable - it = chain(iterable, [_marker] * (window_size - 1)) - windows = windowed(it, window_size) - - n = 0 - for w in windows: - # If the current window matches our predicate (and we haven't hit - # our maximum number of replacements), splice in the substitutes - # and then consume the following windows that overlap with this one. - # For example, if the iterable is (0, 1, 2, 3, 4...) - # and the window size is 2, we have (0, 1), (1, 2), (2, 3)... - # If the predicate matches on (0, 1), we need to zap (0, 1) and (1, 2) - if pred(*w): - if (count is None) or (n < count): - n += 1 - yield from substitutes - consume(windows, window_size - 1) - continue - - # If there was no match (or we've reached the replacement limit), - # yield the first item from the window. - if w and (w[0] is not _marker): - yield w[0] - - -def partitions(iterable): - """Yield all possible order-preserving partitions of *iterable*. - - >>> iterable = 'abc' - >>> for part in partitions(iterable): - ... print([''.join(p) for p in part]) - ['abc'] - ['a', 'bc'] - ['ab', 'c'] - ['a', 'b', 'c'] - - This is unrelated to :func:`partition`. - - """ - sequence = list(iterable) - n = len(sequence) - for i in powerset(range(1, n)): - yield [sequence[i:j] for i, j in zip((0,) + i, i + (n,))] - - -def set_partitions(iterable, k=None): - """ - Yield the set partitions of *iterable* into *k* parts. Set partitions are - not order-preserving. - - >>> iterable = 'abc' - >>> for part in set_partitions(iterable, 2): - ... print([''.join(p) for p in part]) - ['a', 'bc'] - ['ab', 'c'] - ['b', 'ac'] - - - If *k* is not given, every set partition is generated. - - >>> iterable = 'abc' - >>> for part in set_partitions(iterable): - ... print([''.join(p) for p in part]) - ['abc'] - ['a', 'bc'] - ['ab', 'c'] - ['b', 'ac'] - ['a', 'b', 'c'] - - """ - L = list(iterable) - n = len(L) - if k is not None: - if k < 1: - raise ValueError( - "Can't partition in a negative or zero number of groups" - ) - elif k > n: - return - - def set_partitions_helper(L, k): - n = len(L) - if k == 1: - yield [L] - elif n == k: - yield [[s] for s in L] - else: - e, *M = L - for p in set_partitions_helper(M, k - 1): - yield [[e], *p] - for p in set_partitions_helper(M, k): - for i in range(len(p)): - yield p[:i] + [[e] + p[i]] + p[i + 1 :] - - if k is None: - for k in range(1, n + 1): - yield from set_partitions_helper(L, k) - else: - yield from set_partitions_helper(L, k) - - -class time_limited: - """ - Yield items from *iterable* until *limit_seconds* have passed. - If the time limit expires before all items have been yielded, the - ``timed_out`` parameter will be set to ``True``. - - >>> from time import sleep - >>> def generator(): - ... yield 1 - ... yield 2 - ... sleep(0.2) - ... yield 3 - >>> iterable = time_limited(0.1, generator()) - >>> list(iterable) - [1, 2] - >>> iterable.timed_out - True - - Note that the time is checked before each item is yielded, and iteration - stops if the time elapsed is greater than *limit_seconds*. If your time - limit is 1 second, but it takes 2 seconds to generate the first item from - the iterable, the function will run for 2 seconds and not yield anything. - - """ - - def __init__(self, limit_seconds, iterable): - if limit_seconds < 0: - raise ValueError('limit_seconds must be positive') - self.limit_seconds = limit_seconds - self._iterable = iter(iterable) - self._start_time = monotonic() - self.timed_out = False - - def __iter__(self): - return self - - def __next__(self): - item = next(self._iterable) - if monotonic() - self._start_time > self.limit_seconds: - self.timed_out = True - raise StopIteration - - return item - - -def only(iterable, default=None, too_long=None): - """If *iterable* has only one item, return it. - If it has zero items, return *default*. - If it has more than one item, raise the exception given by *too_long*, - which is ``ValueError`` by default. - - >>> only([], default='missing') - 'missing' - >>> only([1]) - 1 - >>> only([1, 2]) # doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ... - ValueError: Expected exactly one item in iterable, but got 1, 2, - and perhaps more.' - >>> only([1, 2], too_long=TypeError) # doctest: +IGNORE_EXCEPTION_DETAIL - Traceback (most recent call last): - ... - TypeError - - Note that :func:`only` attempts to advance *iterable* twice to ensure there - is only one item. See :func:`spy` or :func:`peekable` to check - iterable contents less destructively. - """ - it = iter(iterable) - first_value = next(it, default) - - try: - second_value = next(it) - except StopIteration: - pass - else: - msg = ( - 'Expected exactly one item in iterable, but got {!r}, {!r}, ' - 'and perhaps more.'.format(first_value, second_value) - ) - raise too_long or ValueError(msg) - - return first_value - - -def ichunked(iterable, n): - """Break *iterable* into sub-iterables with *n* elements each. - :func:`ichunked` is like :func:`chunked`, but it yields iterables - instead of lists. - - If the sub-iterables are read in order, the elements of *iterable* - won't be stored in memory. - If they are read out of order, :func:`itertools.tee` is used to cache - elements as necessary. - - >>> from itertools import count - >>> all_chunks = ichunked(count(), 4) - >>> c_1, c_2, c_3 = next(all_chunks), next(all_chunks), next(all_chunks) - >>> list(c_2) # c_1's elements have been cached; c_3's haven't been - [4, 5, 6, 7] - >>> list(c_1) - [0, 1, 2, 3] - >>> list(c_3) - [8, 9, 10, 11] - - """ - source = iter(iterable) - - while True: - # Check to see whether we're at the end of the source iterable - item = next(source, _marker) - if item is _marker: - return - - # Clone the source and yield an n-length slice - source, it = tee(chain([item], source)) - yield islice(it, n) - - # Advance the source iterable - consume(source, n) - - -def distinct_combinations(iterable, r): - """Yield the distinct combinations of *r* items taken from *iterable*. - - >>> list(distinct_combinations([0, 0, 1], 2)) - [(0, 0), (0, 1)] - - Equivalent to ``set(combinations(iterable))``, except duplicates are not - generated and thrown away. For larger input sequences this is much more - efficient. - - """ - if r < 0: - raise ValueError('r must be non-negative') - elif r == 0: - yield () - return - pool = tuple(iterable) - generators = [unique_everseen(enumerate(pool), key=itemgetter(1))] - current_combo = [None] * r - level = 0 - while generators: - try: - cur_idx, p = next(generators[-1]) - except StopIteration: - generators.pop() - level -= 1 - continue - current_combo[level] = p - if level + 1 == r: - yield tuple(current_combo) - else: - generators.append( - unique_everseen( - enumerate(pool[cur_idx + 1 :], cur_idx + 1), - key=itemgetter(1), - ) - ) - level += 1 - - -def filter_except(validator, iterable, *exceptions): - """Yield the items from *iterable* for which the *validator* function does - not raise one of the specified *exceptions*. - - *validator* is called for each item in *iterable*. - It should be a function that accepts one argument and raises an exception - if that item is not valid. - - >>> iterable = ['1', '2', 'three', '4', None] - >>> list(filter_except(int, iterable, ValueError, TypeError)) - ['1', '2', '4'] - - If an exception other than one given by *exceptions* is raised by - *validator*, it is raised like normal. - """ - for item in iterable: - try: - validator(item) - except exceptions: - pass - else: - yield item - - -def map_except(function, iterable, *exceptions): - """Transform each item from *iterable* with *function* and yield the - result, unless *function* raises one of the specified *exceptions*. - - *function* is called to transform each item in *iterable*. - It should be a accept one argument. - - >>> iterable = ['1', '2', 'three', '4', None] - >>> list(map_except(int, iterable, ValueError, TypeError)) - [1, 2, 4] - - If an exception other than one given by *exceptions* is raised by - *function*, it is raised like normal. - """ - for item in iterable: - try: - yield function(item) - except exceptions: - pass - - -def _sample_unweighted(iterable, k): - # Implementation of "Algorithm L" from the 1994 paper by Kim-Hung Li: - # "Reservoir-Sampling Algorithms of Time Complexity O(n(1+log(N/n)))". - - # Fill up the reservoir (collection of samples) with the first `k` samples - reservoir = take(k, iterable) - - # Generate random number that's the largest in a sample of k U(0,1) numbers - # Largest order statistic: https://en.wikipedia.org/wiki/Order_statistic - W = exp(log(random()) / k) - - # The number of elements to skip before changing the reservoir is a random - # number with a geometric distribution. Sample it using random() and logs. - next_index = k + floor(log(random()) / log(1 - W)) - - for index, element in enumerate(iterable, k): - - if index == next_index: - reservoir[randrange(k)] = element - # The new W is the largest in a sample of k U(0, `old_W`) numbers - W *= exp(log(random()) / k) - next_index += floor(log(random()) / log(1 - W)) + 1 - - return reservoir - - -def _sample_weighted(iterable, k, weights): - # Implementation of "A-ExpJ" from the 2006 paper by Efraimidis et al. : - # "Weighted random sampling with a reservoir". - - # Log-transform for numerical stability for weights that are small/large - weight_keys = (log(random()) / weight for weight in weights) - - # Fill up the reservoir (collection of samples) with the first `k` - # weight-keys and elements, then heapify the list. - reservoir = take(k, zip(weight_keys, iterable)) - heapify(reservoir) - - # The number of jumps before changing the reservoir is a random variable - # with an exponential distribution. Sample it using random() and logs. - smallest_weight_key, _ = reservoir[0] - weights_to_skip = log(random()) / smallest_weight_key - - for weight, element in zip(weights, iterable): - if weight >= weights_to_skip: - # The notation here is consistent with the paper, but we store - # the weight-keys in log-space for better numerical stability. - smallest_weight_key, _ = reservoir[0] - t_w = exp(weight * smallest_weight_key) - r_2 = uniform(t_w, 1) # generate U(t_w, 1) - weight_key = log(r_2) / weight - heapreplace(reservoir, (weight_key, element)) - smallest_weight_key, _ = reservoir[0] - weights_to_skip = log(random()) / smallest_weight_key - else: - weights_to_skip -= weight - - # Equivalent to [element for weight_key, element in sorted(reservoir)] - return [heappop(reservoir)[1] for _ in range(k)] - - -def sample(iterable, k, weights=None): - """Return a *k*-length list of elements chosen (without replacement) - from the *iterable*. Like :func:`random.sample`, but works on iterables - of unknown length. - - >>> iterable = range(100) - >>> sample(iterable, 5) # doctest: +SKIP - [81, 60, 96, 16, 4] - - An iterable with *weights* may also be given: - - >>> iterable = range(100) - >>> weights = (i * i + 1 for i in range(100)) - >>> sampled = sample(iterable, 5, weights=weights) # doctest: +SKIP - [79, 67, 74, 66, 78] - - The algorithm can also be used to generate weighted random permutations. - The relative weight of each item determines the probability that it - appears late in the permutation. - - >>> data = "abcdefgh" - >>> weights = range(1, len(data) + 1) - >>> sample(data, k=len(data), weights=weights) # doctest: +SKIP - ['c', 'a', 'b', 'e', 'g', 'd', 'h', 'f'] - """ - if k == 0: - return [] - - iterable = iter(iterable) - if weights is None: - return _sample_unweighted(iterable, k) - else: - weights = iter(weights) - return _sample_weighted(iterable, k, weights) - - -def is_sorted(iterable, key=None, reverse=False): - """Returns ``True`` if the items of iterable are in sorted order, and - ``False`` otherwise. *key* and *reverse* have the same meaning that they do - in the built-in :func:`sorted` function. - - >>> is_sorted(['1', '2', '3', '4', '5'], key=int) - True - >>> is_sorted([5, 4, 3, 1, 2], reverse=True) - False - - The function returns ``False`` after encountering the first out-of-order - item. If there are no out-of-order items, the iterable is exhausted. - """ - - compare = lt if reverse else gt - it = iterable if (key is None) else map(key, iterable) - return not any(starmap(compare, pairwise(it))) - - -class AbortThread(BaseException): - pass - - -class callback_iter: - """Convert a function that uses callbacks to an iterator. - - Let *func* be a function that takes a `callback` keyword argument. - For example: - - >>> def func(callback=None): - ... for i, c in [(1, 'a'), (2, 'b'), (3, 'c')]: - ... if callback: - ... callback(i, c) - ... return 4 - - - Use ``with callback_iter(func)`` to get an iterator over the parameters - that are delivered to the callback. - - >>> with callback_iter(func) as it: - ... for args, kwargs in it: - ... print(args) - (1, 'a') - (2, 'b') - (3, 'c') - - The function will be called in a background thread. The ``done`` property - indicates whether it has completed execution. - - >>> it.done - True - - If it completes successfully, its return value will be available - in the ``result`` property. - - >>> it.result - 4 - - Notes: - - * If the function uses some keyword argument besides ``callback``, supply - *callback_kwd*. - * If it finished executing, but raised an exception, accessing the - ``result`` property will raise the same exception. - * If it hasn't finished executing, accessing the ``result`` - property from within the ``with`` block will raise ``RuntimeError``. - * If it hasn't finished executing, accessing the ``result`` property from - outside the ``with`` block will raise a - ``more_itertools.AbortThread`` exception. - * Provide *wait_seconds* to adjust how frequently the it is polled for - output. - - """ - - def __init__(self, func, callback_kwd='callback', wait_seconds=0.1): - self._func = func - self._callback_kwd = callback_kwd - self._aborted = False - self._future = None - self._wait_seconds = wait_seconds - self._executor = __import__("concurrent.futures").futures.ThreadPoolExecutor(max_workers=1) - self._iterator = self._reader() - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, traceback): - self._aborted = True - self._executor.shutdown() - - def __iter__(self): - return self - - def __next__(self): - return next(self._iterator) - - @property - def done(self): - if self._future is None: - return False - return self._future.done() - - @property - def result(self): - if not self.done: - raise RuntimeError('Function has not yet completed') - - return self._future.result() - - def _reader(self): - q = Queue() - - def callback(*args, **kwargs): - if self._aborted: - raise AbortThread('canceled by user') - - q.put((args, kwargs)) - - self._future = self._executor.submit( - self._func, **{self._callback_kwd: callback} - ) - - while True: - try: - item = q.get(timeout=self._wait_seconds) - except Empty: - pass - else: - q.task_done() - yield item - - if self._future.done(): - break - - remaining = [] - while True: - try: - item = q.get_nowait() - except Empty: - break - else: - q.task_done() - remaining.append(item) - q.join() - yield from remaining - - -def windowed_complete(iterable, n): - """ - Yield ``(beginning, middle, end)`` tuples, where: - - * Each ``middle`` has *n* items from *iterable* - * Each ``beginning`` has the items before the ones in ``middle`` - * Each ``end`` has the items after the ones in ``middle`` - - >>> iterable = range(7) - >>> n = 3 - >>> for beginning, middle, end in windowed_complete(iterable, n): - ... print(beginning, middle, end) - () (0, 1, 2) (3, 4, 5, 6) - (0,) (1, 2, 3) (4, 5, 6) - (0, 1) (2, 3, 4) (5, 6) - (0, 1, 2) (3, 4, 5) (6,) - (0, 1, 2, 3) (4, 5, 6) () - - Note that *n* must be at least 0 and most equal to the length of - *iterable*. - - This function will exhaust the iterable and may require significant - storage. - """ - if n < 0: - raise ValueError('n must be >= 0') - - seq = tuple(iterable) - size = len(seq) - - if n > size: - raise ValueError('n must be <= len(seq)') - - for i in range(size - n + 1): - beginning = seq[:i] - middle = seq[i : i + n] - end = seq[i + n :] - yield beginning, middle, end - - -def all_unique(iterable, key=None): - """ - Returns ``True`` if all the elements of *iterable* are unique (no two - elements are equal). - - >>> all_unique('ABCB') - False - - If a *key* function is specified, it will be used to make comparisons. - - >>> all_unique('ABCb') - True - >>> all_unique('ABCb', str.lower) - False - - The function returns as soon as the first non-unique element is - encountered. Iterables with a mix of hashable and unhashable items can - be used, but the function will be slower for unhashable items. - """ - seenset = set() - seenset_add = seenset.add - seenlist = [] - seenlist_add = seenlist.append - for element in map(key, iterable) if key else iterable: - try: - if element in seenset: - return False - seenset_add(element) - except TypeError: - if element in seenlist: - return False - seenlist_add(element) - return True - - -def nth_product(index, *args): - """Equivalent to ``list(product(*args))[index]``. - - The products of *args* can be ordered lexicographically. - :func:`nth_product` computes the product at sort position *index* without - computing the previous products. - - >>> nth_product(8, range(2), range(2), range(2), range(2)) - (1, 0, 0, 0) - - ``IndexError`` will be raised if the given *index* is invalid. - """ - pools = list(map(tuple, reversed(args))) - ns = list(map(len, pools)) - - c = reduce(mul, ns) - - if index < 0: - index += c - - if not 0 <= index < c: - raise IndexError - - result = [] - for pool, n in zip(pools, ns): - result.append(pool[index % n]) - index //= n - - return tuple(reversed(result)) - - -def nth_permutation(iterable, r, index): - """Equivalent to ``list(permutations(iterable, r))[index]``` - - The subsequences of *iterable* that are of length *r* where order is - important can be ordered lexicographically. :func:`nth_permutation` - computes the subsequence at sort position *index* directly, without - computing the previous subsequences. - - >>> nth_permutation('ghijk', 2, 5) - ('h', 'i') - - ``ValueError`` will be raised If *r* is negative or greater than the length - of *iterable*. - ``IndexError`` will be raised if the given *index* is invalid. - """ - pool = list(iterable) - n = len(pool) - - if r is None or r == n: - r, c = n, factorial(n) - elif not 0 <= r < n: - raise ValueError - else: - c = factorial(n) // factorial(n - r) - - if index < 0: - index += c - - if not 0 <= index < c: - raise IndexError - - if c == 0: - return tuple() - - result = [0] * r - q = index * factorial(n) // c if r < n else index - for d in range(1, n + 1): - q, i = divmod(q, d) - if 0 <= n - d < r: - result[n - d] = i - if q == 0: - break - - return tuple(map(pool.pop, result)) - - -def value_chain(*args): - """Yield all arguments passed to the function in the same order in which - they were passed. If an argument itself is iterable then iterate over its - values. - - >>> list(value_chain(1, 2, 3, [4, 5, 6])) - [1, 2, 3, 4, 5, 6] - - Binary and text strings are not considered iterable and are emitted - as-is: - - >>> list(value_chain('12', '34', ['56', '78'])) - ['12', '34', '56', '78'] - - - Multiple levels of nesting are not flattened. - - """ - for value in args: - if isinstance(value, (str, bytes)): - yield value - continue - try: - yield from value - except TypeError: - yield value - - -def product_index(element, *args): - """Equivalent to ``list(product(*args)).index(element)`` - - The products of *args* can be ordered lexicographically. - :func:`product_index` computes the first index of *element* without - computing the previous products. - - >>> product_index([8, 2], range(10), range(5)) - 42 - - ``ValueError`` will be raised if the given *element* isn't in the product - of *args*. - """ - index = 0 - - for x, pool in zip_longest(element, args, fillvalue=_marker): - if x is _marker or pool is _marker: - raise ValueError('element is not a product of args') - - pool = tuple(pool) - index = index * len(pool) + pool.index(x) - - return index - - -def combination_index(element, iterable): - """Equivalent to ``list(combinations(iterable, r)).index(element)`` - - The subsequences of *iterable* that are of length *r* can be ordered - lexicographically. :func:`combination_index` computes the index of the - first *element*, without computing the previous combinations. - - >>> combination_index('adf', 'abcdefg') - 10 - - ``ValueError`` will be raised if the given *element* isn't one of the - combinations of *iterable*. - """ - element = enumerate(element) - k, y = next(element, (None, None)) - if k is None: - return 0 - - indexes = [] - pool = enumerate(iterable) - for n, x in pool: - if x == y: - indexes.append(n) - tmp, y = next(element, (None, None)) - if tmp is None: - break - else: - k = tmp - else: - raise ValueError('element is not a combination of iterable') - - n, _ = last(pool, default=(n, None)) - - # Python versiosn below 3.8 don't have math.comb - index = 1 - for i, j in enumerate(reversed(indexes), start=1): - j = n - j - if i <= j: - index += factorial(j) // (factorial(i) * factorial(j - i)) - - return factorial(n + 1) // (factorial(k + 1) * factorial(n - k)) - index - - -def permutation_index(element, iterable): - """Equivalent to ``list(permutations(iterable, r)).index(element)``` - - The subsequences of *iterable* that are of length *r* where order is - important can be ordered lexicographically. :func:`permutation_index` - computes the index of the first *element* directly, without computing - the previous permutations. - - >>> permutation_index([1, 3, 2], range(5)) - 19 - - ``ValueError`` will be raised if the given *element* isn't one of the - permutations of *iterable*. - """ - index = 0 - pool = list(iterable) - for i, x in zip(range(len(pool), -1, -1), element): - r = pool.index(x) - index = index * i + r - del pool[r] - - return index - - -class countable: - """Wrap *iterable* and keep a count of how many items have been consumed. - - The ``items_seen`` attribute starts at ``0`` and increments as the iterable - is consumed: - - >>> iterable = map(str, range(10)) - >>> it = countable(iterable) - >>> it.items_seen - 0 - >>> next(it), next(it) - ('0', '1') - >>> list(it) - ['2', '3', '4', '5', '6', '7', '8', '9'] - >>> it.items_seen - 10 - """ - - def __init__(self, iterable): - self._it = iter(iterable) - self.items_seen = 0 - - def __iter__(self): - return self - - def __next__(self): - item = next(self._it) - self.items_seen += 1 - - return item diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/more_itertools/recipes.py b/venv/lib/python3.11/site-packages/setuptools/_vendor/more_itertools/recipes.py deleted file mode 100755 index 521abd7..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_vendor/more_itertools/recipes.py +++ /dev/null @@ -1,620 +0,0 @@ -"""Imported from the recipes section of the itertools documentation. - -All functions taken from the recipes section of the itertools library docs -[1]_. -Some backward-compatible usability improvements have been made. - -.. [1] http://docs.python.org/library/itertools.html#recipes - -""" -import warnings -from collections import deque -from itertools import ( - chain, - combinations, - count, - cycle, - groupby, - islice, - repeat, - starmap, - tee, - zip_longest, -) -import operator -from random import randrange, sample, choice - -__all__ = [ - 'all_equal', - 'consume', - 'convolve', - 'dotproduct', - 'first_true', - 'flatten', - 'grouper', - 'iter_except', - 'ncycles', - 'nth', - 'nth_combination', - 'padnone', - 'pad_none', - 'pairwise', - 'partition', - 'powerset', - 'prepend', - 'quantify', - 'random_combination_with_replacement', - 'random_combination', - 'random_permutation', - 'random_product', - 'repeatfunc', - 'roundrobin', - 'tabulate', - 'tail', - 'take', - 'unique_everseen', - 'unique_justseen', -] - - -def take(n, iterable): - """Return first *n* items of the iterable as a list. - - >>> take(3, range(10)) - [0, 1, 2] - - If there are fewer than *n* items in the iterable, all of them are - returned. - - >>> take(10, range(3)) - [0, 1, 2] - - """ - return list(islice(iterable, n)) - - -def tabulate(function, start=0): - """Return an iterator over the results of ``func(start)``, - ``func(start + 1)``, ``func(start + 2)``... - - *func* should be a function that accepts one integer argument. - - If *start* is not specified it defaults to 0. It will be incremented each - time the iterator is advanced. - - >>> square = lambda x: x ** 2 - >>> iterator = tabulate(square, -3) - >>> take(4, iterator) - [9, 4, 1, 0] - - """ - return map(function, count(start)) - - -def tail(n, iterable): - """Return an iterator over the last *n* items of *iterable*. - - >>> t = tail(3, 'ABCDEFG') - >>> list(t) - ['E', 'F', 'G'] - - """ - return iter(deque(iterable, maxlen=n)) - - -def consume(iterator, n=None): - """Advance *iterable* by *n* steps. If *n* is ``None``, consume it - entirely. - - Efficiently exhausts an iterator without returning values. Defaults to - consuming the whole iterator, but an optional second argument may be - provided to limit consumption. - - >>> i = (x for x in range(10)) - >>> next(i) - 0 - >>> consume(i, 3) - >>> next(i) - 4 - >>> consume(i) - >>> next(i) - Traceback (most recent call last): - File "", line 1, in - StopIteration - - If the iterator has fewer items remaining than the provided limit, the - whole iterator will be consumed. - - >>> i = (x for x in range(3)) - >>> consume(i, 5) - >>> next(i) - Traceback (most recent call last): - File "", line 1, in - StopIteration - - """ - # Use functions that consume iterators at C speed. - if n is None: - # feed the entire iterator into a zero-length deque - deque(iterator, maxlen=0) - else: - # advance to the empty slice starting at position n - next(islice(iterator, n, n), None) - - -def nth(iterable, n, default=None): - """Returns the nth item or a default value. - - >>> l = range(10) - >>> nth(l, 3) - 3 - >>> nth(l, 20, "zebra") - 'zebra' - - """ - return next(islice(iterable, n, None), default) - - -def all_equal(iterable): - """ - Returns ``True`` if all the elements are equal to each other. - - >>> all_equal('aaaa') - True - >>> all_equal('aaab') - False - - """ - g = groupby(iterable) - return next(g, True) and not next(g, False) - - -def quantify(iterable, pred=bool): - """Return the how many times the predicate is true. - - >>> quantify([True, False, True]) - 2 - - """ - return sum(map(pred, iterable)) - - -def pad_none(iterable): - """Returns the sequence of elements and then returns ``None`` indefinitely. - - >>> take(5, pad_none(range(3))) - [0, 1, 2, None, None] - - Useful for emulating the behavior of the built-in :func:`map` function. - - See also :func:`padded`. - - """ - return chain(iterable, repeat(None)) - - -padnone = pad_none - - -def ncycles(iterable, n): - """Returns the sequence elements *n* times - - >>> list(ncycles(["a", "b"], 3)) - ['a', 'b', 'a', 'b', 'a', 'b'] - - """ - return chain.from_iterable(repeat(tuple(iterable), n)) - - -def dotproduct(vec1, vec2): - """Returns the dot product of the two iterables. - - >>> dotproduct([10, 10], [20, 20]) - 400 - - """ - return sum(map(operator.mul, vec1, vec2)) - - -def flatten(listOfLists): - """Return an iterator flattening one level of nesting in a list of lists. - - >>> list(flatten([[0, 1], [2, 3]])) - [0, 1, 2, 3] - - See also :func:`collapse`, which can flatten multiple levels of nesting. - - """ - return chain.from_iterable(listOfLists) - - -def repeatfunc(func, times=None, *args): - """Call *func* with *args* repeatedly, returning an iterable over the - results. - - If *times* is specified, the iterable will terminate after that many - repetitions: - - >>> from operator import add - >>> times = 4 - >>> args = 3, 5 - >>> list(repeatfunc(add, times, *args)) - [8, 8, 8, 8] - - If *times* is ``None`` the iterable will not terminate: - - >>> from random import randrange - >>> times = None - >>> args = 1, 11 - >>> take(6, repeatfunc(randrange, times, *args)) # doctest:+SKIP - [2, 4, 8, 1, 8, 4] - - """ - if times is None: - return starmap(func, repeat(args)) - return starmap(func, repeat(args, times)) - - -def _pairwise(iterable): - """Returns an iterator of paired items, overlapping, from the original - - >>> take(4, pairwise(count())) - [(0, 1), (1, 2), (2, 3), (3, 4)] - - On Python 3.10 and above, this is an alias for :func:`itertools.pairwise`. - - """ - a, b = tee(iterable) - next(b, None) - yield from zip(a, b) - - -try: - from itertools import pairwise as itertools_pairwise -except ImportError: - pairwise = _pairwise -else: - - def pairwise(iterable): - yield from itertools_pairwise(iterable) - - pairwise.__doc__ = _pairwise.__doc__ - - -def grouper(iterable, n, fillvalue=None): - """Collect data into fixed-length chunks or blocks. - - >>> list(grouper('ABCDEFG', 3, 'x')) - [('A', 'B', 'C'), ('D', 'E', 'F'), ('G', 'x', 'x')] - - """ - if isinstance(iterable, int): - warnings.warn( - "grouper expects iterable as first parameter", DeprecationWarning - ) - n, iterable = iterable, n - args = [iter(iterable)] * n - return zip_longest(fillvalue=fillvalue, *args) - - -def roundrobin(*iterables): - """Yields an item from each iterable, alternating between them. - - >>> list(roundrobin('ABC', 'D', 'EF')) - ['A', 'D', 'E', 'B', 'F', 'C'] - - This function produces the same output as :func:`interleave_longest`, but - may perform better for some inputs (in particular when the number of - iterables is small). - - """ - # Recipe credited to George Sakkis - pending = len(iterables) - nexts = cycle(iter(it).__next__ for it in iterables) - while pending: - try: - for next in nexts: - yield next() - except StopIteration: - pending -= 1 - nexts = cycle(islice(nexts, pending)) - - -def partition(pred, iterable): - """ - Returns a 2-tuple of iterables derived from the input iterable. - The first yields the items that have ``pred(item) == False``. - The second yields the items that have ``pred(item) == True``. - - >>> is_odd = lambda x: x % 2 != 0 - >>> iterable = range(10) - >>> even_items, odd_items = partition(is_odd, iterable) - >>> list(even_items), list(odd_items) - ([0, 2, 4, 6, 8], [1, 3, 5, 7, 9]) - - If *pred* is None, :func:`bool` is used. - - >>> iterable = [0, 1, False, True, '', ' '] - >>> false_items, true_items = partition(None, iterable) - >>> list(false_items), list(true_items) - ([0, False, ''], [1, True, ' ']) - - """ - if pred is None: - pred = bool - - evaluations = ((pred(x), x) for x in iterable) - t1, t2 = tee(evaluations) - return ( - (x for (cond, x) in t1 if not cond), - (x for (cond, x) in t2 if cond), - ) - - -def powerset(iterable): - """Yields all possible subsets of the iterable. - - >>> list(powerset([1, 2, 3])) - [(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)] - - :func:`powerset` will operate on iterables that aren't :class:`set` - instances, so repeated elements in the input will produce repeated elements - in the output. Use :func:`unique_everseen` on the input to avoid generating - duplicates: - - >>> seq = [1, 1, 0] - >>> list(powerset(seq)) - [(), (1,), (1,), (0,), (1, 1), (1, 0), (1, 0), (1, 1, 0)] - >>> from more_itertools import unique_everseen - >>> list(powerset(unique_everseen(seq))) - [(), (1,), (0,), (1, 0)] - - """ - s = list(iterable) - return chain.from_iterable(combinations(s, r) for r in range(len(s) + 1)) - - -def unique_everseen(iterable, key=None): - """ - Yield unique elements, preserving order. - - >>> list(unique_everseen('AAAABBBCCDAABBB')) - ['A', 'B', 'C', 'D'] - >>> list(unique_everseen('ABBCcAD', str.lower)) - ['A', 'B', 'C', 'D'] - - Sequences with a mix of hashable and unhashable items can be used. - The function will be slower (i.e., `O(n^2)`) for unhashable items. - - Remember that ``list`` objects are unhashable - you can use the *key* - parameter to transform the list to a tuple (which is hashable) to - avoid a slowdown. - - >>> iterable = ([1, 2], [2, 3], [1, 2]) - >>> list(unique_everseen(iterable)) # Slow - [[1, 2], [2, 3]] - >>> list(unique_everseen(iterable, key=tuple)) # Faster - [[1, 2], [2, 3]] - - Similary, you may want to convert unhashable ``set`` objects with - ``key=frozenset``. For ``dict`` objects, - ``key=lambda x: frozenset(x.items())`` can be used. - - """ - seenset = set() - seenset_add = seenset.add - seenlist = [] - seenlist_add = seenlist.append - use_key = key is not None - - for element in iterable: - k = key(element) if use_key else element - try: - if k not in seenset: - seenset_add(k) - yield element - except TypeError: - if k not in seenlist: - seenlist_add(k) - yield element - - -def unique_justseen(iterable, key=None): - """Yields elements in order, ignoring serial duplicates - - >>> list(unique_justseen('AAAABBBCCDAABBB')) - ['A', 'B', 'C', 'D', 'A', 'B'] - >>> list(unique_justseen('ABBCcAD', str.lower)) - ['A', 'B', 'C', 'A', 'D'] - - """ - return map(next, map(operator.itemgetter(1), groupby(iterable, key))) - - -def iter_except(func, exception, first=None): - """Yields results from a function repeatedly until an exception is raised. - - Converts a call-until-exception interface to an iterator interface. - Like ``iter(func, sentinel)``, but uses an exception instead of a sentinel - to end the loop. - - >>> l = [0, 1, 2] - >>> list(iter_except(l.pop, IndexError)) - [2, 1, 0] - - """ - try: - if first is not None: - yield first() - while 1: - yield func() - except exception: - pass - - -def first_true(iterable, default=None, pred=None): - """ - Returns the first true value in the iterable. - - If no true value is found, returns *default* - - If *pred* is not None, returns the first item for which - ``pred(item) == True`` . - - >>> first_true(range(10)) - 1 - >>> first_true(range(10), pred=lambda x: x > 5) - 6 - >>> first_true(range(10), default='missing', pred=lambda x: x > 9) - 'missing' - - """ - return next(filter(pred, iterable), default) - - -def random_product(*args, repeat=1): - """Draw an item at random from each of the input iterables. - - >>> random_product('abc', range(4), 'XYZ') # doctest:+SKIP - ('c', 3, 'Z') - - If *repeat* is provided as a keyword argument, that many items will be - drawn from each iterable. - - >>> random_product('abcd', range(4), repeat=2) # doctest:+SKIP - ('a', 2, 'd', 3) - - This equivalent to taking a random selection from - ``itertools.product(*args, **kwarg)``. - - """ - pools = [tuple(pool) for pool in args] * repeat - return tuple(choice(pool) for pool in pools) - - -def random_permutation(iterable, r=None): - """Return a random *r* length permutation of the elements in *iterable*. - - If *r* is not specified or is ``None``, then *r* defaults to the length of - *iterable*. - - >>> random_permutation(range(5)) # doctest:+SKIP - (3, 4, 0, 1, 2) - - This equivalent to taking a random selection from - ``itertools.permutations(iterable, r)``. - - """ - pool = tuple(iterable) - r = len(pool) if r is None else r - return tuple(sample(pool, r)) - - -def random_combination(iterable, r): - """Return a random *r* length subsequence of the elements in *iterable*. - - >>> random_combination(range(5), 3) # doctest:+SKIP - (2, 3, 4) - - This equivalent to taking a random selection from - ``itertools.combinations(iterable, r)``. - - """ - pool = tuple(iterable) - n = len(pool) - indices = sorted(sample(range(n), r)) - return tuple(pool[i] for i in indices) - - -def random_combination_with_replacement(iterable, r): - """Return a random *r* length subsequence of elements in *iterable*, - allowing individual elements to be repeated. - - >>> random_combination_with_replacement(range(3), 5) # doctest:+SKIP - (0, 0, 1, 2, 2) - - This equivalent to taking a random selection from - ``itertools.combinations_with_replacement(iterable, r)``. - - """ - pool = tuple(iterable) - n = len(pool) - indices = sorted(randrange(n) for i in range(r)) - return tuple(pool[i] for i in indices) - - -def nth_combination(iterable, r, index): - """Equivalent to ``list(combinations(iterable, r))[index]``. - - The subsequences of *iterable* that are of length *r* can be ordered - lexicographically. :func:`nth_combination` computes the subsequence at - sort position *index* directly, without computing the previous - subsequences. - - >>> nth_combination(range(5), 3, 5) - (0, 3, 4) - - ``ValueError`` will be raised If *r* is negative or greater than the length - of *iterable*. - ``IndexError`` will be raised if the given *index* is invalid. - """ - pool = tuple(iterable) - n = len(pool) - if (r < 0) or (r > n): - raise ValueError - - c = 1 - k = min(r, n - r) - for i in range(1, k + 1): - c = c * (n - k + i) // i - - if index < 0: - index += c - - if (index < 0) or (index >= c): - raise IndexError - - result = [] - while r: - c, n, r = c * r // n, n - 1, r - 1 - while index >= c: - index -= c - c, n = c * (n - r) // n, n - 1 - result.append(pool[-1 - n]) - - return tuple(result) - - -def prepend(value, iterator): - """Yield *value*, followed by the elements in *iterator*. - - >>> value = '0' - >>> iterator = ['1', '2', '3'] - >>> list(prepend(value, iterator)) - ['0', '1', '2', '3'] - - To prepend multiple values, see :func:`itertools.chain` - or :func:`value_chain`. - - """ - return chain([value], iterator) - - -def convolve(signal, kernel): - """Convolve the iterable *signal* with the iterable *kernel*. - - >>> signal = (1, 2, 3, 4, 5) - >>> kernel = [3, 2, 1] - >>> list(convolve(signal, kernel)) - [3, 8, 14, 20, 26, 14, 5] - - Note: the input arguments are not interchangeable, as the *kernel* - is immediately consumed and stored. - - """ - kernel = tuple(kernel)[::-1] - n = len(kernel) - window = deque([0], maxlen=n) * n - for x in chain(signal, repeat(0, n - 1)): - window.append(x) - yield sum(map(operator.mul, kernel, window)) diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/ordered_set.py b/venv/lib/python3.11/site-packages/setuptools/_vendor/ordered_set.py deleted file mode 100755 index 1487600..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_vendor/ordered_set.py +++ /dev/null @@ -1,488 +0,0 @@ -""" -An OrderedSet is a custom MutableSet that remembers its order, so that every -entry has an index that can be looked up. - -Based on a recipe originally posted to ActiveState Recipes by Raymond Hettiger, -and released under the MIT license. -""" -import itertools as it -from collections import deque - -try: - # Python 3 - from collections.abc import MutableSet, Sequence -except ImportError: - # Python 2.7 - from collections import MutableSet, Sequence - -SLICE_ALL = slice(None) -__version__ = "3.1" - - -def is_iterable(obj): - """ - Are we being asked to look up a list of things, instead of a single thing? - We check for the `__iter__` attribute so that this can cover types that - don't have to be known by this module, such as NumPy arrays. - - Strings, however, should be considered as atomic values to look up, not - iterables. The same goes for tuples, since they are immutable and therefore - valid entries. - - We don't need to check for the Python 2 `unicode` type, because it doesn't - have an `__iter__` attribute anyway. - """ - return ( - hasattr(obj, "__iter__") - and not isinstance(obj, str) - and not isinstance(obj, tuple) - ) - - -class OrderedSet(MutableSet, Sequence): - """ - An OrderedSet is a custom MutableSet that remembers its order, so that - every entry has an index that can be looked up. - - Example: - >>> OrderedSet([1, 1, 2, 3, 2]) - OrderedSet([1, 2, 3]) - """ - - def __init__(self, iterable=None): - self.items = [] - self.map = {} - if iterable is not None: - self |= iterable - - def __len__(self): - """ - Returns the number of unique elements in the ordered set - - Example: - >>> len(OrderedSet([])) - 0 - >>> len(OrderedSet([1, 2])) - 2 - """ - return len(self.items) - - def __getitem__(self, index): - """ - Get the item at a given index. - - If `index` is a slice, you will get back that slice of items, as a - new OrderedSet. - - If `index` is a list or a similar iterable, you'll get a list of - items corresponding to those indices. This is similar to NumPy's - "fancy indexing". The result is not an OrderedSet because you may ask - for duplicate indices, and the number of elements returned should be - the number of elements asked for. - - Example: - >>> oset = OrderedSet([1, 2, 3]) - >>> oset[1] - 2 - """ - if isinstance(index, slice) and index == SLICE_ALL: - return self.copy() - elif is_iterable(index): - return [self.items[i] for i in index] - elif hasattr(index, "__index__") or isinstance(index, slice): - result = self.items[index] - if isinstance(result, list): - return self.__class__(result) - else: - return result - else: - raise TypeError("Don't know how to index an OrderedSet by %r" % index) - - def copy(self): - """ - Return a shallow copy of this object. - - Example: - >>> this = OrderedSet([1, 2, 3]) - >>> other = this.copy() - >>> this == other - True - >>> this is other - False - """ - return self.__class__(self) - - def __getstate__(self): - if len(self) == 0: - # The state can't be an empty list. - # We need to return a truthy value, or else __setstate__ won't be run. - # - # This could have been done more gracefully by always putting the state - # in a tuple, but this way is backwards- and forwards- compatible with - # previous versions of OrderedSet. - return (None,) - else: - return list(self) - - def __setstate__(self, state): - if state == (None,): - self.__init__([]) - else: - self.__init__(state) - - def __contains__(self, key): - """ - Test if the item is in this ordered set - - Example: - >>> 1 in OrderedSet([1, 3, 2]) - True - >>> 5 in OrderedSet([1, 3, 2]) - False - """ - return key in self.map - - def add(self, key): - """ - Add `key` as an item to this OrderedSet, then return its index. - - If `key` is already in the OrderedSet, return the index it already - had. - - Example: - >>> oset = OrderedSet() - >>> oset.append(3) - 0 - >>> print(oset) - OrderedSet([3]) - """ - if key not in self.map: - self.map[key] = len(self.items) - self.items.append(key) - return self.map[key] - - append = add - - def update(self, sequence): - """ - Update the set with the given iterable sequence, then return the index - of the last element inserted. - - Example: - >>> oset = OrderedSet([1, 2, 3]) - >>> oset.update([3, 1, 5, 1, 4]) - 4 - >>> print(oset) - OrderedSet([1, 2, 3, 5, 4]) - """ - item_index = None - try: - for item in sequence: - item_index = self.add(item) - except TypeError: - raise ValueError( - "Argument needs to be an iterable, got %s" % type(sequence) - ) - return item_index - - def index(self, key): - """ - Get the index of a given entry, raising an IndexError if it's not - present. - - `key` can be an iterable of entries that is not a string, in which case - this returns a list of indices. - - Example: - >>> oset = OrderedSet([1, 2, 3]) - >>> oset.index(2) - 1 - """ - if is_iterable(key): - return [self.index(subkey) for subkey in key] - return self.map[key] - - # Provide some compatibility with pd.Index - get_loc = index - get_indexer = index - - def pop(self): - """ - Remove and return the last element from the set. - - Raises KeyError if the set is empty. - - Example: - >>> oset = OrderedSet([1, 2, 3]) - >>> oset.pop() - 3 - """ - if not self.items: - raise KeyError("Set is empty") - - elem = self.items[-1] - del self.items[-1] - del self.map[elem] - return elem - - def discard(self, key): - """ - Remove an element. Do not raise an exception if absent. - - The MutableSet mixin uses this to implement the .remove() method, which - *does* raise an error when asked to remove a non-existent item. - - Example: - >>> oset = OrderedSet([1, 2, 3]) - >>> oset.discard(2) - >>> print(oset) - OrderedSet([1, 3]) - >>> oset.discard(2) - >>> print(oset) - OrderedSet([1, 3]) - """ - if key in self: - i = self.map[key] - del self.items[i] - del self.map[key] - for k, v in self.map.items(): - if v >= i: - self.map[k] = v - 1 - - def clear(self): - """ - Remove all items from this OrderedSet. - """ - del self.items[:] - self.map.clear() - - def __iter__(self): - """ - Example: - >>> list(iter(OrderedSet([1, 2, 3]))) - [1, 2, 3] - """ - return iter(self.items) - - def __reversed__(self): - """ - Example: - >>> list(reversed(OrderedSet([1, 2, 3]))) - [3, 2, 1] - """ - return reversed(self.items) - - def __repr__(self): - if not self: - return "%s()" % (self.__class__.__name__,) - return "%s(%r)" % (self.__class__.__name__, list(self)) - - def __eq__(self, other): - """ - Returns true if the containers have the same items. If `other` is a - Sequence, then order is checked, otherwise it is ignored. - - Example: - >>> oset = OrderedSet([1, 3, 2]) - >>> oset == [1, 3, 2] - True - >>> oset == [1, 2, 3] - False - >>> oset == [2, 3] - False - >>> oset == OrderedSet([3, 2, 1]) - False - """ - # In Python 2 deque is not a Sequence, so treat it as one for - # consistent behavior with Python 3. - if isinstance(other, (Sequence, deque)): - # Check that this OrderedSet contains the same elements, in the - # same order, as the other object. - return list(self) == list(other) - try: - other_as_set = set(other) - except TypeError: - # If `other` can't be converted into a set, it's not equal. - return False - else: - return set(self) == other_as_set - - def union(self, *sets): - """ - Combines all unique items. - Each items order is defined by its first appearance. - - Example: - >>> oset = OrderedSet.union(OrderedSet([3, 1, 4, 1, 5]), [1, 3], [2, 0]) - >>> print(oset) - OrderedSet([3, 1, 4, 5, 2, 0]) - >>> oset.union([8, 9]) - OrderedSet([3, 1, 4, 5, 2, 0, 8, 9]) - >>> oset | {10} - OrderedSet([3, 1, 4, 5, 2, 0, 10]) - """ - cls = self.__class__ if isinstance(self, OrderedSet) else OrderedSet - containers = map(list, it.chain([self], sets)) - items = it.chain.from_iterable(containers) - return cls(items) - - def __and__(self, other): - # the parent implementation of this is backwards - return self.intersection(other) - - def intersection(self, *sets): - """ - Returns elements in common between all sets. Order is defined only - by the first set. - - Example: - >>> oset = OrderedSet.intersection(OrderedSet([0, 1, 2, 3]), [1, 2, 3]) - >>> print(oset) - OrderedSet([1, 2, 3]) - >>> oset.intersection([2, 4, 5], [1, 2, 3, 4]) - OrderedSet([2]) - >>> oset.intersection() - OrderedSet([1, 2, 3]) - """ - cls = self.__class__ if isinstance(self, OrderedSet) else OrderedSet - if sets: - common = set.intersection(*map(set, sets)) - items = (item for item in self if item in common) - else: - items = self - return cls(items) - - def difference(self, *sets): - """ - Returns all elements that are in this set but not the others. - - Example: - >>> OrderedSet([1, 2, 3]).difference(OrderedSet([2])) - OrderedSet([1, 3]) - >>> OrderedSet([1, 2, 3]).difference(OrderedSet([2]), OrderedSet([3])) - OrderedSet([1]) - >>> OrderedSet([1, 2, 3]) - OrderedSet([2]) - OrderedSet([1, 3]) - >>> OrderedSet([1, 2, 3]).difference() - OrderedSet([1, 2, 3]) - """ - cls = self.__class__ - if sets: - other = set.union(*map(set, sets)) - items = (item for item in self if item not in other) - else: - items = self - return cls(items) - - def issubset(self, other): - """ - Report whether another set contains this set. - - Example: - >>> OrderedSet([1, 2, 3]).issubset({1, 2}) - False - >>> OrderedSet([1, 2, 3]).issubset({1, 2, 3, 4}) - True - >>> OrderedSet([1, 2, 3]).issubset({1, 4, 3, 5}) - False - """ - if len(self) > len(other): # Fast check for obvious cases - return False - return all(item in other for item in self) - - def issuperset(self, other): - """ - Report whether this set contains another set. - - Example: - >>> OrderedSet([1, 2]).issuperset([1, 2, 3]) - False - >>> OrderedSet([1, 2, 3, 4]).issuperset({1, 2, 3}) - True - >>> OrderedSet([1, 4, 3, 5]).issuperset({1, 2, 3}) - False - """ - if len(self) < len(other): # Fast check for obvious cases - return False - return all(item in self for item in other) - - def symmetric_difference(self, other): - """ - Return the symmetric difference of two OrderedSets as a new set. - That is, the new set will contain all elements that are in exactly - one of the sets. - - Their order will be preserved, with elements from `self` preceding - elements from `other`. - - Example: - >>> this = OrderedSet([1, 4, 3, 5, 7]) - >>> other = OrderedSet([9, 7, 1, 3, 2]) - >>> this.symmetric_difference(other) - OrderedSet([4, 5, 9, 2]) - """ - cls = self.__class__ if isinstance(self, OrderedSet) else OrderedSet - diff1 = cls(self).difference(other) - diff2 = cls(other).difference(self) - return diff1.union(diff2) - - def _update_items(self, items): - """ - Replace the 'items' list of this OrderedSet with a new one, updating - self.map accordingly. - """ - self.items = items - self.map = {item: idx for (idx, item) in enumerate(items)} - - def difference_update(self, *sets): - """ - Update this OrderedSet to remove items from one or more other sets. - - Example: - >>> this = OrderedSet([1, 2, 3]) - >>> this.difference_update(OrderedSet([2, 4])) - >>> print(this) - OrderedSet([1, 3]) - - >>> this = OrderedSet([1, 2, 3, 4, 5]) - >>> this.difference_update(OrderedSet([2, 4]), OrderedSet([1, 4, 6])) - >>> print(this) - OrderedSet([3, 5]) - """ - items_to_remove = set() - for other in sets: - items_to_remove |= set(other) - self._update_items([item for item in self.items if item not in items_to_remove]) - - def intersection_update(self, other): - """ - Update this OrderedSet to keep only items in another set, preserving - their order in this set. - - Example: - >>> this = OrderedSet([1, 4, 3, 5, 7]) - >>> other = OrderedSet([9, 7, 1, 3, 2]) - >>> this.intersection_update(other) - >>> print(this) - OrderedSet([1, 3, 7]) - """ - other = set(other) - self._update_items([item for item in self.items if item in other]) - - def symmetric_difference_update(self, other): - """ - Update this OrderedSet to remove items from another set, then - add items from the other set that were not present in this set. - - Example: - >>> this = OrderedSet([1, 4, 3, 5, 7]) - >>> other = OrderedSet([9, 7, 1, 3, 2]) - >>> this.symmetric_difference_update(other) - >>> print(this) - OrderedSet([4, 5, 9, 2]) - """ - items_to_add = [item for item in other if item not in self] - items_to_remove = set(other) - self._update_items( - [item for item in self.items if item not in items_to_remove] + items_to_add - ) diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/packaging/__about__.py b/venv/lib/python3.11/site-packages/setuptools/_vendor/packaging/__about__.py deleted file mode 100755 index 3551bc2..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_vendor/packaging/__about__.py +++ /dev/null @@ -1,26 +0,0 @@ -# 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. - -__all__ = [ - "__title__", - "__summary__", - "__uri__", - "__version__", - "__author__", - "__email__", - "__license__", - "__copyright__", -] - -__title__ = "packaging" -__summary__ = "Core utilities for Python packages" -__uri__ = "https://github.com/pypa/packaging" - -__version__ = "21.3" - -__author__ = "Donald Stufft and individual contributors" -__email__ = "donald@stufft.io" - -__license__ = "BSD-2-Clause or Apache-2.0" -__copyright__ = "2014-2019 %s" % __author__ diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/packaging/__init__.py b/venv/lib/python3.11/site-packages/setuptools/_vendor/packaging/__init__.py deleted file mode 100755 index 3c50c5d..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_vendor/packaging/__init__.py +++ /dev/null @@ -1,25 +0,0 @@ -# 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 .__about__ import ( - __author__, - __copyright__, - __email__, - __license__, - __summary__, - __title__, - __uri__, - __version__, -) - -__all__ = [ - "__title__", - "__summary__", - "__uri__", - "__version__", - "__author__", - "__email__", - "__license__", - "__copyright__", -] diff --git a/venv/lib/python3.11/site-packages/setuptools/_vendor/packaging/__pycache__/__about__.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_vendor/packaging/__pycache__/__about__.cpython-311.pyc deleted file mode 100755 index f8564044e79844824cd9f72969993a5bd3be3f8d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 646 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 diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/archive_util.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/archive_util.cpython-311.pyc deleted file mode 100755 index 978128da49b9cd9a64ea1bcf6a03438d8df228d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10622 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 diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/cygwinccompiler.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/cygwinccompiler.cpython-311.pyc deleted file mode 100755 index a6b04144331b824aabe7e2fb3a6be8c3aef495ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13626 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 T1A*%btOy8Dr_T+*@Z&!LRbm!5 diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/debug.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/debug.cpython-311.pyc deleted file mode 100755 index 3f4047be8e18ee315571dfd3ea8c90dc2ee8c0ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 324 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 diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/dist.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/dist.cpython-311.pyc deleted file mode 100755 index 8b8efd0dbf14131f19287218378a9a121cb6431a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 55490 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 diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/errors.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/errors.cpython-311.pyc deleted file mode 100755 index 370b451ae39a51fddbebf50eebff22defa0d32df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6797 zcmbVQ&2JmW6<<=MP0_ae?Zi!NkL9|eY>BL6Ag~MD|ZoJ&x z%q<5)+wj{-kV*L;+kn$ihLsH_h#mO zznT5(p+j{CuYdgM%a5xIj`MH&k-w_hmltQtj`M}%IS-t&^RDBSK6kvbD*a{7asGyn zeLW~MHV3St$`jZeV^v`L3Rs1){lIDktjgFtuzCU8$Jha22MgGK#ts2nC}1_l4g)(< zz~&h{3hY<`t21^S*ogvmfU%RnP8G0&jJ*Qv)dF^ivD3i5Q@|D&dkxs@1zR6x>hOfEk1%!)m?&UJ89NVbv49<8>;kaw7O>-tT?F>M0(Qb%T6dNk@((4)@qCk{i65Az z(mK+nUcaZKP2W>Ss7J1f6F&-#NR9GDXCRWE61Vahq91u_piEPUyHTP5%4CGrGgS2D zKxpY3B}^hiPikm6T=_@B4@E3>;=5@e^@>;@m_+q&Kk^gdn|f+e83fsUPjn+KteAE) zsg;O2n|_oUFp+R7^j0CPUNWL9(;%rg)J9Wuq$k{{-^cc=fgdU%^+wuPVPck>_4@su zZ!%r5r!cY$T_Vz%gj?+Ds4tq$rttf5q!V#zk(d=EPec@AU-gK_P2CLoohUG3s~2Hv zDEqJ>RK}DoKk13Zq2U$<1R+r~;5J!)vFYZCN&n#*e!Vz`e_uGtc~C+&m%Y-1Ij;=w z%{^NfuE+BqpSutJbreCWu7K4>t`KU|51MzssywT;+ay=J{jA<@TLfUXY@jl*srjj0Q~$f1Z0 z1HK^fvlXItWeNGK3$P`tNld41-r0S&8O4SA>Nn>X`M~Hhyg^vvtzT*eVYW&BW;XuGk zC?9>3%iRTRxM}@xR7hx$!5#BaHBMU%~9#u`crH~#Z(h%z05}C>Z>~rk=j^b6ZecZ8U^+T9LFrB{5@LN z`XEfCi>8hyfUb)#dEbV&b5GmgH!G+UZcj))Wgw4P&3>BL&hJKHH}J6(vVAy#qXvjU zT|p%n0z4JXJ{YW;SOo#1b5jPX!XD%SI;U_M^Fu6%yo34s(nEn!$(B-Kwhpgi=b;n$ z8-6Hx`z%notqJ35KTcK(p}PY0!me*i8OH{0uac zUE)$kO$BOZdqR5OCJN=p-fg$k5<0v+Rt+O{ofv=}ifbS13G)T%+)qY&6yC zJ7_da7sdjF_-71|QKK1&_V|-KaG&DCCai}eql+Gkfc6v`E)EcAHJt#56qJ8k8TM$- z&dCGD58)=?6A#s3E5f;Qc&wwgvc&UHJEs_dYQ84&4jG|XN3KyFxwfZ{5ciBGI5qUn zy+9^N=RP~=@!vm!#!8i*Y>0~LyBaz39* zv&NXsSf+rZb8w;u6kym0IT)ix@iJ>T>7a&@x#egVYR)E&>1b<<% zV`?Jrk!dI6t6aT>_+mOer(s)s00wl$+h zqE;fu9>Nsor`g~f*?`C|Uv7gp$p&xku>o=a-!{0f`jiw|cfQC?=aDTf)SV^AwFuB8 z1n!i~IwfGwljKC&B>5?j(LwO*N^3iR+rv6B&M5ThVHtR5kfITBOowho}`@iNR?d z<|1~|M0)rXL|xskWN#}fF_KQh*MArF@I9@N#;(fmFU>oUC&g(A)h!-kC~7!mYuv(s zthLrIU$(_=iiMXTfhH2*QxN+H+m-BX#U{oX#Xh*l^>2*HoE4sz2yCKMyXsrzUM9JT z#4nTkt?f$owsI5WjB?lB_d7NwemX9*R!Bb~=`jbL@$fi6OFa<$$fRibsPi#SwOnqv z<4keFWm1MnLdu*486_iKgBPfbj1j98O_))s`S%ggR;yo+X=UTQ5I0u(tXJY@8QGRX z{e`Y?tQI28^zc;58<_%0GDXi-NUVtr@Og=z=Sa^nV)dj6GwONd!;lUc;T_0g)ot8N zs3P+9JIf-{CbfLFZYG0xn&fn=&_q5Z$tTO@8{3uaZ6zkgyUQna4ga6b-_D=?+2=p> z_=2zCe0$}49ba7dc*@5!K1gtD<=(<&nyVn!7tU4=eGVD6CyO@maOIoYTlVSB4SfY$ zQh_no=NxBeu2d@RlxrnAlQ2CsSDMGYzd)Y+>N$<>j-Z1TVk(lSH=fhz?g(1gN1R3S zwE3JycSq2%;>Iitt@%IhzEIe`O1l@y)3eWMbawwS4<_-h1P{fH5L_dN{r5I_66<`w-PG1q*e=Q0xusYME@d=X$uu|rKvizYqNMTqqQt*ih4aajplK6)PLo7lS9o+ts`8w~pPf28KF-(1 zrxh`m!e}|eYm%PJ^3*S@Yw<6LhD%9@6zfqX?CEK|-en{PEHKwRB74mnVxIpe`oSCv zHhf^lZ!=?tTvCO94KvL5bDGWzd{RlJq@)hUcx9d!bR9J3bc;DbcbU+5AydZ!kIQBQ zaFLg8Na~8dC}$SSt8kD`jn*eD@u-s6a|gXWvWBzjo>s}EZ%Hkx|q>)A(KQ;mxmdvf#)+q zTHNaOTfM_6HQPFishTzU%P06WAV4UH9%O>pu7i$W7N9$pCagjs4 zR4FCs@(qbpj0h$TwU&%lP*oJ&#WA*QiIh6k>lvTIXe~zk@$Y5ioBX_@rui`q+PgTZ zNm)S^KxfQFgJx&R@)OkLB1y`z=0!;mK`br0#*aCY zbP2U2x=U_Vfr`?+oRJb~A*m`B31bb~IlDv#H8doRZv&{*ZN`OA?+bA zCTEs-U3Trh*7z-!?@(g-3#b^pOw9|>N|2AyVzew4dSOA3;Q$>r)Le$t`@d6%xwab(r0^TBg;}F}y1C zqA2_INT$PsXcyX|v?0ZbDEOp2-*OEjCZCpS1SWs>;{Arko+a0)k-|;2d#=YeANT z?Ga?|mdmeq(r{2N*KpwHNq-!#Ognqc#a3sv77csxFaVZ=C4(D=ds%`?YY2p}w^f%{ zU&+czfwp(SC8)Z8Im0JuI5zi%TpCUQszEzGX^mp}oEj}~BuOQgsu4sxf5wh2sy^J7 zD{1}zgHUN25@~~C>B@p+J4=O6suFgtUFtoisIDlmR8AiO@yc>l=bRl%&ghbwRV9=$ z+FIqb49DpXcAM>G$2Lb&i|$peXiYj4Bqg+!^qi7nlP>JP585>wl znP7h)2(}?4;h(V?AdIn?n&F4#jEv2Hd@r5^ZKhRGXv^|KLP2ExtO%=Scjy6=viA8b zB6zYbD~gd34!cnWb{~Eb;wRIJ%X=rT&M8V+DI-2}#;V-ypuzGrgw2%!_H27BatsQM zc|Ij%7IFwW_r|WZL2jQhIWEOvu)`B5#>eRarA-b)t=^ZhN?2nNYL>(ryX0GIO++}s zlZzI9d!DC-%-Xq*Smnm^A@@S_5ZoHBrUK~Cl1O5lSU+0_s) zpq*wB=4h$W>{4cr#q6X#w!hHGm#jlm=0oS541o@)_2|17!7t-uNT3yIK2NH21VF%LYLRuV%yJ|+O1L<)4M8H$0`__gx zuKK2rS8JfVy-`}CZ^=3mP%lz)Z?x~0e4#@OYeIDR*ZZnF)-M*kl<$d>=Zd<~2Rx6JttMS<10GuMfyKO^A+YU%Q9>IG;@r-6!VzPG7|G`^2cCLKvoDHilpQ1mLA8`YqIvH18vMp;(C7$<4oHXt!O?sChtNNgQx4awI z^%Kup$7SX(AYap`N?Ax$B^xsX&OT$yRVADHruj5cKtb1R{_wX-!0q?D7^m$=0rtCJ zush#9iqkQtfWv$7Pk z1sYPz1k4Wm)rm{3fX|HBFgF4;TkTk(8uXYUcjq^ooK4jXRyRsBSlz=+FH%y|cU_S) zWT`5B`RTb*Tddp`qYkgJf0cAhX#vmD z^p!Ho_?2?}irs7>IA7|xQ0}-;3}1M{^{)EXLY1EVc!Vp1W5vPvgI8942GXl=+-y9abOd@)>Fm>>*qSDhJ}l11BC0)5~CG z|3q>Bu}4&;IqoCi;M?ULKDY=kcom6OOE^AD>)1x&HRgPOYA*Sf=x681_=? zexcm`!s>-ecmG}aw)|;ebNNpre-~)PxM%g0Wp53xgDlF6-_zegfm3L96VJVu!CZG;{B`mT*3|$dELEtlTG!o885fjE(^$;00YB*9TiCP^8P8UlzeOZLN`uc9 zOqwmQX-~nE_7=Q|8d%Yr@}>O+pH=sz0_moLpJhA@#e|KDPzV6(GZ=giaQ^->a37c- zy0K!RDTH0E5DX#O+jOHtkmX+YQG4jV6+%YnmS^3Q`4_{x>Bf$3Gb%=?kp`7rn=(Qo z>jpyTA%<#iNzYBslBM`+Kx}qugBcIYWcomp8;#b_A?`Cm6l*okgvdq&zaArG1RCS` zLI`mGZpsSHMsqz~g?&1Cc;_bmFJjYIU;XedOCR%k}Jo~}Y0V4%4H)^0?^ zmK)f&jPP|g`u?soujPz3vDH~4!r(^h&%v-O62}Vt5imp?46@O_=|=bU?22uT(kgTq z9b(8CHH3L7CbO>R%_|1yJ&iapclkSwWQ~q`i5cyfJDkUCjgs7pf1O?PgS+;s4r4Yq zKY1RVyJ-ZDC~$Pt;plQ$WuAj$k7fbKMd0YH!{KH(&%v>0oq%HrIJi0-u5J7pIDQ{E zy6SLH@MK-T29Cdm7I!;1LXfG8qtF5>{|>D^b*-*RSgpTAYj0hvD@&{OpFv%p(|QP) z-LcQ1ZjYpmcCD#?9I$%UnqXo5u&_b2xYqq$F=Bl5xn6I;XnmH~!d3J$!!pfDxoH(M#u%O>bln$DrkecBRU=a3pKX=XDe0{CQ- zL2eRC**%w0Rjbu^FMaXfxJ>p)zCU_Mi_(`D9EZ~Z)*^^Y;qY`t(!Zd+EY_6w#FKe% zJekb<;>m25%9}T-93Mwh8cpeR-ZOa-zjNQPFX8bXerNGZ;r9l9@8koMDt+e32Pdym zvLmVa=E`DJ7t|S$uAZWT{@g$qZWS1FW^I%Jku5qga<)S$UL|TUl9_m0$+pG+y56zepD zL>C2tyXdz_wMp|?`U3pWrDja(oH|p6OXMyqs;HR(JLWaL=wPWh_NTcxMB!gW0CAbsjaIL z8Q6{-+=?9B94$qnX}v>|NFZOq*Z?J&n$&az)x<+`uZ zIa2JLs&J#*-1rtZ{@`4Rn=W(HMQ*wh9WQdD6>jj~`v&gyZ1=^s`eF}8OMO%2zNtrS zx$oF|pwb7do9ssNULRh12RGi{cxU6Cd%<=8lg_^4&|Ae$x*_VW-aD^vbBDLM!<%}E zn<#S=MeD9~4Q%MQf3*Ii3fEJ1X?V579V>Ikiq>80GBo@r*M5HOf%lIS_Y&*pD?LM- z9k-2jqtZK2?u~8t9^L9a`smPO?$J=G_e{C>OwqcZG`6yj4?hn6V(RZ-_^iA5&gFmX z|7`HH!SY$0mc3u zl^n~iocEjHY1_Zes!6ocj;N_9cDyXh?s&ZH&<;aIGs8CD3ejJMiQKaOcKY)yi!}Dx X<(C%xtNPZwcY$TQcbI3FR_^;h{fwIC diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/fancy_getopt.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/fancy_getopt.cpython-311.pyc deleted file mode 100755 index 17e919f5559d1c41666d93cd5f0f590a6c70c56b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17237 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 C9}#E( diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/file_util.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/file_util.cpython-311.pyc deleted file mode 100755 index d59b306312526039224d4ba69fade16f78c6e27d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10671 zcmcgyTWlLwdY<8Mco|+LQS#jxTh>a9Wy!JQd*ImC&GyFjCd$THV^ej+8CjGmQadxW zA}zU9gA_{}0>T6aB6PQaT4Ylf*#bd<0)7YcZdcNguDJUl#?|NQ4ax9|H8|JCP{I6Q?r|2WkybKHN^kLqKuM85r7MBe9A?i#1^ zsx8J}<5fYm$86KWHG$_47i0Em@tTOZLv^Yy)%{!HnnMk!p11jHPB&M7sX^6?G?&_< z`ta>m{cm&EB-J*`g@6&1lT%n~27=F^WpkPZ37VIe8)(kC@R!+>j>{x}2EN zbj6Iuugi(JY~VYl$yCYclfEIfFMq=$4D+Sd!K%<l>}se!=2%{h(HZh9w)x(_qTnp8f?X< z1$^w(bCWcwJSk4KeQ4vjkMOacv=Bep$(gm^9Ji0t52Qs?td`(l;pN7*Y8fdmB~DdG ziEEboAzJ;Y*793Cv=M(L&hoR|o5IhyS>9yhZi$+5R7EaRKh`}dzFC_76ZFbcFE-_> z#@CkQxu@uzeUskte|hiLSe;kJX6vNwPobCN|3WV}mlBrUReLplr)mXsq{r~}xHWOLHm#^i28k95msLhe=#v-^}h zo-iln>7-%G<5r2dGL6knme0oLWQ}$;NydY1F;1JJ7KJ38?TEdyt|=-dPUwkgOK`7@ zEp%3ovJJG_2ns4uLo=A5^}8n88dOY0jv7p0KUFuixEzhkk;!EIh9M^=J|2R>hI-}O&_1%5=kUusvJ+4%m8xtFVo#8qRS0(#Zj8_%Bqn=B4VA@w(4SP#=8i$he$|yT;blRdz4jfz4 zidk|Qrp^YeWJ?$&`;1~vmK@rfIHin|BN?YtsAQ)mOCl3p5+kvMp@p3|dGtt0zPf)sjf--omBp}bAZJg|b=eukDlZk1qe_GKaiT;a;>xskt%FImvO)Y-2KNcPD zpMkX#@xy)3J=brbD+gwj$PMMXX7n4HnVc~biI~wpRy&&eYe#e6%v`B$jLy(8mKI6G zF&|7rm(jQ%ALH+Esx5HkR?Zt-7%X}M3xj3bv*Nb0O>n=?ueNPj5|&@z^`3Z=YW3%zJhhJiE)B!`)i8iN4m=VCxCL`^6{o`Ow8e=;HS(&xN+Y+P;oru)S=Djf%n0`_g;T z(&2XlcLG_wHf!j)$D!jZq2u@3?kS&4KQR%19o)*j&yRF*OVZhZ@Gm`Q zCE+tkMD(-3UZj3@D0I%reeR$VpF5>Pb*99P#;OW78gxr+Vu6kAxyAy2R^2sYaf6W^eQT3#Le)N~u9P2E^?is_ z^CLPr*#nTd<$KHXYs;scx*awZ$)+h$byr%Q+C=k)`Ce@k)?d?WUEZX2N4-uxw!z$Z z7NZ-emzdg8jju1uW(3n7V}7t&j?qJq?w@h-NOer(e}n!>mHxfHiH83_{oB^myV}(K zzTTNf>V4a=oXxNSx{ozUW;2NDtzGBo0LpeYmEBR5pW;)2l)I)BhhI|t*TfoP4*T2m zeNB>f)+J%>dr{w0uiv~oZm_!9ScW~yE^G}9>?;hPuYvji#}|O33H1{+R%A7*YY{V{ z&-D^Jh*ye7Etn4U71dPA&^37$pr0`a1KdC+f^bR(ZP4^t!1`V}YSsvZ)iRYpb3GR( z7?ws!OCbx4vI?`&Sd18lo-`-nTruDf0U8}2M{{al*iv;y*9=X+sf|r1)C%Z_;-;R| z;>PDRPf ziTJuXz?^gq7KG&n6Y*}73GKGjCzswFnw^HhF#%Z5RI5;OW+nkn7&TAI-J}nr9zEf1 znM_DxB9mI=2C2b1+|WTLh2#^nr0H~1iN=)i7?!{Vt2AZG6G+AUn}7)oc^p&--DFia zU^+eFirIe}r_s2iMC2=@y>b#HnoZC+Jd`π9%3`7ntzPb-mx!Ppg6X`D5|7HhTZ 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 diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/msvccompiler.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/msvccompiler.cpython-311.pyc deleted file mode 100755 index 923ab5328c2e6b4239f7b9fb35f06269c019006e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26972 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 diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/py38compat.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/py38compat.cpython-311.pyc deleted file mode 100755 index d48b0086ad7d6bce4a462f8c2ac4b6f9f7300608..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 624 zcmZWmL2DC16n?XtG_jkwrz+SYfGn7E=LA-g;LoWrTii9;grmMS|VP=vxO#)Ip z_ydGWPdP=Uei>J++}edM=~@G83>hub!I9K(8 z{i88+} zhl*DHK5^zm^R`nk52;=we1ODCr}G!t<>72xy36P8+L^m{>J~?C zahNSmemb`jAnE)yTx4^fQi+YZ$z*crES)ZeX+KiZWk)c>4|< zFRt1HvTAP?$n^T}Fvbc<2jMFFDB^xIWRK-dl+(`cBEiE6NvsTcn85!a^Jw`48u^r^ diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/py39compat.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/py39compat.cpython-311.pyc deleted file mode 100755 index 08d07707176af8dbda8d5ad54a877c535d2f128b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 992 zcmZ8fK}#D!6rR~6YZ{GpjkUB;2o-7~=r#rlg4ly7RM85yRMJCOGZS6i-C1TfsVR{z zrO-c6DD>pXw%CJ*{(v5Pj1p+rQ=unsDfZ;4Z?-0C-`joj-n?(#d-LXfOePZusQK>0 z)++^}U()Ch*dd*kVR?@TBG^KOe=9CvqP#%`g`%yVkkeAhU&baUJhnMs*MTmkr8im+y2KpMFddN|om+cS zTzxt}|7dM=BJI{(Lno&2DxPVHkzD?Mc#_MI%ULBzT%ZGG^>H>5M2n{F27`3RqmD3{ zQxuhQ+1#NbP%ADmJSs6VC08LvkO1I0M97XnS!d7nO=eTwHh78Y3v7esb;EV_Ds`&5 zWv=UP&D&&7ej=CCh3V08*C=fp8&v3mdKK4W%o2LBTQtD)Qzd4*hBx8X0?i<#c#*W2 zpW=OxHwM300pX)|9K{CwMae(48$Yznv6eZ~#+usLr(9DT_ZM2x_}j(Ti>=fhfc6cy zdjbC&sWJ7B6z!|x6k?*Raw0ExA}2HGd1g9LcV)A5wa_CGU1)@@@EkI8te$^ zPxD@oXYpyvu-Az(!&6`mORqfSqwhmL;z>}mJwZg&L=bl^!z(jxhgS^xs+5OMVmf6O zsDSXO9Sk^>5^<>|LI2ej@j(a~#_i;{8L3!whTjHZlUXb$Za)= zp(kCDMngB7sgb>nAPu$(05gXx)3z(3Tq7UHMHf!RPl& H4r}-e7x3{6 diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/spawn.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/spawn.cpython-311.pyc deleted file mode 100755 index 6f007493950d685ef81c6adf4b011910dd886819..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4436 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 AtN;K2 diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/sysconfig.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/sysconfig.cpython-311.pyc deleted file mode 100755 index ffeafa0d4b151263c262968d1c63f763aad093a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22073 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 CWM`NF diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/text_file.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/text_file.cpython-311.pyc deleted file mode 100755 index b540ab5c7febcd9562f155759e52727e809785d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11273 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 diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/unixccompiler.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/unixccompiler.cpython-311.pyc deleted file mode 100755 index 31da75934b3003ffc6f8b69a5b3df7288660307e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16496 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 UuX^{ic>edK<{$T{C+qru0dq@7e*gdg diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/util.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/util.cpython-311.pyc deleted file mode 100755 index cec334406fa6dc046a8ed57922e040f7d1fa729d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20847 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 diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/version.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/__pycache__/version.cpython-311.pyc deleted file mode 100755 index 58d12b44e36da9b9af1055b8f1ba58c48ae04d20..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11349 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 tZm>PT?jmT`+IJ7h3>> stack = DictStack([dict(a=1, c=2), dict(b=2, a=2)]) - >>> stack['a'] - 2 - >>> stack['b'] - 2 - >>> stack['c'] - 2 - >>> len(stack) - 3 - >>> stack.push(dict(a=3)) - >>> stack['a'] - 3 - >>> set(stack.keys()) == set(['a', 'b', 'c']) - True - >>> set(stack.items()) == set([('a', 3), ('b', 2), ('c', 2)]) - True - >>> dict(**stack) == dict(stack) == dict(a=3, c=2, b=2) - True - >>> d = stack.pop() - >>> stack['a'] - 2 - >>> d = stack.pop() - >>> stack['a'] - 1 - >>> stack.get('b', None) - >>> 'c' in stack - True - """ - - def __iter__(self): - dicts = list.__iter__(self) - return iter(set(itertools.chain.from_iterable(c.keys() for c in dicts))) - - def __getitem__(self, key): - for scope in reversed(tuple(list.__iter__(self))): - if key in scope: - return scope[key] - raise KeyError(key) - - push = list.append - - def __contains__(self, other): - return collections.abc.Mapping.__contains__(self, other) - - def __len__(self): - return len(list(iter(self))) - - -# from jaraco.collections 3.7 -class RangeMap(dict): - """ - A dictionary-like object that uses the keys as bounds for a range. - Inclusion of the value for that range is determined by the - key_match_comparator, which defaults to less-than-or-equal. - A value is returned for a key if it is the first key that matches in - the sorted list of keys. - - One may supply keyword parameters to be passed to the sort function used - to sort keys (i.e. key, reverse) as sort_params. - - Let's create a map that maps 1-3 -> 'a', 4-6 -> 'b' - - >>> r = RangeMap({3: 'a', 6: 'b'}) # boy, that was easy - >>> r[1], r[2], r[3], r[4], r[5], r[6] - ('a', 'a', 'a', 'b', 'b', 'b') - - Even float values should work so long as the comparison operator - supports it. - - >>> r[4.5] - 'b' - - But you'll notice that the way rangemap is defined, it must be open-ended - on one side. - - >>> r[0] - 'a' - >>> r[-1] - 'a' - - One can close the open-end of the RangeMap by using undefined_value - - >>> r = RangeMap({0: RangeMap.undefined_value, 3: 'a', 6: 'b'}) - >>> r[0] - Traceback (most recent call last): - ... - KeyError: 0 - - One can get the first or last elements in the range by using RangeMap.Item - - >>> last_item = RangeMap.Item(-1) - >>> r[last_item] - 'b' - - .last_item is a shortcut for Item(-1) - - >>> r[RangeMap.last_item] - 'b' - - Sometimes it's useful to find the bounds for a RangeMap - - >>> r.bounds() - (0, 6) - - RangeMap supports .get(key, default) - - >>> r.get(0, 'not found') - 'not found' - - >>> r.get(7, 'not found') - 'not found' - - One often wishes to define the ranges by their left-most values, - which requires use of sort params and a key_match_comparator. - - >>> r = RangeMap({1: 'a', 4: 'b'}, - ... sort_params=dict(reverse=True), - ... key_match_comparator=operator.ge) - >>> r[1], r[2], r[3], r[4], r[5], r[6] - ('a', 'a', 'a', 'b', 'b', 'b') - - That wasn't nearly as easy as before, so an alternate constructor - is provided: - - >>> r = RangeMap.left({1: 'a', 4: 'b', 7: RangeMap.undefined_value}) - >>> r[1], r[2], r[3], r[4], r[5], r[6] - ('a', 'a', 'a', 'b', 'b', 'b') - - """ - - def __init__(self, source, sort_params={}, key_match_comparator=operator.le): - dict.__init__(self, source) - self.sort_params = sort_params - self.match = key_match_comparator - - @classmethod - def left(cls, source): - return cls( - source, sort_params=dict(reverse=True), key_match_comparator=operator.ge - ) - - def __getitem__(self, item): - sorted_keys = sorted(self.keys(), **self.sort_params) - if isinstance(item, RangeMap.Item): - result = self.__getitem__(sorted_keys[item]) - else: - key = self._find_first_match_(sorted_keys, item) - result = dict.__getitem__(self, key) - if result is RangeMap.undefined_value: - raise KeyError(key) - return result - - def get(self, key, default=None): - """ - Return the value for key if key is in the dictionary, else default. - If default is not given, it defaults to None, so that this method - never raises a KeyError. - """ - try: - return self[key] - except KeyError: - return default - - def _find_first_match_(self, keys, item): - is_match = functools.partial(self.match, item) - matches = list(filter(is_match, keys)) - if matches: - return matches[0] - raise KeyError(item) - - def bounds(self): - sorted_keys = sorted(self.keys(), **self.sort_params) - return (sorted_keys[RangeMap.first_item], sorted_keys[RangeMap.last_item]) - - # some special values for the RangeMap - undefined_value = type(str('RangeValueUndefined'), (), {})() - - class Item(int): - "RangeMap Item" - - first_item = Item(0) - last_item = Item(-1) diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/_functools.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/_functools.py deleted file mode 100755 index e7053ba..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/_functools.py +++ /dev/null @@ -1,20 +0,0 @@ -import functools - - -# from jaraco.functools 3.5 -def pass_none(func): - """ - Wrap func so it's not called if its first param is None - - >>> print_text = pass_none(print) - >>> print_text('text') - text - >>> print_text(None) - """ - - @functools.wraps(func) - def wrapper(param, *args, **kwargs): - if param is not None: - return func(param, *args, **kwargs) - - return wrapper diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/_log.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/_log.py deleted file mode 100755 index 4a2ae0a..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/_log.py +++ /dev/null @@ -1,4 +0,0 @@ -import logging - - -log = logging.getLogger() diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/_macos_compat.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/_macos_compat.py deleted file mode 100755 index 17769e9..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/_macos_compat.py +++ /dev/null @@ -1,12 +0,0 @@ -import sys -import importlib - - -def bypass_compiler_fixup(cmd, args): - return cmd - - -if sys.platform == 'darwin': - compiler_fixup = importlib.import_module('_osx_support').compiler_fixup -else: - compiler_fixup = bypass_compiler_fixup diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/_msvccompiler.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/_msvccompiler.py deleted file mode 100755 index 8b4023c..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/_msvccompiler.py +++ /dev/null @@ -1,572 +0,0 @@ -"""distutils._msvccompiler - -Contains MSVCCompiler, an implementation of the abstract CCompiler class -for Microsoft Visual Studio 2015. - -The module is compatible with VS 2015 and later. You can find legacy support -for older versions in distutils.msvc9compiler and distutils.msvccompiler. -""" - -# Written by Perry Stoll -# hacked by Robin Becker and Thomas Heller to do a better job of -# finding DevStudio (through the registry) -# ported to VS 2005 and VS 2008 by Christian Heimes -# ported to VS 2015 by Steve Dower - -import os -import subprocess -import contextlib -import warnings -import unittest.mock as mock - -with contextlib.suppress(ImportError): - import winreg - -from .errors import ( - DistutilsExecError, - DistutilsPlatformError, - CompileError, - LibError, - LinkError, -) -from .ccompiler import CCompiler, gen_lib_options -from ._log import log -from .util import get_platform - -from itertools import count - - -def _find_vc2015(): - try: - key = winreg.OpenKeyEx( - winreg.HKEY_LOCAL_MACHINE, - r"Software\Microsoft\VisualStudio\SxS\VC7", - access=winreg.KEY_READ | winreg.KEY_WOW64_32KEY, - ) - except OSError: - log.debug("Visual C++ is not registered") - return None, None - - best_version = 0 - best_dir = None - with key: - for i in count(): - try: - v, vc_dir, vt = winreg.EnumValue(key, i) - except OSError: - break - if v and vt == winreg.REG_SZ and os.path.isdir(vc_dir): - try: - version = int(float(v)) - except (ValueError, TypeError): - continue - if version >= 14 and version > best_version: - best_version, best_dir = version, vc_dir - return best_version, best_dir - - -def _find_vc2017(): - """Returns "15, path" based on the result of invoking vswhere.exe - If no install is found, returns "None, None" - - The version is returned to avoid unnecessarily changing the function - result. It may be ignored when the path is not None. - - If vswhere.exe is not available, by definition, VS 2017 is not - installed. - """ - root = os.environ.get("ProgramFiles(x86)") or os.environ.get("ProgramFiles") - if not root: - return None, None - - try: - path = subprocess.check_output( - [ - os.path.join( - root, "Microsoft Visual Studio", "Installer", "vswhere.exe" - ), - "-latest", - "-prerelease", - "-requires", - "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", - "-property", - "installationPath", - "-products", - "*", - ], - encoding="mbcs", - errors="strict", - ).strip() - except (subprocess.CalledProcessError, OSError, UnicodeDecodeError): - return None, None - - path = os.path.join(path, "VC", "Auxiliary", "Build") - if os.path.isdir(path): - return 15, path - - return None, None - - -PLAT_SPEC_TO_RUNTIME = { - 'x86': 'x86', - 'x86_amd64': 'x64', - 'x86_arm': 'arm', - 'x86_arm64': 'arm64', -} - - -def _find_vcvarsall(plat_spec): - # bpo-38597: Removed vcruntime return value - _, best_dir = _find_vc2017() - - if not best_dir: - best_version, best_dir = _find_vc2015() - - if not best_dir: - log.debug("No suitable Visual C++ version found") - return None, None - - vcvarsall = os.path.join(best_dir, "vcvarsall.bat") - if not os.path.isfile(vcvarsall): - log.debug("%s cannot be found", vcvarsall) - return None, None - - return vcvarsall, None - - -def _get_vc_env(plat_spec): - if os.getenv("DISTUTILS_USE_SDK"): - return {key.lower(): value for key, value in os.environ.items()} - - vcvarsall, _ = _find_vcvarsall(plat_spec) - if not vcvarsall: - raise DistutilsPlatformError("Unable to find vcvarsall.bat") - - try: - out = subprocess.check_output( - f'cmd /u /c "{vcvarsall}" {plat_spec} && set', - stderr=subprocess.STDOUT, - ).decode('utf-16le', errors='replace') - except subprocess.CalledProcessError as exc: - log.error(exc.output) - raise DistutilsPlatformError(f"Error executing {exc.cmd}") - - env = { - key.lower(): value - for key, _, value in (line.partition('=') for line in out.splitlines()) - if key and value - } - - return env - - -def _find_exe(exe, paths=None): - """Return path to an MSVC executable program. - - Tries to find the program in several places: first, one of the - MSVC program search paths from the registry; next, the directories - in the PATH environment variable. If any of those work, return an - absolute path that is known to exist. If none of them work, just - return the original program name, 'exe'. - """ - if not paths: - paths = os.getenv('path').split(os.pathsep) - for p in paths: - fn = os.path.join(os.path.abspath(p), exe) - if os.path.isfile(fn): - return fn - return exe - - -# A map keyed by get_platform() return values to values accepted by -# 'vcvarsall.bat'. Always cross-compile from x86 to work with the -# lighter-weight MSVC installs that do not include native 64-bit tools. -PLAT_TO_VCVARS = { - 'win32': 'x86', - 'win-amd64': 'x86_amd64', - 'win-arm32': 'x86_arm', - 'win-arm64': 'x86_arm64', -} - - -class MSVCCompiler(CCompiler): - """Concrete class that implements an interface to Microsoft Visual C++, - as defined by the CCompiler abstract class.""" - - compiler_type = 'msvc' - - # Just set this so CCompiler's constructor doesn't barf. We currently - # don't use the 'set_executables()' bureaucracy provided by CCompiler, - # as it really isn't necessary for this sort of single-compiler class. - # Would be nice to have a consistent interface with UnixCCompiler, - # though, so it's worth thinking about. - executables = {} - - # Private class data (need to distinguish C from C++ source for compiler) - _c_extensions = ['.c'] - _cpp_extensions = ['.cc', '.cpp', '.cxx'] - _rc_extensions = ['.rc'] - _mc_extensions = ['.mc'] - - # Needed for the filename generation methods provided by the - # base class, CCompiler. - src_extensions = _c_extensions + _cpp_extensions + _rc_extensions + _mc_extensions - res_extension = '.res' - obj_extension = '.obj' - static_lib_extension = '.lib' - shared_lib_extension = '.dll' - static_lib_format = shared_lib_format = '%s%s' - exe_extension = '.exe' - - def __init__(self, verbose=0, dry_run=0, force=0): - super().__init__(verbose, dry_run, force) - # target platform (.plat_name is consistent with 'bdist') - self.plat_name = None - self.initialized = False - - @classmethod - def _configure(cls, vc_env): - """ - Set class-level include/lib dirs. - """ - cls.include_dirs = cls._parse_path(vc_env.get('include', '')) - cls.library_dirs = cls._parse_path(vc_env.get('lib', '')) - - @staticmethod - def _parse_path(val): - return [dir.rstrip(os.sep) for dir in val.split(os.pathsep) if dir] - - def initialize(self, plat_name=None): - # multi-init means we would need to check platform same each time... - assert not self.initialized, "don't init multiple times" - if plat_name is None: - plat_name = get_platform() - # sanity check for platforms to prevent obscure errors later. - if plat_name not in PLAT_TO_VCVARS: - raise DistutilsPlatformError( - f"--plat-name must be one of {tuple(PLAT_TO_VCVARS)}" - ) - - # Get the vcvarsall.bat spec for the requested platform. - plat_spec = PLAT_TO_VCVARS[plat_name] - - vc_env = _get_vc_env(plat_spec) - if not vc_env: - raise DistutilsPlatformError( - "Unable to find a compatible " "Visual Studio installation." - ) - self._configure(vc_env) - - self._paths = vc_env.get('path', '') - paths = self._paths.split(os.pathsep) - self.cc = _find_exe("cl.exe", paths) - self.linker = _find_exe("link.exe", paths) - self.lib = _find_exe("lib.exe", paths) - self.rc = _find_exe("rc.exe", paths) # resource compiler - self.mc = _find_exe("mc.exe", paths) # message compiler - self.mt = _find_exe("mt.exe", paths) # message compiler - - self.preprocess_options = None - # bpo-38597: Always compile with dynamic linking - # Future releases of Python 3.x will include all past - # versions of vcruntime*.dll for compatibility. - self.compile_options = ['/nologo', '/O2', '/W3', '/GL', '/DNDEBUG', '/MD'] - - self.compile_options_debug = [ - '/nologo', - '/Od', - '/MDd', - '/Zi', - '/W3', - '/D_DEBUG', - ] - - ldflags = ['/nologo', '/INCREMENTAL:NO', '/LTCG'] - - ldflags_debug = ['/nologo', '/INCREMENTAL:NO', '/LTCG', '/DEBUG:FULL'] - - self.ldflags_exe = [*ldflags, '/MANIFEST:EMBED,ID=1'] - self.ldflags_exe_debug = [*ldflags_debug, '/MANIFEST:EMBED,ID=1'] - self.ldflags_shared = [ - *ldflags, - '/DLL', - '/MANIFEST:EMBED,ID=2', - '/MANIFESTUAC:NO', - ] - self.ldflags_shared_debug = [ - *ldflags_debug, - '/DLL', - '/MANIFEST:EMBED,ID=2', - '/MANIFESTUAC:NO', - ] - self.ldflags_static = [*ldflags] - self.ldflags_static_debug = [*ldflags_debug] - - self._ldflags = { - (CCompiler.EXECUTABLE, None): self.ldflags_exe, - (CCompiler.EXECUTABLE, False): self.ldflags_exe, - (CCompiler.EXECUTABLE, True): self.ldflags_exe_debug, - (CCompiler.SHARED_OBJECT, None): self.ldflags_shared, - (CCompiler.SHARED_OBJECT, False): self.ldflags_shared, - (CCompiler.SHARED_OBJECT, True): self.ldflags_shared_debug, - (CCompiler.SHARED_LIBRARY, None): self.ldflags_static, - (CCompiler.SHARED_LIBRARY, False): self.ldflags_static, - (CCompiler.SHARED_LIBRARY, True): self.ldflags_static_debug, - } - - self.initialized = True - - # -- Worker methods ------------------------------------------------ - - @property - def out_extensions(self): - return { - **super().out_extensions, - **{ - ext: self.res_extension - for ext in self._rc_extensions + self._mc_extensions - }, - } - - def compile( # noqa: C901 - self, - sources, - output_dir=None, - macros=None, - include_dirs=None, - debug=0, - extra_preargs=None, - extra_postargs=None, - depends=None, - ): - - if not self.initialized: - self.initialize() - compile_info = self._setup_compile( - output_dir, macros, include_dirs, sources, depends, extra_postargs - ) - macros, objects, extra_postargs, pp_opts, build = compile_info - - compile_opts = extra_preargs or [] - compile_opts.append('/c') - if debug: - compile_opts.extend(self.compile_options_debug) - else: - compile_opts.extend(self.compile_options) - - add_cpp_opts = False - - for obj in objects: - try: - src, ext = build[obj] - except KeyError: - continue - if debug: - # pass the full pathname to MSVC in debug mode, - # this allows the debugger to find the source file - # without asking the user to browse for it - src = os.path.abspath(src) - - if ext in self._c_extensions: - input_opt = "/Tc" + src - elif ext in self._cpp_extensions: - input_opt = "/Tp" + src - add_cpp_opts = True - elif ext in self._rc_extensions: - # compile .RC to .RES file - input_opt = src - output_opt = "/fo" + obj - try: - self.spawn([self.rc] + pp_opts + [output_opt, input_opt]) - except DistutilsExecError as msg: - raise CompileError(msg) - continue - elif ext in self._mc_extensions: - # Compile .MC to .RC file to .RES file. - # * '-h dir' specifies the directory for the - # generated include file - # * '-r dir' specifies the target directory of the - # generated RC file and the binary message resource - # it includes - # - # For now (since there are no options to change this), - # we use the source-directory for the include file and - # the build directory for the RC file and message - # resources. This works at least for win32all. - h_dir = os.path.dirname(src) - rc_dir = os.path.dirname(obj) - try: - # first compile .MC to .RC and .H file - self.spawn([self.mc, '-h', h_dir, '-r', rc_dir, src]) - base, _ = os.path.splitext(os.path.basename(src)) - rc_file = os.path.join(rc_dir, base + '.rc') - # then compile .RC to .RES file - self.spawn([self.rc, "/fo" + obj, rc_file]) - - except DistutilsExecError as msg: - raise CompileError(msg) - continue - else: - # how to handle this file? - raise CompileError(f"Don't know how to compile {src} to {obj}") - - args = [self.cc] + compile_opts + pp_opts - if add_cpp_opts: - args.append('/EHsc') - args.append(input_opt) - args.append("/Fo" + obj) - args.extend(extra_postargs) - - try: - self.spawn(args) - except DistutilsExecError as msg: - raise CompileError(msg) - - return objects - - def create_static_lib( - self, objects, output_libname, output_dir=None, debug=0, target_lang=None - ): - - if not self.initialized: - self.initialize() - objects, output_dir = self._fix_object_args(objects, output_dir) - output_filename = self.library_filename(output_libname, output_dir=output_dir) - - if self._need_link(objects, output_filename): - lib_args = objects + ['/OUT:' + output_filename] - if debug: - pass # XXX what goes here? - try: - log.debug('Executing "%s" %s', self.lib, ' '.join(lib_args)) - self.spawn([self.lib] + lib_args) - except DistutilsExecError as msg: - raise LibError(msg) - else: - log.debug("skipping %s (up-to-date)", output_filename) - - def link( - self, - target_desc, - objects, - output_filename, - output_dir=None, - libraries=None, - library_dirs=None, - runtime_library_dirs=None, - export_symbols=None, - debug=0, - extra_preargs=None, - extra_postargs=None, - build_temp=None, - target_lang=None, - ): - - if not self.initialized: - self.initialize() - objects, output_dir = self._fix_object_args(objects, output_dir) - fixed_args = self._fix_lib_args(libraries, library_dirs, runtime_library_dirs) - libraries, library_dirs, runtime_library_dirs = fixed_args - - if runtime_library_dirs: - self.warn( - "I don't know what to do with 'runtime_library_dirs': " - + str(runtime_library_dirs) - ) - - lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, libraries) - if output_dir is not None: - output_filename = os.path.join(output_dir, output_filename) - - if self._need_link(objects, output_filename): - ldflags = self._ldflags[target_desc, debug] - - export_opts = ["/EXPORT:" + sym for sym in (export_symbols or [])] - - ld_args = ( - ldflags + lib_opts + export_opts + objects + ['/OUT:' + output_filename] - ) - - # The MSVC linker generates .lib and .exp files, which cannot be - # suppressed by any linker switches. The .lib files may even be - # needed! Make sure they are generated in the temporary build - # directory. Since they have different names for debug and release - # builds, they can go into the same directory. - build_temp = os.path.dirname(objects[0]) - if export_symbols is not None: - (dll_name, dll_ext) = os.path.splitext( - os.path.basename(output_filename) - ) - implib_file = os.path.join(build_temp, self.library_filename(dll_name)) - ld_args.append('/IMPLIB:' + implib_file) - - if extra_preargs: - ld_args[:0] = extra_preargs - if extra_postargs: - ld_args.extend(extra_postargs) - - output_dir = os.path.dirname(os.path.abspath(output_filename)) - self.mkpath(output_dir) - try: - log.debug('Executing "%s" %s', self.linker, ' '.join(ld_args)) - self.spawn([self.linker] + ld_args) - except DistutilsExecError as msg: - raise LinkError(msg) - else: - log.debug("skipping %s (up-to-date)", output_filename) - - def spawn(self, cmd): - env = dict(os.environ, PATH=self._paths) - with self._fallback_spawn(cmd, env) as fallback: - return super().spawn(cmd, env=env) - return fallback.value - - @contextlib.contextmanager - def _fallback_spawn(self, cmd, env): - """ - Discovered in pypa/distutils#15, some tools monkeypatch the compiler, - so the 'env' kwarg causes a TypeError. Detect this condition and - restore the legacy, unsafe behavior. - """ - bag = type('Bag', (), {})() - try: - yield bag - except TypeError as exc: - if "unexpected keyword argument 'env'" not in str(exc): - raise - else: - return - warnings.warn("Fallback spawn triggered. Please update distutils monkeypatch.") - with mock.patch.dict('os.environ', env): - bag.value = super().spawn(cmd) - - # -- Miscellaneous methods ----------------------------------------- - # These are all used by the 'gen_lib_options() function, in - # ccompiler.py. - - def library_dir_option(self, dir): - return "/LIBPATH:" + dir - - def runtime_library_dir_option(self, dir): - raise DistutilsPlatformError( - "don't know how to set runtime library search path for MSVC" - ) - - def library_option(self, lib): - return self.library_filename(lib) - - def find_library_file(self, dirs, lib, debug=0): - # Prefer a debugging library if found (and requested), but deal - # with it if we don't have one. - if debug: - try_names = [lib + "_d", lib] - else: - try_names = [lib] - for dir in dirs: - for name in try_names: - libfile = os.path.join(dir, self.library_filename(name)) - if os.path.isfile(libfile): - return libfile - else: - # Oops, didn't find it in *any* of 'dirs' - return None diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/archive_util.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/archive_util.py deleted file mode 100755 index 7f9e1e0..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/archive_util.py +++ /dev/null @@ -1,280 +0,0 @@ -"""distutils.archive_util - -Utility functions for creating archive files (tarballs, zip files, -that sort of thing).""" - -import os -from warnings import warn -import sys - -try: - import zipfile -except ImportError: - zipfile = None - - -from .errors import DistutilsExecError -from .spawn import spawn -from .dir_util import mkpath -from ._log import log - -try: - from pwd import getpwnam -except ImportError: - getpwnam = None - -try: - from grp import getgrnam -except ImportError: - getgrnam = None - - -def _get_gid(name): - """Returns a gid, given a group name.""" - if getgrnam is None or name is None: - return None - try: - result = getgrnam(name) - except KeyError: - result = None - if result is not None: - return result[2] - return None - - -def _get_uid(name): - """Returns an uid, given a user name.""" - if getpwnam is None or name is None: - return None - try: - result = getpwnam(name) - except KeyError: - result = None - if result is not None: - return result[2] - return None - - -def make_tarball( - base_name, base_dir, compress="gzip", verbose=0, dry_run=0, owner=None, group=None -): - """Create a (possibly compressed) tar file from all the files under - 'base_dir'. - - 'compress' must be "gzip" (the default), "bzip2", "xz", "compress", or - None. ("compress" will be deprecated in Python 3.2) - - 'owner' and 'group' can be used to define an owner and a group for the - archive that is being built. If not provided, the current owner and group - will be used. - - The output tar file will be named 'base_dir' + ".tar", possibly plus - the appropriate compression extension (".gz", ".bz2", ".xz" or ".Z"). - - Returns the output filename. - """ - tar_compression = { - 'gzip': 'gz', - 'bzip2': 'bz2', - 'xz': 'xz', - None: '', - 'compress': '', - } - compress_ext = {'gzip': '.gz', 'bzip2': '.bz2', 'xz': '.xz', 'compress': '.Z'} - - # flags for compression program, each element of list will be an argument - if compress is not None and compress not in compress_ext.keys(): - raise ValueError( - "bad value for 'compress': must be None, 'gzip', 'bzip2', " - "'xz' or 'compress'" - ) - - archive_name = base_name + '.tar' - if compress != 'compress': - archive_name += compress_ext.get(compress, '') - - mkpath(os.path.dirname(archive_name), dry_run=dry_run) - - # creating the tarball - import tarfile # late import so Python build itself doesn't break - - log.info('Creating tar archive') - - uid = _get_uid(owner) - gid = _get_gid(group) - - def _set_uid_gid(tarinfo): - if gid is not None: - tarinfo.gid = gid - tarinfo.gname = group - if uid is not None: - tarinfo.uid = uid - tarinfo.uname = owner - return tarinfo - - if not dry_run: - tar = tarfile.open(archive_name, 'w|%s' % tar_compression[compress]) - try: - tar.add(base_dir, filter=_set_uid_gid) - finally: - tar.close() - - # compression using `compress` - if compress == 'compress': - warn("'compress' is deprecated.", DeprecationWarning) - # the option varies depending on the platform - compressed_name = archive_name + compress_ext[compress] - if sys.platform == 'win32': - cmd = [compress, archive_name, compressed_name] - else: - cmd = [compress, '-f', archive_name] - spawn(cmd, dry_run=dry_run) - return compressed_name - - return archive_name - - -def make_zipfile(base_name, base_dir, verbose=0, dry_run=0): # noqa: C901 - """Create a zip file from all the files under 'base_dir'. - - The output zip file will be named 'base_name' + ".zip". Uses either the - "zipfile" Python module (if available) or the InfoZIP "zip" utility - (if installed and found on the default search path). If neither tool is - available, raises DistutilsExecError. Returns the name of the output zip - file. - """ - zip_filename = base_name + ".zip" - mkpath(os.path.dirname(zip_filename), dry_run=dry_run) - - # If zipfile module is not available, try spawning an external - # 'zip' command. - if zipfile is None: - if verbose: - zipoptions = "-r" - else: - zipoptions = "-rq" - - try: - spawn(["zip", zipoptions, zip_filename, base_dir], dry_run=dry_run) - except DistutilsExecError: - # XXX really should distinguish between "couldn't find - # external 'zip' command" and "zip failed". - raise DistutilsExecError( - ( - "unable to create zip file '%s': " - "could neither import the 'zipfile' module nor " - "find a standalone zip utility" - ) - % zip_filename - ) - - else: - log.info("creating '%s' and adding '%s' to it", zip_filename, base_dir) - - if not dry_run: - try: - zip = zipfile.ZipFile( - zip_filename, "w", compression=zipfile.ZIP_DEFLATED - ) - except RuntimeError: - zip = zipfile.ZipFile(zip_filename, "w", compression=zipfile.ZIP_STORED) - - with zip: - if base_dir != os.curdir: - path = os.path.normpath(os.path.join(base_dir, '')) - zip.write(path, path) - log.info("adding '%s'", path) - for dirpath, dirnames, filenames in os.walk(base_dir): - for name in dirnames: - path = os.path.normpath(os.path.join(dirpath, name, '')) - zip.write(path, path) - log.info("adding '%s'", path) - for name in filenames: - path = os.path.normpath(os.path.join(dirpath, name)) - if os.path.isfile(path): - zip.write(path, path) - log.info("adding '%s'", path) - - return zip_filename - - -ARCHIVE_FORMATS = { - 'gztar': (make_tarball, [('compress', 'gzip')], "gzip'ed tar-file"), - 'bztar': (make_tarball, [('compress', 'bzip2')], "bzip2'ed tar-file"), - 'xztar': (make_tarball, [('compress', 'xz')], "xz'ed tar-file"), - 'ztar': (make_tarball, [('compress', 'compress')], "compressed tar file"), - 'tar': (make_tarball, [('compress', None)], "uncompressed tar file"), - 'zip': (make_zipfile, [], "ZIP file"), -} - - -def check_archive_formats(formats): - """Returns the first format from the 'format' list that is unknown. - - If all formats are known, returns None - """ - for format in formats: - if format not in ARCHIVE_FORMATS: - return format - return None - - -def make_archive( - base_name, - format, - root_dir=None, - base_dir=None, - verbose=0, - dry_run=0, - owner=None, - group=None, -): - """Create an archive file (eg. zip or tar). - - 'base_name' is the name of the file to create, minus any format-specific - extension; 'format' is the archive format: one of "zip", "tar", "gztar", - "bztar", "xztar", or "ztar". - - 'root_dir' is a directory that will be the root directory of the - archive; ie. we typically chdir into 'root_dir' before creating the - archive. 'base_dir' is the directory where we start archiving from; - ie. 'base_dir' will be the common prefix of all files and - directories in the archive. 'root_dir' and 'base_dir' both default - to the current directory. Returns the name of the archive file. - - 'owner' and 'group' are used when creating a tar archive. By default, - uses the current owner and group. - """ - save_cwd = os.getcwd() - if root_dir is not None: - log.debug("changing into '%s'", root_dir) - base_name = os.path.abspath(base_name) - if not dry_run: - os.chdir(root_dir) - - if base_dir is None: - base_dir = os.curdir - - kwargs = {'dry_run': dry_run} - - try: - format_info = ARCHIVE_FORMATS[format] - except KeyError: - raise ValueError("unknown archive format '%s'" % format) - - func = format_info[0] - for arg, val in format_info[1]: - kwargs[arg] = val - - if format != 'zip': - kwargs['owner'] = owner - kwargs['group'] = group - - try: - filename = func(base_name, base_dir, **kwargs) - finally: - if root_dir is not None: - log.debug("changing back to '%s'", save_cwd) - os.chdir(save_cwd) - - return filename diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/bcppcompiler.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/bcppcompiler.py deleted file mode 100755 index 5d6b865..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/bcppcompiler.py +++ /dev/null @@ -1,408 +0,0 @@ -"""distutils.bcppcompiler - -Contains BorlandCCompiler, an implementation of the abstract CCompiler class -for the Borland C++ compiler. -""" - -# This implementation by Lyle Johnson, based on the original msvccompiler.py -# module and using the directions originally published by Gordon Williams. - -# XXX looks like there's a LOT of overlap between these two classes: -# someone should sit down and factor out the common code as -# WindowsCCompiler! --GPW - - -import os -import warnings - -from .errors import ( - DistutilsExecError, - CompileError, - LibError, - LinkError, - UnknownFileError, -) -from .ccompiler import CCompiler, gen_preprocess_options -from .file_util import write_file -from .dep_util import newer -from ._log import log - - -warnings.warn( - "bcppcompiler is deprecated and slated to be removed " - "in the future. Please discontinue use or file an issue " - "with pypa/distutils describing your use case.", - DeprecationWarning, -) - - -class BCPPCompiler(CCompiler): - """Concrete class that implements an interface to the Borland C/C++ - compiler, as defined by the CCompiler abstract class. - """ - - compiler_type = 'bcpp' - - # Just set this so CCompiler's constructor doesn't barf. We currently - # don't use the 'set_executables()' bureaucracy provided by CCompiler, - # as it really isn't necessary for this sort of single-compiler class. - # Would be nice to have a consistent interface with UnixCCompiler, - # though, so it's worth thinking about. - executables = {} - - # Private class data (need to distinguish C from C++ source for compiler) - _c_extensions = ['.c'] - _cpp_extensions = ['.cc', '.cpp', '.cxx'] - - # Needed for the filename generation methods provided by the - # base class, CCompiler. - src_extensions = _c_extensions + _cpp_extensions - obj_extension = '.obj' - static_lib_extension = '.lib' - shared_lib_extension = '.dll' - static_lib_format = shared_lib_format = '%s%s' - exe_extension = '.exe' - - def __init__(self, verbose=0, dry_run=0, force=0): - - super().__init__(verbose, dry_run, force) - - # These executables are assumed to all be in the path. - # Borland doesn't seem to use any special registry settings to - # indicate their installation locations. - - self.cc = "bcc32.exe" - self.linker = "ilink32.exe" - self.lib = "tlib.exe" - - self.preprocess_options = None - self.compile_options = ['/tWM', '/O2', '/q', '/g0'] - self.compile_options_debug = ['/tWM', '/Od', '/q', '/g0'] - - self.ldflags_shared = ['/Tpd', '/Gn', '/q', '/x'] - self.ldflags_shared_debug = ['/Tpd', '/Gn', '/q', '/x'] - self.ldflags_static = [] - self.ldflags_exe = ['/Gn', '/q', '/x'] - self.ldflags_exe_debug = ['/Gn', '/q', '/x', '/r'] - - # -- Worker methods ------------------------------------------------ - - def compile( # noqa: C901 - self, - sources, - output_dir=None, - macros=None, - include_dirs=None, - debug=0, - extra_preargs=None, - extra_postargs=None, - depends=None, - ): - - macros, objects, extra_postargs, pp_opts, build = self._setup_compile( - output_dir, macros, include_dirs, sources, depends, extra_postargs - ) - compile_opts = extra_preargs or [] - compile_opts.append('-c') - if debug: - compile_opts.extend(self.compile_options_debug) - else: - compile_opts.extend(self.compile_options) - - for obj in objects: - try: - src, ext = build[obj] - except KeyError: - continue - # XXX why do the normpath here? - src = os.path.normpath(src) - obj = os.path.normpath(obj) - # XXX _setup_compile() did a mkpath() too but before the normpath. - # Is it possible to skip the normpath? - self.mkpath(os.path.dirname(obj)) - - if ext == '.res': - # This is already a binary file -- skip it. - continue # the 'for' loop - if ext == '.rc': - # This needs to be compiled to a .res file -- do it now. - try: - self.spawn(["brcc32", "-fo", obj, src]) - except DistutilsExecError as msg: - raise CompileError(msg) - continue # the 'for' loop - - # The next two are both for the real compiler. - if ext in self._c_extensions: - input_opt = "" - elif ext in self._cpp_extensions: - input_opt = "-P" - else: - # Unknown file type -- no extra options. The compiler - # will probably fail, but let it just in case this is a - # file the compiler recognizes even if we don't. - input_opt = "" - - output_opt = "-o" + obj - - # Compiler command line syntax is: "bcc32 [options] file(s)". - # Note that the source file names must appear at the end of - # the command line. - try: - self.spawn( - [self.cc] - + compile_opts - + pp_opts - + [input_opt, output_opt] - + extra_postargs - + [src] - ) - except DistutilsExecError as msg: - raise CompileError(msg) - - return objects - - # compile () - - def create_static_lib( - self, objects, output_libname, output_dir=None, debug=0, target_lang=None - ): - - (objects, output_dir) = self._fix_object_args(objects, output_dir) - output_filename = self.library_filename(output_libname, output_dir=output_dir) - - if self._need_link(objects, output_filename): - lib_args = [output_filename, '/u'] + objects - if debug: - pass # XXX what goes here? - try: - self.spawn([self.lib] + lib_args) - except DistutilsExecError as msg: - raise LibError(msg) - else: - log.debug("skipping %s (up-to-date)", output_filename) - - # create_static_lib () - - def link( # noqa: C901 - self, - target_desc, - objects, - output_filename, - output_dir=None, - libraries=None, - library_dirs=None, - runtime_library_dirs=None, - export_symbols=None, - debug=0, - extra_preargs=None, - extra_postargs=None, - build_temp=None, - target_lang=None, - ): - - # XXX this ignores 'build_temp'! should follow the lead of - # msvccompiler.py - - (objects, output_dir) = self._fix_object_args(objects, output_dir) - (libraries, library_dirs, runtime_library_dirs) = self._fix_lib_args( - libraries, library_dirs, runtime_library_dirs - ) - - if runtime_library_dirs: - log.warning( - "I don't know what to do with 'runtime_library_dirs': %s", - str(runtime_library_dirs), - ) - - if output_dir is not None: - output_filename = os.path.join(output_dir, output_filename) - - if self._need_link(objects, output_filename): - - # Figure out linker args based on type of target. - if target_desc == CCompiler.EXECUTABLE: - startup_obj = 'c0w32' - if debug: - ld_args = self.ldflags_exe_debug[:] - else: - ld_args = self.ldflags_exe[:] - else: - startup_obj = 'c0d32' - if debug: - ld_args = self.ldflags_shared_debug[:] - else: - ld_args = self.ldflags_shared[:] - - # Create a temporary exports file for use by the linker - if export_symbols is None: - def_file = '' - else: - head, tail = os.path.split(output_filename) - modname, ext = os.path.splitext(tail) - temp_dir = os.path.dirname(objects[0]) # preserve tree structure - def_file = os.path.join(temp_dir, '%s.def' % modname) - contents = ['EXPORTS'] - for sym in export_symbols or []: - contents.append(' {}=_{}'.format(sym, sym)) - self.execute(write_file, (def_file, contents), "writing %s" % def_file) - - # Borland C++ has problems with '/' in paths - objects2 = map(os.path.normpath, objects) - # split objects in .obj and .res files - # Borland C++ needs them at different positions in the command line - objects = [startup_obj] - resources = [] - for file in objects2: - (base, ext) = os.path.splitext(os.path.normcase(file)) - if ext == '.res': - resources.append(file) - else: - objects.append(file) - - for ell in library_dirs: - ld_args.append("/L%s" % os.path.normpath(ell)) - ld_args.append("/L.") # we sometimes use relative paths - - # list of object files - ld_args.extend(objects) - - # XXX the command-line syntax for Borland C++ is a bit wonky; - # certain filenames are jammed together in one big string, but - # comma-delimited. This doesn't mesh too well with the - # Unix-centric attitude (with a DOS/Windows quoting hack) of - # 'spawn()', so constructing the argument list is a bit - # awkward. Note that doing the obvious thing and jamming all - # the filenames and commas into one argument would be wrong, - # because 'spawn()' would quote any filenames with spaces in - # them. Arghghh!. Apparently it works fine as coded... - - # name of dll/exe file - ld_args.extend([',', output_filename]) - # no map file and start libraries - ld_args.append(',,') - - for lib in libraries: - # see if we find it and if there is a bcpp specific lib - # (xxx_bcpp.lib) - libfile = self.find_library_file(library_dirs, lib, debug) - if libfile is None: - ld_args.append(lib) - # probably a BCPP internal library -- don't warn - else: - # full name which prefers bcpp_xxx.lib over xxx.lib - ld_args.append(libfile) - - # some default libraries - ld_args.append('import32') - ld_args.append('cw32mt') - - # def file for export symbols - ld_args.extend([',', def_file]) - # add resource files - ld_args.append(',') - ld_args.extend(resources) - - if extra_preargs: - ld_args[:0] = extra_preargs - if extra_postargs: - ld_args.extend(extra_postargs) - - self.mkpath(os.path.dirname(output_filename)) - try: - self.spawn([self.linker] + ld_args) - except DistutilsExecError as msg: - raise LinkError(msg) - - else: - log.debug("skipping %s (up-to-date)", output_filename) - - # link () - - # -- Miscellaneous methods ----------------------------------------- - - def find_library_file(self, dirs, lib, debug=0): - # List of effective library names to try, in order of preference: - # xxx_bcpp.lib is better than xxx.lib - # and xxx_d.lib is better than xxx.lib if debug is set - # - # The "_bcpp" suffix is to handle a Python installation for people - # with multiple compilers (primarily Distutils hackers, I suspect - # ;-). The idea is they'd have one static library for each - # compiler they care about, since (almost?) every Windows compiler - # seems to have a different format for static libraries. - if debug: - dlib = lib + "_d" - try_names = (dlib + "_bcpp", lib + "_bcpp", dlib, lib) - else: - try_names = (lib + "_bcpp", lib) - - for dir in dirs: - for name in try_names: - libfile = os.path.join(dir, self.library_filename(name)) - if os.path.exists(libfile): - return libfile - else: - # Oops, didn't find it in *any* of 'dirs' - return None - - # overwrite the one from CCompiler to support rc and res-files - def object_filenames(self, source_filenames, strip_dir=0, output_dir=''): - if output_dir is None: - output_dir = '' - obj_names = [] - for src_name in source_filenames: - # use normcase to make sure '.rc' is really '.rc' and not '.RC' - (base, ext) = os.path.splitext(os.path.normcase(src_name)) - if ext not in (self.src_extensions + ['.rc', '.res']): - raise UnknownFileError( - "unknown file type '{}' (from '{}')".format(ext, src_name) - ) - if strip_dir: - base = os.path.basename(base) - if ext == '.res': - # these can go unchanged - obj_names.append(os.path.join(output_dir, base + ext)) - elif ext == '.rc': - # these need to be compiled to .res-files - obj_names.append(os.path.join(output_dir, base + '.res')) - else: - obj_names.append(os.path.join(output_dir, base + self.obj_extension)) - return obj_names - - # object_filenames () - - def preprocess( - self, - source, - output_file=None, - macros=None, - include_dirs=None, - extra_preargs=None, - extra_postargs=None, - ): - - (_, macros, include_dirs) = self._fix_compile_args(None, macros, include_dirs) - pp_opts = gen_preprocess_options(macros, include_dirs) - pp_args = ['cpp32.exe'] + pp_opts - if output_file is not None: - pp_args.append('-o' + output_file) - if extra_preargs: - pp_args[:0] = extra_preargs - if extra_postargs: - pp_args.extend(extra_postargs) - pp_args.append(source) - - # We need to preprocess: either we're being forced to, or the - # source file is newer than the target (or the target doesn't - # exist). - if self.force or output_file is None or newer(source, output_file): - if output_file: - self.mkpath(os.path.dirname(output_file)) - try: - self.spawn(pp_args) - except DistutilsExecError as msg: - print(msg) - raise CompileError(msg) - - # preprocess() diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/ccompiler.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/ccompiler.py deleted file mode 100755 index 6463531..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/ccompiler.py +++ /dev/null @@ -1,1220 +0,0 @@ -"""distutils.ccompiler - -Contains CCompiler, an abstract base class that defines the interface -for the Distutils compiler abstraction model.""" - -import sys -import os -import re - -from .errors import ( - CompileError, - LinkError, - UnknownFileError, - DistutilsPlatformError, - DistutilsModuleError, -) -from .spawn import spawn -from .file_util import move_file -from .dir_util import mkpath -from .dep_util import newer_group -from .util import split_quoted, execute -from ._log import log - - -class CCompiler: - """Abstract base class to define the interface that must be implemented - by real compiler classes. Also has some utility methods used by - several compiler classes. - - The basic idea behind a compiler abstraction class is that each - instance can be used for all the compile/link steps in building a - single project. Thus, attributes common to all of those compile and - link steps -- include directories, macros to define, libraries to link - against, etc. -- are attributes of the compiler instance. To allow for - variability in how individual files are treated, most of those - attributes may be varied on a per-compilation or per-link basis. - """ - - # 'compiler_type' is a class attribute that identifies this class. It - # keeps code that wants to know what kind of compiler it's dealing with - # from having to import all possible compiler classes just to do an - # 'isinstance'. In concrete CCompiler subclasses, 'compiler_type' - # should really, really be one of the keys of the 'compiler_class' - # dictionary (see below -- used by the 'new_compiler()' factory - # function) -- authors of new compiler interface classes are - # responsible for updating 'compiler_class'! - compiler_type = None - - # XXX things not handled by this compiler abstraction model: - # * client can't provide additional options for a compiler, - # e.g. warning, optimization, debugging flags. Perhaps this - # should be the domain of concrete compiler abstraction classes - # (UnixCCompiler, MSVCCompiler, etc.) -- or perhaps the base - # class should have methods for the common ones. - # * can't completely override the include or library searchg - # path, ie. no "cc -I -Idir1 -Idir2" or "cc -L -Ldir1 -Ldir2". - # I'm not sure how widely supported this is even by Unix - # compilers, much less on other platforms. And I'm even less - # sure how useful it is; maybe for cross-compiling, but - # support for that is a ways off. (And anyways, cross - # compilers probably have a dedicated binary with the - # right paths compiled in. I hope.) - # * can't do really freaky things with the library list/library - # dirs, e.g. "-Ldir1 -lfoo -Ldir2 -lfoo" to link against - # different versions of libfoo.a in different locations. I - # think this is useless without the ability to null out the - # library search path anyways. - - # Subclasses that rely on the standard filename generation methods - # implemented below should override these; see the comment near - # those methods ('object_filenames()' et. al.) for details: - src_extensions = None # list of strings - obj_extension = None # string - static_lib_extension = None - shared_lib_extension = None # string - static_lib_format = None # format string - shared_lib_format = None # prob. same as static_lib_format - exe_extension = None # string - - # Default language settings. language_map is used to detect a source - # file or Extension target language, checking source filenames. - # language_order is used to detect the language precedence, when deciding - # what language to use when mixing source types. For example, if some - # extension has two files with ".c" extension, and one with ".cpp", it - # is still linked as c++. - language_map = { - ".c": "c", - ".cc": "c++", - ".cpp": "c++", - ".cxx": "c++", - ".m": "objc", - } - language_order = ["c++", "objc", "c"] - - include_dirs = [] - """ - include dirs specific to this compiler class - """ - - library_dirs = [] - """ - library dirs specific to this compiler class - """ - - def __init__(self, verbose=0, dry_run=0, force=0): - self.dry_run = dry_run - self.force = force - self.verbose = verbose - - # 'output_dir': a common output directory for object, library, - # shared object, and shared library files - self.output_dir = None - - # 'macros': a list of macro definitions (or undefinitions). A - # macro definition is a 2-tuple (name, value), where the value is - # either a string or None (no explicit value). A macro - # undefinition is a 1-tuple (name,). - self.macros = [] - - # 'include_dirs': a list of directories to search for include files - self.include_dirs = [] - - # 'libraries': a list of libraries to include in any link - # (library names, not filenames: eg. "foo" not "libfoo.a") - self.libraries = [] - - # 'library_dirs': a list of directories to search for libraries - self.library_dirs = [] - - # 'runtime_library_dirs': a list of directories to search for - # shared libraries/objects at runtime - self.runtime_library_dirs = [] - - # 'objects': a list of object files (or similar, such as explicitly - # named library files) to include on any link - self.objects = [] - - for key in self.executables.keys(): - self.set_executable(key, self.executables[key]) - - def set_executables(self, **kwargs): - """Define the executables (and options for them) that will be run - to perform the various stages of compilation. The exact set of - executables that may be specified here depends on the compiler - class (via the 'executables' class attribute), but most will have: - compiler the C/C++ compiler - linker_so linker used to create shared objects and libraries - linker_exe linker used to create binary executables - archiver static library creator - - On platforms with a command-line (Unix, DOS/Windows), each of these - is a string that will be split into executable name and (optional) - list of arguments. (Splitting the string is done similarly to how - Unix shells operate: words are delimited by spaces, but quotes and - backslashes can override this. See - 'distutils.util.split_quoted()'.) - """ - - # Note that some CCompiler implementation classes will define class - # attributes 'cpp', 'cc', etc. with hard-coded executable names; - # this is appropriate when a compiler class is for exactly one - # compiler/OS combination (eg. MSVCCompiler). Other compiler - # classes (UnixCCompiler, in particular) are driven by information - # discovered at run-time, since there are many different ways to do - # basically the same things with Unix C compilers. - - for key in kwargs: - if key not in self.executables: - raise ValueError( - "unknown executable '%s' for class %s" - % (key, self.__class__.__name__) - ) - self.set_executable(key, kwargs[key]) - - def set_executable(self, key, value): - if isinstance(value, str): - setattr(self, key, split_quoted(value)) - else: - setattr(self, key, value) - - def _find_macro(self, name): - i = 0 - for defn in self.macros: - if defn[0] == name: - return i - i += 1 - return None - - def _check_macro_definitions(self, definitions): - """Ensures that every element of 'definitions' is a valid macro - definition, ie. either (name,value) 2-tuple or a (name,) tuple. Do - nothing if all definitions are OK, raise TypeError otherwise. - """ - for defn in definitions: - if not ( - isinstance(defn, tuple) - and ( - len(defn) in (1, 2) - and (isinstance(defn[1], str) or defn[1] is None) - ) - and isinstance(defn[0], str) - ): - raise TypeError( - ("invalid macro definition '%s': " % defn) - + "must be tuple (string,), (string, string), or " - + "(string, None)" - ) - - # -- Bookkeeping methods ------------------------------------------- - - def define_macro(self, name, value=None): - """Define a preprocessor macro for all compilations driven by this - compiler object. The optional parameter 'value' should be a - string; if it is not supplied, then the macro will be defined - without an explicit value and the exact outcome depends on the - compiler used (XXX true? does ANSI say anything about this?) - """ - # Delete from the list of macro definitions/undefinitions if - # already there (so that this one will take precedence). - i = self._find_macro(name) - if i is not None: - del self.macros[i] - - self.macros.append((name, value)) - - def undefine_macro(self, name): - """Undefine a preprocessor macro for all compilations driven by - this compiler object. If the same macro is defined by - 'define_macro()' and undefined by 'undefine_macro()' the last call - takes precedence (including multiple redefinitions or - undefinitions). If the macro is redefined/undefined on a - per-compilation basis (ie. in the call to 'compile()'), then that - takes precedence. - """ - # Delete from the list of macro definitions/undefinitions if - # already there (so that this one will take precedence). - i = self._find_macro(name) - if i is not None: - del self.macros[i] - - undefn = (name,) - self.macros.append(undefn) - - def add_include_dir(self, dir): - """Add 'dir' to the list of directories that will be searched for - header files. The compiler is instructed to search directories in - the order in which they are supplied by successive calls to - 'add_include_dir()'. - """ - self.include_dirs.append(dir) - - def set_include_dirs(self, dirs): - """Set the list of directories that will be searched to 'dirs' (a - list of strings). Overrides any preceding calls to - 'add_include_dir()'; subsequence calls to 'add_include_dir()' add - to the list passed to 'set_include_dirs()'. This does not affect - any list of standard include directories that the compiler may - search by default. - """ - self.include_dirs = dirs[:] - - def add_library(self, libname): - """Add 'libname' to the list of libraries that will be included in - all links driven by this compiler object. Note that 'libname' - should *not* be the name of a file containing a library, but the - name of the library itself: the actual filename will be inferred by - the linker, the compiler, or the compiler class (depending on the - platform). - - The linker will be instructed to link against libraries in the - order they were supplied to 'add_library()' and/or - 'set_libraries()'. It is perfectly valid to duplicate library - names; the linker will be instructed to link against libraries as - many times as they are mentioned. - """ - self.libraries.append(libname) - - def set_libraries(self, libnames): - """Set the list of libraries to be included in all links driven by - this compiler object to 'libnames' (a list of strings). This does - not affect any standard system libraries that the linker may - include by default. - """ - self.libraries = libnames[:] - - def add_library_dir(self, dir): - """Add 'dir' to the list of directories that will be searched for - libraries specified to 'add_library()' and 'set_libraries()'. The - linker will be instructed to search for libraries in the order they - are supplied to 'add_library_dir()' and/or 'set_library_dirs()'. - """ - self.library_dirs.append(dir) - - def set_library_dirs(self, dirs): - """Set the list of library search directories to 'dirs' (a list of - strings). This does not affect any standard library search path - that the linker may search by default. - """ - self.library_dirs = dirs[:] - - def add_runtime_library_dir(self, dir): - """Add 'dir' to the list of directories that will be searched for - shared libraries at runtime. - """ - self.runtime_library_dirs.append(dir) - - def set_runtime_library_dirs(self, dirs): - """Set the list of directories to search for shared libraries at - runtime to 'dirs' (a list of strings). This does not affect any - standard search path that the runtime linker may search by - default. - """ - self.runtime_library_dirs = dirs[:] - - def add_link_object(self, object): - """Add 'object' to the list of object files (or analogues, such as - explicitly named library files or the output of "resource - compilers") to be included in every link driven by this compiler - object. - """ - self.objects.append(object) - - def set_link_objects(self, objects): - """Set the list of object files (or analogues) to be included in - every link to 'objects'. This does not affect any standard object - files that the linker may include by default (such as system - libraries). - """ - self.objects = objects[:] - - # -- Private utility methods -------------------------------------- - # (here for the convenience of subclasses) - - # Helper method to prep compiler in subclass compile() methods - - def _setup_compile(self, outdir, macros, incdirs, sources, depends, extra): - """Process arguments and decide which source files to compile.""" - outdir, macros, incdirs = self._fix_compile_args(outdir, macros, incdirs) - - if extra is None: - extra = [] - - # Get the list of expected output (object) files - objects = self.object_filenames(sources, strip_dir=0, output_dir=outdir) - assert len(objects) == len(sources) - - pp_opts = gen_preprocess_options(macros, incdirs) - - build = {} - for i in range(len(sources)): - src = sources[i] - obj = objects[i] - ext = os.path.splitext(src)[1] - self.mkpath(os.path.dirname(obj)) - build[obj] = (src, ext) - - return macros, objects, extra, pp_opts, build - - def _get_cc_args(self, pp_opts, debug, before): - # works for unixccompiler, cygwinccompiler - cc_args = pp_opts + ['-c'] - if debug: - cc_args[:0] = ['-g'] - if before: - cc_args[:0] = before - return cc_args - - def _fix_compile_args(self, output_dir, macros, include_dirs): - """Typecheck and fix-up some of the arguments to the 'compile()' - method, and return fixed-up values. Specifically: if 'output_dir' - is None, replaces it with 'self.output_dir'; ensures that 'macros' - is a list, and augments it with 'self.macros'; ensures that - 'include_dirs' is a list, and augments it with 'self.include_dirs'. - Guarantees that the returned values are of the correct type, - i.e. for 'output_dir' either string or None, and for 'macros' and - 'include_dirs' either list or None. - """ - if output_dir is None: - output_dir = self.output_dir - elif not isinstance(output_dir, str): - raise TypeError("'output_dir' must be a string or None") - - if macros is None: - macros = self.macros - elif isinstance(macros, list): - macros = macros + (self.macros or []) - else: - raise TypeError("'macros' (if supplied) must be a list of tuples") - - if include_dirs is None: - include_dirs = self.include_dirs - elif isinstance(include_dirs, (list, tuple)): - include_dirs = list(include_dirs) + (self.include_dirs or []) - else: - raise TypeError("'include_dirs' (if supplied) must be a list of strings") - - # add include dirs for class - include_dirs += self.__class__.include_dirs - - return output_dir, macros, include_dirs - - def _prep_compile(self, sources, output_dir, depends=None): - """Decide which source files must be recompiled. - - Determine the list of object files corresponding to 'sources', - and figure out which ones really need to be recompiled. - Return a list of all object files and a dictionary telling - which source files can be skipped. - """ - # Get the list of expected output (object) files - objects = self.object_filenames(sources, output_dir=output_dir) - assert len(objects) == len(sources) - - # Return an empty dict for the "which source files can be skipped" - # return value to preserve API compatibility. - return objects, {} - - def _fix_object_args(self, objects, output_dir): - """Typecheck and fix up some arguments supplied to various methods. - Specifically: ensure that 'objects' is a list; if output_dir is - None, replace with self.output_dir. Return fixed versions of - 'objects' and 'output_dir'. - """ - if not isinstance(objects, (list, tuple)): - raise TypeError("'objects' must be a list or tuple of strings") - objects = list(objects) - - if output_dir is None: - output_dir = self.output_dir - elif not isinstance(output_dir, str): - raise TypeError("'output_dir' must be a string or None") - - return (objects, output_dir) - - def _fix_lib_args(self, libraries, library_dirs, runtime_library_dirs): - """Typecheck and fix up some of the arguments supplied to the - 'link_*' methods. Specifically: ensure that all arguments are - lists, and augment them with their permanent versions - (eg. 'self.libraries' augments 'libraries'). Return a tuple with - fixed versions of all arguments. - """ - if libraries is None: - libraries = self.libraries - elif isinstance(libraries, (list, tuple)): - libraries = list(libraries) + (self.libraries or []) - else: - raise TypeError("'libraries' (if supplied) must be a list of strings") - - if library_dirs is None: - library_dirs = self.library_dirs - elif isinstance(library_dirs, (list, tuple)): - library_dirs = list(library_dirs) + (self.library_dirs or []) - else: - raise TypeError("'library_dirs' (if supplied) must be a list of strings") - - # add library dirs for class - library_dirs += self.__class__.library_dirs - - if runtime_library_dirs is None: - runtime_library_dirs = self.runtime_library_dirs - elif isinstance(runtime_library_dirs, (list, tuple)): - runtime_library_dirs = list(runtime_library_dirs) + ( - self.runtime_library_dirs or [] - ) - else: - raise TypeError( - "'runtime_library_dirs' (if supplied) " "must be a list of strings" - ) - - return (libraries, library_dirs, runtime_library_dirs) - - def _need_link(self, objects, output_file): - """Return true if we need to relink the files listed in 'objects' - to recreate 'output_file'. - """ - if self.force: - return True - else: - if self.dry_run: - newer = newer_group(objects, output_file, missing='newer') - else: - newer = newer_group(objects, output_file) - return newer - - def detect_language(self, sources): - """Detect the language of a given file, or list of files. Uses - language_map, and language_order to do the job. - """ - if not isinstance(sources, list): - sources = [sources] - lang = None - index = len(self.language_order) - for source in sources: - base, ext = os.path.splitext(source) - extlang = self.language_map.get(ext) - try: - extindex = self.language_order.index(extlang) - if extindex < index: - lang = extlang - index = extindex - except ValueError: - pass - return lang - - # -- Worker methods ------------------------------------------------ - # (must be implemented by subclasses) - - def preprocess( - self, - source, - output_file=None, - macros=None, - include_dirs=None, - extra_preargs=None, - extra_postargs=None, - ): - """Preprocess a single C/C++ source file, named in 'source'. - Output will be written to file named 'output_file', or stdout if - 'output_file' not supplied. 'macros' is a list of macro - definitions as for 'compile()', which will augment the macros set - with 'define_macro()' and 'undefine_macro()'. 'include_dirs' is a - list of directory names that will be added to the default list. - - Raises PreprocessError on failure. - """ - pass - - def compile( - self, - sources, - output_dir=None, - macros=None, - include_dirs=None, - debug=0, - extra_preargs=None, - extra_postargs=None, - depends=None, - ): - """Compile one or more source files. - - 'sources' must be a list of filenames, most likely C/C++ - files, but in reality anything that can be handled by a - particular compiler and compiler class (eg. MSVCCompiler can - handle resource files in 'sources'). Return a list of object - filenames, one per source filename in 'sources'. Depending on - the implementation, not all source files will necessarily be - compiled, but all corresponding object filenames will be - returned. - - If 'output_dir' is given, object files will be put under it, while - retaining their original path component. That is, "foo/bar.c" - normally compiles to "foo/bar.o" (for a Unix implementation); if - 'output_dir' is "build", then it would compile to - "build/foo/bar.o". - - 'macros', if given, must be a list of macro definitions. A macro - definition is either a (name, value) 2-tuple or a (name,) 1-tuple. - The former defines a macro; if the value is None, the macro is - defined without an explicit value. The 1-tuple case undefines a - macro. Later definitions/redefinitions/ undefinitions take - precedence. - - 'include_dirs', if given, must be a list of strings, the - directories to add to the default include file search path for this - compilation only. - - 'debug' is a boolean; if true, the compiler will be instructed to - output debug symbols in (or alongside) the object file(s). - - 'extra_preargs' and 'extra_postargs' are implementation- dependent. - On platforms that have the notion of a command-line (e.g. Unix, - DOS/Windows), they are most likely lists of strings: extra - command-line arguments to prepend/append to the compiler command - line. On other platforms, consult the implementation class - documentation. In any event, they are intended as an escape hatch - for those occasions when the abstract compiler framework doesn't - cut the mustard. - - 'depends', if given, is a list of filenames that all targets - depend on. If a source file is older than any file in - depends, then the source file will be recompiled. This - supports dependency tracking, but only at a coarse - granularity. - - Raises CompileError on failure. - """ - # A concrete compiler class can either override this method - # entirely or implement _compile(). - macros, objects, extra_postargs, pp_opts, build = self._setup_compile( - output_dir, macros, include_dirs, sources, depends, extra_postargs - ) - cc_args = self._get_cc_args(pp_opts, debug, extra_preargs) - - for obj in objects: - try: - src, ext = build[obj] - except KeyError: - continue - self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts) - - # Return *all* object filenames, not just the ones we just built. - return objects - - def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts): - """Compile 'src' to product 'obj'.""" - # A concrete compiler class that does not override compile() - # should implement _compile(). - pass - - def create_static_lib( - self, objects, output_libname, output_dir=None, debug=0, target_lang=None - ): - """Link a bunch of stuff together to create a static library file. - The "bunch of stuff" consists of the list of object files supplied - as 'objects', the extra object files supplied to - 'add_link_object()' and/or 'set_link_objects()', the libraries - supplied to 'add_library()' and/or 'set_libraries()', and the - libraries supplied as 'libraries' (if any). - - 'output_libname' should be a library name, not a filename; the - filename will be inferred from the library name. 'output_dir' is - the directory where the library file will be put. - - 'debug' is a boolean; if true, debugging information will be - included in the library (note that on most platforms, it is the - compile step where this matters: the 'debug' flag is included here - just for consistency). - - 'target_lang' is the target language for which the given objects - are being compiled. This allows specific linkage time treatment of - certain languages. - - Raises LibError on failure. - """ - pass - - # values for target_desc parameter in link() - SHARED_OBJECT = "shared_object" - SHARED_LIBRARY = "shared_library" - EXECUTABLE = "executable" - - def link( - self, - target_desc, - objects, - output_filename, - output_dir=None, - libraries=None, - library_dirs=None, - runtime_library_dirs=None, - export_symbols=None, - debug=0, - extra_preargs=None, - extra_postargs=None, - build_temp=None, - target_lang=None, - ): - """Link a bunch of stuff together to create an executable or - shared library file. - - The "bunch of stuff" consists of the list of object files supplied - as 'objects'. 'output_filename' should be a filename. If - 'output_dir' is supplied, 'output_filename' is relative to it - (i.e. 'output_filename' can provide directory components if - needed). - - 'libraries' is a list of libraries to link against. These are - library names, not filenames, since they're translated into - filenames in a platform-specific way (eg. "foo" becomes "libfoo.a" - on Unix and "foo.lib" on DOS/Windows). However, they can include a - directory component, which means the linker will look in that - specific directory rather than searching all the normal locations. - - 'library_dirs', if supplied, should be a list of directories to - search for libraries that were specified as bare library names - (ie. no directory component). These are on top of the system - default and those supplied to 'add_library_dir()' and/or - 'set_library_dirs()'. 'runtime_library_dirs' is a list of - directories that will be embedded into the shared library and used - to search for other shared libraries that *it* depends on at - run-time. (This may only be relevant on Unix.) - - 'export_symbols' is a list of symbols that the shared library will - export. (This appears to be relevant only on Windows.) - - 'debug' is as for 'compile()' and 'create_static_lib()', with the - slight distinction that it actually matters on most platforms (as - opposed to 'create_static_lib()', which includes a 'debug' flag - mostly for form's sake). - - 'extra_preargs' and 'extra_postargs' are as for 'compile()' (except - of course that they supply command-line arguments for the - particular linker being used). - - 'target_lang' is the target language for which the given objects - are being compiled. This allows specific linkage time treatment of - certain languages. - - Raises LinkError on failure. - """ - raise NotImplementedError - - # Old 'link_*()' methods, rewritten to use the new 'link()' method. - - def link_shared_lib( - self, - objects, - output_libname, - output_dir=None, - libraries=None, - library_dirs=None, - runtime_library_dirs=None, - export_symbols=None, - debug=0, - extra_preargs=None, - extra_postargs=None, - build_temp=None, - target_lang=None, - ): - self.link( - CCompiler.SHARED_LIBRARY, - objects, - self.library_filename(output_libname, lib_type='shared'), - output_dir, - libraries, - library_dirs, - runtime_library_dirs, - export_symbols, - debug, - extra_preargs, - extra_postargs, - build_temp, - target_lang, - ) - - def link_shared_object( - self, - objects, - output_filename, - output_dir=None, - libraries=None, - library_dirs=None, - runtime_library_dirs=None, - export_symbols=None, - debug=0, - extra_preargs=None, - extra_postargs=None, - build_temp=None, - target_lang=None, - ): - self.link( - CCompiler.SHARED_OBJECT, - objects, - output_filename, - output_dir, - libraries, - library_dirs, - runtime_library_dirs, - export_symbols, - debug, - extra_preargs, - extra_postargs, - build_temp, - target_lang, - ) - - def link_executable( - self, - objects, - output_progname, - output_dir=None, - libraries=None, - library_dirs=None, - runtime_library_dirs=None, - debug=0, - extra_preargs=None, - extra_postargs=None, - target_lang=None, - ): - self.link( - CCompiler.EXECUTABLE, - objects, - self.executable_filename(output_progname), - output_dir, - libraries, - library_dirs, - runtime_library_dirs, - None, - debug, - extra_preargs, - extra_postargs, - None, - target_lang, - ) - - # -- Miscellaneous methods ----------------------------------------- - # These are all used by the 'gen_lib_options() function; there is - # no appropriate default implementation so subclasses should - # implement all of these. - - def library_dir_option(self, dir): - """Return the compiler option to add 'dir' to the list of - directories searched for libraries. - """ - raise NotImplementedError - - def runtime_library_dir_option(self, dir): - """Return the compiler option to add 'dir' to the list of - directories searched for runtime libraries. - """ - raise NotImplementedError - - def library_option(self, lib): - """Return the compiler option to add 'lib' to the list of libraries - linked into the shared library or executable. - """ - raise NotImplementedError - - def has_function( # noqa: C901 - self, - funcname, - includes=None, - include_dirs=None, - libraries=None, - library_dirs=None, - ): - """Return a boolean indicating whether funcname is supported on - the current platform. The optional arguments can be used to - augment the compilation environment. - """ - # this can't be included at module scope because it tries to - # import math which might not be available at that point - maybe - # the necessary logic should just be inlined? - import tempfile - - if includes is None: - includes = [] - if include_dirs is None: - include_dirs = [] - if libraries is None: - libraries = [] - if library_dirs is None: - library_dirs = [] - fd, fname = tempfile.mkstemp(".c", funcname, text=True) - f = os.fdopen(fd, "w") - try: - for incl in includes: - f.write("""#include "%s"\n""" % incl) - f.write( - """\ -int main (int argc, char **argv) { - %s(); - return 0; -} -""" - % funcname - ) - finally: - f.close() - try: - objects = self.compile([fname], include_dirs=include_dirs) - except CompileError: - return False - finally: - os.remove(fname) - - try: - self.link_executable( - objects, "a.out", libraries=libraries, library_dirs=library_dirs - ) - except (LinkError, TypeError): - return False - else: - os.remove(os.path.join(self.output_dir or '', "a.out")) - finally: - for fn in objects: - os.remove(fn) - return True - - def find_library_file(self, dirs, lib, debug=0): - """Search the specified list of directories for a static or shared - library file 'lib' and return the full path to that file. If - 'debug' true, look for a debugging version (if that makes sense on - the current platform). Return None if 'lib' wasn't found in any of - the specified directories. - """ - raise NotImplementedError - - # -- Filename generation methods ----------------------------------- - - # The default implementation of the filename generating methods are - # prejudiced towards the Unix/DOS/Windows view of the world: - # * object files are named by replacing the source file extension - # (eg. .c/.cpp -> .o/.obj) - # * library files (shared or static) are named by plugging the - # library name and extension into a format string, eg. - # "lib%s.%s" % (lib_name, ".a") for Unix static libraries - # * executables are named by appending an extension (possibly - # empty) to the program name: eg. progname + ".exe" for - # Windows - # - # To reduce redundant code, these methods expect to find - # several attributes in the current object (presumably defined - # as class attributes): - # * src_extensions - - # list of C/C++ source file extensions, eg. ['.c', '.cpp'] - # * obj_extension - - # object file extension, eg. '.o' or '.obj' - # * static_lib_extension - - # extension for static library files, eg. '.a' or '.lib' - # * shared_lib_extension - - # extension for shared library/object files, eg. '.so', '.dll' - # * static_lib_format - - # format string for generating static library filenames, - # eg. 'lib%s.%s' or '%s.%s' - # * shared_lib_format - # format string for generating shared library filenames - # (probably same as static_lib_format, since the extension - # is one of the intended parameters to the format string) - # * exe_extension - - # extension for executable files, eg. '' or '.exe' - - def object_filenames(self, source_filenames, strip_dir=0, output_dir=''): - if output_dir is None: - output_dir = '' - return list( - self._make_out_path(output_dir, strip_dir, src_name) - for src_name in source_filenames - ) - - @property - def out_extensions(self): - return dict.fromkeys(self.src_extensions, self.obj_extension) - - def _make_out_path(self, output_dir, strip_dir, src_name): - base, ext = os.path.splitext(src_name) - base = self._make_relative(base) - try: - new_ext = self.out_extensions[ext] - except LookupError: - raise UnknownFileError( - "unknown file type '{}' (from '{}')".format(ext, src_name) - ) - if strip_dir: - base = os.path.basename(base) - return os.path.join(output_dir, base + new_ext) - - @staticmethod - def _make_relative(base): - """ - In order to ensure that a filename always honors the - indicated output_dir, make sure it's relative. - Ref python/cpython#37775. - """ - # Chop off the drive - no_drive = os.path.splitdrive(base)[1] - # If abs, chop off leading / - return no_drive[os.path.isabs(no_drive) :] - - def shared_object_filename(self, basename, strip_dir=0, output_dir=''): - assert output_dir is not None - if strip_dir: - basename = os.path.basename(basename) - return os.path.join(output_dir, basename + self.shared_lib_extension) - - def executable_filename(self, basename, strip_dir=0, output_dir=''): - assert output_dir is not None - if strip_dir: - basename = os.path.basename(basename) - return os.path.join(output_dir, basename + (self.exe_extension or '')) - - def library_filename( - self, libname, lib_type='static', strip_dir=0, output_dir='' # or 'shared' - ): - assert output_dir is not None - expected = '"static", "shared", "dylib", "xcode_stub"' - if lib_type not in eval(expected): - raise ValueError(f"'lib_type' must be {expected}") - fmt = getattr(self, lib_type + "_lib_format") - ext = getattr(self, lib_type + "_lib_extension") - - dir, base = os.path.split(libname) - filename = fmt % (base, ext) - if strip_dir: - dir = '' - - return os.path.join(output_dir, dir, filename) - - # -- Utility methods ----------------------------------------------- - - def announce(self, msg, level=1): - log.debug(msg) - - def debug_print(self, msg): - from distutils.debug import DEBUG - - if DEBUG: - print(msg) - - def warn(self, msg): - sys.stderr.write("warning: %s\n" % msg) - - def execute(self, func, args, msg=None, level=1): - execute(func, args, msg, self.dry_run) - - def spawn(self, cmd, **kwargs): - spawn(cmd, dry_run=self.dry_run, **kwargs) - - def move_file(self, src, dst): - return move_file(src, dst, dry_run=self.dry_run) - - def mkpath(self, name, mode=0o777): - mkpath(name, mode, dry_run=self.dry_run) - - -# Map a sys.platform/os.name ('posix', 'nt') to the default compiler -# type for that platform. Keys are interpreted as re match -# patterns. Order is important; platform mappings are preferred over -# OS names. -_default_compilers = ( - # Platform string mappings - # on a cygwin built python we can use gcc like an ordinary UNIXish - # compiler - ('cygwin.*', 'unix'), - # OS name mappings - ('posix', 'unix'), - ('nt', 'msvc'), -) - - -def get_default_compiler(osname=None, platform=None): - """Determine the default compiler to use for the given platform. - - osname should be one of the standard Python OS names (i.e. the - ones returned by os.name) and platform the common value - returned by sys.platform for the platform in question. - - The default values are os.name and sys.platform in case the - parameters are not given. - """ - if osname is None: - osname = os.name - if platform is None: - platform = sys.platform - for pattern, compiler in _default_compilers: - if ( - re.match(pattern, platform) is not None - or re.match(pattern, osname) is not None - ): - return compiler - # Default to Unix compiler - return 'unix' - - -# Map compiler types to (module_name, class_name) pairs -- ie. where to -# find the code that implements an interface to this compiler. (The module -# is assumed to be in the 'distutils' package.) -compiler_class = { - 'unix': ('unixccompiler', 'UnixCCompiler', "standard UNIX-style compiler"), - 'msvc': ('_msvccompiler', 'MSVCCompiler', "Microsoft Visual C++"), - 'cygwin': ( - 'cygwinccompiler', - 'CygwinCCompiler', - "Cygwin port of GNU C Compiler for Win32", - ), - 'mingw32': ( - 'cygwinccompiler', - 'Mingw32CCompiler', - "Mingw32 port of GNU C Compiler for Win32", - ), - 'bcpp': ('bcppcompiler', 'BCPPCompiler', "Borland C++ Compiler"), -} - - -def show_compilers(): - """Print list of available compilers (used by the "--help-compiler" - options to "build", "build_ext", "build_clib"). - """ - # XXX this "knows" that the compiler option it's describing is - # "--compiler", which just happens to be the case for the three - # commands that use it. - from distutils.fancy_getopt import FancyGetopt - - compilers = [] - for compiler in compiler_class.keys(): - compilers.append(("compiler=" + compiler, None, compiler_class[compiler][2])) - compilers.sort() - pretty_printer = FancyGetopt(compilers) - pretty_printer.print_help("List of available compilers:") - - -def new_compiler(plat=None, compiler=None, verbose=0, dry_run=0, force=0): - """Generate an instance of some CCompiler subclass for the supplied - platform/compiler combination. 'plat' defaults to 'os.name' - (eg. 'posix', 'nt'), and 'compiler' defaults to the default compiler - for that platform. Currently only 'posix' and 'nt' are supported, and - the default compilers are "traditional Unix interface" (UnixCCompiler - class) and Visual C++ (MSVCCompiler class). Note that it's perfectly - possible to ask for a Unix compiler object under Windows, and a - Microsoft compiler object under Unix -- if you supply a value for - 'compiler', 'plat' is ignored. - """ - if plat is None: - plat = os.name - - try: - if compiler is None: - compiler = get_default_compiler(plat) - - (module_name, class_name, long_description) = compiler_class[compiler] - except KeyError: - msg = "don't know how to compile C/C++ code on platform '%s'" % plat - if compiler is not None: - msg = msg + " with '%s' compiler" % compiler - raise DistutilsPlatformError(msg) - - try: - module_name = "distutils." + module_name - __import__(module_name) - module = sys.modules[module_name] - klass = vars(module)[class_name] - except ImportError: - raise DistutilsModuleError( - "can't compile C/C++ code: unable to load module '%s'" % module_name - ) - except KeyError: - raise DistutilsModuleError( - "can't compile C/C++ code: unable to find class '%s' " - "in module '%s'" % (class_name, module_name) - ) - - # XXX The None is necessary to preserve backwards compatibility - # with classes that expect verbose to be the first positional - # argument. - return klass(None, dry_run, force) - - -def gen_preprocess_options(macros, include_dirs): - """Generate C pre-processor options (-D, -U, -I) as used by at least - two types of compilers: the typical Unix compiler and Visual C++. - 'macros' is the usual thing, a list of 1- or 2-tuples, where (name,) - means undefine (-U) macro 'name', and (name,value) means define (-D) - macro 'name' to 'value'. 'include_dirs' is just a list of directory - names to be added to the header file search path (-I). Returns a list - of command-line options suitable for either Unix compilers or Visual - C++. - """ - # XXX it would be nice (mainly aesthetic, and so we don't generate - # stupid-looking command lines) to go over 'macros' and eliminate - # redundant definitions/undefinitions (ie. ensure that only the - # latest mention of a particular macro winds up on the command - # line). I don't think it's essential, though, since most (all?) - # Unix C compilers only pay attention to the latest -D or -U - # mention of a macro on their command line. Similar situation for - # 'include_dirs'. I'm punting on both for now. Anyways, weeding out - # redundancies like this should probably be the province of - # CCompiler, since the data structures used are inherited from it - # and therefore common to all CCompiler classes. - pp_opts = [] - for macro in macros: - if not (isinstance(macro, tuple) and 1 <= len(macro) <= 2): - raise TypeError( - "bad macro definition '%s': " - "each element of 'macros' list must be a 1- or 2-tuple" % macro - ) - - if len(macro) == 1: # undefine this macro - pp_opts.append("-U%s" % macro[0]) - elif len(macro) == 2: - if macro[1] is None: # define with no explicit value - pp_opts.append("-D%s" % macro[0]) - else: - # XXX *don't* need to be clever about quoting the - # macro value here, because we're going to avoid the - # shell at all costs when we spawn the command! - pp_opts.append("-D%s=%s" % macro) - - for dir in include_dirs: - pp_opts.append("-I%s" % dir) - return pp_opts - - -def gen_lib_options(compiler, library_dirs, runtime_library_dirs, libraries): - """Generate linker options for searching library directories and - linking with specific libraries. 'libraries' and 'library_dirs' are, - respectively, lists of library names (not filenames!) and search - directories. Returns a list of command-line options suitable for use - with some compiler (depending on the two format strings passed in). - """ - lib_opts = [] - - for dir in library_dirs: - lib_opts.append(compiler.library_dir_option(dir)) - - for dir in runtime_library_dirs: - opt = compiler.runtime_library_dir_option(dir) - if isinstance(opt, list): - lib_opts = lib_opts + opt - else: - lib_opts.append(opt) - - # XXX it's important that we *not* remove redundant library mentions! - # sometimes you really do have to say "-lfoo -lbar -lfoo" in order to - # resolve all symbols. I just hope we never have to say "-lfoo obj.o - # -lbar" to get things to work -- that's certainly a possibility, but a - # pretty nasty way to arrange your C code. - - for lib in libraries: - (lib_dir, lib_name) = os.path.split(lib) - if lib_dir: - lib_file = compiler.find_library_file([lib_dir], lib_name) - if lib_file: - lib_opts.append(lib_file) - else: - compiler.warn( - "no library file corresponding to " "'%s' found (skipping)" % lib - ) - else: - lib_opts.append(compiler.library_option(lib)) - return lib_opts diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/cmd.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/cmd.py deleted file mode 100755 index 918db85..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/cmd.py +++ /dev/null @@ -1,435 +0,0 @@ -"""distutils.cmd - -Provides the Command class, the base class for the command classes -in the distutils.command package. -""" - -import sys -import os -import re -import logging - -from .errors import DistutilsOptionError -from . import util, dir_util, file_util, archive_util, dep_util -from ._log import log - - -class Command: - """Abstract base class for defining command classes, the "worker bees" - of the Distutils. A useful analogy for command classes is to think of - them as subroutines with local variables called "options". The options - are "declared" in 'initialize_options()' and "defined" (given their - final values, aka "finalized") in 'finalize_options()', both of which - must be defined by every command class. The distinction between the - two is necessary because option values might come from the outside - world (command line, config file, ...), and any options dependent on - other options must be computed *after* these outside influences have - been processed -- hence 'finalize_options()'. The "body" of the - subroutine, where it does all its work based on the values of its - options, is the 'run()' method, which must also be implemented by every - command class. - """ - - # 'sub_commands' formalizes the notion of a "family" of commands, - # eg. "install" as the parent with sub-commands "install_lib", - # "install_headers", etc. The parent of a family of commands - # defines 'sub_commands' as a class attribute; it's a list of - # (command_name : string, predicate : unbound_method | string | None) - # tuples, where 'predicate' is a method of the parent command that - # determines whether the corresponding command is applicable in the - # current situation. (Eg. we "install_headers" is only applicable if - # we have any C header files to install.) If 'predicate' is None, - # that command is always applicable. - # - # 'sub_commands' is usually defined at the *end* of a class, because - # predicates can be unbound methods, so they must already have been - # defined. The canonical example is the "install" command. - sub_commands = [] - - # -- Creation/initialization methods ------------------------------- - - def __init__(self, dist): - """Create and initialize a new Command object. Most importantly, - invokes the 'initialize_options()' method, which is the real - initializer and depends on the actual command being - instantiated. - """ - # late import because of mutual dependence between these classes - from distutils.dist import Distribution - - if not isinstance(dist, Distribution): - raise TypeError("dist must be a Distribution instance") - if self.__class__ is Command: - raise RuntimeError("Command is an abstract class") - - self.distribution = dist - self.initialize_options() - - # Per-command versions of the global flags, so that the user can - # customize Distutils' behaviour command-by-command and let some - # commands fall back on the Distribution's behaviour. None means - # "not defined, check self.distribution's copy", while 0 or 1 mean - # false and true (duh). Note that this means figuring out the real - # value of each flag is a touch complicated -- hence "self._dry_run" - # will be handled by __getattr__, below. - # XXX This needs to be fixed. - self._dry_run = None - - # verbose is largely ignored, but needs to be set for - # backwards compatibility (I think)? - self.verbose = dist.verbose - - # Some commands define a 'self.force' option to ignore file - # timestamps, but methods defined *here* assume that - # 'self.force' exists for all commands. So define it here - # just to be safe. - self.force = None - - # The 'help' flag is just used for command-line parsing, so - # none of that complicated bureaucracy is needed. - self.help = 0 - - # 'finalized' records whether or not 'finalize_options()' has been - # called. 'finalize_options()' itself should not pay attention to - # this flag: it is the business of 'ensure_finalized()', which - # always calls 'finalize_options()', to respect/update it. - self.finalized = 0 - - # XXX A more explicit way to customize dry_run would be better. - def __getattr__(self, attr): - if attr == 'dry_run': - myval = getattr(self, "_" + attr) - if myval is None: - return getattr(self.distribution, attr) - else: - return myval - else: - raise AttributeError(attr) - - def ensure_finalized(self): - if not self.finalized: - self.finalize_options() - self.finalized = 1 - - # Subclasses must define: - # initialize_options() - # provide default values for all options; may be customized by - # setup script, by options from config file(s), or by command-line - # options - # finalize_options() - # decide on the final values for all options; this is called - # after all possible intervention from the outside world - # (command-line, option file, etc.) has been processed - # run() - # run the command: do whatever it is we're here to do, - # controlled by the command's various option values - - def initialize_options(self): - """Set default values for all the options that this command - supports. Note that these defaults may be overridden by other - commands, by the setup script, by config files, or by the - command-line. Thus, this is not the place to code dependencies - between options; generally, 'initialize_options()' implementations - are just a bunch of "self.foo = None" assignments. - - This method must be implemented by all command classes. - """ - raise RuntimeError( - "abstract method -- subclass %s must override" % self.__class__ - ) - - def finalize_options(self): - """Set final values for all the options that this command supports. - This is always called as late as possible, ie. after any option - assignments from the command-line or from other commands have been - done. Thus, this is the place to code option dependencies: if - 'foo' depends on 'bar', then it is safe to set 'foo' from 'bar' as - long as 'foo' still has the same value it was assigned in - 'initialize_options()'. - - This method must be implemented by all command classes. - """ - raise RuntimeError( - "abstract method -- subclass %s must override" % self.__class__ - ) - - def dump_options(self, header=None, indent=""): - from distutils.fancy_getopt import longopt_xlate - - if header is None: - header = "command options for '%s':" % self.get_command_name() - self.announce(indent + header, level=logging.INFO) - indent = indent + " " - for (option, _, _) in self.user_options: - option = option.translate(longopt_xlate) - if option[-1] == "=": - option = option[:-1] - value = getattr(self, option) - self.announce(indent + "{} = {}".format(option, value), level=logging.INFO) - - def run(self): - """A command's raison d'etre: carry out the action it exists to - perform, controlled by the options initialized in - 'initialize_options()', customized by other commands, the setup - script, the command-line, and config files, and finalized in - 'finalize_options()'. All terminal output and filesystem - interaction should be done by 'run()'. - - This method must be implemented by all command classes. - """ - raise RuntimeError( - "abstract method -- subclass %s must override" % self.__class__ - ) - - def announce(self, msg, level=logging.DEBUG): - log.log(level, msg) - - def debug_print(self, msg): - """Print 'msg' to stdout if the global DEBUG (taken from the - DISTUTILS_DEBUG environment variable) flag is true. - """ - from distutils.debug import DEBUG - - if DEBUG: - print(msg) - sys.stdout.flush() - - # -- Option validation methods ------------------------------------- - # (these are very handy in writing the 'finalize_options()' method) - # - # NB. the general philosophy here is to ensure that a particular option - # value meets certain type and value constraints. If not, we try to - # force it into conformance (eg. if we expect a list but have a string, - # split the string on comma and/or whitespace). If we can't force the - # option into conformance, raise DistutilsOptionError. Thus, command - # classes need do nothing more than (eg.) - # self.ensure_string_list('foo') - # and they can be guaranteed that thereafter, self.foo will be - # a list of strings. - - def _ensure_stringlike(self, option, what, default=None): - val = getattr(self, option) - if val is None: - setattr(self, option, default) - return default - elif not isinstance(val, str): - raise DistutilsOptionError( - "'{}' must be a {} (got `{}`)".format(option, what, val) - ) - return val - - def ensure_string(self, option, default=None): - """Ensure that 'option' is a string; if not defined, set it to - 'default'. - """ - self._ensure_stringlike(option, "string", default) - - def ensure_string_list(self, option): - r"""Ensure that 'option' is a list of strings. If 'option' is - currently a string, we split it either on /,\s*/ or /\s+/, so - "foo bar baz", "foo,bar,baz", and "foo, bar baz" all become - ["foo", "bar", "baz"]. - """ - val = getattr(self, option) - if val is None: - return - elif isinstance(val, str): - setattr(self, option, re.split(r',\s*|\s+', val)) - else: - if isinstance(val, list): - ok = all(isinstance(v, str) for v in val) - else: - ok = False - if not ok: - raise DistutilsOptionError( - "'{}' must be a list of strings (got {!r})".format(option, val) - ) - - def _ensure_tested_string(self, option, tester, what, error_fmt, default=None): - val = self._ensure_stringlike(option, what, default) - if val is not None and not tester(val): - raise DistutilsOptionError( - ("error in '%s' option: " + error_fmt) % (option, val) - ) - - def ensure_filename(self, option): - """Ensure that 'option' is the name of an existing file.""" - self._ensure_tested_string( - option, os.path.isfile, "filename", "'%s' does not exist or is not a file" - ) - - def ensure_dirname(self, option): - self._ensure_tested_string( - option, - os.path.isdir, - "directory name", - "'%s' does not exist or is not a directory", - ) - - # -- Convenience methods for commands ------------------------------ - - def get_command_name(self): - if hasattr(self, 'command_name'): - return self.command_name - else: - return self.__class__.__name__ - - def set_undefined_options(self, src_cmd, *option_pairs): - """Set the values of any "undefined" options from corresponding - option values in some other command object. "Undefined" here means - "is None", which is the convention used to indicate that an option - has not been changed between 'initialize_options()' and - 'finalize_options()'. Usually called from 'finalize_options()' for - options that depend on some other command rather than another - option of the same command. 'src_cmd' is the other command from - which option values will be taken (a command object will be created - for it if necessary); the remaining arguments are - '(src_option,dst_option)' tuples which mean "take the value of - 'src_option' in the 'src_cmd' command object, and copy it to - 'dst_option' in the current command object". - """ - # Option_pairs: list of (src_option, dst_option) tuples - src_cmd_obj = self.distribution.get_command_obj(src_cmd) - src_cmd_obj.ensure_finalized() - for (src_option, dst_option) in option_pairs: - if getattr(self, dst_option) is None: - setattr(self, dst_option, getattr(src_cmd_obj, src_option)) - - def get_finalized_command(self, command, create=1): - """Wrapper around Distribution's 'get_command_obj()' method: find - (create if necessary and 'create' is true) the command object for - 'command', call its 'ensure_finalized()' method, and return the - finalized command object. - """ - cmd_obj = self.distribution.get_command_obj(command, create) - cmd_obj.ensure_finalized() - return cmd_obj - - # XXX rename to 'get_reinitialized_command()'? (should do the - # same in dist.py, if so) - def reinitialize_command(self, command, reinit_subcommands=0): - return self.distribution.reinitialize_command(command, reinit_subcommands) - - def run_command(self, command): - """Run some other command: uses the 'run_command()' method of - Distribution, which creates and finalizes the command object if - necessary and then invokes its 'run()' method. - """ - self.distribution.run_command(command) - - def get_sub_commands(self): - """Determine the sub-commands that are relevant in the current - distribution (ie., that need to be run). This is based on the - 'sub_commands' class attribute: each tuple in that list may include - a method that we call to determine if the subcommand needs to be - run for the current distribution. Return a list of command names. - """ - commands = [] - for (cmd_name, method) in self.sub_commands: - if method is None or method(self): - commands.append(cmd_name) - return commands - - # -- External world manipulation ----------------------------------- - - def warn(self, msg): - log.warning("warning: %s: %s\n", self.get_command_name(), msg) - - def execute(self, func, args, msg=None, level=1): - util.execute(func, args, msg, dry_run=self.dry_run) - - def mkpath(self, name, mode=0o777): - dir_util.mkpath(name, mode, dry_run=self.dry_run) - - def copy_file( - self, infile, outfile, preserve_mode=1, preserve_times=1, link=None, level=1 - ): - """Copy a file respecting verbose, dry-run and force flags. (The - former two default to whatever is in the Distribution object, and - the latter defaults to false for commands that don't define it.)""" - return file_util.copy_file( - infile, - outfile, - preserve_mode, - preserve_times, - not self.force, - link, - dry_run=self.dry_run, - ) - - def copy_tree( - self, - infile, - outfile, - preserve_mode=1, - preserve_times=1, - preserve_symlinks=0, - level=1, - ): - """Copy an entire directory tree respecting verbose, dry-run, - and force flags. - """ - return dir_util.copy_tree( - infile, - outfile, - preserve_mode, - preserve_times, - preserve_symlinks, - not self.force, - dry_run=self.dry_run, - ) - - def move_file(self, src, dst, level=1): - """Move a file respecting dry-run flag.""" - return file_util.move_file(src, dst, dry_run=self.dry_run) - - def spawn(self, cmd, search_path=1, level=1): - """Spawn an external command respecting dry-run flag.""" - from distutils.spawn import spawn - - spawn(cmd, search_path, dry_run=self.dry_run) - - def make_archive( - self, base_name, format, root_dir=None, base_dir=None, owner=None, group=None - ): - return archive_util.make_archive( - base_name, - format, - root_dir, - base_dir, - dry_run=self.dry_run, - owner=owner, - group=group, - ) - - def make_file( - self, infiles, outfile, func, args, exec_msg=None, skip_msg=None, level=1 - ): - """Special case of 'execute()' for operations that process one or - more input files and generate one output file. Works just like - 'execute()', except the operation is skipped and a different - message printed if 'outfile' already exists and is newer than all - files listed in 'infiles'. If the command defined 'self.force', - and it is true, then the command is unconditionally run -- does no - timestamp checks. - """ - if skip_msg is None: - skip_msg = "skipping %s (inputs unchanged)" % outfile - - # Allow 'infiles' to be a single string - if isinstance(infiles, str): - infiles = (infiles,) - elif not isinstance(infiles, (list, tuple)): - raise TypeError("'infiles' must be a string, or a list or tuple of strings") - - if exec_msg is None: - exec_msg = "generating {} from {}".format(outfile, ', '.join(infiles)) - - # If 'outfile' must be regenerated (either because it doesn't - # exist, is out-of-date, or the 'force' flag is true) then - # perform the action that presumably regenerates it - if self.force or dep_util.newer_group(infiles, outfile): - self.execute(func, args, exec_msg, level) - # Otherwise, print the "skip" message - else: - log.debug(skip_msg) diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/__init__.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/__init__.py deleted file mode 100755 index 028dcfa..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/__init__.py +++ /dev/null @@ -1,25 +0,0 @@ -"""distutils.command - -Package containing implementation of all the standard Distutils -commands.""" - -__all__ = [ # noqa: F822 - 'build', - 'build_py', - 'build_ext', - 'build_clib', - 'build_scripts', - 'clean', - 'install', - 'install_lib', - 'install_headers', - 'install_scripts', - 'install_data', - 'sdist', - 'register', - 'bdist', - 'bdist_dumb', - 'bdist_rpm', - 'check', - 'upload', -] diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/__init__.cpython-311.pyc deleted file mode 100755 index 1fc7410cb7e3ca26a4d6d707fda9de9c1386ca0b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 544 zcmYLGKT88K6wh6$t*1rMLELU|>0pC&6(=VL5!{Lp(j?wR^N%D~tdk!?5FA~^#ZTju z)h|%!=48_L@CDxcy~q3W%X=S#K>?zCzr5XlWdQsnrn zyl5L0n?`Ol+z;Jp!vzifl|g16w%3R~`cSMP5qug3YwU>S#=FoZf?*YUT*dxEgq;mQ zDR-}RYKAGZ?my6$@3t8fdmOqheKPbdtD|sp&0|-*PXaE2J diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/_framework_compat.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/_framework_compat.cpython-311.pyc deleted file mode 100755 index 110bd99242b1c341ca3dc0984d35c46523219d42..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2785 zcmb7FO=ufO6rNqJepj~SKZV9_v!tet3YMDMgt!SUI5DjQmQC%XRELPw&e~pkwY$u$ z{3BbSLkji6$|r_zIO3QjIL_08(Xl1)Q1(!7~@JMX=D z-wF-bUEci=x?@Yws2!|v=5WV2%|K@9OiW{&AB6==H1bg_PC>v7TnRB z_VP&eEQ7v!+kxRlbAhnu4(jBj{jfj4Iu@`O`>-Dea1e*ExEtOHfGqTS+wI!nU=6+A z(!qCH>ON&Dgd=xQTEzSuibo5VLKCvGvL+KODQ3=+Z7r+mn!O<{m_%AKb842TYf?6^ z>6l8UA?0LcW-bvrWX4lU;|%T~0QEpW8iun0R-E1Tb-8t3gEGf_@0KTwOnyrUBS7C@xE+$9%^3QIq#ANoSFwxx z?1sGrSdS*gr3E7A)HRc=oD7C5sje%kWrHlu6V=izNj9*wsv4^a_j8;-WF8!{Bgc8d zB6P?O?f9@v)-=QMT~l>kCXQ$kb6HjFtV~s>XEHT+^SjB}soBiT?EKVBYA!B19=buD z@Ty9vW*QmISTLP{rOP&4lbjREw2tWnVWVOi3)-U7y{Oum`aH7=R(uvw7qoRpWM(pr z1#eQv4=2`$X*eE`hDYh(WOf!v5SSz-EHq9adop9r$%&(ZNQ(l&>4opubg|FL$8Ax^S-$TK`X(zIpQRq3vjt3kcwJ}7&2{B8J zx!;19%$WX0j2wT%Iy_R?)?E0hLNv>!j(}xbj&sg{N!Q!1DySeb*-+RGXtq{{eh8e$ z$Zq9ibfOwjUW5E(w=yhbz2j^Q^>2~Ko?T%FcrRM~?Y7-bgD3SuhHquhliwg8dQ*M3fBV|cdRx)PZw(_>)r8WTK_;gc|bqaEk z6L*m^cO^0i6taj+C`rOJ4xLT_DWQMF-h1Qs$7_i5_EsZ3cY_BpsS+D`zWTCIPE7pS zUyh~rVyQ|j^;c|uKQ_M?yH$zZD$N{-J@+o(zg(IjAA%aC4OF)rGFXmgfxHWFGO&fV z+a+OtyXsABq}qDpMb-<0 z<8Lg0fAhfHxxGolg}74;xcuT z&nPlDQa_)7HN|$|<}=Ug;d77kD{?ivp?w>;nlo`;SHB`xKnKH=z5!D6a2!|Tc}}Py zMnZ@aOCk2FqF~AWRZ+Cu{8v#=x%qGB*L;W{D1A`j`uDh4g^Shr5O;&CAx2+$5P#;F zcNU3}yTjG9A3YhaM!u=`O;)3+YV`YRbh_Gqvl{)h+9lO`f`h(S2*_(jY93MKUm+l` e87cW|Lno~XTz?G#Ikv?(-9GN)8aho}SpEfD2=9yl diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/bdist.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/bdist.cpython-311.pyc deleted file mode 100755 index 4b6af947cb3dc7b38834cadba59bc825c69e2782..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6003 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 diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/bdist_dumb.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/bdist_dumb.cpython-311.pyc deleted file mode 100755 index f3c47f866e798880cc6247ba21d5c665f970e322..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5723 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 KD-+L}>Hh%W>LwZh diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/build.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/build.cpython-311.pyc deleted file mode 100755 index df6651f2aea8d3fa475c40d29555b1188f6bffbb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6058 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 KM^EUd8~P6wpCh{f diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/build_ext.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/build_ext.cpython-311.pyc deleted file mode 100755 index 0e3492e56b87a04359434916b00e9cb67102c77c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30276 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 A;s5{u diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/check.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/check.cpython-311.pyc deleted file mode 100755 index 030bebbdbd4429cebd58fdd75c63da648a0037a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7512 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 H5?cNPA5#t} diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/config.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/config.cpython-311.pyc deleted file mode 100755 index 2080db424b2cdf653da72fe319efc0a45352ad0c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16225 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 diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/install.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/install.cpython-311.pyc deleted file mode 100755 index e3a7783078437b1b7bc8ec7eacbcb1b0376a8f81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29377 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 Tt=S$fPJGH@e*S=XwtxOFHyPBJ diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/install_data.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/install_data.cpython-311.pyc deleted file mode 100755 index 43bcfe9673bb10c7371afa98daf0c47e54f9018f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3765 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 diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/install_headers.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/install_headers.cpython-311.pyc deleted file mode 100755 index ead78b6b540a3d9841e1a703de4c34d8b1a799af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2353 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 O$tR@c>2unN>i-MnPr2#< diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/install_scripts.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/install_scripts.cpython-311.pyc deleted file mode 100755 index 5e619ca25ae8ab4ec3da0b21c9ddda0b85a28763..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3160 zcmaJ@&1)M+6rWw~>T_)+w(Q8?8z;e18c9u4a13rJt<$)1>y#!?5QIh6uH|)BT4i>X z#KLJ^@F52md@v*pg_=^_22;qPhaU4MNJbE`G*Bo#g3&WYsV$rm7j~yk0EkN^)8) z8D>t?BqNX2vT20FpBBrSQdCN&A(~5yIO9GcPIRbFh|U^k#6=y8&a7H0guhrZm-Le8 zESY{zteAh!0wx(N@Ugu!bbXp$Ad;)sq|dL+T+G|n+DNoX+y4;YK2i{nfU>O2WPJrB zvp+Fej*wDdv%Ji&qpV-{0|p2IaNHnZNDcvpq? zMYo!-#>jyB(B9iHm9l{&Kqu}3$TI+LBW#m!*}nilLT?pG?i>Uhj67{R=X%H1^a4#r zz%@IMsjE3F;&KkhrW;!!YKjD7i`pvD@gv6K3`JWs$R^^erOc9ER5HaJ&g+@WdO<&z z$(75QTT1CxMpG9uWg1@R(r3?R4B#PE&gF093W||26thw`bzL(uu!R%p87E3Jt}$*{ zmRGDEwWOMAPE)Ijq?ZZ5Ms>VX@1V{Qm}#5Sh` zg!Q~sfWGI5b~i#Yxs@K7!t3Xk;eB8?nY}^R$LnAd@yUU<1Cm`&I)kp?ybDRX9CAgt z-|Tby2rUyg(kA;>nRaU!v@vFqdf>EW&mz!lJGVLL>L4`Wb!Dy!cFTMfbnmin+10J^g~Sc}ySi!0@diWMn9 z4uHH|F%2sq;}r>(!NjW;r;{TE?FMkQLG1jc;0r2|?r^c`6L=3BwPhx{zuJshW^##)p6Ge%QTj{`~c0 zvoU$89-nQ*XQ2*tJ&Sa0Ol}tTA|tiPNXw4~MxMqKd+|g)e!3Aq-9rAZB!x|`*?Vkj z8q(-!@>%TI)@*I$y~i{4*i<7nRioEGBV#{&wSDdT>pxuoZL%?P?s26)JpII9ANpi- z#(CoWA19x1_1MKm>|!l;@mZ{YYxcpl?f2`kL?f1{(W}*qgi&gWyYsITF3(-z(f7^pr?z6nDk(j;WH5UF8CS#1Q~XMZ5^>G8L|SBBs$bfR>M8 zm=^0}dRvGJ^4`4M!ED)v5{5KN|7SN!I$%~shoJsGJnM{w5>yGL2k4r{&-NmN_i5~b@h4nW)X`8d*;Etf@8{9W z$I--5G|@~>wW2rM(VHEFgKwOWcrEl?8#&hKkw%}9=w7^jqeZShi^TRms86&a?>8>D z$cHCn_?XZmLL2Y4$XJ_<{S{WDp}!G82dTmTg)`uTvgf5OZ7H6!O8}42V|;*WsD^V2 z!;c7vNO|?UxhCC50e(~tkb=Hbpa*u4iFWYM_p&s{sa`%hZrK! zcKDt8=uwz9!}J7%6sr>uOp|m6`-}U={$iV4sm~vg>rHaK6Gp*U^=@shc`4CSlWi3g To9qyz#XC`iwQ8gq@j3nr#CL5U diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/register.cpython-311.pyc b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/__pycache__/register.cpython-311.pyc deleted file mode 100755 index a227a173b26d1c0dcd8c65b6ea091710fff88460..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15559 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 diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/_framework_compat.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/_framework_compat.py deleted file mode 100755 index cffa27c..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/_framework_compat.py +++ /dev/null @@ -1,55 +0,0 @@ -""" -Backward compatibility for homebrew builds on macOS. -""" - - -import sys -import os -import functools -import subprocess -import sysconfig - - -@functools.lru_cache() -def enabled(): - """ - Only enabled for Python 3.9 framework homebrew builds - except ensurepip and venv. - """ - PY39 = (3, 9) < sys.version_info < (3, 10) - framework = sys.platform == 'darwin' and sys._framework - homebrew = "Cellar" in sysconfig.get_config_var('projectbase') - venv = sys.prefix != sys.base_prefix - ensurepip = os.environ.get("ENSUREPIP_OPTIONS") - return PY39 and framework and homebrew and not venv and not ensurepip - - -schemes = dict( - osx_framework_library=dict( - stdlib='{installed_base}/{platlibdir}/python{py_version_short}', - platstdlib='{platbase}/{platlibdir}/python{py_version_short}', - purelib='{homebrew_prefix}/lib/python{py_version_short}/site-packages', - platlib='{homebrew_prefix}/{platlibdir}/python{py_version_short}/site-packages', - include='{installed_base}/include/python{py_version_short}{abiflags}', - platinclude='{installed_platbase}/include/python{py_version_short}{abiflags}', - scripts='{homebrew_prefix}/bin', - data='{homebrew_prefix}', - ) -) - - -@functools.lru_cache() -def vars(): - if not enabled(): - return {} - homebrew_prefix = subprocess.check_output(['brew', '--prefix'], text=True).strip() - return locals() - - -def scheme(name): - """ - Override the selected scheme for posix_prefix. - """ - if not enabled() or not name.endswith('_prefix'): - return name - return 'osx_framework_library' diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/bdist.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/bdist.py deleted file mode 100755 index bf0baab..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/bdist.py +++ /dev/null @@ -1,157 +0,0 @@ -"""distutils.command.bdist - -Implements the Distutils 'bdist' command (create a built [binary] -distribution).""" - -import os -import warnings - -from ..core import Command -from ..errors import DistutilsPlatformError, DistutilsOptionError -from ..util import get_platform - - -def show_formats(): - """Print list of available formats (arguments to "--format" option).""" - from ..fancy_getopt import FancyGetopt - - formats = [] - for format in bdist.format_commands: - formats.append(("formats=" + format, None, bdist.format_commands[format][1])) - pretty_printer = FancyGetopt(formats) - pretty_printer.print_help("List of available distribution formats:") - - -class ListCompat(dict): - # adapter to allow for Setuptools compatibility in format_commands - def append(self, item): - warnings.warn( - """format_commands is now a dict. append is deprecated.""", - DeprecationWarning, - stacklevel=2, - ) - - -class bdist(Command): - - description = "create a built (binary) distribution" - - user_options = [ - ('bdist-base=', 'b', "temporary directory for creating built distributions"), - ( - 'plat-name=', - 'p', - "platform name to embed in generated filenames " - "(default: %s)" % get_platform(), - ), - ('formats=', None, "formats for distribution (comma-separated list)"), - ( - 'dist-dir=', - 'd', - "directory to put final built distributions in " "[default: dist]", - ), - ('skip-build', None, "skip rebuilding everything (for testing/debugging)"), - ( - 'owner=', - 'u', - "Owner name used when creating a tar file" " [default: current user]", - ), - ( - 'group=', - 'g', - "Group name used when creating a tar file" " [default: current group]", - ), - ] - - boolean_options = ['skip-build'] - - help_options = [ - ('help-formats', None, "lists available distribution formats", show_formats), - ] - - # The following commands do not take a format option from bdist - no_format_option = ('bdist_rpm',) - - # This won't do in reality: will need to distinguish RPM-ish Linux, - # Debian-ish Linux, Solaris, FreeBSD, ..., Windows, Mac OS. - default_format = {'posix': 'gztar', 'nt': 'zip'} - - # Define commands in preferred order for the --help-formats option - format_commands = ListCompat( - { - 'rpm': ('bdist_rpm', "RPM distribution"), - 'gztar': ('bdist_dumb', "gzip'ed tar file"), - 'bztar': ('bdist_dumb', "bzip2'ed tar file"), - 'xztar': ('bdist_dumb', "xz'ed tar file"), - 'ztar': ('bdist_dumb', "compressed tar file"), - 'tar': ('bdist_dumb', "tar file"), - 'zip': ('bdist_dumb', "ZIP file"), - } - ) - - # for compatibility until consumers only reference format_commands - format_command = format_commands - - def initialize_options(self): - self.bdist_base = None - self.plat_name = None - self.formats = None - self.dist_dir = None - self.skip_build = 0 - self.group = None - self.owner = None - - def finalize_options(self): - # have to finalize 'plat_name' before 'bdist_base' - if self.plat_name is None: - if self.skip_build: - self.plat_name = get_platform() - else: - self.plat_name = self.get_finalized_command('build').plat_name - - # 'bdist_base' -- parent of per-built-distribution-format - # temporary directories (eg. we'll probably have - # "build/bdist./dumb", "build/bdist./rpm", etc.) - if self.bdist_base is None: - build_base = self.get_finalized_command('build').build_base - self.bdist_base = os.path.join(build_base, 'bdist.' + self.plat_name) - - self.ensure_string_list('formats') - if self.formats is None: - try: - self.formats = [self.default_format[os.name]] - except KeyError: - raise DistutilsPlatformError( - "don't know how to create built distributions " - "on platform %s" % os.name - ) - - if self.dist_dir is None: - self.dist_dir = "dist" - - def run(self): - # Figure out which sub-commands we need to run. - commands = [] - for format in self.formats: - try: - commands.append(self.format_commands[format][0]) - except KeyError: - raise DistutilsOptionError("invalid format '%s'" % format) - - # Reinitialize and run each command. - for i in range(len(self.formats)): - cmd_name = commands[i] - sub_cmd = self.reinitialize_command(cmd_name) - if cmd_name not in self.no_format_option: - sub_cmd.format = self.formats[i] - - # passing the owner and group names for tar archiving - if cmd_name == 'bdist_dumb': - sub_cmd.owner = self.owner - sub_cmd.group = self.group - - # If we're going to need to run this command again, tell it to - # keep its temporary files around so subsequent runs go faster. - if cmd_name in commands[i + 1 :]: - sub_cmd.keep_temp = 1 - self.run_command(cmd_name) diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/bdist_dumb.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/bdist_dumb.py deleted file mode 100755 index 071da77..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/bdist_dumb.py +++ /dev/null @@ -1,144 +0,0 @@ -"""distutils.command.bdist_dumb - -Implements the Distutils 'bdist_dumb' command (create a "dumb" built -distribution -- i.e., just an archive to be unpacked under $prefix or -$exec_prefix).""" - -import os -from ..core import Command -from ..util import get_platform -from ..dir_util import remove_tree, ensure_relative -from ..errors import DistutilsPlatformError -from ..sysconfig import get_python_version -from distutils._log import log - - -class bdist_dumb(Command): - - description = "create a \"dumb\" built distribution" - - user_options = [ - ('bdist-dir=', 'd', "temporary directory for creating the distribution"), - ( - 'plat-name=', - 'p', - "platform name to embed in generated filenames " - "(default: %s)" % get_platform(), - ), - ( - 'format=', - 'f', - "archive format to create (tar, gztar, bztar, xztar, " "ztar, zip)", - ), - ( - 'keep-temp', - 'k', - "keep the pseudo-installation tree around after " - + "creating the distribution archive", - ), - ('dist-dir=', 'd', "directory to put final built distributions in"), - ('skip-build', None, "skip rebuilding everything (for testing/debugging)"), - ( - 'relative', - None, - "build the archive using relative paths " "(default: false)", - ), - ( - 'owner=', - 'u', - "Owner name used when creating a tar file" " [default: current user]", - ), - ( - 'group=', - 'g', - "Group name used when creating a tar file" " [default: current group]", - ), - ] - - boolean_options = ['keep-temp', 'skip-build', 'relative'] - - default_format = {'posix': 'gztar', 'nt': 'zip'} - - def initialize_options(self): - self.bdist_dir = None - self.plat_name = None - self.format = None - self.keep_temp = 0 - self.dist_dir = None - self.skip_build = None - self.relative = 0 - self.owner = None - self.group = None - - def finalize_options(self): - if self.bdist_dir is None: - bdist_base = self.get_finalized_command('bdist').bdist_base - self.bdist_dir = os.path.join(bdist_base, 'dumb') - - if self.format is None: - try: - self.format = self.default_format[os.name] - except KeyError: - raise DistutilsPlatformError( - "don't know how to create dumb built distributions " - "on platform %s" % os.name - ) - - self.set_undefined_options( - 'bdist', - ('dist_dir', 'dist_dir'), - ('plat_name', 'plat_name'), - ('skip_build', 'skip_build'), - ) - - def run(self): - if not self.skip_build: - self.run_command('build') - - install = self.reinitialize_command('install', reinit_subcommands=1) - install.root = self.bdist_dir - install.skip_build = self.skip_build - install.warn_dir = 0 - - log.info("installing to %s", self.bdist_dir) - self.run_command('install') - - # And make an archive relative to the root of the - # pseudo-installation tree. - archive_basename = "{}.{}".format( - self.distribution.get_fullname(), self.plat_name - ) - - pseudoinstall_root = os.path.join(self.dist_dir, archive_basename) - if not self.relative: - archive_root = self.bdist_dir - else: - if self.distribution.has_ext_modules() and ( - install.install_base != install.install_platbase - ): - raise DistutilsPlatformError( - "can't make a dumb built distribution where " - "base and platbase are different (%s, %s)" - % (repr(install.install_base), repr(install.install_platbase)) - ) - else: - archive_root = os.path.join( - self.bdist_dir, ensure_relative(install.install_base) - ) - - # Make the archive - filename = self.make_archive( - pseudoinstall_root, - self.format, - root_dir=archive_root, - owner=self.owner, - group=self.group, - ) - if self.distribution.has_ext_modules(): - pyversion = get_python_version() - else: - pyversion = 'any' - self.distribution.dist_files.append(('bdist_dumb', pyversion, filename)) - - if not self.keep_temp: - remove_tree(self.bdist_dir, dry_run=self.dry_run) diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/bdist_rpm.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/bdist_rpm.py deleted file mode 100755 index 340527b..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/bdist_rpm.py +++ /dev/null @@ -1,615 +0,0 @@ -"""distutils.command.bdist_rpm - -Implements the Distutils 'bdist_rpm' command (create RPM source and binary -distributions).""" - -import subprocess -import sys -import os - -from ..core import Command -from ..debug import DEBUG -from ..file_util import write_file -from ..errors import ( - DistutilsOptionError, - DistutilsPlatformError, - DistutilsFileError, - DistutilsExecError, -) -from ..sysconfig import get_python_version -from distutils._log import log - - -class bdist_rpm(Command): - - description = "create an RPM distribution" - - user_options = [ - ('bdist-base=', None, "base directory for creating built distributions"), - ( - 'rpm-base=', - None, - "base directory for creating RPMs (defaults to \"rpm\" under " - "--bdist-base; must be specified for RPM 2)", - ), - ( - 'dist-dir=', - 'd', - "directory to put final RPM files in " "(and .spec files if --spec-only)", - ), - ( - 'python=', - None, - "path to Python interpreter to hard-code in the .spec file " - "(default: \"python\")", - ), - ( - 'fix-python', - None, - "hard-code the exact path to the current Python interpreter in " - "the .spec file", - ), - ('spec-only', None, "only regenerate spec file"), - ('source-only', None, "only generate source RPM"), - ('binary-only', None, "only generate binary RPM"), - ('use-bzip2', None, "use bzip2 instead of gzip to create source distribution"), - # More meta-data: too RPM-specific to put in the setup script, - # but needs to go in the .spec file -- so we make these options - # to "bdist_rpm". The idea is that packagers would put this - # info in setup.cfg, although they are of course free to - # supply it on the command line. - ( - 'distribution-name=', - None, - "name of the (Linux) distribution to which this " - "RPM applies (*not* the name of the module distribution!)", - ), - ('group=', None, "package classification [default: \"Development/Libraries\"]"), - ('release=', None, "RPM release number"), - ('serial=', None, "RPM serial number"), - ( - 'vendor=', - None, - "RPM \"vendor\" (eg. \"Joe Blow \") " - "[default: maintainer or author from setup script]", - ), - ( - 'packager=', - None, - "RPM packager (eg. \"Jane Doe \") " "[default: vendor]", - ), - ('doc-files=', None, "list of documentation files (space or comma-separated)"), - ('changelog=', None, "RPM changelog"), - ('icon=', None, "name of icon file"), - ('provides=', None, "capabilities provided by this package"), - ('requires=', None, "capabilities required by this package"), - ('conflicts=', None, "capabilities which conflict with this package"), - ('build-requires=', None, "capabilities required to build this package"), - ('obsoletes=', None, "capabilities made obsolete by this package"), - ('no-autoreq', None, "do not automatically calculate dependencies"), - # Actions to take when building RPM - ('keep-temp', 'k', "don't clean up RPM build directory"), - ('no-keep-temp', None, "clean up RPM build directory [default]"), - ( - 'use-rpm-opt-flags', - None, - "compile with RPM_OPT_FLAGS when building from source RPM", - ), - ('no-rpm-opt-flags', None, "do not pass any RPM CFLAGS to compiler"), - ('rpm3-mode', None, "RPM 3 compatibility mode (default)"), - ('rpm2-mode', None, "RPM 2 compatibility mode"), - # Add the hooks necessary for specifying custom scripts - ('prep-script=', None, "Specify a script for the PREP phase of RPM building"), - ('build-script=', None, "Specify a script for the BUILD phase of RPM building"), - ( - 'pre-install=', - None, - "Specify a script for the pre-INSTALL phase of RPM building", - ), - ( - 'install-script=', - None, - "Specify a script for the INSTALL phase of RPM building", - ), - ( - 'post-install=', - None, - "Specify a script for the post-INSTALL phase of RPM building", - ), - ( - 'pre-uninstall=', - None, - "Specify a script for the pre-UNINSTALL phase of RPM building", - ), - ( - 'post-uninstall=', - None, - "Specify a script for the post-UNINSTALL phase of RPM building", - ), - ('clean-script=', None, "Specify a script for the CLEAN phase of RPM building"), - ( - 'verify-script=', - None, - "Specify a script for the VERIFY phase of the RPM build", - ), - # Allow a packager to explicitly force an architecture - ('force-arch=', None, "Force an architecture onto the RPM build process"), - ('quiet', 'q', "Run the INSTALL phase of RPM building in quiet mode"), - ] - - boolean_options = [ - 'keep-temp', - 'use-rpm-opt-flags', - 'rpm3-mode', - 'no-autoreq', - 'quiet', - ] - - negative_opt = { - 'no-keep-temp': 'keep-temp', - 'no-rpm-opt-flags': 'use-rpm-opt-flags', - 'rpm2-mode': 'rpm3-mode', - } - - def initialize_options(self): - self.bdist_base = None - self.rpm_base = None - self.dist_dir = None - self.python = None - self.fix_python = None - self.spec_only = None - self.binary_only = None - self.source_only = None - self.use_bzip2 = None - - self.distribution_name = None - self.group = None - self.release = None - self.serial = None - self.vendor = None - self.packager = None - self.doc_files = None - self.changelog = None - self.icon = None - - self.prep_script = None - self.build_script = None - self.install_script = None - self.clean_script = None - self.verify_script = None - self.pre_install = None - self.post_install = None - self.pre_uninstall = None - self.post_uninstall = None - self.prep = None - self.provides = None - self.requires = None - self.conflicts = None - self.build_requires = None - self.obsoletes = None - - self.keep_temp = 0 - self.use_rpm_opt_flags = 1 - self.rpm3_mode = 1 - self.no_autoreq = 0 - - self.force_arch = None - self.quiet = 0 - - def finalize_options(self): - self.set_undefined_options('bdist', ('bdist_base', 'bdist_base')) - if self.rpm_base is None: - if not self.rpm3_mode: - raise DistutilsOptionError("you must specify --rpm-base in RPM 2 mode") - self.rpm_base = os.path.join(self.bdist_base, "rpm") - - if self.python is None: - if self.fix_python: - self.python = sys.executable - else: - self.python = "python3" - elif self.fix_python: - raise DistutilsOptionError( - "--python and --fix-python are mutually exclusive options" - ) - - if os.name != 'posix': - raise DistutilsPlatformError( - "don't know how to create RPM " "distributions on platform %s" % os.name - ) - if self.binary_only and self.source_only: - raise DistutilsOptionError( - "cannot supply both '--source-only' and '--binary-only'" - ) - - # don't pass CFLAGS to pure python distributions - if not self.distribution.has_ext_modules(): - self.use_rpm_opt_flags = 0 - - self.set_undefined_options('bdist', ('dist_dir', 'dist_dir')) - self.finalize_package_data() - - def finalize_package_data(self): - self.ensure_string('group', "Development/Libraries") - self.ensure_string( - 'vendor', - "%s <%s>" - % (self.distribution.get_contact(), self.distribution.get_contact_email()), - ) - self.ensure_string('packager') - self.ensure_string_list('doc_files') - if isinstance(self.doc_files, list): - for readme in ('README', 'README.txt'): - if os.path.exists(readme) and readme not in self.doc_files: - self.doc_files.append(readme) - - self.ensure_string('release', "1") - self.ensure_string('serial') # should it be an int? - - self.ensure_string('distribution_name') - - self.ensure_string('changelog') - # Format changelog correctly - self.changelog = self._format_changelog(self.changelog) - - self.ensure_filename('icon') - - self.ensure_filename('prep_script') - self.ensure_filename('build_script') - self.ensure_filename('install_script') - self.ensure_filename('clean_script') - self.ensure_filename('verify_script') - self.ensure_filename('pre_install') - self.ensure_filename('post_install') - self.ensure_filename('pre_uninstall') - self.ensure_filename('post_uninstall') - - # XXX don't forget we punted on summaries and descriptions -- they - # should be handled here eventually! - - # Now *this* is some meta-data that belongs in the setup script... - self.ensure_string_list('provides') - self.ensure_string_list('requires') - self.ensure_string_list('conflicts') - self.ensure_string_list('build_requires') - self.ensure_string_list('obsoletes') - - self.ensure_string('force_arch') - - def run(self): # noqa: C901 - if DEBUG: - print("before _get_package_data():") - print("vendor =", self.vendor) - print("packager =", self.packager) - print("doc_files =", self.doc_files) - print("changelog =", self.changelog) - - # make directories - if self.spec_only: - spec_dir = self.dist_dir - self.mkpath(spec_dir) - else: - rpm_dir = {} - for d in ('SOURCES', 'SPECS', 'BUILD', 'RPMS', 'SRPMS'): - rpm_dir[d] = os.path.join(self.rpm_base, d) - self.mkpath(rpm_dir[d]) - spec_dir = rpm_dir['SPECS'] - - # Spec file goes into 'dist_dir' if '--spec-only specified', - # build/rpm. otherwise. - spec_path = os.path.join(spec_dir, "%s.spec" % self.distribution.get_name()) - self.execute( - write_file, (spec_path, self._make_spec_file()), "writing '%s'" % spec_path - ) - - if self.spec_only: # stop if requested - return - - # Make a source distribution and copy to SOURCES directory with - # optional icon. - saved_dist_files = self.distribution.dist_files[:] - sdist = self.reinitialize_command('sdist') - if self.use_bzip2: - sdist.formats = ['bztar'] - else: - sdist.formats = ['gztar'] - self.run_command('sdist') - self.distribution.dist_files = saved_dist_files - - source = sdist.get_archive_files()[0] - source_dir = rpm_dir['SOURCES'] - self.copy_file(source, source_dir) - - if self.icon: - if os.path.exists(self.icon): - self.copy_file(self.icon, source_dir) - else: - raise DistutilsFileError("icon file '%s' does not exist" % self.icon) - - # build package - log.info("building RPMs") - rpm_cmd = ['rpmbuild'] - - if self.source_only: # what kind of RPMs? - rpm_cmd.append('-bs') - elif self.binary_only: - rpm_cmd.append('-bb') - else: - rpm_cmd.append('-ba') - rpm_cmd.extend(['--define', '__python %s' % self.python]) - if self.rpm3_mode: - rpm_cmd.extend(['--define', '_topdir %s' % os.path.abspath(self.rpm_base)]) - if not self.keep_temp: - rpm_cmd.append('--clean') - - if self.quiet: - rpm_cmd.append('--quiet') - - rpm_cmd.append(spec_path) - # Determine the binary rpm names that should be built out of this spec - # file - # Note that some of these may not be really built (if the file - # list is empty) - nvr_string = "%{name}-%{version}-%{release}" - src_rpm = nvr_string + ".src.rpm" - non_src_rpm = "%{arch}/" + nvr_string + ".%{arch}.rpm" - q_cmd = r"rpm -q --qf '{} {}\n' --specfile '{}'".format( - src_rpm, - non_src_rpm, - spec_path, - ) - - out = os.popen(q_cmd) - try: - binary_rpms = [] - source_rpm = None - while True: - line = out.readline() - if not line: - break - ell = line.strip().split() - assert len(ell) == 2 - binary_rpms.append(ell[1]) - # The source rpm is named after the first entry in the spec file - if source_rpm is None: - source_rpm = ell[0] - - status = out.close() - if status: - raise DistutilsExecError("Failed to execute: %s" % repr(q_cmd)) - - finally: - out.close() - - self.spawn(rpm_cmd) - - if not self.dry_run: - if self.distribution.has_ext_modules(): - pyversion = get_python_version() - else: - pyversion = 'any' - - if not self.binary_only: - srpm = os.path.join(rpm_dir['SRPMS'], source_rpm) - assert os.path.exists(srpm) - self.move_file(srpm, self.dist_dir) - filename = os.path.join(self.dist_dir, source_rpm) - self.distribution.dist_files.append(('bdist_rpm', pyversion, filename)) - - if not self.source_only: - for rpm in binary_rpms: - rpm = os.path.join(rpm_dir['RPMS'], rpm) - if os.path.exists(rpm): - self.move_file(rpm, self.dist_dir) - filename = os.path.join(self.dist_dir, os.path.basename(rpm)) - self.distribution.dist_files.append( - ('bdist_rpm', pyversion, filename) - ) - - def _dist_path(self, path): - return os.path.join(self.dist_dir, os.path.basename(path)) - - def _make_spec_file(self): # noqa: C901 - """Generate the text of an RPM spec file and return it as a - list of strings (one per line). - """ - # definitions and headers - spec_file = [ - '%define name ' + self.distribution.get_name(), - '%define version ' + self.distribution.get_version().replace('-', '_'), - '%define unmangled_version ' + self.distribution.get_version(), - '%define release ' + self.release.replace('-', '_'), - '', - 'Summary: ' + (self.distribution.get_description() or "UNKNOWN"), - ] - - # Workaround for #14443 which affects some RPM based systems such as - # RHEL6 (and probably derivatives) - vendor_hook = subprocess.getoutput('rpm --eval %{__os_install_post}') - # Generate a potential replacement value for __os_install_post (whilst - # normalizing the whitespace to simplify the test for whether the - # invocation of brp-python-bytecompile passes in __python): - vendor_hook = '\n'.join( - [' %s \\' % line.strip() for line in vendor_hook.splitlines()] - ) - problem = "brp-python-bytecompile \\\n" - fixed = "brp-python-bytecompile %{__python} \\\n" - fixed_hook = vendor_hook.replace(problem, fixed) - if fixed_hook != vendor_hook: - spec_file.append('# Workaround for http://bugs.python.org/issue14443') - spec_file.append('%define __os_install_post ' + fixed_hook + '\n') - - # put locale summaries into spec file - # XXX not supported for now (hard to put a dictionary - # in a config file -- arg!) - # for locale in self.summaries.keys(): - # spec_file.append('Summary(%s): %s' % (locale, - # self.summaries[locale])) - - spec_file.extend( - [ - 'Name: %{name}', - 'Version: %{version}', - 'Release: %{release}', - ] - ) - - # XXX yuck! this filename is available from the "sdist" command, - # but only after it has run: and we create the spec file before - # running "sdist", in case of --spec-only. - if self.use_bzip2: - spec_file.append('Source0: %{name}-%{unmangled_version}.tar.bz2') - else: - spec_file.append('Source0: %{name}-%{unmangled_version}.tar.gz') - - spec_file.extend( - [ - 'License: ' + (self.distribution.get_license() or "UNKNOWN"), - 'Group: ' + self.group, - 'BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot', - 'Prefix: %{_prefix}', - ] - ) - - if not self.force_arch: - # noarch if no extension modules - if not self.distribution.has_ext_modules(): - spec_file.append('BuildArch: noarch') - else: - spec_file.append('BuildArch: %s' % self.force_arch) - - for field in ( - 'Vendor', - 'Packager', - 'Provides', - 'Requires', - 'Conflicts', - 'Obsoletes', - ): - val = getattr(self, field.lower()) - if isinstance(val, list): - spec_file.append('{}: {}'.format(field, ' '.join(val))) - elif val is not None: - spec_file.append('{}: {}'.format(field, val)) - - if self.distribution.get_url(): - spec_file.append('Url: ' + self.distribution.get_url()) - - if self.distribution_name: - spec_file.append('Distribution: ' + self.distribution_name) - - if self.build_requires: - spec_file.append('BuildRequires: ' + ' '.join(self.build_requires)) - - if self.icon: - spec_file.append('Icon: ' + os.path.basename(self.icon)) - - if self.no_autoreq: - spec_file.append('AutoReq: 0') - - spec_file.extend( - [ - '', - '%description', - self.distribution.get_long_description() or "", - ] - ) - - # put locale descriptions into spec file - # XXX again, suppressed because config file syntax doesn't - # easily support this ;-( - # for locale in self.descriptions.keys(): - # spec_file.extend([ - # '', - # '%description -l ' + locale, - # self.descriptions[locale], - # ]) - - # rpm scripts - # figure out default build script - def_setup_call = "{} {}".format(self.python, os.path.basename(sys.argv[0])) - def_build = "%s build" % def_setup_call - if self.use_rpm_opt_flags: - def_build = 'env CFLAGS="$RPM_OPT_FLAGS" ' + def_build - - # insert contents of files - - # XXX this is kind of misleading: user-supplied options are files - # that we open and interpolate into the spec file, but the defaults - # are just text that we drop in as-is. Hmmm. - - install_cmd = ( - '%s install -O1 --root=$RPM_BUILD_ROOT ' '--record=INSTALLED_FILES' - ) % def_setup_call - - script_options = [ - ('prep', 'prep_script', "%setup -n %{name}-%{unmangled_version}"), - ('build', 'build_script', def_build), - ('install', 'install_script', install_cmd), - ('clean', 'clean_script', "rm -rf $RPM_BUILD_ROOT"), - ('verifyscript', 'verify_script', None), - ('pre', 'pre_install', None), - ('post', 'post_install', None), - ('preun', 'pre_uninstall', None), - ('postun', 'post_uninstall', None), - ] - - for (rpm_opt, attr, default) in script_options: - # Insert contents of file referred to, if no file is referred to - # use 'default' as contents of script - val = getattr(self, attr) - if val or default: - spec_file.extend( - [ - '', - '%' + rpm_opt, - ] - ) - if val: - with open(val) as f: - spec_file.extend(f.read().split('\n')) - else: - spec_file.append(default) - - # files section - spec_file.extend( - [ - '', - '%files -f INSTALLED_FILES', - '%defattr(-,root,root)', - ] - ) - - if self.doc_files: - spec_file.append('%doc ' + ' '.join(self.doc_files)) - - if self.changelog: - spec_file.extend( - [ - '', - '%changelog', - ] - ) - spec_file.extend(self.changelog) - - return spec_file - - def _format_changelog(self, changelog): - """Format the changelog correctly and convert it to a list of strings""" - if not changelog: - return changelog - new_changelog = [] - for line in changelog.strip().split('\n'): - line = line.strip() - if line[0] == '*': - new_changelog.extend(['', line]) - elif line[0] == '-': - new_changelog.append(line) - else: - new_changelog.append(' ' + line) - - # strip trailing newline inserted by first changelog entry - if not new_changelog[0]: - del new_changelog[0] - - return new_changelog diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/build.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/build.py deleted file mode 100755 index c3ab410..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/build.py +++ /dev/null @@ -1,153 +0,0 @@ -"""distutils.command.build - -Implements the Distutils 'build' command.""" - -import sys -import os -from ..core import Command -from ..errors import DistutilsOptionError -from ..util import get_platform - - -def show_compilers(): - from ..ccompiler import show_compilers - - show_compilers() - - -class build(Command): - - description = "build everything needed to install" - - user_options = [ - ('build-base=', 'b', "base directory for build library"), - ('build-purelib=', None, "build directory for platform-neutral distributions"), - ('build-platlib=', None, "build directory for platform-specific distributions"), - ( - 'build-lib=', - None, - "build directory for all distribution (defaults to either " - + "build-purelib or build-platlib", - ), - ('build-scripts=', None, "build directory for scripts"), - ('build-temp=', 't', "temporary build directory"), - ( - 'plat-name=', - 'p', - "platform name to build for, if supported " - "(default: %s)" % get_platform(), - ), - ('compiler=', 'c', "specify the compiler type"), - ('parallel=', 'j', "number of parallel build jobs"), - ('debug', 'g', "compile extensions and libraries with debugging information"), - ('force', 'f', "forcibly build everything (ignore file timestamps)"), - ('executable=', 'e', "specify final destination interpreter path (build.py)"), - ] - - boolean_options = ['debug', 'force'] - - help_options = [ - ('help-compiler', None, "list available compilers", show_compilers), - ] - - def initialize_options(self): - self.build_base = 'build' - # these are decided only after 'build_base' has its final value - # (unless overridden by the user or client) - self.build_purelib = None - self.build_platlib = None - self.build_lib = None - self.build_temp = None - self.build_scripts = None - self.compiler = None - self.plat_name = None - self.debug = None - self.force = 0 - self.executable = None - self.parallel = None - - def finalize_options(self): # noqa: C901 - if self.plat_name is None: - self.plat_name = get_platform() - else: - # plat-name only supported for windows (other platforms are - # supported via ./configure flags, if at all). Avoid misleading - # other platforms. - if os.name != 'nt': - raise DistutilsOptionError( - "--plat-name only supported on Windows (try " - "using './configure --help' on your platform)" - ) - - plat_specifier = ".{}-{}".format(self.plat_name, sys.implementation.cache_tag) - - # Make it so Python 2.x and Python 2.x with --with-pydebug don't - # share the same build directories. Doing so confuses the build - # process for C modules - if hasattr(sys, 'gettotalrefcount'): - plat_specifier += '-pydebug' - - # 'build_purelib' and 'build_platlib' just default to 'lib' and - # 'lib.' under the base build directory. We only use one of - # them for a given distribution, though -- - if self.build_purelib is None: - self.build_purelib = os.path.join(self.build_base, 'lib') - if self.build_platlib is None: - self.build_platlib = os.path.join(self.build_base, 'lib' + plat_specifier) - - # 'build_lib' is the actual directory that we will use for this - # particular module distribution -- if user didn't supply it, pick - # one of 'build_purelib' or 'build_platlib'. - if self.build_lib is None: - if self.distribution.has_ext_modules(): - self.build_lib = self.build_platlib - else: - self.build_lib = self.build_purelib - - # 'build_temp' -- temporary directory for compiler turds, - # "build/temp." - if self.build_temp is None: - self.build_temp = os.path.join(self.build_base, 'temp' + plat_specifier) - if self.build_scripts is None: - self.build_scripts = os.path.join( - self.build_base, 'scripts-%d.%d' % sys.version_info[:2] - ) - - if self.executable is None and sys.executable: - self.executable = os.path.normpath(sys.executable) - - if isinstance(self.parallel, str): - try: - self.parallel = int(self.parallel) - except ValueError: - raise DistutilsOptionError("parallel should be an integer") - - def run(self): - # Run all relevant sub-commands. This will be some subset of: - # - build_py - pure Python modules - # - build_clib - standalone C libraries - # - build_ext - Python extensions - # - build_scripts - (Python) scripts - for cmd_name in self.get_sub_commands(): - self.run_command(cmd_name) - - # -- Predicates for the sub-command list --------------------------- - - def has_pure_modules(self): - return self.distribution.has_pure_modules() - - def has_c_libraries(self): - return self.distribution.has_c_libraries() - - def has_ext_modules(self): - return self.distribution.has_ext_modules() - - def has_scripts(self): - return self.distribution.has_scripts() - - sub_commands = [ - ('build_py', has_pure_modules), - ('build_clib', has_c_libraries), - ('build_ext', has_ext_modules), - ('build_scripts', has_scripts), - ] diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/build_clib.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/build_clib.py deleted file mode 100755 index f90c566..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/build_clib.py +++ /dev/null @@ -1,208 +0,0 @@ -"""distutils.command.build_clib - -Implements the Distutils 'build_clib' command, to build a C/C++ library -that is included in the module distribution and needed by an extension -module.""" - - -# XXX this module has *lots* of code ripped-off quite transparently from -# build_ext.py -- not surprisingly really, as the work required to build -# a static library from a collection of C source files is not really all -# that different from what's required to build a shared object file from -# a collection of C source files. Nevertheless, I haven't done the -# necessary refactoring to account for the overlap in code between the -# two modules, mainly because a number of subtle details changed in the -# cut 'n paste. Sigh. - -import os -from ..core import Command -from ..errors import DistutilsSetupError -from ..sysconfig import customize_compiler -from distutils._log import log - - -def show_compilers(): - from ..ccompiler import show_compilers - - show_compilers() - - -class build_clib(Command): - - description = "build C/C++ libraries used by Python extensions" - - user_options = [ - ('build-clib=', 'b', "directory to build C/C++ libraries to"), - ('build-temp=', 't', "directory to put temporary build by-products"), - ('debug', 'g', "compile with debugging information"), - ('force', 'f', "forcibly build everything (ignore file timestamps)"), - ('compiler=', 'c', "specify the compiler type"), - ] - - boolean_options = ['debug', 'force'] - - help_options = [ - ('help-compiler', None, "list available compilers", show_compilers), - ] - - def initialize_options(self): - self.build_clib = None - self.build_temp = None - - # List of libraries to build - self.libraries = None - - # Compilation options for all libraries - self.include_dirs = None - self.define = None - self.undef = None - self.debug = None - self.force = 0 - self.compiler = None - - def finalize_options(self): - # This might be confusing: both build-clib and build-temp default - # to build-temp as defined by the "build" command. This is because - # I think that C libraries are really just temporary build - # by-products, at least from the point of view of building Python - # extensions -- but I want to keep my options open. - self.set_undefined_options( - 'build', - ('build_temp', 'build_clib'), - ('build_temp', 'build_temp'), - ('compiler', 'compiler'), - ('debug', 'debug'), - ('force', 'force'), - ) - - self.libraries = self.distribution.libraries - if self.libraries: - self.check_library_list(self.libraries) - - if self.include_dirs is None: - self.include_dirs = self.distribution.include_dirs or [] - if isinstance(self.include_dirs, str): - self.include_dirs = self.include_dirs.split(os.pathsep) - - # XXX same as for build_ext -- what about 'self.define' and - # 'self.undef' ? - - def run(self): - if not self.libraries: - return - - # Yech -- this is cut 'n pasted from build_ext.py! - from ..ccompiler import new_compiler - - self.compiler = new_compiler( - compiler=self.compiler, dry_run=self.dry_run, force=self.force - ) - customize_compiler(self.compiler) - - if self.include_dirs is not None: - self.compiler.set_include_dirs(self.include_dirs) - if self.define is not None: - # 'define' option is a list of (name,value) tuples - for (name, value) in self.define: - self.compiler.define_macro(name, value) - if self.undef is not None: - for macro in self.undef: - self.compiler.undefine_macro(macro) - - self.build_libraries(self.libraries) - - def check_library_list(self, libraries): - """Ensure that the list of libraries is valid. - - `library` is presumably provided as a command option 'libraries'. - This method checks that it is a list of 2-tuples, where the tuples - are (library_name, build_info_dict). - - Raise DistutilsSetupError if the structure is invalid anywhere; - just returns otherwise. - """ - if not isinstance(libraries, list): - raise DistutilsSetupError("'libraries' option must be a list of tuples") - - for lib in libraries: - if not isinstance(lib, tuple) and len(lib) != 2: - raise DistutilsSetupError("each element of 'libraries' must a 2-tuple") - - name, build_info = lib - - if not isinstance(name, str): - raise DistutilsSetupError( - "first element of each tuple in 'libraries' " - "must be a string (the library name)" - ) - - if '/' in name or (os.sep != '/' and os.sep in name): - raise DistutilsSetupError( - "bad library name '%s': " - "may not contain directory separators" % lib[0] - ) - - if not isinstance(build_info, dict): - raise DistutilsSetupError( - "second element of each tuple in 'libraries' " - "must be a dictionary (build info)" - ) - - def get_library_names(self): - # Assume the library list is valid -- 'check_library_list()' is - # called from 'finalize_options()', so it should be! - if not self.libraries: - return None - - lib_names = [] - for (lib_name, build_info) in self.libraries: - lib_names.append(lib_name) - return lib_names - - def get_source_files(self): - self.check_library_list(self.libraries) - filenames = [] - for (lib_name, build_info) in self.libraries: - sources = build_info.get('sources') - if sources is None or not isinstance(sources, (list, tuple)): - raise DistutilsSetupError( - "in 'libraries' option (library '%s'), " - "'sources' must be present and must be " - "a list of source filenames" % lib_name - ) - - filenames.extend(sources) - return filenames - - def build_libraries(self, libraries): - for (lib_name, build_info) in libraries: - sources = build_info.get('sources') - if sources is None or not isinstance(sources, (list, tuple)): - raise DistutilsSetupError( - "in 'libraries' option (library '%s'), " - "'sources' must be present and must be " - "a list of source filenames" % lib_name - ) - sources = list(sources) - - log.info("building '%s' library", lib_name) - - # First, compile the source code to object files in the library - # directory. (This should probably change to putting object - # files in a temporary build directory.) - macros = build_info.get('macros') - include_dirs = build_info.get('include_dirs') - objects = self.compiler.compile( - sources, - output_dir=self.build_temp, - macros=macros, - include_dirs=include_dirs, - debug=self.debug, - ) - - # Now "link" the object files together into a static library. - # (On Unix at least, this isn't really linking -- it just - # builds an archive. Whatever.) - self.compiler.create_static_lib( - objects, lib_name, output_dir=self.build_clib, debug=self.debug - ) diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/build_ext.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/build_ext.py deleted file mode 100755 index f4c0ecc..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/build_ext.py +++ /dev/null @@ -1,789 +0,0 @@ -"""distutils.command.build_ext - -Implements the Distutils 'build_ext' command, for building extension -modules (currently limited to C extensions, should accommodate C++ -extensions ASAP).""" - -import contextlib -import os -import re -import sys -from ..core import Command -from ..errors import ( - DistutilsOptionError, - DistutilsSetupError, - CCompilerError, - DistutilsError, - CompileError, - DistutilsPlatformError, -) -from ..sysconfig import customize_compiler, get_python_version -from ..sysconfig import get_config_h_filename -from ..dep_util import newer_group -from ..extension import Extension -from ..util import get_platform -from distutils._log import log -from . import py37compat - -from site import USER_BASE - -# An extension name is just a dot-separated list of Python NAMEs (ie. -# the same as a fully-qualified module name). -extension_name_re = re.compile(r'^[a-zA-Z_][a-zA-Z_0-9]*(\.[a-zA-Z_][a-zA-Z_0-9]*)*$') - - -def show_compilers(): - from ..ccompiler import show_compilers - - show_compilers() - - -class build_ext(Command): - - description = "build C/C++ extensions (compile/link to build directory)" - - # XXX thoughts on how to deal with complex command-line options like - # these, i.e. how to make it so fancy_getopt can suck them off the - # command line and make it look like setup.py defined the appropriate - # lists of tuples of what-have-you. - # - each command needs a callback to process its command-line options - # - Command.__init__() needs access to its share of the whole - # command line (must ultimately come from - # Distribution.parse_command_line()) - # - it then calls the current command class' option-parsing - # callback to deal with weird options like -D, which have to - # parse the option text and churn out some custom data - # structure - # - that data structure (in this case, a list of 2-tuples) - # will then be present in the command object by the time - # we get to finalize_options() (i.e. the constructor - # takes care of both command-line and client options - # in between initialize_options() and finalize_options()) - - sep_by = " (separated by '%s')" % os.pathsep - user_options = [ - ('build-lib=', 'b', "directory for compiled extension modules"), - ('build-temp=', 't', "directory for temporary files (build by-products)"), - ( - 'plat-name=', - 'p', - "platform name to cross-compile for, if supported " - "(default: %s)" % get_platform(), - ), - ( - 'inplace', - 'i', - "ignore build-lib and put compiled extensions into the source " - + "directory alongside your pure Python modules", - ), - ( - 'include-dirs=', - 'I', - "list of directories to search for header files" + sep_by, - ), - ('define=', 'D', "C preprocessor macros to define"), - ('undef=', 'U', "C preprocessor macros to undefine"), - ('libraries=', 'l', "external C libraries to link with"), - ( - 'library-dirs=', - 'L', - "directories to search for external C libraries" + sep_by, - ), - ('rpath=', 'R', "directories to search for shared C libraries at runtime"), - ('link-objects=', 'O', "extra explicit link objects to include in the link"), - ('debug', 'g', "compile/link with debugging information"), - ('force', 'f', "forcibly build everything (ignore file timestamps)"), - ('compiler=', 'c', "specify the compiler type"), - ('parallel=', 'j', "number of parallel build jobs"), - ('swig-cpp', None, "make SWIG create C++ files (default is C)"), - ('swig-opts=', None, "list of SWIG command line options"), - ('swig=', None, "path to the SWIG executable"), - ('user', None, "add user include, library and rpath"), - ] - - boolean_options = ['inplace', 'debug', 'force', 'swig-cpp', 'user'] - - help_options = [ - ('help-compiler', None, "list available compilers", show_compilers), - ] - - def initialize_options(self): - self.extensions = None - self.build_lib = None - self.plat_name = None - self.build_temp = None - self.inplace = 0 - self.package = None - - self.include_dirs = None - self.define = None - self.undef = None - self.libraries = None - self.library_dirs = None - self.rpath = None - self.link_objects = None - self.debug = None - self.force = None - self.compiler = None - self.swig = None - self.swig_cpp = None - self.swig_opts = None - self.user = None - self.parallel = None - - def finalize_options(self): # noqa: C901 - from distutils import sysconfig - - self.set_undefined_options( - 'build', - ('build_lib', 'build_lib'), - ('build_temp', 'build_temp'), - ('compiler', 'compiler'), - ('debug', 'debug'), - ('force', 'force'), - ('parallel', 'parallel'), - ('plat_name', 'plat_name'), - ) - - if self.package is None: - self.package = self.distribution.ext_package - - self.extensions = self.distribution.ext_modules - - # Make sure Python's include directories (for Python.h, pyconfig.h, - # etc.) are in the include search path. - py_include = sysconfig.get_python_inc() - plat_py_include = sysconfig.get_python_inc(plat_specific=1) - if self.include_dirs is None: - self.include_dirs = self.distribution.include_dirs or [] - if isinstance(self.include_dirs, str): - self.include_dirs = self.include_dirs.split(os.pathsep) - - # If in a virtualenv, add its include directory - # Issue 16116 - if sys.exec_prefix != sys.base_exec_prefix: - self.include_dirs.append(os.path.join(sys.exec_prefix, 'include')) - - # Put the Python "system" include dir at the end, so that - # any local include dirs take precedence. - self.include_dirs.extend(py_include.split(os.path.pathsep)) - if plat_py_include != py_include: - self.include_dirs.extend(plat_py_include.split(os.path.pathsep)) - - self.ensure_string_list('libraries') - self.ensure_string_list('link_objects') - - # Life is easier if we're not forever checking for None, so - # simplify these options to empty lists if unset - if self.libraries is None: - self.libraries = [] - if self.library_dirs is None: - self.library_dirs = [] - elif isinstance(self.library_dirs, str): - self.library_dirs = self.library_dirs.split(os.pathsep) - - if self.rpath is None: - self.rpath = [] - elif isinstance(self.rpath, str): - self.rpath = self.rpath.split(os.pathsep) - - # for extensions under windows use different directories - # for Release and Debug builds. - # also Python's library directory must be appended to library_dirs - if os.name == 'nt': - # the 'libs' directory is for binary installs - we assume that - # must be the *native* platform. But we don't really support - # cross-compiling via a binary install anyway, so we let it go. - self.library_dirs.append(os.path.join(sys.exec_prefix, 'libs')) - if sys.base_exec_prefix != sys.prefix: # Issue 16116 - self.library_dirs.append(os.path.join(sys.base_exec_prefix, 'libs')) - if self.debug: - self.build_temp = os.path.join(self.build_temp, "Debug") - else: - self.build_temp = os.path.join(self.build_temp, "Release") - - # Append the source distribution include and library directories, - # this allows distutils on windows to work in the source tree - self.include_dirs.append(os.path.dirname(get_config_h_filename())) - self.library_dirs.append(sys.base_exec_prefix) - - # Use the .lib files for the correct architecture - if self.plat_name == 'win32': - suffix = 'win32' - else: - # win-amd64 - suffix = self.plat_name[4:] - new_lib = os.path.join(sys.exec_prefix, 'PCbuild') - if suffix: - new_lib = os.path.join(new_lib, suffix) - self.library_dirs.append(new_lib) - - # For extensions under Cygwin, Python's library directory must be - # appended to library_dirs - if sys.platform[:6] == 'cygwin': - if not sysconfig.python_build: - # building third party extensions - self.library_dirs.append( - os.path.join( - sys.prefix, "lib", "python" + get_python_version(), "config" - ) - ) - else: - # building python standard extensions - self.library_dirs.append('.') - - # For building extensions with a shared Python library, - # Python's library directory must be appended to library_dirs - # See Issues: #1600860, #4366 - if sysconfig.get_config_var('Py_ENABLE_SHARED'): - if not sysconfig.python_build: - # building third party extensions - self.library_dirs.append(sysconfig.get_config_var('LIBDIR')) - else: - # building python standard extensions - self.library_dirs.append('.') - - # The argument parsing will result in self.define being a string, but - # it has to be a list of 2-tuples. All the preprocessor symbols - # specified by the 'define' option will be set to '1'. Multiple - # symbols can be separated with commas. - - if self.define: - defines = self.define.split(',') - self.define = [(symbol, '1') for symbol in defines] - - # The option for macros to undefine is also a string from the - # option parsing, but has to be a list. Multiple symbols can also - # be separated with commas here. - if self.undef: - self.undef = self.undef.split(',') - - if self.swig_opts is None: - self.swig_opts = [] - else: - self.swig_opts = self.swig_opts.split(' ') - - # Finally add the user include and library directories if requested - if self.user: - user_include = os.path.join(USER_BASE, "include") - user_lib = os.path.join(USER_BASE, "lib") - if os.path.isdir(user_include): - self.include_dirs.append(user_include) - if os.path.isdir(user_lib): - self.library_dirs.append(user_lib) - self.rpath.append(user_lib) - - if isinstance(self.parallel, str): - try: - self.parallel = int(self.parallel) - except ValueError: - raise DistutilsOptionError("parallel should be an integer") - - def run(self): # noqa: C901 - from ..ccompiler import new_compiler - - # 'self.extensions', as supplied by setup.py, is a list of - # Extension instances. See the documentation for Extension (in - # distutils.extension) for details. - # - # For backwards compatibility with Distutils 0.8.2 and earlier, we - # also allow the 'extensions' list to be a list of tuples: - # (ext_name, build_info) - # where build_info is a dictionary containing everything that - # Extension instances do except the name, with a few things being - # differently named. We convert these 2-tuples to Extension - # instances as needed. - - if not self.extensions: - return - - # If we were asked to build any C/C++ libraries, make sure that the - # directory where we put them is in the library search path for - # linking extensions. - if self.distribution.has_c_libraries(): - build_clib = self.get_finalized_command('build_clib') - self.libraries.extend(build_clib.get_library_names() or []) - self.library_dirs.append(build_clib.build_clib) - - # Setup the CCompiler object that we'll use to do all the - # compiling and linking - self.compiler = new_compiler( - compiler=self.compiler, - verbose=self.verbose, - dry_run=self.dry_run, - force=self.force, - ) - customize_compiler(self.compiler) - # If we are cross-compiling, init the compiler now (if we are not - # cross-compiling, init would not hurt, but people may rely on - # late initialization of compiler even if they shouldn't...) - if os.name == 'nt' and self.plat_name != get_platform(): - self.compiler.initialize(self.plat_name) - - # And make sure that any compile/link-related options (which might - # come from the command-line or from the setup script) are set in - # that CCompiler object -- that way, they automatically apply to - # all compiling and linking done here. - if self.include_dirs is not None: - self.compiler.set_include_dirs(self.include_dirs) - if self.define is not None: - # 'define' option is a list of (name,value) tuples - for (name, value) in self.define: - self.compiler.define_macro(name, value) - if self.undef is not None: - for macro in self.undef: - self.compiler.undefine_macro(macro) - if self.libraries is not None: - self.compiler.set_libraries(self.libraries) - if self.library_dirs is not None: - self.compiler.set_library_dirs(self.library_dirs) - if self.rpath is not None: - self.compiler.set_runtime_library_dirs(self.rpath) - if self.link_objects is not None: - self.compiler.set_link_objects(self.link_objects) - - # Now actually compile and link everything. - self.build_extensions() - - def check_extensions_list(self, extensions): # noqa: C901 - """Ensure that the list of extensions (presumably provided as a - command option 'extensions') is valid, i.e. it is a list of - Extension objects. We also support the old-style list of 2-tuples, - where the tuples are (ext_name, build_info), which are converted to - Extension instances here. - - Raise DistutilsSetupError if the structure is invalid anywhere; - just returns otherwise. - """ - if not isinstance(extensions, list): - raise DistutilsSetupError( - "'ext_modules' option must be a list of Extension instances" - ) - - for i, ext in enumerate(extensions): - if isinstance(ext, Extension): - continue # OK! (assume type-checking done - # by Extension constructor) - - if not isinstance(ext, tuple) or len(ext) != 2: - raise DistutilsSetupError( - "each element of 'ext_modules' option must be an " - "Extension instance or 2-tuple" - ) - - ext_name, build_info = ext - - log.warning( - "old-style (ext_name, build_info) tuple found in " - "ext_modules for extension '%s' " - "-- please convert to Extension instance", - ext_name, - ) - - if not (isinstance(ext_name, str) and extension_name_re.match(ext_name)): - raise DistutilsSetupError( - "first element of each tuple in 'ext_modules' " - "must be the extension name (a string)" - ) - - if not isinstance(build_info, dict): - raise DistutilsSetupError( - "second element of each tuple in 'ext_modules' " - "must be a dictionary (build info)" - ) - - # OK, the (ext_name, build_info) dict is type-safe: convert it - # to an Extension instance. - ext = Extension(ext_name, build_info['sources']) - - # Easy stuff: one-to-one mapping from dict elements to - # instance attributes. - for key in ( - 'include_dirs', - 'library_dirs', - 'libraries', - 'extra_objects', - 'extra_compile_args', - 'extra_link_args', - ): - val = build_info.get(key) - if val is not None: - setattr(ext, key, val) - - # Medium-easy stuff: same syntax/semantics, different names. - ext.runtime_library_dirs = build_info.get('rpath') - if 'def_file' in build_info: - log.warning( - "'def_file' element of build info dict " "no longer supported" - ) - - # Non-trivial stuff: 'macros' split into 'define_macros' - # and 'undef_macros'. - macros = build_info.get('macros') - if macros: - ext.define_macros = [] - ext.undef_macros = [] - for macro in macros: - if not (isinstance(macro, tuple) and len(macro) in (1, 2)): - raise DistutilsSetupError( - "'macros' element of build info dict " - "must be 1- or 2-tuple" - ) - if len(macro) == 1: - ext.undef_macros.append(macro[0]) - elif len(macro) == 2: - ext.define_macros.append(macro) - - extensions[i] = ext - - def get_source_files(self): - self.check_extensions_list(self.extensions) - filenames = [] - - # Wouldn't it be neat if we knew the names of header files too... - for ext in self.extensions: - filenames.extend(ext.sources) - return filenames - - def get_outputs(self): - # Sanity check the 'extensions' list -- can't assume this is being - # done in the same run as a 'build_extensions()' call (in fact, we - # can probably assume that it *isn't*!). - self.check_extensions_list(self.extensions) - - # And build the list of output (built) filenames. Note that this - # ignores the 'inplace' flag, and assumes everything goes in the - # "build" tree. - outputs = [] - for ext in self.extensions: - outputs.append(self.get_ext_fullpath(ext.name)) - return outputs - - def build_extensions(self): - # First, sanity-check the 'extensions' list - self.check_extensions_list(self.extensions) - if self.parallel: - self._build_extensions_parallel() - else: - self._build_extensions_serial() - - def _build_extensions_parallel(self): - workers = self.parallel - if self.parallel is True: - workers = os.cpu_count() # may return None - try: - from concurrent.futures import ThreadPoolExecutor - except ImportError: - workers = None - - if workers is None: - self._build_extensions_serial() - return - - with ThreadPoolExecutor(max_workers=workers) as executor: - futures = [ - executor.submit(self.build_extension, ext) for ext in self.extensions - ] - for ext, fut in zip(self.extensions, futures): - with self._filter_build_errors(ext): - fut.result() - - def _build_extensions_serial(self): - for ext in self.extensions: - with self._filter_build_errors(ext): - self.build_extension(ext) - - @contextlib.contextmanager - def _filter_build_errors(self, ext): - try: - yield - except (CCompilerError, DistutilsError, CompileError) as e: - if not ext.optional: - raise - self.warn('building extension "{}" failed: {}'.format(ext.name, e)) - - def build_extension(self, ext): - sources = ext.sources - if sources is None or not isinstance(sources, (list, tuple)): - raise DistutilsSetupError( - "in 'ext_modules' option (extension '%s'), " - "'sources' must be present and must be " - "a list of source filenames" % ext.name - ) - # sort to make the resulting .so file build reproducible - sources = sorted(sources) - - ext_path = self.get_ext_fullpath(ext.name) - depends = sources + ext.depends - if not (self.force or newer_group(depends, ext_path, 'newer')): - log.debug("skipping '%s' extension (up-to-date)", ext.name) - return - else: - log.info("building '%s' extension", ext.name) - - # First, scan the sources for SWIG definition files (.i), run - # SWIG on 'em to create .c files, and modify the sources list - # accordingly. - sources = self.swig_sources(sources, ext) - - # Next, compile the source code to object files. - - # XXX not honouring 'define_macros' or 'undef_macros' -- the - # CCompiler API needs to change to accommodate this, and I - # want to do one thing at a time! - - # Two possible sources for extra compiler arguments: - # - 'extra_compile_args' in Extension object - # - CFLAGS environment variable (not particularly - # elegant, but people seem to expect it and I - # guess it's useful) - # The environment variable should take precedence, and - # any sensible compiler will give precedence to later - # command line args. Hence we combine them in order: - extra_args = ext.extra_compile_args or [] - - macros = ext.define_macros[:] - for undef in ext.undef_macros: - macros.append((undef,)) - - objects = self.compiler.compile( - sources, - output_dir=self.build_temp, - macros=macros, - include_dirs=ext.include_dirs, - debug=self.debug, - extra_postargs=extra_args, - depends=ext.depends, - ) - - # XXX outdated variable, kept here in case third-part code - # needs it. - self._built_objects = objects[:] - - # Now link the object files together into a "shared object" -- - # of course, first we have to figure out all the other things - # that go into the mix. - if ext.extra_objects: - objects.extend(ext.extra_objects) - extra_args = ext.extra_link_args or [] - - # Detect target language, if not provided - language = ext.language or self.compiler.detect_language(sources) - - self.compiler.link_shared_object( - objects, - ext_path, - libraries=self.get_libraries(ext), - library_dirs=ext.library_dirs, - runtime_library_dirs=ext.runtime_library_dirs, - extra_postargs=extra_args, - export_symbols=self.get_export_symbols(ext), - debug=self.debug, - build_temp=self.build_temp, - target_lang=language, - ) - - def swig_sources(self, sources, extension): - """Walk the list of source files in 'sources', looking for SWIG - interface (.i) files. Run SWIG on all that are found, and - return a modified 'sources' list with SWIG source files replaced - by the generated C (or C++) files. - """ - new_sources = [] - swig_sources = [] - swig_targets = {} - - # XXX this drops generated C/C++ files into the source tree, which - # is fine for developers who want to distribute the generated - # source -- but there should be an option to put SWIG output in - # the temp dir. - - if self.swig_cpp: - log.warning("--swig-cpp is deprecated - use --swig-opts=-c++") - - if ( - self.swig_cpp - or ('-c++' in self.swig_opts) - or ('-c++' in extension.swig_opts) - ): - target_ext = '.cpp' - else: - target_ext = '.c' - - for source in sources: - (base, ext) = os.path.splitext(source) - if ext == ".i": # SWIG interface file - new_sources.append(base + '_wrap' + target_ext) - swig_sources.append(source) - swig_targets[source] = new_sources[-1] - else: - new_sources.append(source) - - if not swig_sources: - return new_sources - - swig = self.swig or self.find_swig() - swig_cmd = [swig, "-python"] - swig_cmd.extend(self.swig_opts) - if self.swig_cpp: - swig_cmd.append("-c++") - - # Do not override commandline arguments - if not self.swig_opts: - for o in extension.swig_opts: - swig_cmd.append(o) - - for source in swig_sources: - target = swig_targets[source] - log.info("swigging %s to %s", source, target) - self.spawn(swig_cmd + ["-o", target, source]) - - return new_sources - - def find_swig(self): - """Return the name of the SWIG executable. On Unix, this is - just "swig" -- it should be in the PATH. Tries a bit harder on - Windows. - """ - if os.name == "posix": - return "swig" - elif os.name == "nt": - # Look for SWIG in its standard installation directory on - # Windows (or so I presume!). If we find it there, great; - # if not, act like Unix and assume it's in the PATH. - for vers in ("1.3", "1.2", "1.1"): - fn = os.path.join("c:\\swig%s" % vers, "swig.exe") - if os.path.isfile(fn): - return fn - else: - return "swig.exe" - else: - raise DistutilsPlatformError( - "I don't know how to find (much less run) SWIG " - "on platform '%s'" % os.name - ) - - # -- Name generators ----------------------------------------------- - # (extension names, filenames, whatever) - def get_ext_fullpath(self, ext_name): - """Returns the path of the filename for a given extension. - - The file is located in `build_lib` or directly in the package - (inplace option). - """ - fullname = self.get_ext_fullname(ext_name) - modpath = fullname.split('.') - filename = self.get_ext_filename(modpath[-1]) - - if not self.inplace: - # no further work needed - # returning : - # build_dir/package/path/filename - filename = os.path.join(*modpath[:-1] + [filename]) - return os.path.join(self.build_lib, filename) - - # the inplace option requires to find the package directory - # using the build_py command for that - package = '.'.join(modpath[0:-1]) - build_py = self.get_finalized_command('build_py') - package_dir = os.path.abspath(build_py.get_package_dir(package)) - - # returning - # package_dir/filename - return os.path.join(package_dir, filename) - - def get_ext_fullname(self, ext_name): - """Returns the fullname of a given extension name. - - Adds the `package.` prefix""" - if self.package is None: - return ext_name - else: - return self.package + '.' + ext_name - - def get_ext_filename(self, ext_name): - r"""Convert the name of an extension (eg. "foo.bar") into the name - of the file from which it will be loaded (eg. "foo/bar.so", or - "foo\bar.pyd"). - """ - from ..sysconfig import get_config_var - - ext_path = ext_name.split('.') - ext_suffix = get_config_var('EXT_SUFFIX') - return os.path.join(*ext_path) + ext_suffix - - def get_export_symbols(self, ext): - """Return the list of symbols that a shared extension has to - export. This either uses 'ext.export_symbols' or, if it's not - provided, "PyInit_" + module_name. Only relevant on Windows, where - the .pyd file (DLL) must export the module "PyInit_" function. - """ - name = ext.name.split('.')[-1] - try: - # Unicode module name support as defined in PEP-489 - # https://www.python.org/dev/peps/pep-0489/#export-hook-name - name.encode('ascii') - except UnicodeEncodeError: - suffix = 'U_' + name.encode('punycode').replace(b'-', b'_').decode('ascii') - else: - suffix = "_" + name - - initfunc_name = "PyInit" + suffix - if initfunc_name not in ext.export_symbols: - ext.export_symbols.append(initfunc_name) - return ext.export_symbols - - def get_libraries(self, ext): # noqa: C901 - """Return the list of libraries to link against when building a - shared extension. On most platforms, this is just 'ext.libraries'; - on Windows, we add the Python library (eg. python20.dll). - """ - # The python library is always needed on Windows. For MSVC, this - # is redundant, since the library is mentioned in a pragma in - # pyconfig.h that MSVC groks. The other Windows compilers all seem - # to need it mentioned explicitly, though, so that's what we do. - # Append '_d' to the python import library on debug builds. - if sys.platform == "win32": - from .._msvccompiler import MSVCCompiler - - if not isinstance(self.compiler, MSVCCompiler): - template = "python%d%d" - if self.debug: - template = template + '_d' - pythonlib = template % ( - sys.hexversion >> 24, - (sys.hexversion >> 16) & 0xFF, - ) - # don't extend ext.libraries, it may be shared with other - # extensions, it is a reference to the original list - return ext.libraries + [pythonlib] - else: - # On Android only the main executable and LD_PRELOADs are considered - # to be RTLD_GLOBAL, all the dependencies of the main executable - # remain RTLD_LOCAL and so the shared libraries must be linked with - # libpython when python is built with a shared python library (issue - # bpo-21536). - # On Cygwin (and if required, other POSIX-like platforms based on - # Windows like MinGW) it is simply necessary that all symbols in - # shared libraries are resolved at link time. - from ..sysconfig import get_config_var - - link_libpython = False - if get_config_var('Py_ENABLE_SHARED'): - # A native build on an Android device or on Cygwin - if hasattr(sys, 'getandroidapilevel'): - link_libpython = True - elif sys.platform == 'cygwin': - link_libpython = True - elif '_PYTHON_HOST_PLATFORM' in os.environ: - # We are cross-compiling for one of the relevant platforms - if get_config_var('ANDROID_API_LEVEL') != 0: - link_libpython = True - elif get_config_var('MACHDEP') == 'cygwin': - link_libpython = True - - if link_libpython: - ldversion = get_config_var('LDVERSION') - return ext.libraries + ['python' + ldversion] - - return ext.libraries + py37compat.pythonlib() diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/build_py.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/build_py.py deleted file mode 100755 index 9f78324..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/build_py.py +++ /dev/null @@ -1,407 +0,0 @@ -"""distutils.command.build_py - -Implements the Distutils 'build_py' command.""" - -import os -import importlib.util -import sys -import glob - -from ..core import Command -from ..errors import DistutilsOptionError, DistutilsFileError -from ..util import convert_path -from distutils._log import log - - -class build_py(Command): - - description = "\"build\" pure Python modules (copy to build directory)" - - user_options = [ - ('build-lib=', 'd', "directory to \"build\" (copy) to"), - ('compile', 'c', "compile .py to .pyc"), - ('no-compile', None, "don't compile .py files [default]"), - ( - 'optimize=', - 'O', - "also compile with optimization: -O1 for \"python -O\", " - "-O2 for \"python -OO\", and -O0 to disable [default: -O0]", - ), - ('force', 'f', "forcibly build everything (ignore file timestamps)"), - ] - - boolean_options = ['compile', 'force'] - negative_opt = {'no-compile': 'compile'} - - def initialize_options(self): - self.build_lib = None - self.py_modules = None - self.package = None - self.package_data = None - self.package_dir = None - self.compile = 0 - self.optimize = 0 - self.force = None - - def finalize_options(self): - self.set_undefined_options( - 'build', ('build_lib', 'build_lib'), ('force', 'force') - ) - - # Get the distribution options that are aliases for build_py - # options -- list of packages and list of modules. - self.packages = self.distribution.packages - self.py_modules = self.distribution.py_modules - self.package_data = self.distribution.package_data - self.package_dir = {} - if self.distribution.package_dir: - for name, path in self.distribution.package_dir.items(): - self.package_dir[name] = convert_path(path) - self.data_files = self.get_data_files() - - # Ick, copied straight from install_lib.py (fancy_getopt needs a - # type system! Hell, *everything* needs a type system!!!) - if not isinstance(self.optimize, int): - try: - self.optimize = int(self.optimize) - assert 0 <= self.optimize <= 2 - except (ValueError, AssertionError): - raise DistutilsOptionError("optimize must be 0, 1, or 2") - - def run(self): - # XXX copy_file by default preserves atime and mtime. IMHO this is - # the right thing to do, but perhaps it should be an option -- in - # particular, a site administrator might want installed files to - # reflect the time of installation rather than the last - # modification time before the installed release. - - # XXX copy_file by default preserves mode, which appears to be the - # wrong thing to do: if a file is read-only in the working - # directory, we want it to be installed read/write so that the next - # installation of the same module distribution can overwrite it - # without problems. (This might be a Unix-specific issue.) Thus - # we turn off 'preserve_mode' when copying to the build directory, - # since the build directory is supposed to be exactly what the - # installation will look like (ie. we preserve mode when - # installing). - - # Two options control which modules will be installed: 'packages' - # and 'py_modules'. The former lets us work with whole packages, not - # specifying individual modules at all; the latter is for - # specifying modules one-at-a-time. - - if self.py_modules: - self.build_modules() - if self.packages: - self.build_packages() - self.build_package_data() - - self.byte_compile(self.get_outputs(include_bytecode=0)) - - def get_data_files(self): - """Generate list of '(package,src_dir,build_dir,filenames)' tuples""" - data = [] - if not self.packages: - return data - for package in self.packages: - # Locate package source directory - src_dir = self.get_package_dir(package) - - # Compute package build directory - build_dir = os.path.join(*([self.build_lib] + package.split('.'))) - - # Length of path to strip from found files - plen = 0 - if src_dir: - plen = len(src_dir) + 1 - - # Strip directory from globbed filenames - filenames = [file[plen:] for file in self.find_data_files(package, src_dir)] - data.append((package, src_dir, build_dir, filenames)) - return data - - def find_data_files(self, package, src_dir): - """Return filenames for package's data files in 'src_dir'""" - globs = self.package_data.get('', []) + self.package_data.get(package, []) - files = [] - for pattern in globs: - # Each pattern has to be converted to a platform-specific path - filelist = glob.glob( - os.path.join(glob.escape(src_dir), convert_path(pattern)) - ) - # Files that match more than one pattern are only added once - files.extend( - [fn for fn in filelist if fn not in files and os.path.isfile(fn)] - ) - return files - - def build_package_data(self): - """Copy data files into build directory""" - for package, src_dir, build_dir, filenames in self.data_files: - for filename in filenames: - target = os.path.join(build_dir, filename) - self.mkpath(os.path.dirname(target)) - self.copy_file( - os.path.join(src_dir, filename), target, preserve_mode=False - ) - - def get_package_dir(self, package): - """Return the directory, relative to the top of the source - distribution, where package 'package' should be found - (at least according to the 'package_dir' option, if any).""" - path = package.split('.') - - if not self.package_dir: - if path: - return os.path.join(*path) - else: - return '' - else: - tail = [] - while path: - try: - pdir = self.package_dir['.'.join(path)] - except KeyError: - tail.insert(0, path[-1]) - del path[-1] - else: - tail.insert(0, pdir) - return os.path.join(*tail) - else: - # Oops, got all the way through 'path' without finding a - # match in package_dir. If package_dir defines a directory - # for the root (nameless) package, then fallback on it; - # otherwise, we might as well have not consulted - # package_dir at all, as we just use the directory implied - # by 'tail' (which should be the same as the original value - # of 'path' at this point). - pdir = self.package_dir.get('') - if pdir is not None: - tail.insert(0, pdir) - - if tail: - return os.path.join(*tail) - else: - return '' - - def check_package(self, package, package_dir): - # Empty dir name means current directory, which we can probably - # assume exists. Also, os.path.exists and isdir don't know about - # my "empty string means current dir" convention, so we have to - # circumvent them. - if package_dir != "": - if not os.path.exists(package_dir): - raise DistutilsFileError( - "package directory '%s' does not exist" % package_dir - ) - if not os.path.isdir(package_dir): - raise DistutilsFileError( - "supposed package directory '%s' exists, " - "but is not a directory" % package_dir - ) - - # Directories without __init__.py are namespace packages (PEP 420). - if package: - init_py = os.path.join(package_dir, "__init__.py") - if os.path.isfile(init_py): - return init_py - - # Either not in a package at all (__init__.py not expected), or - # __init__.py doesn't exist -- so don't return the filename. - return None - - def check_module(self, module, module_file): - if not os.path.isfile(module_file): - log.warning("file %s (for module %s) not found", module_file, module) - return False - else: - return True - - def find_package_modules(self, package, package_dir): - self.check_package(package, package_dir) - module_files = glob.glob(os.path.join(glob.escape(package_dir), "*.py")) - modules = [] - setup_script = os.path.abspath(self.distribution.script_name) - - for f in module_files: - abs_f = os.path.abspath(f) - if abs_f != setup_script: - module = os.path.splitext(os.path.basename(f))[0] - modules.append((package, module, f)) - else: - self.debug_print("excluding %s" % setup_script) - return modules - - def find_modules(self): - """Finds individually-specified Python modules, ie. those listed by - module name in 'self.py_modules'. Returns a list of tuples (package, - module_base, filename): 'package' is a tuple of the path through - package-space to the module; 'module_base' is the bare (no - packages, no dots) module name, and 'filename' is the path to the - ".py" file (relative to the distribution root) that implements the - module. - """ - # Map package names to tuples of useful info about the package: - # (package_dir, checked) - # package_dir - the directory where we'll find source files for - # this package - # checked - true if we have checked that the package directory - # is valid (exists, contains __init__.py, ... ?) - packages = {} - - # List of (package, module, filename) tuples to return - modules = [] - - # We treat modules-in-packages almost the same as toplevel modules, - # just the "package" for a toplevel is empty (either an empty - # string or empty list, depending on context). Differences: - # - don't check for __init__.py in directory for empty package - for module in self.py_modules: - path = module.split('.') - package = '.'.join(path[0:-1]) - module_base = path[-1] - - try: - (package_dir, checked) = packages[package] - except KeyError: - package_dir = self.get_package_dir(package) - checked = 0 - - if not checked: - init_py = self.check_package(package, package_dir) - packages[package] = (package_dir, 1) - if init_py: - modules.append((package, "__init__", init_py)) - - # XXX perhaps we should also check for just .pyc files - # (so greedy closed-source bastards can distribute Python - # modules too) - module_file = os.path.join(package_dir, module_base + ".py") - if not self.check_module(module, module_file): - continue - - modules.append((package, module_base, module_file)) - - return modules - - def find_all_modules(self): - """Compute the list of all modules that will be built, whether - they are specified one-module-at-a-time ('self.py_modules') or - by whole packages ('self.packages'). Return a list of tuples - (package, module, module_file), just like 'find_modules()' and - 'find_package_modules()' do.""" - modules = [] - if self.py_modules: - modules.extend(self.find_modules()) - if self.packages: - for package in self.packages: - package_dir = self.get_package_dir(package) - m = self.find_package_modules(package, package_dir) - modules.extend(m) - return modules - - def get_source_files(self): - return [module[-1] for module in self.find_all_modules()] - - def get_module_outfile(self, build_dir, package, module): - outfile_path = [build_dir] + list(package) + [module + ".py"] - return os.path.join(*outfile_path) - - def get_outputs(self, include_bytecode=1): - modules = self.find_all_modules() - outputs = [] - for (package, module, module_file) in modules: - package = package.split('.') - filename = self.get_module_outfile(self.build_lib, package, module) - outputs.append(filename) - if include_bytecode: - if self.compile: - outputs.append( - importlib.util.cache_from_source(filename, optimization='') - ) - if self.optimize > 0: - outputs.append( - importlib.util.cache_from_source( - filename, optimization=self.optimize - ) - ) - - outputs += [ - os.path.join(build_dir, filename) - for package, src_dir, build_dir, filenames in self.data_files - for filename in filenames - ] - - return outputs - - def build_module(self, module, module_file, package): - if isinstance(package, str): - package = package.split('.') - elif not isinstance(package, (list, tuple)): - raise TypeError( - "'package' must be a string (dot-separated), list, or tuple" - ) - - # Now put the module source file into the "build" area -- this is - # easy, we just copy it somewhere under self.build_lib (the build - # directory for Python source). - outfile = self.get_module_outfile(self.build_lib, package, module) - dir = os.path.dirname(outfile) - self.mkpath(dir) - return self.copy_file(module_file, outfile, preserve_mode=0) - - def build_modules(self): - modules = self.find_modules() - for (package, module, module_file) in modules: - # Now "build" the module -- ie. copy the source file to - # self.build_lib (the build directory for Python source). - # (Actually, it gets copied to the directory for this package - # under self.build_lib.) - self.build_module(module, module_file, package) - - def build_packages(self): - for package in self.packages: - # Get list of (package, module, module_file) tuples based on - # scanning the package directory. 'package' is only included - # in the tuple so that 'find_modules()' and - # 'find_package_tuples()' have a consistent interface; it's - # ignored here (apart from a sanity check). Also, 'module' is - # the *unqualified* module name (ie. no dots, no package -- we - # already know its package!), and 'module_file' is the path to - # the .py file, relative to the current directory - # (ie. including 'package_dir'). - package_dir = self.get_package_dir(package) - modules = self.find_package_modules(package, package_dir) - - # Now loop over the modules we found, "building" each one (just - # copy it to self.build_lib). - for (package_, module, module_file) in modules: - assert package == package_ - self.build_module(module, module_file, package) - - def byte_compile(self, files): - if sys.dont_write_bytecode: - self.warn('byte-compiling is disabled, skipping.') - return - - from ..util import byte_compile - - prefix = self.build_lib - if prefix[-1] != os.sep: - prefix = prefix + os.sep - - # XXX this code is essentially the same as the 'byte_compile() - # method of the "install_lib" command, except for the determination - # of the 'prefix' string. Hmmm. - if self.compile: - byte_compile( - files, optimize=0, force=self.force, prefix=prefix, dry_run=self.dry_run - ) - if self.optimize > 0: - byte_compile( - files, - optimize=self.optimize, - force=self.force, - prefix=prefix, - dry_run=self.dry_run, - ) diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/build_scripts.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/build_scripts.py deleted file mode 100755 index 87174f6..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/build_scripts.py +++ /dev/null @@ -1,173 +0,0 @@ -"""distutils.command.build_scripts - -Implements the Distutils 'build_scripts' command.""" - -import os -import re -from stat import ST_MODE -from distutils import sysconfig -from ..core import Command -from ..dep_util import newer -from ..util import convert_path -from distutils._log import log -import tokenize - -shebang_pattern = re.compile('^#!.*python[0-9.]*([ \t].*)?$') -""" -Pattern matching a Python interpreter indicated in first line of a script. -""" - -# for Setuptools compatibility -first_line_re = shebang_pattern - - -class build_scripts(Command): - - description = "\"build\" scripts (copy and fixup #! line)" - - user_options = [ - ('build-dir=', 'd', "directory to \"build\" (copy) to"), - ('force', 'f', "forcibly build everything (ignore file timestamps"), - ('executable=', 'e', "specify final destination interpreter path"), - ] - - boolean_options = ['force'] - - def initialize_options(self): - self.build_dir = None - self.scripts = None - self.force = None - self.executable = None - - def finalize_options(self): - self.set_undefined_options( - 'build', - ('build_scripts', 'build_dir'), - ('force', 'force'), - ('executable', 'executable'), - ) - self.scripts = self.distribution.scripts - - def get_source_files(self): - return self.scripts - - def run(self): - if not self.scripts: - return - self.copy_scripts() - - def copy_scripts(self): - """ - Copy each script listed in ``self.scripts``. - - If a script is marked as a Python script (first line matches - 'shebang_pattern', i.e. starts with ``#!`` and contains - "python"), then adjust in the copy the first line to refer to - the current Python interpreter. - """ - self.mkpath(self.build_dir) - outfiles = [] - updated_files = [] - for script in self.scripts: - self._copy_script(script, outfiles, updated_files) - - self._change_modes(outfiles) - - return outfiles, updated_files - - def _copy_script(self, script, outfiles, updated_files): # noqa: C901 - shebang_match = None - script = convert_path(script) - outfile = os.path.join(self.build_dir, os.path.basename(script)) - outfiles.append(outfile) - - if not self.force and not newer(script, outfile): - log.debug("not copying %s (up-to-date)", script) - return - - # Always open the file, but ignore failures in dry-run mode - # in order to attempt to copy directly. - try: - f = tokenize.open(script) - except OSError: - if not self.dry_run: - raise - f = None - else: - first_line = f.readline() - if not first_line: - self.warn("%s is an empty file (skipping)" % script) - return - - shebang_match = shebang_pattern.match(first_line) - - updated_files.append(outfile) - if shebang_match: - log.info("copying and adjusting %s -> %s", script, self.build_dir) - if not self.dry_run: - if not sysconfig.python_build: - executable = self.executable - else: - executable = os.path.join( - sysconfig.get_config_var("BINDIR"), - "python%s%s" - % ( - sysconfig.get_config_var("VERSION"), - sysconfig.get_config_var("EXE"), - ), - ) - post_interp = shebang_match.group(1) or '' - shebang = "#!" + executable + post_interp + "\n" - self._validate_shebang(shebang, f.encoding) - with open(outfile, "w", encoding=f.encoding) as outf: - outf.write(shebang) - outf.writelines(f.readlines()) - if f: - f.close() - else: - if f: - f.close() - self.copy_file(script, outfile) - - def _change_modes(self, outfiles): - if os.name != 'posix': - return - - for file in outfiles: - self._change_mode(file) - - def _change_mode(self, file): - if self.dry_run: - log.info("changing mode of %s", file) - return - - oldmode = os.stat(file)[ST_MODE] & 0o7777 - newmode = (oldmode | 0o555) & 0o7777 - if newmode != oldmode: - log.info("changing mode of %s from %o to %o", file, oldmode, newmode) - os.chmod(file, newmode) - - @staticmethod - def _validate_shebang(shebang, encoding): - # Python parser starts to read a script using UTF-8 until - # it gets a #coding:xxx cookie. The shebang has to be the - # first line of a file, the #coding:xxx cookie cannot be - # written before. So the shebang has to be encodable to - # UTF-8. - try: - shebang.encode('utf-8') - except UnicodeEncodeError: - raise ValueError( - "The shebang ({!r}) is not encodable " "to utf-8".format(shebang) - ) - - # If the script is encoded to a custom encoding (use a - # #coding:xxx cookie), the shebang has to be encodable to - # the script encoding too. - try: - shebang.encode(encoding) - except UnicodeEncodeError: - raise ValueError( - "The shebang ({!r}) is not encodable " - "to the script encoding ({})".format(shebang, encoding) - ) diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/check.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/check.py deleted file mode 100755 index 575e49f..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/check.py +++ /dev/null @@ -1,151 +0,0 @@ -"""distutils.command.check - -Implements the Distutils 'check' command. -""" -import contextlib - -from ..core import Command -from ..errors import DistutilsSetupError - -with contextlib.suppress(ImportError): - import docutils.utils - import docutils.parsers.rst - import docutils.frontend - import docutils.nodes - - class SilentReporter(docutils.utils.Reporter): - def __init__( - self, - source, - report_level, - halt_level, - stream=None, - debug=0, - encoding='ascii', - error_handler='replace', - ): - self.messages = [] - super().__init__( - source, report_level, halt_level, stream, debug, encoding, error_handler - ) - - def system_message(self, level, message, *children, **kwargs): - self.messages.append((level, message, children, kwargs)) - return docutils.nodes.system_message( - message, level=level, type=self.levels[level], *children, **kwargs - ) - - -class check(Command): - """This command checks the meta-data of the package.""" - - description = "perform some checks on the package" - user_options = [ - ('metadata', 'm', 'Verify meta-data'), - ( - 'restructuredtext', - 'r', - ( - 'Checks if long string meta-data syntax ' - 'are reStructuredText-compliant' - ), - ), - ('strict', 's', 'Will exit with an error if a check fails'), - ] - - boolean_options = ['metadata', 'restructuredtext', 'strict'] - - def initialize_options(self): - """Sets default values for options.""" - self.restructuredtext = 0 - self.metadata = 1 - self.strict = 0 - self._warnings = 0 - - def finalize_options(self): - pass - - def warn(self, msg): - """Counts the number of warnings that occurs.""" - self._warnings += 1 - return Command.warn(self, msg) - - def run(self): - """Runs the command.""" - # perform the various tests - if self.metadata: - self.check_metadata() - if self.restructuredtext: - if 'docutils' in globals(): - try: - self.check_restructuredtext() - except TypeError as exc: - raise DistutilsSetupError(str(exc)) - elif self.strict: - raise DistutilsSetupError('The docutils package is needed.') - - # let's raise an error in strict mode, if we have at least - # one warning - if self.strict and self._warnings > 0: - raise DistutilsSetupError('Please correct your package.') - - def check_metadata(self): - """Ensures that all required elements of meta-data are supplied. - - Required fields: - name, version - - Warns if any are missing. - """ - metadata = self.distribution.metadata - - missing = [] - for attr in 'name', 'version': - if not getattr(metadata, attr, None): - missing.append(attr) - - if missing: - self.warn("missing required meta-data: %s" % ', '.join(missing)) - - def check_restructuredtext(self): - """Checks if the long string fields are reST-compliant.""" - data = self.distribution.get_long_description() - for warning in self._check_rst_data(data): - line = warning[-1].get('line') - if line is None: - warning = warning[1] - else: - warning = '{} (line {})'.format(warning[1], line) - self.warn(warning) - - def _check_rst_data(self, data): - """Returns warnings when the provided data doesn't compile.""" - # the include and csv_table directives need this to be a path - source_path = self.distribution.script_name or 'setup.py' - parser = docutils.parsers.rst.Parser() - settings = docutils.frontend.OptionParser( - components=(docutils.parsers.rst.Parser,) - ).get_default_values() - settings.tab_width = 4 - settings.pep_references = None - settings.rfc_references = None - reporter = SilentReporter( - source_path, - settings.report_level, - settings.halt_level, - stream=settings.warning_stream, - debug=settings.debug, - encoding=settings.error_encoding, - error_handler=settings.error_encoding_error_handler, - ) - - document = docutils.nodes.document(settings, reporter, source=source_path) - document.note_source(source_path, -1) - try: - parser.parse(data, document) - except AttributeError as e: - reporter.messages.append( - (-1, 'Could not finish the parsing: %s.' % e, '', {}) - ) - - return reporter.messages diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/clean.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/clean.py deleted file mode 100755 index d6eb3eb..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/clean.py +++ /dev/null @@ -1,76 +0,0 @@ -"""distutils.command.clean - -Implements the Distutils 'clean' command.""" - -# contributed by Bastian Kleineidam , added 2000-03-18 - -import os -from ..core import Command -from ..dir_util import remove_tree -from distutils._log import log - - -class clean(Command): - - description = "clean up temporary files from 'build' command" - user_options = [ - ('build-base=', 'b', "base build directory (default: 'build.build-base')"), - ( - 'build-lib=', - None, - "build directory for all modules (default: 'build.build-lib')", - ), - ('build-temp=', 't', "temporary build directory (default: 'build.build-temp')"), - ( - 'build-scripts=', - None, - "build directory for scripts (default: 'build.build-scripts')", - ), - ('bdist-base=', None, "temporary directory for built distributions"), - ('all', 'a', "remove all build output, not just temporary by-products"), - ] - - boolean_options = ['all'] - - def initialize_options(self): - self.build_base = None - self.build_lib = None - self.build_temp = None - self.build_scripts = None - self.bdist_base = None - self.all = None - - def finalize_options(self): - self.set_undefined_options( - 'build', - ('build_base', 'build_base'), - ('build_lib', 'build_lib'), - ('build_scripts', 'build_scripts'), - ('build_temp', 'build_temp'), - ) - self.set_undefined_options('bdist', ('bdist_base', 'bdist_base')) - - def run(self): - # remove the build/temp. directory (unless it's already - # gone) - if os.path.exists(self.build_temp): - remove_tree(self.build_temp, dry_run=self.dry_run) - else: - log.debug("'%s' does not exist -- can't clean it", self.build_temp) - - if self.all: - # remove build directories - for directory in (self.build_lib, self.bdist_base, self.build_scripts): - if os.path.exists(directory): - remove_tree(directory, dry_run=self.dry_run) - else: - log.warning("'%s' does not exist -- can't clean it", directory) - - # just for the heck of it, try to remove the base build directory: - # we might have emptied it right now, but if not we don't care - if not self.dry_run: - try: - os.rmdir(self.build_base) - log.info("removing '%s'", self.build_base) - except OSError: - pass diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/config.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/config.py deleted file mode 100755 index 8bf0e48..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/config.py +++ /dev/null @@ -1,377 +0,0 @@ -"""distutils.command.config - -Implements the Distutils 'config' command, a (mostly) empty command class -that exists mainly to be sub-classed by specific module distributions and -applications. The idea is that while every "config" command is different, -at least they're all named the same, and users always see "config" in the -list of standard commands. Also, this is a good place to put common -configure-like tasks: "try to compile this C code", or "figure out where -this header file lives". -""" - -import os -import re - -from ..core import Command -from ..errors import DistutilsExecError -from ..sysconfig import customize_compiler -from distutils._log import log - -LANG_EXT = {"c": ".c", "c++": ".cxx"} - - -class config(Command): - - description = "prepare to build" - - user_options = [ - ('compiler=', None, "specify the compiler type"), - ('cc=', None, "specify the compiler executable"), - ('include-dirs=', 'I', "list of directories to search for header files"), - ('define=', 'D', "C preprocessor macros to define"), - ('undef=', 'U', "C preprocessor macros to undefine"), - ('libraries=', 'l', "external C libraries to link with"), - ('library-dirs=', 'L', "directories to search for external C libraries"), - ('noisy', None, "show every action (compile, link, run, ...) taken"), - ( - 'dump-source', - None, - "dump generated source files before attempting to compile them", - ), - ] - - # The three standard command methods: since the "config" command - # does nothing by default, these are empty. - - def initialize_options(self): - self.compiler = None - self.cc = None - self.include_dirs = None - self.libraries = None - self.library_dirs = None - - # maximal output for now - self.noisy = 1 - self.dump_source = 1 - - # list of temporary files generated along-the-way that we have - # to clean at some point - self.temp_files = [] - - def finalize_options(self): - if self.include_dirs is None: - self.include_dirs = self.distribution.include_dirs or [] - elif isinstance(self.include_dirs, str): - self.include_dirs = self.include_dirs.split(os.pathsep) - - if self.libraries is None: - self.libraries = [] - elif isinstance(self.libraries, str): - self.libraries = [self.libraries] - - if self.library_dirs is None: - self.library_dirs = [] - elif isinstance(self.library_dirs, str): - self.library_dirs = self.library_dirs.split(os.pathsep) - - def run(self): - pass - - # Utility methods for actual "config" commands. The interfaces are - # loosely based on Autoconf macros of similar names. Sub-classes - # may use these freely. - - def _check_compiler(self): - """Check that 'self.compiler' really is a CCompiler object; - if not, make it one. - """ - # We do this late, and only on-demand, because this is an expensive - # import. - from ..ccompiler import CCompiler, new_compiler - - if not isinstance(self.compiler, CCompiler): - self.compiler = new_compiler( - compiler=self.compiler, dry_run=self.dry_run, force=1 - ) - customize_compiler(self.compiler) - if self.include_dirs: - self.compiler.set_include_dirs(self.include_dirs) - if self.libraries: - self.compiler.set_libraries(self.libraries) - if self.library_dirs: - self.compiler.set_library_dirs(self.library_dirs) - - def _gen_temp_sourcefile(self, body, headers, lang): - filename = "_configtest" + LANG_EXT[lang] - with open(filename, "w") as file: - if headers: - for header in headers: - file.write("#include <%s>\n" % header) - file.write("\n") - file.write(body) - if body[-1] != "\n": - file.write("\n") - return filename - - def _preprocess(self, body, headers, include_dirs, lang): - src = self._gen_temp_sourcefile(body, headers, lang) - out = "_configtest.i" - self.temp_files.extend([src, out]) - self.compiler.preprocess(src, out, include_dirs=include_dirs) - return (src, out) - - def _compile(self, body, headers, include_dirs, lang): - src = self._gen_temp_sourcefile(body, headers, lang) - if self.dump_source: - dump_file(src, "compiling '%s':" % src) - (obj,) = self.compiler.object_filenames([src]) - self.temp_files.extend([src, obj]) - self.compiler.compile([src], include_dirs=include_dirs) - return (src, obj) - - def _link(self, body, headers, include_dirs, libraries, library_dirs, lang): - (src, obj) = self._compile(body, headers, include_dirs, lang) - prog = os.path.splitext(os.path.basename(src))[0] - self.compiler.link_executable( - [obj], - prog, - libraries=libraries, - library_dirs=library_dirs, - target_lang=lang, - ) - - if self.compiler.exe_extension is not None: - prog = prog + self.compiler.exe_extension - self.temp_files.append(prog) - - return (src, obj, prog) - - def _clean(self, *filenames): - if not filenames: - filenames = self.temp_files - self.temp_files = [] - log.info("removing: %s", ' '.join(filenames)) - for filename in filenames: - try: - os.remove(filename) - except OSError: - pass - - # XXX these ignore the dry-run flag: what to do, what to do? even if - # you want a dry-run build, you still need some sort of configuration - # info. My inclination is to make it up to the real config command to - # consult 'dry_run', and assume a default (minimal) configuration if - # true. The problem with trying to do it here is that you'd have to - # return either true or false from all the 'try' methods, neither of - # which is correct. - - # XXX need access to the header search path and maybe default macros. - - def try_cpp(self, body=None, headers=None, include_dirs=None, lang="c"): - """Construct a source file from 'body' (a string containing lines - of C/C++ code) and 'headers' (a list of header files to include) - and run it through the preprocessor. Return true if the - preprocessor succeeded, false if there were any errors. - ('body' probably isn't of much use, but what the heck.) - """ - from ..ccompiler import CompileError - - self._check_compiler() - ok = True - try: - self._preprocess(body, headers, include_dirs, lang) - except CompileError: - ok = False - - self._clean() - return ok - - def search_cpp(self, pattern, body=None, headers=None, include_dirs=None, lang="c"): - """Construct a source file (just like 'try_cpp()'), run it through - the preprocessor, and return true if any line of the output matches - 'pattern'. 'pattern' should either be a compiled regex object or a - string containing a regex. If both 'body' and 'headers' are None, - preprocesses an empty file -- which can be useful to determine the - symbols the preprocessor and compiler set by default. - """ - self._check_compiler() - src, out = self._preprocess(body, headers, include_dirs, lang) - - if isinstance(pattern, str): - pattern = re.compile(pattern) - - with open(out) as file: - match = False - while True: - line = file.readline() - if line == '': - break - if pattern.search(line): - match = True - break - - self._clean() - return match - - def try_compile(self, body, headers=None, include_dirs=None, lang="c"): - """Try to compile a source file built from 'body' and 'headers'. - Return true on success, false otherwise. - """ - from ..ccompiler import CompileError - - self._check_compiler() - try: - self._compile(body, headers, include_dirs, lang) - ok = True - except CompileError: - ok = False - - log.info(ok and "success!" or "failure.") - self._clean() - return ok - - def try_link( - self, - body, - headers=None, - include_dirs=None, - libraries=None, - library_dirs=None, - lang="c", - ): - """Try to compile and link a source file, built from 'body' and - 'headers', to executable form. Return true on success, false - otherwise. - """ - from ..ccompiler import CompileError, LinkError - - self._check_compiler() - try: - self._link(body, headers, include_dirs, libraries, library_dirs, lang) - ok = True - except (CompileError, LinkError): - ok = False - - log.info(ok and "success!" or "failure.") - self._clean() - return ok - - def try_run( - self, - body, - headers=None, - include_dirs=None, - libraries=None, - library_dirs=None, - lang="c", - ): - """Try to compile, link to an executable, and run a program - built from 'body' and 'headers'. Return true on success, false - otherwise. - """ - from ..ccompiler import CompileError, LinkError - - self._check_compiler() - try: - src, obj, exe = self._link( - body, headers, include_dirs, libraries, library_dirs, lang - ) - self.spawn([exe]) - ok = True - except (CompileError, LinkError, DistutilsExecError): - ok = False - - log.info(ok and "success!" or "failure.") - self._clean() - return ok - - # -- High-level methods -------------------------------------------- - # (these are the ones that are actually likely to be useful - # when implementing a real-world config command!) - - def check_func( - self, - func, - headers=None, - include_dirs=None, - libraries=None, - library_dirs=None, - decl=0, - call=0, - ): - """Determine if function 'func' is available by constructing a - source file that refers to 'func', and compiles and links it. - If everything succeeds, returns true; otherwise returns false. - - The constructed source file starts out by including the header - files listed in 'headers'. If 'decl' is true, it then declares - 'func' (as "int func()"); you probably shouldn't supply 'headers' - and set 'decl' true in the same call, or you might get errors about - a conflicting declarations for 'func'. Finally, the constructed - 'main()' function either references 'func' or (if 'call' is true) - calls it. 'libraries' and 'library_dirs' are used when - linking. - """ - self._check_compiler() - body = [] - if decl: - body.append("int %s ();" % func) - body.append("int main () {") - if call: - body.append(" %s();" % func) - else: - body.append(" %s;" % func) - body.append("}") - body = "\n".join(body) + "\n" - - return self.try_link(body, headers, include_dirs, libraries, library_dirs) - - def check_lib( - self, - library, - library_dirs=None, - headers=None, - include_dirs=None, - other_libraries=[], - ): - """Determine if 'library' is available to be linked against, - without actually checking that any particular symbols are provided - by it. 'headers' will be used in constructing the source file to - be compiled, but the only effect of this is to check if all the - header files listed are available. Any libraries listed in - 'other_libraries' will be included in the link, in case 'library' - has symbols that depend on other libraries. - """ - self._check_compiler() - return self.try_link( - "int main (void) { }", - headers, - include_dirs, - [library] + other_libraries, - library_dirs, - ) - - def check_header(self, header, include_dirs=None, library_dirs=None, lang="c"): - """Determine if the system header file named by 'header_file' - exists and can be found by the preprocessor; return true if so, - false otherwise. - """ - return self.try_cpp( - body="/* No body */", headers=[header], include_dirs=include_dirs - ) - - -def dump_file(filename, head=None): - """Dumps a file content into log.info. - - If head is not None, will be dumped before the file content. - """ - if head is None: - log.info('%s', filename) - else: - log.info(head) - file = open(filename) - try: - log.info(file.read()) - finally: - file.close() diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/install.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/install.py deleted file mode 100755 index 08d2f88..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/install.py +++ /dev/null @@ -1,814 +0,0 @@ -"""distutils.command.install - -Implements the Distutils 'install' command.""" - -import sys -import os -import contextlib -import sysconfig -import itertools - -from distutils._log import log -from ..core import Command -from ..debug import DEBUG -from ..sysconfig import get_config_vars -from ..file_util import write_file -from ..util import convert_path, subst_vars, change_root -from ..util import get_platform -from ..errors import DistutilsOptionError, DistutilsPlatformError -from . import _framework_compat as fw -from .. import _collections - -from site import USER_BASE -from site import USER_SITE - -HAS_USER_SITE = True - -WINDOWS_SCHEME = { - 'purelib': '{base}/Lib/site-packages', - 'platlib': '{base}/Lib/site-packages', - 'headers': '{base}/Include/{dist_name}', - 'scripts': '{base}/Scripts', - 'data': '{base}', -} - -INSTALL_SCHEMES = { - 'posix_prefix': { - 'purelib': '{base}/lib/{implementation_lower}{py_version_short}/site-packages', - 'platlib': '{platbase}/{platlibdir}/{implementation_lower}' - '{py_version_short}/site-packages', - 'headers': '{base}/include/{implementation_lower}' - '{py_version_short}{abiflags}/{dist_name}', - 'scripts': '{base}/bin', - 'data': '{base}', - }, - 'posix_home': { - 'purelib': '{base}/lib/{implementation_lower}', - 'platlib': '{base}/{platlibdir}/{implementation_lower}', - 'headers': '{base}/include/{implementation_lower}/{dist_name}', - 'scripts': '{base}/bin', - 'data': '{base}', - }, - 'nt': WINDOWS_SCHEME, - 'pypy': { - 'purelib': '{base}/site-packages', - 'platlib': '{base}/site-packages', - 'headers': '{base}/include/{dist_name}', - 'scripts': '{base}/bin', - 'data': '{base}', - }, - 'pypy_nt': { - 'purelib': '{base}/site-packages', - 'platlib': '{base}/site-packages', - 'headers': '{base}/include/{dist_name}', - 'scripts': '{base}/Scripts', - 'data': '{base}', - }, -} - -# user site schemes -if HAS_USER_SITE: - INSTALL_SCHEMES['nt_user'] = { - 'purelib': '{usersite}', - 'platlib': '{usersite}', - 'headers': '{userbase}/{implementation}{py_version_nodot_plat}' - '/Include/{dist_name}', - 'scripts': '{userbase}/{implementation}{py_version_nodot_plat}/Scripts', - 'data': '{userbase}', - } - - INSTALL_SCHEMES['posix_user'] = { - 'purelib': '{usersite}', - 'platlib': '{usersite}', - 'headers': '{userbase}/include/{implementation_lower}' - '{py_version_short}{abiflags}/{dist_name}', - 'scripts': '{userbase}/bin', - 'data': '{userbase}', - } - - -INSTALL_SCHEMES.update(fw.schemes) - - -# The keys to an installation scheme; if any new types of files are to be -# installed, be sure to add an entry to every installation scheme above, -# and to SCHEME_KEYS here. -SCHEME_KEYS = ('purelib', 'platlib', 'headers', 'scripts', 'data') - - -def _load_sysconfig_schemes(): - with contextlib.suppress(AttributeError): - return { - scheme: sysconfig.get_paths(scheme, expand=False) - for scheme in sysconfig.get_scheme_names() - } - - -def _load_schemes(): - """ - Extend default schemes with schemes from sysconfig. - """ - - sysconfig_schemes = _load_sysconfig_schemes() or {} - - return { - scheme: { - **INSTALL_SCHEMES.get(scheme, {}), - **sysconfig_schemes.get(scheme, {}), - } - for scheme in set(itertools.chain(INSTALL_SCHEMES, sysconfig_schemes)) - } - - -def _get_implementation(): - if hasattr(sys, 'pypy_version_info'): - return 'PyPy' - else: - return 'Python' - - -def _select_scheme(ob, name): - scheme = _inject_headers(name, _load_scheme(_resolve_scheme(name))) - vars(ob).update(_remove_set(ob, _scheme_attrs(scheme))) - - -def _remove_set(ob, attrs): - """ - Include only attrs that are None in ob. - """ - return {key: value for key, value in attrs.items() if getattr(ob, key) is None} - - -def _resolve_scheme(name): - os_name, sep, key = name.partition('_') - try: - resolved = sysconfig.get_preferred_scheme(key) - except Exception: - resolved = fw.scheme(_pypy_hack(name)) - return resolved - - -def _load_scheme(name): - return _load_schemes()[name] - - -def _inject_headers(name, scheme): - """ - Given a scheme name and the resolved scheme, - if the scheme does not include headers, resolve - the fallback scheme for the name and use headers - from it. pypa/distutils#88 - """ - # Bypass the preferred scheme, which may not - # have defined headers. - fallback = _load_scheme(_pypy_hack(name)) - scheme.setdefault('headers', fallback['headers']) - return scheme - - -def _scheme_attrs(scheme): - """Resolve install directories by applying the install schemes.""" - return {f'install_{key}': scheme[key] for key in SCHEME_KEYS} - - -def _pypy_hack(name): - PY37 = sys.version_info < (3, 8) - old_pypy = hasattr(sys, 'pypy_version_info') and PY37 - prefix = not name.endswith(('_user', '_home')) - pypy_name = 'pypy' + '_nt' * (os.name == 'nt') - return pypy_name if old_pypy and prefix else name - - -class install(Command): - - description = "install everything from build directory" - - user_options = [ - # Select installation scheme and set base director(y|ies) - ('prefix=', None, "installation prefix"), - ('exec-prefix=', None, "(Unix only) prefix for platform-specific files"), - ('home=', None, "(Unix only) home directory to install under"), - # Or, just set the base director(y|ies) - ( - 'install-base=', - None, - "base installation directory (instead of --prefix or --home)", - ), - ( - 'install-platbase=', - None, - "base installation directory for platform-specific files " - + "(instead of --exec-prefix or --home)", - ), - ('root=', None, "install everything relative to this alternate root directory"), - # Or, explicitly set the installation scheme - ( - 'install-purelib=', - None, - "installation directory for pure Python module distributions", - ), - ( - 'install-platlib=', - None, - "installation directory for non-pure module distributions", - ), - ( - 'install-lib=', - None, - "installation directory for all module distributions " - + "(overrides --install-purelib and --install-platlib)", - ), - ('install-headers=', None, "installation directory for C/C++ headers"), - ('install-scripts=', None, "installation directory for Python scripts"), - ('install-data=', None, "installation directory for data files"), - # Byte-compilation options -- see install_lib.py for details, as - # these are duplicated from there (but only install_lib does - # anything with them). - ('compile', 'c', "compile .py to .pyc [default]"), - ('no-compile', None, "don't compile .py files"), - ( - 'optimize=', - 'O', - "also compile with optimization: -O1 for \"python -O\", " - "-O2 for \"python -OO\", and -O0 to disable [default: -O0]", - ), - # Miscellaneous control options - ('force', 'f', "force installation (overwrite any existing files)"), - ('skip-build', None, "skip rebuilding everything (for testing/debugging)"), - # Where to install documentation (eventually!) - # ('doc-format=', None, "format of documentation to generate"), - # ('install-man=', None, "directory for Unix man pages"), - # ('install-html=', None, "directory for HTML documentation"), - # ('install-info=', None, "directory for GNU info files"), - ('record=', None, "filename in which to record list of installed files"), - ] - - boolean_options = ['compile', 'force', 'skip-build'] - - if HAS_USER_SITE: - user_options.append( - ('user', None, "install in user site-package '%s'" % USER_SITE) - ) - boolean_options.append('user') - - negative_opt = {'no-compile': 'compile'} - - def initialize_options(self): - """Initializes options.""" - # High-level options: these select both an installation base - # and scheme. - self.prefix = None - self.exec_prefix = None - self.home = None - self.user = 0 - - # These select only the installation base; it's up to the user to - # specify the installation scheme (currently, that means supplying - # the --install-{platlib,purelib,scripts,data} options). - self.install_base = None - self.install_platbase = None - self.root = None - - # These options are the actual installation directories; if not - # supplied by the user, they are filled in using the installation - # scheme implied by prefix/exec-prefix/home and the contents of - # that installation scheme. - self.install_purelib = None # for pure module distributions - self.install_platlib = None # non-pure (dists w/ extensions) - self.install_headers = None # for C/C++ headers - self.install_lib = None # set to either purelib or platlib - self.install_scripts = None - self.install_data = None - self.install_userbase = USER_BASE - self.install_usersite = USER_SITE - - self.compile = None - self.optimize = None - - # Deprecated - # These two are for putting non-packagized distributions into their - # own directory and creating a .pth file if it makes sense. - # 'extra_path' comes from the setup file; 'install_path_file' can - # be turned off if it makes no sense to install a .pth file. (But - # better to install it uselessly than to guess wrong and not - # install it when it's necessary and would be used!) Currently, - # 'install_path_file' is always true unless some outsider meddles - # with it. - self.extra_path = None - self.install_path_file = 1 - - # 'force' forces installation, even if target files are not - # out-of-date. 'skip_build' skips running the "build" command, - # handy if you know it's not necessary. 'warn_dir' (which is *not* - # a user option, it's just there so the bdist_* commands can turn - # it off) determines whether we warn about installing to a - # directory not in sys.path. - self.force = 0 - self.skip_build = 0 - self.warn_dir = 1 - - # These are only here as a conduit from the 'build' command to the - # 'install_*' commands that do the real work. ('build_base' isn't - # actually used anywhere, but it might be useful in future.) They - # are not user options, because if the user told the install - # command where the build directory is, that wouldn't affect the - # build command. - self.build_base = None - self.build_lib = None - - # Not defined yet because we don't know anything about - # documentation yet. - # self.install_man = None - # self.install_html = None - # self.install_info = None - - self.record = None - - # -- Option finalizing methods ------------------------------------- - # (This is rather more involved than for most commands, - # because this is where the policy for installing third- - # party Python modules on various platforms given a wide - # array of user input is decided. Yes, it's quite complex!) - - def finalize_options(self): # noqa: C901 - """Finalizes options.""" - # This method (and its helpers, like 'finalize_unix()', - # 'finalize_other()', and 'select_scheme()') is where the default - # installation directories for modules, extension modules, and - # anything else we care to install from a Python module - # distribution. Thus, this code makes a pretty important policy - # statement about how third-party stuff is added to a Python - # installation! Note that the actual work of installation is done - # by the relatively simple 'install_*' commands; they just take - # their orders from the installation directory options determined - # here. - - # Check for errors/inconsistencies in the options; first, stuff - # that's wrong on any platform. - - if (self.prefix or self.exec_prefix or self.home) and ( - self.install_base or self.install_platbase - ): - raise DistutilsOptionError( - "must supply either prefix/exec-prefix/home or " - + "install-base/install-platbase -- not both" - ) - - if self.home and (self.prefix or self.exec_prefix): - raise DistutilsOptionError( - "must supply either home or prefix/exec-prefix -- not both" - ) - - if self.user and ( - self.prefix - or self.exec_prefix - or self.home - or self.install_base - or self.install_platbase - ): - raise DistutilsOptionError( - "can't combine user with prefix, " - "exec_prefix/home, or install_(plat)base" - ) - - # Next, stuff that's wrong (or dubious) only on certain platforms. - if os.name != "posix": - if self.exec_prefix: - self.warn("exec-prefix option ignored on this platform") - self.exec_prefix = None - - # Now the interesting logic -- so interesting that we farm it out - # to other methods. The goal of these methods is to set the final - # values for the install_{lib,scripts,data,...} options, using as - # input a heady brew of prefix, exec_prefix, home, install_base, - # install_platbase, user-supplied versions of - # install_{purelib,platlib,lib,scripts,data,...}, and the - # install schemes. Phew! - - self.dump_dirs("pre-finalize_{unix,other}") - - if os.name == 'posix': - self.finalize_unix() - else: - self.finalize_other() - - self.dump_dirs("post-finalize_{unix,other}()") - - # Expand configuration variables, tilde, etc. in self.install_base - # and self.install_platbase -- that way, we can use $base or - # $platbase in the other installation directories and not worry - # about needing recursive variable expansion (shudder). - - py_version = sys.version.split()[0] - (prefix, exec_prefix) = get_config_vars('prefix', 'exec_prefix') - try: - abiflags = sys.abiflags - except AttributeError: - # sys.abiflags may not be defined on all platforms. - abiflags = '' - local_vars = { - 'dist_name': self.distribution.get_name(), - 'dist_version': self.distribution.get_version(), - 'dist_fullname': self.distribution.get_fullname(), - 'py_version': py_version, - 'py_version_short': '%d.%d' % sys.version_info[:2], - 'py_version_nodot': '%d%d' % sys.version_info[:2], - 'sys_prefix': prefix, - 'prefix': prefix, - 'sys_exec_prefix': exec_prefix, - 'exec_prefix': exec_prefix, - 'abiflags': abiflags, - 'platlibdir': getattr(sys, 'platlibdir', 'lib'), - 'implementation_lower': _get_implementation().lower(), - 'implementation': _get_implementation(), - } - - # vars for compatibility on older Pythons - compat_vars = dict( - # Python 3.9 and earlier - py_version_nodot_plat=getattr(sys, 'winver', '').replace('.', ''), - ) - - if HAS_USER_SITE: - local_vars['userbase'] = self.install_userbase - local_vars['usersite'] = self.install_usersite - - self.config_vars = _collections.DictStack( - [fw.vars(), compat_vars, sysconfig.get_config_vars(), local_vars] - ) - - self.expand_basedirs() - - self.dump_dirs("post-expand_basedirs()") - - # Now define config vars for the base directories so we can expand - # everything else. - local_vars['base'] = self.install_base - local_vars['platbase'] = self.install_platbase - - if DEBUG: - from pprint import pprint - - print("config vars:") - pprint(dict(self.config_vars)) - - # Expand "~" and configuration variables in the installation - # directories. - self.expand_dirs() - - self.dump_dirs("post-expand_dirs()") - - # Create directories in the home dir: - if self.user: - self.create_home_path() - - # Pick the actual directory to install all modules to: either - # install_purelib or install_platlib, depending on whether this - # module distribution is pure or not. Of course, if the user - # already specified install_lib, use their selection. - if self.install_lib is None: - if self.distribution.has_ext_modules(): # has extensions: non-pure - self.install_lib = self.install_platlib - else: - self.install_lib = self.install_purelib - - # Convert directories from Unix /-separated syntax to the local - # convention. - self.convert_paths( - 'lib', - 'purelib', - 'platlib', - 'scripts', - 'data', - 'headers', - 'userbase', - 'usersite', - ) - - # Deprecated - # Well, we're not actually fully completely finalized yet: we still - # have to deal with 'extra_path', which is the hack for allowing - # non-packagized module distributions (hello, Numerical Python!) to - # get their own directories. - self.handle_extra_path() - self.install_libbase = self.install_lib # needed for .pth file - self.install_lib = os.path.join(self.install_lib, self.extra_dirs) - - # If a new root directory was supplied, make all the installation - # dirs relative to it. - if self.root is not None: - self.change_roots( - 'libbase', 'lib', 'purelib', 'platlib', 'scripts', 'data', 'headers' - ) - - self.dump_dirs("after prepending root") - - # Find out the build directories, ie. where to install from. - self.set_undefined_options( - 'build', ('build_base', 'build_base'), ('build_lib', 'build_lib') - ) - - # Punt on doc directories for now -- after all, we're punting on - # documentation completely! - - def dump_dirs(self, msg): - """Dumps the list of user options.""" - if not DEBUG: - return - from ..fancy_getopt import longopt_xlate - - log.debug(msg + ":") - for opt in self.user_options: - opt_name = opt[0] - if opt_name[-1] == "=": - opt_name = opt_name[0:-1] - if opt_name in self.negative_opt: - opt_name = self.negative_opt[opt_name] - opt_name = opt_name.translate(longopt_xlate) - val = not getattr(self, opt_name) - else: - opt_name = opt_name.translate(longopt_xlate) - val = getattr(self, opt_name) - log.debug(" %s: %s", opt_name, val) - - def finalize_unix(self): - """Finalizes options for posix platforms.""" - if self.install_base is not None or self.install_platbase is not None: - incomplete_scheme = ( - ( - self.install_lib is None - and self.install_purelib is None - and self.install_platlib is None - ) - or self.install_headers is None - or self.install_scripts is None - or self.install_data is None - ) - if incomplete_scheme: - raise DistutilsOptionError( - "install-base or install-platbase supplied, but " - "installation scheme is incomplete" - ) - return - - if self.user: - if self.install_userbase is None: - raise DistutilsPlatformError("User base directory is not specified") - self.install_base = self.install_platbase = self.install_userbase - self.select_scheme("posix_user") - elif self.home is not None: - self.install_base = self.install_platbase = self.home - self.select_scheme("posix_home") - else: - if self.prefix is None: - if self.exec_prefix is not None: - raise DistutilsOptionError( - "must not supply exec-prefix without prefix" - ) - - # Allow Fedora to add components to the prefix - _prefix_addition = getattr(sysconfig, '_prefix_addition', "") - - self.prefix = os.path.normpath(sys.prefix) + _prefix_addition - self.exec_prefix = os.path.normpath(sys.exec_prefix) + _prefix_addition - - else: - if self.exec_prefix is None: - self.exec_prefix = self.prefix - - self.install_base = self.prefix - self.install_platbase = self.exec_prefix - self.select_scheme("posix_prefix") - - def finalize_other(self): - """Finalizes options for non-posix platforms""" - if self.user: - if self.install_userbase is None: - raise DistutilsPlatformError("User base directory is not specified") - self.install_base = self.install_platbase = self.install_userbase - self.select_scheme(os.name + "_user") - elif self.home is not None: - self.install_base = self.install_platbase = self.home - self.select_scheme("posix_home") - else: - if self.prefix is None: - self.prefix = os.path.normpath(sys.prefix) - - self.install_base = self.install_platbase = self.prefix - try: - self.select_scheme(os.name) - except KeyError: - raise DistutilsPlatformError( - "I don't know how to install stuff on '%s'" % os.name - ) - - def select_scheme(self, name): - _select_scheme(self, name) - - def _expand_attrs(self, attrs): - for attr in attrs: - val = getattr(self, attr) - if val is not None: - if os.name == 'posix' or os.name == 'nt': - val = os.path.expanduser(val) - val = subst_vars(val, self.config_vars) - setattr(self, attr, val) - - def expand_basedirs(self): - """Calls `os.path.expanduser` on install_base, install_platbase and - root.""" - self._expand_attrs(['install_base', 'install_platbase', 'root']) - - def expand_dirs(self): - """Calls `os.path.expanduser` on install dirs.""" - self._expand_attrs( - [ - 'install_purelib', - 'install_platlib', - 'install_lib', - 'install_headers', - 'install_scripts', - 'install_data', - ] - ) - - def convert_paths(self, *names): - """Call `convert_path` over `names`.""" - for name in names: - attr = "install_" + name - setattr(self, attr, convert_path(getattr(self, attr))) - - def handle_extra_path(self): - """Set `path_file` and `extra_dirs` using `extra_path`.""" - if self.extra_path is None: - self.extra_path = self.distribution.extra_path - - if self.extra_path is not None: - log.warning( - "Distribution option extra_path is deprecated. " - "See issue27919 for details." - ) - if isinstance(self.extra_path, str): - self.extra_path = self.extra_path.split(',') - - if len(self.extra_path) == 1: - path_file = extra_dirs = self.extra_path[0] - elif len(self.extra_path) == 2: - path_file, extra_dirs = self.extra_path - else: - raise DistutilsOptionError( - "'extra_path' option must be a list, tuple, or " - "comma-separated string with 1 or 2 elements" - ) - - # convert to local form in case Unix notation used (as it - # should be in setup scripts) - extra_dirs = convert_path(extra_dirs) - else: - path_file = None - extra_dirs = '' - - # XXX should we warn if path_file and not extra_dirs? (in which - # case the path file would be harmless but pointless) - self.path_file = path_file - self.extra_dirs = extra_dirs - - def change_roots(self, *names): - """Change the install directories pointed by name using root.""" - for name in names: - attr = "install_" + name - setattr(self, attr, change_root(self.root, getattr(self, attr))) - - def create_home_path(self): - """Create directories under ~.""" - if not self.user: - return - home = convert_path(os.path.expanduser("~")) - for name, path in self.config_vars.items(): - if str(path).startswith(home) and not os.path.isdir(path): - self.debug_print("os.makedirs('%s', 0o700)" % path) - os.makedirs(path, 0o700) - - # -- Command execution methods ------------------------------------- - - def run(self): - """Runs the command.""" - # Obviously have to build before we can install - if not self.skip_build: - self.run_command('build') - # If we built for any other platform, we can't install. - build_plat = self.distribution.get_command_obj('build').plat_name - # check warn_dir - it is a clue that the 'install' is happening - # internally, and not to sys.path, so we don't check the platform - # matches what we are running. - if self.warn_dir and build_plat != get_platform(): - raise DistutilsPlatformError("Can't install when " "cross-compiling") - - # Run all sub-commands (at least those that need to be run) - for cmd_name in self.get_sub_commands(): - self.run_command(cmd_name) - - if self.path_file: - self.create_path_file() - - # write list of installed files, if requested. - if self.record: - outputs = self.get_outputs() - if self.root: # strip any package prefix - root_len = len(self.root) - for counter in range(len(outputs)): - outputs[counter] = outputs[counter][root_len:] - self.execute( - write_file, - (self.record, outputs), - "writing list of installed files to '%s'" % self.record, - ) - - sys_path = map(os.path.normpath, sys.path) - sys_path = map(os.path.normcase, sys_path) - install_lib = os.path.normcase(os.path.normpath(self.install_lib)) - if ( - self.warn_dir - and not (self.path_file and self.install_path_file) - and install_lib not in sys_path - ): - log.debug( - ( - "modules installed to '%s', which is not in " - "Python's module search path (sys.path) -- " - "you'll have to change the search path yourself" - ), - self.install_lib, - ) - - def create_path_file(self): - """Creates the .pth file""" - filename = os.path.join(self.install_libbase, self.path_file + ".pth") - if self.install_path_file: - self.execute( - write_file, (filename, [self.extra_dirs]), "creating %s" % filename - ) - else: - self.warn("path file '%s' not created" % filename) - - # -- Reporting methods --------------------------------------------- - - def get_outputs(self): - """Assembles the outputs of all the sub-commands.""" - outputs = [] - for cmd_name in self.get_sub_commands(): - cmd = self.get_finalized_command(cmd_name) - # Add the contents of cmd.get_outputs(), ensuring - # that outputs doesn't contain duplicate entries - for filename in cmd.get_outputs(): - if filename not in outputs: - outputs.append(filename) - - if self.path_file and self.install_path_file: - outputs.append(os.path.join(self.install_libbase, self.path_file + ".pth")) - - return outputs - - def get_inputs(self): - """Returns the inputs of all the sub-commands""" - # XXX gee, this looks familiar ;-( - inputs = [] - for cmd_name in self.get_sub_commands(): - cmd = self.get_finalized_command(cmd_name) - inputs.extend(cmd.get_inputs()) - - return inputs - - # -- Predicates for sub-command list ------------------------------- - - def has_lib(self): - """Returns true if the current distribution has any Python - modules to install.""" - return ( - self.distribution.has_pure_modules() or self.distribution.has_ext_modules() - ) - - def has_headers(self): - """Returns true if the current distribution has any headers to - install.""" - return self.distribution.has_headers() - - def has_scripts(self): - """Returns true if the current distribution has any scripts to. - install.""" - return self.distribution.has_scripts() - - def has_data(self): - """Returns true if the current distribution has any data to. - install.""" - return self.distribution.has_data_files() - - # 'sub_commands': a list of commands this command might have to run to - # get its work done. See cmd.py for more info. - sub_commands = [ - ('install_lib', has_lib), - ('install_headers', has_headers), - ('install_scripts', has_scripts), - ('install_data', has_data), - ('install_egg_info', lambda self: True), - ] diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/install_data.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/install_data.py deleted file mode 100755 index d92ed87..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/install_data.py +++ /dev/null @@ -1,84 +0,0 @@ -"""distutils.command.install_data - -Implements the Distutils 'install_data' command, for installing -platform-independent data files.""" - -# contributed by Bastian Kleineidam - -import os -from ..core import Command -from ..util import change_root, convert_path - - -class install_data(Command): - - description = "install data files" - - user_options = [ - ( - 'install-dir=', - 'd', - "base directory for installing data files " - "(default: installation base dir)", - ), - ('root=', None, "install everything relative to this alternate root directory"), - ('force', 'f', "force installation (overwrite existing files)"), - ] - - boolean_options = ['force'] - - def initialize_options(self): - self.install_dir = None - self.outfiles = [] - self.root = None - self.force = 0 - self.data_files = self.distribution.data_files - self.warn_dir = 1 - - def finalize_options(self): - self.set_undefined_options( - 'install', - ('install_data', 'install_dir'), - ('root', 'root'), - ('force', 'force'), - ) - - def run(self): - self.mkpath(self.install_dir) - for f in self.data_files: - if isinstance(f, str): - # it's a simple file, so copy it - f = convert_path(f) - if self.warn_dir: - self.warn( - "setup script did not provide a directory for " - "'%s' -- installing right in '%s'" % (f, self.install_dir) - ) - (out, _) = self.copy_file(f, self.install_dir) - self.outfiles.append(out) - else: - # it's a tuple with path to install to and a list of files - dir = convert_path(f[0]) - if not os.path.isabs(dir): - dir = os.path.join(self.install_dir, dir) - elif self.root: - dir = change_root(self.root, dir) - self.mkpath(dir) - - if f[1] == []: - # If there are no files listed, the user must be - # trying to create an empty directory, so add the - # directory to the list of output files. - self.outfiles.append(dir) - else: - # Copy files, adding them to the list of output files. - for data in f[1]: - data = convert_path(data) - (out, _) = self.copy_file(data, dir) - self.outfiles.append(out) - - def get_inputs(self): - return self.data_files or [] - - def get_outputs(self): - return self.outfiles diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/install_egg_info.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/install_egg_info.py deleted file mode 100755 index f3e8f34..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/install_egg_info.py +++ /dev/null @@ -1,92 +0,0 @@ -""" -distutils.command.install_egg_info - -Implements the Distutils 'install_egg_info' command, for installing -a package's PKG-INFO metadata. -""" - -import os -import sys -import re - -from ..cmd import Command -from .. import dir_util -from .._log import log - - -class install_egg_info(Command): - """Install an .egg-info file for the package""" - - description = "Install package's PKG-INFO metadata as an .egg-info file" - user_options = [ - ('install-dir=', 'd', "directory to install to"), - ] - - def initialize_options(self): - self.install_dir = None - - @property - def basename(self): - """ - Allow basename to be overridden by child class. - Ref pypa/distutils#2. - """ - return "%s-%s-py%d.%d.egg-info" % ( - to_filename(safe_name(self.distribution.get_name())), - to_filename(safe_version(self.distribution.get_version())), - *sys.version_info[:2], - ) - - def finalize_options(self): - self.set_undefined_options('install_lib', ('install_dir', 'install_dir')) - self.target = os.path.join(self.install_dir, self.basename) - self.outputs = [self.target] - - def run(self): - target = self.target - if os.path.isdir(target) and not os.path.islink(target): - dir_util.remove_tree(target, dry_run=self.dry_run) - elif os.path.exists(target): - self.execute(os.unlink, (self.target,), "Removing " + target) - elif not os.path.isdir(self.install_dir): - self.execute( - os.makedirs, (self.install_dir,), "Creating " + self.install_dir - ) - log.info("Writing %s", target) - if not self.dry_run: - with open(target, 'w', encoding='UTF-8') as f: - self.distribution.metadata.write_pkg_file(f) - - def get_outputs(self): - return self.outputs - - -# The following routines are taken from setuptools' pkg_resources module and -# can be replaced by importing them from pkg_resources once it is included -# in the stdlib. - - -def safe_name(name): - """Convert an arbitrary string to a standard distribution name - - Any runs of non-alphanumeric/. characters are replaced with a single '-'. - """ - return re.sub('[^A-Za-z0-9.]+', '-', name) - - -def safe_version(version): - """Convert an arbitrary string to a standard version string - - Spaces become dots, and all other non-alphanumeric characters become - dashes, with runs of multiple dashes condensed to a single dash. - """ - version = version.replace(' ', '.') - return re.sub('[^A-Za-z0-9.]+', '-', version) - - -def to_filename(name): - """Convert a project or version name to its filename-escaped form - - Any '-' characters are currently replaced with '_'. - """ - return name.replace('-', '_') diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/install_headers.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/install_headers.py deleted file mode 100755 index 1cdee82..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/install_headers.py +++ /dev/null @@ -1,45 +0,0 @@ -"""distutils.command.install_headers - -Implements the Distutils 'install_headers' command, to install C/C++ header -files to the Python include directory.""" - -from ..core import Command - - -# XXX force is never used -class install_headers(Command): - - description = "install C/C++ header files" - - user_options = [ - ('install-dir=', 'd', "directory to install header files to"), - ('force', 'f', "force installation (overwrite existing files)"), - ] - - boolean_options = ['force'] - - def initialize_options(self): - self.install_dir = None - self.force = 0 - self.outfiles = [] - - def finalize_options(self): - self.set_undefined_options( - 'install', ('install_headers', 'install_dir'), ('force', 'force') - ) - - def run(self): - headers = self.distribution.headers - if not headers: - return - - self.mkpath(self.install_dir) - for header in headers: - (out, _) = self.copy_file(header, self.install_dir) - self.outfiles.append(out) - - def get_inputs(self): - return self.distribution.headers or [] - - def get_outputs(self): - return self.outfiles diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/install_lib.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/install_lib.py deleted file mode 100755 index 840d340..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/install_lib.py +++ /dev/null @@ -1,238 +0,0 @@ -"""distutils.command.install_lib - -Implements the Distutils 'install_lib' command -(install all Python modules).""" - -import os -import importlib.util -import sys - -from ..core import Command -from ..errors import DistutilsOptionError - - -# Extension for Python source files. -PYTHON_SOURCE_EXTENSION = ".py" - - -class install_lib(Command): - - description = "install all Python modules (extensions and pure Python)" - - # The byte-compilation options are a tad confusing. Here are the - # possible scenarios: - # 1) no compilation at all (--no-compile --no-optimize) - # 2) compile .pyc only (--compile --no-optimize; default) - # 3) compile .pyc and "opt-1" .pyc (--compile --optimize) - # 4) compile "opt-1" .pyc only (--no-compile --optimize) - # 5) compile .pyc and "opt-2" .pyc (--compile --optimize-more) - # 6) compile "opt-2" .pyc only (--no-compile --optimize-more) - # - # The UI for this is two options, 'compile' and 'optimize'. - # 'compile' is strictly boolean, and only decides whether to - # generate .pyc files. 'optimize' is three-way (0, 1, or 2), and - # decides both whether to generate .pyc files and what level of - # optimization to use. - - user_options = [ - ('install-dir=', 'd', "directory to install to"), - ('build-dir=', 'b', "build directory (where to install from)"), - ('force', 'f', "force installation (overwrite existing files)"), - ('compile', 'c', "compile .py to .pyc [default]"), - ('no-compile', None, "don't compile .py files"), - ( - 'optimize=', - 'O', - "also compile with optimization: -O1 for \"python -O\", " - "-O2 for \"python -OO\", and -O0 to disable [default: -O0]", - ), - ('skip-build', None, "skip the build steps"), - ] - - boolean_options = ['force', 'compile', 'skip-build'] - negative_opt = {'no-compile': 'compile'} - - def initialize_options(self): - # let the 'install' command dictate our installation directory - self.install_dir = None - self.build_dir = None - self.force = 0 - self.compile = None - self.optimize = None - self.skip_build = None - - def finalize_options(self): - # Get all the information we need to install pure Python modules - # from the umbrella 'install' command -- build (source) directory, - # install (target) directory, and whether to compile .py files. - self.set_undefined_options( - 'install', - ('build_lib', 'build_dir'), - ('install_lib', 'install_dir'), - ('force', 'force'), - ('compile', 'compile'), - ('optimize', 'optimize'), - ('skip_build', 'skip_build'), - ) - - if self.compile is None: - self.compile = True - if self.optimize is None: - self.optimize = False - - if not isinstance(self.optimize, int): - try: - self.optimize = int(self.optimize) - if self.optimize not in (0, 1, 2): - raise AssertionError - except (ValueError, AssertionError): - raise DistutilsOptionError("optimize must be 0, 1, or 2") - - def run(self): - # Make sure we have built everything we need first - self.build() - - # Install everything: simply dump the entire contents of the build - # directory to the installation directory (that's the beauty of - # having a build directory!) - outfiles = self.install() - - # (Optionally) compile .py to .pyc - if outfiles is not None and self.distribution.has_pure_modules(): - self.byte_compile(outfiles) - - # -- Top-level worker functions ------------------------------------ - # (called from 'run()') - - def build(self): - if not self.skip_build: - if self.distribution.has_pure_modules(): - self.run_command('build_py') - if self.distribution.has_ext_modules(): - self.run_command('build_ext') - - def install(self): - if os.path.isdir(self.build_dir): - outfiles = self.copy_tree(self.build_dir, self.install_dir) - else: - self.warn( - "'%s' does not exist -- no Python modules to install" % self.build_dir - ) - return - return outfiles - - def byte_compile(self, files): - if sys.dont_write_bytecode: - self.warn('byte-compiling is disabled, skipping.') - return - - from ..util import byte_compile - - # Get the "--root" directory supplied to the "install" command, - # and use it as a prefix to strip off the purported filename - # encoded in bytecode files. This is far from complete, but it - # should at least generate usable bytecode in RPM distributions. - install_root = self.get_finalized_command('install').root - - if self.compile: - byte_compile( - files, - optimize=0, - force=self.force, - prefix=install_root, - dry_run=self.dry_run, - ) - if self.optimize > 0: - byte_compile( - files, - optimize=self.optimize, - force=self.force, - prefix=install_root, - verbose=self.verbose, - dry_run=self.dry_run, - ) - - # -- Utility methods ----------------------------------------------- - - def _mutate_outputs(self, has_any, build_cmd, cmd_option, output_dir): - if not has_any: - return [] - - build_cmd = self.get_finalized_command(build_cmd) - build_files = build_cmd.get_outputs() - build_dir = getattr(build_cmd, cmd_option) - - prefix_len = len(build_dir) + len(os.sep) - outputs = [] - for file in build_files: - outputs.append(os.path.join(output_dir, file[prefix_len:])) - - return outputs - - def _bytecode_filenames(self, py_filenames): - bytecode_files = [] - for py_file in py_filenames: - # Since build_py handles package data installation, the - # list of outputs can contain more than just .py files. - # Make sure we only report bytecode for the .py files. - ext = os.path.splitext(os.path.normcase(py_file))[1] - if ext != PYTHON_SOURCE_EXTENSION: - continue - if self.compile: - bytecode_files.append( - importlib.util.cache_from_source(py_file, optimization='') - ) - if self.optimize > 0: - bytecode_files.append( - importlib.util.cache_from_source( - py_file, optimization=self.optimize - ) - ) - - return bytecode_files - - # -- External interface -------------------------------------------- - # (called by outsiders) - - def get_outputs(self): - """Return the list of files that would be installed if this command - were actually run. Not affected by the "dry-run" flag or whether - modules have actually been built yet. - """ - pure_outputs = self._mutate_outputs( - self.distribution.has_pure_modules(), - 'build_py', - 'build_lib', - self.install_dir, - ) - if self.compile: - bytecode_outputs = self._bytecode_filenames(pure_outputs) - else: - bytecode_outputs = [] - - ext_outputs = self._mutate_outputs( - self.distribution.has_ext_modules(), - 'build_ext', - 'build_lib', - self.install_dir, - ) - - return pure_outputs + bytecode_outputs + ext_outputs - - def get_inputs(self): - """Get the list of files that are input to this command, ie. the - files that get installed as they are named in the build tree. - The files in this list correspond one-to-one to the output - filenames returned by 'get_outputs()'. - """ - inputs = [] - - if self.distribution.has_pure_modules(): - build_py = self.get_finalized_command('build_py') - inputs.extend(build_py.get_outputs()) - - if self.distribution.has_ext_modules(): - build_ext = self.get_finalized_command('build_ext') - inputs.extend(build_ext.get_outputs()) - - return inputs diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/install_scripts.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/install_scripts.py deleted file mode 100755 index ec6ec5a..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/install_scripts.py +++ /dev/null @@ -1,61 +0,0 @@ -"""distutils.command.install_scripts - -Implements the Distutils 'install_scripts' command, for installing -Python scripts.""" - -# contributed by Bastian Kleineidam - -import os -from ..core import Command -from distutils._log import log -from stat import ST_MODE - - -class install_scripts(Command): - - description = "install scripts (Python or otherwise)" - - user_options = [ - ('install-dir=', 'd', "directory to install scripts to"), - ('build-dir=', 'b', "build directory (where to install from)"), - ('force', 'f', "force installation (overwrite existing files)"), - ('skip-build', None, "skip the build steps"), - ] - - boolean_options = ['force', 'skip-build'] - - def initialize_options(self): - self.install_dir = None - self.force = 0 - self.build_dir = None - self.skip_build = None - - def finalize_options(self): - self.set_undefined_options('build', ('build_scripts', 'build_dir')) - self.set_undefined_options( - 'install', - ('install_scripts', 'install_dir'), - ('force', 'force'), - ('skip_build', 'skip_build'), - ) - - def run(self): - if not self.skip_build: - self.run_command('build_scripts') - self.outfiles = self.copy_tree(self.build_dir, self.install_dir) - if os.name == 'posix': - # Set the executable bits (owner, group, and world) on - # all the scripts we just installed. - for file in self.get_outputs(): - if self.dry_run: - log.info("changing mode of %s", file) - else: - mode = ((os.stat(file)[ST_MODE]) | 0o555) & 0o7777 - log.info("changing mode of %s to %o", file, mode) - os.chmod(file, mode) - - def get_inputs(self): - return self.distribution.scripts or [] - - def get_outputs(self): - return self.outfiles or [] diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/py37compat.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/py37compat.py deleted file mode 100755 index aa0c0a7..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/py37compat.py +++ /dev/null @@ -1,31 +0,0 @@ -import sys - - -def _pythonlib_compat(): - """ - On Python 3.7 and earlier, distutils would include the Python - library. See pypa/distutils#9. - """ - from distutils import sysconfig - - if not sysconfig.get_config_var('Py_ENABLED_SHARED'): - return - - yield 'python{}.{}{}'.format( - sys.hexversion >> 24, - (sys.hexversion >> 16) & 0xFF, - sysconfig.get_config_var('ABIFLAGS'), - ) - - -def compose(f1, f2): - return lambda *args, **kwargs: f1(f2(*args, **kwargs)) - - -pythonlib = ( - compose(list, _pythonlib_compat) - if sys.version_info < (3, 8) - and sys.platform != 'darwin' - and sys.platform[:3] != 'aix' - else list -) diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/register.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/register.py deleted file mode 100755 index 55c1045..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/register.py +++ /dev/null @@ -1,321 +0,0 @@ -"""distutils.command.register - -Implements the Distutils 'register' command (register with the repository). -""" - -# created 2002/10/21, Richard Jones - -import getpass -import io -import logging -import urllib.parse -import urllib.request -from warnings import warn - -from ..core import PyPIRCCommand -from distutils._log import log - - -class register(PyPIRCCommand): - - description = "register the distribution with the Python package index" - user_options = PyPIRCCommand.user_options + [ - ('list-classifiers', None, 'list the valid Trove classifiers'), - ( - 'strict', - None, - 'Will stop the registering if the meta-data are not fully compliant', - ), - ] - boolean_options = PyPIRCCommand.boolean_options + [ - 'verify', - 'list-classifiers', - 'strict', - ] - - sub_commands = [('check', lambda self: True)] - - def initialize_options(self): - PyPIRCCommand.initialize_options(self) - self.list_classifiers = 0 - self.strict = 0 - - def finalize_options(self): - PyPIRCCommand.finalize_options(self) - # setting options for the `check` subcommand - check_options = { - 'strict': ('register', self.strict), - 'restructuredtext': ('register', 1), - } - self.distribution.command_options['check'] = check_options - - def run(self): - self.finalize_options() - self._set_config() - - # Run sub commands - for cmd_name in self.get_sub_commands(): - self.run_command(cmd_name) - - if self.dry_run: - self.verify_metadata() - elif self.list_classifiers: - self.classifiers() - else: - self.send_metadata() - - def check_metadata(self): - """Deprecated API.""" - warn( - "distutils.command.register.check_metadata is deprecated; " - "use the check command instead", - DeprecationWarning, - ) - check = self.distribution.get_command_obj('check') - check.ensure_finalized() - check.strict = self.strict - check.restructuredtext = 1 - check.run() - - def _set_config(self): - '''Reads the configuration file and set attributes.''' - config = self._read_pypirc() - if config != {}: - self.username = config['username'] - self.password = config['password'] - self.repository = config['repository'] - self.realm = config['realm'] - self.has_config = True - else: - if self.repository not in ('pypi', self.DEFAULT_REPOSITORY): - raise ValueError('%s not found in .pypirc' % self.repository) - if self.repository == 'pypi': - self.repository = self.DEFAULT_REPOSITORY - self.has_config = False - - def classifiers(self): - '''Fetch the list of classifiers from the server.''' - url = self.repository + '?:action=list_classifiers' - response = urllib.request.urlopen(url) - log.info(self._read_pypi_response(response)) - - def verify_metadata(self): - '''Send the metadata to the package index server to be checked.''' - # send the info to the server and report the result - (code, result) = self.post_to_server(self.build_post_data('verify')) - log.info('Server response (%s): %s', code, result) - - def send_metadata(self): # noqa: C901 - '''Send the metadata to the package index server. - - Well, do the following: - 1. figure who the user is, and then - 2. send the data as a Basic auth'ed POST. - - First we try to read the username/password from $HOME/.pypirc, - which is a ConfigParser-formatted file with a section - [distutils] containing username and password entries (both - in clear text). Eg: - - [distutils] - index-servers = - pypi - - [pypi] - username: fred - password: sekrit - - Otherwise, to figure who the user is, we offer the user three - choices: - - 1. use existing login, - 2. register as a new user, or - 3. set the password to a random string and email the user. - - ''' - # see if we can short-cut and get the username/password from the - # config - if self.has_config: - choice = '1' - username = self.username - password = self.password - else: - choice = 'x' - username = password = '' - - # get the user's login info - choices = '1 2 3 4'.split() - while choice not in choices: - self.announce( - '''\ -We need to know who you are, so please choose either: - 1. use your existing login, - 2. register as a new user, - 3. have the server generate a new password for you (and email it to you), or - 4. quit -Your selection [default 1]: ''', - logging.INFO, - ) - choice = input() - if not choice: - choice = '1' - elif choice not in choices: - print('Please choose one of the four options!') - - if choice == '1': - # get the username and password - while not username: - username = input('Username: ') - while not password: - password = getpass.getpass('Password: ') - - # set up the authentication - auth = urllib.request.HTTPPasswordMgr() - host = urllib.parse.urlparse(self.repository)[1] - auth.add_password(self.realm, host, username, password) - # send the info to the server and report the result - code, result = self.post_to_server(self.build_post_data('submit'), auth) - self.announce('Server response ({}): {}'.format(code, result), logging.INFO) - - # possibly save the login - if code == 200: - if self.has_config: - # sharing the password in the distribution instance - # so the upload command can reuse it - self.distribution.password = password - else: - self.announce( - ( - 'I can store your PyPI login so future ' - 'submissions will be faster.' - ), - logging.INFO, - ) - self.announce( - '(the login will be stored in %s)' % self._get_rc_file(), - logging.INFO, - ) - choice = 'X' - while choice.lower() not in 'yn': - choice = input('Save your login (y/N)?') - if not choice: - choice = 'n' - if choice.lower() == 'y': - self._store_pypirc(username, password) - - elif choice == '2': - data = {':action': 'user'} - data['name'] = data['password'] = data['email'] = '' - data['confirm'] = None - while not data['name']: - data['name'] = input('Username: ') - while data['password'] != data['confirm']: - while not data['password']: - data['password'] = getpass.getpass('Password: ') - while not data['confirm']: - data['confirm'] = getpass.getpass(' Confirm: ') - if data['password'] != data['confirm']: - data['password'] = '' - data['confirm'] = None - print("Password and confirm don't match!") - while not data['email']: - data['email'] = input(' EMail: ') - code, result = self.post_to_server(data) - if code != 200: - log.info('Server response (%s): %s', code, result) - else: - log.info('You will receive an email shortly.') - log.info('Follow the instructions in it to ' 'complete registration.') - elif choice == '3': - data = {':action': 'password_reset'} - data['email'] = '' - while not data['email']: - data['email'] = input('Your email address: ') - code, result = self.post_to_server(data) - log.info('Server response (%s): %s', code, result) - - def build_post_data(self, action): - # figure the data to send - the metadata plus some additional - # information used by the package server - meta = self.distribution.metadata - data = { - ':action': action, - 'metadata_version': '1.0', - 'name': meta.get_name(), - 'version': meta.get_version(), - 'summary': meta.get_description(), - 'home_page': meta.get_url(), - 'author': meta.get_contact(), - 'author_email': meta.get_contact_email(), - 'license': meta.get_licence(), - 'description': meta.get_long_description(), - 'keywords': meta.get_keywords(), - 'platform': meta.get_platforms(), - 'classifiers': meta.get_classifiers(), - 'download_url': meta.get_download_url(), - # PEP 314 - 'provides': meta.get_provides(), - 'requires': meta.get_requires(), - 'obsoletes': meta.get_obsoletes(), - } - if data['provides'] or data['requires'] or data['obsoletes']: - data['metadata_version'] = '1.1' - return data - - def post_to_server(self, data, auth=None): # noqa: C901 - '''Post a query to the server, and return a string response.''' - if 'name' in data: - self.announce( - 'Registering {} to {}'.format(data['name'], self.repository), - logging.INFO, - ) - # Build up the MIME payload for the urllib2 POST data - boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254' - sep_boundary = '\n--' + boundary - end_boundary = sep_boundary + '--' - body = io.StringIO() - for key, value in data.items(): - # handle multiple entries for the same name - if type(value) not in (type([]), type(())): - value = [value] - for value in value: - value = str(value) - body.write(sep_boundary) - body.write('\nContent-Disposition: form-data; name="%s"' % key) - body.write("\n\n") - body.write(value) - if value and value[-1] == '\r': - body.write('\n') # write an extra newline (lurve Macs) - body.write(end_boundary) - body.write("\n") - body = body.getvalue().encode("utf-8") - - # build the Request - headers = { - 'Content-type': 'multipart/form-data; boundary=%s; charset=utf-8' - % boundary, - 'Content-length': str(len(body)), - } - req = urllib.request.Request(self.repository, body, headers) - - # handle HTTP and include the Basic Auth handler - opener = urllib.request.build_opener( - urllib.request.HTTPBasicAuthHandler(password_mgr=auth) - ) - data = '' - try: - result = opener.open(req) - except urllib.error.HTTPError as e: - if self.show_response: - data = e.fp.read() - result = e.code, e.msg - except urllib.error.URLError as e: - result = 500, str(e) - else: - if self.show_response: - data = self._read_pypi_response(result) - result = 200, 'OK' - if self.show_response: - msg = '\n'.join(('-' * 75, data, '-' * 75)) - self.announce(msg, logging.INFO) - return result diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/sdist.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/sdist.py deleted file mode 100755 index 5cfd4c1..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/sdist.py +++ /dev/null @@ -1,531 +0,0 @@ -"""distutils.command.sdist - -Implements the Distutils 'sdist' command (create a source distribution).""" - -import os -import sys -from glob import glob -from warnings import warn - -from ..core import Command -from distutils import dir_util -from distutils import file_util -from distutils import archive_util -from ..text_file import TextFile -from ..filelist import FileList -from distutils._log import log -from ..util import convert_path -from ..errors import DistutilsOptionError, DistutilsTemplateError - - -def show_formats(): - """Print all possible values for the 'formats' option (used by - the "--help-formats" command-line option). - """ - from ..fancy_getopt import FancyGetopt - from ..archive_util import ARCHIVE_FORMATS - - formats = [] - for format in ARCHIVE_FORMATS.keys(): - formats.append(("formats=" + format, None, ARCHIVE_FORMATS[format][2])) - formats.sort() - FancyGetopt(formats).print_help("List of available source distribution formats:") - - -class sdist(Command): - - description = "create a source distribution (tarball, zip file, etc.)" - - def checking_metadata(self): - """Callable used for the check sub-command. - - Placed here so user_options can view it""" - return self.metadata_check - - user_options = [ - ('template=', 't', "name of manifest template file [default: MANIFEST.in]"), - ('manifest=', 'm', "name of manifest file [default: MANIFEST]"), - ( - 'use-defaults', - None, - "include the default file set in the manifest " - "[default; disable with --no-defaults]", - ), - ('no-defaults', None, "don't include the default file set"), - ( - 'prune', - None, - "specifically exclude files/directories that should not be " - "distributed (build tree, RCS/CVS dirs, etc.) " - "[default; disable with --no-prune]", - ), - ('no-prune', None, "don't automatically exclude anything"), - ( - 'manifest-only', - 'o', - "just regenerate the manifest and then stop " "(implies --force-manifest)", - ), - ( - 'force-manifest', - 'f', - "forcibly regenerate the manifest and carry on as usual. " - "Deprecated: now the manifest is always regenerated.", - ), - ('formats=', None, "formats for source distribution (comma-separated list)"), - ( - 'keep-temp', - 'k', - "keep the distribution tree around after creating " + "archive file(s)", - ), - ( - 'dist-dir=', - 'd', - "directory to put the source distribution archive(s) in " "[default: dist]", - ), - ( - 'metadata-check', - None, - "Ensure that all required elements of meta-data " - "are supplied. Warn if any missing. [default]", - ), - ( - 'owner=', - 'u', - "Owner name used when creating a tar file [default: current user]", - ), - ( - 'group=', - 'g', - "Group name used when creating a tar file [default: current group]", - ), - ] - - boolean_options = [ - 'use-defaults', - 'prune', - 'manifest-only', - 'force-manifest', - 'keep-temp', - 'metadata-check', - ] - - help_options = [ - ('help-formats', None, "list available distribution formats", show_formats), - ] - - negative_opt = {'no-defaults': 'use-defaults', 'no-prune': 'prune'} - - sub_commands = [('check', checking_metadata)] - - READMES = ('README', 'README.txt', 'README.rst') - - def initialize_options(self): - # 'template' and 'manifest' are, respectively, the names of - # the manifest template and manifest file. - self.template = None - self.manifest = None - - # 'use_defaults': if true, we will include the default file set - # in the manifest - self.use_defaults = 1 - self.prune = 1 - - self.manifest_only = 0 - self.force_manifest = 0 - - self.formats = ['gztar'] - self.keep_temp = 0 - self.dist_dir = None - - self.archive_files = None - self.metadata_check = 1 - self.owner = None - self.group = None - - def finalize_options(self): - if self.manifest is None: - self.manifest = "MANIFEST" - if self.template is None: - self.template = "MANIFEST.in" - - self.ensure_string_list('formats') - - bad_format = archive_util.check_archive_formats(self.formats) - if bad_format: - raise DistutilsOptionError("unknown archive format '%s'" % bad_format) - - if self.dist_dir is None: - self.dist_dir = "dist" - - def run(self): - # 'filelist' contains the list of files that will make up the - # manifest - self.filelist = FileList() - - # Run sub commands - for cmd_name in self.get_sub_commands(): - self.run_command(cmd_name) - - # Do whatever it takes to get the list of files to process - # (process the manifest template, read an existing manifest, - # whatever). File list is accumulated in 'self.filelist'. - self.get_file_list() - - # If user just wanted us to regenerate the manifest, stop now. - if self.manifest_only: - return - - # Otherwise, go ahead and create the source distribution tarball, - # or zipfile, or whatever. - self.make_distribution() - - def check_metadata(self): - """Deprecated API.""" - warn( - "distutils.command.sdist.check_metadata is deprecated, \ - use the check command instead", - PendingDeprecationWarning, - ) - check = self.distribution.get_command_obj('check') - check.ensure_finalized() - check.run() - - def get_file_list(self): - """Figure out the list of files to include in the source - distribution, and put it in 'self.filelist'. This might involve - reading the manifest template (and writing the manifest), or just - reading the manifest, or just using the default file set -- it all - depends on the user's options. - """ - # new behavior when using a template: - # the file list is recalculated every time because - # even if MANIFEST.in or setup.py are not changed - # the user might have added some files in the tree that - # need to be included. - # - # This makes --force the default and only behavior with templates. - template_exists = os.path.isfile(self.template) - if not template_exists and self._manifest_is_not_generated(): - self.read_manifest() - self.filelist.sort() - self.filelist.remove_duplicates() - return - - if not template_exists: - self.warn( - ("manifest template '%s' does not exist " + "(using default file list)") - % self.template - ) - self.filelist.findall() - - if self.use_defaults: - self.add_defaults() - - if template_exists: - self.read_template() - - if self.prune: - self.prune_file_list() - - self.filelist.sort() - self.filelist.remove_duplicates() - self.write_manifest() - - def add_defaults(self): - """Add all the default files to self.filelist: - - README or README.txt - - setup.py - - test/test*.py - - all pure Python modules mentioned in setup script - - all files pointed by package_data (build_py) - - all files defined in data_files. - - all files defined as scripts. - - all C sources listed as part of extensions or C libraries - in the setup script (doesn't catch C headers!) - Warns if (README or README.txt) or setup.py are missing; everything - else is optional. - """ - self._add_defaults_standards() - self._add_defaults_optional() - self._add_defaults_python() - self._add_defaults_data_files() - self._add_defaults_ext() - self._add_defaults_c_libs() - self._add_defaults_scripts() - - @staticmethod - def _cs_path_exists(fspath): - """ - Case-sensitive path existence check - - >>> sdist._cs_path_exists(__file__) - True - >>> sdist._cs_path_exists(__file__.upper()) - False - """ - if not os.path.exists(fspath): - return False - # make absolute so we always have a directory - abspath = os.path.abspath(fspath) - directory, filename = os.path.split(abspath) - return filename in os.listdir(directory) - - def _add_defaults_standards(self): - standards = [self.READMES, self.distribution.script_name] - for fn in standards: - if isinstance(fn, tuple): - alts = fn - got_it = False - for fn in alts: - if self._cs_path_exists(fn): - got_it = True - self.filelist.append(fn) - break - - if not got_it: - self.warn( - "standard file not found: should have one of " + ', '.join(alts) - ) - else: - if self._cs_path_exists(fn): - self.filelist.append(fn) - else: - self.warn("standard file '%s' not found" % fn) - - def _add_defaults_optional(self): - optional = ['test/test*.py', 'setup.cfg'] - for pattern in optional: - files = filter(os.path.isfile, glob(pattern)) - self.filelist.extend(files) - - def _add_defaults_python(self): - # build_py is used to get: - # - python modules - # - files defined in package_data - build_py = self.get_finalized_command('build_py') - - # getting python files - if self.distribution.has_pure_modules(): - self.filelist.extend(build_py.get_source_files()) - - # getting package_data files - # (computed in build_py.data_files by build_py.finalize_options) - for pkg, src_dir, build_dir, filenames in build_py.data_files: - for filename in filenames: - self.filelist.append(os.path.join(src_dir, filename)) - - def _add_defaults_data_files(self): - # getting distribution.data_files - if self.distribution.has_data_files(): - for item in self.distribution.data_files: - if isinstance(item, str): - # plain file - item = convert_path(item) - if os.path.isfile(item): - self.filelist.append(item) - else: - # a (dirname, filenames) tuple - dirname, filenames = item - for f in filenames: - f = convert_path(f) - if os.path.isfile(f): - self.filelist.append(f) - - def _add_defaults_ext(self): - if self.distribution.has_ext_modules(): - build_ext = self.get_finalized_command('build_ext') - self.filelist.extend(build_ext.get_source_files()) - - def _add_defaults_c_libs(self): - if self.distribution.has_c_libraries(): - build_clib = self.get_finalized_command('build_clib') - self.filelist.extend(build_clib.get_source_files()) - - def _add_defaults_scripts(self): - if self.distribution.has_scripts(): - build_scripts = self.get_finalized_command('build_scripts') - self.filelist.extend(build_scripts.get_source_files()) - - def read_template(self): - """Read and parse manifest template file named by self.template. - - (usually "MANIFEST.in") The parsing and processing is done by - 'self.filelist', which updates itself accordingly. - """ - log.info("reading manifest template '%s'", self.template) - template = TextFile( - self.template, - strip_comments=1, - skip_blanks=1, - join_lines=1, - lstrip_ws=1, - rstrip_ws=1, - collapse_join=1, - ) - - try: - while True: - line = template.readline() - if line is None: # end of file - break - - try: - self.filelist.process_template_line(line) - # the call above can raise a DistutilsTemplateError for - # malformed lines, or a ValueError from the lower-level - # convert_path function - except (DistutilsTemplateError, ValueError) as msg: - self.warn( - "%s, line %d: %s" - % (template.filename, template.current_line, msg) - ) - finally: - template.close() - - def prune_file_list(self): - """Prune off branches that might slip into the file list as created - by 'read_template()', but really don't belong there: - * the build tree (typically "build") - * the release tree itself (only an issue if we ran "sdist" - previously with --keep-temp, or it aborted) - * any RCS, CVS, .svn, .hg, .git, .bzr, _darcs directories - """ - build = self.get_finalized_command('build') - base_dir = self.distribution.get_fullname() - - self.filelist.exclude_pattern(None, prefix=build.build_base) - self.filelist.exclude_pattern(None, prefix=base_dir) - - if sys.platform == 'win32': - seps = r'/|\\' - else: - seps = '/' - - vcs_dirs = ['RCS', 'CVS', r'\.svn', r'\.hg', r'\.git', r'\.bzr', '_darcs'] - vcs_ptrn = r'(^|{})({})({}).*'.format(seps, '|'.join(vcs_dirs), seps) - self.filelist.exclude_pattern(vcs_ptrn, is_regex=1) - - def write_manifest(self): - """Write the file list in 'self.filelist' (presumably as filled in - by 'add_defaults()' and 'read_template()') to the manifest file - named by 'self.manifest'. - """ - if self._manifest_is_not_generated(): - log.info( - "not writing to manually maintained " - "manifest file '%s'" % self.manifest - ) - return - - content = self.filelist.files[:] - content.insert(0, '# file GENERATED by distutils, do NOT edit') - self.execute( - file_util.write_file, - (self.manifest, content), - "writing manifest file '%s'" % self.manifest, - ) - - def _manifest_is_not_generated(self): - # check for special comment used in 3.1.3 and higher - if not os.path.isfile(self.manifest): - return False - - fp = open(self.manifest) - try: - first_line = fp.readline() - finally: - fp.close() - return first_line != '# file GENERATED by distutils, do NOT edit\n' - - def read_manifest(self): - """Read the manifest file (named by 'self.manifest') and use it to - fill in 'self.filelist', the list of files to include in the source - distribution. - """ - log.info("reading manifest file '%s'", self.manifest) - with open(self.manifest) as manifest: - for line in manifest: - # ignore comments and blank lines - line = line.strip() - if line.startswith('#') or not line: - continue - self.filelist.append(line) - - def make_release_tree(self, base_dir, files): - """Create the directory tree that will become the source - distribution archive. All directories implied by the filenames in - 'files' are created under 'base_dir', and then we hard link or copy - (if hard linking is unavailable) those files into place. - Essentially, this duplicates the developer's source tree, but in a - directory named after the distribution, containing only the files - to be distributed. - """ - # Create all the directories under 'base_dir' necessary to - # put 'files' there; the 'mkpath()' is just so we don't die - # if the manifest happens to be empty. - self.mkpath(base_dir) - dir_util.create_tree(base_dir, files, dry_run=self.dry_run) - - # And walk over the list of files, either making a hard link (if - # os.link exists) to each one that doesn't already exist in its - # corresponding location under 'base_dir', or copying each file - # that's out-of-date in 'base_dir'. (Usually, all files will be - # out-of-date, because by default we blow away 'base_dir' when - # we're done making the distribution archives.) - - if hasattr(os, 'link'): # can make hard links on this system - link = 'hard' - msg = "making hard links in %s..." % base_dir - else: # nope, have to copy - link = None - msg = "copying files to %s..." % base_dir - - if not files: - log.warning("no files to distribute -- empty manifest?") - else: - log.info(msg) - for file in files: - if not os.path.isfile(file): - log.warning("'%s' not a regular file -- skipping", file) - else: - dest = os.path.join(base_dir, file) - self.copy_file(file, dest, link=link) - - self.distribution.metadata.write_pkg_info(base_dir) - - def make_distribution(self): - """Create the source distribution(s). First, we create the release - tree with 'make_release_tree()'; then, we create all required - archive files (according to 'self.formats') from the release tree. - Finally, we clean up by blowing away the release tree (unless - 'self.keep_temp' is true). The list of archive files created is - stored so it can be retrieved later by 'get_archive_files()'. - """ - # Don't warn about missing meta-data here -- should be (and is!) - # done elsewhere. - base_dir = self.distribution.get_fullname() - base_name = os.path.join(self.dist_dir, base_dir) - - self.make_release_tree(base_dir, self.filelist.files) - archive_files = [] # remember names of files we create - # tar archive must be created last to avoid overwrite and remove - if 'tar' in self.formats: - self.formats.append(self.formats.pop(self.formats.index('tar'))) - - for fmt in self.formats: - file = self.make_archive( - base_name, fmt, base_dir=base_dir, owner=self.owner, group=self.group - ) - archive_files.append(file) - self.distribution.dist_files.append(('sdist', '', file)) - - self.archive_files = archive_files - - if not self.keep_temp: - dir_util.remove_tree(base_dir, dry_run=self.dry_run) - - def get_archive_files(self): - """Return the list of archive files created when the command - was run, or None if the command hasn't run yet. - """ - return self.archive_files diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/upload.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/command/upload.py deleted file mode 100755 index 16e15d8..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/command/upload.py +++ /dev/null @@ -1,207 +0,0 @@ -""" -distutils.command.upload - -Implements the Distutils 'upload' subcommand (upload package to a package -index). -""" - -import os -import io -import hashlib -import logging -from base64 import standard_b64encode -from urllib.request import urlopen, Request, HTTPError -from urllib.parse import urlparse -from ..errors import DistutilsError, DistutilsOptionError -from ..core import PyPIRCCommand -from ..spawn import spawn - - -# PyPI Warehouse supports MD5, SHA256, and Blake2 (blake2-256) -# https://bugs.python.org/issue40698 -_FILE_CONTENT_DIGESTS = { - "md5_digest": getattr(hashlib, "md5", None), - "sha256_digest": getattr(hashlib, "sha256", None), - "blake2_256_digest": getattr(hashlib, "blake2b", None), -} - - -class upload(PyPIRCCommand): - - description = "upload binary package to PyPI" - - user_options = PyPIRCCommand.user_options + [ - ('sign', 's', 'sign files to upload using gpg'), - ('identity=', 'i', 'GPG identity used to sign files'), - ] - - boolean_options = PyPIRCCommand.boolean_options + ['sign'] - - def initialize_options(self): - PyPIRCCommand.initialize_options(self) - self.username = '' - self.password = '' - self.show_response = 0 - self.sign = False - self.identity = None - - def finalize_options(self): - PyPIRCCommand.finalize_options(self) - if self.identity and not self.sign: - raise DistutilsOptionError("Must use --sign for --identity to have meaning") - config = self._read_pypirc() - if config != {}: - self.username = config['username'] - self.password = config['password'] - self.repository = config['repository'] - self.realm = config['realm'] - - # getting the password from the distribution - # if previously set by the register command - if not self.password and self.distribution.password: - self.password = self.distribution.password - - def run(self): - if not self.distribution.dist_files: - msg = ( - "Must create and upload files in one command " - "(e.g. setup.py sdist upload)" - ) - raise DistutilsOptionError(msg) - for command, pyversion, filename in self.distribution.dist_files: - self.upload_file(command, pyversion, filename) - - def upload_file(self, command, pyversion, filename): # noqa: C901 - # Makes sure the repository URL is compliant - schema, netloc, url, params, query, fragments = urlparse(self.repository) - if params or query or fragments: - raise AssertionError("Incompatible url %s" % self.repository) - - if schema not in ('http', 'https'): - raise AssertionError("unsupported schema " + schema) - - # Sign if requested - if self.sign: - gpg_args = ["gpg", "--detach-sign", "-a", filename] - if self.identity: - gpg_args[2:2] = ["--local-user", self.identity] - spawn(gpg_args, dry_run=self.dry_run) - - # Fill in the data - send all the meta-data in case we need to - # register a new release - f = open(filename, 'rb') - try: - content = f.read() - finally: - f.close() - - meta = self.distribution.metadata - data = { - # action - ':action': 'file_upload', - 'protocol_version': '1', - # identify release - 'name': meta.get_name(), - 'version': meta.get_version(), - # file content - 'content': (os.path.basename(filename), content), - 'filetype': command, - 'pyversion': pyversion, - # additional meta-data - 'metadata_version': '1.0', - 'summary': meta.get_description(), - 'home_page': meta.get_url(), - 'author': meta.get_contact(), - 'author_email': meta.get_contact_email(), - 'license': meta.get_licence(), - 'description': meta.get_long_description(), - 'keywords': meta.get_keywords(), - 'platform': meta.get_platforms(), - 'classifiers': meta.get_classifiers(), - 'download_url': meta.get_download_url(), - # PEP 314 - 'provides': meta.get_provides(), - 'requires': meta.get_requires(), - 'obsoletes': meta.get_obsoletes(), - } - - data['comment'] = '' - - # file content digests - for digest_name, digest_cons in _FILE_CONTENT_DIGESTS.items(): - if digest_cons is None: - continue - try: - data[digest_name] = digest_cons(content).hexdigest() - except ValueError: - # hash digest not available or blocked by security policy - pass - - if self.sign: - with open(filename + ".asc", "rb") as f: - data['gpg_signature'] = (os.path.basename(filename) + ".asc", f.read()) - - # set up the authentication - user_pass = (self.username + ":" + self.password).encode('ascii') - # The exact encoding of the authentication string is debated. - # Anyway PyPI only accepts ascii for both username or password. - auth = "Basic " + standard_b64encode(user_pass).decode('ascii') - - # Build up the MIME payload for the POST data - boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254' - sep_boundary = b'\r\n--' + boundary.encode('ascii') - end_boundary = sep_boundary + b'--\r\n' - body = io.BytesIO() - for key, value in data.items(): - title = '\r\nContent-Disposition: form-data; name="%s"' % key - # handle multiple entries for the same name - if not isinstance(value, list): - value = [value] - for value in value: - if type(value) is tuple: - title += '; filename="%s"' % value[0] - value = value[1] - else: - value = str(value).encode('utf-8') - body.write(sep_boundary) - body.write(title.encode('utf-8')) - body.write(b"\r\n\r\n") - body.write(value) - body.write(end_boundary) - body = body.getvalue() - - msg = "Submitting {} to {}".format(filename, self.repository) - self.announce(msg, logging.INFO) - - # build the Request - headers = { - 'Content-type': 'multipart/form-data; boundary=%s' % boundary, - 'Content-length': str(len(body)), - 'Authorization': auth, - } - - request = Request(self.repository, data=body, headers=headers) - # send the data - try: - result = urlopen(request) - status = result.getcode() - reason = result.msg - except HTTPError as e: - status = e.code - reason = e.msg - except OSError as e: - self.announce(str(e), logging.ERROR) - raise - - if status == 200: - self.announce( - 'Server response ({}): {}'.format(status, reason), logging.INFO - ) - if self.show_response: - text = self._read_pypi_response(result) - msg = '\n'.join(('-' * 75, text, '-' * 75)) - self.announce(msg, logging.INFO) - else: - msg = 'Upload failed ({}): {}'.format(status, reason) - self.announce(msg, logging.ERROR) - raise DistutilsError(msg) diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/config.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/config.py deleted file mode 100755 index 9a4044a..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/config.py +++ /dev/null @@ -1,139 +0,0 @@ -"""distutils.pypirc - -Provides the PyPIRCCommand class, the base class for the command classes -that uses .pypirc in the distutils.command package. -""" -import os -from configparser import RawConfigParser - -from .cmd import Command - -DEFAULT_PYPIRC = """\ -[distutils] -index-servers = - pypi - -[pypi] -username:%s -password:%s -""" - - -class PyPIRCCommand(Command): - """Base command that knows how to handle the .pypirc file""" - - DEFAULT_REPOSITORY = 'https://upload.pypi.org/legacy/' - DEFAULT_REALM = 'pypi' - repository = None - realm = None - - user_options = [ - ('repository=', 'r', "url of repository [default: %s]" % DEFAULT_REPOSITORY), - ('show-response', None, 'display full response text from server'), - ] - - boolean_options = ['show-response'] - - def _get_rc_file(self): - """Returns rc file path.""" - return os.path.join(os.path.expanduser('~'), '.pypirc') - - def _store_pypirc(self, username, password): - """Creates a default .pypirc file.""" - rc = self._get_rc_file() - with os.fdopen(os.open(rc, os.O_CREAT | os.O_WRONLY, 0o600), 'w') as f: - f.write(DEFAULT_PYPIRC % (username, password)) - - def _read_pypirc(self): # noqa: C901 - """Reads the .pypirc file.""" - rc = self._get_rc_file() - if os.path.exists(rc): - self.announce('Using PyPI login from %s' % rc) - repository = self.repository or self.DEFAULT_REPOSITORY - - config = RawConfigParser() - config.read(rc) - sections = config.sections() - 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() != '' - ] - if _servers == []: - # nothing set, let's try to get the default pypi - if 'pypi' in sections: - _servers = ['pypi'] - else: - # the file is not properly defined, returning - # an empty dict - return {} - for server in _servers: - current = {'server': server} - current['username'] = config.get(server, 'username') - - # optional params - for key, default in ( - ('repository', self.DEFAULT_REPOSITORY), - ('realm', self.DEFAULT_REALM), - ('password', None), - ): - if config.has_option(server, key): - current[key] = config.get(server, key) - else: - current[key] = default - - # 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', - ): - current['repository'] = self.DEFAULT_REPOSITORY - return current - - if ( - current['server'] == repository - or current['repository'] == repository - ): - return current - elif 'server-login' in sections: - # old format - server = 'server-login' - if config.has_option(server, 'repository'): - repository = config.get(server, 'repository') - else: - repository = self.DEFAULT_REPOSITORY - return { - 'username': config.get(server, 'username'), - 'password': config.get(server, 'password'), - 'repository': repository, - 'server': server, - 'realm': self.DEFAULT_REALM, - } - - return {} - - def _read_pypi_response(self, response): - """Read and decode a PyPI HTTP response.""" - import cgi - - content_type = response.getheader('content-type', 'text/plain') - encoding = cgi.parse_header(content_type)[1].get('charset', 'ascii') - return response.read().decode(encoding) - - def initialize_options(self): - """Initialize options.""" - self.repository = None - self.realm = None - self.show_response = 0 - - def finalize_options(self): - """Finalizes options.""" - if self.repository is None: - self.repository = self.DEFAULT_REPOSITORY - if self.realm is None: - self.realm = self.DEFAULT_REALM diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/core.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/core.py deleted file mode 100755 index 34cafbc..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/core.py +++ /dev/null @@ -1,291 +0,0 @@ -"""distutils.core - -The only module that needs to be imported to use the Distutils; provides -the 'setup' function (which is to be called from the setup script). Also -indirectly provides the Distribution and Command classes, although they are -really defined in distutils.dist and distutils.cmd. -""" - -import os -import sys -import tokenize - -from .debug import DEBUG -from .errors import ( - DistutilsSetupError, - DistutilsError, - CCompilerError, - DistutilsArgError, -) - -# Mainly import these so setup scripts can "from distutils.core import" them. -from .dist import Distribution -from .cmd import Command -from .config import PyPIRCCommand -from .extension import Extension - - -__all__ = ['Distribution', 'Command', 'PyPIRCCommand', 'Extension', 'setup'] - -# This is a barebones help message generated displayed when the user -# runs the setup script with no arguments at all. More useful help -# is generated with various --help options: global help, list commands, -# and per-command help. -USAGE = """\ -usage: %(script)s [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...] - or: %(script)s --help [cmd1 cmd2 ...] - or: %(script)s --help-commands - or: %(script)s cmd --help -""" - - -def gen_usage(script_name): - script = os.path.basename(script_name) - return USAGE % locals() - - -# Some mild magic to control the behaviour of 'setup()' from 'run_setup()'. -_setup_stop_after = None -_setup_distribution = None - -# Legal keyword arguments for the setup() function -setup_keywords = ( - 'distclass', - 'script_name', - 'script_args', - 'options', - 'name', - 'version', - 'author', - 'author_email', - 'maintainer', - 'maintainer_email', - 'url', - 'license', - 'description', - 'long_description', - 'keywords', - 'platforms', - 'classifiers', - 'download_url', - 'requires', - 'provides', - 'obsoletes', -) - -# Legal keyword arguments for the Extension constructor -extension_keywords = ( - 'name', - 'sources', - 'include_dirs', - 'define_macros', - 'undef_macros', - 'library_dirs', - 'libraries', - 'runtime_library_dirs', - 'extra_objects', - 'extra_compile_args', - 'extra_link_args', - 'swig_opts', - 'export_symbols', - 'depends', - 'language', -) - - -def setup(**attrs): # noqa: C901 - """The gateway to the Distutils: do everything your setup script needs - to do, in a highly flexible and user-driven way. Briefly: create a - Distribution instance; find and parse config files; parse the command - line; run each Distutils command found there, customized by the options - supplied to 'setup()' (as keyword arguments), in config files, and on - the command line. - - The Distribution instance might be an instance of a class supplied via - the 'distclass' keyword argument to 'setup'; if no such class is - supplied, then the Distribution class (in dist.py) is instantiated. - All other arguments to 'setup' (except for 'cmdclass') are used to set - attributes of the Distribution instance. - - The 'cmdclass' argument, if supplied, is a dictionary mapping command - names to command classes. Each command encountered on the command line - will be turned into a command class, which is in turn instantiated; any - class found in 'cmdclass' is used in place of the default, which is - (for command 'foo_bar') class 'foo_bar' in module - 'distutils.command.foo_bar'. The command class must provide a - 'user_options' attribute which is a list of option specifiers for - 'distutils.fancy_getopt'. Any command-line options between the current - and the next command are used to set attributes of the current command - object. - - When the entire command-line has been successfully parsed, calls the - 'run()' method on each command object in turn. This method will be - driven entirely by the Distribution object (which each command object - has a reference to, thanks to its constructor), and the - command-specific options that became attributes of each command - object. - """ - - global _setup_stop_after, _setup_distribution - - # Determine the distribution class -- either caller-supplied or - # our Distribution (see below). - klass = attrs.get('distclass') - if klass: - del attrs['distclass'] - else: - klass = Distribution - - if 'script_name' not in attrs: - attrs['script_name'] = os.path.basename(sys.argv[0]) - if 'script_args' not in attrs: - attrs['script_args'] = sys.argv[1:] - - # Create the Distribution instance, using the remaining arguments - # (ie. everything except distclass) to initialize it - try: - _setup_distribution = dist = klass(attrs) - except DistutilsSetupError as msg: - if 'name' not in attrs: - raise SystemExit("error in setup command: %s" % msg) - else: - raise SystemExit("error in {} setup command: {}".format(attrs['name'], msg)) - - if _setup_stop_after == "init": - return dist - - # Find and parse the config file(s): they will override options from - # the setup script, but be overridden by the command line. - dist.parse_config_files() - - if DEBUG: - print("options (after parsing config files):") - dist.dump_option_dicts() - - if _setup_stop_after == "config": - return dist - - # Parse the command line and override config files; any - # command-line errors are the end user's fault, so turn them into - # SystemExit to suppress tracebacks. - try: - ok = dist.parse_command_line() - except DistutilsArgError as msg: - raise SystemExit(gen_usage(dist.script_name) + "\nerror: %s" % msg) - - if DEBUG: - print("options (after parsing command line):") - dist.dump_option_dicts() - - if _setup_stop_after == "commandline": - return dist - - # And finally, run all the commands found on the command line. - if ok: - return run_commands(dist) - - return dist - - -# setup () - - -def run_commands(dist): - """Given a Distribution object run all the commands, - raising ``SystemExit`` errors in the case of failure. - - This function assumes that either ``sys.argv`` or ``dist.script_args`` - is already set accordingly. - """ - try: - dist.run_commands() - except KeyboardInterrupt: - raise SystemExit("interrupted") - except OSError as exc: - if DEBUG: - sys.stderr.write("error: {}\n".format(exc)) - raise - else: - raise SystemExit("error: {}".format(exc)) - - except (DistutilsError, CCompilerError) as msg: - if DEBUG: - raise - else: - raise SystemExit("error: " + str(msg)) - - return dist - - -def run_setup(script_name, script_args=None, stop_after="run"): - """Run a setup script in a somewhat controlled environment, and - return the Distribution instance that drives things. This is useful - if you need to find out the distribution meta-data (passed as - keyword args from 'script' to 'setup()', or the contents of the - config files or command-line. - - 'script_name' is a file that will be read and run with 'exec()'; - 'sys.argv[0]' will be replaced with 'script' for the duration of the - call. 'script_args' is a list of strings; if supplied, - 'sys.argv[1:]' will be replaced by 'script_args' for the duration of - the call. - - 'stop_after' tells 'setup()' when to stop processing; possible - values: - init - stop after the Distribution instance has been created and - populated with the keyword arguments to 'setup()' - config - stop after config files have been parsed (and their data - stored in the Distribution instance) - commandline - stop after the command-line ('sys.argv[1:]' or 'script_args') - have been parsed (and the data stored in the Distribution) - run [default] - stop after all commands have been run (the same as if 'setup()' - had been called in the usual way - - Returns the Distribution instance, which provides all information - used to drive the Distutils. - """ - if stop_after not in ('init', 'config', 'commandline', 'run'): - raise ValueError("invalid value for 'stop_after': {!r}".format(stop_after)) - - global _setup_stop_after, _setup_distribution - _setup_stop_after = stop_after - - save_argv = sys.argv.copy() - g = {'__file__': script_name, '__name__': '__main__'} - try: - try: - sys.argv[0] = script_name - if script_args is not None: - sys.argv[1:] = script_args - # tokenize.open supports automatic encoding detection - with tokenize.open(script_name) as f: - code = f.read().replace(r'\r\n', r'\n') - exec(code, g) - finally: - sys.argv = save_argv - _setup_stop_after = None - except SystemExit: - # Hmm, should we do something if exiting with a non-zero code - # (ie. error)? - pass - - if _setup_distribution is None: - raise RuntimeError( - ( - "'distutils.core.setup()' was never called -- " - "perhaps '%s' is not a Distutils setup script?" - ) - % script_name - ) - - # I wonder if the setup script's namespace -- g and l -- would be of - # any interest to callers? - # print "_setup_distribution:", _setup_distribution - return _setup_distribution - - -# run_setup () diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/cygwinccompiler.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/cygwinccompiler.py deleted file mode 100755 index f15b8ee..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/cygwinccompiler.py +++ /dev/null @@ -1,358 +0,0 @@ -"""distutils.cygwinccompiler - -Provides the CygwinCCompiler class, a subclass of UnixCCompiler that -handles the Cygwin port of the GNU C compiler to Windows. It also contains -the Mingw32CCompiler class which handles the mingw32 port of GCC (same as -cygwin in no-cygwin mode). -""" - -import os -import re -import sys -import copy -import shlex -import warnings -from subprocess import check_output - -from .unixccompiler import UnixCCompiler -from .file_util import write_file -from .errors import ( - DistutilsExecError, - DistutilsPlatformError, - CCompilerError, - CompileError, -) -from .version import LooseVersion, suppress_known_deprecation -from ._collections import RangeMap - - -_msvcr_lookup = RangeMap.left( - { - # MSVC 7.0 - 1300: ['msvcr70'], - # MSVC 7.1 - 1310: ['msvcr71'], - # VS2005 / MSVC 8.0 - 1400: ['msvcr80'], - # VS2008 / MSVC 9.0 - 1500: ['msvcr90'], - # VS2010 / MSVC 10.0 - 1600: ['msvcr100'], - # VS2012 / MSVC 11.0 - 1700: ['msvcr110'], - # VS2013 / MSVC 12.0 - 1800: ['msvcr120'], - # VS2015 / MSVC 14.0 - 1900: ['ucrt', 'vcruntime140'], - 2000: RangeMap.undefined_value, - }, -) - - -def get_msvcr(): - """Include the appropriate MSVC runtime library if Python was built - with MSVC 7.0 or later. - """ - match = re.search(r'MSC v\.(\d{4})', sys.version) - try: - msc_ver = int(match.group(1)) - except AttributeError: - return - try: - return _msvcr_lookup[msc_ver] - except KeyError: - raise ValueError("Unknown MS Compiler version %s " % msc_ver) - - -_runtime_library_dirs_msg = ( - "Unable to set runtime library search path on Windows, " - "usually indicated by `runtime_library_dirs` parameter to Extension" -) - - -class CygwinCCompiler(UnixCCompiler): - """Handles the Cygwin port of the GNU C compiler to Windows.""" - - compiler_type = 'cygwin' - obj_extension = ".o" - static_lib_extension = ".a" - shared_lib_extension = ".dll.a" - dylib_lib_extension = ".dll" - static_lib_format = "lib%s%s" - shared_lib_format = "lib%s%s" - dylib_lib_format = "cyg%s%s" - exe_extension = ".exe" - - def __init__(self, verbose=0, dry_run=0, force=0): - - super().__init__(verbose, dry_run, force) - - status, details = check_config_h() - self.debug_print( - "Python's GCC status: {} (details: {})".format(status, details) - ) - if status is not CONFIG_H_OK: - self.warn( - "Python's pyconfig.h doesn't seem to support your compiler. " - "Reason: %s. " - "Compiling may fail because of undefined preprocessor macros." % details - ) - - self.cc = os.environ.get('CC', 'gcc') - self.cxx = os.environ.get('CXX', 'g++') - - self.linker_dll = self.cc - shared_option = "-shared" - - self.set_executables( - compiler='%s -mcygwin -O -Wall' % self.cc, - compiler_so='%s -mcygwin -mdll -O -Wall' % self.cc, - compiler_cxx='%s -mcygwin -O -Wall' % self.cxx, - linker_exe='%s -mcygwin' % self.cc, - linker_so=('{} -mcygwin {}'.format(self.linker_dll, shared_option)), - ) - - # Include the appropriate MSVC runtime library if Python was built - # with MSVC 7.0 or later. - self.dll_libraries = get_msvcr() - - @property - def gcc_version(self): - # Older numpy dependend on this existing to check for ancient - # gcc versions. This doesn't make much sense with clang etc so - # just hardcode to something recent. - # https://github.com/numpy/numpy/pull/20333 - warnings.warn( - "gcc_version attribute of CygwinCCompiler is deprecated. " - "Instead of returning actual gcc version a fixed value 11.2.0 is returned.", - DeprecationWarning, - stacklevel=2, - ) - with suppress_known_deprecation(): - return LooseVersion("11.2.0") - - def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts): - """Compiles the source by spawning GCC and windres if needed.""" - if ext == '.rc' or ext == '.res': - # gcc needs '.res' and '.rc' compiled to object files !!! - try: - self.spawn(["windres", "-i", src, "-o", obj]) - except DistutilsExecError as msg: - raise CompileError(msg) - else: # for other files use the C-compiler - try: - self.spawn( - self.compiler_so + cc_args + [src, '-o', obj] + extra_postargs - ) - except DistutilsExecError as msg: - raise CompileError(msg) - - def link( - self, - target_desc, - objects, - output_filename, - output_dir=None, - libraries=None, - library_dirs=None, - runtime_library_dirs=None, - export_symbols=None, - debug=0, - extra_preargs=None, - extra_postargs=None, - build_temp=None, - target_lang=None, - ): - """Link the objects.""" - # use separate copies, so we can modify the lists - extra_preargs = copy.copy(extra_preargs or []) - libraries = copy.copy(libraries or []) - objects = copy.copy(objects or []) - - if runtime_library_dirs: - self.warn(_runtime_library_dirs_msg) - - # Additional libraries - libraries.extend(self.dll_libraries) - - # handle export symbols by creating a def-file - # with executables this only works with gcc/ld as linker - if (export_symbols is not None) and ( - target_desc != self.EXECUTABLE or self.linker_dll == "gcc" - ): - # (The linker doesn't do anything if output is up-to-date. - # So it would probably better to check if we really need this, - # but for this we had to insert some unchanged parts of - # UnixCCompiler, and this is not what we want.) - - # we want to put some files in the same directory as the - # object files are, build_temp doesn't help much - # where are the object files - temp_dir = os.path.dirname(objects[0]) - # name of dll to give the helper files the same base name - (dll_name, dll_extension) = os.path.splitext( - os.path.basename(output_filename) - ) - - # generate the filenames for these files - def_file = os.path.join(temp_dir, dll_name + ".def") - - # Generate .def file - contents = ["LIBRARY %s" % os.path.basename(output_filename), "EXPORTS"] - for sym in export_symbols: - contents.append(sym) - self.execute(write_file, (def_file, contents), "writing %s" % def_file) - - # next add options for def-file - - # for gcc/ld the def-file is specified as any object files - objects.append(def_file) - - # end: if ((export_symbols is not None) and - # (target_desc != self.EXECUTABLE or self.linker_dll == "gcc")): - - # who wants symbols and a many times larger output file - # should explicitly switch the debug mode on - # otherwise we let ld strip the output file - # (On my machine: 10KiB < stripped_file < ??100KiB - # unstripped_file = stripped_file + XXX KiB - # ( XXX=254 for a typical python extension)) - if not debug: - extra_preargs.append("-s") - - UnixCCompiler.link( - self, - target_desc, - objects, - output_filename, - output_dir, - libraries, - library_dirs, - runtime_library_dirs, - None, # export_symbols, we do this in our def-file - debug, - extra_preargs, - extra_postargs, - build_temp, - target_lang, - ) - - def runtime_library_dir_option(self, dir): - # cygwin doesn't support rpath. While in theory we could error - # out like MSVC does, code might expect it to work like on Unix, so - # just warn and hope for the best. - self.warn(_runtime_library_dirs_msg) - return [] - - # -- Miscellaneous methods ----------------------------------------- - - def _make_out_path(self, output_dir, strip_dir, src_name): - # use normcase to make sure '.rc' is really '.rc' and not '.RC' - norm_src_name = os.path.normcase(src_name) - return super()._make_out_path(output_dir, strip_dir, norm_src_name) - - @property - def out_extensions(self): - """ - Add support for rc and res files. - """ - return { - **super().out_extensions, - **{ext: ext + self.obj_extension for ext in ('.res', '.rc')}, - } - - -# the same as cygwin plus some additional parameters -class Mingw32CCompiler(CygwinCCompiler): - """Handles the Mingw32 port of the GNU C compiler to Windows.""" - - compiler_type = 'mingw32' - - def __init__(self, verbose=0, dry_run=0, force=0): - - super().__init__(verbose, dry_run, force) - - shared_option = "-shared" - - if is_cygwincc(self.cc): - raise CCompilerError('Cygwin gcc cannot be used with --compiler=mingw32') - - self.set_executables( - compiler='%s -O -Wall' % self.cc, - compiler_so='%s -mdll -O -Wall' % self.cc, - compiler_cxx='%s -O -Wall' % self.cxx, - linker_exe='%s' % self.cc, - linker_so='{} {}'.format(self.linker_dll, shared_option), - ) - - def runtime_library_dir_option(self, dir): - raise DistutilsPlatformError(_runtime_library_dirs_msg) - - -# Because these compilers aren't configured in Python's pyconfig.h file by -# default, we should at least warn the user if he is using an unmodified -# version. - -CONFIG_H_OK = "ok" -CONFIG_H_NOTOK = "not ok" -CONFIG_H_UNCERTAIN = "uncertain" - - -def check_config_h(): - """Check if the current Python installation appears amenable to building - extensions with GCC. - - Returns a tuple (status, details), where 'status' is one of the following - constants: - - - CONFIG_H_OK: all is well, go ahead and compile - - CONFIG_H_NOTOK: doesn't look good - - CONFIG_H_UNCERTAIN: not sure -- unable to read pyconfig.h - - 'details' is a human-readable string explaining the situation. - - Note there are two ways to conclude "OK": either 'sys.version' contains - the string "GCC" (implying that this Python was built with GCC), or the - installed "pyconfig.h" contains the string "__GNUC__". - """ - - # XXX since this function also checks sys.version, it's not strictly a - # "pyconfig.h" check -- should probably be renamed... - - from distutils import sysconfig - - # if sys.version contains GCC then python was compiled with GCC, and the - # pyconfig.h file should be OK - if "GCC" in sys.version: - return CONFIG_H_OK, "sys.version mentions 'GCC'" - - # Clang would also work - if "Clang" in sys.version: - return CONFIG_H_OK, "sys.version mentions 'Clang'" - - # let's see if __GNUC__ is mentioned in python.h - fn = sysconfig.get_config_h_filename() - try: - config_h = open(fn) - try: - if "__GNUC__" in config_h.read(): - return CONFIG_H_OK, "'%s' mentions '__GNUC__'" % fn - else: - return CONFIG_H_NOTOK, "'%s' does not mention '__GNUC__'" % fn - finally: - config_h.close() - except OSError as exc: - return (CONFIG_H_UNCERTAIN, "couldn't read '{}': {}".format(fn, exc.strerror)) - - -def is_cygwincc(cc): - '''Try to determine if the compiler that would be used is from cygwin.''' - out_string = check_output(shlex.split(cc) + ['-dumpmachine']) - return out_string.strip().endswith(b'cygwin') - - -get_versions = None -""" -A stand-in for the previous get_versions() function to prevent failures -when monkeypatched. See pypa/setuptools#2969. -""" diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/debug.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/debug.py deleted file mode 100755 index daf1660..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/debug.py +++ /dev/null @@ -1,5 +0,0 @@ -import os - -# If DISTUTILS_DEBUG is anything other than the empty string, we run in -# debug mode. -DEBUG = os.environ.get('DISTUTILS_DEBUG') diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/dep_util.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/dep_util.py deleted file mode 100755 index 48da864..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/dep_util.py +++ /dev/null @@ -1,96 +0,0 @@ -"""distutils.dep_util - -Utility functions for simple, timestamp-based dependency of files -and groups of files; also, function based entirely on such -timestamp dependency analysis.""" - -import os -from .errors import DistutilsFileError - - -def newer(source, target): - """Return true if 'source' exists and is more recently modified than - 'target', or if 'source' exists and 'target' doesn't. Return false if - both exist and 'target' is the same age or younger than 'source'. - Raise DistutilsFileError if 'source' does not exist. - """ - if not os.path.exists(source): - raise DistutilsFileError("file '%s' does not exist" % os.path.abspath(source)) - if not os.path.exists(target): - return 1 - - from stat import ST_MTIME - - mtime1 = os.stat(source)[ST_MTIME] - mtime2 = os.stat(target)[ST_MTIME] - - return mtime1 > mtime2 - - -# newer () - - -def newer_pairwise(sources, targets): - """Walk two filename lists in parallel, testing if each source is newer - than its corresponding target. Return a pair of lists (sources, - targets) where source is newer than target, according to the semantics - of 'newer()'. - """ - if len(sources) != len(targets): - raise ValueError("'sources' and 'targets' must be same length") - - # build a pair of lists (sources, targets) where source is newer - n_sources = [] - n_targets = [] - for i in range(len(sources)): - if newer(sources[i], targets[i]): - n_sources.append(sources[i]) - n_targets.append(targets[i]) - - return (n_sources, n_targets) - - -# newer_pairwise () - - -def newer_group(sources, target, missing='error'): - """Return true if 'target' is out-of-date with respect to any file - listed in 'sources'. In other words, if 'target' exists and is newer - than every file in 'sources', return false; otherwise return true. - 'missing' controls what we do when a source file is missing; the - default ("error") is to blow up with an OSError from inside 'stat()'; - if it is "ignore", we silently drop any missing source files; if it is - "newer", any missing source files make us assume that 'target' is - out-of-date (this is handy in "dry-run" mode: it'll make you pretend to - carry out commands that wouldn't work because inputs are missing, but - that doesn't matter because you're not actually going to run the - commands). - """ - # If the target doesn't even exist, then it's definitely out-of-date. - if not os.path.exists(target): - return 1 - - # Otherwise we have to find out the hard way: if *any* source file - # is more recent than 'target', then 'target' is out-of-date and - # we can immediately return true. If we fall through to the end - # of the loop, then 'target' is up-to-date and we return false. - from stat import ST_MTIME - - target_mtime = os.stat(target)[ST_MTIME] - for source in sources: - if not os.path.exists(source): - if missing == 'error': # blow up when we stat() the file - pass - elif missing == 'ignore': # missing source dropped from - continue # target's dependency list - elif missing == 'newer': # missing source means target is - return 1 # out-of-date - - source_mtime = os.stat(source)[ST_MTIME] - if source_mtime > target_mtime: - return 1 - else: - return 0 - - -# newer_group () diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/dir_util.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/dir_util.py deleted file mode 100755 index 80f7764..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/dir_util.py +++ /dev/null @@ -1,243 +0,0 @@ -"""distutils.dir_util - -Utility functions for manipulating directories and directory trees.""" - -import os -import errno -from .errors import DistutilsInternalError, DistutilsFileError -from ._log import log - -# cache for by mkpath() -- in addition to cheapening redundant calls, -# eliminates redundant "creating /foo/bar/baz" messages in dry-run mode -_path_created = {} - - -def mkpath(name, mode=0o777, verbose=1, dry_run=0): # noqa: C901 - """Create a directory and any missing ancestor directories. - - If the directory already exists (or if 'name' is the empty string, which - means the current directory, which of course exists), then do nothing. - Raise DistutilsFileError if unable to create some directory along the way - (eg. some sub-path exists, but is a file rather than a directory). - If 'verbose' is true, print a one-line summary of each mkdir to stdout. - Return the list of directories actually created. - - os.makedirs is not used because: - - a) It's new to Python 1.5.2, and - b) it blows up if the directory already exists (in which case it should - silently succeed). - """ - - global _path_created - - # Detect a common bug -- name is None - if not isinstance(name, str): - raise DistutilsInternalError( - "mkpath: 'name' must be a string (got {!r})".format(name) - ) - - # XXX what's the better way to handle verbosity? print as we create - # each directory in the path (the current behaviour), or only announce - # the creation of the whole path? (quite easy to do the latter since - # we're not using a recursive algorithm) - - name = os.path.normpath(name) - created_dirs = [] - if os.path.isdir(name) or name == '': - return created_dirs - if _path_created.get(os.path.abspath(name)): - return created_dirs - - (head, tail) = os.path.split(name) - tails = [tail] # stack of lone dirs to create - - while head and tail and not os.path.isdir(head): - (head, tail) = os.path.split(head) - tails.insert(0, tail) # push next higher dir onto stack - - # now 'head' contains the deepest directory that already exists - # (that is, the child of 'head' in 'name' is the highest directory - # that does *not* exist) - for d in tails: - # print "head = %s, d = %s: " % (head, d), - head = os.path.join(head, d) - abs_head = os.path.abspath(head) - - if _path_created.get(abs_head): - continue - - if verbose >= 1: - log.info("creating %s", head) - - if not dry_run: - try: - os.mkdir(head, mode) - except OSError as exc: - if not (exc.errno == errno.EEXIST and os.path.isdir(head)): - raise DistutilsFileError( - "could not create '{}': {}".format(head, exc.args[-1]) - ) - created_dirs.append(head) - - _path_created[abs_head] = 1 - return created_dirs - - -def create_tree(base_dir, files, mode=0o777, verbose=1, dry_run=0): - """Create all the empty directories under 'base_dir' needed to put 'files' - there. - - 'base_dir' is just the name of a directory which doesn't necessarily - exist yet; 'files' is a list of filenames to be interpreted relative to - 'base_dir'. 'base_dir' + the directory portion of every file in 'files' - will be created if it doesn't already exist. 'mode', 'verbose' and - 'dry_run' flags are as for 'mkpath()'. - """ - # First get the list of directories to create - need_dir = set() - for file in files: - need_dir.add(os.path.join(base_dir, os.path.dirname(file))) - - # Now create them - for dir in sorted(need_dir): - mkpath(dir, mode, verbose=verbose, dry_run=dry_run) - - -def copy_tree( # noqa: C901 - src, - dst, - preserve_mode=1, - preserve_times=1, - preserve_symlinks=0, - update=0, - verbose=1, - dry_run=0, -): - """Copy an entire directory tree 'src' to a new location 'dst'. - - Both 'src' and 'dst' must be directory names. If 'src' is not a - directory, raise DistutilsFileError. If 'dst' does not exist, it is - created with 'mkpath()'. The end result of the copy is that every - file in 'src' is copied to 'dst', and directories under 'src' are - recursively copied to 'dst'. Return the list of files that were - copied or might have been copied, using their output name. The - return value is unaffected by 'update' or 'dry_run': it is simply - the list of all files under 'src', with the names changed to be - under 'dst'. - - 'preserve_mode' and 'preserve_times' are the same as for - 'copy_file'; note that they only apply to regular files, not to - directories. If 'preserve_symlinks' is true, symlinks will be - copied as symlinks (on platforms that support them!); otherwise - (the default), the destination of the symlink will be copied. - 'update' and 'verbose' are the same as for 'copy_file'. - """ - from distutils.file_util import copy_file - - if not dry_run and not os.path.isdir(src): - raise DistutilsFileError("cannot copy tree '%s': not a directory" % src) - try: - names = os.listdir(src) - except OSError as e: - if dry_run: - names = [] - else: - raise DistutilsFileError( - "error listing files in '{}': {}".format(src, e.strerror) - ) - - if not dry_run: - mkpath(dst, verbose=verbose) - - outputs = [] - - for n in names: - src_name = os.path.join(src, n) - dst_name = os.path.join(dst, n) - - if n.startswith('.nfs'): - # skip NFS rename files - continue - - if preserve_symlinks and os.path.islink(src_name): - link_dest = os.readlink(src_name) - if verbose >= 1: - log.info("linking %s -> %s", dst_name, link_dest) - if not dry_run: - os.symlink(link_dest, dst_name) - outputs.append(dst_name) - - elif os.path.isdir(src_name): - outputs.extend( - copy_tree( - src_name, - dst_name, - preserve_mode, - preserve_times, - preserve_symlinks, - update, - verbose=verbose, - dry_run=dry_run, - ) - ) - else: - copy_file( - src_name, - dst_name, - preserve_mode, - preserve_times, - update, - verbose=verbose, - dry_run=dry_run, - ) - outputs.append(dst_name) - - return outputs - - -def _build_cmdtuple(path, cmdtuples): - """Helper for remove_tree().""" - for f in os.listdir(path): - real_f = os.path.join(path, f) - if os.path.isdir(real_f) and not os.path.islink(real_f): - _build_cmdtuple(real_f, cmdtuples) - else: - cmdtuples.append((os.remove, real_f)) - cmdtuples.append((os.rmdir, path)) - - -def remove_tree(directory, verbose=1, dry_run=0): - """Recursively remove an entire directory tree. - - Any errors are ignored (apart from being reported to stdout if 'verbose' - is true). - """ - global _path_created - - if verbose >= 1: - log.info("removing '%s' (and everything under it)", directory) - if dry_run: - return - cmdtuples = [] - _build_cmdtuple(directory, cmdtuples) - for cmd in cmdtuples: - try: - cmd[0](cmd[1]) - # remove dir from cache if it's already there - abspath = os.path.abspath(cmd[1]) - if abspath in _path_created: - del _path_created[abspath] - except OSError as exc: - log.warning("error removing %s: %s", directory, exc) - - -def ensure_relative(path): - """Take the full path 'path', and make it a relative path. - - This is useful to make 'path' the second argument to os.path.join(). - """ - drive, path = os.path.splitdrive(path) - if path[0:1] == os.sep: - path = drive + path[1:] - return path diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/dist.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/dist.py deleted file mode 100755 index d7458a0..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/dist.py +++ /dev/null @@ -1,1287 +0,0 @@ -"""distutils.dist - -Provides the Distribution class, which represents the module distribution -being built/installed/distributed. -""" - -import sys -import os -import re -import pathlib -import contextlib -import logging -from email import message_from_file - -try: - import warnings -except ImportError: - warnings = None - -from .errors import ( - DistutilsOptionError, - DistutilsModuleError, - DistutilsArgError, - DistutilsClassError, -) -from .fancy_getopt import FancyGetopt, translate_longopt -from .util import check_environ, strtobool, rfc822_escape -from ._log import log -from .debug import DEBUG - -# Regex to define acceptable Distutils command names. This is not *quite* -# the same as a Python NAME -- I don't allow leading underscores. The fact -# that they're very similar is no coincidence; the default naming scheme is -# to look for a Python module named after the command. -command_re = re.compile(r'^[a-zA-Z]([a-zA-Z0-9_]*)$') - - -def _ensure_list(value, fieldname): - if isinstance(value, str): - # a string containing comma separated values is okay. It will - # be converted to a list by Distribution.finalize_options(). - pass - elif not isinstance(value, list): - # passing a tuple or an iterator perhaps, warn and convert - typename = type(value).__name__ - msg = "Warning: '{fieldname}' should be a list, got type '{typename}'" - msg = msg.format(**locals()) - log.warning(msg) - value = list(value) - return value - - -class Distribution: - """The core of the Distutils. Most of the work hiding behind 'setup' - is really done within a Distribution instance, which farms the work out - to the Distutils commands specified on the command line. - - Setup scripts will almost never instantiate Distribution directly, - unless the 'setup()' function is totally inadequate to their needs. - However, it is conceivable that a setup script might wish to subclass - Distribution for some specialized purpose, and then pass the subclass - to 'setup()' as the 'distclass' keyword argument. If so, it is - necessary to respect the expectations that 'setup' has of Distribution. - See the code for 'setup()', in core.py, for details. - """ - - # 'global_options' describes the command-line options that may be - # supplied to the setup script prior to any actual commands. - # Eg. "./setup.py -n" or "./setup.py --quiet" both take advantage of - # these global options. This list should be kept to a bare minimum, - # since every global option is also valid as a command option -- and we - # don't want to pollute the commands with too many options that they - # have minimal control over. - # The fourth entry for verbose means that it can be repeated. - global_options = [ - ('verbose', 'v', "run verbosely (default)", 1), - ('quiet', 'q', "run quietly (turns verbosity off)"), - ('dry-run', 'n', "don't actually do anything"), - ('help', 'h', "show detailed help message"), - ('no-user-cfg', None, 'ignore pydistutils.cfg in your home directory'), - ] - - # 'common_usage' is a short (2-3 line) string describing the common - # usage of the setup script. - common_usage = """\ -Common commands: (see '--help-commands' for more) - - setup.py build will build the package underneath 'build/' - setup.py install will install the package -""" - - # options that are not propagated to the commands - display_options = [ - ('help-commands', None, "list all available commands"), - ('name', None, "print package name"), - ('version', 'V', "print package version"), - ('fullname', None, "print -"), - ('author', None, "print the author's name"), - ('author-email', None, "print the author's email address"), - ('maintainer', None, "print the maintainer's name"), - ('maintainer-email', None, "print the maintainer's email address"), - ('contact', None, "print the maintainer's name if known, else the author's"), - ( - 'contact-email', - None, - "print the maintainer's email address if known, else the author's", - ), - ('url', None, "print the URL for this package"), - ('license', None, "print the license of the package"), - ('licence', None, "alias for --license"), - ('description', None, "print the package description"), - ('long-description', None, "print the long package description"), - ('platforms', None, "print the list of platforms"), - ('classifiers', None, "print the list of classifiers"), - ('keywords', None, "print the list of keywords"), - ('provides', None, "print the list of packages/modules provided"), - ('requires', None, "print the list of packages/modules required"), - ('obsoletes', None, "print the list of packages/modules made obsolete"), - ] - display_option_names = [translate_longopt(x[0]) for x in display_options] - - # negative options are options that exclude other options - negative_opt = {'quiet': 'verbose'} - - # -- Creation/initialization methods ------------------------------- - - def __init__(self, attrs=None): # noqa: C901 - """Construct a new Distribution instance: initialize all the - attributes of a Distribution, and then use 'attrs' (a dictionary - mapping attribute names to values) to assign some of those - attributes their "real" values. (Any attributes not mentioned in - 'attrs' will be assigned to some null value: 0, None, an empty list - or dictionary, etc.) Most importantly, initialize the - 'command_obj' attribute to the empty dictionary; this will be - filled in with real command objects by 'parse_command_line()'. - """ - - # Default values for our command-line options - self.verbose = 1 - self.dry_run = 0 - self.help = 0 - for attr in self.display_option_names: - setattr(self, attr, 0) - - # Store the distribution meta-data (name, version, author, and so - # forth) in a separate object -- we're getting to have enough - # information here (and enough command-line options) that it's - # worth it. Also delegate 'get_XXX()' methods to the 'metadata' - # object in a sneaky and underhanded (but efficient!) way. - self.metadata = DistributionMetadata() - for basename in self.metadata._METHOD_BASENAMES: - method_name = "get_" + basename - setattr(self, method_name, getattr(self.metadata, method_name)) - - # 'cmdclass' maps command names to class objects, so we - # can 1) quickly figure out which class to instantiate when - # we need to create a new command object, and 2) have a way - # for the setup script to override command classes - self.cmdclass = {} - - # 'command_packages' is a list of packages in which commands - # are searched for. The factory for command 'foo' is expected - # to be named 'foo' in the module 'foo' in one of the packages - # named here. This list is searched from the left; an error - # is raised if no named package provides the command being - # searched for. (Always access using get_command_packages().) - self.command_packages = None - - # 'script_name' and 'script_args' are usually set to sys.argv[0] - # and sys.argv[1:], but they can be overridden when the caller is - # not necessarily a setup script run from the command-line. - self.script_name = None - self.script_args = None - - # 'command_options' is where we store command options between - # parsing them (from config files, the command-line, etc.) and when - # they are actually needed -- ie. when the command in question is - # instantiated. It is a dictionary of dictionaries of 2-tuples: - # command_options = { command_name : { option : (source, value) } } - self.command_options = {} - - # 'dist_files' is the list of (command, pyversion, file) that - # have been created by any dist commands run so far. This is - # filled regardless of whether the run is dry or not. pyversion - # gives sysconfig.get_python_version() if the dist file is - # specific to a Python version, 'any' if it is good for all - # Python versions on the target platform, and '' for a source - # file. pyversion should not be used to specify minimum or - # maximum required Python versions; use the metainfo for that - # instead. - self.dist_files = [] - - # These options are really the business of various commands, rather - # than of the Distribution itself. We provide aliases for them in - # Distribution as a convenience to the developer. - self.packages = None - self.package_data = {} - self.package_dir = None - self.py_modules = None - self.libraries = None - self.headers = None - self.ext_modules = None - self.ext_package = None - self.include_dirs = None - self.extra_path = None - self.scripts = None - self.data_files = None - self.password = '' - - # And now initialize bookkeeping stuff that can't be supplied by - # the caller at all. 'command_obj' maps command names to - # Command instances -- that's how we enforce that every command - # class is a singleton. - self.command_obj = {} - - # 'have_run' maps command names to boolean values; it keeps track - # of whether we have actually run a particular command, to make it - # cheap to "run" a command whenever we think we might need to -- if - # it's already been done, no need for expensive filesystem - # operations, we just check the 'have_run' dictionary and carry on. - # It's only safe to query 'have_run' for a command class that has - # been instantiated -- a false value will be inserted when the - # command object is created, and replaced with a true value when - # the command is successfully run. Thus it's probably best to use - # '.get()' rather than a straight lookup. - self.have_run = {} - - # Now we'll use the attrs dictionary (ultimately, keyword args from - # the setup script) to possibly override any or all of these - # distribution options. - - if attrs: - # Pull out the set of command options and work on them - # specifically. Note that this order guarantees that aliased - # command options will override any supplied redundantly - # through the general options dictionary. - options = attrs.get('options') - if options is not None: - del attrs['options'] - for (command, cmd_options) in options.items(): - opt_dict = self.get_option_dict(command) - for (opt, val) in cmd_options.items(): - opt_dict[opt] = ("setup script", val) - - if 'licence' in attrs: - attrs['license'] = attrs['licence'] - del attrs['licence'] - msg = "'licence' distribution option is deprecated; use 'license'" - if warnings is not None: - warnings.warn(msg) - else: - sys.stderr.write(msg + "\n") - - # Now work on the rest of the attributes. Any attribute that's - # not already defined is invalid! - for (key, val) in attrs.items(): - if hasattr(self.metadata, "set_" + key): - getattr(self.metadata, "set_" + key)(val) - elif hasattr(self.metadata, key): - setattr(self.metadata, key, val) - elif hasattr(self, key): - setattr(self, key, val) - else: - msg = "Unknown distribution option: %s" % repr(key) - warnings.warn(msg) - - # no-user-cfg is handled before other command line args - # because other args override the config files, and this - # one is needed before we can load the config files. - # If attrs['script_args'] wasn't passed, assume false. - # - # This also make sure we just look at the global options - self.want_user_cfg = True - - if self.script_args is not None: - for arg in self.script_args: - if not arg.startswith('-'): - break - if arg == '--no-user-cfg': - self.want_user_cfg = False - break - - self.finalize_options() - - def get_option_dict(self, command): - """Get the option dictionary for a given command. If that - command's option dictionary hasn't been created yet, then create it - and return the new dictionary; otherwise, return the existing - option dictionary. - """ - dict = self.command_options.get(command) - if dict is None: - dict = self.command_options[command] = {} - return dict - - def dump_option_dicts(self, header=None, commands=None, indent=""): - from pprint import pformat - - if commands is None: # dump all command option dicts - commands = sorted(self.command_options.keys()) - - if header is not None: - self.announce(indent + header) - indent = indent + " " - - if not commands: - self.announce(indent + "no commands known yet") - return - - for cmd_name in commands: - opt_dict = self.command_options.get(cmd_name) - if opt_dict is None: - self.announce(indent + "no option dict for '%s' command" % cmd_name) - else: - self.announce(indent + "option dict for '%s' command:" % cmd_name) - out = pformat(opt_dict) - for line in out.split('\n'): - self.announce(indent + " " + line) - - # -- Config file finding/parsing methods --------------------------- - - def find_config_files(self): - """Find as many configuration files as should be processed for this - platform, and return a list of filenames in the order in which they - should be parsed. The filenames returned are guaranteed to exist - (modulo nasty race conditions). - - There are multiple possible config files: - - distutils.cfg in the Distutils installation directory (i.e. - where the top-level Distutils __inst__.py file lives) - - a file in the user's home directory named .pydistutils.cfg - on Unix and pydistutils.cfg on Windows/Mac; may be disabled - with the ``--no-user-cfg`` option - - setup.cfg in the current directory - - a file named by an environment variable - """ - check_environ() - files = [str(path) for path in self._gen_paths() if os.path.isfile(path)] - - if DEBUG: - self.announce("using config files: %s" % ', '.join(files)) - - return files - - def _gen_paths(self): - # The system-wide Distutils config file - sys_dir = pathlib.Path(sys.modules['distutils'].__file__).parent - yield sys_dir / "distutils.cfg" - - # The per-user config file - prefix = '.' * (os.name == 'posix') - filename = prefix + 'pydistutils.cfg' - if self.want_user_cfg: - yield pathlib.Path('~').expanduser() / filename - - # All platforms support local setup.cfg - yield pathlib.Path('setup.cfg') - - # Additional config indicated in the environment - with contextlib.suppress(TypeError): - yield pathlib.Path(os.getenv("DIST_EXTRA_CONFIG")) - - def parse_config_files(self, filenames=None): # noqa: C901 - from configparser import ConfigParser - - # Ignore install directory options if we have a venv - if sys.prefix != sys.base_prefix: - ignore_options = [ - 'install-base', - 'install-platbase', - 'install-lib', - 'install-platlib', - 'install-purelib', - 'install-headers', - 'install-scripts', - 'install-data', - 'prefix', - 'exec-prefix', - 'home', - 'user', - 'root', - ] - else: - ignore_options = [] - - ignore_options = frozenset(ignore_options) - - if filenames is None: - filenames = self.find_config_files() - - if DEBUG: - self.announce("Distribution.parse_config_files():") - - parser = ConfigParser() - for filename in filenames: - if DEBUG: - self.announce(" reading %s" % filename) - parser.read(filename) - for section in parser.sections(): - options = parser.options(section) - opt_dict = self.get_option_dict(section) - - for opt in options: - if opt != '__name__' and opt not in ignore_options: - val = parser.get(section, opt) - opt = opt.replace('-', '_') - opt_dict[opt] = (filename, val) - - # Make the ConfigParser forget everything (so we retain - # the original filenames that options come from) - parser.__init__() - - # If there was a "global" section in the config file, use it - # to set Distribution options. - - if 'global' in self.command_options: - for (opt, (src, val)) in self.command_options['global'].items(): - alias = self.negative_opt.get(opt) - try: - if alias: - setattr(self, alias, not strtobool(val)) - elif opt in ('verbose', 'dry_run'): # ugh! - setattr(self, opt, strtobool(val)) - else: - setattr(self, opt, val) - except ValueError as msg: - raise DistutilsOptionError(msg) - - # -- Command-line parsing methods ---------------------------------- - - def parse_command_line(self): - """Parse the setup script's command line, taken from the - 'script_args' instance attribute (which defaults to 'sys.argv[1:]' - -- see 'setup()' in core.py). This list is first processed for - "global options" -- options that set attributes of the Distribution - instance. Then, it is alternately scanned for Distutils commands - and options for that command. Each new command terminates the - options for the previous command. The allowed options for a - command are determined by the 'user_options' attribute of the - command class -- thus, we have to be able to load command classes - in order to parse the command line. Any error in that 'options' - attribute raises DistutilsGetoptError; any error on the - command-line raises DistutilsArgError. If no Distutils commands - were found on the command line, raises DistutilsArgError. Return - true if command-line was successfully parsed and we should carry - on with executing commands; false if no errors but we shouldn't - execute commands (currently, this only happens if user asks for - help). - """ - # - # We now have enough information to show the Macintosh dialog - # that allows the user to interactively specify the "command line". - # - toplevel_options = self._get_toplevel_options() - - # We have to parse the command line a bit at a time -- global - # options, then the first command, then its options, and so on -- - # because each command will be handled by a different class, and - # the options that are valid for a particular class aren't known - # until we have loaded the command class, which doesn't happen - # until we know what the command is. - - self.commands = [] - parser = FancyGetopt(toplevel_options + self.display_options) - parser.set_negative_aliases(self.negative_opt) - parser.set_aliases({'licence': 'license'}) - args = parser.getopt(args=self.script_args, object=self) - option_order = parser.get_option_order() - logging.getLogger().setLevel(logging.WARN - 10 * self.verbose) - - # for display options we return immediately - if self.handle_display_options(option_order): - return - while args: - args = self._parse_command_opts(parser, args) - if args is None: # user asked for help (and got it) - return - - # Handle the cases of --help as a "global" option, ie. - # "setup.py --help" and "setup.py --help command ...". For the - # former, we show global options (--verbose, --dry-run, etc.) - # and display-only options (--name, --version, etc.); for the - # latter, we omit the display-only options and show help for - # each command listed on the command line. - if self.help: - self._show_help( - parser, display_options=len(self.commands) == 0, commands=self.commands - ) - return - - # Oops, no commands found -- an end-user error - if not self.commands: - raise DistutilsArgError("no commands supplied") - - # All is well: return true - return True - - def _get_toplevel_options(self): - """Return the non-display options recognized at the top level. - - This includes options that are recognized *only* at the top - level as well as options recognized for commands. - """ - return self.global_options + [ - ( - "command-packages=", - None, - "list of packages that provide distutils commands", - ), - ] - - def _parse_command_opts(self, parser, args): # noqa: C901 - """Parse the command-line options for a single command. - 'parser' must be a FancyGetopt instance; 'args' must be the list - of arguments, starting with the current command (whose options - we are about to parse). Returns a new version of 'args' with - the next command at the front of the list; will be the empty - list if there are no more commands on the command line. Returns - None if the user asked for help on this command. - """ - # late import because of mutual dependence between these modules - from distutils.cmd import Command - - # Pull the current command from the head of the command line - command = args[0] - if not command_re.match(command): - raise SystemExit("invalid command name '%s'" % command) - self.commands.append(command) - - # Dig up the command class that implements this command, so we - # 1) know that it's a valid command, and 2) know which options - # it takes. - try: - cmd_class = self.get_command_class(command) - except DistutilsModuleError as msg: - raise DistutilsArgError(msg) - - # Require that the command class be derived from Command -- want - # to be sure that the basic "command" interface is implemented. - if not issubclass(cmd_class, Command): - raise DistutilsClassError( - "command class %s must subclass Command" % cmd_class - ) - - # Also make sure that the command object provides a list of its - # known options. - if not ( - hasattr(cmd_class, 'user_options') - and isinstance(cmd_class.user_options, list) - ): - msg = ( - "command class %s must provide " - "'user_options' attribute (a list of tuples)" - ) - raise DistutilsClassError(msg % cmd_class) - - # If the command class has a list of negative alias options, - # merge it in with the global negative aliases. - negative_opt = self.negative_opt - if hasattr(cmd_class, 'negative_opt'): - negative_opt = negative_opt.copy() - negative_opt.update(cmd_class.negative_opt) - - # Check for help_options in command class. They have a different - # format (tuple of four) so we need to preprocess them here. - if hasattr(cmd_class, 'help_options') and isinstance( - cmd_class.help_options, list - ): - help_options = fix_help_options(cmd_class.help_options) - else: - help_options = [] - - # All commands support the global options too, just by adding - # in 'global_options'. - parser.set_option_table( - self.global_options + cmd_class.user_options + help_options - ) - parser.set_negative_aliases(negative_opt) - (args, opts) = parser.getopt(args[1:]) - if hasattr(opts, 'help') and opts.help: - self._show_help(parser, display_options=0, commands=[cmd_class]) - return - - if hasattr(cmd_class, 'help_options') and isinstance( - cmd_class.help_options, list - ): - help_option_found = 0 - for (help_option, short, desc, func) in cmd_class.help_options: - if hasattr(opts, parser.get_attr_name(help_option)): - help_option_found = 1 - if callable(func): - func() - else: - raise DistutilsClassError( - "invalid help function %r for help option '%s': " - "must be a callable object (function, etc.)" - % (func, help_option) - ) - - if help_option_found: - return - - # Put the options from the command-line into their official - # holding pen, the 'command_options' dictionary. - opt_dict = self.get_option_dict(command) - for (name, value) in vars(opts).items(): - opt_dict[name] = ("command line", value) - - return args - - def finalize_options(self): - """Set final values for all the options on the Distribution - instance, analogous to the .finalize_options() method of Command - objects. - """ - for attr in ('keywords', 'platforms'): - value = getattr(self.metadata, attr) - if value is None: - continue - if isinstance(value, str): - value = [elm.strip() for elm in value.split(',')] - setattr(self.metadata, attr, value) - - def _show_help(self, parser, global_options=1, display_options=1, commands=[]): - """Show help for the setup script command-line in the form of - several lists of command-line options. 'parser' should be a - FancyGetopt instance; do not expect it to be returned in the - same state, as its option table will be reset to make it - generate the correct help text. - - If 'global_options' is true, lists the global options: - --verbose, --dry-run, etc. If 'display_options' is true, lists - the "display-only" options: --name, --version, etc. Finally, - lists per-command help for every command name or command class - in 'commands'. - """ - # late import because of mutual dependence between these modules - from distutils.core import gen_usage - from distutils.cmd import Command - - if global_options: - if display_options: - options = self._get_toplevel_options() - else: - options = self.global_options - parser.set_option_table(options) - parser.print_help(self.common_usage + "\nGlobal options:") - print('') - - if display_options: - parser.set_option_table(self.display_options) - parser.print_help( - "Information display options (just display " - + "information, ignore any commands)" - ) - print('') - - for command in self.commands: - if isinstance(command, type) and issubclass(command, Command): - klass = command - else: - klass = self.get_command_class(command) - if hasattr(klass, 'help_options') and isinstance(klass.help_options, list): - parser.set_option_table( - klass.user_options + fix_help_options(klass.help_options) - ) - else: - parser.set_option_table(klass.user_options) - parser.print_help("Options for '%s' command:" % klass.__name__) - print('') - - print(gen_usage(self.script_name)) - - def handle_display_options(self, option_order): - """If there were any non-global "display-only" options - (--help-commands or the metadata display options) on the command - line, display the requested info and return true; else return - false. - """ - from distutils.core import gen_usage - - # User just wants a list of commands -- we'll print it out and stop - # processing now (ie. if they ran "setup --help-commands foo bar", - # we ignore "foo bar"). - if self.help_commands: - self.print_commands() - print('') - print(gen_usage(self.script_name)) - return 1 - - # If user supplied any of the "display metadata" options, then - # display that metadata in the order in which the user supplied the - # metadata options. - any_display_options = 0 - is_display_option = {} - for option in self.display_options: - is_display_option[option[0]] = 1 - - for (opt, val) in option_order: - if val and is_display_option.get(opt): - opt = translate_longopt(opt) - value = getattr(self.metadata, "get_" + opt)() - if opt in ['keywords', 'platforms']: - print(','.join(value)) - elif opt in ('classifiers', 'provides', 'requires', 'obsoletes'): - print('\n'.join(value)) - else: - print(value) - any_display_options = 1 - - return any_display_options - - def print_command_list(self, commands, header, max_length): - """Print a subset of the list of all commands -- used by - 'print_commands()'. - """ - print(header + ":") - - for cmd in commands: - klass = self.cmdclass.get(cmd) - if not klass: - klass = self.get_command_class(cmd) - try: - description = klass.description - except AttributeError: - description = "(no description available)" - - print(" %-*s %s" % (max_length, cmd, description)) - - def print_commands(self): - """Print out a help message listing all available commands with a - description of each. The list is divided into "standard commands" - (listed in distutils.command.__all__) and "extra commands" - (mentioned in self.cmdclass, but not a standard command). The - descriptions come from the command class attribute - 'description'. - """ - import distutils.command - - std_commands = distutils.command.__all__ - is_std = {} - for cmd in std_commands: - is_std[cmd] = 1 - - extra_commands = [] - for cmd in self.cmdclass.keys(): - if not is_std.get(cmd): - extra_commands.append(cmd) - - max_length = 0 - for cmd in std_commands + extra_commands: - if len(cmd) > max_length: - max_length = len(cmd) - - self.print_command_list(std_commands, "Standard commands", max_length) - if extra_commands: - print() - self.print_command_list(extra_commands, "Extra commands", max_length) - - def get_command_list(self): - """Get a list of (command, description) tuples. - The list is divided into "standard commands" (listed in - distutils.command.__all__) and "extra commands" (mentioned in - self.cmdclass, but not a standard command). The descriptions come - from the command class attribute 'description'. - """ - # Currently this is only used on Mac OS, for the Mac-only GUI - # Distutils interface (by Jack Jansen) - import distutils.command - - std_commands = distutils.command.__all__ - is_std = {} - for cmd in std_commands: - is_std[cmd] = 1 - - extra_commands = [] - for cmd in self.cmdclass.keys(): - if not is_std.get(cmd): - extra_commands.append(cmd) - - rv = [] - for cmd in std_commands + extra_commands: - klass = self.cmdclass.get(cmd) - if not klass: - klass = self.get_command_class(cmd) - try: - description = klass.description - except AttributeError: - description = "(no description available)" - rv.append((cmd, description)) - return rv - - # -- Command class/object methods ---------------------------------- - - def get_command_packages(self): - """Return a list of packages from which commands are loaded.""" - pkgs = self.command_packages - if not isinstance(pkgs, list): - if pkgs is None: - pkgs = '' - pkgs = [pkg.strip() for pkg in pkgs.split(',') if pkg != ''] - if "distutils.command" not in pkgs: - pkgs.insert(0, "distutils.command") - self.command_packages = pkgs - return pkgs - - def get_command_class(self, command): - """Return the class that implements the Distutils command named by - 'command'. First we check the 'cmdclass' dictionary; if the - command is mentioned there, we fetch the class object from the - dictionary and return it. Otherwise we load the command module - ("distutils.command." + command) and fetch the command class from - the module. The loaded class is also stored in 'cmdclass' - to speed future calls to 'get_command_class()'. - - Raises DistutilsModuleError if the expected module could not be - found, or if that module does not define the expected class. - """ - klass = self.cmdclass.get(command) - if klass: - return klass - - for pkgname in self.get_command_packages(): - module_name = "{}.{}".format(pkgname, command) - klass_name = command - - try: - __import__(module_name) - module = sys.modules[module_name] - except ImportError: - continue - - try: - klass = getattr(module, klass_name) - except AttributeError: - raise DistutilsModuleError( - "invalid command '%s' (no class '%s' in module '%s')" - % (command, klass_name, module_name) - ) - - self.cmdclass[command] = klass - return klass - - raise DistutilsModuleError("invalid command '%s'" % command) - - def get_command_obj(self, command, create=1): - """Return the command object for 'command'. Normally this object - is cached on a previous call to 'get_command_obj()'; if no command - object for 'command' is in the cache, then we either create and - return it (if 'create' is true) or return None. - """ - cmd_obj = self.command_obj.get(command) - if not cmd_obj and create: - if DEBUG: - self.announce( - "Distribution.get_command_obj(): " - "creating '%s' command object" % command - ) - - klass = self.get_command_class(command) - cmd_obj = self.command_obj[command] = klass(self) - self.have_run[command] = 0 - - # Set any options that were supplied in config files - # or on the command line. (NB. support for error - # reporting is lame here: any errors aren't reported - # until 'finalize_options()' is called, which means - # we won't report the source of the error.) - options = self.command_options.get(command) - if options: - self._set_command_options(cmd_obj, options) - - return cmd_obj - - def _set_command_options(self, command_obj, option_dict=None): # noqa: C901 - """Set the options for 'command_obj' from 'option_dict'. Basically - this means copying elements of a dictionary ('option_dict') to - attributes of an instance ('command'). - - 'command_obj' must be a Command instance. If 'option_dict' is not - supplied, uses the standard option dictionary for this command - (from 'self.command_options'). - """ - command_name = command_obj.get_command_name() - if option_dict is None: - option_dict = self.get_option_dict(command_name) - - if DEBUG: - self.announce(" setting options for '%s' command:" % command_name) - for (option, (source, value)) in option_dict.items(): - if DEBUG: - self.announce(" {} = {} (from {})".format(option, value, source)) - try: - bool_opts = [translate_longopt(o) for o in command_obj.boolean_options] - except AttributeError: - bool_opts = [] - try: - neg_opt = command_obj.negative_opt - except AttributeError: - neg_opt = {} - - try: - is_string = isinstance(value, str) - if option in neg_opt and is_string: - setattr(command_obj, neg_opt[option], not strtobool(value)) - elif option in bool_opts and is_string: - setattr(command_obj, option, strtobool(value)) - elif hasattr(command_obj, option): - setattr(command_obj, option, value) - else: - raise DistutilsOptionError( - "error in %s: command '%s' has no such option '%s'" - % (source, command_name, option) - ) - except ValueError as msg: - raise DistutilsOptionError(msg) - - def reinitialize_command(self, command, reinit_subcommands=0): - """Reinitializes a command to the state it was in when first - returned by 'get_command_obj()': ie., initialized but not yet - finalized. This provides the opportunity to sneak option - values in programmatically, overriding or supplementing - user-supplied values from the config files and command line. - You'll have to re-finalize the command object (by calling - 'finalize_options()' or 'ensure_finalized()') before using it for - real. - - 'command' should be a command name (string) or command object. If - 'reinit_subcommands' is true, also reinitializes the command's - sub-commands, as declared by the 'sub_commands' class attribute (if - it has one). See the "install" command for an example. Only - reinitializes the sub-commands that actually matter, ie. those - whose test predicates return true. - - Returns the reinitialized command object. - """ - from distutils.cmd import Command - - if not isinstance(command, Command): - command_name = command - command = self.get_command_obj(command_name) - else: - command_name = command.get_command_name() - - if not command.finalized: - return command - command.initialize_options() - command.finalized = 0 - self.have_run[command_name] = 0 - self._set_command_options(command) - - if reinit_subcommands: - for sub in command.get_sub_commands(): - self.reinitialize_command(sub, reinit_subcommands) - - return command - - # -- Methods that operate on the Distribution ---------------------- - - def announce(self, msg, level=logging.INFO): - log.log(level, msg) - - def run_commands(self): - """Run each command that was seen on the setup script command line. - Uses the list of commands found and cache of command objects - created by 'get_command_obj()'. - """ - for cmd in self.commands: - self.run_command(cmd) - - # -- Methods that operate on its Commands -------------------------- - - def run_command(self, command): - """Do whatever it takes to run a command (including nothing at all, - if the command has already been run). Specifically: if we have - already created and run the command named by 'command', return - silently without doing anything. If the command named by 'command' - doesn't even have a command object yet, create one. Then invoke - 'run()' on that command object (or an existing one). - """ - # Already been here, done that? then return silently. - if self.have_run.get(command): - return - - log.info("running %s", command) - cmd_obj = self.get_command_obj(command) - cmd_obj.ensure_finalized() - cmd_obj.run() - self.have_run[command] = 1 - - # -- Distribution query methods ------------------------------------ - - def has_pure_modules(self): - return len(self.packages or self.py_modules or []) > 0 - - def has_ext_modules(self): - return self.ext_modules and len(self.ext_modules) > 0 - - def has_c_libraries(self): - return self.libraries and len(self.libraries) > 0 - - def has_modules(self): - return self.has_pure_modules() or self.has_ext_modules() - - def has_headers(self): - return self.headers and len(self.headers) > 0 - - def has_scripts(self): - return self.scripts and len(self.scripts) > 0 - - def has_data_files(self): - return self.data_files and len(self.data_files) > 0 - - def is_pure(self): - return ( - self.has_pure_modules() - and not self.has_ext_modules() - and not self.has_c_libraries() - ) - - # -- Metadata query methods ---------------------------------------- - - # If you're looking for 'get_name()', 'get_version()', and so forth, - # they are defined in a sneaky way: the constructor binds self.get_XXX - # to self.metadata.get_XXX. The actual code is in the - # DistributionMetadata class, below. - - -class DistributionMetadata: - """Dummy class to hold the distribution meta-data: name, version, - author, and so forth. - """ - - _METHOD_BASENAMES = ( - "name", - "version", - "author", - "author_email", - "maintainer", - "maintainer_email", - "url", - "license", - "description", - "long_description", - "keywords", - "platforms", - "fullname", - "contact", - "contact_email", - "classifiers", - "download_url", - # PEP 314 - "provides", - "requires", - "obsoletes", - ) - - def __init__(self, path=None): - if path is not None: - self.read_pkg_file(open(path)) - else: - self.name = None - self.version = None - self.author = None - self.author_email = None - self.maintainer = None - self.maintainer_email = None - self.url = None - self.license = None - self.description = None - self.long_description = None - self.keywords = None - self.platforms = None - self.classifiers = None - self.download_url = None - # PEP 314 - self.provides = None - self.requires = None - self.obsoletes = None - - def read_pkg_file(self, file): - """Reads the metadata values from a file object.""" - msg = message_from_file(file) - - def _read_field(name): - value = msg[name] - if value and value != "UNKNOWN": - return value - - def _read_list(name): - values = msg.get_all(name, None) - if values == []: - return None - return values - - metadata_version = msg['metadata-version'] - self.name = _read_field('name') - self.version = _read_field('version') - self.description = _read_field('summary') - # we are filling author only. - self.author = _read_field('author') - self.maintainer = None - self.author_email = _read_field('author-email') - self.maintainer_email = None - self.url = _read_field('home-page') - self.license = _read_field('license') - - if 'download-url' in msg: - self.download_url = _read_field('download-url') - else: - self.download_url = None - - self.long_description = _read_field('description') - self.description = _read_field('summary') - - if 'keywords' in msg: - self.keywords = _read_field('keywords').split(',') - - self.platforms = _read_list('platform') - self.classifiers = _read_list('classifier') - - # PEP 314 - these fields only exist in 1.1 - if metadata_version == '1.1': - self.requires = _read_list('requires') - self.provides = _read_list('provides') - self.obsoletes = _read_list('obsoletes') - else: - self.requires = None - self.provides = None - self.obsoletes = None - - def write_pkg_info(self, base_dir): - """Write the PKG-INFO file into the release tree.""" - with open( - os.path.join(base_dir, 'PKG-INFO'), 'w', encoding='UTF-8' - ) as pkg_info: - self.write_pkg_file(pkg_info) - - def write_pkg_file(self, file): - """Write the PKG-INFO format data to a file object.""" - version = '1.0' - if ( - self.provides - or self.requires - or self.obsoletes - or self.classifiers - or self.download_url - ): - version = '1.1' - - # required fields - file.write('Metadata-Version: %s\n' % version) - file.write('Name: %s\n' % self.get_name()) - file.write('Version: %s\n' % self.get_version()) - - def maybe_write(header, val): - if val: - file.write(f"{header}: {val}\n") - - # optional fields - maybe_write("Summary", self.get_description()) - maybe_write("Home-page", self.get_url()) - maybe_write("Author", self.get_contact()) - maybe_write("Author-email", self.get_contact_email()) - maybe_write("License", self.get_license()) - maybe_write("Download-URL", self.download_url) - maybe_write("Description", rfc822_escape(self.get_long_description() or "")) - maybe_write("Keywords", ",".join(self.get_keywords())) - - self._write_list(file, 'Platform', self.get_platforms()) - self._write_list(file, 'Classifier', self.get_classifiers()) - - # PEP 314 - self._write_list(file, 'Requires', self.get_requires()) - self._write_list(file, 'Provides', self.get_provides()) - self._write_list(file, 'Obsoletes', self.get_obsoletes()) - - def _write_list(self, file, name, values): - values = values or [] - for value in values: - file.write('{}: {}\n'.format(name, value)) - - # -- Metadata query methods ---------------------------------------- - - def get_name(self): - return self.name or "UNKNOWN" - - def get_version(self): - return self.version or "0.0.0" - - def get_fullname(self): - return "{}-{}".format(self.get_name(), self.get_version()) - - def get_author(self): - return self.author - - def get_author_email(self): - return self.author_email - - def get_maintainer(self): - return self.maintainer - - def get_maintainer_email(self): - return self.maintainer_email - - def get_contact(self): - return self.maintainer or self.author - - def get_contact_email(self): - return self.maintainer_email or self.author_email - - def get_url(self): - return self.url - - def get_license(self): - return self.license - - get_licence = get_license - - def get_description(self): - return self.description - - def get_long_description(self): - return self.long_description - - def get_keywords(self): - return self.keywords or [] - - def set_keywords(self, value): - self.keywords = _ensure_list(value, 'keywords') - - def get_platforms(self): - return self.platforms - - def set_platforms(self, value): - self.platforms = _ensure_list(value, 'platforms') - - def get_classifiers(self): - return self.classifiers or [] - - def set_classifiers(self, value): - self.classifiers = _ensure_list(value, 'classifiers') - - def get_download_url(self): - return self.download_url - - # PEP 314 - def get_requires(self): - return self.requires or [] - - def set_requires(self, value): - import distutils.versionpredicate - - for v in value: - distutils.versionpredicate.VersionPredicate(v) - self.requires = list(value) - - def get_provides(self): - return self.provides or [] - - def set_provides(self, value): - value = [v.strip() for v in value] - for v in value: - import distutils.versionpredicate - - distutils.versionpredicate.split_provision(v) - self.provides = value - - def get_obsoletes(self): - return self.obsoletes or [] - - def set_obsoletes(self, value): - import distutils.versionpredicate - - for v in value: - distutils.versionpredicate.VersionPredicate(v) - self.obsoletes = list(value) - - -def fix_help_options(options): - """Convert a 4-tuple 'help_options' list as found in various command - classes to the 3-tuple form required by FancyGetopt. - """ - new_options = [] - for help_tuple in options: - new_options.append(help_tuple[0:3]) - return new_options diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/errors.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/errors.py deleted file mode 100755 index 626254c..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/errors.py +++ /dev/null @@ -1,127 +0,0 @@ -"""distutils.errors - -Provides exceptions used by the Distutils modules. Note that Distutils -modules may raise standard exceptions; in particular, SystemExit is -usually raised for errors that are obviously the end-user's fault -(eg. bad command-line arguments). - -This module is safe to use in "from ... import *" mode; it only exports -symbols whose names start with "Distutils" and end with "Error".""" - - -class DistutilsError(Exception): - """The root of all Distutils evil.""" - - pass - - -class DistutilsModuleError(DistutilsError): - """Unable to load an expected module, or to find an expected class - within some module (in particular, command modules and classes).""" - - pass - - -class DistutilsClassError(DistutilsError): - """Some command class (or possibly distribution class, if anyone - feels a need to subclass Distribution) is found not to be holding - up its end of the bargain, ie. implementing some part of the - "command "interface.""" - - pass - - -class DistutilsGetoptError(DistutilsError): - """The option table provided to 'fancy_getopt()' is bogus.""" - - pass - - -class DistutilsArgError(DistutilsError): - """Raised by fancy_getopt in response to getopt.error -- ie. an - error in the command line usage.""" - - pass - - -class DistutilsFileError(DistutilsError): - """Any problems in the filesystem: expected file not found, etc. - Typically this is for problems that we detect before OSError - could be raised.""" - - pass - - -class DistutilsOptionError(DistutilsError): - """Syntactic/semantic errors in command options, such as use of - mutually conflicting options, or inconsistent options, - badly-spelled values, etc. No distinction is made between option - values originating in the setup script, the command line, config - files, or what-have-you -- but if we *know* something originated in - the setup script, we'll raise DistutilsSetupError instead.""" - - pass - - -class DistutilsSetupError(DistutilsError): - """For errors that can be definitely blamed on the setup script, - such as invalid keyword arguments to 'setup()'.""" - - pass - - -class DistutilsPlatformError(DistutilsError): - """We don't know how to do something on the current platform (but - we do know how to do it on some platform) -- eg. trying to compile - C files on a platform not supported by a CCompiler subclass.""" - - pass - - -class DistutilsExecError(DistutilsError): - """Any problems executing an external program (such as the C - compiler, when compiling C files).""" - - pass - - -class DistutilsInternalError(DistutilsError): - """Internal inconsistencies or impossibilities (obviously, this - should never be seen if the code is working!).""" - - pass - - -class DistutilsTemplateError(DistutilsError): - """Syntax error in a file list template.""" - - -class DistutilsByteCompileError(DistutilsError): - """Byte compile error.""" - - -# Exception classes used by the CCompiler implementation classes -class CCompilerError(Exception): - """Some compile/link operation failed.""" - - -class PreprocessError(CCompilerError): - """Failure to preprocess one or more C/C++ files.""" - - -class CompileError(CCompilerError): - """Failure to compile one or more C/C++ source files.""" - - -class LibError(CCompilerError): - """Failure to create a static library from one or more C/C++ object - files.""" - - -class LinkError(CCompilerError): - """Failure to link one or more C/C++ object files into an executable - or shared library file.""" - - -class UnknownFileError(CCompilerError): - """Attempt to process an unknown file type.""" diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/extension.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/extension.py deleted file mode 100755 index 6b8575d..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/extension.py +++ /dev/null @@ -1,248 +0,0 @@ -"""distutils.extension - -Provides the Extension class, used to describe C/C++ extension -modules in setup scripts.""" - -import os -import warnings - -# This class is really only used by the "build_ext" command, so it might -# make sense to put it in distutils.command.build_ext. However, that -# module is already big enough, and I want to make this class a bit more -# complex to simplify some common cases ("foo" module in "foo.c") and do -# better error-checking ("foo.c" actually exists). -# -# Also, putting this in build_ext.py means every setup script would have to -# import that large-ish module (indirectly, through distutils.core) in -# order to do anything. - - -class Extension: - """Just a collection of attributes that describes an extension - module and everything needed to build it (hopefully in a portable - way, but there are hooks that let you be as unportable as you need). - - Instance attributes: - name : string - the full name of the extension, including any packages -- ie. - *not* a filename or pathname, but Python dotted name - sources : [string] - list of source filenames, relative to the distribution root - (where the setup script lives), in Unix form (slash-separated) - for portability. Source files may be C, C++, SWIG (.i), - platform-specific resource files, or whatever else is recognized - by the "build_ext" command as source for a Python extension. - include_dirs : [string] - list of directories to search for C/C++ header files (in Unix - form for portability) - define_macros : [(name : string, value : string|None)] - list of macros to define; each macro is defined using a 2-tuple, - where 'value' is either the string to define it to or None to - define it without a particular value (equivalent of "#define - FOO" in source or -DFOO on Unix C compiler command line) - undef_macros : [string] - list of macros to undefine explicitly - library_dirs : [string] - list of directories to search for C/C++ libraries at link time - libraries : [string] - list of library names (not filenames or paths) to link against - runtime_library_dirs : [string] - list of directories to search for C/C++ libraries at run time - (for shared extensions, this is when the extension is loaded) - extra_objects : [string] - list of extra files to link with (eg. object files not implied - by 'sources', static library that must be explicitly specified, - binary resource files, etc.) - extra_compile_args : [string] - any extra platform- and compiler-specific information to use - when compiling the source files in 'sources'. For platforms and - compilers where "command line" makes sense, this is typically a - list of command-line arguments, but for other platforms it could - be anything. - extra_link_args : [string] - any extra platform- and compiler-specific information to use - when linking object files together to create the extension (or - to create a new static Python interpreter). Similar - interpretation as for 'extra_compile_args'. - export_symbols : [string] - list of symbols to be exported from a shared extension. Not - used on all platforms, and not generally necessary for Python - extensions, which typically export exactly one symbol: "init" + - extension_name. - swig_opts : [string] - any extra options to pass to SWIG if a source file has the .i - extension. - depends : [string] - list of files that the extension depends on - language : string - extension language (i.e. "c", "c++", "objc"). Will be detected - from the source extensions if not provided. - optional : boolean - specifies that a build failure in the extension should not abort the - build process, but simply not install the failing extension. - """ - - # When adding arguments to this constructor, be sure to update - # setup_keywords in core.py. - def __init__( - self, - name, - sources, - include_dirs=None, - define_macros=None, - undef_macros=None, - library_dirs=None, - libraries=None, - runtime_library_dirs=None, - extra_objects=None, - extra_compile_args=None, - extra_link_args=None, - export_symbols=None, - swig_opts=None, - depends=None, - language=None, - optional=None, - **kw # To catch unknown keywords - ): - if not isinstance(name, str): - raise AssertionError("'name' must be a string") - if not (isinstance(sources, list) and all(isinstance(v, str) for v in sources)): - raise AssertionError("'sources' must be a list of strings") - - self.name = name - self.sources = sources - self.include_dirs = include_dirs or [] - self.define_macros = define_macros or [] - self.undef_macros = undef_macros or [] - self.library_dirs = library_dirs or [] - self.libraries = libraries or [] - self.runtime_library_dirs = runtime_library_dirs or [] - self.extra_objects = extra_objects or [] - self.extra_compile_args = extra_compile_args or [] - self.extra_link_args = extra_link_args or [] - self.export_symbols = export_symbols or [] - self.swig_opts = swig_opts or [] - self.depends = depends or [] - self.language = language - self.optional = optional - - # If there are unknown keyword options, warn about them - if len(kw) > 0: - options = [repr(option) for option in kw] - options = ', '.join(sorted(options)) - msg = "Unknown Extension options: %s" % options - warnings.warn(msg) - - def __repr__(self): - return '<{}.{}({!r}) at {:#x}>'.format( - self.__class__.__module__, - self.__class__.__qualname__, - self.name, - id(self), - ) - - -def read_setup_file(filename): # noqa: C901 - """Reads a Setup file and returns Extension instances.""" - from distutils.sysconfig import parse_makefile, expand_makefile_vars, _variable_rx - - from distutils.text_file import TextFile - from distutils.util import split_quoted - - # First pass over the file to gather "VAR = VALUE" assignments. - vars = parse_makefile(filename) - - # Second pass to gobble up the real content: lines of the form - # ... [ ...] [ ...] [ ...] - file = TextFile( - filename, - strip_comments=1, - skip_blanks=1, - join_lines=1, - lstrip_ws=1, - rstrip_ws=1, - ) - try: - extensions = [] - - while True: - line = file.readline() - if line is None: # eof - break - if _variable_rx.match(line): # VAR=VALUE, handled in first pass - continue - - if line[0] == line[-1] == "*": - file.warn("'%s' lines not handled yet" % line) - continue - - line = expand_makefile_vars(line, vars) - words = split_quoted(line) - - # NB. this parses a slightly different syntax than the old - # makesetup script: here, there must be exactly one extension per - # line, and it must be the first word of the line. I have no idea - # why the old syntax supported multiple extensions per line, as - # they all wind up being the same. - - module = words[0] - ext = Extension(module, []) - append_next_word = None - - for word in words[1:]: - if append_next_word is not None: - append_next_word.append(word) - append_next_word = None - continue - - suffix = os.path.splitext(word)[1] - switch = word[0:2] - value = word[2:] - - if suffix in (".c", ".cc", ".cpp", ".cxx", ".c++", ".m", ".mm"): - # hmm, should we do something about C vs. C++ sources? - # or leave it up to the CCompiler implementation to - # worry about? - ext.sources.append(word) - elif switch == "-I": - ext.include_dirs.append(value) - elif switch == "-D": - equals = value.find("=") - if equals == -1: # bare "-DFOO" -- no value - ext.define_macros.append((value, None)) - else: # "-DFOO=blah" - ext.define_macros.append((value[0:equals], value[equals + 2 :])) - elif switch == "-U": - ext.undef_macros.append(value) - elif switch == "-C": # only here 'cause makesetup has it! - ext.extra_compile_args.append(word) - elif switch == "-l": - ext.libraries.append(value) - elif switch == "-L": - ext.library_dirs.append(value) - elif switch == "-R": - ext.runtime_library_dirs.append(value) - elif word == "-rpath": - append_next_word = ext.runtime_library_dirs - elif word == "-Xlinker": - append_next_word = ext.extra_link_args - elif word == "-Xcompiler": - append_next_word = ext.extra_compile_args - elif switch == "-u": - ext.extra_link_args.append(word) - if not value: - append_next_word = ext.extra_link_args - elif suffix in (".a", ".so", ".sl", ".o", ".dylib"): - # NB. a really faithful emulation of makesetup would - # append a .o file to extra_objects only if it - # had a slash in it; otherwise, it would s/.o/.c/ - # and append it to sources. Hmmmm. - ext.extra_objects.append(word) - else: - file.warn("unrecognized argument '%s'" % word) - - extensions.append(ext) - finally: - file.close() - - return extensions diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/fancy_getopt.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/fancy_getopt.py deleted file mode 100755 index 6abb884..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/fancy_getopt.py +++ /dev/null @@ -1,470 +0,0 @@ -"""distutils.fancy_getopt - -Wrapper around the standard getopt module that provides the following -additional features: - * short and long options are tied together - * options have help strings, so fancy_getopt could potentially - create a complete usage summary - * options set attributes of a passed-in object -""" - -import sys -import string -import re -import getopt -from .errors import DistutilsGetoptError, DistutilsArgError - -# Much like command_re in distutils.core, this is close to but not quite -# the same as a Python NAME -- except, in the spirit of most GNU -# utilities, we use '-' in place of '_'. (The spirit of LISP lives on!) -# The similarities to NAME are again not a coincidence... -longopt_pat = r'[a-zA-Z](?:[a-zA-Z0-9-]*)' -longopt_re = re.compile(r'^%s$' % longopt_pat) - -# For recognizing "negative alias" options, eg. "quiet=!verbose" -neg_alias_re = re.compile("^({})=!({})$".format(longopt_pat, longopt_pat)) - -# This is used to translate long options to legitimate Python identifiers -# (for use as attributes of some object). -longopt_xlate = str.maketrans('-', '_') - - -class FancyGetopt: - """Wrapper around the standard 'getopt()' module that provides some - handy extra functionality: - * short and long options are tied together - * options have help strings, and help text can be assembled - from them - * options set attributes of a passed-in object - * boolean options can have "negative aliases" -- eg. if - --quiet is the "negative alias" of --verbose, then "--quiet" - on the command line sets 'verbose' to false - """ - - def __init__(self, option_table=None): - # The option table is (currently) a list of tuples. The - # tuples may have 3 or four values: - # (long_option, short_option, help_string [, repeatable]) - # if an option takes an argument, its long_option should have '=' - # appended; short_option should just be a single character, no ':' - # in any case. If a long_option doesn't have a corresponding - # short_option, short_option should be None. All option tuples - # must have long options. - self.option_table = option_table - - # 'option_index' maps long option names to entries in the option - # table (ie. those 3-tuples). - self.option_index = {} - if self.option_table: - self._build_index() - - # 'alias' records (duh) alias options; {'foo': 'bar'} means - # --foo is an alias for --bar - self.alias = {} - - # 'negative_alias' keeps track of options that are the boolean - # opposite of some other option - self.negative_alias = {} - - # These keep track of the information in the option table. We - # don't actually populate these structures until we're ready to - # parse the command-line, since the 'option_table' passed in here - # isn't necessarily the final word. - self.short_opts = [] - self.long_opts = [] - self.short2long = {} - self.attr_name = {} - self.takes_arg = {} - - # And 'option_order' is filled up in 'getopt()'; it records the - # original order of options (and their values) on the command-line, - # but expands short options, converts aliases, etc. - self.option_order = [] - - def _build_index(self): - self.option_index.clear() - for option in self.option_table: - self.option_index[option[0]] = option - - def set_option_table(self, option_table): - self.option_table = option_table - self._build_index() - - def add_option(self, long_option, short_option=None, help_string=None): - if long_option in self.option_index: - raise DistutilsGetoptError( - "option conflict: already an option '%s'" % long_option - ) - else: - option = (long_option, short_option, help_string) - self.option_table.append(option) - self.option_index[long_option] = option - - def has_option(self, long_option): - """Return true if the option table for this parser has an - option with long name 'long_option'.""" - return long_option in self.option_index - - def get_attr_name(self, long_option): - """Translate long option name 'long_option' to the form it - has as an attribute of some object: ie., translate hyphens - to underscores.""" - return long_option.translate(longopt_xlate) - - def _check_alias_dict(self, aliases, what): - assert isinstance(aliases, dict) - for (alias, opt) in aliases.items(): - if alias not in self.option_index: - raise DistutilsGetoptError( - ("invalid %s '%s': " "option '%s' not defined") - % (what, alias, alias) - ) - if opt not in self.option_index: - raise DistutilsGetoptError( - ("invalid %s '%s': " "aliased option '%s' not defined") - % (what, alias, opt) - ) - - def set_aliases(self, alias): - """Set the aliases for this option parser.""" - self._check_alias_dict(alias, "alias") - self.alias = alias - - def set_negative_aliases(self, negative_alias): - """Set the negative aliases for this option parser. - 'negative_alias' should be a dictionary mapping option names to - option names, both the key and value must already be defined - in the option table.""" - self._check_alias_dict(negative_alias, "negative alias") - self.negative_alias = negative_alias - - def _grok_option_table(self): # noqa: C901 - """Populate the various data structures that keep tabs on the - option table. Called by 'getopt()' before it can do anything - worthwhile. - """ - self.long_opts = [] - self.short_opts = [] - self.short2long.clear() - self.repeat = {} - - for option in self.option_table: - if len(option) == 3: - long, short, help = option - repeat = 0 - elif len(option) == 4: - long, short, help, repeat = option - else: - # the option table is part of the code, so simply - # assert that it is correct - raise ValueError("invalid option tuple: {!r}".format(option)) - - # Type- and value-check the option names - if not isinstance(long, str) or len(long) < 2: - raise DistutilsGetoptError( - ("invalid long option '%s': " "must be a string of length >= 2") - % long - ) - - if not ((short is None) or (isinstance(short, str) and len(short) == 1)): - raise DistutilsGetoptError( - "invalid short option '%s': " - "must a single character or None" % short - ) - - self.repeat[long] = repeat - self.long_opts.append(long) - - if long[-1] == '=': # option takes an argument? - if short: - short = short + ':' - long = long[0:-1] - self.takes_arg[long] = 1 - else: - # Is option is a "negative alias" for some other option (eg. - # "quiet" == "!verbose")? - alias_to = self.negative_alias.get(long) - if alias_to is not None: - if self.takes_arg[alias_to]: - raise DistutilsGetoptError( - "invalid negative alias '%s': " - "aliased option '%s' takes a value" % (long, alias_to) - ) - - self.long_opts[-1] = long # XXX redundant?! - self.takes_arg[long] = 0 - - # If this is an alias option, make sure its "takes arg" flag is - # the same as the option it's aliased to. - alias_to = self.alias.get(long) - if alias_to is not None: - if self.takes_arg[long] != self.takes_arg[alias_to]: - raise DistutilsGetoptError( - "invalid alias '%s': inconsistent with " - "aliased option '%s' (one of them takes a value, " - "the other doesn't" % (long, alias_to) - ) - - # Now enforce some bondage on the long option name, so we can - # later translate it to an attribute name on some object. Have - # to do this a bit late to make sure we've removed any trailing - # '='. - if not longopt_re.match(long): - raise DistutilsGetoptError( - "invalid long option name '%s' " - "(must be letters, numbers, hyphens only" % long - ) - - self.attr_name[long] = self.get_attr_name(long) - if short: - self.short_opts.append(short) - self.short2long[short[0]] = long - - def getopt(self, args=None, object=None): # noqa: C901 - """Parse command-line options in args. Store as attributes on object. - - If 'args' is None or not supplied, uses 'sys.argv[1:]'. If - 'object' is None or not supplied, creates a new OptionDummy - object, stores option values there, and returns a tuple (args, - object). If 'object' is supplied, it is modified in place and - 'getopt()' just returns 'args'; in both cases, the returned - 'args' is a modified copy of the passed-in 'args' list, which - is left untouched. - """ - if args is None: - args = sys.argv[1:] - if object is None: - object = OptionDummy() - created_object = True - else: - created_object = False - - self._grok_option_table() - - short_opts = ' '.join(self.short_opts) - try: - opts, args = getopt.getopt(args, short_opts, self.long_opts) - except getopt.error as msg: - raise DistutilsArgError(msg) - - for opt, val in opts: - if len(opt) == 2 and opt[0] == '-': # it's a short option - opt = self.short2long[opt[1]] - else: - assert len(opt) > 2 and opt[:2] == '--' - opt = opt[2:] - - alias = self.alias.get(opt) - if alias: - opt = alias - - if not self.takes_arg[opt]: # boolean option? - assert val == '', "boolean option can't have value" - alias = self.negative_alias.get(opt) - if alias: - opt = alias - val = 0 - else: - val = 1 - - attr = self.attr_name[opt] - # The only repeating option at the moment is 'verbose'. - # It has a negative option -q quiet, which should set verbose = 0. - if val and self.repeat.get(attr) is not None: - val = getattr(object, attr, 0) + 1 - setattr(object, attr, val) - self.option_order.append((opt, val)) - - # for opts - if created_object: - return args, object - else: - return args - - def get_option_order(self): - """Returns the list of (option, value) tuples processed by the - previous run of 'getopt()'. Raises RuntimeError if - 'getopt()' hasn't been called yet. - """ - if self.option_order is None: - raise RuntimeError("'getopt()' hasn't been called yet") - else: - return self.option_order - - def generate_help(self, header=None): # noqa: C901 - """Generate help text (a list of strings, one per suggested line of - output) from the option table for this FancyGetopt object. - """ - # Blithely assume the option table is good: probably wouldn't call - # 'generate_help()' unless you've already called 'getopt()'. - - # First pass: determine maximum length of long option names - max_opt = 0 - for option in self.option_table: - long = option[0] - short = option[1] - ell = len(long) - if long[-1] == '=': - ell = ell - 1 - if short is not None: - ell = ell + 5 # " (-x)" where short == 'x' - if ell > max_opt: - max_opt = ell - - opt_width = max_opt + 2 + 2 + 2 # room for indent + dashes + gutter - - # Typical help block looks like this: - # --foo controls foonabulation - # Help block for longest option looks like this: - # --flimflam set the flim-flam level - # and with wrapped text: - # --flimflam set the flim-flam level (must be between - # 0 and 100, except on Tuesdays) - # Options with short names will have the short name shown (but - # it doesn't contribute to max_opt): - # --foo (-f) controls foonabulation - # If adding the short option would make the left column too wide, - # we push the explanation off to the next line - # --flimflam (-l) - # set the flim-flam level - # Important parameters: - # - 2 spaces before option block start lines - # - 2 dashes for each long option name - # - min. 2 spaces between option and explanation (gutter) - # - 5 characters (incl. space) for short option name - - # Now generate lines of help text. (If 80 columns were good enough - # for Jesus, then 78 columns are good enough for me!) - line_width = 78 - text_width = line_width - opt_width - big_indent = ' ' * opt_width - if header: - lines = [header] - else: - lines = ['Option summary:'] - - for option in self.option_table: - long, short, help = option[:3] - text = wrap_text(help, text_width) - if long[-1] == '=': - long = long[0:-1] - - # Case 1: no short option at all (makes life easy) - if short is None: - if text: - lines.append(" --%-*s %s" % (max_opt, long, text[0])) - else: - lines.append(" --%-*s " % (max_opt, long)) - - # Case 2: we have a short option, so we have to include it - # just after the long option - else: - opt_names = "{} (-{})".format(long, short) - if text: - lines.append(" --%-*s %s" % (max_opt, opt_names, text[0])) - else: - lines.append(" --%-*s" % opt_names) - - for ell in text[1:]: - lines.append(big_indent + ell) - return lines - - def print_help(self, header=None, file=None): - if file is None: - file = sys.stdout - for line in self.generate_help(header): - file.write(line + "\n") - - -def fancy_getopt(options, negative_opt, object, args): - parser = FancyGetopt(options) - parser.set_negative_aliases(negative_opt) - return parser.getopt(args, object) - - -WS_TRANS = {ord(_wschar): ' ' for _wschar in string.whitespace} - - -def wrap_text(text, width): - """wrap_text(text : string, width : int) -> [string] - - Split 'text' into multiple lines of no more than 'width' characters - each, and return the list of strings that results. - """ - if text is None: - return [] - if len(text) <= width: - return [text] - - text = text.expandtabs() - text = text.translate(WS_TRANS) - chunks = re.split(r'( +|-+)', text) - chunks = [ch for ch in chunks if ch] # ' - ' results in empty strings - lines = [] - - while chunks: - cur_line = [] # list of chunks (to-be-joined) - cur_len = 0 # length of current line - - while chunks: - ell = len(chunks[0]) - if cur_len + ell <= width: # can squeeze (at least) this chunk in - cur_line.append(chunks[0]) - del chunks[0] - cur_len = cur_len + ell - else: # this line is full - # drop last chunk if all space - if cur_line and cur_line[-1][0] == ' ': - del cur_line[-1] - break - - if chunks: # any chunks left to process? - # if the current line is still empty, then we had a single - # chunk that's too big too fit on a line -- so we break - # down and break it up at the line width - if cur_len == 0: - cur_line.append(chunks[0][0:width]) - chunks[0] = chunks[0][width:] - - # all-whitespace chunks at the end of a line can be discarded - # (and we know from the re.split above that if a chunk has - # *any* whitespace, it is *all* whitespace) - if chunks[0][0] == ' ': - del chunks[0] - - # and store this line in the list-of-all-lines -- as a single - # string, of course! - lines.append(''.join(cur_line)) - - return lines - - -def translate_longopt(opt): - """Convert a long option name to a valid Python identifier by - changing "-" to "_". - """ - return opt.translate(longopt_xlate) - - -class OptionDummy: - """Dummy class just used as a place to hold command-line option - values as instance attributes.""" - - def __init__(self, options=[]): - """Create a new OptionDummy instance. The attributes listed in - 'options' will be initialized to None.""" - for opt in options: - setattr(self, opt, None) - - -if __name__ == "__main__": - text = """\ -Tra-la-la, supercalifragilisticexpialidocious. -How *do* you spell that odd word, anyways? -(Someone ask Mary -- she'll know [or she'll -say, "How should I know?"].)""" - - for w in (10, 20, 30, 40): - print("width: %d" % w) - print("\n".join(wrap_text(text, w))) - print() diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/file_util.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/file_util.py deleted file mode 100755 index 1b7cd53..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/file_util.py +++ /dev/null @@ -1,249 +0,0 @@ -"""distutils.file_util - -Utility functions for operating on single files. -""" - -import os -from .errors import DistutilsFileError -from ._log import log - -# for generating verbose output in 'copy_file()' -_copy_action = {None: 'copying', 'hard': 'hard linking', 'sym': 'symbolically linking'} - - -def _copy_file_contents(src, dst, buffer_size=16 * 1024): # noqa: C901 - """Copy the file 'src' to 'dst'; both must be filenames. Any error - opening either file, reading from 'src', or writing to 'dst', raises - DistutilsFileError. Data is read/written in chunks of 'buffer_size' - bytes (default 16k). No attempt is made to handle anything apart from - regular files. - """ - # Stolen from shutil module in the standard library, but with - # custom error-handling added. - fsrc = None - fdst = None - try: - try: - fsrc = open(src, 'rb') - except OSError as e: - raise DistutilsFileError("could not open '{}': {}".format(src, e.strerror)) - - if os.path.exists(dst): - try: - os.unlink(dst) - except OSError as e: - raise DistutilsFileError( - "could not delete '{}': {}".format(dst, e.strerror) - ) - - try: - fdst = open(dst, 'wb') - except OSError as e: - raise DistutilsFileError( - "could not create '{}': {}".format(dst, e.strerror) - ) - - while True: - try: - buf = fsrc.read(buffer_size) - except OSError as e: - raise DistutilsFileError( - "could not read from '{}': {}".format(src, e.strerror) - ) - - if not buf: - break - - try: - fdst.write(buf) - except OSError as e: - raise DistutilsFileError( - "could not write to '{}': {}".format(dst, e.strerror) - ) - finally: - if fdst: - fdst.close() - if fsrc: - fsrc.close() - - -def copy_file( # noqa: C901 - src, - dst, - preserve_mode=1, - preserve_times=1, - update=0, - link=None, - verbose=1, - dry_run=0, -): - """Copy a file 'src' to 'dst'. If 'dst' is a directory, then 'src' is - copied there with the same name; otherwise, it must be a filename. (If - the file exists, it will be ruthlessly clobbered.) If 'preserve_mode' - is true (the default), the file's mode (type and permission bits, or - whatever is analogous on the current platform) is copied. If - 'preserve_times' is true (the default), the last-modified and - last-access times are copied as well. If 'update' is true, 'src' will - only be copied if 'dst' does not exist, or if 'dst' does exist but is - older than 'src'. - - 'link' allows you to make hard links (os.link) or symbolic links - (os.symlink) instead of copying: set it to "hard" or "sym"; if it is - None (the default), files are copied. Don't set 'link' on systems that - don't support it: 'copy_file()' doesn't check if hard or symbolic - linking is available. If hardlink fails, falls back to - _copy_file_contents(). - - Under Mac OS, uses the native file copy function in macostools; on - other systems, uses '_copy_file_contents()' to copy file contents. - - Return a tuple (dest_name, copied): 'dest_name' is the actual name of - the output file, and 'copied' is true if the file was copied (or would - have been copied, if 'dry_run' true). - """ - # XXX if the destination file already exists, we clobber it if - # copying, but blow up if linking. Hmmm. And I don't know what - # macostools.copyfile() does. Should definitely be consistent, and - # should probably blow up if destination exists and we would be - # changing it (ie. it's not already a hard/soft link to src OR - # (not update) and (src newer than dst). - - from distutils.dep_util import newer - from stat import ST_ATIME, ST_MTIME, ST_MODE, S_IMODE - - if not os.path.isfile(src): - raise DistutilsFileError( - "can't copy '%s': doesn't exist or not a regular file" % src - ) - - if os.path.isdir(dst): - dir = dst - dst = os.path.join(dst, os.path.basename(src)) - else: - dir = os.path.dirname(dst) - - if update and not newer(src, dst): - if verbose >= 1: - log.debug("not copying %s (output up-to-date)", src) - return (dst, 0) - - try: - action = _copy_action[link] - except KeyError: - raise ValueError("invalid value '%s' for 'link' argument" % link) - - if verbose >= 1: - if os.path.basename(dst) == os.path.basename(src): - log.info("%s %s -> %s", action, src, dir) - else: - log.info("%s %s -> %s", action, src, dst) - - if dry_run: - return (dst, 1) - - # If linking (hard or symbolic), use the appropriate system call - # (Unix only, of course, but that's the caller's responsibility) - elif link == 'hard': - if not (os.path.exists(dst) and os.path.samefile(src, dst)): - try: - os.link(src, dst) - return (dst, 1) - except OSError: - # If hard linking fails, fall back on copying file - # (some special filesystems don't support hard linking - # even under Unix, see issue #8876). - pass - elif link == 'sym': - if not (os.path.exists(dst) and os.path.samefile(src, dst)): - os.symlink(src, dst) - return (dst, 1) - - # Otherwise (non-Mac, not linking), copy the file contents and - # (optionally) copy the times and mode. - _copy_file_contents(src, dst) - if preserve_mode or preserve_times: - st = os.stat(src) - - # According to David Ascher , utime() should be done - # before chmod() (at least under NT). - if preserve_times: - os.utime(dst, (st[ST_ATIME], st[ST_MTIME])) - if preserve_mode: - os.chmod(dst, S_IMODE(st[ST_MODE])) - - return (dst, 1) - - -# XXX I suspect this is Unix-specific -- need porting help! -def move_file(src, dst, verbose=1, dry_run=0): # noqa: C901 - - """Move a file 'src' to 'dst'. If 'dst' is a directory, the file will - be moved into it with the same name; otherwise, 'src' is just renamed - to 'dst'. Return the new full name of the file. - - Handles cross-device moves on Unix using 'copy_file()'. What about - other systems??? - """ - from os.path import exists, isfile, isdir, basename, dirname - import errno - - if verbose >= 1: - log.info("moving %s -> %s", src, dst) - - if dry_run: - return dst - - if not isfile(src): - raise DistutilsFileError("can't move '%s': not a regular file" % src) - - if isdir(dst): - dst = os.path.join(dst, basename(src)) - elif exists(dst): - raise DistutilsFileError( - "can't move '{}': destination '{}' already exists".format(src, dst) - ) - - if not isdir(dirname(dst)): - raise DistutilsFileError( - "can't move '{}': destination '{}' not a valid path".format(src, dst) - ) - - copy_it = False - try: - os.rename(src, dst) - except OSError as e: - (num, msg) = e.args - if num == errno.EXDEV: - copy_it = True - else: - raise DistutilsFileError( - "couldn't move '{}' to '{}': {}".format(src, dst, msg) - ) - - if copy_it: - copy_file(src, dst, verbose=verbose) - try: - os.unlink(src) - except OSError as e: - (num, msg) = e.args - try: - os.unlink(dst) - except OSError: - pass - raise DistutilsFileError( - "couldn't move '%s' to '%s' by copy/delete: " - "delete '%s' failed: %s" % (src, dst, src, msg) - ) - return dst - - -def write_file(filename, contents): - """Create a file with the specified name and write 'contents' (a - sequence of strings without line terminators) to it. - """ - f = open(filename, "w") - try: - for line in contents: - f.write(line + "\n") - finally: - f.close() diff --git a/venv/lib/python3.11/site-packages/setuptools/_distutils/filelist.py b/venv/lib/python3.11/site-packages/setuptools/_distutils/filelist.py deleted file mode 100755 index 6dadf92..0000000 --- a/venv/lib/python3.11/site-packages/setuptools/_distutils/filelist.py +++ /dev/null @@ -1,371 +0,0 @@ -"""distutils.filelist - -Provides the FileList class, used for poking about the filesystem -and building lists of files. -""" - -import os -import re -import fnmatch -import functools - -from .util import convert_path -from .errors import DistutilsTemplateError, DistutilsInternalError -from ._log import log - - -class FileList: - """A list of files built by on exploring the filesystem and filtered by - applying various patterns to what we find there. - - Instance attributes: - dir - directory from which files will be taken -- only used if - 'allfiles' not supplied to constructor - files - list of filenames currently being built/filtered/manipulated - allfiles - complete list of files under consideration (ie. without any - filtering applied) - """ - - def __init__(self, warn=None, debug_print=None): - # ignore argument to FileList, but keep them for backwards - # compatibility - self.allfiles = None - self.files = [] - - def set_allfiles(self, allfiles): - self.allfiles = allfiles - - def findall(self, dir=os.curdir): - self.allfiles = findall(dir) - - def debug_print(self, msg): - """Print 'msg' to stdout if the global DEBUG (taken from the - DISTUTILS_DEBUG environment variable) flag is true. - """ - from distutils.debug import DEBUG - - if DEBUG: - print(msg) - - # Collection methods - - def append(self, item): - self.files.append(item) - - def extend(self, items): - self.files.extend(items) - - def sort(self): - # Not a strict lexical sort! - sortable_files = sorted(map(os.path.split, self.files)) - self.files = [] - for sort_tuple in sortable_files: - self.files.append(os.path.join(*sort_tuple)) - - # Other miscellaneous utility methods - - def remove_duplicates(self): - # Assumes list has been sorted! - for i in range(len(self.files) - 1, 0, -1): - if self.files[i] == self.files[i - 1]: - del self.files[i] - - # "File template" methods - - def _parse_template_line(self, line): - words = line.split() - action = words[0] - - patterns = dir = dir_pattern = None - - if action in ('include', 'exclude', 'global-include', 'global-exclude'): - if len(words) < 2: - raise DistutilsTemplateError( - "'%s' expects ..." % action - ) - patterns = [convert_path(w) for w in words[1:]] - elif action in ('recursive-include', 'recursive-exclude'): - if len(words) < 3: - raise DistutilsTemplateError( - "'%s' expects